Merge pull request #238 from prt2121/pt/haskell-7.10.1
[jackhill/mal.git] / docs / step_notes.txt
index 09bc356..e28761a 100644 (file)
@@ -4,6 +4,19 @@ Step Notes:
     - prompt, input, READ, EVAL, PRINT, output
     - readline module
         - display prompt, read line of input
+    - Details:
+        - get your language compiler/interpreter running
+        - create step0_repl.EXT
+            - loop that reads input, calls rep, writes output, exits
+              on EOF/Ctrl-D
+            - rep calls PRINT(EVAL(READ(str)))
+            - READ, EVAL, PRINT just return input parameter
+        - modify toplevel Makefile
+            - add language (directory name) to IMPLS
+            - add <lang>_STEP_TO_PROG entry
+            - add <lang>_RUNSTEP entry
+        - for a compiled language, add <lang>/Makefile
+            - targets: all, step*, stats, stats-lisp, 
 
 - use native eval in EVAL if available
 
@@ -17,6 +30,7 @@ Step Notes:
     - types module:
         - add boxed types if no language equivalent:
             - nil, true, false, symbol, integer, string, list
+        - error types if necessary
     - reader module:
         - stateful reader object
             - alternative: mutate token list
@@ -33,15 +47,42 @@ Step Notes:
         - read_atom (not atom type)
             - return scalar boxed type:
                 - nil, true, false, symbol, integer, string
+            - skip unquoting
     - printer module:
         - _pr_str:
             - stringify boxed types to their Mal representations
             - list/array is recursive
+            - skip quoting
     - 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
+    - Details:
+        - copy step0_repl.EXT to step1_read_print.EXT
+            - modify Makefile if compiled
+            - call reader.read_str from READ
+            - pass through type returned from read_str through
+              READ/EVAL/PRINT
+        - create reader.EXT
+            - if regex support (much easier) then tokenize with this:
+                /[\s,]*(~@|[\[\]{}()'`~^@]|"(?:\\.|[^\\"])*"|;.*|[^\s\[\]{}('"`,;)]*)/g
+            - add read_str:
+                - call tokenize
+                - handle blank line (exceptions, return code, global
+                  depending on lang features)
+            - read_str -> read_form -> {read_list, read_atom}
+                - mutable reader thing
+        - create printer.EXT
+            - _pr_str function which basically reverses read_str and
+              returns a string representation
+        - run `make test^EXT^step1`. Much of the basics should pass up
+          to vectors
+        - implement read_hash_map (can refactor read_list)
+        - import read_vector 
+            - probably want to define types for List and Vector in
+              types.EXT that extend or wrap native arrays
+        - run `make test^EXT^step1`. All mandatory should pass
 
 - comments
 
@@ -82,8 +123,23 @@ Step Notes:
     - 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)
+    - repl_env as simple one level hash map (assoc. array)
         - store function as hash_map value
+    - Details:
+        - copy step1_read_print.EXT to step2_eval.EXT
+        - create repl_env hash_map) with +, -, *, /
+            - store anon func as values if possible
+        - types.EXT
+            - implement symbol? (symbol_Q) and list? (list_Q)
+        - add env param to EVAL and add to rep EVAL call
+        - EVAL
+            - if not list call eval_ast
+            - otherwise eval_ast, and call first arg with rest
+        - eval_ast
+            - if symbol?, lookup in env
+            - if List, EVAL each and return eval's list
+            - otherwise, return original
+        - optional: handle vector and hash-map in eval_ast
 
 - vectors
     - eval each item, return new vector
@@ -99,6 +155,22 @@ Step Notes:
     - EVAL/apply:
         - def! - mutate current environment
         - let* - create new environment with bindings
+    - Details:
+        - cp step2_eval.EXT to step3_env.EXT
+        - add env.EXT if lang support file dep cycles, otherwise, add
+          to types.EXT
+            - Env type
+            - find, get, set methods/functions
+        - use Env type instead of map/assoc. array
+        - eval_ast: use method for lookup
+        - EVAL:
+            - switch on first symbol
+                - def!
+                    - set env[a1] to EVAL(a2, env)
+                - let*
+                    - loop through let building up let_env
+                    - EVAL(a2, let_env)
+                - move apply to default
 
 - step4_if_fn_do
     - types module:
@@ -126,13 +198,45 @@ Step Notes:
             - otherwise needs a way of representing functions that can
               have associated metadata
     - define "not" using REP/RE
+    - Details:
+        - cp step3_env.EXT to step4_env.EXT
+            - modify Makefile if compiled
+        - env.EXT
+            - add binds and exprs args. Create new environments with
+              exprs bound to binds. If & symbol, bind rest of exprs to
+              next bind symbol
+        - EVAL:
+            - do:
+                - eval_ast [1:], then return last eval'd element
+            - if
+                - EVAL(a1)
+                    - if true EVAL(a2)
+                    - else EVAL(a3), unless no a3 then return nil
+            - fn*
+                - if available use function closures to return a new
+                  native function that calls EVAL(a2, Env(env, a1, fargs))
+                - otherwise, store exp, params and env in a structure
+        - core.EXT
+            - create ns object to hold core namespace
+            - move numeric operators here
+            - add comparison operators
+            - add list, list?, empty?, count
+        - run make test^EXT^step4
+        - implement equal?/equal_Q in types.EXT and refer in core.ns
+        - implement not as rep("(def! not (fn* (a) (if a false true)))")
+        - run make test^EXT^step4: should pass everything except
+          string routines
+        - implement: pr-str, str, prn, println in core.EXT and
+          refer in core.ns
+            - should leverage pr-str from printer.EXT
+            - add reader/printer string quote/unquote
 
 - step5_tco
     - types module:
         - mal function type:
-            - stores: func, exp, env, params
-            - func is EVAL in native mal case, otherwise reference to
-              platform function
+            - stores: eval, exp, env, params
+            - eval is EVAL in native mal case (needed for map function
+              later), otherwise reference to platform function
             - if metadata support, then store exp, env, params as
               metadata
     - printer
@@ -142,8 +246,24 @@ Step Notes:
         - cases where we directly return result of EVAL, instead set
           ast and env to what would be put in the EVAL, then loop.
             - do, if, "apply"
-            - for "apply" case, set env to new Env based on properties
-              on the function
+            - "apply"
+                - if mal function type
+                    - set env to new Env based on properties on the function
+                - if native function, same as before
+    - Details:
+        - types.EXT
+            - create Mal function type to store eval, exp, env, params
+        - cp step4_if_fn_do.EXT to step5_tco.EXT
+            - wrap EVAL in infinite while loop
+            - in let*, do, and if:
+                - set ast and env and loop (no return)
+            - in fn* create Mal function type
+        - if compiled, update Makefile
+        - in apply, test if Mal function type:
+            - if so, generate new env from stored env, args and callee
+              params
+            - set ast to stored ast
+
 
 - step6_file
     - core module:
@@ -152,6 +272,26 @@ Step Notes:
     - set *ARGV*
     - if files on command line, use load-file to run first argument
       using rest as arguments
+    - Details:
+        - cp step5_tco.EXT to step6_file.EXT
+        - if compiled update Makefile
+        - add eval to repl_env
+            - if no (or limited closures) may have to add an "eval"
+              case to EVAL and use function which gets root of
+              environment to env.EXT (see rust).
+        - add empty *ARGV* list to repl_env
+        - in core.ns:
+            - wrap printer.read-str as read-string
+            - implement slurp
+        - implement load-file using rep
+        - test:
+            (load-file "../tests/inc.mal")
+            (inc3 10)
+        - implement command line execution
+        - test:
+            ./step6_file ../tests/incA.mal
+            =>9
+        - implement comments in reader.EXT (ignore in tokenize)
 
 - step7_quote
     - add is_pair and quasiquote functions
@@ -164,6 +304,15 @@ Step Notes:
     - reader module:
         - add reader macros to read_form for quote, unquote,
           splice-unquote and quasiquote
+    - Details:
+        - cp step6_file.EXT to step6_quote.EXT
+        - if compiled update Makefile
+        - implement reader macros (', `, ~, ~@) in reader
+        - retest make test^go^step1
+        - add is_pair and quasiquote
+        - add quote and quasiquote cases to EVAL
+        - implement cons and concat in core.EXT
+        - retest test^go^step7
 
 - step8_macros
     - types
@@ -178,12 +327,19 @@ Step Notes:
     - EVAL:
         - add 'defmacro!' and 'macroexpand'
         - set ismacro property on function
+    - Details:
+        - cp step7_quote.EXT to step8_macros.EXT
+        - if compiled update Makefile
+        - add isMacro property to Mal Function type
+            - may need to go back and adjust step5-7
+        - implement is_macro_call and macroexpand
+        - call macroexpand on ast before apply in EVAL
+        - add defmacro! and macroexpand to EVAL switch
+        - make test^go^step8 should pass some basic macros
+        - add nth, first, and rest to core.ns
+        - make test^go^step8 should now pass
 
-- step9_interop
-    - convert returned data to mal data
-        - recursive, similar to pr_str
-
-- stepA_more
+- step9_try
     - core module:
         - throw function
         - apply, map functions: should not directly call EVAL, which
@@ -195,6 +351,33 @@ Step Notes:
           otherwise extracts full value
     - set and print *host-language*
     - define cond and or macros using REP/RE
+    - Details:
+        - cp step8_macros.EXT to stepA_try.EXT
+        - if compiled update Makefile
+        - core.ns implement nil?, true?, false?, symbol?, sequential?,
+          vector, vector?
+        - add mal error type which wraps normal mal type
+            - in core.ns add throw which wraps type in mal error type
+              and throws/raises/sets exception
+        - add try*/catch* support to EVAL
+            - if mal error type, bind to catch* bind symbol
+            - otherwise, bind string of error to catch* bind symbol
+        - implement apply, map in core.ns
+        - make test^go^stepA
+        - implement readline.EXT
+            - provide option (e.g. commented out) to link with GNU
+              readline (GPL) or libedit (BSD)
+        - add hash-map functions: hash-map, map?, assoc, dissoc, get,
+          contains?, keys, vals
+        - add metadata support to List, Vector, HashMap, and Functions
+            - add reader macro
+            - may need to box HashMap and native functions
+        - add atom type, reader macro and functions: with_meta, meta
+        - get `make test^go^stepA` to fully pass
+        - get `./stepA_try ../mal/step1_read_print` to pass
+            - continue for each mal step until ../mal/stepA_try
+            - Now self-hosting!
+
 
 - Extra defintions needed for self-hosting
     - core module:
@@ -202,9 +385,6 @@ Step Notes:
         - vector, vector?
 
 
-- Other misc:
-    - conj function
-
 - atoms
     - reader module:
         - @a reader macro -> (deref a)
@@ -221,3 +401,12 @@ Step Notes:
             - clone/copy of collections
     - core module:
         - add with-meta, meta functions
+
+- Other misc:
+    - conj function
+
+- stepA_mal
+    - convert returned data to mal data
+        - recursive, similar to pr_str
+    - Details:
+