Sheesh! This is the first post of year 2016… and it is April already! I worked on the ‘typed-language’ branch of Vicare, mostly on the expander. The typed language is moving forwards, step by step; there is still a lot to do.
Despite being called ‘typed-language’: I am using it as if it is the
master branch. This is bad. There have been so many changes that I hesitate
to merge it into the actual master; I keep telling to myself: I have to do this
first, I have to do that first. Well… I will not merge it tomorrow, because I
have to do stuff first.
Everything I discuss here is relative to code in the head of the ‘typed-language’ branch.
When importing a module: it is now possible to use the full syntactic binding name modifiers. Example:
(module it
(red blue)
(define red 1)
(define blue 2))
(define (doit)
(import (prefix it private::))
(fprintf (current-error-port)
"~a, ~a\n" private::red private::blue))
this should make modules usable as full namespace things, like in other languages.
Indeed, I have removed the ugly library (vicare language-extensions
namespaces) (still there in the master branch) because it is now useless.
The biggest development in the last four months is about type annotations: forms that
specify which type a variable has and a value is expected to have, when the typed
language is enabled. Simple type annotations where already present (I called them
tags before); in this example, the type annotation is the identifier
<string>:
(define {O <string>}
"ciao")
(.length O) ⇒ 4
There are more now:
(is-a? "123" (or <false> <string>)) ⇒ #t
(is-a? #f (or <false> <string>)) ⇒ #t
(is-a? 99 (or <false> <string>)) ⇒ #f
(is-a? 123 (and <fixnum> <positive>)) ⇒ #t
(is-a? 123 (not <vector>)) ⇒ #t
(is-a? '#(123) (not <vector>)) ⇒ #f
(is-a? '(1 2 3) (list-of <positive-fixnum>)) ⇒ #t
(is-a? '(1 "2") (list <fixnum> <string>)) ⇒ #t
(is-a? '(1 "b" c)
(pair <fixnum>
(pair <string>
(pair <symbol> <null>))))
⇒ #t
there is also support for closure object’s signatures:
(type-annotation-super-and-sub? (lambda (<fixnum>) => (<fixnum>)) (lambda (<non-negative-fixnum>) => (<positive-fixnum>))) ⇒ #t
which will be useful in some future when I will attempt an implementation of interfaces. Unfortunately there is no way to validate the type of a closure object at run–time; this is problematic:
(is-a? display
(case-lambda
((<top>) => (<void>))
((<top> <textual-output-port>) => (<void>))))
⇒ #t
(is-a? display
(lambda (<fixnum>) => (<fixnum>)))
⇒ #f
(is-a? (unsafe-cast-signature (<procedure>) display)
(lambda (<fixnum>) => (<fixnum>)))
⇒ #t ;;wrong!!!
the run–time predicate for all the type annotations describing closure objects is
procedure?. What can I do?
It is possible to define aliases for type annotations:
(define-type <string-maybe> (or <false> <string>))
In the documentation file vicare-scheme there is a node ‘types’ which describes the typed language; it is WIP3 but enough up–to–date to be useful. Readers will notice that some type annotations’ syntaxes are similar (but not equal) to Typed Racket’s ones; this is inevitable: they chose good names.
Some built–in syntaxes (if, and, or) propagate type
informations correctly:
(type-of (and 1 "ciao" 'blue))
⇒ #[signature (<symbol>)]
(type-of (and (read) 123))
⇒ #[signature ((or <positive-fixnum> <false>))]
(type-of
(or (cast-signature ((or <false> <string>)) (read))
(cast-signature ((or <false> <fixnum>)) (read))))
⇒ #[signature ((or <string> <false> <fixnum>))]
cond is built upon if:
(type-of
(cond ((read) 123)
((read) "ciao")
(else 'blue)))
⇒ #[signature ((or <positive-fixnum> <string> <symbol>))]
(type-of
(cond ((read) 123)
((read) => (lambda ({_ <string>} x) "ciao"))
(else 'blue)))
⇒ #[signature ((or <positive-fixnum> <string> <symbol>))]
other syntaxes (case) do not do it yet:
(type-of
(case (read)
((a) 123)
((b) "ciao")
(else 'blue)))
⇒ #[signature <list>]
a standalone <list> identifier means: unspecified number of values, of
unspecified type. This is what I am working on these days, mostly. For correct type
propagation: non–core macros must be reimplemented as core macros.
There was once support for RHS type propagation. It means this:
(define O (new <vector> 1 2 3)) (type-of O) ⇒ #[signature (<vector>)]
it is not needed to explicitly specify the type annotation for the variable O
because the expander figures it out. At some point, I removed such feature because
it was problematic with the type infrastructure implemented back then.
It is now time to reconsider this feature. I will try something about it.
Work–in–progress. I went crazy the first time I saw this acronym in source code: what is this design pattern I never heard about?!?