From afcc5eaecd7b6878ce0399a8b7d6a113c4b004b9 Mon Sep 17 00:00:00 2001 From: Justin Ethier Date: Thu, 23 Mar 2017 00:21:16 -0400 Subject: [PATCH 01/37] WIP --- Makefile | 3 ++- Makefile.config | 6 ++++-- cyclone.scm | 5 +++-- runtime.c | 5 +++++ 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index bb6235aa..29b4fa2c 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ include Makefile.config # Commands CYCLONE = cyclone -A . -CCOMP = $(CC) $(CFLAGS) +CCOMP = $(CC) $(LIB_CFLAGS) INDENT_CMD = indent -linux -l80 -i2 -nut # Directories @@ -162,6 +162,7 @@ runtime.o : runtime.c $(HEADERS) -DCYC_CC_PROG=\"$(CC_PROG)\" \ -DCYC_CC_EXEC=\"$(CC_EXEC)\" \ -DCYC_CC_LIB=\"$(CC_LIB)\" \ + -DCYC_CC_SO=\"$(CC_SO)\" \ $< -o $@ libcyclone.a : runtime.o gc.o dispatch.o mstreams.o diff --git a/Makefile.config b/Makefile.config index c0eb6c25..4de3fe88 100644 --- a/Makefile.config +++ b/Makefile.config @@ -5,8 +5,9 @@ # Configuration options for the makefile # Compiler options -CFLAGS ?= -O2 -Wall -Iinclude -L. -COMP_CFLAGS ?= -O2 -Wall -I$(PREFIX)/include -L$(PREFIX)/lib +CFLAGS ?= -O2 -fPIC -Wall -Iinclude -L. +LIB_CFLAGS ?= -O2 -Wall -Iinclude -L. +COMP_CFLAGS ?= -O2 -fPIC -Wall -I$(PREFIX)/include -L$(PREFIX)/lib # Use these lines instead for debugging or profiling #CFLAGS = -g -Wall #CFLAGS = -g -pg -Wall @@ -17,6 +18,7 @@ LIBS = -pthread -lcyclone -lck -lm -ltommath CC_PROG ?= "$(CC) ~src-file~ $(COMP_CFLAGS) -c -o ~exec-file~.o" CC_EXEC ?= "$(CC) ~exec-file~.o ~obj-files~ $(LIBS) $(COMP_CFLAGS) -o ~exec-file~" CC_LIB ?= "$(CC) ~src-file~ $(COMP_CFLAGS) -c -o ~exec-file~.o" +CC_SO ?= "$(CC) -shared -o ~exec-file~.so -o ~exec-file~.o" AR ?= ar #CD ?= cd diff --git a/cyclone.scm b/cyclone.scm index 6ee9e670..8e2a61f0 100644 --- a/cyclone.scm +++ b/cyclone.scm @@ -454,15 +454,16 @@ (let ((comp-lib-cmd (string-replace-all (string-replace-all - ;(Cyc-compilation-environment 'cc-lib) (get-comp-env 'cc-lib cc-lib) "~src-file~" src-file) "~exec-file~" exec-file))) (cond (cc? - (system comp-lib-cmd)) + (system comp-lib-cmd) + ) (else (display comp-lib-cmd) + (newline) (newline)))))))) ;; Collect values for the given command line arguments and option. diff --git a/runtime.c b/runtime.c index a45d33e6..3e8600e9 100644 --- a/runtime.c +++ b/runtime.c @@ -2156,6 +2156,11 @@ object Cyc_compilation_environment(void *data, object cont, object var) snprintf(buf, sizeof(buf), "%s", CYC_CC_LIB); make_string(str, buf); _return_closcall1(data, cont, &str); + } else if (strncmp(((symbol) var)->desc, "cc-so", 6) == 0) { + char buf[1024]; + snprintf(buf, sizeof(buf), "%s", CYC_CC_SO); + make_string(str, buf); + _return_closcall1(data, cont, &str); } } Cyc_rt_raise2(data, From a93c1e8cdeb892786a8151748c855b51d2379465 Mon Sep 17 00:00:00 2001 From: Justin Ethier Date: Thu, 23 Mar 2017 04:47:47 -0400 Subject: [PATCH 02/37] Added so generation and dl lib --- Makefile.config | 4 ++-- cyclone.scm | 18 +++++++++++++++--- include/cyclone/types.h | 2 ++ runtime.c | 18 ++++++++++++++++++ scheme/cyclone/libraries.sld | 15 +++++++++++++++ 5 files changed, 52 insertions(+), 5 deletions(-) diff --git a/Makefile.config b/Makefile.config index 4de3fe88..801bb5a4 100644 --- a/Makefile.config +++ b/Makefile.config @@ -12,13 +12,13 @@ COMP_CFLAGS ?= -O2 -fPIC -Wall -I$(PREFIX)/include -L$(PREFIX)/lib #CFLAGS = -g -Wall #CFLAGS = -g -pg -Wall CC ?= cc -LIBS = -pthread -lcyclone -lck -lm -ltommath +LIBS = -pthread -lcyclone -lck -lm -ltommath -ldl # Commands "baked into" cyclone for invoking the C compiler CC_PROG ?= "$(CC) ~src-file~ $(COMP_CFLAGS) -c -o ~exec-file~.o" CC_EXEC ?= "$(CC) ~exec-file~.o ~obj-files~ $(LIBS) $(COMP_CFLAGS) -o ~exec-file~" CC_LIB ?= "$(CC) ~src-file~ $(COMP_CFLAGS) -c -o ~exec-file~.o" -CC_SO ?= "$(CC) -shared -o ~exec-file~.so -o ~exec-file~.o" +CC_SO ?= "$(CC) -shared -o ~exec-file~.so ~exec-file~.o" AR ?= ar #CD ?= cd diff --git a/cyclone.scm b/cyclone.scm index 8e2a61f0..4b904c40 100644 --- a/cyclone.scm +++ b/cyclone.scm @@ -370,7 +370,7 @@ (read-all port)))) ;; Compile and emit: -(define (run-compiler args cc? cc-prog cc-exec cc-lib append-dirs prepend-dirs) +(define (run-compiler args cc? cc-prog cc-exec cc-lib cc-so append-dirs prepend-dirs) (let* ((in-file (car args)) (expander (base-expander)) (in-prog-raw (read-file in-file)) @@ -456,14 +456,23 @@ (string-replace-all (get-comp-env 'cc-lib cc-lib) "~src-file~" src-file) - "~exec-file~" exec-file))) + "~exec-file~" exec-file)) + (comp-so-cmd + (string-replace-all + (string-replace-all + (get-comp-env 'cc-so cc-so) + "~src-file~" src-file) + "~exec-file~" exec-file)) + ) (cond (cc? (system comp-lib-cmd) + (system comp-so-cmd) ) (else (display comp-lib-cmd) (newline) + (display comp-so-cmd) (newline)))))))) ;; Collect values for the given command line arguments and option. @@ -500,6 +509,7 @@ (cc-prog (apply string-append (collect-opt-values args "-CP"))) (cc-exec (apply string-append (collect-opt-values args "-CE"))) (cc-lib (apply string-append (collect-opt-values args "-CL"))) + (cc-so (apply string-append (collect-opt-values args "-CS"))) (append-dirs (collect-opt-values args "-A")) (prepend-dirs (collect-opt-values args "-I"))) ;; Set optimization level(s) @@ -526,6 +536,8 @@ an executable. -CL cc-commands Specify a custom command line for the C compiler to compile a library module. + -CS cc-commands Specify a custom command line for the C compiler to compile + a shared object module. -Ox Optimization level, higher means more optimizations will be used. Set to 0 to disable optimizations. -d Only generate intermediate C files, do not compile them @@ -548,5 +560,5 @@ (display "cyclone: no input file") (newline)) (else - (run-compiler non-opts compile? cc-prog cc-exec cc-lib append-dirs prepend-dirs)))) + (run-compiler non-opts compile? cc-prog cc-exec cc-lib cc-so append-dirs prepend-dirs)))) diff --git a/include/cyclone/types.h b/include/cyclone/types.h index f59f73e6..86ed9f9d 100644 --- a/include/cyclone/types.h +++ b/include/cyclone/types.h @@ -18,6 +18,7 @@ #include #include #include +#include #include "tommath.h" /** @@ -1059,4 +1060,5 @@ void *gc_alloc_from_bignum(gc_thread_data *data, bignum_type *src); int gc_minor(void *data, object low_limit, object high_limit, closure cont, object * args, int num_args); +void Cyc_import_shared_object(void *data, object cont, object filename, object entry_pt_fnc); #endif /* CYCLONE_TYPES_H */ diff --git a/runtime.c b/runtime.c index 3e8600e9..6a37f83f 100644 --- a/runtime.c +++ b/runtime.c @@ -5592,3 +5592,21 @@ double MRG32k3a (double seed) return ((p1 - p2) * norm); } /* END RNG */ + + +/** Dynamic loading */ +void Cyc_import_shared_object(void *data, object cont, object filename, object entry_pt_fnc) +{ + void *handle; + function_type entry_pt; + Cyc_check_str(data, filename); + Cyc_check_str(data, entry_pt_fnc); + handle = dlopen(string_str(filename), RTLD_LAZY); + if (handle == NULL) { + Cyc_rt_raise2(data, "Unable to import library from", filename); + } + entry_pt = (function_type) dlsym(handle, string_str(entry_pt_fnc)); + mclosure1(clo, entry_pt, cont); + entry_pt(data, 0, &clo, &clo); +} + diff --git a/scheme/cyclone/libraries.sld b/scheme/cyclone/libraries.sld index a3650373..47f956b5 100644 --- a/scheme/cyclone/libraries.sld +++ b/scheme/cyclone/libraries.sld @@ -58,6 +58,8 @@ lib:idb:lookup lib:idb:entry->library-name lib:idb:entry->library-id + ;; Dynamic import + lib:dyn-load ) (begin @@ -589,4 +591,17 @@ (deps (reverse (cdr (get-cell resolved))))) ;; cdr to get rid of master list (map car deps))) + +(define (lib:dyn-load import) + (let ((lib-name (lib:list->import-set import))) + (c:dyn-load + (lib:import->filename lib-name ".so") + (string-append + " c_" (lib:name->string lib-name) "_entry_pt_first_lambda")))) + +(define-c c:dyn-load + "(void *data, int argc, closure _, object k, object fn, object entry_fnc)" + " Cyc_import_shared_object(data, k, fn, entry_fnc); ") + + )) From a63fb1b1c788497c5edd33b8b08af78fcc3391d3 Mon Sep 17 00:00:00 2001 From: Justin Ethier Date: Wed, 22 Mar 2017 18:38:34 -0400 Subject: [PATCH 03/37] WIP --- runtime.c | 11 ++++++++++- scheme/cyclone/libraries.sld | 2 +- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/runtime.c b/runtime.c index 6a37f83f..d4316f00 100644 --- a/runtime.c +++ b/runtime.c @@ -5603,9 +5603,18 @@ void Cyc_import_shared_object(void *data, object cont, object filename, object e Cyc_check_str(data, entry_pt_fnc); handle = dlopen(string_str(filename), RTLD_LAZY); if (handle == NULL) { - Cyc_rt_raise2(data, "Unable to import library from", filename); + //make_string(s, dlerror()); + fprintf(stderr, "%s\n", dlerror()); + Cyc_rt_raise2(data, "Unable to import library", filename); } + dlerror(); /* Clear any existing error */ + entry_pt = (function_type) dlsym(handle, string_str(entry_pt_fnc)); + if (entry_pt == NULL) { + //make_string(s, dlerror()); + fprintf(stderr, "%s\n", dlerror()); + Cyc_rt_raise2(data, "Unable to load symbol", entry_pt_fnc); + } mclosure1(clo, entry_pt, cont); entry_pt(data, 0, &clo, &clo); } diff --git a/scheme/cyclone/libraries.sld b/scheme/cyclone/libraries.sld index 47f956b5..ea70b219 100644 --- a/scheme/cyclone/libraries.sld +++ b/scheme/cyclone/libraries.sld @@ -597,7 +597,7 @@ (c:dyn-load (lib:import->filename lib-name ".so") (string-append - " c_" (lib:name->string lib-name) "_entry_pt_first_lambda")))) + "c_" (lib:name->string lib-name) "_entry_pt_first_lambda")))) (define-c c:dyn-load "(void *data, int argc, closure _, object k, object fn, object entry_fnc)" From a6f42b28692e0af95f91ffafcf0ff8267879eaae Mon Sep 17 00:00:00 2001 From: Justin Ethier Date: Wed, 22 Mar 2017 18:39:31 -0400 Subject: [PATCH 04/37] Experimenting with -rdynamic - not sure this is final --- Makefile.config | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Makefile.config b/Makefile.config index 801bb5a4..1620b102 100644 --- a/Makefile.config +++ b/Makefile.config @@ -5,9 +5,9 @@ # Configuration options for the makefile # Compiler options -CFLAGS ?= -O2 -fPIC -Wall -Iinclude -L. -LIB_CFLAGS ?= -O2 -Wall -Iinclude -L. -COMP_CFLAGS ?= -O2 -fPIC -Wall -I$(PREFIX)/include -L$(PREFIX)/lib +CFLAGS ?= -g -fPIC -rdynamic -Wall -Iinclude -L. +LIB_CFLAGS ?= -g -rdynamic -Wall -Iinclude -L. +COMP_CFLAGS ?= -g -fPIC -rdynamic -Wall -I$(PREFIX)/include -L$(PREFIX)/lib # Use these lines instead for debugging or profiling #CFLAGS = -g -Wall #CFLAGS = -g -pg -Wall @@ -18,7 +18,7 @@ LIBS = -pthread -lcyclone -lck -lm -ltommath -ldl CC_PROG ?= "$(CC) ~src-file~ $(COMP_CFLAGS) -c -o ~exec-file~.o" CC_EXEC ?= "$(CC) ~exec-file~.o ~obj-files~ $(LIBS) $(COMP_CFLAGS) -o ~exec-file~" CC_LIB ?= "$(CC) ~src-file~ $(COMP_CFLAGS) -c -o ~exec-file~.o" -CC_SO ?= "$(CC) -shared -o ~exec-file~.so ~exec-file~.o" +CC_SO ?= "$(CC) -shared -rdynamic -o ~exec-file~.so ~exec-file~.o" AR ?= ar #CD ?= cd From 6f2bf6f72e82976de9aad8cff890819e43da6e76 Mon Sep 17 00:00:00 2001 From: Justin Ethier Date: Wed, 22 Mar 2017 19:02:11 -0400 Subject: [PATCH 05/37] Big TODO for next steps --- scheme/cyclone/libraries.sld | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/scheme/cyclone/libraries.sld b/scheme/cyclone/libraries.sld index ea70b219..0ad3c4f1 100644 --- a/scheme/cyclone/libraries.sld +++ b/scheme/cyclone/libraries.sld @@ -592,6 +592,12 @@ (map car deps))) +TODO: this is not good enough because need to load new symbols into +the global environment for eval. I don't think it is good enough +to just reset env because then any vars, changes, etc are lost. +also, what library should all of this go into? could move these 2 +into (scheme eval) but can that module import libraries? or will that +cause build errors? lot of little details to decide here (define (lib:dyn-load import) (let ((lib-name (lib:list->import-set import))) (c:dyn-load From 8c55370b5dec565c6946f653cf243d51cd00add3 Mon Sep 17 00:00:00 2001 From: Justin Ethier Date: Thu, 23 Mar 2017 13:51:42 +0000 Subject: [PATCH 06/37] Adding import capability to eval --- icyc.scm | 12 +++++----- scheme/cyclone/libraries.sld | 21 ------------------ scheme/eval.sld | 43 +++++++++++++++++++++++++++++++----- 3 files changed, 43 insertions(+), 33 deletions(-) diff --git a/icyc.scm b/icyc.scm index 424333a1..87af4428 100644 --- a/icyc.scm +++ b/icyc.scm @@ -29,7 +29,7 @@ (display *Cyc-version-banner*)) (else #f)) -(define *icyc-env* (setup-environment)) +;(define *icyc-env* (setup-environment)) (define (repl:next-line) (call/cc (lambda (k) @@ -57,7 +57,7 @@ (define (repl) (display "cyclone> ") - (let ((c (eval (read) *icyc-env*))) + (let ((c (eval (read) #;*icyc-env*))) (cond ((not (eof-object? c)) (write c) @@ -68,11 +68,11 @@ (exit 0))))) ;; Use a special version of load to pull defs into the repl's env -(define (load2 f) - (load f *icyc-env*)) -(env:define-variable! 'load load2 *icyc-env*) +;(define (load2 f) +; (load f *icyc-env*)) +;(env:define-variable! 'load load2 *icyc-env*) (let ((args (command-line-arguments))) (if (= (length args) 1) - (load (car args) *icyc-env*)) + (load (car args) #;*icyc-env*)) (repl:next-line)) diff --git a/scheme/cyclone/libraries.sld b/scheme/cyclone/libraries.sld index 0ad3c4f1..a3650373 100644 --- a/scheme/cyclone/libraries.sld +++ b/scheme/cyclone/libraries.sld @@ -58,8 +58,6 @@ lib:idb:lookup lib:idb:entry->library-name lib:idb:entry->library-id - ;; Dynamic import - lib:dyn-load ) (begin @@ -591,23 +589,4 @@ (deps (reverse (cdr (get-cell resolved))))) ;; cdr to get rid of master list (map car deps))) - -TODO: this is not good enough because need to load new symbols into -the global environment for eval. I don't think it is good enough -to just reset env because then any vars, changes, etc are lost. -also, what library should all of this go into? could move these 2 -into (scheme eval) but can that module import libraries? or will that -cause build errors? lot of little details to decide here -(define (lib:dyn-load import) - (let ((lib-name (lib:list->import-set import))) - (c:dyn-load - (lib:import->filename lib-name ".so") - (string-append - "c_" (lib:name->string lib-name) "_entry_pt_first_lambda")))) - -(define-c c:dyn-load - "(void *data, int argc, closure _, object k, object fn, object entry_fnc)" - " Cyc_import_shared_object(data, k, fn, entry_fnc); ") - - )) diff --git a/scheme/eval.sld b/scheme/eval.sld index ba517bfe..7bdcdda1 100644 --- a/scheme/eval.sld +++ b/scheme/eval.sld @@ -10,7 +10,7 @@ (define-library (scheme eval) (import (scheme cyclone util) - ;(scheme cyclone libraries) ;; for handling import sets + (scheme cyclone libraries) ;; for handling import sets (scheme base) (scheme file) (scheme write) ;; Only used for debugging @@ -21,6 +21,8 @@ eval-from-c ; non-standard create-environment ; non-standard setup-environment ; non-standard + ;; Dynamic import + lib:dyn-load ;; TODO: eventually this becomes "import"? ) (begin @@ -322,11 +324,11 @@ ;; (define (primitive-procedure? proc) ;; (equal? proc 'cons)) -(define (setup-environment) +(define (setup-environment . env) (let ((initial-env - (env:extend-environment (primitive-procedure-names) - (primitive-procedure-objects) - env:the-empty-environment))) + (if (not (null? env)) + (car env) + (create-initial-environment)))) (cond-expand (cyclone ;; Also include compiled variables @@ -335,7 +337,13 @@ (map (lambda (v) (cdr v)) (Cyc-global-vars)) initial-env)) (else initial-env)))) -(define *global-environment* (setup-environment)) + +(define (create-initial-environment) + (env:extend-environment (primitive-procedure-names) + (primitive-procedure-objects) + env:the-empty-environment)) +(define *initial-environment* (create-initial-environment)) +(define *global-environment* (setup-environment (create-initial-environment))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; This step separates syntactic analysis from execution. @@ -578,4 +586,27 @@ ; (loop)) ;(loop) + + +;TODO: this is not good enough because need to load new symbols into +;the global environment for eval. I don't think it is good enough +;to just reset env because then any vars, changes, etc are lost. +;also, what library should all of this go into? could move these 2 +;into (scheme eval) but can that module import libraries? or will that +;cause build errors? lot of little details to decide here +(define (lib:dyn-load import) + (let ((lib-name (lib:list->import-set import))) + (c:dyn-load + (lib:import->filename lib-name ".so") + (string-append + "c_" (lib:name->string lib-name) "_entry_pt_first_lambda"))) + ;; Reload env with new compiled bindings + ;; NOTE: will undo any changes to these bindings!!! + (set! *global-environment* (setup-environment *initial-environment*)) + #t) + +(define-c c:dyn-load + "(void *data, int argc, closure _, object k, object fn, object entry_fnc)" + " Cyc_import_shared_object(data, k, fn, entry_fnc); ") + )) From 0cbcadc382695db965ca046ad786b85f76b11889 Mon Sep 17 00:00:00 2001 From: Justin Ethier Date: Thu, 23 Mar 2017 18:33:36 -0400 Subject: [PATCH 07/37] Added (%import) --- scheme/eval.sld | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/scheme/eval.sld b/scheme/eval.sld index 7bdcdda1..c49da8a9 100644 --- a/scheme/eval.sld +++ b/scheme/eval.sld @@ -22,7 +22,7 @@ create-environment ; non-standard setup-environment ; non-standard ;; Dynamic import - lib:dyn-load ;; TODO: eventually this becomes "import"? + %import ) (begin @@ -587,14 +587,25 @@ ;(loop) +;; TODO: right now this is a hack, just get all the imports sets and call their entry point +;; function to initialize them. longer-term will need to only load the specific identifiers +;; called out in the import sets +;; +;; TODO: get any dependencies and load them, too +(define (%import . import-sets) + (let ((lib-names (lib:get-all-import-deps import-sets '() '()))) + (for-each + (lambda (lib-name) + (c:dyn-load + (lib:import->filename lib-name ".so") + (string-append + "c_" (lib:name->string lib-name) "_entry_pt_first_lambda"))) + lib-names) + (set! *global-environment* (setup-environment *initial-environment*)) + #t)) -;TODO: this is not good enough because need to load new symbols into -;the global environment for eval. I don't think it is good enough -;to just reset env because then any vars, changes, etc are lost. -;also, what library should all of this go into? could move these 2 -;into (scheme eval) but can that module import libraries? or will that -;cause build errors? lot of little details to decide here -(define (lib:dyn-load import) +;; TODO: this function is just a proof of concept +#;(define (lib:dyn-load import) (let ((lib-name (lib:list->import-set import))) (c:dyn-load (lib:import->filename lib-name ".so") From a36d68a323909436a8ad7e48f7ba8fafb9a5a54d Mon Sep 17 00:00:00 2001 From: Justin Ethier Date: Thu, 23 Mar 2017 18:53:24 -0400 Subject: [PATCH 08/37] Initial support for (import) in eval --- scheme/eval.sld | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/scheme/eval.sld b/scheme/eval.sld index c49da8a9..a15c771e 100644 --- a/scheme/eval.sld +++ b/scheme/eval.sld @@ -375,6 +375,9 @@ (not (null? (cdr exp)))) (analyze-lambda exp env)) + ((tagged-list? 'import exp) + (analyze-import exp env)) + ;; experimenting with passing these back to eval ((compound-procedure? exp) (lambda (env) exp)) ;; TODO: good enough? update env? @@ -432,6 +435,13 @@ ; ;(lambda (env) ; (make-macro `(lambda ,vars ,@(lambda-body exp))))) +(define (analyze-import exp env) + (lambda (env) + ;; TODO: allow %import to take env + (write `(%import ,(cdr exp))) + (apply %import (cdr exp)) + 'ok)) + (define (analyze-if exp a-env) (let ((pproc (analyze (if-predicate exp) a-env)) (cproc (analyze (if-consequent exp) a-env)) From 9d1365f56f5e0f93c1863950f41c58f1ddc3f82e Mon Sep 17 00:00:00 2001 From: Justin Ethier Date: Fri, 24 Mar 2017 12:39:03 +0000 Subject: [PATCH 09/37] Install/clean `.so` files --- Makefile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 29b4fa2c..c44beab7 100644 --- a/Makefile +++ b/Makefile @@ -40,7 +40,7 @@ example : cd $(EXAMPLE_DIR) ; make clean : - rm -rf test.txt a.out *.o *.a *.out tags cyclone icyc scheme/*.o scheme/*.c scheme/*.meta srfi/*.c srfi/*.meta srfi/*.o scheme/cyclone/*.o scheme/cyclone/*.c scheme/cyclone/*.meta cyclone.c dispatch.c icyc.c generate-c.c generate-c + rm -rf test.txt a.out *.so *.o *.a *.out tags cyclone icyc scheme/*.o scheme/*.so scheme/*.c scheme/*.meta srfi/*.c srfi/*.meta srfi/*.o srfi/*.so scheme/cyclone/*.o scheme/cyclone/*.so scheme/cyclone/*.c scheme/cyclone/*.meta cyclone.c dispatch.c icyc.c generate-c.c generate-c cd $(EXAMPLE_DIR) ; make clean rm -rf html tests/*.o tests/*.c @@ -53,12 +53,15 @@ install : libs install-libs install-includes install-bin $(MKDIR) $(DESTDIR)$(DATADIR)/srfi/sorting $(INSTALL) -m0644 scheme/*.sld $(DESTDIR)$(DATADIR)/scheme $(INSTALL) -m0644 scheme/*.o $(DESTDIR)$(DATADIR)/scheme + $(INSTALL) -m0644 scheme/*.so $(DESTDIR)$(DATADIR)/scheme $(INSTALL) -m0644 scheme/cyclone/*.sld $(DESTDIR)$(DATADIR)/scheme/cyclone $(INSTALL) -m0644 scheme/cyclone/*.scm $(DESTDIR)$(DATADIR)/scheme/cyclone $(INSTALL) -m0644 scheme/cyclone/test.meta $(DESTDIR)$(DATADIR)/scheme/cyclone $(INSTALL) -m0644 scheme/cyclone/*.o $(DESTDIR)$(DATADIR)/scheme/cyclone + $(INSTALL) -m0644 scheme/cyclone/*.so $(DESTDIR)$(DATADIR)/scheme/cyclone $(INSTALL) -m0644 srfi/*.sld $(DESTDIR)$(DATADIR)/srfi $(INSTALL) -m0644 srfi/*.o $(DESTDIR)$(DATADIR)/srfi + $(INSTALL) -m0644 srfi/*.so $(DESTDIR)$(DATADIR)/srfi $(INSTALL) -m0644 srfi/*.meta $(DESTDIR)$(DATADIR)/srfi $(INSTALL) -m0644 srfi/list-queues/*.scm $(DESTDIR)$(DATADIR)/srfi/list-queues $(INSTALL) -m0644 srfi/sets/*.scm $(DESTDIR)$(DATADIR)/srfi/sets From 435d15d2f499d0398cfc573b787b0b82a1fc82b8 Mon Sep 17 00:00:00 2001 From: Justin Ethier Date: Fri, 24 Mar 2017 17:37:04 +0000 Subject: [PATCH 10/37] Cleanup, adding TODO's --- scheme/eval.sld | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/scheme/eval.sld b/scheme/eval.sld index a15c771e..09a507e9 100644 --- a/scheme/eval.sld +++ b/scheme/eval.sld @@ -602,8 +602,21 @@ ;; called out in the import sets ;; ;; TODO: get any dependencies and load them, too +;; TODO: for some of that (prefix, maybe other stuff), can we do the renaming in the env?? (define (%import . import-sets) (let ((lib-names (lib:get-all-import-deps import-sets '() '()))) + + ;; TODO: + ;; Instead of blindly loading everything, should only load the libraries that are + ;; actually needed. may want to create a new table in the runtime that keeps track of + ;; loaded libraries. maybe have one of the libck data structures be used for it. could + ;; then have supporting functions: + ;; - add_lib - auto-generated call placed in each lib's entry point + ;; - check_lib - called here to look up each library to see if it is already loaded + ;; one issue - what if a library has changed and really should be reloaded? + ;; also, is there any value to loading a library that is not compiled? I guess we can + ;; sort of do that now via (load). + (for-each (lambda (lib-name) (c:dyn-load @@ -614,18 +627,7 @@ (set! *global-environment* (setup-environment *initial-environment*)) #t)) -;; TODO: this function is just a proof of concept -#;(define (lib:dyn-load import) - (let ((lib-name (lib:list->import-set import))) - (c:dyn-load - (lib:import->filename lib-name ".so") - (string-append - "c_" (lib:name->string lib-name) "_entry_pt_first_lambda"))) - ;; Reload env with new compiled bindings - ;; NOTE: will undo any changes to these bindings!!! - (set! *global-environment* (setup-environment *initial-environment*)) - #t) - +;; Wrapper around the actual shared object import function (define-c c:dyn-load "(void *data, int argc, closure _, object k, object fn, object entry_fnc)" " Cyc_import_shared_object(data, k, fn, entry_fnc); ") From 6d85b83240cc7ad229d6c85494b48fb3f41530ee Mon Sep 17 00:00:00 2001 From: Justin Ethier Date: Tue, 28 Mar 2017 01:19:20 -0400 Subject: [PATCH 11/37] WIP --- include/cyclone/runtime.h | 10 ++++++++++ runtime.c | 32 ++++++++++++++++++++++++++++++++ scheme/cyclone/cgen.sld | 3 +++ scheme/cyclone/libraries.sld | 11 +++++++++++ scheme/eval.sld | 4 ++-- 5 files changed, 58 insertions(+), 2 deletions(-) diff --git a/include/cyclone/runtime.h b/include/cyclone/runtime.h index f62cd9f6..706275ef 100644 --- a/include/cyclone/runtime.h +++ b/include/cyclone/runtime.h @@ -649,6 +649,16 @@ object find_or_add_symbol(const char *name); char *_strdup(const char *s); /**@}*/ +/** + * \defgroup prim_glo Library table + * + * @brief A table of scheme libraries that are loaded. + */ +/**@{*/ +object is_library_loaded(const char *name); +object register_library(const char *name); +/**@}*/ + /** * \defgroup prim_glo Global table * diff --git a/runtime.c b/runtime.c index d4316f00..945d3b1d 100644 --- a/runtime.c +++ b/runtime.c @@ -148,6 +148,7 @@ char **_cyc_argv = NULL; static symbol_type __EOF = { {0}, eof_tag, ""}; // symbol_type in lieu of custom type const object Cyc_EOF = &__EOF; +static ck_hs_t lib_table; static ck_hs_t symbol_table; static int symbol_table_initial_size = 4096; static pthread_mutex_t symbol_table_lock; @@ -265,6 +266,13 @@ static bool set_insert(ck_hs_t * hs, const void *value) */ void gc_init_heap(long heap_size) { + if (!ck_hs_init(&lib_table, + CK_HS_MODE_OBJECT | CK_HS_MODE_SPMC, + hs_hash, hs_compare, + &my_allocator, 32, 43423)) { + fprintf(stderr, "Unable to initialize library table\n"); + exit(1); + } if (!ck_hs_init(&symbol_table, CK_HS_MODE_OBJECT | CK_HS_MODE_SPMC, hs_hash, hs_compare, @@ -386,6 +394,30 @@ object find_or_add_symbol(const char *name) /* END symbol table */ +/* Library table */ +object is_library_loaded(const char *name) +{ + symbol_type tmp = { {0}, symbol_tag, name}; + object result = set_get(&symbol_table, &tmp); + if (result) + return boolean_t; + return boolean_f; +} + +object register_library(const char *name) +{ + symbol_type sym = { {0}, symbol_tag, _strdup(name)}; + symbol_type *psym = malloc(sizeof(symbol_type)); + memcpy(psym, &sym, sizeof(symbol_type)); + // Reuse mutex since lib inserts will be rare + pthread_mutex_lock(&symbol_table_lock); // Only 1 "writer" allowed + set_insert(&lib_table, psym); + pthread_mutex_unlock(&symbol_table_lock); + return psym; +} +/* END Library table */ + + /* Global table */ list global_table = NULL; diff --git a/scheme/cyclone/cgen.sld b/scheme/cyclone/cgen.sld index 5bfc26fe..f092b223 100644 --- a/scheme/cyclone/cgen.sld +++ b/scheme/cyclone/cgen.sld @@ -1421,6 +1421,9 @@ (emit* "}") (emit* "void c_" (lib:name->string lib-name) "_entry_pt(data, argc, cont,value) void *data; int argc; closure cont; object value;{ ") + (emit* " register_library(\"" + (lib:name->unique-string lib-name) + "\");") (if (null? lib-pass-thru-exports) (emit* " c_" (lib:name->string lib-name) "_entry_pt_first_lambda(data, argc, cont,value);") ; GC to ensure objects are moved when exporting exports. diff --git a/scheme/cyclone/libraries.sld b/scheme/cyclone/libraries.sld index a3650373..da183664 100644 --- a/scheme/cyclone/libraries.sld +++ b/scheme/cyclone/libraries.sld @@ -25,6 +25,7 @@ lib:name lib:name->string lib:name->symbol + lib:name->unique-string lib:result lib:exports lib:rename-exports @@ -119,6 +120,16 @@ (define (lib:name->string name) (apply string-append (map mangle (lib:import->library-name name)))) +;; Convert name (as list of symbols) to a mangled string guaranteed to be unique +(define (lib:name->unique-string name) + (foldl + (lambda (s acc) + (if (> (string-length acc) 0) + (string-append acc "_" s) + s)) + "" + (map mangle (lib:import->library-name name)))) + ;; Convert library name to a unique symbol (define (lib:name->symbol name) (string->symbol diff --git a/scheme/eval.sld b/scheme/eval.sld index 09a507e9..1583e80f 100644 --- a/scheme/eval.sld +++ b/scheme/eval.sld @@ -437,8 +437,8 @@ (define (analyze-import exp env) (lambda (env) - ;; TODO: allow %import to take env - (write `(%import ,(cdr exp))) + ;; FUTURE: allow %import to take env? + ;(write `(%import ,(cdr exp))) (apply %import (cdr exp)) 'ok)) From 793e4e1426d666607e152700ca984294da1d06e1 Mon Sep 17 00:00:00 2001 From: Justin Ethier Date: Tue, 28 Mar 2017 04:45:24 -0400 Subject: [PATCH 12/37] Cleanup, do not import loaded libraries --- scheme/eval.sld | 34 +++++++++++++++------------------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/scheme/eval.sld b/scheme/eval.sld index 1583e80f..b515e7f1 100644 --- a/scheme/eval.sld +++ b/scheme/eval.sld @@ -601,35 +601,31 @@ ;; function to initialize them. longer-term will need to only load the specific identifiers ;; called out in the import sets ;; -;; TODO: get any dependencies and load them, too -;; TODO: for some of that (prefix, maybe other stuff), can we do the renaming in the env?? +;; TODO: for some imports (prefix, maybe other stuff), can we do the renaming in the env?? (define (%import . import-sets) (let ((lib-names (lib:get-all-import-deps import-sets '() '()))) - - ;; TODO: - ;; Instead of blindly loading everything, should only load the libraries that are - ;; actually needed. may want to create a new table in the runtime that keeps track of - ;; loaded libraries. maybe have one of the libck data structures be used for it. could - ;; then have supporting functions: - ;; - add_lib - auto-generated call placed in each lib's entry point - ;; - check_lib - called here to look up each library to see if it is already loaded - ;; one issue - what if a library has changed and really should be reloaded? - ;; also, is there any value to loading a library that is not compiled? I guess we can - ;; sort of do that now via (load). - (for-each (lambda (lib-name) - (c:dyn-load - (lib:import->filename lib-name ".so") - (string-append - "c_" (lib:name->string lib-name) "_entry_pt_first_lambda"))) + (let ((loaded? (c:lib-loaded? (lib:name->unique-string lib-name)))) + (if loaded? + (c:import-shared-obj + (lib:import->filename lib-name ".so") + (string-append + "c_" (lib:name->string lib-name) "_entry_pt_first_lambda")) + ;(write `(,lib-name is already loaded skipping)) + ))) lib-names) (set! *global-environment* (setup-environment *initial-environment*)) #t)) ;; Wrapper around the actual shared object import function -(define-c c:dyn-load +(define-c c:import-shared-obj "(void *data, int argc, closure _, object k, object fn, object entry_fnc)" " Cyc_import_shared_object(data, k, fn, entry_fnc); ") +(define-c c:lib-loaded? + "(void *data, int argc, closure _, object k, object name)" + " Cyc_check_str(data, name); + return_closcall1(data, k, is_library_loaded(string_str(name))); ") + )) From 5d06cf1836b06a4d76d79524d12463c63b91793f Mon Sep 17 00:00:00 2001 From: Justin Ethier Date: Mon, 27 Mar 2017 17:42:22 -0400 Subject: [PATCH 13/37] Issue #87 - `eval` now supports `import` --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c33baf4e..4a90fbbd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ Features +- Cyclone now has support in the interpreter for loading libraries via `import`. This is probably the most important change in this release and allows `icyc` to be used to its full potential. - Store parameter objects in such a way that changes to a parameter object do not affect other threads that use the same parameter object. The specific requirement from R7RS is: From 3ee462f54c9c57d7b87cea3bdfa9fed7a9d25793 Mon Sep 17 00:00:00 2001 From: Justin Ethier Date: Mon, 27 Mar 2017 17:43:15 -0400 Subject: [PATCH 14/37] Bumping to 0.5 --- CHANGELOG.md | 2 +- scheme/cyclone/common.sld | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4a90fbbd..69192409 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## TBD (Tenatively 0.4.1) +## TBD (Tenatively 0.5) Features diff --git a/scheme/cyclone/common.sld b/scheme/cyclone/common.sld index ff6fdee0..2de255b1 100644 --- a/scheme/cyclone/common.sld +++ b/scheme/cyclone/common.sld @@ -15,7 +15,7 @@ *version-banner* *c-file-header-comment*) (begin -(define *version-number* "0.4.1") +(define *version-number* "0.5") (define *version-name* "") (define *version* (string-append *version-number* " " *version-name* "")) From ee48b908e2ada56613a5b870f0afc3556547bbee Mon Sep 17 00:00:00 2001 From: Justin Ethier Date: Mon, 27 Mar 2017 19:02:54 -0400 Subject: [PATCH 15/37] Debugging --- scheme/eval.sld | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/scheme/eval.sld b/scheme/eval.sld index b515e7f1..347e0071 100644 --- a/scheme/eval.sld +++ b/scheme/eval.sld @@ -23,6 +23,7 @@ setup-environment ; non-standard ;; Dynamic import %import + c:lib-loaded? ;; TODO: debug only! ) (begin @@ -606,13 +607,15 @@ (let ((lib-names (lib:get-all-import-deps import-sets '() '()))) (for-each (lambda (lib-name) - (let ((loaded? (c:lib-loaded? (lib:name->unique-string lib-name)))) - (if loaded? + (let* ((us (lib:name->unique-string lib-name)) + (loaded? (c:lib-loaded? us))) +;; TODO: some kind of bug here, seems libraries are never registered as loaded + (if (not loaded?) (c:import-shared-obj (lib:import->filename lib-name ".so") (string-append "c_" (lib:name->string lib-name) "_entry_pt_first_lambda")) - ;(write `(,lib-name is already loaded skipping)) + (begin (write `(,lib-name ,us ,loaded? is already loaded skipping)) (newline)) ))) lib-names) (set! *global-environment* (setup-environment *initial-environment*)) From 3993a4d2773fb42827de9bb8a1c927022538cef9 Mon Sep 17 00:00:00 2001 From: Justin Ethier Date: Tue, 28 Mar 2017 09:46:57 +0000 Subject: [PATCH 16/37] Fixed table reference --- runtime.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime.c b/runtime.c index 945d3b1d..b9798c92 100644 --- a/runtime.c +++ b/runtime.c @@ -398,7 +398,7 @@ object find_or_add_symbol(const char *name) object is_library_loaded(const char *name) { symbol_type tmp = { {0}, symbol_tag, name}; - object result = set_get(&symbol_table, &tmp); + object result = set_get(&lib_table, &tmp); if (result) return boolean_t; return boolean_f; From 4dd72a876cd172f27e4e5a45efdaed1dbd4f8009 Mon Sep 17 00:00:00 2001 From: Justin Ethier Date: Tue, 28 Mar 2017 10:14:02 +0000 Subject: [PATCH 17/37] Load unloaded or explicitly imported libs --- scheme/eval.sld | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/scheme/eval.sld b/scheme/eval.sld index 347e0071..931cebe2 100644 --- a/scheme/eval.sld +++ b/scheme/eval.sld @@ -604,18 +604,22 @@ ;; ;; TODO: for some imports (prefix, maybe other stuff), can we do the renaming in the env?? (define (%import . import-sets) - (let ((lib-names (lib:get-all-import-deps import-sets '() '()))) + (let (;; Libraries explicitly listed in the import expression + (explicit-lib-names + (map lib:import->library-name (lib:list->import-set import-sets))) + ;; All dependent libraries + (lib-names (lib:get-all-import-deps import-sets '() '()))) (for-each (lambda (lib-name) (let* ((us (lib:name->unique-string lib-name)) (loaded? (c:lib-loaded? us))) -;; TODO: some kind of bug here, seems libraries are never registered as loaded - (if (not loaded?) + (if (or (not loaded?) + (member lib-name explicit-lib-names)) (c:import-shared-obj (lib:import->filename lib-name ".so") (string-append "c_" (lib:name->string lib-name) "_entry_pt_first_lambda")) - (begin (write `(,lib-name ,us ,loaded? is already loaded skipping)) (newline)) + ;(begin (write `(,lib-name ,us ,loaded? is already loaded skipping)) (newline)) ))) lib-names) (set! *global-environment* (setup-environment *initial-environment*)) From 205905a629ae30592b7ee8e867a025b57380c445 Mon Sep 17 00:00:00 2001 From: Justin Ethier Date: Tue, 28 Mar 2017 11:12:01 +0000 Subject: [PATCH 18/37] Cleanup --- Makefile | 6 +++--- scheme/eval.sld | 1 - 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index c44beab7..ebb18754 100644 --- a/Makefile +++ b/Makefile @@ -53,15 +53,15 @@ install : libs install-libs install-includes install-bin $(MKDIR) $(DESTDIR)$(DATADIR)/srfi/sorting $(INSTALL) -m0644 scheme/*.sld $(DESTDIR)$(DATADIR)/scheme $(INSTALL) -m0644 scheme/*.o $(DESTDIR)$(DATADIR)/scheme - $(INSTALL) -m0644 scheme/*.so $(DESTDIR)$(DATADIR)/scheme + $(INSTALL) -m0755 scheme/*.so $(DESTDIR)$(DATADIR)/scheme $(INSTALL) -m0644 scheme/cyclone/*.sld $(DESTDIR)$(DATADIR)/scheme/cyclone $(INSTALL) -m0644 scheme/cyclone/*.scm $(DESTDIR)$(DATADIR)/scheme/cyclone $(INSTALL) -m0644 scheme/cyclone/test.meta $(DESTDIR)$(DATADIR)/scheme/cyclone $(INSTALL) -m0644 scheme/cyclone/*.o $(DESTDIR)$(DATADIR)/scheme/cyclone - $(INSTALL) -m0644 scheme/cyclone/*.so $(DESTDIR)$(DATADIR)/scheme/cyclone + $(INSTALL) -m0755 scheme/cyclone/*.so $(DESTDIR)$(DATADIR)/scheme/cyclone $(INSTALL) -m0644 srfi/*.sld $(DESTDIR)$(DATADIR)/srfi $(INSTALL) -m0644 srfi/*.o $(DESTDIR)$(DATADIR)/srfi - $(INSTALL) -m0644 srfi/*.so $(DESTDIR)$(DATADIR)/srfi + $(INSTALL) -m0755 srfi/*.so $(DESTDIR)$(DATADIR)/srfi $(INSTALL) -m0644 srfi/*.meta $(DESTDIR)$(DATADIR)/srfi $(INSTALL) -m0644 srfi/list-queues/*.scm $(DESTDIR)$(DATADIR)/srfi/list-queues $(INSTALL) -m0644 srfi/sets/*.scm $(DESTDIR)$(DATADIR)/srfi/sets diff --git a/scheme/eval.sld b/scheme/eval.sld index 931cebe2..5ed800b4 100644 --- a/scheme/eval.sld +++ b/scheme/eval.sld @@ -23,7 +23,6 @@ setup-environment ; non-standard ;; Dynamic import %import - c:lib-loaded? ;; TODO: debug only! ) (begin From e7aa82a1562b113b9812dbf73fbe0e05f860acda Mon Sep 17 00:00:00 2001 From: Justin Ethier Date: Tue, 28 Mar 2017 12:45:26 +0000 Subject: [PATCH 19/37] Revert -O2 flags --- Makefile.config | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile.config b/Makefile.config index 1620b102..27145a36 100644 --- a/Makefile.config +++ b/Makefile.config @@ -5,9 +5,9 @@ # Configuration options for the makefile # Compiler options -CFLAGS ?= -g -fPIC -rdynamic -Wall -Iinclude -L. -LIB_CFLAGS ?= -g -rdynamic -Wall -Iinclude -L. -COMP_CFLAGS ?= -g -fPIC -rdynamic -Wall -I$(PREFIX)/include -L$(PREFIX)/lib +CFLAGS ?= -O2 -fPIC -rdynamic -Wall -Iinclude -L. +LIB_CFLAGS ?= -O2 -rdynamic -Wall -Iinclude -L. +COMP_CFLAGS ?= -O2 -fPIC -rdynamic -Wall -I$(PREFIX)/include -L$(PREFIX)/lib # Use these lines instead for debugging or profiling #CFLAGS = -g -Wall #CFLAGS = -g -pg -Wall From 36261118a93b38b2c821ce065db463020a756359 Mon Sep 17 00:00:00 2001 From: Justin Ethier Date: Tue, 28 Mar 2017 12:50:04 +0000 Subject: [PATCH 20/37] Document .so files --- docs/User-Manual.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/User-Manual.md b/docs/User-Manual.md index 19b3826a..a308f717 100644 --- a/docs/User-Manual.md +++ b/docs/User-Manual.md @@ -123,6 +123,7 @@ File Extension | Notes `.meta` | These text files contain the expanded version of any macros exported by a Scheme library, and allow other modules to easily use those macros during compilation. This file is not generated when compiling a program. `.c` | C code file generated by Cyclone. `.o` | Object file generated by the C compiler from the corresponding `.c` file. +`.so` | Shared Object files generated by the C compiler from the corresponding `.c` file. These are only generated for Scheme libraries and are used to allow loading a library at runtime. (None) | Final executable file generated by the C compiler when compiling a program. ## Interpreter From 78be3cd185f6a9f5bb15ef01bbaedaaff4b06508 Mon Sep 17 00:00:00 2001 From: Justin Ethier Date: Tue, 28 Mar 2017 13:41:31 +0000 Subject: [PATCH 21/37] Do not "leak" symbol --- runtime.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime.c b/runtime.c index b9798c92..70d8afb9 100644 --- a/runtime.c +++ b/runtime.c @@ -413,7 +413,7 @@ object register_library(const char *name) pthread_mutex_lock(&symbol_table_lock); // Only 1 "writer" allowed set_insert(&lib_table, psym); pthread_mutex_unlock(&symbol_table_lock); - return psym; + return boolean_t; } /* END Library table */ From 4c08f7099db262557d0846a8a54e0d612b02c0d8 Mon Sep 17 00:00:00 2001 From: Justin Ethier Date: Tue, 28 Mar 2017 21:44:59 +0000 Subject: [PATCH 22/37] Added TODO --- scheme/inexact.sld | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/scheme/inexact.sld b/scheme/inexact.sld index 200227e6..1fbf1717 100644 --- a/scheme/inexact.sld +++ b/scheme/inexact.sld @@ -68,7 +68,14 @@ (/ (c-log z1) (c-log z2*))))) (define-c c-log "(void *data, int argc, closure _, object k, object z)" - " return_inexact_double_op(data, k, log, z);") + " return_inexact_double_op(data, k, log, z);" +; TODO: experimenting with how an inline definition might look. +; need something that can both work within the same module and +; also when imported into another module. +; inline: +; "(void *data, object ptr, object z)" +; " return_inexact_double_op(data, k, log, z);" + ) (define-c sin "(void *data, int argc, closure _, object k, object z)" " return_inexact_double_op(data, k, sin, z);") From 0369788ab65dcdbef15306714196d90e07363286 Mon Sep 17 00:00:00 2001 From: Justin Ethier Date: Tue, 28 Mar 2017 21:46:39 +0000 Subject: [PATCH 23/37] Remove LIB_CFLAGS --- Makefile | 2 +- Makefile.config | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/Makefile b/Makefile index ebb18754..dd54d793 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ include Makefile.config # Commands CYCLONE = cyclone -A . -CCOMP = $(CC) $(LIB_CFLAGS) +CCOMP = $(CC) $(CFLAGS) INDENT_CMD = indent -linux -l80 -i2 -nut # Directories diff --git a/Makefile.config b/Makefile.config index 27145a36..32e01cc2 100644 --- a/Makefile.config +++ b/Makefile.config @@ -6,7 +6,6 @@ # Compiler options CFLAGS ?= -O2 -fPIC -rdynamic -Wall -Iinclude -L. -LIB_CFLAGS ?= -O2 -rdynamic -Wall -Iinclude -L. COMP_CFLAGS ?= -O2 -fPIC -rdynamic -Wall -I$(PREFIX)/include -L$(PREFIX)/lib # Use these lines instead for debugging or profiling #CFLAGS = -g -Wall From a019a29471d0d81a87fb1fb84e417b969fad7a7e Mon Sep 17 00:00:00 2001 From: Justin Ethier Date: Wed, 29 Mar 2017 00:37:13 +0000 Subject: [PATCH 24/37] Use RTLD_GLOBAL --- runtime.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime.c b/runtime.c index 70d8afb9..56690a9c 100644 --- a/runtime.c +++ b/runtime.c @@ -5633,7 +5633,7 @@ void Cyc_import_shared_object(void *data, object cont, object filename, object e function_type entry_pt; Cyc_check_str(data, filename); Cyc_check_str(data, entry_pt_fnc); - handle = dlopen(string_str(filename), RTLD_LAZY); + handle = dlopen(string_str(filename), RTLD_GLOBAL | RTLD_LAZY); if (handle == NULL) { //make_string(s, dlerror()); fprintf(stderr, "%s\n", dlerror()); From 6511490f21c165911949c1703a3969434264d31d Mon Sep 17 00:00:00 2001 From: Justin Ethier Date: Wed, 29 Mar 2017 01:20:52 +0000 Subject: [PATCH 25/37] Improve error reporting for dl functions --- runtime.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/runtime.c b/runtime.c index 56690a9c..b998c144 100644 --- a/runtime.c +++ b/runtime.c @@ -5629,23 +5629,24 @@ double MRG32k3a (double seed) /** Dynamic loading */ void Cyc_import_shared_object(void *data, object cont, object filename, object entry_pt_fnc) { + char buffer[256]; void *handle; function_type entry_pt; Cyc_check_str(data, filename); Cyc_check_str(data, entry_pt_fnc); handle = dlopen(string_str(filename), RTLD_GLOBAL | RTLD_LAZY); if (handle == NULL) { - //make_string(s, dlerror()); - fprintf(stderr, "%s\n", dlerror()); - Cyc_rt_raise2(data, "Unable to import library", filename); + snprintf(buffer, 256, "%s", dlerror()); + make_string(s, buffer); + Cyc_rt_raise2(data, "Unable to import library", &s); } dlerror(); /* Clear any existing error */ entry_pt = (function_type) dlsym(handle, string_str(entry_pt_fnc)); if (entry_pt == NULL) { - //make_string(s, dlerror()); - fprintf(stderr, "%s\n", dlerror()); - Cyc_rt_raise2(data, "Unable to load symbol", entry_pt_fnc); + snprintf(buffer, 256, "%s, %s, %s", string_str(filename), string_str(entry_pt_fnc), dlerror()); + make_string(s, buffer); + Cyc_rt_raise2(data, "Unable to load symbol", &s); } mclosure1(clo, entry_pt, cont); entry_pt(data, 0, &clo, &clo); From acbb33cf5b24abf477fada2b856758b99b03c031 Mon Sep 17 00:00:00 2001 From: Justin Ethier Date: Wed, 29 Mar 2017 01:21:05 +0000 Subject: [PATCH 26/37] Always output relative path to libs --- scheme/cyclone/libraries.sld | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scheme/cyclone/libraries.sld b/scheme/cyclone/libraries.sld index da183664..dddc77c4 100644 --- a/scheme/cyclone/libraries.sld +++ b/scheme/cyclone/libraries.sld @@ -256,7 +256,7 @@ (tagged-list? 'srfi import) (tagged-list? 'cyclone import)) (Cyc-installation-dir 'sld) - ""))) + "./"))) (call/cc (lambda (return) (for-each From 173109e072813a71ee32308a4d2e33d5accc6f32 Mon Sep 17 00:00:00 2001 From: Justin Ethier Date: Wed, 29 Mar 2017 18:02:50 -0400 Subject: [PATCH 27/37] WIP - bignums --- srfi/60.scm | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/srfi/60.scm b/srfi/60.scm index 17f459ca..1715be67 100644 --- a/srfi/60.scm +++ b/srfi/60.scm @@ -111,13 +111,19 @@ (define-c integer-length "(void* data, int argc, closure _, object k, object x)" "Cyc_check_int(data, x); - int input = (int)unbox_number(x); - int res = 0; - while (input) { - res++; - input >>= 1; - }; - return_closcall1(data, k, obj_int2obj(res));") + if (Cyc_is_bignum(x) == boolean_t) { + int res; + mp_radix_size(&bignum_value(x), 2, &res); + return_closcall1(data, k, obj_int2obj((res - 1))); + } else { + int input = (int)unbox_number(x); + int res = 0; + while (input) { + res++; + input >>= 1; + }; + return_closcall1(data, k, obj_int2obj(res)); + }") (define (log2-binary-factors n) (- (integer-length (raw-logand n (- n))) 1)) From 4e600a243a486f496e56d63c2afcab60972ba458 Mon Sep 17 00:00:00 2001 From: Justin Ethier Date: Wed, 29 Mar 2017 07:11:04 +0000 Subject: [PATCH 28/37] Expose bignum helper functions --- include/cyclone/runtime.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/cyclone/runtime.h b/include/cyclone/runtime.h index 706275ef..272ff922 100644 --- a/include/cyclone/runtime.h +++ b/include/cyclone/runtime.h @@ -349,6 +349,9 @@ object Cyc_num_op_va_list(void *data, int argc, object(fn_op(void *, common_type *, object)), int default_no_args, int default_one_arg, object n, va_list ns, common_type * buf); +void Cyc_int2bignum(int n, mp_int *bn); +object Cyc_bignum_normalize(void *data, object n); +int Cyc_bignum_cmp(bn_cmp_type type, object x, int tx, object y, int ty); double MRG32k3a (double seed); /**@}*/ /** From 6e9fcc6434a9283c00687fb68bc806c75e4f276e Mon Sep 17 00:00:00 2001 From: Justin Ethier Date: Wed, 29 Mar 2017 07:11:15 +0000 Subject: [PATCH 29/37] Beginning of bignum support --- srfi/60.scm | 105 ++++++++++++++++++++++++++++++++++------------------ 1 file changed, 70 insertions(+), 35 deletions(-) diff --git a/srfi/60.scm b/srfi/60.scm index 1715be67..934891c5 100644 --- a/srfi/60.scm +++ b/srfi/60.scm @@ -1,38 +1,73 @@ -#| - | Copyright (c) 1991, 1993, 2001, 2003, 2005 Aubrey Jaffer - | Copyright (c) 2017, Koz Ross - | - | All rights reserved. - | - | Redistribution and use in source and binary forms, with or without - | modification, are permitted provided that the following conditions are met: - | * Redistributions of source code must retain the above copyright - | notice, this list of conditions and the following disclaimer. - | * Redistributions in binary form must reproduce the above copyright - | notice, this list of conditions and the following disclaimer in the - | documentation and/or other materials provided with the distribution. - | * Neither the name of Cyclone nor the - | names of its contributors may be used to endorse or promote products - | derived from this software without specific prior written permission. - | - | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - | DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY - | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - |# +;;;; Cyclone Scheme +;;;; https://github.com/justinethier/cyclone +;;;; +;;;; Copyright (c) 1991, 1993, 2001, 2003, 2005 Aubrey Jaffer +;;;; Copyright (c) 2017, Koz Ross, Justin Ethier +;;;; +;;;; All rights reserved. +;;;; +;;;; Redistribution and use in source and binary forms, with or without +;;;; modification, are permitted provided that the following conditions are met: +;;;; * Redistributions of source code must retain the above copyright +;;;; notice, this list of conditions and the following disclaimer. +;;;; * Redistributions in binary form must reproduce the above copyright +;;;; notice, this list of conditions and the following disclaimer in the +;;;; documentation and/or other materials provided with the distribution. +;;;; * Neither the name of Cyclone nor the +;;;; names of its contributors may be used to endorse or promote products +;;;; derived from this software without specific prior written permission. +;;;; +;;;; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +;;;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +;;;; DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +;;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +;;;; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +;;;; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +;;;; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +;;;; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +;;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;;;; (define-c raw-logand "(void* data, int argc, closure _, object k, object x, object y)" "Cyc_check_int(data, x); - Cyc_check_int(data, y); - int result = ((int)unbox_number(x)) & ((int)unbox_number(y)); - return_closcall1(data, k, obj_int2obj(result));") + Cyc_check_int(data, y); + + if (obj_is_int(x) && obj_is_int(y)) { + int result = ((int)unbox_number(x)) & ((int)unbox_number(y)); + return_closcall1(data, k, obj_int2obj(result)); + } else { + int result; + alloc_bignum(data, bn); + mp_int *xx, *yy; + mp_int tmpx, tmpy; + + if (obj_is_int(x)) { + mp_init(&tmpx); + Cyc_int2bignum(obj_obj2int(x), &tmpx); + xx = &tmpx; + } else { + xx = &bignum_value(x); + } + + if (obj_is_int(y)) { + mp_init(&tmpy); + Cyc_int2bignum(obj_obj2int(y), &tmpy); + yy = &tmpy; + } else { + yy = &bignum_value(y); + } + + result = mp_and(xx, yy, &(bignum_value(bn))); + if (MP_OKAY != result) { + char buffer[128]; + snprintf(buffer, 127, \"Bignum error: %s\", mp_error_to_string(result)); + Cyc_rt_raise_msg(data, buffer); + } + return_closcall1(data, k, Cyc_bignum_normalize(data, bn)); + } + ") (define (logand x . rest) (if (null? rest) @@ -43,10 +78,10 @@ (define-c raw-logior "(void* data, int argc, closure _, object k, object x, object y)" - "Cyc_check_int(data, x); - Cyc_check_int(data, y); - int result = ((int)unbox_number(x)) | ((int)unbox_number(y)); - return_closcall1(data, k, obj_int2obj(result));") + "Cyc_check_fixnum(data, x); // TODO: bignum support + Cyc_check_fixnum(data, y); + int result = ((int)unbox_number(x)) | ((int)unbox_number(y)); + return_closcall1(data, k, obj_int2obj(result));") (define (logior x . rest) (if (null? rest) From f8bbff4ebb363b5c6c447f68d5ab2f2730e1ad2d Mon Sep 17 00:00:00 2001 From: Justin Ethier Date: Wed, 29 Mar 2017 07:34:30 +0000 Subject: [PATCH 30/37] Bignum AND, OR, XOR --- srfi/60.scm | 67 ++++++++++++++++++++++++++++++++++------------------- 1 file changed, 43 insertions(+), 24 deletions(-) diff --git a/srfi/60.scm b/srfi/60.scm index 934891c5..a946a865 100644 --- a/srfi/60.scm +++ b/srfi/60.scm @@ -29,15 +29,22 @@ ;;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ;;;; -(define-c raw-logand - "(void* data, int argc, closure _, object k, object x, object y)" +(define-syntax binop + (er-macro-transformer + (lambda (expr rename compare) + (let* ((fnc (cadr expr)) + (args + "(void* data, int argc, closure _, object k, object x, object y)") + (int-code (caddr expr)) + (bn-op-code (cadddr expr)) + (body + (string-append "Cyc_check_int(data, x); Cyc_check_int(data, y); - if (obj_is_int(x) && obj_is_int(y)) { - int result = ((int)unbox_number(x)) & ((int)unbox_number(y)); - return_closcall1(data, k, obj_int2obj(result)); - } else { + if (obj_is_int(x) && obj_is_int(y)) {" + int-code + "} else { int result; alloc_bignum(data, bn); mp_int *xx, *yy; @@ -59,7 +66,9 @@ yy = &bignum_value(y); } - result = mp_and(xx, yy, &(bignum_value(bn))); + " + bn-op-code + " if (MP_OKAY != result) { char buffer[128]; snprintf(buffer, 127, \"Bignum error: %s\", mp_error_to_string(result)); @@ -67,7 +76,26 @@ } return_closcall1(data, k, Cyc_bignum_normalize(data, bn)); } - ") + "))) + `(define-c ,fnc ,args ,body))))) + +(begin + (binop + raw-logand + " int result = ((int)unbox_number(x)) & ((int)unbox_number(y)); + return_closcall1(data, k, obj_int2obj(result)); " + " result = mp_and(xx, yy, &(bignum_value(bn))); ") + (binop + raw-logior + " int result = ((int)unbox_number(x)) | ((int)unbox_number(y)); + return_closcall1(data, k, obj_int2obj(result)); " + " result = mp_or(xx, yy, &(bignum_value(bn))); ") + (binop + raw-logxor + " int result = ((int)unbox_number(x)) ^ ((int)unbox_number(y)); + return_closcall1(data, k, obj_int2obj(result)); " + " result = mp_xor(xx, yy, &(bignum_value(bn))); ") + ) (define (logand x . rest) (if (null? rest) @@ -76,13 +104,6 @@ (define bitwise-and logand) -(define-c raw-logior - "(void* data, int argc, closure _, object k, object x, object y)" - "Cyc_check_fixnum(data, x); // TODO: bignum support - Cyc_check_fixnum(data, y); - int result = ((int)unbox_number(x)) | ((int)unbox_number(y)); - return_closcall1(data, k, obj_int2obj(result));") - (define (logior x . rest) (if (null? rest) x @@ -90,13 +111,6 @@ (define bitwise-ior logior) -(define-c raw-logxor - "(void* data, int argc, closure _, object k, object x, object y)" - "Cyc_check_int(data, x); - Cyc_check_int(data, y); - int result = ((int)unbox_number(x)) ^ ((int)unbox_number(y)); - return_closcall1(data, k, obj_int2obj(result));") - (define (logxor x . rest) (if (null? rest) x @@ -107,8 +121,13 @@ (define-c lognot "(void* data, int argc, closure _, object k, object x)" "Cyc_check_int(data, x); - int result = ~((int)unbox_number(x)); - return_closcall1(data, k, obj_int2obj(result));") + if (Cyc_is_bignum(x) == boolean_t) { + // uh oh, libtommath doesn't provide this! + Cyc_rt_raise_msg(data, \"bignum negation not supported yet\"); + } else { + int result = ~((int)unbox_number(x)); + return_closcall1(data, k, obj_int2obj(result)); + }") (define bitwise-not lognot) From ffb9fd9e22ad68d3409a47c69882079421eeb355 Mon Sep 17 00:00:00 2001 From: Justin Ethier Date: Thu, 30 Mar 2017 17:58:39 -0400 Subject: [PATCH 31/37] Cleanup --- srfi/60.scm | 45 +++++++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/srfi/60.scm b/srfi/60.scm index a946a865..03fb2b48 100644 --- a/srfi/60.scm +++ b/srfi/60.scm @@ -134,12 +134,12 @@ (define-c bitwise-if "(void* data, int argc, closure _, object k, object mask, object n0, object n1)" - "Cyc_check_int(data, mask); - Cyc_check_int(data, n0); - Cyc_check_int(data, n1); - int m = unbox_number(mask); - int result = (m & ((int)unbox_number(n0))) | ((~m) & ((int)unbox_number(n1))); - return_closcall1(data, k, obj_int2obj(result));") + "Cyc_check_fixnum(data, mask); // TODO: bignum support + Cyc_check_fixnum(data, n0); + Cyc_check_fixnum(data, n1); + int m = unbox_number(mask); + int result = (m & ((int)unbox_number(n0))) | ((~m) & ((int)unbox_number(n1))); + return_closcall1(data, k, obj_int2obj(result));") (define bitwise-merge bitwise-if) @@ -206,20 +206,25 @@ (define-c ash "(void* data, int argc, closure _, object k, object x, object y)" "Cyc_check_int(data, x); - Cyc_check_int(data,y); - int bf = (int)unbox_number(x); - int shift = (int)unbox_number(y); - int i; - if (shift > 0) { - for (i = 0; i < shift; i++) { - bf *= 2; - } - } else { - for (i = 0; i < abs(shift); i++) { - bf /= 2; - } - } - return_closcall1(data, k, obj_int2obj(bf))") + Cyc_check_int(data,y); + int bf = (int)unbox_number(x); + int shift = (int)unbox_number(y); + //int i; + if (shift > 0) { + bf <<= shift; + } else { + bf >>= abs(shift); + } +// if (shift > 0) { +// for (i = 0; i < shift; i++) { +// bf *= 2; +// } +// } else { +// for (i = 0; i < abs(shift); i++) { +// bf /= 2; +// } +// } + return_closcall1(data, k, obj_int2obj(bf))") (define arithmetic-shift ash) From c0a5daf898dc55d179a56cd718f52b7220e56ede Mon Sep 17 00:00:00 2001 From: Justin Ethier Date: Thu, 30 Mar 2017 19:03:46 -0400 Subject: [PATCH 32/37] WIP --- srfi/60.scm | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/srfi/60.scm b/srfi/60.scm index 03fb2b48..7a4256ff 100644 --- a/srfi/60.scm +++ b/srfi/60.scm @@ -226,6 +226,28 @@ // } return_closcall1(data, k, obj_int2obj(bf))") +;; (define-c ash +;; "(void* data, int argc, closure _, object k, object x, object y)" +;; "Cyc_check_int(data, x); +;; Cyc_check_fixnum(data,y); +;; int shift; +;; //int result; +;; alloc_bignum(data, bn); +;; +;; if (obj_is_int(x)) { +;; Cyc_int2bignum(obj_obj2int(x), &bignum_value(bn)); +;; } else { +;; mp_copy(&bignum_value(x), &bignum_value(bn)); +;; } +;; +;; shift = (int)unbox_number(y); +;; if (shift > 0) { +;; mp_lshd(&bignum_value(bn), shift); +;; } else { +;; mp_rshd(&bignum_value(bn), abs(shift)); +;; } +;; return_closcall1(data, k, Cyc_bignum_normalize(data, bn));") + (define arithmetic-shift ash) (define (rotate-bit-field n count start end) From afa12cec5fc5ef5bf0ac19330b0e8b6576ea2d4c Mon Sep 17 00:00:00 2001 From: Justin Ethier Date: Sat, 1 Apr 2017 00:14:02 -0400 Subject: [PATCH 33/37] Bignum-compatible version of ash --- srfi/60.scm | 93 ++++++++++++++++++++++++++++------------------------- 1 file changed, 50 insertions(+), 43 deletions(-) diff --git a/srfi/60.scm b/srfi/60.scm index 7a4256ff..fc9d31b1 100644 --- a/srfi/60.scm +++ b/srfi/60.scm @@ -203,50 +203,57 @@ (ash from start) to)) -(define-c ash - "(void* data, int argc, closure _, object k, object x, object y)" - "Cyc_check_int(data, x); - Cyc_check_int(data,y); - int bf = (int)unbox_number(x); - int shift = (int)unbox_number(y); - //int i; - if (shift > 0) { - bf <<= shift; - } else { - bf >>= abs(shift); - } -// if (shift > 0) { -// for (i = 0; i < shift; i++) { -// bf *= 2; -// } -// } else { -// for (i = 0; i < abs(shift); i++) { -// bf /= 2; -// } -// } - return_closcall1(data, k, obj_int2obj(bf))") +;(define-c ash +; "(void* data, int argc, closure _, object k, object x, object y)" +; "Cyc_check_int(data, x); +; Cyc_check_int(data,y); +; int bf = (int)unbox_number(x); +; int shift = (int)unbox_number(y); +; //int i; +; if (shift > 0) { +; bf <<= shift; +; } else { +; bf >>= abs(shift); +; } +;// if (shift > 0) { +;// for (i = 0; i < shift; i++) { +;// bf *= 2; +;// } +;// } else { +;// for (i = 0; i < abs(shift); i++) { +;// bf /= 2; +;// } +;// } +; return_closcall1(data, k, obj_int2obj(bf))") -;; (define-c ash -;; "(void* data, int argc, closure _, object k, object x, object y)" -;; "Cyc_check_int(data, x); -;; Cyc_check_fixnum(data,y); -;; int shift; -;; //int result; -;; alloc_bignum(data, bn); -;; -;; if (obj_is_int(x)) { -;; Cyc_int2bignum(obj_obj2int(x), &bignum_value(bn)); -;; } else { -;; mp_copy(&bignum_value(x), &bignum_value(bn)); -;; } -;; -;; shift = (int)unbox_number(y); -;; if (shift > 0) { -;; mp_lshd(&bignum_value(bn), shift); -;; } else { -;; mp_rshd(&bignum_value(bn), abs(shift)); -;; } -;; return_closcall1(data, k, Cyc_bignum_normalize(data, bn));") + (define-c ash + "(void* data, int argc, closure _, object k, object x, object y)" + "Cyc_check_int(data, x); + Cyc_check_fixnum(data,y); + int shift, i; + //int result; + alloc_bignum(data, bn); + + if (Cyc_is_bignum(x) == boolean_t){ + mp_copy(&bignum_value(x), &bignum_value(bn)); + } else { + Cyc_int2bignum((int)unbox_number(x), &bignum_value(bn)); + } + +// Inefficient but always works without overflow +// Should be able to do pure fixnum math in some cases, though + shift = (int)unbox_number(y); + if (shift > 0) { + for (i = 0; i < shift; i++) { + mp_mul_2(&bignum_value(bn), &bignum_value(bn)); + } + } else { + for (i = 0; i < abs(shift); i++) { + mp_div_2(&bignum_value(bn), &bignum_value(bn)); + } + } + + return_closcall1(data, k, Cyc_bignum_normalize(data, bn));") (define arithmetic-shift ash) From 37a1d65980c035c18d67269cac849c77d1ce0042 Mon Sep 17 00:00:00 2001 From: Justin Ethier Date: Sat, 1 Apr 2017 00:17:58 -0400 Subject: [PATCH 34/37] WIP --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 69192409..eba9f935 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ Features +IN PROGRESS - bignum support for SRFI 60 + - Cyclone now has support in the interpreter for loading libraries via `import`. This is probably the most important change in this release and allows `icyc` to be used to its full potential. - Store parameter objects in such a way that changes to a parameter object do not affect other threads that use the same parameter object. From 9162e3691399a1942259f1c7322469cf285d4cc4 Mon Sep 17 00:00:00 2001 From: Justin Ethier Date: Sat, 1 Apr 2017 01:02:41 -0400 Subject: [PATCH 35/37] Bignum NOT operation --- srfi/60.scm | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/srfi/60.scm b/srfi/60.scm index fc9d31b1..33533f96 100644 --- a/srfi/60.scm +++ b/srfi/60.scm @@ -121,13 +121,21 @@ (define-c lognot "(void* data, int argc, closure _, object k, object x)" "Cyc_check_int(data, x); + alloc_bignum(data, bn); if (Cyc_is_bignum(x) == boolean_t) { - // uh oh, libtommath doesn't provide this! - Cyc_rt_raise_msg(data, \"bignum negation not supported yet\"); + mp_copy(&bignum_value(x), &bignum_value(bn)); } else { - int result = ~((int)unbox_number(x)); - return_closcall1(data, k, obj_int2obj(result)); - }") + Cyc_int2bignum((int)unbox_number(x), &bignum_value(bn)); + } + + // From https://github.com/libtom/libtommath/issues/30 + /* A one's complement, aka bitwise NOT, is actually just -a - 1 */ + //CHECK_ERROR(mp_neg(&op->mp, &out->mp)); + //CHECK_ERROR(mp_sub_d(&out->mp, 1, &out->mp)); + mp_neg(&bignum_value(bn), &bignum_value(bn)); + mp_sub_d(&bignum_value(bn), 1, &bignum_value(bn)); + return_closcall1(data, k, Cyc_bignum_normalize(data, bn)); + ") (define bitwise-not lognot) From 7c287a97a24d0944e391893b1a711fae6ba3c42b Mon Sep 17 00:00:00 2001 From: Justin Ethier Date: Sat, 1 Apr 2017 01:05:19 -0400 Subject: [PATCH 36/37] Fixes for SRFI 60 --- CHANGELOG.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index eba9f935..db110147 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,8 +4,6 @@ Features -IN PROGRESS - bignum support for SRFI 60 - - Cyclone now has support in the interpreter for loading libraries via `import`. This is probably the most important change in this release and allows `icyc` to be used to its full potential. - Store parameter objects in such a way that changes to a parameter object do not affect other threads that use the same parameter object. @@ -13,6 +11,7 @@ IN PROGRESS - bignum support for SRFI 60 > `parameterize` must not change the associated values of any parameters in any thread other than the current thread and threads created inside the `parameterize` body. +- Added bignum support to SRFI 60 - integers as bits. - Normalize the result of `string->number` such that bignums are only returned if the result truly is a bignum. - Allow Cyclone to find `(cyclone)` prefixed libraries installed in Cyclone's system folder. - Allow a library to export identifiers that are exported by another library. Previously a library could only export identifiers that it defined directly. From 074dee78861d3a032ede29f0168bc14df6914884 Mon Sep 17 00:00:00 2001 From: Justin Ethier Date: Mon, 3 Apr 2017 13:37:27 +0000 Subject: [PATCH 37/37] Exploring how define-c could inline functions --- include/cyclone/runtime.h | 15 +++++++++++++++ scheme/inexact.sld | 8 +++++--- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/include/cyclone/runtime.h b/include/cyclone/runtime.h index 272ff922..8a497b64 100644 --- a/include/cyclone/runtime.h +++ b/include/cyclone/runtime.h @@ -275,6 +275,21 @@ object Cyc_io_read_line(void *data, object cont, object port); */ /**@{*/ +#define unboxed_inexact_double_op(data, ptr, OP, z) \ + double unboxed; \ + Cyc_check_num(data, z); \ + if (obj_is_int(z)) { \ + unboxed = OP(obj_obj2int(z)); \ + } else if (type_of(z) == integer_tag) { \ + unboxed = OP(((integer_type *)z)->value); \ + } else if (type_of(z) == bignum_tag) { \ + unboxed = OP(mp_get_double(&bignum_value(z))); \ + } else { \ + unboxed = OP(((double_type *)z)->value); \ + } \ + assign_double(ptr, unboxed); \ + return ptr; + #define return_inexact_double_op(data, cont, OP, z) \ make_double(d, 0.0); \ Cyc_check_num(data, z); \ diff --git a/scheme/inexact.sld b/scheme/inexact.sld index 1fbf1717..f31055ad 100644 --- a/scheme/inexact.sld +++ b/scheme/inexact.sld @@ -72,9 +72,11 @@ ; TODO: experimenting with how an inline definition might look. ; need something that can both work within the same module and ; also when imported into another module. -; inline: -; "(void *data, object ptr, object z)" -; " return_inexact_double_op(data, k, log, z);" + ;; Inline arguments: + "(void *data, object ptr, object z)" + ;; must always return an object + ;; Inline body: + " unboxed_inexact_double_op(data, ptr, log, z);" ) (define-c sin "(void *data, int argc, closure _, object k, object z)"