~ chicken-core (chicken-5) 01f77922a1cb2a81e07c82c6b3a5744cc085fcc2


commit 01f77922a1cb2a81e07c82c6b3a5744cc085fcc2
Author:     felix <felix@call-with-current-continuation.org>
AuthorDate: Sat Mar 19 17:50:38 2011 +0100
Commit:     felix <felix@call-with-current-continuation.org>
CommitDate: Sat Mar 19 17:50:38 2011 +0100

    functors

diff --git a/chicken-syntax.scm b/chicken-syntax.scm
index 2db03701..8b1034fe 100644
--- a/chicken-syntax.scm
+++ b/chicken-syntax.scm
@@ -1117,20 +1117,52 @@
  (##sys#er-transformer
   (lambda (x r c)
     (##sys#check-syntax 'define-interface x '(_ symbol _))
-    (let ((name (##sys#strip-syntax (cadr x))))
+    (let ((name (##sys#strip-syntax (cadr x)))
+	  (%quote (r 'quote)))
       `(,(r 'begin-for-syntax)
 	(##sys#register-interface
-	 ',name
-	 ',(let ((exps (##sys#strip-syntax (caddr x))))
-	     (cond ((eq? '* exps) '*)
-		   ((symbol? exps) `(#:interface ,exps))
-		   ((list? exps) (##sys#validate-exports exps 'define-interface))
-		   (else (##sys#syntax-error-hook
-			  'define-interface "invalid exports" (caddr x)))))))))))
+	 (,%quote ,name)
+	 (,%quote ,(let ((exps (##sys#strip-syntax (caddr x))))
+		     (cond ((eq? '* exps) '*)
+			   ((symbol? exps) `(#:interface ,exps))
+			   ((list? exps) (##sys#validate-exports exps 'define-interface))
+			   (else (##sys#syntax-error-hook
+				  'define-interface "invalid exports" (caddr x))))))))))))
 
 
+;;; functor definition
+
+(##sys#extend-macro-environment
+ 'functor '()
+ (##sys#er-transformer
+  (lambda (x r c)
+    (##sys#check-syntax 'functor x '(_ (symbol . #((symbol _) 0)) . _))
+    (let* ((x (##sys#strip-syntax x))
+	   (head (cadr x))
+	   (name (car head))
+	   (body (cddr x))
+	   (%quote (r 'quote))
+	   (registration
+	    `(##sys#register-functor
+	      ',name
+	      ',(map (lambda (arg)
+		       (let ((argname (car arg))
+			     (exps (##sys#validate-exports (cadr arg) 'functor)))
+			 (cons argname exps)))
+		     (cdr head))
+	      ',body)))
+      `(##core#module
+	,name
+	#t
+	(import scheme chicken)
+	(begin-for-syntax ,registration))))))
+
+
+;; capture current macro env
+
 (##sys#macro-subset me0 ##sys#default-macro-environment)))
 
+
 ;; register features
 
 (eval-when (compile load eval)
diff --git a/compiler.scm b/compiler.scm
index 5ddc5608..33e317d2 100644
--- a/compiler.scm
+++ b/compiler.scm
@@ -602,10 +602,11 @@
 			    (let loop ([ids (##sys#strip-syntax (cadr x))])
 			      (if (null? ids)
 				  '(##core#undefined)
-				  (let ([id (car ids)])
+				  (let ((id (##sys#resolve-module-name (car ids) #f)))
 				    (let-values ([(exp f)
 						  (##sys#do-the-right-thing
-						   id #t imp?)])
+						   (##sys#resolve-module-name id #f)
+						   #t imp?)])
 				      (unless (or f 
 						  (and (symbol? id)
 						       (or (feature? id)
@@ -808,13 +809,13 @@
 			 e se dest ldest h))
 
 		       ((##core#let-module-alias)
-			(fluid-let ((##sys#module-alias-environment
-				     (cons 
-				      (##sys#strip-syntax 
-				       (map (lambda (b) (cons (car b) (cadr b)))
-					    (cadr x)))
-				      ##sys#module-alias-environment)))
-			  (walk `(##core#begin ,@(cddr x)) e se dest ldest h)))
+			(##sys#with-module-aliases
+			 (map (lambda (b)
+				(##sys#check-syntax 'functor b '(symbol symbol))
+				(##sys#strip-syntax b))
+			      (cadr x))
+			 (lambda ()
+			   (walk `(##core#begin ,@(cddr x)) e se dest ldest h))))
 
 		       ((##core#module)
 			(let* ((x (##sys#strip-syntax x))
@@ -857,7 +858,7 @@
 						       (lambda (il)
 							 (when enable-module-registration
 							   (emit-import-lib name il))
-							 (values 
+							 (values
 							  (reverse xs)
 							  '((##core#undefined)))))
 						      ((not enable-module-registration)
@@ -869,7 +870,8 @@
 							(reverse xs)
 							(if standalone-executable
 							    '()
-							    (##sys#compiled-module-registration (##sys#current-module)))))))
+							    (##sys#compiled-module-registration 
+							     (##sys#current-module)))))))
 					       (else
 						(loop 
 						 (cdr body)
@@ -1162,7 +1164,9 @@
 						   (list 
 						    var
 						    (foreign-type-convert-result
-						     (finish-foreign-result (final-foreign-type type) var)
+						     (finish-foreign-result
+						      (final-foreign-type type) 
+						      var)
 						     type) )
 						   (loop (cdr vars) (cdr types)) ) ) ) )
 					 ,(foreign-type-convert-argument
diff --git a/eval.scm b/eval.scm
index d482c12e..f93fe3c1 100644
--- a/eval.scm
+++ b/eval.scm
@@ -615,13 +615,13 @@
 			   e #f tf cntr se))
 
 			 ((##core#let-module-alias)
-			  (fluid-let ((##sys#module-alias-environment
-				       (cons 
-					(##sys#strip-syntax 
-					 (map (lambda (b) (cons (car b) (cadr b)))
-					      (cadr x)))
-					##sys#module-alias-environment)))
-			    (walk `(##core#begin ,@(cddr x)) e #f tf cntr se)))
+			  (##sys#with-module-aliases
+			   (map (lambda (b)
+				  (##sys#check-syntax 'functor b '(symbol symbol))
+				  (##sys#strip-syntax b))
+				(cadr x))
+			   (lambda ()
+			     (compile `(##core#begin ,@(cddr x)) e #f tf cntr se))))
 
 			 ((##core#module)
 			  (let* ((x (##sys#strip-syntax x))
@@ -692,7 +692,8 @@
 				   '(##core#undefined)
 				   (let-values ([(exp _) 
 						 (##sys#do-the-right-thing
-						  (car ids) #f imp?)])
+						  (##sys#resolve-module-name (car ids) #f)
+						  #f imp?)])
 				     `(##core#begin ,exp ,(loop (cdr ids))) ) ) )
 			     e #f tf cntr se) ) ]
 
diff --git a/expand.scm b/expand.scm
index e6fc4769..69a38a03 100644
--- a/expand.scm
+++ b/expand.scm
@@ -1312,21 +1312,38 @@
  '()
  (##sys#er-transformer
   (lambda (x r c)
-    ;;XXX module alias + functor application
-    (##sys#check-syntax 'module x '(_ symbol _ . #(_ 0)))
-    ;;XXX use module name in "loc" argument?
-    (let ((exports (##sys#validate-exports (##sys#strip-syntax (caddr x)) 'module)))
-      `(##core#module 
-	,(cadr x)
-	,(if (eq? '* exports)
-	     #t 
-	     (caddr x))
-	,@(let ((body (cdddr x)))
-	    (if (and (pair? body) 
-		     (null? (cdr body))
-		     (string? (car body)))
-		`((##core#include ,(car body)))
-		body)))))))
+    (let ((len (length x)))
+      (cond ((and (fx>= len 2) (pair? (cadr x)))
+	     (##sys#check-syntax 'module x '(_ (symbol (symbol . #(_ 1))) . #(_ 0 1)))
+	     (let* ((x (##sys#strip-syntax x))
+		    (head (cadr x)))
+	       (##sys#instantiate-functor
+		(car head)
+		(caadr head)
+		(cdadr head)
+		(if (null? (cddr x))
+		    '*
+		    (##sys#validate-exports (caddr x) (car head))))))
+	    ((and (fx= len 3) (symbol? (cadr x)))
+	     (##sys#check-syntax 'module x '(_ symbol symbol))
+	     (let ((x (##sys#strip-syntax x)))
+	       (##sys#register-module-alias (cadr x) (caddr x))
+	       '(##core#undefined)))
+	    (else
+	     (##sys#check-syntax 'module x '(_ symbol _ . #(_ 0)))
+	     ;;XXX use module name in "loc" argument?
+	     (let ((exports (##sys#validate-exports (##sys#strip-syntax (caddr x)) 'module)))
+	       `(##core#module 
+		 ,(cadr x)
+		 ,(if (eq? '* exports)
+		      #t 
+		      exports)
+		 ,@(let ((body (cdddr x)))
+		     (if (and (pair? body) 
+			      (null? (cdr body))
+			      (string? (car body)))
+			 `((##core#include ,(car body)))
+			 body))))))))))
 
 (##sys#extend-macro-environment
  'begin-for-syntax
@@ -1394,6 +1411,8 @@
 (define ##sys#default-macro-environment
   (##sys#fixup-macro-environment (##sys#macro-environment)))
 
+(define ##sys#meta-macro-environment (make-parameter (##sys#macro-environment)))
+
 
 ;; Used by the syntax-rules implementation (and possibly handy elsewhere)
 ;; (kindly contributed by Peter Bex)
@@ -1416,4 +1435,3 @@
      ((> len temp)
       (loop (- len 1) (cdr input)))
      (else input))))
-
diff --git a/modules.scm b/modules.scm
index d9fe5bde..c337a895 100644
--- a/modules.scm
+++ b/modules.scm
@@ -55,7 +55,6 @@
 
 ;;; low-level module support
 
-(define ##sys#meta-macro-environment (make-parameter (##sys#macro-environment)))
 (define ##sys#current-module (make-parameter #f))
 (define ##sys#module-alias-environment '())
 
@@ -99,6 +98,17 @@
 (define (make-module name explist vexports sexports)
   (%make-module name explist '() '() '() '() '() '() '() vexports sexports))
 
+(define (##sys#register-module-alias alias name)
+  (set! ##sys#module-alias-environment
+    (cons (cons alias name) ##sys#module-alias-environment)))
+
+(define (##sys#with-module-aliases bindings thunk)
+  (fluid-let ((##sys#module-alias-environment
+	       (append
+		(map (lambda (b) (cons (car b) (cadr b))) bindings)
+		##sys#module-alias-environment)))
+    (thunk)))
+
 (define (##sys#resolve-module-name name loc)
   (let loop ((n name) (done '()))
     (cond ((assq n ##sys#module-alias-environment) =>
@@ -715,3 +725,47 @@
 				      (err "invalid interface specification" x exps)))
 			       (err "invalid interface specification" x exps)))
 			  (else (err "invalid export" x exps))))))))))
+
+(define (##sys#register-functor name fargs body)
+  (putp name '##core#functor (cons fargs body)))
+
+(define (##sys#instantiate-functor name fname args exports)
+  (let ((funcdef (getp fname '##core#functor)))
+    (define (err . args)
+      (apply ##sys#syntax-error-hook name args))
+    (unless funcdef (err "instantation of undefined functor" fname))
+    (let ((fargs (car funcdef))
+	  (body (cdr funcdef)))
+      (define (merr)
+	(err "argument list mismatch in functor instantiation" 
+	     (cons name args) (cons fname (map car fargs))))
+      `(##core#let-module-alias
+	,(let loop ((as args) (fas fargs))
+	   (cond ((null? as) (if (null? fas) '() (merr)))
+		 ((null? fas) (merr))
+		 (else
+		  (let* ((p (car fas))
+			 (alias (car p))
+			 (mname (car as))
+			 (exps (cdr p)))
+		    (##sys#match-functor-argument alias mname exps name)
+		    (cons (list alias mname) (loop (cdr as) (cdr fas)))))))
+	(##core#module
+	 ,name
+	 ,(if (eq? '* exports) #t exports)
+	 ,@body)))))
+
+(define (##sys#match-functor-argument alias mname exps loc)
+  (let ((mod (##sys#find-module (##sys#resolve-module-name mname loc) #t loc)))
+    (unless (eq? exps '*)
+      (let ((missing '()))
+	(for-each
+	 (lambda (exp)
+	   (let ((sym (if (symbol? exp) exp (car exp))))
+	     (unless (##sys#find-export sym mod #f)
+	       (set! missing (cons sym missing)))))
+	 exps)
+	(when (pair? missing)
+	  (##sys#syntax-error-hook
+	   loc "argument module does not match required signature"
+	   mname alias))))))
Trap