SKILL® Type Specifier Syntax
See trademark information about the SKILL® language.
Types are behind some of the highly-productive features of the Veda intelligent editor/IDE:
Identifier Completion;
Jump to Definition;
Function Parameter Hinting;
Completion of Structure And Class Members;
Method Completion.
Note: you can try these by opening
demo.il
and following the instructions!
The Veda toolchain allows users to add type annotations to SKILL/SKILL++ language forms. This document details the syntax understood by the upcoming beta version and proposes a few extensions.
These annotations are optional, and type inference allows a few of them to make a big difference in how Veda understands your code.
Types and documentation comments also contribute to the output of the
condense
tool, which generates static definitions for
“library IP,” enabling seamless plugging into customer development
workflows:
("com.crosstwine.veda.condense.il.defs"
library "my-library"
symbols ((MyIpFunction1
description (("<documentation elided>"))
params ((filename
summary "<summary elided>"
type (or string symbol)))
returns (nil
summary "<summary elided>"
type list))))
The type specifier syntax is heavily inspired by Common Lisp; some of the extensions proposed below have been “tuned” to work well with infix syntax.
Annotation Syntax
Currently Supported
The following type specifiers are currently fully supported:
foo
-
Single symbols denote named types, either built-in, such as
fixnum
orstring
, or user-defined, such asMyClass
orMyStruct
. As a special case,null
is a synonym forlist
; - (
or
typespec*) -
Analogous to
CL:OR
. As in CL,(or)
denotes a type which has no members, and is used to annotate emptiness. E.g.: the return type of non-returning functions. - (
lambda
arg-typespec value-typespec) -
Somewhat analogous to
CL:FUNCTION
, with arg-typespec having the following form:arg-typespec::= (typespec* [@optional typespec*] [@key typespec*] [@rest typespec])
Will be replaced by something closer to
CL:FUNCTION
at some point.
Proposed Extensions
We currently envision supporting the following type specifiers, but their syntax has not yet been set in stone (feel free to chime in!):
- (
member
object*) -
Expands to (
or
(eqv
object)*); - (
eqv
object) -
Analogous to
CL:EQL
; - (
range
list-or-array typespec) -
Denotes a subtype of
list
orarray
which holds objects of type typespec. E.g.:(range array string)
is equivalent to the following JSDoc/Closure type expression:
{Array.<string>}
Note that with
range
available, thenull
type specifier could expand to(range list (or))
; - (
range
table
typespec) -
Denotes a subtype of
table
which holds values of type typespec and keys of any type; - (
range
(arrayref
table
typespec1) typespec2) -
Denotes a subtype of
table
which holds keys of type typespec1 and values of type typespec2; - (
null
typespec) -
Expands to (
or
typespecnull
). This is a bit peculiar, but meshes nicely with infix syntax.
Infix Syntax
SKILL supports infix syntax, and we intend to enable it for type specifiers:
string||fixnum
-
Reads as
(or string fixnum)
; list:string
-
Reads as
(range list string)
; list:string||fixnum
,list:(string||fixnum)
-
Reads as
(range list (or string fixnum))
; (list:string)||fixnum
-
Reads as
(or (range list string) fixnum)
; member(t nil)
-
Reads as
(member t nil)
; table[string]:number
-
Reads as
(range (arrayref table string) number)
; !symbol
-
Reads as
(null symbol)
.Note that this is a clear departure from the JSDoc/Closure notation, in which
!
denotes not null. Our types are never “nullable” by default, however, so!
may double as a mnemonic for “attention!”
Note: “Unnatural” Alternative to
!
The following has been considered a possible alternative to
!
—at the cost of using a bizarre compound type
specifier:
~foo
-
Would expand to
(or foo null)
after being read as(bnot foo)
;
We do not plan to support it.
In Function Documentation
Type annotations can be used in JSDoc-inspired
documentation comments. E.g. with @type
for
structure and class slots:
;; A struct.
defstruct(MyStruct
;; Slot A.
;;
;; @type {string}
a
;; @type (or fixnum flonum)
b
c
)
or with @param
and
@return
for complex functions where argument type templates won’t do:
;; @param {MyStruct} a - A!
;; @param (or fixnum null) b B?
;; @param (or
;; (lambda () string)
;; port) c
;; @return {symbol} Always t!
procedure( MyVeryComplexProc(a b c @rest rest)
Delegate(b c a)
)
Note that in these contexts, a type specification
must start with either {
or
(
. This means that atomic types and some infix syntax
expressions must be wrapped in braces, as in {MyStruct}
above. Extra braces are currently disallowed.
Note that these braces are delimiters, and are not considered to be part of the specifier.
Conclusion
Types enable SKILL/SKILL++ developers to use highly-productive development tools and practices.
Documentation comments and a few type annotations go a long way toward delivering fully-documented “IP” which offers the same benefits to downstream users.
Feedback is welcome; we can be reached via:
Telephone: +32 470 96 38 56;
Email: dd@crosstwine.com.
Thank you for your attention!
Regards,
Damien Diederen.