Previous page Table of Contents Next page
The # macro introduces data syntax, which can be used to describe data. The expansion of the macro is an expression that constructs the data described. In the simplest case, it is simply a quotation of constant data. However, data syntax allows variables' values to be dropped into a template.
Data syntax is extensible. When the name (including punctuation) xxx appears, if a function parse-#xxx is defined, it is called to parse its own form of data syntax. The statement def#parser can be used to define these functions; it is identical to defparser except for the name of the parse function to which it adds a method. By convention xxx should only be punctuation or a funny-looking name, to avoid conflicts with #xxx as a quoted simple-name xxx. By convention, the syntax for a form of data object called xyz begins with #/xyz; this is implemented by defining a function named parse-#/xyz.
When a name-in-context is quoted in data syntax, and the context is not a module, it is translated to the simple-name with the same spelling.
Data syntax is defined as follows:
defmacro # ?:data => data defparser data ;; Any name or string can be quoted with backslash \\ ?n is name => quotation(if context(n) is false or module then n else simple-name(spelling(n))) \\ ?s is string => quotation(name(s)) ;; Literal numbers and characters represent themselves, ;; while strings are string templates ?:literal => if literal is string expand-string-template(literal) else literal ;; If parse-#x is defined as a function, call it ?x is data-macro-call => x ;; For convenience, ignore extra # inside data \# ?:data => data ;; Any name not defined that way is quoted ?n is name => quotation(if context(n) is false or module then n else simple-name(spelling(n))) ;; This predefined data syntax parser allows ? variable to ;; substitute the value of a variable into the data being constructed def#parser \? ?:variable => variable ;; This predefined data syntax parser allows a list or dictionary to ;; be expressed within parentheses ;; #(x y z ?true ?false) is a list ;; #(x => 1 y => 2 z => 3) is a dictionary ;; commas between the items are optional def#parser ( { ?item is data [ \=> ?item2 is data ] [,] }* ) => ;; Utility function to unwrap quotations def unwrap(x is quotation) x.data def unwrap(x is anything) x ;; If no arrows are present, it is a list if every?(\not, item2) ;; If all items are literals or quotations, quote the whole list if every?(_ is quotation or literal, item) quotation(list(map(unwrap, item)...)) else ;; This is a list template, expand into invocation of list constructor invocation(#list@PLOT, item...) ;; If arrows are present, it is a dictionary else if member?(false, item2) error("Inconsistent use of arrows in (...) data syntax") ;; If all items are literals or quotations, quote the whole dictionary if every?(_ is quotation or literal, item) and every?(_ is quotation or literal, item2) quotation(dictionary((for key in item, value in item2 collect unwrap(key) collect unwrap(value))...)) else ;; This is a dictionary template, expand into invocation of dictionary constructor invocation(#dictionary@PLOT, (for key in item, value in item2 collect key collect value)...)
Previous page Table of Contents Next page