[Chicken-hackers] [PATCH] Add 'a shorthand for forall types
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
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
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
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