[Chicken-hackers] [PATCH] Add 'a shorthand for forall types

2018-05-29 Thread megane
Hello,

This adds support for declaring forall types in more compact manner.

It supports syntax like ('a -> 'a) to declare the type
(forall (a) (a -> a)).

diff --git a/manual/Types b/manual/Types
index 6d5de10..cab029d 100644
--- a/manual/Types
+++ b/manual/Types
@@ -158,6 +158,12 @@ or {{:}} should follow the syntax given below:
 
 (*) Note: no type-variables are bound inside {{(not TYPE)}}.
 
+You can use a shorthand {{'SYMBOL}} for introducing free variables in
+{{forall}} types, examples:
+
+  ('a -> 'a) is translated to (forall (a) (a -> a))
+  (forall (a) ('a -> a)) is translated to (forall (a) (a -> a))
+
 Note that type-variables in {{forall}} types may be given "constraint" types, i.e.
 
   (: sort (forall (e (s (or (vector-of e) (list-of e
diff --git a/scrutinizer.scm b/scrutinizer.scm
index ece07ed..6d4a0c8 100644
--- a/scrutinizer.scm
+++ b/scrutinizer.scm
@@ -1967,6 +1967,16 @@
 (second t))
 			   constraints))
 		 (validate (third t) rec)
+	((and (eq? 'quote (car t))
+		  (pair? (cdr t))
+		  (symbol? (second t))
+		  (null? (cddr t))
+		  (second t))
+	 =>
+	 (lambda (v)
+	   (unless (memq v typevars)
+		 (set! typevars (cons v typevars)))
+	   v))
 	((eq? 'or (car t)) 
 	 (and (list? t)
 		  (let ((ts (map validate (cdr t
diff --git a/tests/typematch-tests.scm b/tests/typematch-tests.scm
index 44c6c32..8a01094 100644
--- a/tests/typematch-tests.scm
+++ b/tests/typematch-tests.scm
@@ -3,6 +3,7 @@
 
 (import chicken.blob chicken.condition chicken.memory chicken.locative)
 
+(define something)
 
 (define (make-list n x)
   (list-tabulate n (lambda _ x)))
@@ -394,3 +395,22 @@
  (compiler-typecase #x7fff
(fixnum #f)
(bignum #t)))
+
+(assert
+ (compiler-typecase 1
+   ('a #t)))
+
+(assert
+ (compiler-typecase (the (list fixnum string string) something)
+   ((list 'a 'a 'b) #f)
+   ((list 'a 'b 'b) #t)))
+
+(assert
+ (compiler-typecase (the (list fixnum string string) something)
+   ((forall (a) (list a 'a 'b)) #f)
+   ((forall (b) (list 'a 'b b)) #t)))
+
+(assert
+ (compiler-typecase (the (list string (list string fixnum)) something)
+   ((list 'a (forall (a) (list 'b a))) #f)
+   ((list 'b (forall (b) (list b 'a))) #t)))
___
Chicken-hackers mailing list
Chicken-hackers@nongnu.org
https://lists.nongnu.org/mailman/listinfo/chicken-hackers


Re: [Chicken-hackers] Make the test suite work when PROGRAM_PREFIX and PROGRAM_SUFFIX are defined

2018-05-29 Thread Evan Hanson


On 2018-05-02 16:29, Kooda wrote:
> New patch, all is in the title. This fixes ticket #1458.

Applied!

I did make one small change, adding programs-path.scm to the manifest.

I'll close #1458 now. Thanks Kooda!

Evan

___
Chicken-hackers mailing list
Chicken-hackers@nongnu.org
https://lists.nongnu.org/mailman/listinfo/chicken-hackers


[Chicken-hackers] [PATCH] Remove some type expansion related code duplication in scrutinizer

2018-05-29 Thread megane
Hi,

There were cases in match-types which essentially duplicated what
expand-type was doing. This is a simple refactoring to remove that
duplication.

diff --git a/scrutinizer.scm b/scrutinizer.scm
index ece07ed..c89bd60 100644
--- a/scrutinizer.scm
+++ b/scrutinizer.scm
@@ -138,6 +138,15 @@
 s64vector f32vector f64vector thread queue environment time
 continuation lock mmap condition hash-table tcp-listener))
 
+(define-constant type-expansions
+  '((pair . (pair * *))
+(list . (list-of *))
+(vector . (vector-of *))
+(boolean . (or true false))
+(integer . (or fixnum bignum))
+(number . (or fixnum float bignum ratnum cplxnum))
+(procedure . (procedure (#!rest *) . *
+
 (define-inline (struct-type? t)
   (and (pair? t) (eq? (car t) 'struct)))
 
@@ -1042,18 +1051,8 @@
 	  ((eq? t2 'undefined) #f)
 	  ((eq? t1 'noreturn))
 	  ((eq? t2 'noreturn))
-	  ((eq? t1 'boolean) (match1 '(or true false) t2))
-	  ((eq? t2 'boolean) (match1 t1 '(or true false)))
-	  ((eq? t1 'integer) (match1 '(or fixnum bignum) t2))
-	  ((eq? t2 'integer) (match1 t1 '(or fixnum bignum)))
-	  ((eq? t1 'number) (match1 '(or fixnum float bignum ratnum cplxnum) t2))
-	  ((eq? t2 'number) (match1 t1 '(or fixnum float bignum ratnum cplxnum)))
-	  ((eq? t1 'pair) (match1 '(pair * *) t2))
-	  ((eq? t2 'pair) (match1 t1 '(pair * *)))
-	  ((eq? t1 'list) (match1 '(list-of *) t2))
-	  ((eq? t2 'list) (match1 t1 '(list-of *)))
-	  ((eq? t1 'vector) (match1 '(vector-of *) t2))
-	  ((eq? t2 'vector) (match1 t1 '(vector-of *)))
+	  ((maybe-expand-type t1) => (cut match1 <> t2))
+	  ((maybe-expand-type t2) => (cut match1 t1 <>))
 	  ((and (pair? t1) (eq? 'not (car t1)))
 	   (fluid-let ((all (not all)))
 	 (let* ((trail0 trail)
@@ -1356,17 +1355,9 @@
   (dd "simplify: ~a -> ~a" t t2)
   t2)))
 
-(define (expand-type t)
-  (case t
-((pair) '(pair * *))
-((list) '(list-of *))
-((vector) '(vector-of *))
-((boolean) '(or true false))
-((integer) '(or fixnum bignum))
-((number) '(or fixnum float bignum ratnum cplxnum))
-((procedure) '(procedure (#!rest *) . *))
-(else t)))
-
+(define (maybe-expand-type t)
+  (and (symbol? t)
+   (alist-ref t type-expansions eq?)))
 
 ;;; Merging types
 
@@ -1432,10 +1423,8 @@
   (define (refine t1 t2 te)
 (let loop ((t1 t1) (t2 t2))
   (cond
-	((and (symbol? t1) (memq t1 '(pair list vector boolean integer number)))
-	 (loop (expand-type t1) t2))
-	((and (symbol? t2) (memq t2 '(pair list vector boolean integer number)))
-	 (loop t1 (expand-type t2)))
+   ((maybe-expand-type t1) => (cut loop <> t2))
+   ((maybe-expand-type t2) => (cut loop t1 <>))
 	((and (pair? t1) (memq (car t1) '(forall refine)))
 	 (let ((t1* (loop (third t1) t2)))
 	   (and t1* (list (car t1) (second t1) t1*
___
Chicken-hackers mailing list
Chicken-hackers@nongnu.org
https://lists.nongnu.org/mailman/listinfo/chicken-hackers


[Chicken-hackers] [PATCH] Rework library loading to support conditional unit entry

2018-05-29 Thread Evan Hanson
Hello fellow hackers,

Here is a big, gnarly patch that finishes the work I started in Bergen,
which was to change the way we handle library dependencies so that units
can be loaded conditionally. This was inspired by Peter's changes to
make import expressions lexically-scoped, so that you can write a
program like the following and have it work like you'd expect:

  (if (some-condition)
  (let () (import (foo)) ...)
  (let () (import (bar)) ...))

With Peter's changes, those imports will only affect the syntactic
environments of their respective branches. However, when the libraries
"foo" and "bar" are compiled in (for example when "-static" is used),
they'll both be loaded unconditionally. This patch changes things so
that those libraries will only be loaded when program execution reaches
the corresponding import expression.

I'm sorry about the size of the diff, but I needed to rework quite a bit
of bookkeeping for this to work. I also took the opportunity to clean up
some related bits of code and rip out some provisional things that were
left over from my last round of library loading changes. The commit
message is exhaustive, and probably exhausting too.

Note that I've taken care to preserve the current behaviour of the
"-uses" flag and "(uses ...)" declaration, which "hoist" the named units
to the top level and call them at the start of the program. This makes
the code slightly more complex than it would otherwise be, but I wanted
to preserve the idea that declarations have unit-global effect. The
correct way to link a program with a unit that may *or may not* be
loaded during program execution is to use the "-link" flag.

Another complicating factor was static libraries containing modules that
export syntax, which contain those now-infamous "(eval '(import-syntax
...))" forms. Previously, such `eval' expressions would never cause an
[unsuccessful] attempt to load a dynamic library into a static program
because the imported module's implementing library would have already
been loaded (at the start of the program, thanks to the aforementioned
unit hoisting), indicating that the module is already provided. Now,
however, that library's top level is only entered when the "culpable"
import expression is reached, but the `eval' form will always precede
that point in the program. Luckily, the compiler knows exactly what
libraries need to be loaded before the `eval' expression to avoid this
situation, because it can consult the module's import forms. So, we now
inject the necessary library entrypoints into the program just before
the `eval' (this is the `compiled-module-dependencies' bit of the patch
that does this, in modules.scm). This is only done when necessary, i.e.
for statically compiled modules that export syntax.

I've tested this pretty extensively, but I also know that it's nasty in
terms of sheer size (15 files changed, 266 insertions, 309 deletions),
so please just let me know if you have any questions and I'll do my best
to help clarify what's going on.

Cheers,

Evan
>From 7a4622bfcf1c727c05b6a6bf5cbfb754914d289b Mon Sep 17 00:00:00 2001
From: Evan Hanson 
Date: Tue, 29 May 2018 18:33:00 +1200
Subject: [PATCH] Rework library loading to support conditional unit entry

This makes a handful of changes to the way library dependencies are
processed in order to support conditional unit loading, i.e. not calling
a unit's entry procedure unless its code path is really visited:

Drop the `file-requirements' hash table in favour of two "lset" globals,
`library-requirements' and `unit-requirements', the first of which is a
superset of the second. The `unit-requirements' list includes everything
that needs to be linked with the program statically (i.e. as a unit),
and everything else is a runtime dependency (i.e. loaded as a shared
object or source file). Remove the "M" debug option.

Introduce a new `uses-declarations' global to keep track of units that
are specified with "-uses" or `(declare (uses))'. These are hoisted to
the top level and called at the start of the program. Construct the list
of `used-units', which is used to generate prototypes for external unit
toplevels in the C backend, by simply remembering all `##core#callunit'
nodes as they're encounted during canonicalisation.

Split the batch driver's `initforms' list into two separate values, one
for import forms (which must be included within the program's wrapper
module's body, if one is used) and one for compiler-introduced
initialisation forms (which must precede the profiling-related
expressions that are inserted into the program when profiling is
enabled, since they're responsible for loading the "profiler" unit).
Move all "forms" bindings together in the `let' that introduces them.

Simplify `##sys#process-require' so that it expects just a library name
and compilation flag as arguments, and returns just a single value. Get
rid of the `provided' list, which is no longer necessary.

For modules that export syntax in static