Previous page Table of Contents Next page
Annotations are like machine-readable comments. They are introduced by colon, whereas ordinary comments are introduced by semicolon. Annotations can only appear in specific places in the grammar, generally in definition statements. Annotations allow attaching "extra" information to a definition that can be used by the compiler to enable optimizations or by a development environment to assist the developer. Annotations are not documentation; the self-documentation for a definition is simply any comments immediately preceding the definition.
You can annotate classes, slots, functations (both fun and defun), definitions (def), and any user-defined constructs that allow annotations. An annotation can look like a name or a function call. The argument expressions in a call-like annotation must be literals or names, which are implicitly quoted.
The syntax for annotations is defined as:
;; Return a list of lists of function and argument list defparser annotations : { ?:name [ ( ?argument is annotation-argument & , ^^ ) ] & , ^^ }+ => map(fun(name, args) def fname = name-in-context(":" + name, name) list(known-function(fname, tokens), args or list()), name, arguments) ;; An argument to an annotation must be a literal, a name that is ;; not punctuation, or a name quoted by backslash. defun parse-annotation-argument (tokens is token-stream, indentation is integer, error? is boolean) def token = tokens.next if token = #\\ tokens.advance def token2 = tokens.next if token2 is name tokens.advance token2 else if token2 is string tokens.advance name(token2) else wrong-token-error(tokens, "a name or string") else if token is name and not punctuation?(token) or token is literal tokens.advance token else wrong-token-error(tokens, "a literal, a name, or a backslash followed by a name or a string") defun known-function (name is name, tokens is token-stream) is function def definition = known-definition(name) if definition is function definition else syntax-error(tokens, #"No known function for ?name")
The annotation mechanism is completely user-extensible. An annotation is implemented by calling a function whose name is the annotation name prefixed with colon and whose arguments are the object being defined and any additional arguments specified in the annotation. The method executed can return a replacement object or side-effect the object and return its first argument. Annotations are called during macro expansion.
For example, the sealed annotation for methods could be defined in one of these two ways:
defun :sealed(m is method-definition) m.sealed? := true m defun :sealed(m is method-definition) sealed-method-definition(m.name, m.method)
The following helper function applies annotations to an object. It is invoked during macro expansion of a definition statement.
defun apply-annotations(annotation-list, object) if annotation-list reduce(fun(annotation, object) (annotation[0])(object, annotation[1]...), object, annotation-list) ;; No annotations, just return the original object else object
Previous page Table of Contents Next page