diff options
author | Péter Diviánszky <divipp@gmail.com> | 2016-04-01 15:27:01 +0200 |
---|---|---|
committer | Péter Diviánszky <divipp@gmail.com> | 2016-04-01 15:28:36 +0200 |
commit | 7fa3dea62d21c60deb38a083a2ea4f4a14da2bde (patch) | |
tree | ea7e12f4af6f260221f105a01a72f4aeca35ca36 /doc | |
parent | bf154eb6a4bf04935c0ecf1cf5666e7adb8e572e (diff) |
begin to write developer's guide
Diffstat (limited to 'doc')
-rw-r--r-- | doc/Makefile | 4 | ||||
-rw-r--r-- | doc/common.css | 207 | ||||
-rw-r--r-- | doc/guide.pandoc | 238 |
3 files changed, 449 insertions, 0 deletions
diff --git a/doc/Makefile b/doc/Makefile new file mode 100644 index 00000000..14202ea4 --- /dev/null +++ b/doc/Makefile | |||
@@ -0,0 +1,4 @@ | |||
1 | |||
2 | guide.html: guide.pandoc | ||
3 | pandoc --toc --css common.css $< -o $@ | ||
4 | |||
diff --git a/doc/common.css b/doc/common.css new file mode 100644 index 00000000..ce60b17f --- /dev/null +++ b/doc/common.css | |||
@@ -0,0 +1,207 @@ | |||
1 | |||
2 | /* slides */ | ||
3 | |||
4 | body.single_slide > * { display: none; visibility: hidden } | ||
5 | body.single_slide .current { display: block; visibility: visible } | ||
6 | body.single_slide div#TOC { display: none; visibility: hidden } | ||
7 | body.single_slide div.handout { display: none; visibility: hidden } | ||
8 | body.single_slide div#lang { display: block; visibility: visible } | ||
9 | |||
10 | |||
11 | /* padding */ | ||
12 | |||
13 | body { | ||
14 | margin: auto; | ||
15 | padding: 1em 1em 1em 1em; | ||
16 | max-width: 50em; | ||
17 | line-height: 130%; | ||
18 | background-color: white; | ||
19 | color: black; | ||
20 | } | ||
21 | |||
22 | h1 { | ||
23 | padding-top: 1.5em; | ||
24 | } | ||
25 | |||
26 | h2 { | ||
27 | padding-top: 1em; | ||
28 | } | ||
29 | |||
30 | h3 { | ||
31 | padding-top: 0.5em; | ||
32 | } | ||
33 | |||
34 | h1.title { | ||
35 | padding-top: 3em; | ||
36 | padding-bottom: 2em; | ||
37 | //text-align: center; | ||
38 | line-height: normal; | ||
39 | border-bottom: 0; | ||
40 | font-size: 200%; | ||
41 | } | ||
42 | |||
43 | hr { | ||
44 | height: 10px; | ||
45 | } | ||
46 | |||
47 | |||
48 | /* margin */ | ||
49 | |||
50 | div.indent, pre, table { | ||
51 | margin-left: 5%; | ||
52 | width: 95%; | ||
53 | } | ||
54 | |||
55 | div.indent, pre { | ||
56 | margin-top: 0.5em; | ||
57 | margin-bottom: 0.5em; | ||
58 | } | ||
59 | |||
60 | pre.normal { | ||
61 | margin: 0; | ||
62 | width: auto; | ||
63 | } | ||
64 | |||
65 | |||
66 | div.indent input { | ||
67 | margin-bottom: 0.5em; | ||
68 | } | ||
69 | |||
70 | input, textarea { | ||
71 | margin: 0; | ||
72 | } | ||
73 | |||
74 | |||
75 | /* border */ | ||
76 | |||
77 | h1, h2, h3 { | ||
78 | border-bottom: 1px dotted black; | ||
79 | } | ||
80 | |||
81 | h1.cover, input, textarea, hr { | ||
82 | border-style: none; | ||
83 | } | ||
84 | |||
85 | |||
86 | /* font sizes */ | ||
87 | |||
88 | h1 { font-size: 130%; } | ||
89 | h1.cover { font-size: 200%; } | ||
90 | h2 { font-size: 110%; } | ||
91 | input, textarea { font-size: 100%; } /* monospace correction */ | ||
92 | |||
93 | |||
94 | /* font family, style, weight, text decoration */ | ||
95 | |||
96 | h1, h2, h3 { | ||
97 | font-weight: bold; | ||
98 | } | ||
99 | |||
100 | pre code, textarea, div.string { | ||
101 | font-family: monospace; | ||
102 | font-size: 130%; | ||
103 | } | ||
104 | |||
105 | pre.normal, pre.normal code, code, .error, input { | ||
106 | font-family: sans-serif; | ||
107 | font-size: 100%; | ||
108 | } | ||
109 | |||
110 | |||
111 | .wait { | ||
112 | font-style: italic; | ||
113 | } | ||
114 | |||
115 | a { | ||
116 | text-decoration: none; | ||
117 | } | ||
118 | |||
119 | |||
120 | |||
121 | div.serious {font-weight: bold;} | ||
122 | div.info {color: gray;} | ||
123 | |||
124 | |||
125 | /* colors other than highlighting */ | ||
126 | |||
127 | input { background-color: #eeeeee; } | ||
128 | textarea { background-color: #ffffba; } | ||
129 | hr { background-color: #f5f0ee; } | ||
130 | div.string span { background-color: yellow; } | ||
131 | |||
132 | a { color: #2a207a; } | ||
133 | h1 a, h2 a, h3 a { color: black; } | ||
134 | code { color: red; } | ||
135 | .wait { color: gray; } | ||
136 | .result { color: green; } | ||
137 | .type { color: #0080ff; } | ||
138 | .error { color: #a030a0; } | ||
139 | .comment { color: gray; float: right; } | ||
140 | |||
141 | |||
142 | /* misc */ | ||
143 | |||
144 | .result { | ||
145 | word-wrap: break-word; | ||
146 | } | ||
147 | |||
148 | p.caption { | ||
149 | display: none; | ||
150 | } | ||
151 | |||
152 | div#lang { | ||
153 | position:fixed; | ||
154 | z-index:1000; | ||
155 | right: 1%; | ||
156 | top: 1%; | ||
157 | } | ||
158 | |||
159 | div#info { | ||
160 | display: none; | ||
161 | position:fixed; | ||
162 | z-index:1000; | ||
163 | left: 40%; | ||
164 | width: 20%; | ||
165 | top: 40%; | ||
166 | height: 20%; | ||
167 | } | ||
168 | |||
169 | .wait { | ||
170 | padding: 10px; | ||
171 | width: 8em; | ||
172 | border: 1px solid grey; | ||
173 | } | ||
174 | |||
175 | /* search result colors */ | ||
176 | |||
177 | code.search { color: black; } | ||
178 | code.search b { color: gray; } | ||
179 | |||
180 | .c0{background-color: #fcc;} | ||
181 | .c1{background-color: #cfc;} | ||
182 | .c2{background-color: #ccf;} | ||
183 | .c3{background-color: #ffc;} | ||
184 | .c4{background-color: #fcf;} | ||
185 | .c5{background-color: #cff;} | ||
186 | |||
187 | |||
188 | /* highlighting css */ | ||
189 | |||
190 | table.sourceCode, tr.sourceCode, td.lineNumbers, td.sourceCode, table.sourceCode | ||
191 | { margin: 0; padding: 0; border: 0; vertical-align: baseline; border: none; } | ||
192 | td.lineNumbers { border-right: 1px solid #AAAAAA; text-align: right; color: #AAAAAA; padding-right: 5px; padding-left: 5px; } | ||
193 | td.sourceCode { padding-left: 5px; } | ||
194 | pre.sourceCode span.kw { color: #007020; /* font-weight: bold; */ } | ||
195 | pre.sourceCode span.dt { color: #902000; } | ||
196 | pre.sourceCode span.dv { color: #40a070; } | ||
197 | pre.sourceCode span.bn { color: #40a070; } | ||
198 | pre.sourceCode span.fl { color: #40a070; } | ||
199 | pre.sourceCode span.ch { color: #4070a0; } | ||
200 | pre.sourceCode span.st { color: #4070a0; } | ||
201 | pre.sourceCode span.co { color: #60a0b0; /* font-style: italic; */ } | ||
202 | pre.sourceCode span.ot { color: #007020; } | ||
203 | pre.sourceCode span.al { color: red; /* font-weight: bold; */ } | ||
204 | pre.sourceCode span.fu { color: #06287e; } | ||
205 | pre.sourceCode span.re { } | ||
206 | pre.sourceCode span.er { color: red; /* font-weight: bold; */ } | ||
207 | |||
diff --git a/doc/guide.pandoc b/doc/guide.pandoc new file mode 100644 index 00000000..b1636c13 --- /dev/null +++ b/doc/guide.pandoc | |||
@@ -0,0 +1,238 @@ | |||
1 | % LambdaCube 3D compiler developer's documentation | ||
2 | |||
3 | The interface of the compiler | ||
4 | ============================ | ||
5 | |||
6 | Live coding system structure: | ||
7 | |||
8 | editor frame WebGL frame | ||
9 | | ^ ^ | ||
10 | source code| |errors | | ||
11 | | | & infos |pipeline description | ||
12 | v | | | ||
13 | compiler----------/ | ||
14 | |||
15 | Try online at [http://lambdacube3d.com/editor.html](http://lambdacube3d.com/editor.html) | ||
16 | |||
17 | |||
18 | Compiler structure | ||
19 | ================== | ||
20 | |||
21 | Compiler tasks: | ||
22 | |||
23 | - find errors in source code | ||
24 | - eliminate abstractions | ||
25 | - optimizations | ||
26 | - reduction, partial evaluation | ||
27 | - multistage compilation | ||
28 | - support incremental compilation | ||
29 | - modules support | ||
30 | - code generation* | ||
31 | - support livecoding | ||
32 | - highlight errors | ||
33 | - inferred types in tooltips | ||
34 | - completion | ||
35 | - show desugared source (on a separate tab) | ||
36 | - show optimizations (how?) | ||
37 | |||
38 | Design decisions | ||
39 | |||
40 | - lexing, parsing, scope checking and desugaring is done in the same phase, sharing the same state | ||
41 | |||
42 | Compilation pipline: | ||
43 | |||
44 | | | ||
45 | | source code | ||
46 | v | ||
47 | lexer + parser + scope checking + desugaring | ||
48 | | | ||
49 | | desugared source code | ||
50 | v | ||
51 | inference | ||
52 | | | ||
53 | | typed & reduced code | ||
54 | v | ||
55 | code generator | ||
56 | | | ||
57 | | pipeline description | ||
58 | v | ||
59 | |||
60 | |||
61 | Modules support | ||
62 | --------------- | ||
63 | |||
64 | Design decisions | ||
65 | |||
66 | - module header and body are parsed in two phases | ||
67 | - module status and availabe information are cached in a map | ||
68 | - modules can be loaded by filename or by module name | ||
69 | - builtin modules are always accessible by the last default path element | ||
70 | |||
71 | The module header contains | ||
72 | |||
73 | - module name | ||
74 | - export list | ||
75 | - import list | ||
76 | |||
77 | The driver state contains | ||
78 | |||
79 | - the paths (in a ReaderT monad transformer) | ||
80 | - map of cached modules: status + available information (in a StateT monad transformer) | ||
81 | - fatal error (in an ExceptT monad transformer) | ||
82 | |||
83 | Possible module status | ||
84 | |||
85 | status available information | ||
86 | --------------------------------------- --------------------------------- | ||
87 | file cannot be found filename or module name (the paths are available in the driver state) | ||
88 | header cannot be parsed module name, filename, source code | ||
89 | error with loading imported modules module name, filename, source code, import and export lists (the successfully loaded modules and the error messages are available in the driver state) | ||
90 | body cannot be parsed module name, filename, source code, import and export lists, parse error | ||
91 | body cannot be elaborated module name, filename, source code, import and export lists, desugared body, error message | ||
92 | loaded module name, filename, source code, import and export lists, desugared body, elaborated definitions | ||
93 | --------------------------------------- --------------------------------- | ||
94 | |||
95 | |||
96 | Lexer | ||
97 | ===== | ||
98 | |||
99 | [Source code of the lexer](https://github.com/lambdacube3d/lambdacube-compiler/blob/master/src/LambdaCube/Compiler/Lexer.hs) | ||
100 | |||
101 | Tasks | ||
102 | |||
103 | - pruning white space and comments | ||
104 | - recognise literals, reserved words and identifiers | ||
105 | - recognise indentation (case & let expressions, where blocks, ...) | ||
106 | - calculate ranges (start + end position) of tokens | ||
107 | |||
108 | Design decisions | ||
109 | |||
110 | - use the `megaparsec` parser combinator library (a better parsec) | ||
111 | - Lexing and parsing is done in the same phase, sharing the same state | ||
112 | how it works: Whitespace is consumed immediately after each "lexeme". | ||
113 | - do custom indentation sensitive parsing | ||
114 | - use custom lexer for literals | ||
115 | |||
116 | Indentation sensitive parsing | ||
117 | ----------------------------- | ||
118 | |||
119 | State used for indentation sensitive parsing: | ||
120 | |||
121 | - current position (line + column) | ||
122 | - current active indentation, in a reader monad | ||
123 | |||
124 | Range calculation | ||
125 | ----------------- | ||
126 | |||
127 | State used for calculating ranges: | ||
128 | |||
129 | - position at the end of the last lexeme | ||
130 | |||
131 | |||
132 | Parsing & desugaring | ||
133 | ==================== | ||
134 | |||
135 | [Source code of the parser and desugarer](https://github.com/lambdacube3d/lambdacube-compiler/blob/master/src/LambdaCube/Compiler/Parser.hs) | ||
136 | |||
137 | Parser tasks | ||
138 | |||
139 | - recognise syntactic structures | ||
140 | - compute ranges of syntactic structures | ||
141 | - handle namespaces: expression + type namespace | ||
142 | |||
143 | Parser design decisions | ||
144 | |||
145 | |||
146 | |||
147 | Scope checker tasks | ||
148 | |||
149 | - disambiguate names | ||
150 | |||
151 | Scope checker design decisions | ||
152 | |||
153 | - scope checking is done by calculating De Bruijn indices | ||
154 | |||
155 | Desugarer tasks | ||
156 | |||
157 | - handle operator precendences | ||
158 | - compile patterns and guards into function calls | ||
159 | - desugar local functions | ||
160 | - desugar node definitions | ||
161 | - desugar case expressions | ||
162 | - desugar let expressions | ||
163 | - desugar if expressions | ||
164 | - desugar list comprehensions | ||
165 | - add missing foralls in type annotations | ||
166 | - insert wildcards | ||
167 | - desugar type synonym declarations | ||
168 | - desugar type family declarations | ||
169 | - desugar type classes and instances | ||
170 | |||
171 | |||
172 | Desugared source code | ||
173 | --------------------- | ||
174 | |||
175 | ~~~~~ {.haskell} | ||
176 | data SExp | ||
177 | = SGlobal SIName | ||
178 | | SVar SIName Int | ||
179 | | SBind SI Binder SIName SExp SExp | ||
180 | | SApp SI Visibility SExp SExp | ||
181 | | SLet SI SIName SExp SExp | ||
182 | | SLit SI Lit | ||
183 | |||
184 | data Binder | ||
185 | = BPi Visibility | ||
186 | | BLam Visibility | ||
187 | | BMeta -- a metavariable is like a floating hidden lambda | ||
188 | |||
189 | data Stmt | ||
190 | = Let SIName (Maybe SExp) SExp | ||
191 | | Data SIName -- name | ||
192 | [(Visibility, SExp)] -- parameters | ||
193 | SExp -- type | ||
194 | [(SIName, SExp)] -- constructor names and types | ||
195 | | PrecDef SIName Fixity | ||
196 | ~~~~~ | ||
197 | |||
198 | |||
199 | Type inference | ||
200 | ============== | ||
201 | |||
202 | Design decisions | ||
203 | |||
204 | - use a dependently typed core language | ||
205 | - use metavariables | ||
206 | - support hidden arguments | ||
207 | - use a rich environment | ||
208 | - use a zipper to move in the environment | ||
209 | - do type inference and reduction in one step | ||
210 | - use labels to remember the beginning of right hand side instead of arity information | ||
211 | - separate types and expressions | ||
212 | - erease types when possible | ||
213 | |||
214 | Tasks | ||
215 | |||
216 | - find semantic errors | ||
217 | - insert metavariables | ||
218 | - eliminate all metavariables (supersede type inference) | ||
219 | - reduce expressions (beta-reduction) | ||
220 | - avoid infinite recursion during type checking (termination checking) - this is not a priority at the moment | ||
221 | |||
222 | |||
223 | Code generation | ||
224 | =============== | ||
225 | |||
226 | Tasks | ||
227 | |||
228 | - generate pipeline | ||
229 | |||
230 | Design decisions | ||
231 | |||
232 | - the type system should prevent all misuse, no error handling is needed (*) | ||
233 | - the result of inference should be very easy to deal with w.r. reduction | ||
234 | - use a custom data type which encapsulates expessions with types and De Bruijn environment | ||
235 | - use quoting to do code generation in the libraries (TODO) | ||
236 | |||
237 | |||
238 | |||