diff --git a/Makefile b/Makefile index d6f62d1..0e89e1c 100644 --- a/Makefile +++ b/Makefile @@ -1 +1,3 @@ +PROJECT = calrissian + include resources/make/common.mk diff --git a/include/monads.lfe b/include/monads.lfe index 59f2c19..5904a49 100644 --- a/include/monads.lfe +++ b/include/monads.lfe @@ -3,14 +3,14 @@ ;; Provide the state monad in terms of the state transformer (''state `(transformer 'state 'identity)) (_ - `(list_to_atom (lists:flatten (list "calrissian-" - (atom_to_list ,name) - "-monad")))))) + `(list_to_atom (lists:flatten `("calrissian-" + ,(atom_to_list ,name) + "-monad")))))) (defmacro transformer (name inner-monad) - `(tuple (list_to_atom (lists:flatten (list "calrissian-" - (atom_to_list ,name) - "-transformer"))) + `(tuple (list_to_atom (lists:flatten `("calrissian-" + ,(atom_to_list ,name) + "-transformer"))) (monad ,inner-monad))) (defmacro do-m args @@ -31,7 +31,7 @@ `(call ,monad 'fail ,expr)) (defmacro sequence (monad list) - `(: lists foldr + `(lists:foldr (lambda (m acc) (mcons ,monad m acc)) (return ,monad []) ,list)) diff --git a/lfe.config b/lfe.config new file mode 100644 index 0000000..9af290f --- /dev/null +++ b/lfe.config @@ -0,0 +1,11 @@ +#(project + (#(deps (#("lfex/lcfg" "master"))) + #(meta ( + #(name logjam) + #(description "Monads for LFE") + #(version "0.1.0") + #(keywords ("LFE" "Lisp" "Library" "Monads")) + #(maintainers ( + (#(name "Correl Roush") #(email "correl@gmail.com")))) + #(repos ( + #(github "correl/calrissian"))))))) diff --git a/package.exs b/package.exs deleted file mode 100644 index 027db08..0000000 --- a/package.exs +++ /dev/null @@ -1,7 +0,0 @@ -Expm.Package.new( - name: "calrissian", - description: "Monads for LFE", - version: "0.1.0", - keywords: ["LFE", "Lisp", "Library", "Monads"], - maintainers: [[name: "Correl Roush", email: "correl@gmail.com"]], - repositories: [[github: "correl/calrissian"]]) diff --git a/rebar.config b/rebar.config index 46ae791..2aa306a 100644 --- a/rebar.config +++ b/rebar.config @@ -1,16 +1,12 @@ -{erl_opts, [debug_info, {src_dirs, ["test/unit", - "test/integration", - "test/system"]}]}. +{erl_opts, [debug_info, {src_dirs, ["test"]}]}. {lfe_first_files, []}. {deps_dir, ["deps"]}. {eunit_compile_opts, [ - {src_dirs, ["test/unit", - "test/integration", - "test/system", - "src"]} + {src_dirs, ["test"]} ]}. {deps, [ {lfe, ".*", {git, "git://github.com/rvirding/lfe.git", "develop"}}, - {'lfe-utils', ".*", {git, "https://github.com/lfe/lfe-utils.git", "master"}}, - {lfeunit, ".*", {git, "git://github.com/lfe/lfeunit.git", "master"}} + {lutil, ".*", {git, "https://github.com/lfex/lutil.git", "master"}}, + {ltest, ".*", {git, "git://github.com/lfex/ltest.git", "master"}}, + {lcfg, ".*", {git, "git://github.com/lfex/lcfg.git", "master"}} ]}. diff --git a/resources/make/common.mk b/resources/make/common.mk index e062f14..e609701 100644 --- a/resources/make/common.mk +++ b/resources/make/common.mk @@ -1,102 +1,119 @@ -PROJECT = calrissian +ifeq ($(shell which erl),) +$(error Can't find Erlang executable 'erl') +exit 1 +endif + LIB = $(PROJECT) DEPS = ./deps BIN_DIR = ./bin -EXPM = $(BIN_DIR)/expm - SOURCE_DIR = ./src OUT_DIR = ./ebin TEST_DIR = ./test TEST_OUT_DIR = ./.eunit SCRIPT_PATH=$(DEPS)/lfe/bin:.:./bin:"$(PATH)":/usr/local/bin -ERL_LIBS=$(shell pwd):$(shell $(LFETOOL) info erllibs) -EMPTY = -ifeq ($(shell which lfetool),$EMPTY) - LFETOOL=$(BIN_DIR)/lfetool +ifeq ($(shell which lfetool),) +LFETOOL=$(BIN_DIR)/lfetool else - LFETOOL=lfetool +LFETOOL=lfetool endif +ERL_LIBS=.:..:$(shell pwd):$(shell $(LFETOOL) info erllibs) OS := $(shell uname -s) ifeq ($(OS),Linux) - HOST=$(HOSTNAME) + HOST=$(HOSTNAME) endif ifeq ($(OS),Darwin) - HOST = $(shell scutil --get ComputerName) + HOST = $(shell scutil --get ComputerName) endif $(BIN_DIR): mkdir -p $(BIN_DIR) -$(LFETOOL): $(BIN_DIR) - @[ -f $(LFETOOL) ] || \ - curl -L -o ./lfetool https://raw.github.com/lfe/lfetool/master/lfetool && \ +$(BIN_DIR)/lfetool: $(BIN_DIR) + @make get-lfetool + +get-lfetool: $(BIN_DIR) + curl -L -o ./lfetool https://raw.github.com/lfe/lfetool/dev-v1/lfetool && \ chmod 755 ./lfetool && \ mv ./lfetool $(BIN_DIR) get-version: - @PATH=$(SCRIPT_PATH) lfetool info version - -$(EXPM): $(BIN_DIR) - @[ -f $(EXPM) ] || \ - PATH=$(SCRIPT_PATH) lfetool install expm $(BIN_DIR) + @PATH=$(SCRIPT_PATH) $(LFETOOL) info version + @echo "Erlang/OTP, LFE, & library versions:" + @ERL_LIBS=$(ERL_LIBS) PATH=$(SCRIPT_PATH) erl \ + -eval "lfe_io:format(\"~p~n\",['$(PROJECT)-util':'get-versions'()])." \ + -noshell -s erlang halt get-deps: @echo "Getting dependencies ..." - @which rebar.cmd >/dev/null 2>&1 && rebar.cmd get-deps || rebar get-deps - @PATH=$(SCRIPT_PATH) lfetool update deps + @PATH=$(SCRIPT_PATH) ERL_LIBS=$(ERL_LIBS) $(LFETOOL) download deps clean-ebin: @echo "Cleaning ebin dir ..." @rm -f $(OUT_DIR)/*.beam clean-eunit: - @PATH=$(SCRIPT_PATH) lfetool tests clean + -@PATH=$(SCRIPT_PATH) $(LFETOOL) tests clean compile: get-deps clean-ebin @echo "Compiling project code and dependencies ..." - @which rebar.cmd >/dev/null 2>&1 && rebar.cmd compile || rebar compile + @which rebar.cmd >/dev/null 2>&1 && \ + PATH=$(SCRIPT_PATH) ERL_LIBS=$(ERL_LIBS) rebar.cmd compile || \ + PATH=$(SCRIPT_PATH) ERL_LIBS=$(ERL_LIBS) rebar compile compile-no-deps: clean-ebin @echo "Compiling only project code ..." - @which rebar.cmd >/dev/null 2>&1 && rebar.cmd compile skip_deps=true || rebar compile skip_deps=true + @which rebar.cmd >/dev/null 2>&1 && \ + PATH=$(SCRIPT_PATH) ERL_LIBS=$(ERL_LIBS) \ + rebar.cmd compile skip_deps=true || \ + PATH=$(SCRIPT_PATH) ERL_LIBS=$(ERL_LIBS) rebar compile skip_deps=true -compile-tests: - @PATH=$(SCRIPT_PATH) lfetool tests build +compile-tests: clean-eunit + @PATH=$(SCRIPT_PATH) ERL_LIBS=$(ERL_LIBS) $(LFETOOL) tests build + +repl: compile + @which clear >/dev/null 2>&1 && clear || printf "\033c" + @echo "Starting an LFE REPL ..." + @PATH=$(SCRIPT_PATH) ERL_LIBS=$(ERL_LIBS) $(LFETOOL) repl lfe +pc unicode + +repl-no-deps: compile-no-deps + @which clear >/dev/null 2>&1 && clear || printf "\033c" + @echo "Starting an LFE REPL ..." + @PATH=$(SCRIPT_PATH) ERL_LIBS=$(ERL_LIBS) $(LFETOOL) repl lfe +pc unicode shell: compile @which clear >/dev/null 2>&1 && clear || printf "\033c" - @echo "Starting shell ..." - @PATH=$(SCRIPT_PATH) lfetool repl + @echo "Starting an Erlang shell ..." + @PATH=$(SCRIPT_PATH) ERL_LIBS=$(ERL_LIBS) erl + pc unicode shell-no-deps: compile-no-deps @which clear >/dev/null 2>&1 && clear || printf "\033c" - @echo "Starting shell ..." - @PATH=$(SCRIPT_PATH) lfetool repl + @echo "Starting an Erlang shell ..." + @PATH=$(SCRIPT_PATH) ERL_LIBS=$(ERL_LIBS) erl + pc unicode clean: clean-ebin clean-eunit @which rebar.cmd >/dev/null 2>&1 && rebar.cmd clean || rebar clean check-unit-only: - @PATH=$(SCRIPT_PATH) lfetool tests unit + @PATH=$(SCRIPT_PATH) ERL_LIBS=$(ERL_LIBS) $(LFETOOL) tests unit check-integration-only: - @PATH=$(SCRIPT_PATH) lfetool tests integration + @PATH=$(SCRIPT_PATH) ERL_LIBS=$(ERL_LIBS) $(LFETOOL) tests integration check-system-only: - @PATH=$(SCRIPT_PATH) lfetool tests system + @PATH=$(SCRIPT_PATH) ERL_LIBS=$(ERL_LIBS) $(LFETOOL) tests system check-unit-with-deps: get-deps compile compile-tests check-unit-only -check-unit: compile-no-deps check-unit-only -check-integration: compile check-integration-only -check-system: compile check-system-only -check-all-with-deps: compile check-unit-only check-integration-only \ - check-system-only -check-all: get-deps compile-no-deps - @PATH=$(SCRIPT_PATH) lfetool tests all +check-unit: clean-eunit compile-no-deps check-unit-only +check-integration: clean-eunit compile check-integration-only +check-system: clean-eunit compile check-system-only +check-all-with-deps: clean-eunit compile check-unit-only \ + check-integration-only check-system-only clean-eunit +check-all: get-deps clean-eunit compile-no-deps + @PATH=$(SCRIPT_PATH) ERL_LIBS=$(ERL_LIBS) $(LFETOOL) tests all check: check-unit-with-deps -check-travis: $(LFETOOL) check +check-travis: $(BIN_DIR)/lfetool check push-all: @echo "Pusing code to github ..." @@ -106,16 +123,6 @@ push-all: git push upstream --tags install: compile - @echo "Installing calrissian ..." + @echo "Installing lumberjack ..." @PATH=$(SCRIPT_PATH) lfetool install lfe -upload: $(EXPM) get-version - @echo "Preparing to upload calrissian ..." - @echo - @echo "Package file:" - @echo - @cat package.exs - @echo - @echo "Continue with upload? " - @read - $(EXPM) publish diff --git a/src/calrissian-error-monad.lfe b/src/calrissian-error-monad.lfe index 0beffd0..a76e8a7 100644 --- a/src/calrissian-error-monad.lfe +++ b/src/calrissian-error-monad.lfe @@ -5,9 +5,9 @@ (fail 1))) (defun >>= - (((tuple 'error reason) f) - (tuple 'error reason)) - (((tuple 'ok value) f) + ((`#(error ,reason) f) + `#(error ,reason)) + ((`#(ok ,value) f) (funcall f value)) (('ok f) (funcall f 'ok))) @@ -16,7 +16,7 @@ (('ok) 'ok) ((x) - (tuple 'ok x))) + `#(ok ,x))) (defun fail (reason) - (tuple 'error reason)) + `#(error ,reason)) diff --git a/src/calrissian-identity-monad.lfe b/src/calrissian-identity-monad.lfe index 4be2a99..6eb1af4 100644 --- a/src/calrissian-identity-monad.lfe +++ b/src/calrissian-identity-monad.lfe @@ -10,4 +10,4 @@ (defun return (x) x) (defun fail (x) - (throw (tuple 'error x))) + (throw `#(error ,x))) diff --git a/src/calrissian-maybe-monad.lfe b/src/calrissian-maybe-monad.lfe index e19ac6f..25a728b 100644 --- a/src/calrissian-maybe-monad.lfe +++ b/src/calrissian-maybe-monad.lfe @@ -7,11 +7,11 @@ (defun >>= (('nothing f) 'nothing) - (((tuple 'just x) f) + ((`#(just ,x) f) (funcall f x))) (defun return (x) - (tuple 'just x)) + `#(just ,x)) (defun fail (_) 'nothing) diff --git a/src/calrissian-monad.lfe b/src/calrissian-monad.lfe index be444c0..d2bafc7 100644 --- a/src/calrissian-monad.lfe +++ b/src/calrissian-monad.lfe @@ -3,17 +3,17 @@ (do-transform 2))) (defun behaviour_info - (('callbacks) (list #(>>= 2) - #(return 1) - #(fail 1))) + (('callbacks) '(#(>>= 2) + #(return 1) + #(fail 1))) ((_) 'undefined)) (defun do-transform - ((monad (cons h '())) + ((monad `(,h . ())) h) - ((monad (cons (list f '<- m) t)) - (list '>>= monad - m - (list 'lambda (list f) (do-transform monad t)))) - ((monad (cons h t)) - (list '>> monad h (do-transform monad t)))) + ((monad `((,f <- ,m) . ,t)) + `(>>= ,monad + ,m + (lambda (,f) ,(do-transform monad t)))) + ((monad `(,h . ,t)) + `(>> ,monad ,h ,(do-transform monad t)))) diff --git a/src/calrissian-state-transformer.lfe b/src/calrissian-state-transformer.lfe index eb30588..052b05a 100644 --- a/src/calrissian-state-transformer.lfe +++ b/src/calrissian-state-transformer.lfe @@ -4,57 +4,57 @@ (include-lib "include/monads.lfe") (defun new (inner-monad) - (tuple 'calrissian-state-transformer inner-monad)) + `#(calrissian-state-transformer ,inner-monad)) (defun return - ((x (tuple 'calrissian-state-transformer inner-monad)) + ((x `#(calrissian-state-transformer ,inner-monad)) (lambda (s) (call inner-monad 'return (tuple x s))))) (defun fail - ((reason (tuple 'calrissian-state-transformer inner-monad)) + ((reason `#(calrissian-state-transformer ,inner-monad)) (lambda (_) (call inner-monad 'fail reason)))) (defun >>= - ((x f (tuple 'calrissian-state-transformer inner-monad)) + ((x f `#(calrissian-state-transformer ,inner-monad)) (lambda (s) (call inner-monad '>>= (funcall x s) - (match-lambda (((tuple x1 s1)) (funcall (funcall f x1) s1))))))) + (match-lambda ((`#(,x1 ,s1)) (funcall (funcall f x1) s1))))))) (defun get (_) (lambda (s) - (tuple s s))) + `#(,s ,s))) (defun put (s _) (lambda (_) - (tuple 'ok s))) + `#(ok ,s))) (defun modify - ((f (tuple 'calrissian-state-transformer inner-monad)) + ((f `#(calrissian-state-transformer ,inner-monad)) (lambda (s) - (tuple 'ok (call inner-monad 'return (funcall f s)))))) + `#(ok ,(call inner-monad 'return (funcall f s)))))) (defun modify-and-return - ((f (tuple 'calrissian-state-transformer inner-monad)) + ((f `#(calrissian-state-transformer ,inner-monad)) (lambda (s) (let ((newstate (call inner-monad 'return (funcall f s)))) - (tuple newstate newstate))))) + `#(,newstate ,newstate))))) (defun eval - ((m s (tuple 'calrissian-state-transformer inner-monad)) + ((m s `#(calrissian-state-transformer ,inner-monad)) (call inner-monad '>>= (funcall m s) - (match-lambda (((tuple x s1)) + (match-lambda ((`#(,x ,s1)) (call inner-monad 'return x)))))) (defun exec - ((m s (tuple 'calrissian-state-transformer inner-monad)) + ((m s `#(calrissian-state-transformer ,inner-monad)) (call inner-monad '>>= (funcall m s) - (match-lambda (((tuple x s1)) + (match-lambda ((`#(,x ,s1)) (call inner-monad 'return s1)))))) (defun run - ((m s (tuple 'calrissian-state-transformer inner-monad)) + ((m s `#(calrissian-state-transformer ,inner-monad)) (funcall m s))) diff --git a/src/calrissian-state.lfe b/src/calrissian-state.lfe index 6fc37a0..b35f703 100644 --- a/src/calrissian-state.lfe +++ b/src/calrissian-state.lfe @@ -2,11 +2,11 @@ (export (behaviour_info 1))) (defun behaviour_info - (('callbacks) (list #(run 2) - #(get 0) - #(put 1) - #(modify 1) - #(modify-and-return 1) - #(exec 2) - #(eval 2))) + (('callbacks) `(#(run 2) + #(get 0) + #(put 1) + #(modify 1) + #(modify-and-return 1) + #(exec 2) + #(eval 2))) ((_) 'undefined)) \ No newline at end of file diff --git a/src/calrissian-util.lfe b/src/calrissian-util.lfe index e9ace16..6fb31a1 100644 --- a/src/calrissian-util.lfe +++ b/src/calrissian-util.lfe @@ -1,19 +1,28 @@ (defmodule calrissian-util - (export (module-info 1) + (export (get-version 0) + (get-versions 0) + (module-info 1) (module-info 2) (implements? 2) (exports? 2))) +(defun get-version () + (lutil:get-app-version 'calrissian)) + +(defun get-versions () + (++ (lutil:get-versions) + `(#(calrissian ,(get-version))))) + (defun module-info - (((tuple module _args)) + ((`#(,module ,_args)) ;; Report exported function arities as (arity - 1) to account for ;; the extra argument supplied to tuple modules (let ((fix-info (lambda (info-plist) (let* ((exports (proplists:get_value 'exports info-plist)) (fix-arity (match-lambda ;; module_info is added by the compiler and therefore remains as-is - (((tuple 'module_info arity)) (tuple 'module_info arity)) - (((tuple fun arity)) (tuple fun (- arity 1))))) + ((`#(module_info ,arity)) `#(module_info ,arity)) + ((`#(,fun ,arity)) `#(,fun ,(- arity 1))))) (info-dict (dict:from_list info-plist)) (new-dict (dict:store 'exports (lists:map fix-arity exports) info-dict)) (new-plist (dict:to_list new-dict))) diff --git a/test/unit/unit-calrissian-error-monad-tests.lfe b/test/unit-calrissian-error-monad-tests.lfe similarity index 74% rename from test/unit/unit-calrissian-error-monad-tests.lfe rename to test/unit-calrissian-error-monad-tests.lfe index 37003aa..d6125ed 100644 --- a/test/unit/unit-calrissian-error-monad-tests.lfe +++ b/test/unit-calrissian-error-monad-tests.lfe @@ -1,13 +1,10 @@ (defmodule unit-calrissian-error-monad-tests - (export all) - (import - (from lfeunit-util - (check-failed-assert 2) - (check-wrong-assert-exception 2)))) + (behaviour ltest-unit) + (export all)) -(include-lib "deps/lfeunit/include/lfeunit-macros.lfe") -(include-lib "include/monads.lfe") -(include-lib "include/monad-tests.lfe") +(include-lib "ltest/include/ltest-macros.lfe") +(include-lib "calrissian/include/monads.lfe") +(include-lib "calrissian/include/monad-tests.lfe") (test-monad (monad 'error)) diff --git a/test/unit/unit-calrissian-identity-monad-tests.lfe b/test/unit-calrissian-identity-monad-tests.lfe similarity index 50% rename from test/unit/unit-calrissian-identity-monad-tests.lfe rename to test/unit-calrissian-identity-monad-tests.lfe index ea8ccac..87e15a9 100644 --- a/test/unit/unit-calrissian-identity-monad-tests.lfe +++ b/test/unit-calrissian-identity-monad-tests.lfe @@ -1,13 +1,10 @@ (defmodule unit-calrissian-identity-monad-tests - (export all) - (import - (from lfeunit-util - (check-failed-assert 2) - (check-wrong-assert-exception 2)))) + (behaviour ltest-unit) + (export all)) -(include-lib "deps/lfeunit/include/lfeunit-macros.lfe") -(include-lib "include/monads.lfe") -(include-lib "include/monad-tests.lfe") +(include-lib "ltest/include/ltest-macros.lfe") +(include-lib "calrissian/include/monads.lfe") +(include-lib "calrissian/include/monad-tests.lfe") (test-monad (monad 'identity)) diff --git a/test/unit/unit-calrissian-maybe-monad-tests.lfe b/test/unit-calrissian-maybe-monad-tests.lfe similarity index 75% rename from test/unit/unit-calrissian-maybe-monad-tests.lfe rename to test/unit-calrissian-maybe-monad-tests.lfe index e463b49..16de31c 100644 --- a/test/unit/unit-calrissian-maybe-monad-tests.lfe +++ b/test/unit-calrissian-maybe-monad-tests.lfe @@ -1,13 +1,10 @@ (defmodule unit-calrissian-maybe-monad-tests - (export all) - (import - (from lfeunit-util - (check-failed-assert 2) - (check-wrong-assert-exception 2)))) + (behaviour ltest-unit) + (export all)) -(include-lib "deps/lfeunit/include/lfeunit-macros.lfe") -(include-lib "include/monads.lfe") -(include-lib "include/monad-tests.lfe") +(include-lib "ltest/include/ltest-macros.lfe") +(include-lib "calrissian/include/monads.lfe") +(include-lib "calrissian/include/monad-tests.lfe") (test-monad (monad 'maybe)) diff --git a/test/unit/unit-calrissian-state-transformer-tests.lfe b/test/unit-calrissian-state-transformer-tests.lfe similarity index 86% rename from test/unit/unit-calrissian-state-transformer-tests.lfe rename to test/unit-calrissian-state-transformer-tests.lfe index 99e1c8a..02f1718 100644 --- a/test/unit/unit-calrissian-state-transformer-tests.lfe +++ b/test/unit-calrissian-state-transformer-tests.lfe @@ -1,13 +1,10 @@ (defmodule unit-calrissian-state-transformer-tests - (export all) - (import - (from lfeunit-util - (check-failed-assert 2) - (check-wrong-assert-exception 2)))) + (behaviour ltest-unit) + (export all)) -(include-lib "deps/lfeunit/include/lfeunit-macros.lfe") -(include-lib "include/monads.lfe") -(include-lib "include/monad-tests.lfe") +(include-lib "ltest/include/ltest-macros.lfe") +(include-lib "calrissian/include/monads.lfe") +(include-lib "calrissian/include/monad-tests.lfe") (test-monad (transformer 'state 'identity))