aboutsummaryrefslogtreecommitdiff
path: root/documentation/book/the_lux_programming_language/chapter_9.md
diff options
context:
space:
mode:
Diffstat (limited to 'documentation/book/the_lux_programming_language/chapter_9.md')
-rw-r--r--documentation/book/the_lux_programming_language/chapter_9.md119
1 files changed, 36 insertions, 83 deletions
diff --git a/documentation/book/the_lux_programming_language/chapter_9.md b/documentation/book/the_lux_programming_language/chapter_9.md
index 49ffe48bb..13d3c2462 100644
--- a/documentation/book/the_lux_programming_language/chapter_9.md
+++ b/documentation/book/the_lux_programming_language/chapter_9.md
@@ -1,6 +1,6 @@
# Chapter 9: Meta-programming
-_Where we go meta. For real._
+_Where we take a peek behind the curtains of the compiler._
---
@@ -18,39 +18,49 @@ Instead, I'll reveal the infrastructure that makes macros possible, and we'll di
The Lux compiler was designed to integrate very well with the language itself.
-Most compilers are just programs that take source code and emit some binary executable or some byte-code. But the Lux compiler opens itself for usage within Lux programs and provides Lux programmers with a wealth of information.
+Most compilers are just programs that take source code and emit some binary executable or some byte-code.
+
+But the Lux compiler opens itself for usage within Lux programs and provides Lux programmers with a wealth of information.
The `Lux` type enters the stage.
```clojure
-(type: #export Lux
- {#info Info
- #source Source
- #location Location
- #current_module (Maybe Text)
- #modules (List [Text Module])
- #scopes (List Scope)
- #type_context Type_Context
- #expected (Maybe Type)
- #seed Nat
- #scope_type_vars (List Nat)
- #extensions Any
- #host Any})
+(type: .public Lux
+ (Rec Lux
+ (Record
+ [#info Info
+ #source Source
+ #location Location
+ #current_module (Maybe Text)
+ #modules (List [Text Module])
+ #scopes (List Scope)
+ #type_context Type_Context
+ #expected (Maybe Type)
+ #seed Nat
+ #scope_type_vars (List Nat)
+ #extensions Any
+ #eval (-> Type Code (-> Lux (Either Text [Lux Any])))
+ #host Any])))
```
- By the way, the `Lux` type and other weird types you may not recognize there are all defined in the `library/lux` module. Check the documentation for the Standard Library for more details.
+ By the way, the `Lux` type and other weird types you may not recognize there are all defined in the `library/lux` module.
+ Check [the documentation for the Standard Library](https://github.com/LuxLang/lux/tree/master/documentation/library/standard) for more details.
The `Lux` type represents the state of the Lux compiler at any given point.
-It is not a reflection of that state, or a subset of it. It is `the` state of the Lux compiler; and, as you can see, it contains quite a lot of information about compiled modules, the state of the type-checker, the lexical and global environments, and more.
+It is not a reflection of that state, or a subset of it.
+
+It **is** the state of the Lux compiler; and, as you can see, it contains quite a lot of information about compiled modules, the state of the type-checker, the lexical and global environments, and more.
Heck, you can even access the yet-unprocessed source code of a module at any given time.
That's pretty neat.
-You can actually write computations that can read and even modify (_careful with that one_) the state of the compiler. This turns out to be massively useful when implementing a variety of powerful macros.
+You can actually write computations that can read and even modify (_careful with that one_) the state of the compiler.
+
+This turns out to be massively useful when implementing a variety of powerful macros.
-For example, remember the `open:` and `\` macros from [chapter 7](chapter_7.md)?
+For example, remember the `open:` and `#` macros from [chapter 7](chapter_7.md)?
They actually look up the typing information for the structures you give them to figure out the names of members and generate the code necessary to get that functionality going.
@@ -71,7 +81,7 @@ I won't go into detail about what's available, but you'll quickly get an idea of
However, one thing I _will_ say is that those functions rely heavily on the `Meta` type, which is defined thusly:
```clojure
-(type: #export (Meta a)
+(type: .public (Meta a)
(-> Lux (Either Text [Lux a])))
```
@@ -79,7 +89,7 @@ However, one thing I _will_ say is that those functions rely heavily on the `Met
The `Meta` type has a `Functor`, and a `Monad`, but they are a bit rather complicated.
-You saw some functor/monad examples in the last chapter, but this is more colorful.
+You saw some `Functor`/`Monad` examples in the last chapter, but this is more colorful.
`Meta` instances are functions that given an instance of the `Lux` compiler state, will perform some calculations which may fail (_with an error message_); but if they succeed, they yield a value, plus a (_possibly updated_) instance of the `Lux` compiler state.
@@ -93,72 +103,15 @@ The compiler is only ever present during... well... compilation.
And that is precisely when all of your `Lux`-dependant code will execute.
-Basically, in order for you to get your hands on that _sweet_ compiler information, your code must be run at compile-time. But only macro code can ever do that, so you will have to wait until the next chapter to learn how this story ends.
-
-## Definition annotations
-
-Another important piece of information you should be aware of is that definitions don't just have values and types associated with them, but also arbitrary meta-data which you can customize as much as you want.
-
-The relevant types in the `library/lux` module are:
-
-```clojure
-(type: #export Location
- {#module Text
- #line Nat
- #column Nat})
-
-(type: #export (Ann m v)
- {#meta m
- #datum v})
-
-(type: #export (Code' w)
- (#Bit Bit)
- (#Nat Nat)
- (#Int Int)
- (#Rev Rev)
- (#Frac Frac)
- (#Text Text)
- (#Identifier Name)
- (#Tag Name)
- (#Form (List (w (Code' w))))
- (#Tuple (List (w (Code' w))))
- (#Record (List [(w (Code' w)) (w (Code' w))])))
-
-(type: #export Code
- (Ann Location (Code' (Ann Location))))
-```
-
-You can add annotations to definitions in the many definition macros offered in the standard library.
-You can also annotate modules when using the `module:` macro.
+Basically, in order for you to get your hands on that _sweet_ compiler information, your code must be run at compile-time.
-All you need to do is pass in some record syntax, with tags signaling the type of annotation you want, and the associated value being either an explicit variant `Code`, or some function or macro call that would produce such a value.
-
-Here's an example from `library/lux`:
-
-```clojure
-(def: #export (is? reference sample)
- {#.doc (doc "Tests whether the 2 values are identical (not just 'equal')."
- "This one should succeed:"
- (let [value +5]
- (is? value value))
-
- "This one should fail:"
- (is? +5 (+ +2 +3)))}
- (All [a] (-> a a Bit))
- ("lux is" reference sample))
-```
-
- The (_optional_) annotations always goes after the declaration or name of the thing being defined.
-
-Note that all tag usage within annotation records should be fully qualified, to avoid potential confusions, as different modules could be using annotation tags with similar names.
-
-The `library/lux/meta/annotation` module contains various functions for reading and exploring annotations, and some modules in the standard library (for example, the `lbrary/lux/ffi` module) make heavy use of annotations to figure out properties of definitions which may be useful during code-generation and parsing in macros.
-
-And also, as you can appreciate from the previous example, some macros may be designed to be used during annotation specification.
+But only macro code can ever do that, so you will have to wait until the next chapter to learn the conclusion to this story.
---
-This chapter feels a little empty because the topic only makes sense within the context of macros. But macros by themselves are a huge subject, and involve more machinery than you've seen so far.
+This chapter feels a little empty because the topic only makes sense within the context of macros.
+
+But macros by themselves are a huge subject, and involve more machinery than you've seen so far.
However, I wanted to give you a taste of what's possible in order to whet your appetite, while keeping the chapter focused.