4 ms·
Disclaimer: I only did a hobby project in Lisp once. But I did use some of the macro functionality. Judging by some of the comments here, it seems like the mac
by thsealienbstrds 7y ago
Disclaimer: I only did a hobby project in Lisp once. But I did use some of the macro functionality.
Judging by some of the comments here, it seems like the macro system has a similar approach as Lisp's macro system, which is also AST-based. Something I don't see here is macros that generate other macros, but the question is how much you really want that anyway (when I did that, I thought the syntax was horribly complicated because of all the quoting). I know Lisp also has reader macros (they run before the parser) that allow you to effectively change the language syntax, but I didn't use those.
- lispm 7y agoLisp macros are not based on an AST. The macro forms in Lisp need to be valid s-expressions and begin with a macro operator. That's it.
- thsealienbstrds 7y agoStill, isn't it AST-based in the sense that the input of a Lisp macro is effectively a parsed syntax tree, just as in Nim?
- lispm 7y agoThe only restriction is that it is a s-expression: a possibly nested list of data. There is no particular programming language syntax it is parsed against - it's parsed as data. For example this is a valid Lisp macro form (loop for i below 10 and j downfrom 20 when (= (+ i j) 9) sum i into isum of-type integer finally (return (+ j isum))) It returns 10. The LOOP macro parses it on its own - it just sees a list of data. Lisp has other than that no idea what the tokens mean and what syntax the LOOP macro accepts. CL-USER 142 > (defmacro my-macro (&rest stuff) t) MY-MACRO CL-USER 143 > (my-macro we are going to Europe and have a good time) T Works.
- kazinator 7y agoThe data has an AST. The AST is made of conses, and atoms. The atoms have a large variety of types. They are not "tokens", but objects. Tokens only exist briefly inside the Lisp reader. 123 and |123| are tokens; one converts to an integer node, one to a symbol node. (1 (2 3)) has an AST which is CONS / \ FIXNUM CONS | / \ 1 CONS SYMBOL / \ \ FIXNUM CONS NIL | / \ 2 FIXNUM SYMBOL | | 3 NIL
- lispm 7y ago> The data has an AST. (not (eq 'has 'is)) But for an Abstract Syntax Tree for code we have more categories: function, operator, call, control structure, variable, class, ...
- thsealienbstrds 7y agoFair enough I guess. If the Lisp macro system only sees parsed s-exps, in principle you still need to figure out for yourself what kind of construct you are dealing with on a higher level of abstraction. Nim's macro system seems to be operating on a higher level of abstraction in that regard.
- kazinator 7y agoThat kind of tree is stipulated a particular form of compiler (well, parser) writing dogma revolving around C++/Java style OOP. You set up classes with inheritance representing various node types; everything has methods, and "visitors" walk the tree, and various nonsense like that. If our code walker dispatches on pattern matches on the nested list structure of conses and atoms, we don't need that sort of encapsulated data structuring. The shapes of the patterns are de facto the higher level AST nodes. The code walking pattern case that recognizes (if test [then [else]]) is in fact working with an "if node". That AST node isn't defined in a rigid structure in the underlying data, but it's defined in the pattern that is applied to it which imposes a schema on the data. If that's not an AST node, that's like saying that (1 95000) isn't an employee record; only #S(employee id 1 salary 95000) is an employee record because it has a proper type with a name, and named fields, whereas (1 95000) "could be anything".
- arc776 7y ago> Something I don't see here is macros that generate other macros, but the question is how much you really want that anyway You can do that in Nim in a readable way. import macros macro genMacro(name: untyped): untyped = result = quote do: macro `name`: untyped = result = quote do: echo "Foo" genMacro(bar) bar # Generate and perform the echo Surprisingly I've actually used this kind of thing! In one of my projects I use a macro to parse a set of types for fields and generate constructor macros for them. The generated constructor macro passes through the parameters it's given to the default built-in constructor but does some setup before. The final generated code is a normal built-in construction without proc calling yet with special fields initialised automatically.
- thsealienbstrds 7y ago> In one of my projects I use a macro to parse a set of types for fields and generate constructor macros for them. Funny, I did a similar thing! :)