From a738372ac080f29c9762007a3ea049b6d9e0e94f Mon Sep 17 00:00:00 2001 From: Tom Harrison Date: Thu, 29 Dec 2016 19:01:29 +1000 Subject: [PATCH] merge macros and macros-core (#162) --- CMakeLists.txt | 5 +- README.md | 10 +- doc/1-7-macros.md | 11 +- doc/2-10-utility.md | 225 ++++ doc/2-11-derivations.md | 120 ++ doc/2-12-algorithms.md | 308 +++++ doc/2-13-list.md | 436 +++++++ doc/2-14-vector.md | 518 ++++++++ doc/2-15-set.md | 418 ++++++ doc/2-16-map.md | 433 +++++++ doc/2-17-array.md | 396 ++++++ doc/2-18-shared-ptr.md | 118 ++ doc/2-19-unique-ptr.md | 118 ++ doc/2-20-operator-macros.md | 90 ++ doc/2-21-bitset-enum.md | 49 + doc/2-22-variant.md | 84 ++ doc/2-3-math.md | 4 +- doc/{2-4-macros-core.md => 2-4-macros.md} | 62 +- doc/2-5-stdlib.md | 20 +- doc/2-6-assert.md | 58 + doc/2-7-concepts-core.md | 480 +++++++ doc/2-8-concept-defs.md | 251 ++++ doc/2-9-concepts.md | 78 ++ doc/3-1-cerrno.md | 4 +- doc/all.md | 174 ++- doc/index.md | 31 +- generate-docs | 37 +- modules/macros-core.dt | 1142 ----------------- modules/macros.dt | 1134 +++++++++++++++- modules/operator-macros.dt | 1 - modules/stdlib.dt | 2 +- .../operator-macro-need-three.dt.errors | 6 +- verify-targets | 1 - 33 files changed, 5501 insertions(+), 1323 deletions(-) create mode 100644 doc/2-10-utility.md create mode 100644 doc/2-11-derivations.md create mode 100644 doc/2-12-algorithms.md create mode 100644 doc/2-13-list.md create mode 100644 doc/2-14-vector.md create mode 100644 doc/2-15-set.md create mode 100644 doc/2-16-map.md create mode 100644 doc/2-17-array.md create mode 100644 doc/2-18-shared-ptr.md create mode 100644 doc/2-19-unique-ptr.md create mode 100644 doc/2-20-operator-macros.md create mode 100644 doc/2-21-bitset-enum.md create mode 100644 doc/2-22-variant.md rename doc/{2-4-macros-core.md => 2-4-macros.md} (85%) create mode 100644 doc/2-6-assert.md create mode 100644 doc/2-7-concepts-core.md create mode 100644 doc/2-8-concept-defs.md create mode 100644 doc/2-9-concepts.md delete mode 100644 modules/macros-core.dt diff --git a/CMakeLists.txt b/CMakeLists.txt index e59a0e4f..da40c27d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -393,9 +393,8 @@ standard_library (modules/ctime.dt ctime macros) standard_library (modules/clocale.dt clocale drt) standard_library (modules/cstdio-core.dt cstdio-core drt) standard_library (modules/introspection.dt introspection drt) -standard_library (modules/macros-core.dt macros-core cstdio-core) -standard_library (modules/stdlib.dt stdlib macros-core introspection) -standard_library (modules/macros.dt macros cstdio-core macros-core introspection) +standard_library (modules/macros.dt macros cstdio-core introspection) +standard_library (modules/stdlib.dt stdlib macros introspection) standard_library (modules/operator-macros.dt operator-macros macros stdlib) standard_library (modules/assert.dt assert macros cstdio cstdlib stdlib) standard_library (modules/concepts-core.dt concepts-core macros assert unistd cstring) diff --git a/README.md b/README.md index 1e860a29..4a1756d9 100644 --- a/README.md +++ b/README.md @@ -196,10 +196,8 @@ able to be built. It has been tested on the following: 0))) ``` ``` -> Struct: Point -> Member count: 2 -> Member 1: x -> Member 2: y +> ./introspection.dt:8:7: error: not in scope: 'let' +> ./introspection.dt:18:6: error: not in scope: 'show-struct-details' ``` **error-reporting** @@ -221,8 +219,8 @@ able to be built. It has been tested on the following: 0))) ``` ``` -> ./error-reporting.dt:13:23: error: struct type does not exist (see macro at 13:5) -> ./error-reporting.dt:13:5: error: macro expansion error (see previous) +> ./error-reporting.dt:6:6: error: not in scope: 'let' +> ./error-reporting.dt:13:6: error: not in scope: 'assert-is-struct' ``` **derivations** diff --git a/doc/1-7-macros.md b/doc/1-7-macros.md index d0b52985..0e833a09 100644 --- a/doc/1-7-macros.md +++ b/doc/1-7-macros.md @@ -95,12 +95,11 @@ a pointer to a `DNode` (static). For example: (def const-string (macro extern (void) (q (p (const char))))) -There are two principal standard libraries that deal with macros: -[`macros-core`](./2-4-macros-core.md) and [`macros`](./2-6-macros.md). -The former provides many functions that ease macro authorship. The -latter provides the quasiquotation (`qq`) macro, which is one of the -more useful macro-writing macros. For example, an `unless` (opposite -of `if`) macro would look like so, when using `qq`: +The standard library for dealing with macros is (unsurprisingly) +[`macros`](./2-6-macros.md). It provides many functions that ease +macro authorship, as well as the quasiquotation (`qq`) macro, which is +one of the more useful macro-writing macros. For example, an `unless` +(opposite of `if`) macro would look like so, when using `qq`: (def unless (macro extern (expr tc fc) (qq if (not (uq expr)) (uq tc) (uq fc)))) diff --git a/doc/2-10-utility.md b/doc/2-10-utility.md new file mode 100644 index 00000000..02d4df23 --- /dev/null +++ b/doc/2-10-utility.md @@ -0,0 +1,225 @@ +# Dale + +[Previous](./2-9-concepts.md) | [Next](./2-11-derivations.md) + +## 2.10 utility + +### Details + +Module: utility + +### Description + +Provides the common functions and macros used by the container and +algorithm modules. + + + +### Functions + +#### `make-type-string` + +Linkage: `extern` +Returns: `bool` +Parameters: + + * `(mc (p MContext))`: An MContext. + * `(prefix (p (const char)))`: The type string prefix. + * `(T (p DNode))`: The type node. + * `(buf (p char))`: The buffer for the type string. + + +Writes the prefix, and the internal string representation of the type +node, to the provided buffer. If the type node is a token that begins +with a digit, then the token's contents are written to the buffer +instead. + + +#### `make-type-string` + +Linkage: `extern` +Returns: `bool` +Parameters: + + * `(mc (p MContext))`: An MContext. + * `(prefix (p (const char)))`: The type string prefix. + * `(T1 (p DNode))`: The first type node. + * `(T2 (p DNode))`: The second type node. + * `(buf (p char))`: The buffer for the type string. + + +As per the earlier implementation, except that it takes two type +nodes. + + +#### `make-type-string` + +Linkage: `extern` +Returns: `bool` +Parameters: + + * `(mc (p MContext))`: An MContext. + * `(prefix (p (const char)))`: The type string prefix. + * `(T1 (p DNode))`: The first type node. + * `(T2 (p DNode))`: The second type node. + * `(T3 (p DNode))`: The third type node. + * `(buf (p char))`: The buffer for the type string. + + +As per the earlier implementation, except that it takes three type +nodes. + + +#### `make-type-display-string` + +Linkage: `extern` +Returns: `bool` +Parameters: + + * `(mc (p MContext))`: An MContext. + * `(prefix (p (const char)))`: The type display string prefix. + * `(T (p DNode))`: The type node. + * `(buf (p char))`: The buffer for the type display string. + + +Similar to `make-type-string`, except that it adds the display +representation (i.e. the one set by way of `register-type`, if +applicable) to the buffer, rather than the internal representation. + + +#### `make-type-display-string` + +Linkage: `extern` +Returns: `bool` +Parameters: + + * `(mc (p MContext))`: An MContext. + * `(prefix (p (const char)))`: The type display string prefix. + * `(T1 (p DNode))`: The first type node. + * `(T2 (p DNode))`: The second type node. + * `(buf (p char))`: The buffer for the type display string. + + +As per the earlier implementation, except that it takes two type +nodes. + + +#### `make-type-display-string` + +Linkage: `extern` +Returns: `bool` +Parameters: + + * `(mc (p MContext))`: An MContext. + * `(prefix (p (const char)))`: The type display string prefix. + * `(T1 (p DNode))`: The first type node. + * `(T2 (p DNode))`: The second type node. + * `(T3 (p DNode))`: The third type node. + * `(buf (p char))`: The buffer for the type display string. + + +As per the earlier implementation, except that it takes two type +nodes. + + + + +### Concept macros + +#### `Pair` + +Linkage: `extern` +Parameters: + + * `(T1 Type)`: The first type node. + * `(T2 Type)`: The second type node. + + +Expands to a struct definition with two members, named `first` and +`second`. + + +#### `Triple` + +Linkage: `extern` +Parameters: + + * `(T1 Type)`: The first type node. + * `(T2 Type)`: The second type node. + * `(T3 Type)`: The third type node. + + +Expands to a struct definition with three members, named `first`, +`second` and `third`. + + + + +### Macros + +#### `def-type-macro` + +Linkage: `extern` +Parameters: + + * `name`: The type macro name. + + +Takes a node as its single argument. Constructs a macro with that +name that takes one arbitrary type and expands to the concatenation of +that name and the stringification of the type. + + +#### `Iterator` + +Linkage: `extern` +Parameters: + + * `T`: The type node. + + +Expands to a string that can be used as the `Iterator` type name for +the argument type. + + +#### `ReverseIterator` + +Linkage: `extern` +Parameters: + + * `T`: The type node. + + +Expands to a string that can be used as the `Iterator` type name for +the argument type. + + +#### `Pair` + +Linkage: `extern` +Parameters: + + * `T1`: The first type node. + * `T2`: The second type node. + + +Expands to the concrete type name of the `Pair` generated by way of +the concept macro. + + +#### `Triple` + +Linkage: `extern` +Parameters: + + * `T1`: The first type node. + * `T2`: The second type node. + * `T3`: The third type node. + + +Expands to the concrete type name of the `Triple` generated by way of +the concept macro. + + +[Previous](./2-9-concepts.md) | [Next](./2-11-derivations.md) + diff --git a/doc/2-11-derivations.md b/doc/2-11-derivations.md new file mode 100644 index 00000000..11b9b9c3 --- /dev/null +++ b/doc/2-11-derivations.md @@ -0,0 +1,120 @@ +# Dale + +[Previous](./2-10-utility.md) | [Next](./2-12-algorithms.md) + +## 2.11 derivations + +### Details + +Module: derivations + +### Description + +Provides concept macros for generating common functions over types. +The difference between this module and `algorithms` is that this one +is limited to very simple functions, namely the basic relations and +the `swap` function. + + + +### Concept macros + +#### `swap` + +Linkage: `extern` +Parameters: + + * `(T Type)`: The type node. + + +Expands to a `swap` function over references to the provided type. + + +#### `!=` + +Linkage: `extern` +Parameters: + + * `(T Type)`: The type node. + + +Expands to a `!=` function over the provided type. `=` must be defined +over the type before calling this macro. + + +#### `<=` + +Linkage: `extern` +Parameters: + + * `(T Type)`: The type node. + + +Expands to a `<=` function over the provided type. `<` must be defined +over the type before calling this macro. + + +#### `>` + +Linkage: `extern` +Parameters: + + * `(T Type)`: The type node. + + +Expands to a `>` function over the provided type. `<` must be defined +over the type before calling this macro. + + +#### `>=` + +Linkage: `extern` +Parameters: + + * `(T Type)`: The type node. + + +Expands to a `>=` function over the provided type. `<` must be defined +over the type before calling this macro. + + +#### `=` + +Linkage: `extern` +Parameters: + + * `(T Struct)`: The struct type node. + + +Expands to a `=` function over the provided struct type. `=` must be +defined over each of the struct's member types before calling this +macro. + + +#### `<` + +Linkage: `extern` +Parameters: + + * `(T Struct)`: The struct type node. + + +Expands to a `<` function over the provided struct type. `<` must be +defined over each of the struct's member types before calling this +macro. + + +#### `relations` + +Linkage: `extern` +Parameters: + + * `(T Struct)`: The struct type node. + + +Expands to `=`, `!=`, `<`, `<=`, `>` and `>=` functions over the +provided struct type. Any that have already been defined are skipped. + + +[Previous](./2-10-utility.md) | [Next](./2-12-algorithms.md) + diff --git a/doc/2-12-algorithms.md b/doc/2-12-algorithms.md new file mode 100644 index 00000000..a564fa42 --- /dev/null +++ b/doc/2-12-algorithms.md @@ -0,0 +1,308 @@ +# Dale + +[Previous](./2-11-derivations.md) | [Next](./2-13-list.md) + +## 2.12 algorithms + +### Details + +Module: algorithms + +### Description + +Provides concept macros for generating algorithm functions. + + + +### Concept macros + +#### `find` + +Linkage: `extern` +Parameters: + + * `(Ti InputIterator)`: The iterator type. + + +Expands to a function that accepts two of the provided iterator types +and an instance of the iterator type's `value-type`. On calling that +function, if the value is found in the range, the iterator containing +the value is returned. Otherwise, the second argument iterator is +returned. + + +#### `find-if` + +Linkage: `extern` +Parameters: + + * `(Ti InputIterator)`: The iterator type. + + +Expands to a function that accepts two of the provided iterator types +and a `Predicate`. On calling that function, if a value satisfying the +predicate is found in the range, the iterator containing that value is +returned. Otherwise, the second argument iterator is returned. + + +#### `find-if-not` + +Linkage: `extern` +Parameters: + + * `(Ti InputIterator)`: The iterator type. + + +Expands to a function that accepts two of the provided iterator types +and a `Predicate`. On calling that function, if a value that does not +satisfy the predicate is found in the range, the iterator containing +that value is returned. Otherwise, the second argument iterator is +returned. + + +#### `sort` + +Linkage: `extern` +Parameters: + + * `(Ti RandomAccessIterator)`: The iterator type. + + +Expands to a function that accepts two of the provided iterator types. +On calling that function, the corresponding range is sorted. (The +implementation here needs some work, because the resulting function is +pretty slow.) + + +#### `for-each` + +Linkage: `extern` +Parameters: + + * `(Ti InputIterator)`: The iterator type. + + +Expands to a function that accepts two of the provided iterator types +and an `Action`. On calling that function, the action is run against +each value in the range. + + +#### `lower-bound` + +Linkage: `extern` +Parameters: + + * `(Ti RandomAccessIterator)`: The iterator type. + + +Expands to a function that accepts two of the provided iterator types +and a `value-type`. On calling that function, returns the position of +the first value in the range that is not less than the provided value. +The function assumes that the range is sorted. + + +#### `upper-bound` + +Linkage: `extern` +Parameters: + + * `(Ti RandomAccessIterator)`: The iterator type. + + +Expands to a function that accepts two of the provided iterator types +and a `value-type`. On calling that function, returns the position of +the first value in the range that is greater than the provided value. +The function assumes that the range is sorted. + + +#### `binary-search` + +Linkage: `extern` +Parameters: + + * `(Ti RandomAccessIterator)`: The iterator type. + + +Expands to a function that accepts two of the provided iterator types +and a `value-type`. On calling that function, returns a boolean +indicating whether the value is present in the range. The function +assumes that the range is sorted. + + +#### `equal-range` + +Linkage: `extern` +Parameters: + + * `(Ti RandomAccessIterator)`: The iterator type. + + +Expands to a function that accepts two of the provided iterator types +and a `value-type`. It also instantiates a `Pair` type over the +iterator type, if required. On calling that function, it returns a +`Pair` containing the `lower-bound` and `upper-bound` iterators for +the value. + + +#### `max` + +Linkage: `extern` +Parameters: + + * `(T Type)`: The type node. + + +Expands to a function that takes two values of the specified type. If +the first value is greater than the second value, then the first is +returned. Otherwise, the second is returned. Does not support types +that do not permit copying. + + +#### `min` + +Linkage: `extern` +Parameters: + + * `(T Type)`: The type node. + + +Expands to a function that takes two values of the specified type. If +the first value is less than than the second value, then the first is +returned. Otherwise, the second is returned. Does not support types +that do not permit copying. + + +#### `copy` + +Linkage: `extern` +Parameters: + + * `(Ti InputIterator)`: The input iterator type. + * `(To OutputIterator)`: The output iterator type. + + +Takes input and output iterator types as its arguments. Expands to a +function that takes two of the input iterators and an output iterator. +That function iterates over the provided range, sinking values into +the output iterator at each step. + + +#### `assign` + +Linkage: `extern` +Parameters: + + * `(Tc BackInsertionSequence)`: The container type. + * `(Ti InputIterator)`: The input iterator type. + + +Takes a container type and an input iterator type as its arguments. +Expands to a function that takes a container value and two input +iterators as its arguments. That function clears the container, and +then copies each element from the range formed by the input iterators +into the cleared container. + + +#### `foldl` + +Linkage: `extern` +Parameters: + + * `(Ti InputIterator)`: The input iterator type. + + +Takes an input iterator type as its arguments. Expands to a fold-left +function that takes a binary operation function pointer, an initial +value, and a pair of input iterators as its arguments. Does not +support types that do not permit copying. + + +#### `=` + +Linkage: `extern` +Parameters: + + * `(Tc Container)`: The container type. + + +Takes a container type as its argument. Expands to a function that +takes two container pointers and returns a boolean indicating whether +the elements of those containers match. + + +#### `<` + +Linkage: `extern` +Parameters: + + * `(Tc Container)`: The container type. + + +Takes a container type as its argument. Expands to a function that +takes two container pointers and returns a boolean indicating whether +the first container is 'less than' the second. This will be so when: + + * the first element of the first container that is not equal to the + element at the same position in the second container compares as + less than that element; or + * there are fewer elements in the first container than in the + second. + +(`<` is defined over pointers to containers, rather than container +values, for the same reasons as `=`). + + + + +### Macros + +#### `Predicate` + +Linkage: `extern` +Parameters: + + * `T`: The type node. + + +Expands to a function pointer type that takes the `value-type` of the +corresponding type argument and returns a `bool`. This name is used as +shorthand in this module's documentation. + + +#### `RefPredicate` + +Linkage: `extern` +Parameters: + + * `T`: The type node. + + +Like `Predicate`, except the function pointer type takes a const reference. + + +#### `Action` + +Linkage: `extern` +Parameters: + + * `T`: The type node. + + +Expands to a function pointer type that takes the `value-type` of the +corresponding type argument and returns `void`. This name is used as +shorthand in this module's documentation. + + +#### `RefAction` + +Linkage: `extern` +Parameters: + + * `T`: The type node. + + +Like `Action`, except the function pointer takes a reference. + + +[Previous](./2-11-derivations.md) | [Next](./2-13-list.md) + diff --git a/doc/2-13-list.md b/doc/2-13-list.md new file mode 100644 index 00000000..3dac4c21 --- /dev/null +++ b/doc/2-13-list.md @@ -0,0 +1,436 @@ +# Dale + +[Previous](./2-12-algorithms.md) | [Next](./2-14-vector.md) + +## 2.13 list + +### Details + +Module: list + +### Description + +Concept macro for a doubly-linked list. Apart from the `List` macro +and concept macro, the documentation in this module is for a generated +list instance of type `T`. + +All of the functions that take `Iterator` arguments are defined for +`ReverseIterator`s as well, notwithstanding that there is no +documentation for those instances. + +The `List` type implements the following concepts: + + * `FrontInsertionSequence`; + * `BackInsertionSequence`; and + * `ReversibleContainer`. + +Its iterators implement `OutputIterator` and `BidirectionalIterator`. + + + +### Structs + +#### `(List T)` + +Linkage: `extern` +Members: N/A + +The core list structure type. + + +#### `(Iterator (List T))` + +Linkage: `extern` +Members: + + * `(node (p nodetypenode))` + + + +#### `(ReverseIterator (List T))` + +Linkage: `extern` +Members: + + * `(node (p nodetypenode))` + + + + + +### Functions + +#### `init` + +Linkage: `extern` +Returns: `bool` +Parameters: + + * `(lst (ref (List T)))`: A list reference. + + +Initialise a list. + + +#### `empty` + +Linkage: `extern` +Returns: `bool` +Parameters: + + * `(lst (ref (const (List T))))`: A list reference. + + +Determine whether the list is empty. + + +#### `size` + +Linkage: `extern` +Returns: `size` +Parameters: + + * `(lst (ref (const (List T))))`: A list reference. + + +Returns the number of elements in the list. + + +#### `max-size` + +Linkage: `extern` +Returns: `size` +Parameters: + + * `(lst (ref (const (List T))))`: A list reference. + + +Returns the number of elements that can be accommodated by the +list. + + +#### `front` + +Linkage: `extern` +Returns: `(p T)` +Parameters: + + * `(lst (ref (const (List T))))`: A list reference. + + +Returns a pointer to the value of the first element in the list. + + +#### `back` + +Linkage: `extern` +Returns: `(p T)` +Parameters: + + * `(lst (ref (const (List T))))`: A list reference. + + +Returns a pointer to the value of the last element in the list. + + +#### `push-back` + +Linkage: `extern` +Returns: `bool` +Parameters: + + * `(lst (ref (List T)))`: A list reference. + * `(value T)`: The value to add to the list. + + +Adds an element to the end of the list. + + +#### `pop-back` + +Linkage: `extern` +Returns: `void` +Parameters: + + * `(lst (ref (List T)))`: A list reference. + + +Removes an element from the end of the list. + + +#### `push-front` + +Linkage: `extern` +Returns: `bool` +Parameters: + + * `(lst (ref (List T)))`: A list reference. + * `(value T)`: The value to add to the list. + + +Adds an element to the beginning of the list. + + +#### `pop-front` + +Linkage: `extern` +Returns: `void` +Parameters: + + * `(lst (ref (List T)))`: A list reference. + + +Removes an element from the beginning of the list. + + +#### `begin` + +Linkage: `extern` +Returns: `(Iterator (List T))` +Parameters: + + * `(lst (ref (List T)))`: A list reference. + + +Returns the iterator for the first list element. + + +#### `end` + +Linkage: `extern` +Returns: `(Iterator (List T))` +Parameters: + + * `(lst (ref (List T)))`: A list reference. + + +Returns the iterator representing the end of the list (sentinel). + + +#### `source` + +Linkage: `extern` +Returns: `(p T)` +Parameters: + + * `(iter (Iterator (List T)))`: An iterator. + + +Returns a pointer to the iterator's value. + + +#### `sink` + +Linkage: `extern` +Returns: `bool` +Parameters: + + * `(iter (Iterator (List T)))`: An iterator. + * `(v T)`: The new value. + + +Set the given value at the specified position in the list. + + +#### `successor` + +Linkage: `extern` +Returns: `(Iterator (List T))` +Parameters: + + * `(iter (Iterator (List T)))`: An iterator. + + +Returns the iterator for the position that follows the argument +iterator. + + +#### `predecessor` + +Linkage: `extern` +Returns: `(Iterator (List T))` +Parameters: + + * `(iter (Iterator (List T)))`: An iterator. + + +Returns the iterator for the position just before the argument +iterator. + + +#### `=` + +Linkage: `extern` +Returns: `bool` +Parameters: + + * `(iter1 (Iterator (List T)))`: The first iterator. + * `(iter2 (Iterator (List T)))`: The second iterator. + + + +#### `rbegin` + +Linkage: `extern` +Returns: `(ReverseIterator (List T))` +Parameters: + + * `(lst (ref (List T)))`: A list reference. + + +Returns the iterator for the last list element. + + +#### `rend` + +Linkage: `extern` +Returns: `(ReverseIterator (List T))` +Parameters: + + * `(lst (ref (List T)))`: A list reference. + + +Returns the iterator representing the beginning of the list (sentinel). + + +#### `insert` + +Linkage: `extern` +Returns: `(Iterator (List T))` +Parameters: + + * `(lst (ref (List T)))`: The list reference. + * `(iter (Iterator (List T)))`: The iterator for the position. + * `(value T)`: The new value. + + +Inserts a new element into the list before the specified position, +and returns the iterator for the new element. + + +#### `erase` + +Linkage: `extern` +Returns: `(Iterator (List T))` +Parameters: + + * `(lst (ref (List T)))`: The list reference. + * `(iter (Iterator (List T)))`: The iterator for the position. + + +Remove the element at the specified position from the list. + + +#### `clear` + +Linkage: `extern` +Returns: `bool` +Parameters: + + * `(lst (ref (List T)))`: The list reference. + + +Remove all of the elements from the list. + + +#### `swap` + +Linkage: `extern` +Returns: `void` +Parameters: + + * `(lst1 (ref (List T)))`: The first list reference. + * `(lst2 (ref (List T)))`: The second list reference. + + + + + +### Concept macros + +#### `List` + +Linkage: `extern` +Parameters: + + * `(T Type)`: The type node. + + +Expands to a `List` definition over the relevant type. + + + + +### Macros + +#### `List` + +Linkage: `extern` +Parameters: + + * `T`: The type node. + + +Expands to the concrete type name of the `List` generated by way of +the concept macro. + + +#### `value-type` + +Linkage: `extern` +Parameters: + + * `(lst (p (List T)))`: A type node. + + +Expands to the underlying value type (i.e. `T`) of the list. This +only uses the type node for dispatch purposes, so it's safe to +call this with e.g. `(nullptr (List T))` as the argument. + + +#### `size-type` + +Linkage: `extern` +Parameters: + + * `(lst (p (List T)))`: A type node. + + +Expands to the underlying size type of the list. + + +#### `difference-type` + +Linkage: `extern` +Parameters: + + * `(lst (p (List T)))`: A type node. + + +Expands to the underlying iterator difference type of the list. + + +#### `value-type` + +Linkage: `extern` +Parameters: + + * `(iter (p (Iterator (List T))))`: A type node. + + +Expands to the underlying value type (i.e. `T`) of the iterator. + + +#### `distance-type` + +Linkage: `extern` +Parameters: + + * `(iter (p (Iterator (List T))))`: A type node. + + +Expands to the underlying distance type of the iterator. + + +[Previous](./2-12-algorithms.md) | [Next](./2-14-vector.md) + diff --git a/doc/2-14-vector.md b/doc/2-14-vector.md new file mode 100644 index 00000000..912aaa88 --- /dev/null +++ b/doc/2-14-vector.md @@ -0,0 +1,518 @@ +# Dale + +[Previous](./2-13-list.md) | [Next](./2-15-set.md) + +## 2.14 vector + +### Details + +Module: vector + +### Description + +Concept macro for a vector. Apart from the `Vector` macro and concept +macro, the documentation in this module is for a generated vector +instance of type `T`. + +All of the functions that take `Iterator` arguments are defined for +`ReverseIterator`s as well, notwithstanding that there is no +documentation for those instances. + +The `Vector` type implements `BackInsertionSequence` and +`RandomAccessContainer`. Its iterators implement `OutputIterator` and +`RandomAccessIterator`. + + + +### Structs + +#### `(Vector T)` + +Linkage: `extern` +Members: N/A + +The core vector structure type. + + +#### `(Iterator (Vector T))` + +Linkage: `extern` +Members: + + * `(parent-vector (p (Vector T)))` + * `(element (p T))` + + + +#### `(ReverseIterator (Vector T))` + +Linkage: `extern` +Members: + + * `(element (p T))` + + + + + +### Functions + +#### `init` + +Linkage: `extern` +Returns: `bool` +Parameters: + + * `(vecp (ref (Vector T)))`: A vector reference. + * `(cap int)`: The capacity of the new vector. + + +Initialise a vector by providing a specific capacity. + + +#### `init` + +Linkage: `extern` +Returns: `bool` +Parameters: + + * `(vecp (ref (Vector T)))`: A vector reference. + + +Initialise a vector. + + +#### `empty` + +Linkage: `extern` +Returns: `bool` +Parameters: + + * `(vecp (ref (const (Vector T))))`: A vector reference. + + +Determine whether the vector is empty. + + +#### `size` + +Linkage: `extern` +Returns: `(const size)` +Parameters: + + * `(vecp (ref (const (Vector T))))`: A vector reference. + + +Returns the number of elements in the vector. + + +#### `max-size` + +Linkage: `extern` +Returns: `size` +Parameters: + + * `(vecp (ref (const (Vector T))))`: A vector reference. + + +Returns the number of elements that can be accommodated by the +vector. + + +#### `front` + +Linkage: `extern` +Returns: `(const (p T))` +Parameters: + + * `(vecp (ref (const (Vector T))))`: A vector reference. + + +Returns a pointer to the value of the first element in the vector. + + +#### `back` + +Linkage: `extern` +Returns: `(const (p T))` +Parameters: + + * `(vecp (ref (const (Vector T))))`: A vector reference. + + +Returns a pointer to the value of the last element in the vector. + + +#### `pop-back` + +Linkage: `extern` +Returns: `void` +Parameters: + + * `(vecp (ref (Vector T)))`: A vector reference. + + +Removes an element from the end of the vector. + + +#### `resize` + +Linkage: `extern` +Returns: `bool` +Parameters: + + * `(vecp (ref (Vector T)))`: A vector reference. + * `(new-capacity size)`: The new capacity for the vector. + + +Change the vector's capacity. + + +#### `reserve` + +Linkage: `extern` +Returns: `bool` +Parameters: + + * `(vecp (ref (Vector T)))`: A vector reference. + * `(extra size)`: The amount by which the capacity should be increased. + + +Increase the vector's capacity by the specified amount. + + +#### `push-back` + +Linkage: `extern` +Returns: `bool` +Parameters: + + * `(vecp (ref (Vector T)))`: A vector reference. + * `(value T)`: The value to add to the vector. + + +Adds an element to the end of the vector. + + +#### `$` + +Linkage: `extern` +Returns: `(p T)` +Parameters: + + * `(vecp (ref (const (Vector T))))`: A vector reference. + * `(index int)`: The index of the element. + + + +#### `$` + +Linkage: `extern` +Returns: `(p T)` +Parameters: + + * `(vecp (ref (const (Vector T))))`: A vector reference. + * `(index size)`: The index of the element. + + + +#### `begin` + +Linkage: `extern` +Returns: `(Iterator (Vector T))` +Parameters: + + * `(vecp (ref (Vector T)))`: A vector reference. + + +Returns the iterator for the first vector element. + + +#### `end` + +Linkage: `extern` +Returns: `(Iterator (Vector T))` +Parameters: + + * `(vecp (ref (Vector T)))`: A vector reference. + + +Returns the iterator representing the end of the vector (sentinel). + + +#### `source` + +Linkage: `extern` +Returns: `(p T)` +Parameters: + + * `(iter (Iterator (Vector T)))`: An iterator. + + +Returns a pointer to the iterator's value. + + +#### `sink` + +Linkage: `extern` +Returns: `bool` +Parameters: + + * `(iter (Iterator (Vector T)))`: An iterator. + * `(v T)`: The new value. + + +Set the given value at the specified position in the vector. + + +#### `successor` + +Linkage: `extern` +Returns: `(Iterator (Vector T))` +Parameters: + + * `(iter (Iterator (Vector T)))`: An iterator. + + +Returns the iterator for the position that follows the argument +iterator. + + +#### `predecessor` + +Linkage: `extern` +Returns: `(Iterator (Vector T))` +Parameters: + + * `(iter (Iterator (Vector T)))`: An iterator. + + +Returns the iterator for the position just before the argument +iterator. + + +#### `=` + +Linkage: `extern` +Returns: `bool` +Parameters: + + * `(iter1 (Iterator (Vector T)))`: The first iterator. + * `(iter2 (Iterator (Vector T)))`: The second iterator. + + + +#### `<` + +Linkage: `extern` +Returns: `bool` +Parameters: + + * `(iter1 (Iterator (Vector T)))`: The first iterator. + * `(iter2 (Iterator (Vector T)))`: The second iterator. + + + +#### `+` + +Linkage: `extern` +Returns: `(Iterator (Vector T))` +Parameters: + + * `(iter1 (Iterator (Vector T)))`: The first iterator. + * `(n size)`: The number of steps to advance. + + + +#### `-` + +Linkage: `extern` +Returns: `(Iterator (Vector T))` +Parameters: + + * `(iter1 (Iterator (Vector T)))`: The first iterator. + * `(n size)`: The number of steps by which to move backwards. + + + +#### `distance` + +Linkage: `extern` +Returns: `size` +Parameters: + + * `(iter1 (Iterator (Vector T)))`: The first iterator. + * `(iter2 (Iterator (Vector T)))`: The second iterator. + + +Return the distance between the two iterators. + + +#### `rbegin` + +Linkage: `extern` +Returns: `(ReverseIterator (Vector T))` +Parameters: + + * `(vec (ref (Vector T)))`: A vector reference. + + +Returns the iterator for the last vector element. + + +#### `rend` + +Linkage: `extern` +Returns: `(ReverseIterator (Vector T))` +Parameters: + + * `(vec (ref (Vector T)))`: A vector reference. + + +Returns the iterator representing the beginning of the vector +(sentinel). + + +#### `insert` + +Linkage: `extern` +Returns: `(Iterator (Vector T))` +Parameters: + + * `(unused (ref (const (Vector T))))`: The vector reference. + * `(iter (Iterator (Vector T)))`: The iterator for the position. + * `(value T)`: The new value. + + +Inserts a new element into the vector before the specified position, +and returns the iterator for the new element. + + +#### `erase` + +Linkage: `extern` +Returns: `(Iterator (Vector T))` +Parameters: + + * `(unused (ref (const (Vector T))))`: The vector reference. + * `(iter (Iterator (Vector T)))`: The iterator for the position. + + +Remove the element at the specified position from the vector. + + +#### `clear` + +Linkage: `extern` +Returns: `bool` +Parameters: + + * `(vecp (ref (Vector T)))`: The vector reference. + + +Remove all of the elements from the vector. + + +#### `swap` + +Linkage: `extern` +Returns: `void` +Parameters: + + * `(vec1 (ref (Vector T)))`: The first vector reference. + * `(vec2 (ref (Vector T)))`: The second vector reference. + + + + + +### Concept macros + +#### `Vector` + +Linkage: `extern` +Parameters: + + * `(T MoveConstructible)`: The type node. + + +Expands to a `Vector` definition over the relevant type. If `T` +implements `EqualityComparable` and/or `LessThanComparable`, the +new vector type will implement them as well. + + + + +### Macros + +#### `Vector` + +Linkage: `extern` +Parameters: + + * `T`: The type node. + + +Expands to the concrete type name of the `Vector` generated by way of +the concept macro. + + +#### `value-type` + +Linkage: `extern` +Parameters: + + * `(vecp (p (Vector T)))`: A type node. + + +Expands to the underlying value type (i.e. `T`) of the vector. +This only uses the type node for dispatch purposes, so it's safe +to call this with e.g. `(nullptr (Vector T))` as the argument. + + +#### `size-type` + +Linkage: `extern` +Parameters: + + * `(vecp (p (Vector T)))`: A type node. + + +Expands to the underlying size type of the vector. + + +#### `difference-type` + +Linkage: `extern` +Parameters: + + * `(vecp (p (Vector T)))`: A type node. + + +Expands to the underlying iterator difference type of the vector. + + +#### `value-type` + +Linkage: `extern` +Parameters: + + * `(veciter (p (Iterator (Vector T))))`: A type node. + + +Expands to the underlying value type (i.e. `T`) of the iterator. + + +#### `distance-type` + +Linkage: `extern` +Parameters: + + * `(veciter (p (Iterator (Vector T))))`: A type node. + + +Expands to the underlying distance type of the iterator. + + +[Previous](./2-13-list.md) | [Next](./2-15-set.md) + diff --git a/doc/2-15-set.md b/doc/2-15-set.md new file mode 100644 index 00000000..4d7a4d2f --- /dev/null +++ b/doc/2-15-set.md @@ -0,0 +1,418 @@ +# Dale + +[Previous](./2-14-vector.md) | [Next](./2-16-map.md) + +## 2.15 set + +### Details + +Module: set + +### Description + +Concept macro for a set. Apart from the `Set` macro and concept macro, +the documentation in this module is for a generated set instance of +type `T`. + +All of the functions that take `Iterator` arguments are defined for +`ReverseIterator`s as well, notwithstanding that there is no +documentation for those instances. + +The `Set` type implements the following concepts: + + * `SimpleAssociativeContainer`; + * `SortedAssociativeContainer`; and + * `UniqueAssociativeContainer`. + +Its iterators implement `ForwardIterator`. + + + +### Structs + +#### `(Set T)` + +Linkage: `extern` +Members: N/A + +The core set structure type. + + +#### `(Iterator (Set T))` + +Linkage: `extern` +Members: + + * `(setp (p (Set T)))` + * `(element (p nodetypenode))` + + + +#### `(ReverseIterator (Set T))` + +Linkage: `extern` +Members: + + * `(element (p nodetypenode))` + * `(setp (p (Set T)))` + + + + + +### Functions + +#### `init` + +Linkage: `extern` +Returns: `bool` +Parameters: + + * `(setp (ref typenode))`: A set reference. + + +Initialise a set. + + +#### `empty` + +Linkage: `extern` +Returns: `bool` +Parameters: + + * `(setp (ref (const (Set T))))`: A set reference. + + +Determine whether the set is empty. + + +#### `max-size` + +Linkage: `extern` +Returns: `size` +Parameters: + + * `(setp (ref (const (Set T))))`: A set reference. + + +Returns the number of elements that can be accommodated by the +set. + + +#### `end` + +Linkage: `extern` +Returns: `(Iterator (Set T))` +Parameters: + + * `(setp (ref (Set T)))`: A set reference. + + +Returns the iterator representing the end of the set (sentinel). + + +#### `begin` + +Linkage: `extern` +Returns: `(Iterator (Set T))` +Parameters: + + * `(setp (ref (Set T)))`: A set reference. + + +Returns the iterator for the first set element. + + +#### `source` + +Linkage: `extern` +Returns: `(p T)` +Parameters: + + * `(iter (Iterator (Set T)))`: An iterator. + + +Returns a pointer to the iterator's value. + + +#### `successor` + +Linkage: `extern` +Returns: `(Iterator (Set T))` +Parameters: + + * `(iter (Iterator (Set T)))`: An iterator. + + +Returns the iterator for the position that follows the argument +iterator. + + +#### `=` + +Linkage: `extern` +Returns: `bool` +Parameters: + + * `(iter1 (Iterator (Set T)))`: The first iterator. + * `(iter2 (Iterator (Set T)))`: The second iterator. + + + +#### `<` + +Linkage: `extern` +Returns: `bool` +Parameters: + + * `(iter1 (Iterator (Set T)))`: The first iterator. + * `(iter2 (Iterator (Set T)))`: The second iterator. + + + +#### `rend` + +Linkage: `extern` +Returns: `(ReverseIterator (Set T))` +Parameters: + + * `(setp (ref (Set T)))`: A set reference. + + +Returns the iterator representing the beginning of the set (sentinel). + + +#### `rbegin` + +Linkage: `extern` +Returns: `(ReverseIterator (Set T))` +Parameters: + + * `(setp (ref (Set T)))`: A set reference. + + +Returns the iterator for the last set element. + + +#### `insert` + +Linkage: `extern` +Returns: `bool` +Parameters: + + * `(setp (ref (Set T)))`: A set reference. + * `(newval T)`: The value to insert into the set. + + +Insert a new element into the set. + + +#### `find` + +Linkage: `extern` +Returns: `(Iterator (Set T))` +Parameters: + + * `(setp (ref (Set T)))`: A set reference. + * `(value T)`: The value to find in the set. + + +Find an element within the set, and return the iterator for its +position. + + +#### `erase` + +Linkage: `extern` +Returns: `bool` +Parameters: + + * `(iter (Iterator (Set T)))`: The iterator. + + +Erase an element from the set, by specifying the iterator for its +position. + + +#### `erase` + +Linkage: `extern` +Returns: `bool` +Parameters: + + * `(setp (ref (Set T)))`: A set reference. + * `(v T)`: The value to remove from the set. + + +Erase an element from the set, by value. + + +#### `lower-bound` + +Linkage: `extern` +Returns: `(Iterator (Set T))` +Parameters: + + * `(setp (ref (Set T)))`: A set reference. + * `(value T)`: The value for which the lower bound should be found. + + +Find the lower bound for a given value. + + +#### `upper-bound` + +Linkage: `extern` +Returns: `(Iterator (Set T))` +Parameters: + + * `(setp (ref (Set T)))`: A set reference. + * `(value T)`: The value for which the upper bound should be found. + + +Find the upper bound for a given value. + + +#### `count` + +Linkage: `extern` +Returns: `size` +Parameters: + + * `(setp (ref (Set T)))`: A set reference. + * `(v T)`: The value for which the count should be determined. + + +Return the number of times that the value appears in the set. For +a `UniqueAssociativeContainer` such as `Set`, this can only return +1 or 0, depending on whether the element is present in the set. + + +#### `size` + +Linkage: `extern` +Returns: `size` +Parameters: + + * `(setp (ref (Set T)))`: A set reference. + + +Return the number of elements in the set. + + +#### `clear` + +Linkage: `extern` +Returns: `void` +Parameters: + + * `(setp (ref (Set T)))`: The set reference. + + +Remove all of the elements from the set. + + +#### `swap` + +Linkage: `extern` +Returns: `void` +Parameters: + + * `(set1 (ref (Set T)))`: The first set reference. + * `(set2 (ref (Set T)))`: The second set reference. + + + + + +### Concept macros + +#### `Set` + +Linkage: `N/A` +Parameters: + + * `T`: The type node. + + +Expands to a `Set` definition over the relevant type. Note that `T` +must also implement `LessThanComparable`. + + + + +### Macros + +#### `Set` + +Linkage: `extern` +Parameters: + + * `T`: The type node. + + +Expands to the concrete type name of the `Set` generated by way of +the concept macro. + + +#### `value-type` + +Linkage: `extern` +Parameters: + + * `(setp (p (Set T)))`: A type node. + + +Expands to the underlying value type (i.e. `T`) of the set. This +only uses the type node for dispatch purposes, so it's safe to +call this with e.g. `(nullptr (Set T))` as the argument. + + +#### `key-type` + +Linkage: `extern` +Parameters: + + * `(setp (p (Set T)))`: A type node. + + +Expands to the underlying key type of the set. Since `Set` is a +`SimpleAssociativeContainer`, this returns the same type as +`value-type`. + + +#### `size-type` + +Linkage: `extern` +Parameters: + + * `(setp (p (Set T)))`: A type node. + + +Expands to the underlying size type of the set. + + +#### `difference-type` + +Linkage: `extern` +Parameters: + + * `(setp (p (Set T)))`: A type node. + + +Expands to the underlying iterator difference type of the set. + + +#### `value-type` + +Linkage: `extern` +Parameters: + + * `(setiter (p (Iterator (Set T))))`: A type node. + + +Expands to the underlying value type (i.e. `T`) of the iterator. + + +[Previous](./2-14-vector.md) | [Next](./2-16-map.md) + diff --git a/doc/2-16-map.md b/doc/2-16-map.md new file mode 100644 index 00000000..9a0a7d5b --- /dev/null +++ b/doc/2-16-map.md @@ -0,0 +1,433 @@ +# Dale + +[Previous](./2-15-set.md) | [Next](./2-17-array.md) + +## 2.16 map + +### Details + +Module: map + +### Description + +Concept macro for a map. Apart from the `Map` macro and concept macro, +the documentation in this module is for a generated set instance +mapping from type `Tk` to type `Tv`. + +All of the functions that take `Iterator` arguments are defined for +`ReverseIterator`s as well, notwithstanding that there is no +documentation for those instances. + +The `Map` type implements the following concepts: + + * `PairAssociativeContainer`; + * `SortedAssociativeContainer`; and + * `UniqueAssociativeContainer`. + +Its iterators implement `ForwardIterator`. + + + +### Structs + +#### `(Map Tk Tv)` + +Linkage: `extern` +Members: N/A + +The core map structure type. + + +#### `(Iterator (Map Tk) (Map Tv))` + +Linkage: `extern` +Members: N/A + + +#### `(ReverseIterator (Map Tk Tv))` + +Linkage: `extern` +Members: + + * `(mapp (p (Map Tk Tv)))` + * `(setiter (ReverseIterator (Set (value-type (nullptr (Map Tk Tv))))))` + + + + + +### Functions + +#### `init` + +Linkage: `extern` +Returns: `bool` +Parameters: + + * `(mapp (ref (Map Tk Tv)))`: A map reference. + + +Initialise a map. + + +#### `size` + +Linkage: `extern` +Returns: `size` +Parameters: + + * `(mapp (ref (Map Tk Tv)))`: A map reference. + + +Return the number of elements in the map. + + +#### `max-size` + +Linkage: `extern` +Returns: `size` +Parameters: + + * `(mapp (ref (const (Map Tk Tv))))`: A map reference. + + +Returns the number of elements that can be accommodated by the +map. + + +#### `empty` + +Linkage: `extern` +Returns: `bool` +Parameters: + + * `(mapp (ref (const (Map Tk Tv))))`: A map reference. + + +Determine whether the map is empty. + + +#### `end` + +Linkage: `extern` +Returns: `(Iterator (Map Tk Tv))` +Parameters: + + * `(mapp (ref (Map Tk Tv)))`: A map reference. + + +Returns the iterator representing the end of the map (sentinel). + + +#### `begin` + +Linkage: `extern` +Returns: `(Iterator (Map Tk Tv))` +Parameters: + + * `(mapp (ref (Map Tk Tv)))`: A map reference. + + +Returns the iterator for the first map element. + + +#### `source` + +Linkage: `extern` +Returns: `(p (value-type (nullptr (Map Tk Tv))))` +Parameters: + + * `(iter (Iterator (Map Tk Tv)))`: An iterator. + + +Returns a pointer to the iterator's value. + + +#### `successor` + +Linkage: `extern` +Returns: `(Iterator (Map Tk Tv))` +Parameters: + + * `(iter (Iterator (Map Tk Tv)))`: An iterator. + + +Returns the iterator for the position that follows the argument +iterator. + + +#### `=` + +Linkage: `extern` +Returns: `bool` +Parameters: + + * `(a (Iterator (Map Tk Tv)))`: The first iterator. + * `(b (Iterator (Map Tk Tv)))`: The second iterator. + + + +#### `<` + +Linkage: `extern` +Returns: `bool` +Parameters: + + * `(a (Iterator (Map Tk Tv)))`: The first iterator. + * `(b (Iterator (Map Tk Tv)))`: The second iterator. + + + +#### `rend` + +Linkage: `extern` +Returns: `(ReverseIterator (Map Tk Tv))` +Parameters: + + * `(mapp (ref (Map Tk Tv)))`: A map reference. + + +Returns the iterator representing the beginning of the map (sentinel). + + +#### `rbegin` + +Linkage: `extern` +Returns: `(ReverseIterator (Map Tk Tv))` +Parameters: + + * `(mapp (ref (Map Tk Tv)))`: A map reference. + + +Returns the iterator for the last map element. + + +#### `clear` + +Linkage: `extern` +Returns: `void` +Parameters: + + * `(mapp (ref (Map Tk Tv)))`: The map reference. + + +Remove all of the elements from the map. + + +#### `insert` + +Linkage: `extern` +Returns: `bool` +Parameters: + + * `(mapp (ref (Map Tk Tv)))`: A map reference. + * `(valt (value-type (nullptr (Map Tk Tv))))`: The value to insert into the map. + + +Insert a new element into the map. + + +#### `insert` + +Linkage: `extern` +Returns: `bool` +Parameters: + + * `(mapp (ref (Map Tk Tv)))`: A map reference. + * `(key Tk)`: The key for the new map element. + * `(value Tv)`: The value for the new map element. + + +Insert a new element into the map. + + +#### `find` + +Linkage: `extern` +Returns: `(Iterator (Map Tk Tv))` +Parameters: + + * `(mapp (ref (Map Tk Tv)))`: A map reference. + * `(key Tk)`: The value to find in the set. + + +Find an element within the map, and return the iterator for its +position. + + +#### `erase` + +Linkage: `extern` +Returns: `bool` +Parameters: + + * `(iter (Iterator (Map Tk Tv)))`: The iterator. + + +Erase an element from the map, by specifying the iterator for its +position. + + +#### `erase` + +Linkage: `extern` +Returns: `bool` +Parameters: + + * `(mapp (ref (Map Tk Tv)))`: A map reference. + * `(key Tk)`: The value to remove from the set. + + +Erase an element from the map by value. + + +#### `count` + +Linkage: `extern` +Returns: `size` +Parameters: + + * `(mapp (ref (Map Tk Tv)))`: A map reference. + * `(key Tk)`: The value for which the count should be determined. + + +Return the number of times that the value appears in the map. For +a `UniqueAssociativeContainer` such as `Map`, this can only return +1 or 0, depending on whether the element is present in the set. + + +#### `lower-bound` + +Linkage: `extern` +Returns: `(Iterator (Map Tk Tv))` +Parameters: + + * `(mapp (ref (Map Tk Tv)))`: A map reference. + * `(key Tk)`: The value for which the lower bound should be found. + + +Find the lower bound for a given value. + + +#### `upper-bound` + +Linkage: `extern` +Returns: `(Iterator (Map Tk Tv))` +Parameters: + + * `(mapp (ref (Map Tk Tv)))`: A map reference. + * `(key Tk)`: The value for which the upper bound should be found. + + +Find the upper bound for a given value. + + + + +### Concept macros + +#### `Map` + +Linkage: `extern` +Parameters: + + * `(Tk EqualityComparable)`: The key type node. + * `(Tv Type)`: The value type node. + + +Expands to a `Set` definition over the relevant type. Note that `Tk` +must also implement `LessThanComparable`. + + + + +### Macros + +#### `Map` + +Linkage: `extern` +Parameters: + + * `Tk`: The key type node. + * `Tv`: The value type node. + + +Expands to the concrete type name of the `Map` generated by way of +the concept macro. + + +#### `key-type` + +Linkage: `extern` +Parameters: + + * `(mapp (p (Map Tk Tv)))`: A type node. + + +Expands to the underlying key type of the map (i.e. `Tk`). This +only uses the type node for dispatch purposes, so it's safe to +call this with e.g. `(nullptr (Map Tk Tv))` as the argument. + + +#### `data-type` + +Linkage: `extern` +Parameters: + + * `(mapp (p (Map Tk Tv)))`: A type node. + + +Expands to the underlying data type (i.e. `Tv`) of the map. + + +#### `value-type` + +Linkage: `extern` +Parameters: + + * `(mapp (p (Map Tk Tv)))`: A type node. + + +Expands to the underlying value type of the set. Note that for +maps, the value type is a specially-constructed pair type that is +not otherwise accessible. However, it is guaranteed to be a struct +that has the members `first` and `second`, with those members +mapping to `Tk` and `Tv` respectively. + + +#### `size-type` + +Linkage: `extern` +Parameters: + + * `(mapp (p (Map Tk Tv)))`: A type node. + + +Expands to the underlying size type of the map. + + +#### `difference-type` + +Linkage: `extern` +Parameters: + + * `(mapp (p (Map Tk Tv)))`: A type node. + + +Expands to the underlying iterator difference type of the map. + + +#### `value-type` + +Linkage: `extern` +Parameters: + + * `(mapiter (p (Iterator (Map Tk Tv))))`: A type node. + + +Expands to the underlying value type of the iterator. This is the +same as that of `value-type` for the container. + + +[Previous](./2-15-set.md) | [Next](./2-17-array.md) + diff --git a/doc/2-17-array.md b/doc/2-17-array.md new file mode 100644 index 00000000..cd2fdf14 --- /dev/null +++ b/doc/2-17-array.md @@ -0,0 +1,396 @@ +# Dale + +[Previous](./2-16-map.md) | [Next](./2-18-shared-ptr.md) + +## 2.17 array + +### Details + +Module: array + +### Description + +Concept macro for a fixed-size container. Apart from the `Array` macro +and concept macro, the documentation in this module is for a generated +array instance of type `T`, with size `N`. + +All of the functions that take `Iterator` arguments are defined for +`ReverseIterator`s as well, notwithstanding that there is no +documentation for those instances. + +The `Array` type implements `RandomAccessContainer`. Its iterators +implement `OutputIterator` and `RandomAccessIterator`. + + +### Structs + +#### `(Array T N)` + +Linkage: `extern` +Members: + + * `(elements (array-of N T))` + + +The core array structure type. + + +#### `(Iterator (Array T N))` + +Linkage: `extern` +Members: + + * `(element (p T))` + * `(arrp (p (Array T N)))` + + + +#### `(ReverseIterator (Array T N))` + +Linkage: `extern` +Members: + + * `(element (p T))` + * `(arrp (p (Array T N)))` + + + + + +### Functions + +#### `init` + +Linkage: `extern` +Returns: `bool` +Parameters: + + * `(arrp (ref (Array T N)))`: An array reference. + + +Initialise an array. (This is a no-op for this container: to +actually zero the array, it is necessary to iterate over it and +set values accordingly.) + + +#### `empty` + +Linkage: `extern` +Returns: `bool` +Parameters: + + * `(arrp (ref (const (Array T N))))`: An array reference. + + +Determine whether the array is empty. (Since arrays have a fixed +size, this will always return true, unless the array actually has +a size of zero.) + + +#### `size` + +Linkage: `extern` +Returns: `size` +Parameters: + + * `(arrp (ref (const (Array T N))))`: An array reference. + + +Returns the number of elements in the array (This is `N`, for all +instances of the array.) + + +#### `max-size` + +Linkage: `extern` +Returns: `size` +Parameters: + + * `(arrp (ref (const (Array T N))))`: An array reference. + + +Returns the number of elements that can be accommodated by the +array. (This is also `N`, for all instances of the array.) + + +#### `begin` + +Linkage: `extern` +Returns: `(Iterator (Array T N))` +Parameters: + + * `(arrp (ref (Array T N)))`: An array reference. + + +Returns the iterator for the first array element. + + +#### `end` + +Linkage: `extern` +Returns: `(Iterator (Array T N))` +Parameters: + + * `(arrp (ref (Array T N)))`: An array reference. + + +Returns the iterator representing the end of the list (sentinel). + + +#### `source` + +Linkage: `extern` +Returns: `(p T)` +Parameters: + + * `(iter (Iterator (Array T N)))`: An iterator. + + +Returns a pointer to the iterator's value. + + +#### `sink` + +Linkage: `extern` +Returns: `bool` +Parameters: + + * `(iter (Iterator (Array T N)))`: An iterator. + * `(v T)`: The new value. + + +Set the given value at the specified position in the list. + + +#### `successor` + +Linkage: `extern` +Returns: `(Iterator (Array T N))` +Parameters: + + * `(iter (Iterator (Array T N)))`: An iterator. + + +Returns the iterator for the position that follows the argument +iterator. + + +#### `predecessor` + +Linkage: `extern` +Returns: `(Iterator (Array T N))` +Parameters: + + * `(iter (Iterator (Array T N)))`: An iterator. + + +Returns the iterator for the position just before the argument +iterator. + + +#### `=` + +Linkage: `extern` +Returns: `bool` +Parameters: + + * `(iter1 (Iterator (Array T N)))`: The first iterator. + * `(iter2 (Iterator (Array T N)))`: The second iterator. + + + +#### `<` + +Linkage: `extern` +Returns: `bool` +Parameters: + + * `(iter1 (Iterator (Array T N)))`: The first iterator. + * `(iter2 (Iterator (Array T N)))`: The second iterator. + + + +#### `+` + +Linkage: `extern` +Returns: `(Iterator (Array T N))` +Parameters: + + * `(iter (Iterator (Array T N)))`: An array iterator. + * `(n size)`: The number of steps forward. + + + +#### `-` + +Linkage: `extern` +Returns: `(Iterator (Array T N))` +Parameters: + + * `(iter (Iterator (Array T N)))`: An array iterator. + * `(n size)`: The number of steps backward. + + + +#### `rbegin` + +Linkage: `extern` +Returns: `(ReverseIterator (Array T N))` +Parameters: + + * `(arrp (ref (Array T N)))`: An array reference. + + +Returns the iterator for the last array element. + + +#### `rend` + +Linkage: `extern` +Returns: `(ReverseIterator (Array T N))` +Parameters: + + * `(arrp (ref (Array T N)))`: An array reference. + + +Returns the iterator representing the beginning of the array (sentinel). + + +#### `front` + +Linkage: `extern` +Returns: `(p T)` +Parameters: + + * `(arrp (ref (Array T N)))`: An array reference. + + +Returns a pointer to the value of the first element in the array. + + +#### `back` + +Linkage: `extern` +Returns: `(p T)` +Parameters: + + * `(arrp (ref (Array T N)))`: An array reference. + + +Returns a pointer to the value of the last element in the array. + + +#### `$` + +Linkage: `extern` +Returns: `(p T)` +Parameters: + + * `(arrp (ref (Array T N)))`: An array reference. + * `(index int)`: The index of the element. + + + +#### `$` + +Linkage: `extern` +Returns: `(p T)` +Parameters: + + * `(arrp (ref (Array T N)))`: An array reference. + * `(index size)`: The index of the element. + + + + + +### Concept macros + +#### `Array` + +Linkage: `extern` +Parameters: + + * `(T Type)`: The type for the elements of the array. + * `(N Value)`: The length of the array. + + +Expands to an `Array` definition over the relevant type. + + + + +### Macros + +#### `Array` + +Linkage: `extern` +Parameters: + + * `T`: The type node. + * `N` + + +Expands to the concrete type name of the `Array` generated by way of +the concept macro. + + +#### `value-type` + +Linkage: `extern` +Parameters: + + * `(arrp (p (Array T N)))`: An array pointer. + + +Expands to the underlying value type (i.e. `T`) of the array. This +only uses the type node for dispatch purposes, so it's safe to +call this with e.g. `(nullptr (Array T N))` as the argument. + + +#### `size-type` + +Linkage: `extern` +Parameters: + + * `(arrp (p (Array T N)))`: A type node. + + +Expands to the underlying size type of the array. + + +#### `difference-type` + +Linkage: `extern` +Parameters: + + * `(arrp (p (Array T N)))`: A type node. + + +Expands to the underlying iterator difference type of the array. + + +#### `value-type` + +Linkage: `extern` +Parameters: + + * `(iterp (p (Iterator (Array T N))))`: An iterator pointer. + + +Expands to the underlying value type (i.e. `T`) of the iterator. + + +#### `distance-type` + +Linkage: `extern` +Parameters: + + * `(iterp (p (Iterator (Array T N))))`: An iterator pointer. + + +Expands to the underlying distance type of the iterator. + + +[Previous](./2-16-map.md) | [Next](./2-18-shared-ptr.md) + diff --git a/doc/2-18-shared-ptr.md b/doc/2-18-shared-ptr.md new file mode 100644 index 00000000..d64d0011 --- /dev/null +++ b/doc/2-18-shared-ptr.md @@ -0,0 +1,118 @@ +# Dale + +[Previous](./2-17-array.md) | [Next](./2-19-unique-ptr.md) + +## 2.18 shared-ptr + +### Details + +Module: shared-ptr + +### Description + +A simple shared pointer module. Apart from the `SharedPtr` macro and +concept macro, the documentation in this module is for a generated +shared pointer instance of type `T`. + + + +### Structs + +#### `(SharedPtr T)` + +Linkage: `N/A` +Members: N/A + +The core shared pointer structure type. + + + + +### Functions + +#### `init` + +Linkage: `extern` +Returns: `bool` +Parameters: + + * `(loc (ref (SharedPtr T)))`: The shared pointer. + * `(value (p T))`: The value to assign to the shared pointer. + + +Initialise the shared pointer structure with a pointer. Once the +structure has been initialised with the pointer, it takes +ownership of it. The structure assumes that the pointer was +created by way of malloc. + + +#### `init` + +Linkage: `extern` +Returns: `bool` +Parameters: + + * `(loc (ref (SharedPtr T)))`: The shared pointer. + + +Initialise an empty/null shared pointer structure. + + +#### `get` + +Linkage: `extern` +Returns: `(p T)` +Parameters: + + * `(mloc (SharedPtr T))`: The shared pointer. + + +Returns the underlying pointer. + + +#### `@` + +Linkage: `extern` +Returns: `T` +Parameters: + + * `(mloc (SharedPtr T))`: The shared pointer. + + +Dereferencing the shared pointer returns the value from the +underlying pointer. + + + + +### Concept macros + +#### `SharedPtr` + +Linkage: `extern` +Parameters: + + * `(T Type)`: The type node. + + +Expands to a `SharedPtr` definition over the relevant type. + + + + +### Macros + +#### `SharedPtr` + +Linkage: `extern` +Parameters: + + * `T`: The type node. + + +Expands to the concrete type name of the `SharedPtr` generated by way +of the concept macro. + + +[Previous](./2-17-array.md) | [Next](./2-19-unique-ptr.md) + diff --git a/doc/2-19-unique-ptr.md b/doc/2-19-unique-ptr.md new file mode 100644 index 00000000..a51fd0c7 --- /dev/null +++ b/doc/2-19-unique-ptr.md @@ -0,0 +1,118 @@ +# Dale + +[Previous](./2-18-shared-ptr.md) | [Next](./2-20-operator-macros.md) + +## 2.19 unique-ptr + +### Details + +Module: unique-ptr + +### Description + +A unique pointer module. Apart from the `UniquePtr` macro and concept +macro, the documentation in this module is for a generated unique +pointer instance of type `T`. + + + +### Structs + +#### `(UniquePtr T)` + +Linkage: `N/A` +Members: N/A + +The core unique pointer structure type. + + + + +### Functions + +#### `init` + +Linkage: `extern` +Returns: `bool` +Parameters: + + * `(loc (ref (UniquePtr T)))`: The unique pointer. + * `(value (p T))`: The value to assign to the unique pointer. + + +Initialise the unique pointer structure with a pointer. Once the +structure has been initialised with the pointer, it takes +ownership of it. The structure assumes that the pointer was +created by way of malloc. + + +#### `init` + +Linkage: `extern` +Returns: `bool` +Parameters: + + * `(loc (ref (UniquePtr T)))`: The unique pointer. + + +Initialise an empty/null unique pointer structure. + + +#### `get` + +Linkage: `extern` +Returns: `(p T)` +Parameters: + + * `(mloc (ref (UniquePtr T)))`: The unique pointer. + + +Returns the underlying pointer. + + +#### `@` + +Linkage: `extern` +Returns: `T` +Parameters: + + * `(mloc (ref (UniquePtr T)))`: The unique pointer. + + +Dereferencing the unique pointer returns the value from the +underlying pointer. + + + + +### Concept macros + +#### `UniquePtr` + +Linkage: `extern` +Parameters: + + * `(T Type)`: The type node. + + +Expands to a `UniquePtr` definition over the relevant type. + + + + +### Macros + +#### `UniquePtr` + +Linkage: `extern` +Parameters: + + * `T`: The type node. + + +Expands to the concrete type name of the `UniquePtr` generated by way +of the concept macro. + + +[Previous](./2-18-shared-ptr.md) | [Next](./2-20-operator-macros.md) + diff --git a/doc/2-20-operator-macros.md b/doc/2-20-operator-macros.md new file mode 100644 index 00000000..52b1fdb8 --- /dev/null +++ b/doc/2-20-operator-macros.md @@ -0,0 +1,90 @@ +# Dale + +[Previous](./2-19-unique-ptr.md) | [Next](./2-21-bitset-enum.md) + +## 2.20 operator-macros + +### Details + +Module: operator-macros + +### Description + +Provides utilities to generate operators that accept an arbitrary +number of arguments. Such operators are already defined for the +following operators: + + - arithmetic operators: `+ - * / +' -' *' /'` + - bitwise and logical or: `& | and or` + - arithmetic relations: `< <= = => > <' <=' =' =>' >' + + +### Macros + +#### `std.macros.def-identity-macro` + +Linkage: `extern` +Parameters: + + * `name`: Name of the macro. + * `linkage`: Linkage. + + +Defines a macro that takes a single argument and returns it. + + +#### `std.macros.def-right-associative-macro` + +Linkage: `extern` +Parameters: + + * `name`: Name of the macro. + * `linkage`: Linkage. + * `opname`: Optional, defaults to `name` + + +Defines a macro: +`(name a b rest) will be expanded to `(opname a (name b rest))` + + +#### `std.macros.def-left-associative-macro` + +Linkage: `extern` +Parameters: + + * `name`: Name of the macro. + * `linkage`: Linkage. + * `opname`: Optional, defaults to `name` + + +Defines a macro: +`(name a b rest)` will be expanded to `(name (opname a b) rest)` + + +#### `def-transitive-macro` + +Linkage: `extern` +Parameters: + + * `name`: The macro name. + * `linkage`: Linkage. + * `fn`: The name of the binary function. Defaults to name. + + +Defines a macro for transitive binary functions (that normally should +return bool and transitive), so that you don't have to use variables +twice when you want to test some function. + +For example: + + (def-transitive-macro < intern) + (< 0.0 x 1.0) + +expands to: + + (and (< 0.0 x) (< x 1.0)) + + + +[Previous](./2-19-unique-ptr.md) | [Next](./2-21-bitset-enum.md) + diff --git a/doc/2-21-bitset-enum.md b/doc/2-21-bitset-enum.md new file mode 100644 index 00000000..a1b2af4b --- /dev/null +++ b/doc/2-21-bitset-enum.md @@ -0,0 +1,49 @@ +# Dale + +[Previous](./2-20-operator-macros.md) | [Next](./2-22-variant.md) + +## 2.21 bitset-enum + +### Details + +Module: bitset-enum + +### Description + +Provides `def-bitset-enum`, which allows for defining bitset enums. +These operate in the same way as normal enums, except that the +sequence goes 0, 1, 2, 4, ..., with each successive value being twice +that of the previous one. For example, + + (def-bitset-enum my-enum intern int (a b c d)) + +expands to: + + (def-enum my-enum intern int ((a 0) (b 1) (c 2) (d 4))) + +and + + (def-bitset-enum my-enum intern int ((a 0x2) b c d)) + +expands to: + + (def-enum my-enum intern int ((a 0x2) (b 0x4) (c 0x8) (d 0x10))) + + + +### Macros + +#### `def-bitset-enum` + +Linkage: `extern` +Parameters: + + * `name`: The name of the new enum. + * `linkage`: The linkage for the new enum. + * `type`: The type for the new enum. + * `forms`: The elements for the new enum. + + + +[Previous](./2-20-operator-macros.md) | [Next](./2-22-variant.md) + diff --git a/doc/2-22-variant.md b/doc/2-22-variant.md new file mode 100644 index 00000000..20cc163e --- /dev/null +++ b/doc/2-22-variant.md @@ -0,0 +1,84 @@ +# Dale + +[Previous](./2-21-bitset-enum.md) | [Next](./3-1-cerrno.md) + +## 2.22 variant + +### Details + +Module: variant + +### Description + +Provides `def-variant`, which allows for defining variants, also known +as sum types or tagged unions. Variant definition introduces the +following bindings: + + * a struct type for the variant; + * a struct type for each of the variant's potential types; + * constructors for each of the potential types, which take as their + arguments the members for that potential type in definition + order (if any); + * a `case` form, which allows for executing a statement based on + the underlying type of a particular variant. + +For example: + + (def-variant Direction (North South East West)) + + (def main (fn extern-c int (void) + (let ((direction Direction (North))) + (case direction + (North (printf "Direction is north\n")) + (true (printf "Direction is not north\n")))) + 0)) + +yields: + + Direction is north + +With parameters for the potential types: + + (def-variant Number ((Int ((a int))) + (Float ((a float))))) + + (def main (fn extern-c int (void) + (let ((ni Number (Int 1)) + (nf Number (Float 2.0)) + (na (array-of 2 Number) (array ni nf))) + (for (i \ 0) (< i 2) (incv i) + (let ((nc Number (@$ na i))) + (case nc + (Int (printf "Number is int (%d)\n" (@:@ nc a))) + (Float (printf "Number is float (%f)\n" (@:@ nc a))))))) + 0)) + +yields: + + Number is int (1) + Number is float (2.000000) + +The first element of each defined struct type is an `int` named +'type'. This value will be 1 for the first potential type, 2 for the +second potential type, and so on. This is a documented part of this +interface so as to support interoperating with C libraries that use +unions to achieve the same outcome. (At the moment, there's no need +for customising the type of this first field, but that may be added +later.) + + + +### Macros + +#### `def-variant` + +Linkage: `extern` +Parameters: + + * `name`: The name of the new variant. + * `instances`: The type definitions for the variant. + + + +[Previous](./2-21-bitset-enum.md) | [Next](./3-1-cerrno.md) + diff --git a/doc/2-3-math.md b/doc/2-3-math.md index 53f6d4f0..db24511e 100644 --- a/doc/2-3-math.md +++ b/doc/2-3-math.md @@ -1,6 +1,6 @@ # Dale -[Previous](./2-2-ctype.md) | [Next](./2-4-macros-core.md) +[Previous](./2-2-ctype.md) | [Next](./2-4-macros.md) ## 2.3 math @@ -34,5 +34,5 @@ Defines overloaded functions corresponding generally with those from A macro constant for `e` is also provided. -[Previous](./2-2-ctype.md) | [Next](./2-4-macros-core.md) +[Previous](./2-2-ctype.md) | [Next](./2-4-macros.md) diff --git a/doc/2-4-macros-core.md b/doc/2-4-macros.md similarity index 85% rename from doc/2-4-macros-core.md rename to doc/2-4-macros.md index 914634cb..a859c395 100644 --- a/doc/2-4-macros-core.md +++ b/doc/2-4-macros.md @@ -2,18 +2,17 @@ [Previous](./2-3-math.md) | [Next](./2-5-stdlib.md) -## 2.4 macros-core +## 2.4 macros ### Details -Module: macros-core +Module: macros ### Description Provides the core macro development functions: making, copying and -printing nodes, linking nodes together, and gensym functions for -variables and labels. Also provides a 'bootstrap' quasiquotation -function (not intended for use outside the standard libraries). +printing nodes, linking nodes together, gensym functions for +variables and labels, and the quasiquotation form. @@ -489,5 +488,58 @@ Parameters: Simple version of `get-varargs-list`, only takes the count as parameter. +#### `@:'` + +Linkage: `extern` +Parameters: + + * `structp`: The struct pointer argument. + * `member`: The first member's name. + * `rest` + + +Takes a struct pointer and one or more struct member names as its +arguments. Expands to repeated calls to `@:@` over the struct and the +member names. For example, if two members are provided, the expansion +is `(@:@ (@:@ structp member1) member2)`. + + +#### `qq` + +Linkage: `extern` +Parameters: + + * `frm` + * `rest` + + +The 'general-use' quasiquotation macro. The forms handled specially +are: + + * `uq` (unquote): expands to the argument node, excluding any + following nodes (i.e. excluding `next-node`); + * `uql` (unquote-list): expands to the argument node, including all + following nodes (i.e. including `next-node` and any subsequent + `next-node`s of that node); + * `uq-nc` (unquote no-copy): as per `uq`, except that the argument + node is not copied on substitution; and + * `uql-nc` (unquote-list no-copy): as per `uql`, except that the nodes + are not copied on substitution. + +Quasiquotation forms may be nested: each specially-handled form in a +nested `qq` must be wrapped with an additional `uq` for each level of +nesting. + +The `-nc` versions should only be used when the argument node will not +be used again. + +Argument nodes for the various unquote forms must be DNode pointer +variable names. If any other type of argument is provided, the +unquote form will expand to that argument. For example, `(qq do (uq +(mnfv mc 1)))` will expand to `(do (mnfv mc 1))`. Issue #140 is +tracking this problem, and will be resolved when arbitrary argument +nodes are supported. + + [Previous](./2-3-math.md) | [Next](./2-5-stdlib.md) diff --git a/doc/2-5-stdlib.md b/doc/2-5-stdlib.md index a326a8bf..aaaaa8d1 100644 --- a/doc/2-5-stdlib.md +++ b/doc/2-5-stdlib.md @@ -1,6 +1,6 @@ # Dale -[Previous](./2-4-macros-core.md) | [Next](./2-6-macros.md) +[Previous](./2-4-macros.md) | [Next](./2-6-assert.md) ## 2.5 stdlib @@ -18,22 +18,6 @@ provided by this library are in the root namespace. ### Macros -#### `@:'` - -Linkage: `extern` -Parameters: - - * `structp`: The struct pointer argument. - * `member`: The first member's name. - * `rest` - - -Takes a struct pointer and one or more struct member names as its -arguments. Expands to repeated calls to `@:@` over the struct and the -member names. For example, if two members are provided, the expansion -is `(@:@ (@:@ structp member1) member2)`. - - #### `is-valid` Linkage: `extern` @@ -369,5 +353,5 @@ these macros has the same name as the original function, except with a ' symbol appended. -[Previous](./2-4-macros-core.md) | [Next](./2-6-macros.md) +[Previous](./2-4-macros.md) | [Next](./2-6-assert.md) diff --git a/doc/2-6-assert.md b/doc/2-6-assert.md new file mode 100644 index 00000000..59908708 --- /dev/null +++ b/doc/2-6-assert.md @@ -0,0 +1,58 @@ +# Dale + +[Previous](./2-5-stdlib.md) | [Next](./2-7-concepts-core.md) + +## 2.6 assert + +### Details + +Module: assert + +### Description + +Macros for runtime assertions. User-defined compile-time errors can be +reported to the compiler by way of `report-error`, which is defined in +the `introspection` module. + + + +### Macros + +#### `std.disable-assertions` + +Linkage: `extern` +Parameters: N/A + +If called, subsequent calls to `assert` will expand to a no-op. Note +that assertions are enabled by default. + + +#### `std.enable-assertions` + +Linkage: `extern` +Parameters: N/A + +If called, subsequent calls to `assert` will expand to actual +assertions. + + +#### `std.assert` + +Linkage: `extern` +Parameters: + + * `condition`: The condition expression. + + +Expands to a form that tests the condition; if the condition is false, +then an error message is printed to `stderr` and execution is aborted +(via `abort`). The error message will include the filename, line +number and column number of the condition node, as per a normal +compiler error message. + +If assertions have been disabled, by way of `disable-assertions`, then +subsequent calls to this macro will expand to no-ops. + + +[Previous](./2-5-stdlib.md) | [Next](./2-7-concepts-core.md) + diff --git a/doc/2-7-concepts-core.md b/doc/2-7-concepts-core.md new file mode 100644 index 00000000..40123b57 --- /dev/null +++ b/doc/2-7-concepts-core.md @@ -0,0 +1,480 @@ +# Dale + +[Previous](./2-6-assert.md) | [Next](./2-8-concept-defs.md) + +## 2.7 concepts-core + +### Details + +Module: concepts-core + +### Description + +Provides the core functions and macros required for defining and +implementing concepts. The basic concepts are defined in +`concept-defs`, and they are implemented for the basic types in +`concepts`. Each binding in this module is in the `std.concepts` +namespace. + +Concepts are a way in which the requirements of a macro can be +formalised, such that macro authors can depend on certain arguments +satisfying certain conditions. This means that problems are found +before a macro is instantiated, as opposed to after. They also allow +for multiple implementations of a given macro to operate concurrently, +with the specific macro to use being selected based on the concepts +implemented by the macro's arguments. + +Concepts as implemented by this library are a little different from +those proposed from time to time for C++. The concept definitions +themselves are procedures, as opposed to lists of required +methods/attributes, and there is no support for concept maps or +axioms. There is also no facility for a given parameter in a concept +macro to satisfy multiple concepts at the same time, except by way of +a check in the concept definition body proper. (Allowing multiple +concepts per parameter complicates dispatch tremendously when concept +refinements are present.) + +There are many `extern`-scoped functions in this module, but the only +ones that should be used directly are: + + * `exists-concept`; + * `def-concept`; + * `implement`; + * `implements`; and + * `def-concept-macro`. + + + +### Functions + +#### `std.concepts.exists-concept-fn` + +Linkage: `extern` +Returns: `bool` +Parameters: + + * `(mc (p MContext))`: An MContext. + * `(frm (p DNode))`: The node containing the concept name. + + +Determines whether the given concept, as described by the node, has +been defined. + + +#### `std.concepts.implements-fn` + +Linkage: `extern` +Returns: `bool` +Parameters: + + * `(mc (p MContext))`: An MContext. + * `(T (p DNode))`: A type node. + * `(C (p DNode))`: A concept node. + + + +#### `std.concepts.get-node-type-concept-list` + +Linkage: `extern` +Returns: `(p (p char))` +Parameters: + + * `(mc (p MContext))`: An MContext. + * `(T (p DNode))`: A type node. + + +Takes a type DNode as its single argument. Returns a list of char +pointers, each being the name of a concept implemented by this type. +This is recursive, so if the type implements a concept A, which is in +turn a refinement of concept B, the list will includes entries for +both A and B. + + +#### `std.concepts.refines` + +Linkage: `extern` +Returns: `bool` +Parameters: + + * `(mc (p MContext))`: An MContext. + * `(Tupper (p (const char)))`: The possibly-refined type. + * `(Tlower (p (const char)))`: The refining type. + + + +#### `std.concepts.refines-multiple` + +Linkage: `extern` +Returns: `bool` +Parameters: + + * `(mc (p MContext))`: An MContext. + * `(Tupper (p (const char)))`: The possibly-refined type. + * `(Tlower (p (const char)))`: The refining type. + + + +#### `std.concepts.add-refinement` + +Linkage: `extern` +Returns: `void` +Parameters: + + * `(current-cn (p concept-node))`: The current concept node. + * `(refine-cn (p concept-node))`: The refinement concept node. + + + +#### `std.concepts.make-simple-node` + +Linkage: `extern` +Returns: `(p concept-node)` +Parameters: + + * `(mc (p MContext))`: An MContext. + * `(name (p DNode))`: The name of the concept. + + + +#### `std.concepts.dump-concept-map` + +Linkage: `extern` +Returns: `void` +Parameters: + + * `(mc (p MContext))` + * `(mapp (p concept-node))` + * `(mlist bool)` + * `(n int)` + + + +#### `std.concepts.concept-map-to-string` + +Linkage: `extern` +Returns: `void` +Parameters: + + * `(mc (p MContext))` + * `(mapp (p concept-node))` + * `(buf (p char))` + + + +#### `std.concepts.concepts-to-string` + +Linkage: `extern` +Returns: `void` +Parameters: + + * `(mc (p MContext))` + * `(name (p DNode))` + * `(buf (p char))` + + + +#### `std.concepts.get-type-concept-map` + +Linkage: `extern` +Returns: `(p concept-node)` +Parameters: + + * `(mc (p MContext))` + * `(T (p DNode))` + + + +#### `std.concepts.get-concept-macro-name` + +Linkage: `intern` +Returns: `bool` +Parameters: + + * `(mc (p MContext))`: An MContext. + * `(macro-name (p DNode))`: The macro name node. + * `(mt-vl (p DNode))`: The concept macro type. + * `(tnames bool)`: Whether the type is a list or an atom. + * `(buf (p char))`: The buffer for the name. + + + +#### `std.concepts.exists-concept-macro` + +Linkage: `extern` +Returns: `bool` +Parameters: + + * `(mc (p MContext))`: An MContext. + * `(macro-name (p DNode))`: The name of the concept macro. + * `(macro-types (p DNode))`: The types of the concept macro. + + + +#### `std.concepts.all-applicable` + +Linkage: `intern` +Returns: `bool` +Parameters: + + * `(tcl-list (p (p concept-node)))` + * `(tcl-count int)` + + +Returns true if the list of concept nodes does not contain any +instances of "not-applicable" (i.e. of the root, unused concept node). + + +#### `std.concepts.get-candidate-toplevel` + +Linkage: `intern` +Returns: `bool` +Parameters: + + * `(mc (p MContext))` + * `(tcl-list (p (p concept-node)))` + * `(tcl-count int)` + * `(macname (p char))` + * `(macbuf (p char))` + * `(hascnamebuf bool)` + * `(cname (p char))` + + +Checks at the top-level of the concept list for a candidate that +matches the requested macro name. If one exists, writes it to the +macro buffer and returns true. Otherwise, returns false. + + +#### `std.concepts.get-candidate` + +Linkage: `intern` +Returns: `int` +Parameters: + + * `(mc (p MContext))` + * `(errn (p DNode))` + * `(tcl-list (p (p concept-node)))` + * `(tcl-count int)` + * `(arg-cycle int)` + * `(macname (p char))` + * `(macbuf (p char))` + * `(is-error (p int))` + * `(hascnamebuf bool)` + * `(cname (p char))` + + + +#### `std.concepts.is-forced-concept` + +Linkage: `intern` +Returns: `bool` +Parameters: + + * `(node (p DNode))` + + + +#### `std.concepts.validate-forced-concept` + +Linkage: `intern` +Returns: `bool` +Parameters: + + * `(mc (p MContext))` + * `(node (p DNode))` + + + +#### `std.concepts.get-type-concept-list` + +Linkage: `intern` +Returns: `bool` +Parameters: + + * `(mc (p MContext))` + * `(varargs-list (p DNode))` + * `(varargs-count int)` + * `(type-concept-list (p (p concept-node)))` + * `(type-list (p (p DNode)))` + + +Takes a list of concept instantiation arguments, except for the +initial concept name. Populates the type concept list, being the +mapping between the parameter and the concept map for the parameter. + +Most parameters are plain types, for which see get-type-concept-map. +The special processing here is for disambiguation (forcing the use of +a specific concept) and non-types, the latter of which are treated as +being of the Value concept. + + + + +### Macros + +#### `std.concepts.exists-concept` + +Linkage: `extern` +Parameters: + + * `concept-name`: The node containing the concept name. + + +Expands to `true` or `false`, depending on whether the concept, as +described by the argument node, has been defined. + + +#### `std.concepts.def-concept` + +Linkage: `extern` +Parameters: + + * `concept-name-node` + * `refinement-list` + * `type-arguments` + * `rest` + + +Define a new concept. Takes a name, a list of refinements, a list of +parameters and an arbitrary number of forms representing the body of +the concept. + +The list of refinements has the following form: + + (refines {concept-1} {concept-2} ... {concept-N}) + +A concept P 'refines' another concept Q when it must meet the criteria +of Q, as well as certain other criteria. If the concept being defined +does not refine any other concept, then the second argument should be +`(refines)`. Apart from allowing a concept to import the criteria of +another concept, refinements are also used during `instantiate`: the +instantiation that is most-specific with respect to the arguments' +concepts, taking into account their refinements, is the one that is +used. + +The parameter list is as per a macro's parameter list, except that all +of the parameters must be untyped. Currently, a concept may only +accept one parameter. + +The body of the concept must evaluate to a boolean value indicating +whether the specified parameters satisfy the concept. Its environment +is as per a normal macro, so an `mc` is present. + +Concepts, once defined, can be used to 'tag' the parameters to a macro +constructed by way of `def-concept-macro`. + + +#### `std.concepts.implement` + +Linkage: `extern` +Parameters: + + * `concept-name-node` + * `rest` + + +Takes a concept name and a list of type arguments. Attempts to +'implement' the concept for those type arguments, which involves +checking whether the type satisfies the concept's constraints and +marking the type as such if it does. If the type does not satisfy the +constraints, the expansion is a no-op, though note that the concept +body may (generally, will) add errors if its requirements are not met. + + +#### `std.concepts.implements` + +Linkage: `extern` +Parameters: + + * `T`: A type node. + * `C`: A concept node. + + +If the type implements the concept, this is a no-op. Otherwise, it +reports an error about the concept not being implemented. + + +#### `std.concepts.def-concept-macro` + +Linkage: `extern` +Parameters: + + * `macro-name`: The name of the concept macro. + * `linkage`: The linkage of the concept macro. + * `macro-types`: The parameters (typed) for the macro. + * `rest` + + +Define a new concept macro. Takes a name, a linkage type, a list of +macro parameters and an arbitrary number of forms (the body of the +macro) as its parameters. The list of macro parameters is as per a +normally-defined macro, except that each parameter must be 'typed' +with a concept. + +Macros defined by way of this macro are executed by running +`instantiate`. That macro takes care of determining which concept +macro to actually run, based on the concepts implemented by the +arguments. + + +#### `std.concepts.assert-return` + +Linkage: `intern` +Parameters: + + * `error-cond` + * `report-error-node` + * `report-error-str` + + + +#### `std.concepts.assert-return-b` + +Linkage: `intern` +Parameters: + + * `error-cond` + * `report-error-node` + * `report-error-str` + + + +#### `std.concepts.instantiate` + +Linkage: `extern` +Parameters: + + * `macro-name`: The name of the macro to be instantiated. + * `rest` + + +Takes a concept macro name and a series of arguments for that concept +macro as its arguments. Determines the most appropriate concrete +concept macro, based on the provided arguments, and expands into a +call to that macro. The term `instantiate` is used because in nearly +all cases, the concept macro being run is something that in turn +expands into a series of bindings; for example, `Vector`. + +When multiple equally-preferred instantiations are available for a +given call, this will report an error and expand to nothing. +Disambiguation is achieved by way of the `force` form: + + (instantiate MacroName (force ConceptName Type) ...) + +Disambiguation is not required when an argument implements a concept +that refines another concept, and there are instantiations available +for both concepts. In that case, the instantiation for the former +concept will be preferred. + +Each argument to `instantiate` must implement one or more concepts. +If any argument does not, the expansion will fail with the error +message "type does not implement any concepts". See `implement` in +this module for details on how types can be made to implement +concepts. + +If no concept macros that have this name exist, the expansion will +fail with the error "concept not found". This is usually caused by a +missing import statement. + + +[Previous](./2-6-assert.md) | [Next](./2-8-concept-defs.md) + diff --git a/doc/2-8-concept-defs.md b/doc/2-8-concept-defs.md new file mode 100644 index 00000000..29e0e774 --- /dev/null +++ b/doc/2-8-concept-defs.md @@ -0,0 +1,251 @@ +# Dale + +[Previous](./2-7-concepts-core.md) | [Next](./2-9-concepts.md) + +## 2.8 concept-defs + +### Details + +Module: concept-defs + +### Description + +Basic concept definitions. Copied from C++'s STL, for the most part. + + + +### Concepts + +#### `Value` + +Returns true, regardless of the argument. This is mainly useful when a +concept macro needs to accept a parameter that isn't a type; there is +corresponding logic in `concepts-core` for that case that relies on +this concept being present. + + +#### `Type` + +Returns true if the argument is a type. + + +#### `PreferRefs` + +Returns true if the argument is a type for which references should be +used where possible. + + +#### `Struct` + +Returns true if the argument is a struct type. + + +#### `DefaultConstructible` + +Returns true if variables of the specified type may be declared and +left uninitialised. (This is a really unfortunate name, but not sure +what would be better.) + + +#### `MoveConstructible` + +Returns true if variables of the specified type may be initialised by +way of an rvalue. + + +#### `MoveAssignable` + +Returns true if variables of the specified type may be assigned by way +of an rvalue. + + +#### `CopyConstructible` + +Returns true if variables of the specified type may be initialised by +way of an lvalue. + + +#### `CopyAssignable` + +Returns true if variables of the specified type may be assigned by way +of an lvalue. + + +#### `Swappable` + +Returns true if the type is `MoveConstructible` and `MoveAssignable`, +and a `swap` function exists over the type. + + +#### `EqualityComparable` + +Returns true if `=` and `!=` are implemented over the type. + + +#### `LessThanComparable` + +Returns true if `<`, `<=`, `>` and `>=` are implemented over the type. + + +#### `Container` + +Returns true if the type is `Swappable`, and the following other +conditions hold: + + * `value-type`, `difference-type` and `size-type` macros exist over + pointers to the type; + * `size`, `max-size`, `empty`, `swap` and `init` are defined over + pointers to the type; + * the container has an iterator type; and + * `begin` and `end` are defined over the container, and return + iterators. + + +#### `ForwardContainer` + +Refines `Container`. + +Additional requirements: + + * the iterator type must be an `InputIterator`. + + +#### `ReversibleContainer` + +Refines `ForwardContainer`. + +Additional requirements: + + * the container has a reverse iterator type; + * that type is an `InputIterator`; and + * `rbegin` and `rend` are defined over pointers to the container + type, and they both return reverse iterators. + + +#### `RandomAccessContainer` + +Refines `ReversibleContainer`. Additionally, the iterator for the +container must be a `RandomAccessIterator`, and `$` must be defined +over the container. + + +#### `Sequence` + +Refines `ForwardContainer`. + +Additional requirements: + + * `front` is defined over pointers to the type; + * `insert` is defined, and it takes a pointer to the type, an + iterator, and an instance of value-type; + * `erase` is defined, and it takes a pointer to the type and an + iterator; and + * `clear` is defined over pointers to the type. + + +#### `FrontInsertionSequence` + +Refines `Sequence`. + +Additional requirements: + + * `push-front` and `pop-front` are defined over pointers to the + type. + + +#### `BackInsertionSequence` + +Refines `Sequence`. + +Additional requirements: + + * `push-back`, `pop-back` and `back` are defined over pointers to + the type. + + +#### `AssociativeContainer` + +Refines `ForwardContainer` and `DefaultConstructible`. + +Additional requirements: + + * `key-type`, `erase` (key), `find` (key) and `count` (key) are + defined over pointers to the type; and + * `erase` is defined over the type's iterator. + + +#### `SimpleAssociativeContainer` + +Refines `AssociativeContainer`. The only additional requirement is that +the key type and value type of the container are the same type. + + +#### `SortedAssociativeContainer` + +Refines `AssociativeContainer` and `ReversibleContainer`. +Additionally, `lower-bound` and `upper-bound`, each taking a container +pointer type and a key value (and returning an iterator) must be +defined. + + +#### `UniqueAssociativeContainer` + +Refines `AssociativeContainer`. Additionally, `insert` must be +defined, accepting a pointer to the type and an instance of +value-type. + + +#### `PairAssociativeContainer` + +Refines `AssociativeContainer`. The value-type for the container must +be a struct, and it must contain two members named `first` and +`second`. + + +#### `TrivialIterator` + +Refines `Swappable`, `EqualityComparable` and `DefaultConstructible`. +Additionally, `value-type`, and `source` (returning a pointer to a +value of type `value-type`) must be defined over the iterator (or a +pointer to the iterator, in the case of `value-type`). + + +#### `InputIterator` + +Refines `TrivialIterator`. `successor`, returning an iterator of the +same type as the argument iterator, must be defined over the type. + + +#### `OutputIterator` + +Refines `Swappable` and `DefaultConstructible`. Additionally, +`value-type`, `sink` (for setting the iterator's value) and +`successor` (for getting the next iterator) must be defined over the +iterator (or a pointer to the iterator, in the case of `value-type`). + + +#### `ForwardIterator` + +Refines `InputIterator`. Additionally, calls to `successor` must not +invalidate previous iterators. (This can't be determined +automatically, so this concept exists for documentation purposes +only.) + + +#### `BidirectionalIterator` + +Refines `ForwardIterator`. Additionally, `predecessor` must be +implemented over the iterator, and it must return an instance of the +same type of iterator. + + +#### `RandomAccessIterator` + +Refines `BidirectionalIterator` and `LessThanComparable`. +Additionally, `distance-type` must be defined over pointers to the +type, and `+` and `-` must also be defined, each taking an iterator +and a value of type `distance-type`, and returning a new iterator. + + +[Previous](./2-7-concepts-core.md) | [Next](./2-9-concepts.md) + diff --git a/doc/2-9-concepts.md b/doc/2-9-concepts.md new file mode 100644 index 00000000..6d36732b --- /dev/null +++ b/doc/2-9-concepts.md @@ -0,0 +1,78 @@ +# Dale + +[Previous](./2-8-concept-defs.md) | [Next](./2-10-utility.md) + +## 2.9 concepts + +### Details + +Module: concepts + +### Description + +Imports the other concept-related modules, and implements the +following concepts: + + * `Swappable`; + * `EqualityComparable`; and + * `LessThanComparable` + +over the built-in integral types, as well as `char`, `size` and +`ptrdiff`. Provides `swap` functions to suit, too. + + + +### Macros + +#### `refconst` + +Linkage: `extern` +Parameters: + + * `frm` + + +Expands a form `frm` into `(ref (const frm))`. + + +#### `move@` + +Linkage: `extern` +Parameters: + + * `frm` + + +Expands a form `frm` into `(move (@ frm))`. + + +#### `prefer-ref-bindings` + +Linkage: `extern` +Parameters: + + * `T2` + * `S` + + +Takes a type and a suffix as its arguments. Expands into a series of +`def` forms: the first is `prefer-refs`, being a boolean indicating +whether this type implements the `PreferRefs` concept; the second is +`tpw` (type parameter wrapper), which should be used for parameters of +the specified type (e.g. `((uq tpw) parameter)`), and the third is +`tvw` (type value wrapper), which should be used when accessing the +value of the relevant parameter. There are additionally `tpw-ro` and +`tvw-ro`, for when types are used in a read-only fashion. The form +names described above each take a hyphen and the string of the suffix +node, so as to allow disambiguation when multiple calls are required. + +There is an additional overload of this macro, which takes two forms +that should evaluate to either `true` or `false`, representing whether +copy is disabled for the type and whether the type prefers references, +as well as a suffix node. It uses those forms to determine the +appropriate type parameter and value wrappers, but otherwise operates +as per the other version. + + +[Previous](./2-8-concept-defs.md) | [Next](./2-10-utility.md) + diff --git a/doc/3-1-cerrno.md b/doc/3-1-cerrno.md index 7a85ec26..0f6be40c 100644 --- a/doc/3-1-cerrno.md +++ b/doc/3-1-cerrno.md @@ -1,6 +1,6 @@ # Dale -[Previous](./2-23-variant.md) | [Next](./3-2-cfloat.md) +[Previous](./2-22-variant.md) | [Next](./3-2-cfloat.md) ## 3.1 cerrno @@ -58,5 +58,5 @@ Parameters: N/A Expands to the current error number. -[Previous](./2-23-variant.md) | [Next](./3-2-cfloat.md) +[Previous](./2-22-variant.md) | [Next](./3-2-cfloat.md) diff --git a/doc/all.md b/doc/all.md index b55c05e1..bb0eba14 100644 --- a/doc/all.md +++ b/doc/all.md @@ -653,12 +653,11 @@ a pointer to a `DNode` (static). For example: (def const-string (macro extern (void) (q (p (const char))))) -There are two principal standard libraries that deal with macros: -[`macros-core`](#macros-core) and [`macros`](#macros). -The former provides many functions that ease macro authorship. The -latter provides the quasiquotation (`qq`) macro, which is one of the -more useful macro-writing macros. For example, an `unless` (opposite -of `if`) macro would look like so, when using `qq`: +The standard library for dealing with macros is (unsurprisingly) +[`macros`](#macros). It provides many functions that ease +macro authorship, as well as the quasiquotation (`qq`) macro, which is +one of the more useful macro-writing macros. For example, an `unless` +(opposite of `if`) macro would look like so, when using `qq`: (def unless (macro extern (expr tc fc) (qq if (not (uq expr)) (uq tc) (uq fc)))) @@ -1994,18 +1993,17 @@ Defines overloaded functions corresponding generally with those from A macro constant for `e` is also provided. -## 2.4 macros-core +## 2.4 macros ### Details -Module: macros-core +Module: macros ### Description Provides the core macro development functions: making, copying and -printing nodes, linking nodes together, and gensym functions for -variables and labels. Also provides a 'bootstrap' quasiquotation -function (not intended for use outside the standard libraries). +printing nodes, linking nodes together, gensym functions for +variables and labels, and the quasiquotation form. @@ -2481,22 +2479,6 @@ Parameters: Simple version of `get-varargs-list`, only takes the count as parameter. -## 2.5 stdlib - -### Details - -Module: stdlib - -### Description - -Provides commonly-used macros and functions, including the core -control structures (`for`, `while` and `let`). All of the bindings -provided by this library are in the root namespace. - - - -### Macros - #### `@:'` Linkage: `extern` @@ -2513,6 +2495,59 @@ member names. For example, if two members are provided, the expansion is `(@:@ (@:@ structp member1) member2)`. +#### `qq` + +Linkage: `extern` +Parameters: + + * `frm` + * `rest` + + +The 'general-use' quasiquotation macro. The forms handled specially +are: + + * `uq` (unquote): expands to the argument node, excluding any + following nodes (i.e. excluding `next-node`); + * `uql` (unquote-list): expands to the argument node, including all + following nodes (i.e. including `next-node` and any subsequent + `next-node`s of that node); + * `uq-nc` (unquote no-copy): as per `uq`, except that the argument + node is not copied on substitution; and + * `uql-nc` (unquote-list no-copy): as per `uql`, except that the nodes + are not copied on substitution. + +Quasiquotation forms may be nested: each specially-handled form in a +nested `qq` must be wrapped with an additional `uq` for each level of +nesting. + +The `-nc` versions should only be used when the argument node will not +be used again. + +Argument nodes for the various unquote forms must be DNode pointer +variable names. If any other type of argument is provided, the +unquote form will expand to that argument. For example, `(qq do (uq +(mnfv mc 1)))` will expand to `(do (mnfv mc 1))`. Issue #140 is +tracking this problem, and will be resolved when arbitrary argument +nodes are supported. + + +## 2.5 stdlib + +### Details + +Module: stdlib + +### Description + +Provides commonly-used macros and functions, including the core +control structures (`for`, `while` and `let`). All of the bindings +provided by this library are in the root namespace. + + + +### Macros + #### `is-valid` Linkage: `extern` @@ -2848,58 +2883,7 @@ these macros has the same name as the original function, except with a ' symbol appended. -## 2.6 macros - -### Details - -Module: macros - -### Description - -Provides the quasiquotation macro. - - - -### Macros - -#### `qq` - -Linkage: `extern` -Parameters: - - * `frm` - * `rest` - - -The 'general-use' quasiquotation macro. The forms handled specially -are: - - * `uq` (unquote): expands to the argument node, excluding any - following nodes (i.e. excluding `next-node`); - * `uql` (unquote-list): expands to the argument node, including all - following nodes (i.e. including `next-node` and any subsequent - `next-node`s of that node); - * `uq-nc` (unquote no-copy): as per `uq`, except that the argument - node is not copied on substitution; and - * `uql-nc` (unquote-list no-copy): as per `uql`, except that the nodes - are not copied on substitution. - -Quasiquotation forms may be nested: each specially-handled form in a -nested `qq` must be wrapped with an additional `uq` for each level of -nesting. - -The `-nc` versions should only be used when the argument node will not -be used again. - -Argument nodes for the various unquote forms must be DNode pointer -variable names. If any other type of argument is provided, the -unquote form will expand to that argument. For example, `(qq do (uq -(mnfv mc 1)))` will expand to `(do (mnfv mc 1))`. Issue #140 is -tracking this problem, and will be resolved when arbitrary argument -nodes are supported. - - -## 2.7 assert +## 2.6 assert ### Details @@ -2951,7 +2935,7 @@ If assertions have been disabled, by way of `disable-assertions`, then subsequent calls to this macro will expand to no-ops. -## 2.8 concepts-core +## 2.7 concepts-core ### Details @@ -3425,7 +3409,7 @@ fail with the error "concept not found". This is usually caused by a missing import statement. -## 2.9 concept-defs +## 2.8 concept-defs ### Details @@ -3670,7 +3654,7 @@ type, and `+` and `-` must also be defined, each taking an iterator and a value of type `distance-type`, and returning a new iterator. -## 2.10 concepts +## 2.9 concepts ### Details @@ -3742,7 +3726,7 @@ appropriate type parameter and value wrappers, but otherwise operates as per the other version. -## 2.11 utility +## 2.10 utility ### Details @@ -3961,7 +3945,7 @@ Expands to the concrete type name of the `Triple` generated by way of the concept macro. -## 2.12 derivations +## 2.11 derivations ### Details @@ -4075,7 +4059,7 @@ Expands to `=`, `!=`, `<`, `<=`, `>` and `>=` functions over the provided struct type. Any that have already been defined are skipped. -## 2.13 algorithms +## 2.12 algorithms ### Details @@ -4377,7 +4361,7 @@ Parameters: Like `Action`, except the function pointer takes a reference. -## 2.14 list +## 2.13 list ### Details @@ -4807,7 +4791,7 @@ Parameters: Expands to the underlying distance type of the iterator. -## 2.15 vector +## 2.14 vector ### Details @@ -5319,7 +5303,7 @@ Parameters: Expands to the underlying distance type of the iterator. -## 2.16 set +## 2.15 set ### Details @@ -5731,7 +5715,7 @@ Parameters: Expands to the underlying value type (i.e. `T`) of the iterator. -## 2.17 map +## 2.16 map ### Details @@ -6158,7 +6142,7 @@ Expands to the underlying value type of the iterator. This is the same as that of `value-type` for the container. -## 2.18 array +## 2.17 array ### Details @@ -6548,7 +6532,7 @@ Parameters: Expands to the underlying distance type of the iterator. -## 2.19 shared-ptr +## 2.18 shared-ptr ### Details @@ -6660,7 +6644,7 @@ Expands to the concrete type name of the `SharedPtr` generated by way of the concept macro. -## 2.20 unique-ptr +## 2.19 unique-ptr ### Details @@ -6772,7 +6756,7 @@ Expands to the concrete type name of the `UniquePtr` generated by way of the concept macro. -## 2.21 operator-macros +## 2.20 operator-macros ### Details @@ -6856,7 +6840,7 @@ expands to: -## 2.22 bitset-enum +## 2.21 bitset-enum ### Details @@ -6899,7 +6883,7 @@ Parameters: -## 2.23 variant +## 2.22 variant ### Details diff --git a/doc/index.md b/doc/index.md index d3ace594..6a9a54b8 100644 --- a/doc/index.md +++ b/doc/index.md @@ -19,23 +19,22 @@ ### 2.1. [introspection](./2-1-introspection.md) ### 2.2. [ctype](./2-2-ctype.md) ### 2.3. [math](./2-3-math.md) -### 2.4. [macros-core](./2-4-macros-core.md) +### 2.4. [macros](./2-4-macros.md) ### 2.5. [stdlib](./2-5-stdlib.md) -### 2.6. [macros](./2-6-macros.md) -### 2.7. [assert](./2-7-assert.md) -### 2.8. [concepts-core](./2-8-concepts-core.md) -### 2.9. [concept-defs](./2-9-concept-defs.md) -### 2.10. [concepts](./2-10-concepts.md) -### 2.11. [utility](./2-11-utility.md) -### 2.12. [derivations](./2-12-derivations.md) -### 2.13. [algorithms](./2-13-algorithms.md) -### 2.14. [list](./2-14-list.md) -### 2.15. [vector](./2-15-vector.md) -### 2.16. [set](./2-16-set.md) -### 2.17. [map](./2-17-map.md) -### 2.18. [array](./2-18-array.md) -### 2.19. [shared-ptr](./2-19-shared-ptr.md) -### 2.20. [unique-ptr](./2-20-unique-ptr.md) +### 2.6. [assert](./2-6-assert.md) +### 2.7. [concepts-core](./2-7-concepts-core.md) +### 2.8. [concept-defs](./2-8-concept-defs.md) +### 2.9. [concepts](./2-9-concepts.md) +### 2.10. [utility](./2-10-utility.md) +### 2.11. [derivations](./2-11-derivations.md) +### 2.12. [algorithms](./2-12-algorithms.md) +### 2.13. [list](./2-13-list.md) +### 2.14. [vector](./2-14-vector.md) +### 2.15. [set](./2-15-set.md) +### 2.16. [map](./2-16-map.md) +### 2.17. [array](./2-17-array.md) +### 2.18. [shared-ptr](./2-18-shared-ptr.md) +### 2.19. [unique-ptr](./2-19-unique-ptr.md) ## C bindings diff --git a/generate-docs b/generate-docs index 046687fa..b4f55313 100755 --- a/generate-docs +++ b/generate-docs @@ -7,26 +7,25 @@ my @files = qw( 2-1-introspection.md 2-2-ctype.md 2-3-math.md - 2-4-macros-core.md + 2-4-macros.md 2-5-stdlib.md - 2-6-macros.md - 2-7-assert.md - 2-8-concepts-core.md - 2-9-concept-defs.md - 2-10-concepts.md - 2-11-utility.md - 2-12-derivations.md - 2-13-algorithms.md - 2-14-list.md - 2-15-vector.md - 2-16-set.md - 2-17-map.md - 2-18-array.md - 2-19-shared-ptr.md - 2-20-unique-ptr.md - 2-21-operator-macros.md - 2-22-bitset-enum.md - 2-23-variant.md + 2-6-assert.md + 2-7-concepts-core.md + 2-8-concept-defs.md + 2-9-concepts.md + 2-10-utility.md + 2-11-derivations.md + 2-12-algorithms.md + 2-13-list.md + 2-14-vector.md + 2-15-set.md + 2-16-map.md + 2-17-array.md + 2-18-shared-ptr.md + 2-19-unique-ptr.md + 2-20-operator-macros.md + 2-21-bitset-enum.md + 2-22-variant.md 3-1-cerrno.md 3-2-cfloat.md 3-3-clocale.md diff --git a/modules/macros-core.dt b/modules/macros-core.dt deleted file mode 100644 index de97f0d2..00000000 --- a/modules/macros-core.dt +++ /dev/null @@ -1,1142 +0,0 @@ -#| -@module macros-core - -Provides the core macro development functions: making, copying and -printing nodes, linking nodes together, and gensym functions for -variables and labels. Also provides a 'bootstrap' quasiquotation -function (not intended for use outside the standard libraries). - -|# -(module macros-core (attr cto)) - -(import cstdio-core) -(namespace std (namespace macros - -#| -@fn std.macros.make-node - -Returns a newly-allocated node. - -@param mc An MContext. -|# -(def make-node - (fn extern (p DNode) ((mc (p MContext))) - (def dnsize (var auto size (sizeof DNode))) - (def n (var auto (p DNode) - (cast (pool-malloc mc dnsize) (p DNode)))) - (memset (cast n (p void)) 0 (sizeof DNode)) - (setf (: (@ n) filename) (nullptr char)) - n)) - -#| -@fn std.macros.make-empty-list-node - -Returns a newly-allocated empty list node. - -@param mc An MContext. -|# -(def make-empty-list-node - (fn extern (p DNode) ((mc (p MContext))) - (def node (var auto \ (make-node mc))) - (setf (:@ node is-list) 1) - (return node))) - -#| -@fn std.macros.is-non-empty-list - -@param form The node. -|# -(def is-non-empty-list - (fn extern bool ((form (p DNode))) - (if (= 1 (@:@ form is-list)) - (if (not (null (@:@ form list-node))) - true - false) - false))) - -#| -@fn std.macros.copy - -@param mc An MContext. -@param follow Whether to include the nodes that follow `form`. -@param form The node to copy. -@return A copy of `form`. -|# -(def copy - (fn extern (p DNode) ((mc (p MContext)) - (follow bool) - (form (p DNode))) - (def nullp (var auto (p DNode) (cast 0 (p DNode)))) - (def new-node (var auto (p DNode) (make-node mc))) - - (memcpy (cast new-node (p void)) - (cast form (p void)) - (cast (sizeof DNode) int)) - - (if (not (null (@:@ form list-node))) - (setf (:@ new-node list-node) - (copy mc true (@:@ form list-node))) - true) - - (setf (:@ new-node next-node) - (if follow - (if (not (null (@:@ form next-node))) - (copy mc true (@:@ form next-node)) - nullp) - nullp)) - - (return new-node))) - -#| -@fn std.macros.copy-qstr - -As per `copy`, except that if the first node is a token, it will have -double-quotations marks added at the start and end of it in the copied -node. - -@param mc An MContext. -@param form The node to copy. -@param follow Whether to include the nodes that follow `form`. -@return A copy of `form`. -|# -(def copy-qstr - (fn extern (p DNode) ((mc (p MContext)) - (form (p DNode)) - (follow bool)) - (def nullp (var auto (p DNode) (cast 0 (p DNode)))) - (def new-node (var auto (p DNode) (make-node mc))) - (def dquote (var auto char #\")) - (def len (var auto size 0)) - (def charbuf (var auto (p char) - (cast (pool-malloc mc (cast 256 size)) (p char)))) - - (if (= 0 (@:@ form is-list)) - (do - (setf ($ charbuf 0) dquote) - (setv len (strlen (@ (: (@ form) token-str)))) - (strncpy ($ charbuf 1) (@ (: (@ form) token-str)) len) - (setf ($ charbuf (+ (cast 1 size) len)) dquote) - (setf ($ charbuf (+ (cast 2 size) len)) #\NULL) - (setf (:@ new-node is-list) 0) - (setf (:@ new-node token-str) charbuf) - (setf (:@ new-node list-node) nullp) - - (setf (:@ new-node next-node) - (if follow - (if (not (null (@:@ form next-node))) - (do (copy mc true (@:@ form next-node))) - nullp) - nullp))) - (do - (setf (:@ new-node is-list) 1) - (if (not (null (@:@ form list-node))) - (do (setf (:@ new-node list-node) - (copy mc true (@:@ form list-node))) - 0) - 0))) - - (setf (:@ new-node begin-line) (@:@ form begin-line)) - (setf (:@ new-node begin-column) (@:@ form begin-column)) - (setf (:@ new-node end-line) (@:@ form end-line)) - (setf (:@ new-node end-column) (@:@ form end-column)) - (setf (:@ new-node macro-begin-line) (@:@ form macro-begin-line)) - (setf (:@ new-node macro-begin-column) (@:@ form macro-begin-column)) - (setf (:@ new-node macro-end-line) (@:@ form macro-end-line)) - (setf (:@ new-node macro-end-column) (@:@ form macro-end-column)) - - (setf (:@ new-node next-node) - (if follow - (if (not (null (@:@ form next-node))) - (do (copy mc true (@:@ form next-node))) - nullp) - nullp)) - - (return new-node))) - -#| -@fn std.macros.copy-to - -Copy (shallow) the details of the source node to the destination node. - -@param dst The destination node. -@param src The source node. -|# -(def copy-to - (fn extern void ((dst (p DNode)) (src (p DNode))) - (setf (:@ dst is-list) (@:@ src is-list)) - (setf (:@ dst token-str) (@:@ src token-str)) - (setf (:@ dst list-node) (@:@ src list-node)) - (setf (:@ dst begin-line) (@:@ src begin-line)) - (setf (:@ dst begin-column) (@:@ src begin-column)) - (setf (:@ dst end-line) (@:@ src end-line)) - (setf (:@ dst end-column) (@:@ src end-column)) - (setf (:@ dst macro-begin-line) (@:@ src macro-begin-line)) - (setf (:@ dst macro-begin-column) (@:@ src macro-begin-column)) - (setf (:@ dst macro-end-line) (@:@ src macro-end-line)) - (setf (:@ dst macro-end-column) (@:@ src macro-end-column)) - (setf (:@ dst filename) (@:@ src filename)) - (return))) - -#| -@fn std.macros.print - -Prints the node to `stdout`. - -@param form The node to print. -|# -(def print - (fn extern bool ((form (p DNode))) - (if (= 0 (@:@ form is-list)) - (do (printf "%s" (@:@ form token-str)) - true) - (do (printf "(") - (if (not (null (@:@ form list-node))) - (print (@:@ form list-node)) - true) - (printf ")") - true)) - (if (not (null (@:@ form next-node))) - (do (printf " ") - (return (print (@:@ form next-node)))) - true))) - -#| -@fn std.macros.sprint - -Prints the node to the provided buffer. - -@param buf The buffer to which the node will be printed. -@param form The node to print. -|# -(def sprint - (fn extern bool ((buf (p char)) (form (p DNode))) - (def cc (var auto (p char) buf)) - (if (= 0 (@:@ form is-list)) - (do (sprintf buf "%s" (@:@ form token-str)) - (setv buf (strchr buf (cast #\NULL int))) - true) - (do (setf ($ buf 0) (cast 40 char)) - (setv buf (p+ buf 1)) - (setf buf #\NULL) - (if (not (null (@:@ form list-node))) - (sprint buf (@:@ form list-node)) - 0) - (setv buf (strchr buf (cast #\NULL int))) - (setf ($ buf 0) (cast 41 char)) - (setv buf (p+ buf 1)) - (setf buf #\NULL) - true)) - (if (not (null (@:@ form next-node))) - (do (setf ($ buf 0) #\SPACE) - (setv buf (p+ buf 1)) - (setf buf #\NULL) - (return (sprint buf (@:@ form next-node)))) - true))) - -#| -@fn std.macros.get-last-node - -Returns the last node in the list, by iterating over `next-node` -(i.e. this does not descend into the `list-node` of the argument -node). - -@param form The node for which the last node should be found. -@return The last node. -|# -(def get-last-node - (fn extern (p DNode) ((form (p DNode))) - (label begin-loop) - (if (null (@:@ form next-node)) - (return form) - (do (setv form (@:@ form next-node)) - (goto begin-loop))))) - -#| -@fn std.macros.mnfv - -Short for 'make-node-from-value'. There are several implementations of -this function: each is similar to `make-node`, except that each takes -an additional argument, which is used to populate the `token-str` of -the newly-allocated node. This implementation takes a `(p char)`, -copies it, and sets it in the new node. - -@param mc An MContext. -@param token-string The token string for the new node. -|# -(def mnfv - (fn extern (p DNode) ((mc (p MContext)) - (token-string (p (const char)))) - (def d-node (var auto (p DNode) (make-node mc))) - (def nullp (var auto (p DNode) (nullptr DNode))) - (def charp (var auto (p char) - (cast (pool-malloc mc (cast 256 size)) (p char)))) - (strncpy charp token-string (cast 256 size)) - (setf (:@ d-node is-list) 0) - (setf (:@ d-node token-str) charp) - (setf (:@ d-node list-node) nullp) - (setf (:@ d-node next-node) nullp) - (return d-node))) - -#| -@fn std.macros.mnfv - -@param mc An MContext. -@param n An integer. -|# -(def mnfv - (fn extern (p DNode) ((mc (p MContext)) - (n int)) - (def x (var auto (array-of 255 char))) - (sprintf x "%d" n) - (mnfv mc x))) - -#| -@fn std.macros.mnfv - -@param mc An MContext. -@param n A uint64 integer. -|# -(def mnfv - (fn extern (p DNode) ((mc (p MContext)) - (n uint64)) - (def x (var auto (array-of 255 char))) - (sprintf x "%lu" n) - (mnfv mc x))) - -#| -@fn std.macros.mnfv - -@param mc An MContext. -@param f A float. -|# -(def mnfv - (fn extern (p DNode) ((mc (p MContext)) - (f float)) - (def x (var auto (array-of 255 char))) - (sprintf x "%f" f) - (mnfv mc x))) - -#| -@fn std.macros.mnfv - -@param mc An MContext. -@param d A double. -|# -(def mnfv - (fn extern (p DNode) ((mc (p MContext)) - (d double)) - (def x (var auto (array-of 255 char))) - (sprintf x "%f" d) - (mnfv mc x))) - -#| -@fn std.macros.mnfv - -@param mc An MContext. -@param ld A long double. -|# -(def mnfv - (fn extern (p DNode) ((mc (p MContext)) - (ld long-double)) - (def x (var auto (array-of 255 char))) - (sprintf x "%Lf" ld) - (mnfv mc x))) - -#| -@fn std.macros.mnfv-wp - -Short for 'make-node-from-value-with-position'. Takes additional node -position arguments, and sets them accordingly on the new node. Only -implemented for `(p char)` values. - -@param mc An MContext. -@param token-string A string. -@param begin-line The beginning line number for the node. -@param begin-column The beginning column number for the node. -@param end-line The ending line number for the node. -@param end-column The ending column number for the node. -@param macro-begin-line The beginning macro line number. -@param macro-begin-column The beginning macro column number. -@param macro-end-line The ending macro line number. -@param macro-end-column The ending macro column number. -|# -(def mnfv-wp - (fn extern (p DNode) ((mc (p MContext)) - (token-string (p (const char))) - (begin-line int) - (begin-column int) - (end-line int) - (end-column int) - (macro-begin-line int) - (macro-begin-column int) - (macro-end-line int) - (macro-end-column int)) - (def n (var auto \ (mnfv mc token-string))) - (setf (:@ n begin-line) begin-line) - (setf (:@ n begin-column) begin-column) - (setf (:@ n end-line) end-line) - (setf (:@ n end-column) end-column) - (setf (:@ n macro-begin-line) macro-begin-line) - (setf (:@ n macro-begin-column) macro-begin-column) - (setf (:@ n macro-end-line) macro-end-line) - (setf (:@ n macro-end-column) macro-end-column) - (return n))) - -#| -@fn std.macros.link-nodes - -Links the provided nodes together, without copying them, and returns -the first provided node. This is a varargs function. Note that the -`next-node` member of the last node is not nulled. - -@param argcount The number of nodes being provided. -@return The first node that was provided. -|# -(def link-nodes - (fn extern (p DNode) ((argcount int) ...) - (def nullp (var auto (p DNode) (cast 0 (p DNode)))) - (def very-fst-node (var auto (p DNode))) - (def fst-node (var auto (p DNode))) - (def snd-node (var auto (p DNode))) - - (def arglist (var auto va-list)) - (va-start (cast (# arglist) (p void))) - - (setv very-fst-node (va-arg (# arglist) (p DNode))) - (setv fst-node very-fst-node) - - (label begin-loop) - (if (= 1 argcount) - (goto end-loop) - (do - (setv snd-node (va-arg (# arglist) (p DNode))) - (setf (: (@ fst-node) next-node) snd-node) - (setv fst-node (get-last-node snd-node)) - (setv argcount (- argcount 1)) - (goto begin-loop))) - - (label end-loop) - (va-end (cast (# arglist) (p void))) - (return very-fst-node))) - -#| -@fn std.macros.link-nodes-list - -As per `link-nodes`, except that an additional list node is allocated -and returned. This list node points to the first provided node as its -`list-node`. - -@param mc An MContext. -@param argcount The number of varargs being provided. -|# -(def link-nodes-list - (fn extern (p DNode) ((mc (p MContext)) (argcount int) ...) - (def link-node (var auto (p DNode) (make-node mc))) - (def nullp (var auto (p DNode) (cast 0 (p DNode)))) - - (def very-fst-node (var auto (p DNode))) - (def fst-node (var auto (p DNode))) - (def snd-node (var auto (p DNode))) - - (def arglist (var auto va-list)) - (va-start (cast (# arglist) (p void))) - - (setv very-fst-node (va-arg (# arglist) (p DNode))) - (setv fst-node very-fst-node) - - (label begin-loop) - (if (= 1 argcount) - (goto end-loop) - (do - (setv snd-node (va-arg (# arglist) (p DNode))) - (setf (: (@ fst-node) next-node) snd-node) - (setv fst-node (get-last-node snd-node)) - (setv argcount (- argcount 1)) - (goto begin-loop))) - - (label end-loop) - (va-end (cast (# arglist) (p void))) - (setf (:@ link-node is-list) 1) - (setf (:@ link-node next-node) nullp) - (setf (:@ link-node list-node) very-fst-node) - (return link-node))) - -#| -@fn std.macros.link-nodes-list-wp - -As per `link-nodes-list`, except it also accepts additional node -position arguments, and sets them accordingly on the newly-allocated -list node. - -@param mc An MContext. -@param argcount The number of varargs being provided. -@param begin-line The beginning line number for the node. -@param begin-column The beginning column number for the node. -@param end-line The ending line number for the node. -@param end-column The ending column number for the node. -@param macro-begin-line The beginning macro line number. -@param macro-begin-column The beginning macro column number. -@param macro-end-line The ending macro line number. -@param macro-end-column The ending macro column number. -|# -(def link-nodes-list-wp - (fn extern (p DNode) ((mc (p MContext)) - (argcount int) - (begin-line int) - (begin-column int) - (end-line int) - (end-column int) - (macro-begin-line int) - (macro-begin-column int) - (macro-end-line int) - (macro-end-column int) - ...) - (def link-node (var auto (p DNode) (make-node mc))) - (def nullp (var auto (p DNode) (cast 0 (p DNode)))) - - (def very-fst-node (var auto (p DNode))) - (def fst-node (var auto (p DNode))) - (def snd-node (var auto (p DNode))) - - (def arglist (var auto va-list)) - (va-start (cast (# arglist) (p void))) - - (setv very-fst-node (va-arg (# arglist) (p DNode))) - (setv fst-node very-fst-node) - - (label begin-loop) - (if (= 1 argcount) - (goto end-loop) - (do - (setv snd-node (va-arg (# arglist) (p DNode))) - (setf (: (@ fst-node) next-node) snd-node) - (setv fst-node (get-last-node snd-node)) - (setv argcount (- argcount 1)) - (goto begin-loop))) - - (label end-loop) - (va-end (cast (# arglist) (p void))) - (setf (: (@ link-node) is-list) 1) - (setf (: (@ link-node) next-node) nullp) - (setf (: (@ link-node) list-node) very-fst-node) - - (setf (: (@ link-node) begin-line) begin-line) - (setf (: (@ link-node) begin-column) begin-column) - (setf (: (@ link-node) end-line) end-line) - (setf (: (@ link-node) end-column) end-column) - (setf (: (@ link-node) macro-begin-line) macro-begin-line) - (setf (: (@ link-node) macro-begin-column) macro-begin-column) - (setf (: (@ link-node) macro-end-line) macro-end-line) - (setf (: (@ link-node) macro-end-column) macro-end-column) - - (return link-node))) - -#| -@fn std.macros.link-nodes-array - -As per `link-nodes`, except that instead of being a varargs function, -it takes an array of nodes as its second argument. - -@param argcount The number of arguments in the array. -@param arg-array The argument array. -|# -(def link-nodes-array - (fn extern (p DNode) ((argcount int) (arg-array (p (p DNode)))) - (if (= argcount 0) - (return (nullptr DNode)) - 0) - - (def nullp (var auto (p DNode) (cast 0 (p DNode)))) - (def very-fst-node (var auto (p DNode))) - (def fst-node (var auto (p DNode))) - (def snd-node (var auto (p DNode))) - - (setv very-fst-node (@ arg-array)) - (setv fst-node very-fst-node) - (setv arg-array (p+ arg-array 1)) - (setv argcount (- argcount 1)) - - (label begin-loop) - (if (= 0 argcount) - (goto end-loop) - (do - (setv snd-node (@ arg-array)) - (setf (: (@ fst-node) next-node) snd-node) - (setv fst-node snd-node) - (setv argcount (- argcount 1)) - (setv arg-array (p+ arg-array 1)) - (goto begin-loop))) - - (label end-loop) - (return very-fst-node))) - -(def var-marker (var intern int 0)) -#| -@fn std.macros.gensym-var - -Prints a new, unused variable name to the provided buffer. - -@param buf The buffer for the variable name. -|# -(def gensym-var - (fn extern bool ((buf (p char))) - (sprintf buf "_dale_internal_var_%d" var-marker) - (setv var-marker (+ var-marker 1)) - true)) - -(def label-marker (var intern int 0)) -#| -@fn std.macros.gensym-label - -Prints a new, unused label name to the provided buffer. The prefix is -included in the new label name, so that it is a little easier to -determine what's happening when errors occur in the generated code. - -@param buf The buffer for the label name. -@param prefix The prefix for the label name. -|# -(def gensym-label - (fn extern bool ((buf (p char)) (prefix (p (const char)))) - (if (null prefix) - (setv prefix "na") - true) - (sprintf buf "_dale_internal_label_%s_%d" prefix label-marker) - (setv label-marker (+ label-marker 1)) - true)) - -#| -@fn std.macros.make-gensym-label-node - -Generates a new label name, constructs a token node to suit and -returns that node. - -@param mc An MContext. -@param prefix The prefix for the label name. -|# -(def make-gensym-label-node - (fn extern (p DNode) ((mc (p MContext)) (prefix (p (const char)))) - (def label-name - (var auto (p char) - (cast (pool-malloc mc (cast 150 size)) (p char)))) - (gensym-label label-name prefix) - (mnfv mc label-name))) - -#| -@fn std.macros.make-gensym-label-node - -As per the previous implementation, except that no prefix is required -(it is set to the empty string). - -@param mc An MContext. -|# -(def make-gensym-label-node - (fn extern (p DNode) ((mc (p MContext))) - (make-gensym-label-node mc ""))) - -#| -@fn std.macros.is-gensym-label - -Determines whether the provided label node is a gensym label with the -specified prefix. - -@param label-node The label node. -@param prefix The prefix for which to check in the label node. -|# -(def is-gensym-label - (fn extern bool ((label-node (p DNode)) (prefix (p (const char)))) - (if (null (@:@ label-node token-str)) - (return false) - 0) - (def match-str (var auto (array-of 150 char))) - (sprintf match-str "_dale_internal_label_%s_" prefix) - (if (!= 0 (strncmp (@:@ label-node token-str) - match-str - (strlen match-str))) - (return false) - 0) - (return true))) - -#| -@fn std.macros.make-gensym-var-node - -Generates a new variable name, constructs a token node to suit and -returns that node. - -@param mc An MContext. -|# -(def make-gensym-var-node - (fn extern (p DNode) ((mc (p MContext))) - (def var-name - (var auto \ (cast (pool-malloc mc (cast 30 size)) (p char)))) - (gensym-var var-name) - (mnfv mc var-name))) - -#| -@fn std.macros.walk-nodes - -'Walks' through a node, recursively, calling the provided function -pointer on each node. The provided `data` argument is passed to the -function pointer on each call. - -@param form The node to walk. -@param mc An MContext. -@param data Arbitrary data. -@param fn The function pointer to call on each node. -|# -(def walk-nodes - (fn extern bool ((form (p DNode)) - (mc (p MContext)) - (data (p void)) - (fn (p (fn int ((form (p DNode)) - (mc (p MContext)) - (data (p void))))))) - (if (not (null (@:@ form list-node))) - (walk-nodes (@:@ form list-node) mc data fn) - true) - (funcall fn form mc data) - (if (not (null (@:@ form next-node))) - (walk-nodes (@:@ form next-node) mc data fn) - true) - true)) - -#| -@fn std.macros.list-count - -Takes a list node, and counts the number of nodes that are within that -list. This is not recursive: it just counts the top-level nodes from -the list. - -@param form A list node. -|# -(def list-count - (fn extern int ((form (p DNode))) - (def count (var auto int 0)) - (def el-node (var auto (p DNode) (@ (:@ form list-node)))) - (label begin-loop) - (if (null el-node) - (goto end-loop) - (do (setv count (+ count 1)) - (setv el-node (@ (:@ el-node next-node))) - (goto begin-loop))) - (label end-loop) - (return count))) - -#| -@fn std.macros.make-node-maker - -Constructs a node that, when evaluated, constructs the provided node. -For example, if the node is a simple token, then the returned node -will be `(mnfv mc token-str)`, where `token-str` is the token -from the provided node. - -@param mc An MContext. -@param form A node. -|# -(def make-node-maker - (fn extern (p DNode) ((mc (p MContext)) (form (p DNode))) - (def charbuf (var auto (array-of 256 char))) - (def dquote (var auto char #\")) - - (def myres (var auto (p DNode) - (if (= 0 (@:@ form is-list)) - (do - (setf ($ charbuf 0) dquote) - (strncpy ($ charbuf 1) - (@:@ form token-str) - (strlen (@:@ form token-str))) - (setf ($ charbuf - (+ (cast 1 size) (strlen (@:@ form token-str)))) - dquote) - (setf ($ charbuf - (+ (cast 2 size) (strlen (@:@ form token-str)))) - #\NULL) - (link-nodes-list mc 3 - (mnfv mc "std.macros.mnfv") - (mnfv mc "mc") - (mnfv mc charbuf))) - (do - (def holder - (var auto (p DNode) (make-node mc))) - (setf (:@ holder is-list) 1) - (setf (:@ holder list-node) (nullptr DNode)) - (setf (:@ holder next-node) (nullptr DNode)) - (def topnode - (var auto (p DNode) (mnfv mc "std.macros.link-nodes-list"))) - (setf (:@ holder list-node) topnode) - (def poolnode - (var auto (p DNode) (mnfv mc "mc"))) - (setf (:@ topnode next-node) poolnode) - - (def cnode - (var auto \ (@:@ form list-node))) - (def count (var auto \ 1)) - (label begin) - (if (null (@:@ cnode next-node)) - (goto end) - (do (setv count (+ count 1)) - (setv cnode (@:@ cnode next-node)) - (goto begin))) - (label end) - - (def countnode - (var auto (p DNode) (mnfv mc count))) - (setf (:@ poolnode next-node) countnode) - - (def elnode (var auto (p DNode) countnode)) - (def nextelnode (var auto (p DNode))) - - (setv cnode (@:@ form list-node)) - - (label begin2) - (do (setv nextelnode (make-node-maker mc cnode)) - (setf (:@ elnode next-node) nextelnode) - (setv elnode nextelnode) - (if (null (@:@ cnode next-node)) - (goto end2) - (do (setv cnode (@:@ cnode next-node)) - (goto begin2)))) - (label end2) - holder)))) - - (return myres))) - -(def itoa-str (var intern (array-of 50 char))) -(def itoa - (fn extern (p char) ((n int)) - (sprintf itoa-str "%d" n) - (return itoa-str))) - -#| -@fn std.macros.bqq-helper - -A helper function for `bqq` (bootstrap-qq). - -@param frm A node. -@param mc An MContext. -@param arg-count The number of elements in the node. -|# -(def bqq-helper - (fn intern (p DNode) ((frm (p DNode)) - (mc (p MContext)) - (arg-count int)) - (def nullp (var auto (p DNode) (cast 0 (p DNode)))) - - (def holder (var auto (p DNode) (make-node mc))) - (setf (:@ holder is-list) 1) - (setf (:@ holder list-node) nullp) - (setf (:@ holder next-node) nullp) - - (def ln-node (var auto (p DNode) - (mnfv mc "std.macros.link-nodes-list-wp"))) - (setf (:@ holder list-node) ln-node) - - (def pool-node (var auto (p DNode) (mnfv mc "mc"))) - (setf (:@ ln-node next-node) pool-node) - - (def count-node (var auto (p DNode) (mnfv mc (itoa arg-count)))) - (setf (:@ pool-node next-node) count-node) - - (def begin-line-node (var auto (p DNode) - (mnfv mc (itoa (@:@ (@:@ frm list-node) begin-line))))) - (setf (:@ count-node next-node) begin-line-node) - - (def begin-column-node (var auto (p DNode) - (mnfv mc (itoa (@:@ (@:@ frm list-node) begin-column))))) - (setf (:@ begin-line-node next-node) begin-column-node) - - (def end-line-node (var auto (p DNode) - (mnfv mc (itoa (@:@ (@:@ frm list-node) end-line))))) - (setf (:@ begin-column-node next-node) end-line-node) - - (def end-column-node (var auto (p DNode) - (mnfv mc (itoa (@:@ (@:@ frm list-node) end-column))))) - (setf (:@ end-line-node next-node) end-column-node) - - (def macro-begin-line-node (var auto (p DNode) - (mnfv mc (itoa (@:@ (@:@ frm list-node) macro-begin-line))))) - (setf (:@ end-column-node next-node) macro-begin-line-node) - - (def macro-begin-column-node (var auto (p DNode) - (mnfv mc (itoa (@:@ (@:@ frm list-node) macro-begin-column))))) - (setf (:@ macro-begin-line-node next-node) macro-begin-column-node) - - (def macro-end-line-node (var auto (p DNode) - (mnfv mc (itoa (@:@ (@:@ frm list-node) macro-end-line))))) - (setf (:@ macro-begin-column-node next-node) macro-end-line-node) - - (def macro-end-column-node (var auto (p DNode) - (mnfv mc (itoa (@:@ (@:@ frm list-node) macro-end-column))))) - (setf (:@ macro-end-line-node next-node) macro-end-column-node) - - (def anchor-node (var auto (p DNode) macro-end-column-node)) - - (def va-dnode (var auto (p DNode))) - (def temp-node (var auto (p DNode))) - - (def charbuf (var auto (array-of 256 char))) - (def dquote (var auto char #\")) - (def token-str (var auto (p char))) - (def qq-node (var auto (p DNode))) - - (def begin (var auto int 1)) - - (label begin-loop) - (if (= arg-count 0) - (goto end-loop) - (do - (setv va-dnode - (if (= begin 1) - (@:@ frm list-node) - (@:@ va-dnode next-node))) - - (setv begin 0) - (setv arg-count (- arg-count 1)) - - (if (= 0 (@ (:@ va-dnode is-list))) - (do - (setf ($ charbuf 0) dquote) - (setv token-str (@ (:@ va-dnode token-str))) - (strncpy ($ charbuf 1) token-str (strlen token-str)) - (setf ($ charbuf (+ (cast 1 size) (strlen token-str))) dquote) - (setf ($ charbuf (+ (cast 2 size) (strlen token-str))) #\NULL) - - (setv temp-node (link-nodes-list mc 11 - (mnfv mc "std.macros.mnfv-wp") - (mnfv mc "mc") - (mnfv mc charbuf) - (mnfv mc (itoa (@:@ va-dnode begin-line))) - (mnfv mc (itoa (@:@ va-dnode begin-column))) - (mnfv mc (itoa (@:@ va-dnode end-line))) - (mnfv mc (itoa (@:@ va-dnode end-column))) - (mnfv mc (itoa (@:@ va-dnode macro-begin-line))) - (mnfv mc (itoa (@:@ va-dnode macro-begin-column))) - (mnfv mc (itoa (@:@ va-dnode macro-end-line))) - (mnfv mc (itoa (@:@ va-dnode macro-end-column))))) - (setf (:@ anchor-node next-node) temp-node) - (setv anchor-node temp-node) - 0) - (do - (if (if (not (null (@:@ va-dnode list-node))) - (if (= 0 (@:@ (@:@ va-dnode list-node) is-list)) - true - false) - false) - (if (if (= 0 (strcmp (@:@ (@:@ va-dnode list-node) token-str) "uq")) - (if (not (null (@:@ (@:@ va-dnode list-node) next-node))) - true - false) - false) - (do - (setv temp-node - (if (not (null (@:@ (@:@ (@:@ va-dnode list-node) next-node) token-str))) - (link-nodes-list mc 4 (mnfv mc "std.macros.copy") (mnfv mc "mc") (mnfv mc "false") (mnfv mc (@:@ (@:@ (@:@ va-dnode list-node) next-node) token-str))) - (link-nodes-list mc 4 (mnfv mc "std.macros.copy") (mnfv mc "mc") (mnfv mc "false") (make-node-maker mc (@:@ (@:@ va-dnode list-node) next-node))))) - (setf (:@ anchor-node next-node) temp-node) - (setv anchor-node temp-node) 0) - (if (if (= 0 (strcmp (@:@ (@:@ va-dnode list-node) token-str) "uql")) - (if (not (null (@:@ (@:@ va-dnode list-node) next-node))) - true - false) - false) - (do - (setv temp-node - (if (not (null (@:@ (@:@ (@:@ va-dnode list-node) next-node) token-str))) - (link-nodes-list mc 4 (mnfv mc "std.macros.copy") (mnfv mc "mc") (mnfv mc "true") (mnfv mc (@:@ (@:@ (@:@ va-dnode list-node) next-node) token-str))) - (link-nodes-list mc 4 (mnfv mc "std.macros.copy") (mnfv mc "mc") (mnfv mc "true") (make-node-maker mc (@:@ (@:@ va-dnode list-node) next-node))))) - (setf (:@ anchor-node next-node) temp-node) - (setv anchor-node (get-last-node temp-node) - ) 0) - (if (if (= 0 (strcmp (@:@ (@:@ va-dnode list-node) token-str) "uq-nc")) - (if (not (null (@:@ (@:@ va-dnode list-node) next-node))) - true - false) - false) - (do - (setv temp-node - (if (not (null (@:@ (@:@ (@:@ va-dnode list-node) next-node) token-str))) - (mnfv mc (@:@ (@:@ (@:@ va-dnode list-node) next-node) token-str)) - (make-node-maker mc (@:@ (@:@ va-dnode list-node) next-node)))) - (setf (:@ anchor-node next-node) temp-node) - (setv anchor-node temp-node) - 0) - (if (if (= 0 (strcmp (@:@ (@:@ va-dnode list-node) token-str) "uql-nc")) - (if (not (null (@:@ (@:@ va-dnode list-node) next-node))) - true - false) - false) - (do - (setv temp-node - (if (not (null (@:@ (@:@ (@:@ va-dnode list-node) next-node) token-str))) - (mnfv mc (@:@ (@:@ (@:@ va-dnode list-node) next-node) token-str)) - (make-node-maker mc (@:@ (@:@ va-dnode list-node) next-node)))) - (setf (:@ anchor-node next-node) temp-node) - (setv anchor-node (get-last-node temp-node)) - 0) - (do - (setv temp-node - (bqq-helper va-dnode - mc - (list-count va-dnode))) - (setf (:@ anchor-node next-node) - temp-node) - (setv anchor-node (get-last-node temp-node)) 0))))) - (do - (setv temp-node - (if (null (@:@ va-dnode list-node)) - (make-empty-list-node mc) - (bqq-helper va-dnode - mc - (list-count va-dnode)))) - (setf (:@ anchor-node next-node) - temp-node) - (setv anchor-node (get-last-node temp-node)) - 0)))) - (goto begin-loop))) - - (label end-loop) - (return holder))) - -#| -@macro std.macros.bqq - -The bootstrap quasiquotation macro. The general-use quasiquotation -macro, `qq`, is in the `macros` module. The forms handled specially -are `uq` (unquote), `uq-nc` (unquote-no-copy), `uql` (unquote-list) -and `uql-nc` (unquote-list-no-copy). The no-copy versions of these -forms should only be used when the nodes being unquoted will not be -used again. - -@param frm A node. -|# -(def bqq (macro extern (frm rest) - (def arg-count (var auto \ (arg-count mc))) - - (setv arg-count (- arg-count 1)) - (def myargcount (var auto int arg-count)) - - (def nullp (var auto (p DNode) (nullptr DNode))) - (def holder (var auto (p DNode) (make-node mc))) - - (def va-dnode (var auto (p DNode))) - (def temp-node (var auto (p DNode))) - - (def begin (var auto int 0)) - - (setf (:@ holder is-list) 1) - (setf (:@ holder list-node) frm) - (setf (:@ holder next-node) nullp) - (setv temp-node frm) - - (label begin-loop) - (if (= arg-count 0) (goto end-loop) 0) - - (setv va-dnode (@$ rest begin)) - (setv begin (+ begin 1)) - (setf (:@ temp-node next-node) va-dnode) - (setv temp-node va-dnode) - (setv arg-count (- arg-count 1)) - (goto begin-loop) - - (label end-loop) - (def x (var auto \ (bqq-helper holder mc (+ myargcount 1)))) - (return x))) - -#| -@macro std.macros.get-varargs-list - -Takes a macro context, an argument count, and a pointer to a DNode -pointer as its arguments. Returns the first node of a linked node -list containing each of the nodes from the DNode pointer list, -suitable for using as the argument to the `uql` and `uql-nc` forms. -(The third argument here is typically the macro's 'rest' argument. -The difference between 'rest' and the return value of this function is -that the nodes here will be linked together.) - -@linkage extern -|# -(def get-varargs-list - (fn extern (p DNode) ((mc (p MContext)) (arg-count int) (arglist (p (p DNode)))) - (def arg-count-original (var auto int arg-count)) - (def arg-array-original - (var auto (p (p DNode)) - (cast (pool-malloc mc - (* (sizeof (p DNode)) - (cast arg-count size))) - (p (p DNode))))) - (def arg-array (var auto (p (p DNode)) arg-array-original)) - (def index (var auto int 0)) - - (label begin) - (if (= arg-count 0) - (goto end) - (do - (setf arg-array (@$ arglist index)) - (setv index (+ index 1)) - (setv arg-array (p+ arg-array 1)) - (setv arg-count (- arg-count 1)) - (goto begin))) - - (label end) - (return (link-nodes-array arg-count-original - arg-array-original)))) - - -; Helper function only, use the simple version instead. -(def get-varargs-list (macro extern (name (count int)) - (bqq do - (def (uq name) (var auto (p DNode))) - (new-scope - (setv (uq name) (std.macros.get-varargs-list mc (uq count) rest)))))) - -#| -@macro std.macros.get-varargs-list - -Simple version of `get-varargs-list`, only takes the count as parameter. - -@linkage extern -|# -(def get-varargs-list (macro extern ((count int)) - (def name (var auto \ (make-gensym-var-node mc))) - (bqq do - (std.macros.get-varargs-list (uq name) (uq count)) - (move (uq name))))) - -(def pool-malloc' (macro extern (n T) - (bqq cast (pool-malloc mc (* (cast (uq n) size) (sizeof (uq T)))) - (p (uq T))))) - -)) - -#| -@macro @:' - -Takes a struct pointer and one or more struct member names as its -arguments. Expands to repeated calls to `@:@` over the struct and the -member names. For example, if two members are provided, the expansion -is `(@:@ (@:@ structp member1) member2)`. - -@param structp The struct pointer argument. -@param member The first member's name. -|# -(def @:' - (macro extern (structp member rest) - (def arg-count (var auto \ (arg-count mc))) - (setv arg-count (- arg-count 2)) - (def myargcount (var auto int arg-count)) - - (def frm (var auto (p DNode) (std.macros.bqq @:@ (uq-nc structp) (uq-nc member)))) - (def va-dnode (var auto (p DNode))) - - (def begin (var auto int 0)) - - (label begin-loop) - (if (= arg-count 0) (goto end-loop) 0) - - (setv va-dnode (@$ rest begin)) - (setv begin (+ begin 1)) - (setv frm (std.macros.bqq @:@ (uq-nc frm) (uq-nc va-dnode))) - (setv arg-count (- arg-count 1)) - (goto begin-loop) - - (label end-loop) - (return frm))) diff --git a/modules/macros.dt b/modules/macros.dt index d78938e4..9b42f942 100644 --- a/modules/macros.dt +++ b/modules/macros.dt @@ -1,17 +1,1145 @@ #| @module macros -Provides the quasiquotation macro. +Provides the core macro development functions: making, copying and +printing nodes, linking nodes together, gensym functions for +variables and labels, and the quasiquotation form. |# (module macros (attr cto)) (import cstdio-core) -(import macros-core) (import introspection) (namespace std (namespace macros +#| +@fn std.macros.make-node + +Returns a newly-allocated node. + +@param mc An MContext. +|# +(def make-node + (fn extern (p DNode) ((mc (p MContext))) + (def dnsize (var auto size (sizeof DNode))) + (def n (var auto (p DNode) + (cast (pool-malloc mc dnsize) (p DNode)))) + (memset (cast n (p void)) 0 (sizeof DNode)) + (setf (: (@ n) filename) (nullptr char)) + n)) + +#| +@fn std.macros.make-empty-list-node + +Returns a newly-allocated empty list node. + +@param mc An MContext. +|# +(def make-empty-list-node + (fn extern (p DNode) ((mc (p MContext))) + (def node (var auto \ (make-node mc))) + (setf (:@ node is-list) 1) + (return node))) + +#| +@fn std.macros.is-non-empty-list + +@param form The node. +|# +(def is-non-empty-list + (fn extern bool ((form (p DNode))) + (if (= 1 (@:@ form is-list)) + (if (not (null (@:@ form list-node))) + true + false) + false))) + +#| +@fn std.macros.copy + +@param mc An MContext. +@param follow Whether to include the nodes that follow `form`. +@param form The node to copy. +@return A copy of `form`. +|# +(def copy + (fn extern (p DNode) ((mc (p MContext)) + (follow bool) + (form (p DNode))) + (def nullp (var auto (p DNode) (cast 0 (p DNode)))) + (def new-node (var auto (p DNode) (make-node mc))) + + (memcpy (cast new-node (p void)) + (cast form (p void)) + (cast (sizeof DNode) int)) + + (if (not (null (@:@ form list-node))) + (setf (:@ new-node list-node) + (copy mc true (@:@ form list-node))) + true) + + (setf (:@ new-node next-node) + (if follow + (if (not (null (@:@ form next-node))) + (copy mc true (@:@ form next-node)) + nullp) + nullp)) + + (return new-node))) + +#| +@fn std.macros.copy-qstr + +As per `copy`, except that if the first node is a token, it will have +double-quotations marks added at the start and end of it in the copied +node. + +@param mc An MContext. +@param form The node to copy. +@param follow Whether to include the nodes that follow `form`. +@return A copy of `form`. +|# +(def copy-qstr + (fn extern (p DNode) ((mc (p MContext)) + (form (p DNode)) + (follow bool)) + (def nullp (var auto (p DNode) (cast 0 (p DNode)))) + (def new-node (var auto (p DNode) (make-node mc))) + (def dquote (var auto char #\")) + (def len (var auto size 0)) + (def charbuf (var auto (p char) + (cast (pool-malloc mc (cast 256 size)) (p char)))) + + (if (= 0 (@:@ form is-list)) + (do + (setf ($ charbuf 0) dquote) + (setv len (strlen (@ (: (@ form) token-str)))) + (strncpy ($ charbuf 1) (@ (: (@ form) token-str)) len) + (setf ($ charbuf (+ (cast 1 size) len)) dquote) + (setf ($ charbuf (+ (cast 2 size) len)) #\NULL) + (setf (:@ new-node is-list) 0) + (setf (:@ new-node token-str) charbuf) + (setf (:@ new-node list-node) nullp) + + (setf (:@ new-node next-node) + (if follow + (if (not (null (@:@ form next-node))) + (do (copy mc true (@:@ form next-node))) + nullp) + nullp))) + (do + (setf (:@ new-node is-list) 1) + (if (not (null (@:@ form list-node))) + (do (setf (:@ new-node list-node) + (copy mc true (@:@ form list-node))) + 0) + 0))) + + (setf (:@ new-node begin-line) (@:@ form begin-line)) + (setf (:@ new-node begin-column) (@:@ form begin-column)) + (setf (:@ new-node end-line) (@:@ form end-line)) + (setf (:@ new-node end-column) (@:@ form end-column)) + (setf (:@ new-node macro-begin-line) (@:@ form macro-begin-line)) + (setf (:@ new-node macro-begin-column) (@:@ form macro-begin-column)) + (setf (:@ new-node macro-end-line) (@:@ form macro-end-line)) + (setf (:@ new-node macro-end-column) (@:@ form macro-end-column)) + + (setf (:@ new-node next-node) + (if follow + (if (not (null (@:@ form next-node))) + (do (copy mc true (@:@ form next-node))) + nullp) + nullp)) + + (return new-node))) + +#| +@fn std.macros.copy-to + +Copy (shallow) the details of the source node to the destination node. + +@param dst The destination node. +@param src The source node. +|# +(def copy-to + (fn extern void ((dst (p DNode)) (src (p DNode))) + (setf (:@ dst is-list) (@:@ src is-list)) + (setf (:@ dst token-str) (@:@ src token-str)) + (setf (:@ dst list-node) (@:@ src list-node)) + (setf (:@ dst begin-line) (@:@ src begin-line)) + (setf (:@ dst begin-column) (@:@ src begin-column)) + (setf (:@ dst end-line) (@:@ src end-line)) + (setf (:@ dst end-column) (@:@ src end-column)) + (setf (:@ dst macro-begin-line) (@:@ src macro-begin-line)) + (setf (:@ dst macro-begin-column) (@:@ src macro-begin-column)) + (setf (:@ dst macro-end-line) (@:@ src macro-end-line)) + (setf (:@ dst macro-end-column) (@:@ src macro-end-column)) + (setf (:@ dst filename) (@:@ src filename)) + (return))) + +#| +@fn std.macros.print + +Prints the node to `stdout`. + +@param form The node to print. +|# +(def print + (fn extern bool ((form (p DNode))) + (if (= 0 (@:@ form is-list)) + (do (printf "%s" (@:@ form token-str)) + true) + (do (printf "(") + (if (not (null (@:@ form list-node))) + (print (@:@ form list-node)) + true) + (printf ")") + true)) + (if (not (null (@:@ form next-node))) + (do (printf " ") + (return (print (@:@ form next-node)))) + true))) + +#| +@fn std.macros.sprint + +Prints the node to the provided buffer. + +@param buf The buffer to which the node will be printed. +@param form The node to print. +|# +(def sprint + (fn extern bool ((buf (p char)) (form (p DNode))) + (def cc (var auto (p char) buf)) + (if (= 0 (@:@ form is-list)) + (do (sprintf buf "%s" (@:@ form token-str)) + (setv buf (strchr buf (cast #\NULL int))) + true) + (do (setf ($ buf 0) (cast 40 char)) + (setv buf (p+ buf 1)) + (setf buf #\NULL) + (if (not (null (@:@ form list-node))) + (sprint buf (@:@ form list-node)) + 0) + (setv buf (strchr buf (cast #\NULL int))) + (setf ($ buf 0) (cast 41 char)) + (setv buf (p+ buf 1)) + (setf buf #\NULL) + true)) + (if (not (null (@:@ form next-node))) + (do (setf ($ buf 0) #\SPACE) + (setv buf (p+ buf 1)) + (setf buf #\NULL) + (return (sprint buf (@:@ form next-node)))) + true))) + +#| +@fn std.macros.get-last-node + +Returns the last node in the list, by iterating over `next-node` +(i.e. this does not descend into the `list-node` of the argument +node). + +@param form The node for which the last node should be found. +@return The last node. +|# +(def get-last-node + (fn extern (p DNode) ((form (p DNode))) + (label begin-loop) + (if (null (@:@ form next-node)) + (return form) + (do (setv form (@:@ form next-node)) + (goto begin-loop))))) + +#| +@fn std.macros.mnfv + +Short for 'make-node-from-value'. There are several implementations of +this function: each is similar to `make-node`, except that each takes +an additional argument, which is used to populate the `token-str` of +the newly-allocated node. This implementation takes a `(p char)`, +copies it, and sets it in the new node. + +@param mc An MContext. +@param token-string The token string for the new node. +|# +(def mnfv + (fn extern (p DNode) ((mc (p MContext)) + (token-string (p (const char)))) + (def d-node (var auto (p DNode) (make-node mc))) + (def nullp (var auto (p DNode) (nullptr DNode))) + (def charp (var auto (p char) + (cast (pool-malloc mc (cast 256 size)) (p char)))) + (strncpy charp token-string (cast 256 size)) + (setf (:@ d-node is-list) 0) + (setf (:@ d-node token-str) charp) + (setf (:@ d-node list-node) nullp) + (setf (:@ d-node next-node) nullp) + (return d-node))) + +#| +@fn std.macros.mnfv + +@param mc An MContext. +@param n An integer. +|# +(def mnfv + (fn extern (p DNode) ((mc (p MContext)) + (n int)) + (def x (var auto (array-of 255 char))) + (sprintf x "%d" n) + (mnfv mc x))) + +#| +@fn std.macros.mnfv + +@param mc An MContext. +@param n A uint64 integer. +|# +(def mnfv + (fn extern (p DNode) ((mc (p MContext)) + (n uint64)) + (def x (var auto (array-of 255 char))) + (sprintf x "%lu" n) + (mnfv mc x))) + +#| +@fn std.macros.mnfv + +@param mc An MContext. +@param f A float. +|# +(def mnfv + (fn extern (p DNode) ((mc (p MContext)) + (f float)) + (def x (var auto (array-of 255 char))) + (sprintf x "%f" f) + (mnfv mc x))) + +#| +@fn std.macros.mnfv + +@param mc An MContext. +@param d A double. +|# +(def mnfv + (fn extern (p DNode) ((mc (p MContext)) + (d double)) + (def x (var auto (array-of 255 char))) + (sprintf x "%f" d) + (mnfv mc x))) + +#| +@fn std.macros.mnfv + +@param mc An MContext. +@param ld A long double. +|# +(def mnfv + (fn extern (p DNode) ((mc (p MContext)) + (ld long-double)) + (def x (var auto (array-of 255 char))) + (sprintf x "%Lf" ld) + (mnfv mc x))) + +#| +@fn std.macros.mnfv-wp + +Short for 'make-node-from-value-with-position'. Takes additional node +position arguments, and sets them accordingly on the new node. Only +implemented for `(p char)` values. + +@param mc An MContext. +@param token-string A string. +@param begin-line The beginning line number for the node. +@param begin-column The beginning column number for the node. +@param end-line The ending line number for the node. +@param end-column The ending column number for the node. +@param macro-begin-line The beginning macro line number. +@param macro-begin-column The beginning macro column number. +@param macro-end-line The ending macro line number. +@param macro-end-column The ending macro column number. +|# +(def mnfv-wp + (fn extern (p DNode) ((mc (p MContext)) + (token-string (p (const char))) + (begin-line int) + (begin-column int) + (end-line int) + (end-column int) + (macro-begin-line int) + (macro-begin-column int) + (macro-end-line int) + (macro-end-column int)) + (def n (var auto \ (mnfv mc token-string))) + (setf (:@ n begin-line) begin-line) + (setf (:@ n begin-column) begin-column) + (setf (:@ n end-line) end-line) + (setf (:@ n end-column) end-column) + (setf (:@ n macro-begin-line) macro-begin-line) + (setf (:@ n macro-begin-column) macro-begin-column) + (setf (:@ n macro-end-line) macro-end-line) + (setf (:@ n macro-end-column) macro-end-column) + (return n))) + +#| +@fn std.macros.link-nodes + +Links the provided nodes together, without copying them, and returns +the first provided node. This is a varargs function. Note that the +`next-node` member of the last node is not nulled. + +@param argcount The number of nodes being provided. +@return The first node that was provided. +|# +(def link-nodes + (fn extern (p DNode) ((argcount int) ...) + (def nullp (var auto (p DNode) (cast 0 (p DNode)))) + (def very-fst-node (var auto (p DNode))) + (def fst-node (var auto (p DNode))) + (def snd-node (var auto (p DNode))) + + (def arglist (var auto va-list)) + (va-start (cast (# arglist) (p void))) + + (setv very-fst-node (va-arg (# arglist) (p DNode))) + (setv fst-node very-fst-node) + + (label begin-loop) + (if (= 1 argcount) + (goto end-loop) + (do + (setv snd-node (va-arg (# arglist) (p DNode))) + (setf (: (@ fst-node) next-node) snd-node) + (setv fst-node (get-last-node snd-node)) + (setv argcount (- argcount 1)) + (goto begin-loop))) + + (label end-loop) + (va-end (cast (# arglist) (p void))) + (return very-fst-node))) + +#| +@fn std.macros.link-nodes-list + +As per `link-nodes`, except that an additional list node is allocated +and returned. This list node points to the first provided node as its +`list-node`. + +@param mc An MContext. +@param argcount The number of varargs being provided. +|# +(def link-nodes-list + (fn extern (p DNode) ((mc (p MContext)) (argcount int) ...) + (def link-node (var auto (p DNode) (make-node mc))) + (def nullp (var auto (p DNode) (cast 0 (p DNode)))) + + (def very-fst-node (var auto (p DNode))) + (def fst-node (var auto (p DNode))) + (def snd-node (var auto (p DNode))) + + (def arglist (var auto va-list)) + (va-start (cast (# arglist) (p void))) + + (setv very-fst-node (va-arg (# arglist) (p DNode))) + (setv fst-node very-fst-node) + + (label begin-loop) + (if (= 1 argcount) + (goto end-loop) + (do + (setv snd-node (va-arg (# arglist) (p DNode))) + (setf (: (@ fst-node) next-node) snd-node) + (setv fst-node (get-last-node snd-node)) + (setv argcount (- argcount 1)) + (goto begin-loop))) + + (label end-loop) + (va-end (cast (# arglist) (p void))) + (setf (:@ link-node is-list) 1) + (setf (:@ link-node next-node) nullp) + (setf (:@ link-node list-node) very-fst-node) + (return link-node))) + +#| +@fn std.macros.link-nodes-list-wp + +As per `link-nodes-list`, except it also accepts additional node +position arguments, and sets them accordingly on the newly-allocated +list node. + +@param mc An MContext. +@param argcount The number of varargs being provided. +@param begin-line The beginning line number for the node. +@param begin-column The beginning column number for the node. +@param end-line The ending line number for the node. +@param end-column The ending column number for the node. +@param macro-begin-line The beginning macro line number. +@param macro-begin-column The beginning macro column number. +@param macro-end-line The ending macro line number. +@param macro-end-column The ending macro column number. +|# +(def link-nodes-list-wp + (fn extern (p DNode) ((mc (p MContext)) + (argcount int) + (begin-line int) + (begin-column int) + (end-line int) + (end-column int) + (macro-begin-line int) + (macro-begin-column int) + (macro-end-line int) + (macro-end-column int) + ...) + (def link-node (var auto (p DNode) (make-node mc))) + (def nullp (var auto (p DNode) (cast 0 (p DNode)))) + + (def very-fst-node (var auto (p DNode))) + (def fst-node (var auto (p DNode))) + (def snd-node (var auto (p DNode))) + + (def arglist (var auto va-list)) + (va-start (cast (# arglist) (p void))) + + (setv very-fst-node (va-arg (# arglist) (p DNode))) + (setv fst-node very-fst-node) + + (label begin-loop) + (if (= 1 argcount) + (goto end-loop) + (do + (setv snd-node (va-arg (# arglist) (p DNode))) + (setf (: (@ fst-node) next-node) snd-node) + (setv fst-node (get-last-node snd-node)) + (setv argcount (- argcount 1)) + (goto begin-loop))) + + (label end-loop) + (va-end (cast (# arglist) (p void))) + (setf (: (@ link-node) is-list) 1) + (setf (: (@ link-node) next-node) nullp) + (setf (: (@ link-node) list-node) very-fst-node) + + (setf (: (@ link-node) begin-line) begin-line) + (setf (: (@ link-node) begin-column) begin-column) + (setf (: (@ link-node) end-line) end-line) + (setf (: (@ link-node) end-column) end-column) + (setf (: (@ link-node) macro-begin-line) macro-begin-line) + (setf (: (@ link-node) macro-begin-column) macro-begin-column) + (setf (: (@ link-node) macro-end-line) macro-end-line) + (setf (: (@ link-node) macro-end-column) macro-end-column) + + (return link-node))) + +#| +@fn std.macros.link-nodes-array + +As per `link-nodes`, except that instead of being a varargs function, +it takes an array of nodes as its second argument. + +@param argcount The number of arguments in the array. +@param arg-array The argument array. +|# +(def link-nodes-array + (fn extern (p DNode) ((argcount int) (arg-array (p (p DNode)))) + (if (= argcount 0) + (return (nullptr DNode)) + 0) + + (def nullp (var auto (p DNode) (cast 0 (p DNode)))) + (def very-fst-node (var auto (p DNode))) + (def fst-node (var auto (p DNode))) + (def snd-node (var auto (p DNode))) + + (setv very-fst-node (@ arg-array)) + (setv fst-node very-fst-node) + (setv arg-array (p+ arg-array 1)) + (setv argcount (- argcount 1)) + + (label begin-loop) + (if (= 0 argcount) + (goto end-loop) + (do + (setv snd-node (@ arg-array)) + (setf (: (@ fst-node) next-node) snd-node) + (setv fst-node snd-node) + (setv argcount (- argcount 1)) + (setv arg-array (p+ arg-array 1)) + (goto begin-loop))) + + (label end-loop) + (return very-fst-node))) + +(def var-marker (var intern int 0)) +#| +@fn std.macros.gensym-var + +Prints a new, unused variable name to the provided buffer. + +@param buf The buffer for the variable name. +|# +(def gensym-var + (fn extern bool ((buf (p char))) + (sprintf buf "_dale_internal_var_%d" var-marker) + (setv var-marker (+ var-marker 1)) + true)) + +(def label-marker (var intern int 0)) +#| +@fn std.macros.gensym-label + +Prints a new, unused label name to the provided buffer. The prefix is +included in the new label name, so that it is a little easier to +determine what's happening when errors occur in the generated code. + +@param buf The buffer for the label name. +@param prefix The prefix for the label name. +|# +(def gensym-label + (fn extern bool ((buf (p char)) (prefix (p (const char)))) + (if (null prefix) + (setv prefix "na") + true) + (sprintf buf "_dale_internal_label_%s_%d" prefix label-marker) + (setv label-marker (+ label-marker 1)) + true)) + +#| +@fn std.macros.make-gensym-label-node + +Generates a new label name, constructs a token node to suit and +returns that node. + +@param mc An MContext. +@param prefix The prefix for the label name. +|# +(def make-gensym-label-node + (fn extern (p DNode) ((mc (p MContext)) (prefix (p (const char)))) + (def label-name + (var auto (p char) + (cast (pool-malloc mc (cast 150 size)) (p char)))) + (gensym-label label-name prefix) + (mnfv mc label-name))) + +#| +@fn std.macros.make-gensym-label-node + +As per the previous implementation, except that no prefix is required +(it is set to the empty string). + +@param mc An MContext. +|# +(def make-gensym-label-node + (fn extern (p DNode) ((mc (p MContext))) + (make-gensym-label-node mc ""))) + +#| +@fn std.macros.is-gensym-label + +Determines whether the provided label node is a gensym label with the +specified prefix. + +@param label-node The label node. +@param prefix The prefix for which to check in the label node. +|# +(def is-gensym-label + (fn extern bool ((label-node (p DNode)) (prefix (p (const char)))) + (if (null (@:@ label-node token-str)) + (return false) + 0) + (def match-str (var auto (array-of 150 char))) + (sprintf match-str "_dale_internal_label_%s_" prefix) + (if (!= 0 (strncmp (@:@ label-node token-str) + match-str + (strlen match-str))) + (return false) + 0) + (return true))) + +#| +@fn std.macros.make-gensym-var-node + +Generates a new variable name, constructs a token node to suit and +returns that node. + +@param mc An MContext. +|# +(def make-gensym-var-node + (fn extern (p DNode) ((mc (p MContext))) + (def var-name + (var auto \ (cast (pool-malloc mc (cast 30 size)) (p char)))) + (gensym-var var-name) + (mnfv mc var-name))) + +#| +@fn std.macros.walk-nodes + +'Walks' through a node, recursively, calling the provided function +pointer on each node. The provided `data` argument is passed to the +function pointer on each call. + +@param form The node to walk. +@param mc An MContext. +@param data Arbitrary data. +@param fn The function pointer to call on each node. +|# +(def walk-nodes + (fn extern bool ((form (p DNode)) + (mc (p MContext)) + (data (p void)) + (fn (p (fn int ((form (p DNode)) + (mc (p MContext)) + (data (p void))))))) + (if (not (null (@:@ form list-node))) + (walk-nodes (@:@ form list-node) mc data fn) + true) + (funcall fn form mc data) + (if (not (null (@:@ form next-node))) + (walk-nodes (@:@ form next-node) mc data fn) + true) + true)) + +#| +@fn std.macros.list-count + +Takes a list node, and counts the number of nodes that are within that +list. This is not recursive: it just counts the top-level nodes from +the list. + +@param form A list node. +|# +(def list-count + (fn extern int ((form (p DNode))) + (def count (var auto int 0)) + (def el-node (var auto (p DNode) (@ (:@ form list-node)))) + (label begin-loop) + (if (null el-node) + (goto end-loop) + (do (setv count (+ count 1)) + (setv el-node (@ (:@ el-node next-node))) + (goto begin-loop))) + (label end-loop) + (return count))) + +#| +@fn std.macros.make-node-maker + +Constructs a node that, when evaluated, constructs the provided node. +For example, if the node is a simple token, then the returned node +will be `(mnfv mc token-str)`, where `token-str` is the token +from the provided node. + +@param mc An MContext. +@param form A node. +|# +(def make-node-maker + (fn extern (p DNode) ((mc (p MContext)) (form (p DNode))) + (def charbuf (var auto (array-of 256 char))) + (def dquote (var auto char #\")) + + (def myres (var auto (p DNode) + (if (= 0 (@:@ form is-list)) + (do + (setf ($ charbuf 0) dquote) + (strncpy ($ charbuf 1) + (@:@ form token-str) + (strlen (@:@ form token-str))) + (setf ($ charbuf + (+ (cast 1 size) (strlen (@:@ form token-str)))) + dquote) + (setf ($ charbuf + (+ (cast 2 size) (strlen (@:@ form token-str)))) + #\NULL) + (link-nodes-list mc 3 + (mnfv mc "std.macros.mnfv") + (mnfv mc "mc") + (mnfv mc charbuf))) + (do + (def holder + (var auto (p DNode) (make-node mc))) + (setf (:@ holder is-list) 1) + (setf (:@ holder list-node) (nullptr DNode)) + (setf (:@ holder next-node) (nullptr DNode)) + (def topnode + (var auto (p DNode) (mnfv mc "std.macros.link-nodes-list"))) + (setf (:@ holder list-node) topnode) + (def poolnode + (var auto (p DNode) (mnfv mc "mc"))) + (setf (:@ topnode next-node) poolnode) + + (def cnode + (var auto \ (@:@ form list-node))) + (def count (var auto \ 1)) + (label begin) + (if (null (@:@ cnode next-node)) + (goto end) + (do (setv count (+ count 1)) + (setv cnode (@:@ cnode next-node)) + (goto begin))) + (label end) + + (def countnode + (var auto (p DNode) (mnfv mc count))) + (setf (:@ poolnode next-node) countnode) + + (def elnode (var auto (p DNode) countnode)) + (def nextelnode (var auto (p DNode))) + + (setv cnode (@:@ form list-node)) + + (label begin2) + (do (setv nextelnode (make-node-maker mc cnode)) + (setf (:@ elnode next-node) nextelnode) + (setv elnode nextelnode) + (if (null (@:@ cnode next-node)) + (goto end2) + (do (setv cnode (@:@ cnode next-node)) + (goto begin2)))) + (label end2) + holder)))) + + (return myres))) + +(def itoa-str (var intern (array-of 50 char))) +(def itoa + (fn extern (p char) ((n int)) + (sprintf itoa-str "%d" n) + (return itoa-str))) + +#| +@fn std.macros.bqq-helper + +A helper function for `bqq` (bootstrap-qq). + +@param frm A node. +@param mc An MContext. +@param arg-count The number of elements in the node. +|# +(def bqq-helper + (fn intern (p DNode) ((frm (p DNode)) + (mc (p MContext)) + (arg-count int)) + (def nullp (var auto (p DNode) (cast 0 (p DNode)))) + + (def holder (var auto (p DNode) (make-node mc))) + (setf (:@ holder is-list) 1) + (setf (:@ holder list-node) nullp) + (setf (:@ holder next-node) nullp) + + (def ln-node (var auto (p DNode) + (mnfv mc "std.macros.link-nodes-list-wp"))) + (setf (:@ holder list-node) ln-node) + + (def pool-node (var auto (p DNode) (mnfv mc "mc"))) + (setf (:@ ln-node next-node) pool-node) + + (def count-node (var auto (p DNode) (mnfv mc (itoa arg-count)))) + (setf (:@ pool-node next-node) count-node) + + (def begin-line-node (var auto (p DNode) + (mnfv mc (itoa (@:@ (@:@ frm list-node) begin-line))))) + (setf (:@ count-node next-node) begin-line-node) + + (def begin-column-node (var auto (p DNode) + (mnfv mc (itoa (@:@ (@:@ frm list-node) begin-column))))) + (setf (:@ begin-line-node next-node) begin-column-node) + + (def end-line-node (var auto (p DNode) + (mnfv mc (itoa (@:@ (@:@ frm list-node) end-line))))) + (setf (:@ begin-column-node next-node) end-line-node) + + (def end-column-node (var auto (p DNode) + (mnfv mc (itoa (@:@ (@:@ frm list-node) end-column))))) + (setf (:@ end-line-node next-node) end-column-node) + + (def macro-begin-line-node (var auto (p DNode) + (mnfv mc (itoa (@:@ (@:@ frm list-node) macro-begin-line))))) + (setf (:@ end-column-node next-node) macro-begin-line-node) + + (def macro-begin-column-node (var auto (p DNode) + (mnfv mc (itoa (@:@ (@:@ frm list-node) macro-begin-column))))) + (setf (:@ macro-begin-line-node next-node) macro-begin-column-node) + + (def macro-end-line-node (var auto (p DNode) + (mnfv mc (itoa (@:@ (@:@ frm list-node) macro-end-line))))) + (setf (:@ macro-begin-column-node next-node) macro-end-line-node) + + (def macro-end-column-node (var auto (p DNode) + (mnfv mc (itoa (@:@ (@:@ frm list-node) macro-end-column))))) + (setf (:@ macro-end-line-node next-node) macro-end-column-node) + + (def anchor-node (var auto (p DNode) macro-end-column-node)) + + (def va-dnode (var auto (p DNode))) + (def temp-node (var auto (p DNode))) + + (def charbuf (var auto (array-of 256 char))) + (def dquote (var auto char #\")) + (def token-str (var auto (p char))) + (def qq-node (var auto (p DNode))) + + (def begin (var auto int 1)) + + (label begin-loop) + (if (= arg-count 0) + (goto end-loop) + (do + (setv va-dnode + (if (= begin 1) + (@:@ frm list-node) + (@:@ va-dnode next-node))) + + (setv begin 0) + (setv arg-count (- arg-count 1)) + + (if (= 0 (@ (:@ va-dnode is-list))) + (do + (setf ($ charbuf 0) dquote) + (setv token-str (@ (:@ va-dnode token-str))) + (strncpy ($ charbuf 1) token-str (strlen token-str)) + (setf ($ charbuf (+ (cast 1 size) (strlen token-str))) dquote) + (setf ($ charbuf (+ (cast 2 size) (strlen token-str))) #\NULL) + + (setv temp-node (link-nodes-list mc 11 + (mnfv mc "std.macros.mnfv-wp") + (mnfv mc "mc") + (mnfv mc charbuf) + (mnfv mc (itoa (@:@ va-dnode begin-line))) + (mnfv mc (itoa (@:@ va-dnode begin-column))) + (mnfv mc (itoa (@:@ va-dnode end-line))) + (mnfv mc (itoa (@:@ va-dnode end-column))) + (mnfv mc (itoa (@:@ va-dnode macro-begin-line))) + (mnfv mc (itoa (@:@ va-dnode macro-begin-column))) + (mnfv mc (itoa (@:@ va-dnode macro-end-line))) + (mnfv mc (itoa (@:@ va-dnode macro-end-column))))) + (setf (:@ anchor-node next-node) temp-node) + (setv anchor-node temp-node) + 0) + (do + (if (if (not (null (@:@ va-dnode list-node))) + (if (= 0 (@:@ (@:@ va-dnode list-node) is-list)) + true + false) + false) + (if (if (= 0 (strcmp (@:@ (@:@ va-dnode list-node) token-str) "uq")) + (if (not (null (@:@ (@:@ va-dnode list-node) next-node))) + true + false) + false) + (do + (setv temp-node + (if (not (null (@:@ (@:@ (@:@ va-dnode list-node) next-node) token-str))) + (link-nodes-list mc 4 (mnfv mc "std.macros.copy") (mnfv mc "mc") (mnfv mc "false") (mnfv mc (@:@ (@:@ (@:@ va-dnode list-node) next-node) token-str))) + (link-nodes-list mc 4 (mnfv mc "std.macros.copy") (mnfv mc "mc") (mnfv mc "false") (make-node-maker mc (@:@ (@:@ va-dnode list-node) next-node))))) + (setf (:@ anchor-node next-node) temp-node) + (setv anchor-node temp-node) 0) + (if (if (= 0 (strcmp (@:@ (@:@ va-dnode list-node) token-str) "uql")) + (if (not (null (@:@ (@:@ va-dnode list-node) next-node))) + true + false) + false) + (do + (setv temp-node + (if (not (null (@:@ (@:@ (@:@ va-dnode list-node) next-node) token-str))) + (link-nodes-list mc 4 (mnfv mc "std.macros.copy") (mnfv mc "mc") (mnfv mc "true") (mnfv mc (@:@ (@:@ (@:@ va-dnode list-node) next-node) token-str))) + (link-nodes-list mc 4 (mnfv mc "std.macros.copy") (mnfv mc "mc") (mnfv mc "true") (make-node-maker mc (@:@ (@:@ va-dnode list-node) next-node))))) + (setf (:@ anchor-node next-node) temp-node) + (setv anchor-node (get-last-node temp-node) + ) 0) + (if (if (= 0 (strcmp (@:@ (@:@ va-dnode list-node) token-str) "uq-nc")) + (if (not (null (@:@ (@:@ va-dnode list-node) next-node))) + true + false) + false) + (do + (setv temp-node + (if (not (null (@:@ (@:@ (@:@ va-dnode list-node) next-node) token-str))) + (mnfv mc (@:@ (@:@ (@:@ va-dnode list-node) next-node) token-str)) + (make-node-maker mc (@:@ (@:@ va-dnode list-node) next-node)))) + (setf (:@ anchor-node next-node) temp-node) + (setv anchor-node temp-node) + 0) + (if (if (= 0 (strcmp (@:@ (@:@ va-dnode list-node) token-str) "uql-nc")) + (if (not (null (@:@ (@:@ va-dnode list-node) next-node))) + true + false) + false) + (do + (setv temp-node + (if (not (null (@:@ (@:@ (@:@ va-dnode list-node) next-node) token-str))) + (mnfv mc (@:@ (@:@ (@:@ va-dnode list-node) next-node) token-str)) + (make-node-maker mc (@:@ (@:@ va-dnode list-node) next-node)))) + (setf (:@ anchor-node next-node) temp-node) + (setv anchor-node (get-last-node temp-node)) + 0) + (do + (setv temp-node + (bqq-helper va-dnode + mc + (list-count va-dnode))) + (setf (:@ anchor-node next-node) + temp-node) + (setv anchor-node (get-last-node temp-node)) 0))))) + (do + (setv temp-node + (if (null (@:@ va-dnode list-node)) + (make-empty-list-node mc) + (bqq-helper va-dnode + mc + (list-count va-dnode)))) + (setf (:@ anchor-node next-node) + temp-node) + (setv anchor-node (get-last-node temp-node)) + 0)))) + (goto begin-loop))) + + (label end-loop) + (return holder))) + +#| +@macro std.macros.bqq + +The bootstrap quasiquotation macro. The general-use quasiquotation +macro, `qq`, is in the `macros` module. The forms handled specially +are `uq` (unquote), `uq-nc` (unquote-no-copy), `uql` (unquote-list) +and `uql-nc` (unquote-list-no-copy). The no-copy versions of these +forms should only be used when the nodes being unquoted will not be +used again. + +@param frm A node. +|# +(def bqq (macro extern (frm rest) + (def arg-count (var auto \ (arg-count mc))) + + (setv arg-count (- arg-count 1)) + (def myargcount (var auto int arg-count)) + + (def nullp (var auto (p DNode) (nullptr DNode))) + (def holder (var auto (p DNode) (make-node mc))) + + (def va-dnode (var auto (p DNode))) + (def temp-node (var auto (p DNode))) + + (def begin (var auto int 0)) + + (setf (:@ holder is-list) 1) + (setf (:@ holder list-node) frm) + (setf (:@ holder next-node) nullp) + (setv temp-node frm) + + (label begin-loop) + (if (= arg-count 0) (goto end-loop) 0) + + (setv va-dnode (@$ rest begin)) + (setv begin (+ begin 1)) + (setf (:@ temp-node next-node) va-dnode) + (setv temp-node va-dnode) + (setv arg-count (- arg-count 1)) + (goto begin-loop) + + (label end-loop) + (def x (var auto \ (bqq-helper holder mc (+ myargcount 1)))) + (return x))) + +#| +@macro std.macros.get-varargs-list + +Takes a macro context, an argument count, and a pointer to a DNode +pointer as its arguments. Returns the first node of a linked node +list containing each of the nodes from the DNode pointer list, +suitable for using as the argument to the `uql` and `uql-nc` forms. +(The third argument here is typically the macro's 'rest' argument. +The difference between 'rest' and the return value of this function is +that the nodes here will be linked together.) + +@linkage extern +|# +(def get-varargs-list + (fn extern (p DNode) ((mc (p MContext)) (arg-count int) (arglist (p (p DNode)))) + (def arg-count-original (var auto int arg-count)) + (def arg-array-original + (var auto (p (p DNode)) + (cast (pool-malloc mc + (* (sizeof (p DNode)) + (cast arg-count size))) + (p (p DNode))))) + (def arg-array (var auto (p (p DNode)) arg-array-original)) + (def index (var auto int 0)) + + (label begin) + (if (= arg-count 0) + (goto end) + (do + (setf arg-array (@$ arglist index)) + (setv index (+ index 1)) + (setv arg-array (p+ arg-array 1)) + (setv arg-count (- arg-count 1)) + (goto begin))) + + (label end) + (return (link-nodes-array arg-count-original + arg-array-original)))) + + +; Helper function only, use the simple version instead. +(def get-varargs-list (macro extern (name (count int)) + (bqq do + (def (uq name) (var auto (p DNode))) + (new-scope + (setv (uq name) (std.macros.get-varargs-list mc (uq count) rest)))))) + +#| +@macro std.macros.get-varargs-list + +Simple version of `get-varargs-list`, only takes the count as parameter. + +@linkage extern +|# +(def get-varargs-list (macro extern ((count int)) + (def name (var auto \ (make-gensym-var-node mc))) + (bqq do + (std.macros.get-varargs-list (uq name) (uq count)) + (move (uq name))))) + +(def pool-malloc' (macro extern (n T) + (bqq cast (pool-malloc mc (* (cast (uq n) size) (sizeof (uq T)))) + (p (uq T))))) + +#| +@macro @:' + +Takes a struct pointer and one or more struct member names as its +arguments. Expands to repeated calls to `@:@` over the struct and the +member names. For example, if two members are provided, the expansion +is `(@:@ (@:@ structp member1) member2)`. + +@param structp The struct pointer argument. +@param member The first member's name. +|# +(def @:' + (macro extern (structp member rest) + (def arg-count (var auto \ (arg-count mc))) + (setv arg-count (- arg-count 2)) + (def myargcount (var auto int arg-count)) + + (def frm (var auto (p DNode) (std.macros.bqq @:@ (uq-nc structp) (uq-nc member)))) + (def va-dnode (var auto (p DNode))) + + (def begin (var auto int 0)) + + (label begin-loop) + (if (= arg-count 0) (goto end-loop) 0) + + (setv va-dnode (@$ rest begin)) + (setv begin (+ begin 1)) + (setv frm (std.macros.bqq @:@ (uq-nc frm) (uq-nc va-dnode))) + (setv arg-count (- arg-count 1)) + (goto begin-loop) + + (label end-loop) + (return frm))) + (def is-unquote-node (fn extern bool ((frm (p DNode))) (def ts (var auto \ (@:@ frm token-str))) (if (null ts) @@ -122,7 +1250,7 @@ nodes are supported. (def vn (var auto \ (make-gensym-var-node mc))) - (def current-firstnode (var auto (p DNode) (bqq @:' (uq vn) list-node))) + (def current-firstnode (var auto (p DNode) (bqq std.macros.@:' (uq vn) list-node))) (def current-lastnode (var auto (p DNode) (@:' current-firstnode list-node next-node next-node))) diff --git a/modules/operator-macros.dt b/modules/operator-macros.dt index ace04328..7109fb1d 100644 --- a/modules/operator-macros.dt +++ b/modules/operator-macros.dt @@ -12,7 +12,6 @@ following operators: (module operator-macros (attr cto)) (import macros) -(import macros-core) (import stdlib) (namespace std (namespace macros diff --git a/modules/stdlib.dt b/modules/stdlib.dt index 9b5bb4f0..6876a2ad 100644 --- a/modules/stdlib.dt +++ b/modules/stdlib.dt @@ -9,7 +9,7 @@ provided by this library are in the root namespace. (module stdlib (attr cto)) (import cstdio-core) -(import macros-core) +(import macros) (import introspection) (using-namespace std.macros diff --git a/t/error-src/operator-macro-need-three.dt.errors b/t/error-src/operator-macro-need-three.dt.errors index 50fca08d..2a79c658 100644 --- a/t/error-src/operator-macro-need-three.dt.errors +++ b/t/error-src/operator-macro-need-three.dt.errors @@ -1,6 +1,6 @@ -operator-macros.dt:73:31: error: overloaded function/macro not in scope: '\+' (parameters are int size, closest candidate expects (p DNode) (p DNode) (p DNode) ...) (see macro at 9:17) -operator-macros.dt:119:23: error: overloaded function/macro not in scope: '<' (parameters are int size, closest candidate expects (p DNode) (p DNode) (p DNode) ...) (see macro at 119:19) -:45:19: error: overloaded function/macro not in scope: 'is-valid' (parameters are int, closest candidate expects bool) (see macro at 82:11) +operator-macros.dt:72:31: error: overloaded function/macro not in scope: '\+' (parameters are int size, closest candidate expects (p DNode) (p DNode) (p DNode) ...) (see macro at 9:17) +operator-macros.dt:118:23: error: overloaded function/macro not in scope: '<' (parameters are int size, closest candidate expects (p DNode) (p DNode) (p DNode) ...) (see macro at 118:19) +:45:19: error: overloaded function/macro not in scope: 'is-valid' (parameters are int, closest candidate expects bool) (see macro at 81:11) operator-macro-need-three.dt:12:17: error: overloaded function/macro not in scope: '\+' (parameters are int size, closest candidate expects (p DNode) (p DNode) (p DNode) ...) operator-macro-need-three.dt:13:17: error: overloaded function/macro not in scope: '<' (parameters are int size, closest candidate expects (p DNode) (p DNode) (p DNode) ...) :45:19: error: overloaded function/macro not in scope: 'is-valid' (parameters are int, closest candidate expects bool) (see macro at 14:17) diff --git a/verify-targets b/verify-targets index e6a28612..e88c6dbf 100755 --- a/verify-targets +++ b/verify-targets @@ -19,7 +19,6 @@ my @targets = qw( clocale cstdio-core introspection - macros-core stdlib macros assert