aboutsummaryrefslogtreecommitdiff
path: root/docs/step_notes.txt
blob: b5b1c6f45281e0f1046715f9e45787e29c8a5231 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
Step Notes:

- step0_repl
    - prompt, input, READ, EVAL, PRINT, output
    - readline module
        - display prompt, read line of input

- use native eval in EVAL if available

- libedit/GNU readline:
    - use existing lib, wrap shell call or implement
    - load history file on first call
    - add non-blank lines to history
    - append to history file

- step1_read_print
    - types module:
        - add boxed types if no language equivalent:
            - nil, true, false, symbol, integer, string, list
        - pr_str:
            - stringify boxed types to their Mal representations
            - list/array is recursive
    - reader module:
        - stateful reader object
            - alternative: mutate token list
        - tokenize (if regex available)
            - standard regex pattern: "/[\s,]*(~@|[\[\]{}()'`~^@]|\"(?:\\.|[^\\\"])*\"|;.*|[^\s\[\]{}('\"`,;)]*)/"
        - read_str
            - read_form(new Reader(tokenize(str)))
        - read_form
            - detect errors
            - call read_list or read_atom
        - read_list
            - read_form until ')'
            - return array (boxed)
        - read_atom
            - return scalar boxed type:
                - nil, true, false, symbol, integer, string
    - repl loop
        - catch errors, print them and continue
        - impls without exception handling will need to have a global
          variable with checks for it at the beginning of critical
          code sections

- vectors
    - Basically: two array types that retain their boxed types, can be
      challenging depending on the language (e.g. JS, PHP: no clean
      way to derive new array types).
    - types module:
        - add vector boxed type
            - derived from array if possible
        - pr_str:
            - vector is recursive
        - sequential?
    - reader module:
        - read_vector:
            - re-use read_list but with different constructor, delims

- hash-maps
    - reader module:
        - re-use read_list function and apply that using hash-map
          constructor
    - types module:
        - pr_str addition
        - hash-map, map?, assoc, dissoc, get, contains?, keys,
          vals (probably assoc! and dissoc! for internal)
    - eval_map: eval the keys and values of hash_maps
    - EVAL:
        - if hash_map, call eval_map on it

- step2_eval
    - types module:
        - first, rest, nth on list
    - eval_ast:
        - if symbol, return value of looking up in env
        - if list, eval each item, return new list
        - if vector support, eval each item, return new vector
        - if hash_map support, eval each value, return new hash_map
        - otherwise, just return unchanged ast
    - EVAL/apply:
        - if not a list, call eval_ast
        - otherwise, apply first item to eval_ast of (rest ast)
    - repl_env as simple one level assoc. array (or hash_map)
        - store function as hash_map value

- step3_env
    - types module:
        - Env type:
            - find, set, get (no binds/exprs in constructor yet)
        - may need function type if HashMap is strongly typed (e.g. Java)
    - EVAL/apply:
        - def! - mutate current environment
        - let* - create new environment with bindings
    - _ref sugar

- step4_if_fn_do
    - types module:
        - function type (closure)
        - add function printing to pr_str
        - add binds/exprs handling to Env constructor with variable arity
        - functions (exported via types_ns):
            - move arith operations here
            - comparison operations (including =)
            - prn, pr_str, = (recursive)
            - list, list?, count, empty?
    - EVAL:
        - do:
        - if:
        - fn*:
            - simple if language supports closures
            - otherwise needs a way of representing functions that can
              have associated metadata
    - define "not" using REP/RE


- metadata
    - 

- step5_tco
    - types module:
        - function type:
            - stores: func, exp, env, params
            - func is EVAL in native mal case, otherwise reference to
              platform function
            - if metadata support, then store exp, env, params as
              metadata
        - update function printer to show function types
    - EVAL:
        - while loop around whole thing
        - cases where we directly return result of EVAL, instead set
          ast and env to what would be put in the EVAL, then loop.
            - for apply case, set env to new Env based on properties
              on the function

- step6_file
    - add read-string, eval, slurp platform wrappers
    - define load-file function
    - if files on command line, use load-file to run

- step7_quote
    - add is_pair and quasiquote functions
        - rewrite ast using cons/concat functions
        - if vectors, use sequential? instead of list? in is_pair
    - EVAL:
        - add 'quote', 'quasiquote' cases
    - types module:
        - add cons and concat functions
    - reader module:
        - add reader macros to read_form for quote, unquote,
          splice-unquote and quasiquote

- step8_macros
    - types module:
        - add first, rest functions
    - add is_macro_call and macroexpand
        - recursively macroexpand lists
        - if applying a macro function, run it on the ast first before
          continuing
    - call macroexpand apply in EVAL
    - EVAL:
        - add 'defmacro!' and 'macroexpand'
        - store ismacro property on function metadata

- step9_interop

- stepA_more
    - types module:
        - throw function
        - apply, map functions: should not directly call EVAL, which
          requires the function object to be runnable
    - EVAL:
        - try*/catch*: for normal exceptions, extracts string
          otherwise extracts full value

- Extra defintions needed for self-hosting
    - types module:
        - symbol?, nil?, true?, false?, sequential? (if not already)
        - first, rest
    - define cond and or macros using REP/RE

- Other misc:
    - conj function

- atoms
    - reader module:
        - @a reader macro -> (deref a)
    - types module:
        - pr_str case
        - atom type, atom, atom?, deref, reset!, swap!

- metadata
    - types module:
        - support meta property on symbols, hash-maps, lists, vectors,
          functions, atoms
        - add with-meta, meta functions
    - reader module:
        - ^ reader macro reads ^meta obj -> (with-meta obj meta)