----------------------------------------------------------------------------------
@MSGID: <20230707102938.23@kylheku.com> 1d7e661b
@REPLY:
f1c445a7
@REPLYADDR Kaz Kylheku <864-117-4973@kylheku.com>
@REPLYTO 2:5075/128 Kaz Kylheku
@CHRS: CP866 2
@RFC: 1 0
@RFC-Message-ID: <20230707102938.23@kylheku.com>
@RFC-References:
@TZUTC: -0000
@PID: slrn/1.0.3 (Linux)
@TID: FIDOGATE-5.12-ge4e8b94
On 2023-07-07, albert@cherry.(none) (albert)
wrote:
> I`m trying to implement mal on ciforth
> https://github.com/kanaka/mal
> Amounts to implementing a dialect of lisp using a dialect of Forth.
>
> In step 8 I encounter the following:
>
> -Add a new attribute is_macro to mal function types. This should
> default to false.
>
> Am I mistaken or is this the familiar immediate flag added to
> Forth definitions?
It may be similar. Macros are invoked during expansion.
Code can be expanded without being executed immediately. Or
at all. For instance
;; function is only defined, not called; but macro is called
(defun foo ()
(macro ..))
;; macro likely called in spite of being dead code.
;; (unless expander handles trivial dead code elimination cases).
(if nil
(macro ...))
> - Add a new special form defmacro!. This is very similar to the def!
> form, but before the evaluated value (mal function) is set in the
> environment, the is_macro attribute should be set to true.
>
> Much like colon definitions, later to be modified by IMMEDIATE to add
> that behaviour.
There amy be some similarities, but that doesn`t necessarily mean
you can solve the MAL task by mapping macros directly to IMMEDIATE
words.
>
> - Add a macroexpand function: This function takes arguments ast and env.
> It calls is_macro_call with ast and env and loops while that condition
> is true.
>
> How is this different from executing an immediate definition in
> the middle of deferring an action? The only difference seems
> to be that Forth does this much cleaner and with less caveats.
> First and foremost it is far easier to keep track of arguments.
> They reside on the stack.
The user of the macro system doesn`t have any problem with argument
tracking; arguments nicely appear as lexically scoped identifiers,
bound on entry into the function.
If you`re writing code in Forth to make that work, then of course
that is your problem.
If you`re making a Forth from scratch, you have to implement
several stacks yourself.
If you`re making a Lisp from scratch, you have to implement
environments.
The simplest possible implementation of environments is stack-like.
The environment is the head of an association list, which looks like
this: ((b . 1) (a . 2)) for an environment which contains two
variables a and b bound to values 1 and 2.
A new binding is created with cons:
(cons (cons `c 3) previous-env)
In some Lisps like Common Lisp, there is an acons for this:
(acons `c 3 previous-env)
a new env is returned which looks like ((c . 3) (b . 1) (a . 2)).
The new environment doesn`t clobber the old one; the environment
is a local variable in a recursive interpreter, passed around through
its recursion.
That`s a reference model for a lexically scoped Lisp that came
into the Lisp culture mainly via the Scheme influence.
A lexically scoped Lisp doesn`t have to reveal to the programs
the detailed representation of environments. Unless a special
escape hatch is provided for it, programs don`t see the hidden
"env" variable. This is a good thing because it allows programs
to be compiled. Compiled code uses a radically different
representation of the environment.
> Am I the first to notice this? Chuck Moore was a student of McCarthy.
> Perhaps he invented Forth as a simpler version of lisp.
Even assembly languages have actions that are done now, while
assembling the code, and not at run-time.
--
TXR Programming Language: http://nongnu.org/txr
Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
Mastodon: @Kazinator@mstdn.ca
--- slrn/1.0.3 (Linux)
* Origin: A noiseless patient Spider (2:5075/128)
SEEN-BY: 5005/49 5015/255 5019/40 5020/715 848 1042
4441 12000 5030/49 1081
SEEN-BY: 5058/104 5075/128
@PATH: 5075/128 5020/1042 4441