Macros actually working

This commit is contained in:
FelixBrendel
2018-10-27 15:57:45 +02:00
parent 65b97fe535
commit 5aa92062c3
15 changed files with 693 additions and 192 deletions
+162 -10
View File
@@ -1,3 +1,139 @@
* Issues
** DONE #001
CLOSED: [2018-10-26 Fr 22:36]
#+begin_src lisp
(define seq (list 1 2 3))
(when 1 (printf seq))
#+end_src
The problem is, that =when= calls =apply= and the params of =apply= are named =fun= and =seq=. So
when we refer to seq in =printf= then we are refering to the =apply='s argument names. Maybe a good
solution to that is, that a child environment can never look up something in a parent macro
environment, but will always pass through
| stack depth | is macro environment | defined symbols | scope |
|-------------+----------------------+--------------------------+---------------------|
| 0 | no | seq nil printf apply etc | |
| 1 | yes | test body | (when 1 printf seq) |
| 2 | yes | fun seq | (apply prog body) |
| 3 | no | | (printf seq) |
** DONE #002
CLOSED: [2018-10-27 Sa 13:50]
#+begin_src lisp
(define l (list 1 2 3))
(extend l 4)
;; === Environment ===
;; current: in (apply)
;; fun -> prog
;; seq -> body
;; parent (hidden): in (when)
;; test -> (pair? seq)
;; body -> ((define e (end seq)) (mutate e (pair (first e) elem)))
;; parent: in (extend)
;; seq -> (1.000000 2.000000 3.000000)
;; elem -> 4.000000
;; parent: (top level)
;; nil -> nil
;; defun -> [macro]
;; defmacro -> [macro]
;; pe -> [macro]
;; nil? -> [lambda]
;; number? -> [lambda]
;; symbol? -> [lambda]
;; keyword? -> [lambda]
;; pair? -> [lambda]
;; string? -> [lambda]
;; dynamic-function? -> [lambda]
;; dynamic-macro? -> [lambda]
;; built-in-function? -> [lambda]
;; apply -> [macro]
;; when -> [macro]
;; unless -> [macro]
;; end -> [lambda]
;; last -> [lambda]
;; extend -> [lambda]
;; append -> [lambda]
;; n-times -> [macro]
;; range -> [lambda]
;; map -> [lambda]
;; reduce -> [lambda]
;; reduce-binary -> [lambda]
;; filter -> [lambda]
;; printf-quoted -> [macro]
;; printf -> [lambda]
;; l -> (1.000000 2.000000 3.000000)
;; M (apply fun -> prog seq -> body)
;; M (when test -> (pair? seq) body -> ((define e (end seq)) (mutate e (pair (first e) elem))))
;; (extend seq -> (1.000000 2.000000 3.000000) elem -> 4.000000)
#+end_src
The problem is that a funciton g called by a function f has access to the environment of f. This is
a real problem.
#+begin_src lisp
(defun f () 1)
(defun g () (f))
(defun h (f) (g))
(h 4)
#+end_src
What *should* happen:
- (h 1) calls (g)
- (g) calls (f)
- (f) retunrs 1
What *actually* happens:
- (h 1) calls (g)
- (g) tries to call (f) but f is not a funciton but =4=
** DONE #003
CLOSED: [2018-10-27 Sa 15:22]
#+begin_src lisp
(defmacro n-times (times action)
(unless (<= (eval times) 0)
(breakpoint)
(eval action)
(macro-define args (pair (pair - (pair (eval times) (pair 1 nil))) (pair action nil)))
;; [o|o] --------------------------> [o|o] -> nil
;; | |
;; V V
;; [o|o] -> [o|o] -> [o|o]-> nil action
;; | | |
;; V V V
;; - times 1
(eval (pair n-times args))))
#+end_src
- *let* should never have access to parenting macro because =(while 2 test) -> 2.00000=
- Should it have access to the grandad macro?
- no, =(when 2 (when 3 test)) -> 2=
- in the example, =n-times= is a macro, that calls =unless=, that itself is a macro that calls the
content of =n-times= in a let. So of course the contents of =n-times= wont have acess to the
parameters to =n-times=, which is bad.
So right now the only way I see to fix this is to make maco environments accessable again, but pay
attention on how to name macro parameters, to avoid collision, maybe a naming convention would help,
maybe prefix with =@=
*** Solutions:
First instinct to prevent that, is that if a parent environment is a function then just pass it and
go for their parent etc. Then we need =let= of a way to create environments that are neither macro-
nor funciton environmetns. They will be still different though.
*** Defining
In a macro environment define will still behave differently than in a function environment. If you
use =define= in a macro environment, it will actually be defined in the closest non-macro
environment. If you actually want to define something in a macro environment, then use
=macro-define=. However =define= will do the same if you are in a function or let environment.
*** Looking up
If the symbol is found on the active environment then use it. If not: Go up the environments untily
ou find a let-environment and recurse on that.
* Arguments
In Emacs lisp, keyword arguments must be passed in the same order as they were
@@ -191,13 +327,23 @@ set to see if we are in an errornious state.
Ast_Node_array_list body;
} lambda;
#+end_src
* TODO =assert_equal_type= macro in testing
* DONE use an enum for builtin identifiers
CLOSED: [2018-10-11 Do 17:15]
* TODO dont create new nils or builtins, but store one of each globally
* TODO source code locations for errors
* Build-in forms
* TODO =assert_equal_type= macro in testing
* TODO =t= ast node type, universal source of truth
* TODO backquoting
* TODO dont create new nils or builtins, but store one of each globally
* TODO make keywords unique (binary tree)
* TODO store all ast nodes in a huge arena
* TODO source code locations for errors
* TODO String error messages
* TODO Rename macro to =special= or something
* Build-in forms [29/30]
** TODO info
** DONE let
CLOSED: [2018-10-27 Sa 15:30]
** DONE +
CLOSED: [2018-09-18 Di 12:14]
** DONE -
@@ -206,8 +352,14 @@ set to see if we are in an errornious state.
CLOSED: [2018-09-18 Di 12:14]
** DONE /
CLOSED: [2018-09-18 Di 12:14]
** TODO >
** TODO <
** DONE >
CLOSED: [2018-10-26 Fr 23:30]
** DONE >=
CLOSED: [2018-10-26 Fr 23:30]
** DONE <
CLOSED: [2018-10-26 Fr 23:30]
** DONE >=
CLOSED: [2018-10-26 Fr 23:30]
** DONE =
CLOSED: [2018-10-21 So 00:25]
** DONE if
@@ -239,10 +391,12 @@ set to see if we are in an errornious state.
CLOSED: [2018-10-21 So 00:25]
** DONE define
CLOSED: [2018-10-08 Mo 20:28]
** TODO mutateW
** DONE mutate
CLOSED: [2018-10-25 Do 19:40]
** DONE lambda
CLOSED: [2018-10-21 So 00:25]
** TODO macro
** DONE macro
CLOSED: [2018-10-25 Do 19:40]
** DONE prog
CLOSED: [2018-10-21 So 00:25]
** DONE eval
@@ -279,5 +433,3 @@ set to see if we are in an errornious state.
CLOSED: [2018-10-08 Mo 20:28]
** DONE type
CLOSED: [2018-10-08 Mo 21:30]
** TODO info