How to Build a Macro and Use it
carl@...
Hi,
I'm coming to this project from Jitx. I'm trying to write a macro as an exercise in understanding the environment. I'm using stanza version 0.17
I want to write an `assert` like macro similar to what you might use in C. Here is the source for the test macro. Keep in mind that it doesn't actually do anything yet - I'm just trying to get it to compile and be able to use it in a stanza command: https://gist.github.com/callendorph/2d9f93c694f9b0d345ef771d3a868ec6 I think I have been able to get my macro to compile with: Now - I want to compile a separate test program that uses this macro: https://gist.github.com/callendorph/a53581e0cf0b9350994c0897d714028f Here is where things go off the rails:
OK so it seems like it can't find my package because it isn't in the search path. I find that in the `compiler/config.stanza` directory there is the option for a `pkg-dirs` configuration statement. So I try adding that to my `~/.stanza` file:
When I try to recompile:
I've tried various iterations on the `$HOME/.stanza` file to no avail.
I also tried putting a symlink in the `$(install-dir)/pkgs` directory - but this still can't find my package:
This also results in the "FATAL ERROR: Could not resolve syntax package assert-check." message. As a last ditch effort, I tried: $> stanza compile assert-check.stanza test.stanza -o asdf But this results in the same problem. Can someone please help me understand how I get a macro package to compile and be used in a stanza program ? |
|
Hi Carl, The implementation of the macro looks good. To use it you need to build an "extended compiler". Support for loading in macros dynamically is still in the works. Here is how you can extend Stanza with your syntax.
And then you can use your extended Stanza, which will include your new syntax package.
Note that, the above Once you're confident in your macro implementation you can add the
Hope that helps, Patrick |
|
carl@...
Hi Patrick,
Thank you for taking the time to respond. I used the `extend` command to create a new stanza implementation:
The `assertx` command now exists and I can run it (version and help respond as expected). Next I tried to compile using this new command as you have outlined:
I also attempted to compile with the `-optimize` flag just to try something else but I get the same result. So I'm not sure what to try next. Do I perhaps have a syntax error in my test program? Do I need to import the macro or added it to some list when I compile with `stanza` ? Any ideas? |
|
Ah, I should have read the code more carefully. Try this: The construct:
means that your syntax package is called So in your test program try using this directive:
Patrick |
|
carl@...
Great, I figured I was doing something wrong.
Now when I run:
I get something that I can work with. Alright, now the fun begins. :) Thank you! |
|
The error is in the call to Since the expression you passed in was Here is one possible fix:
Patrick |
|
carl@...
Hi,
Thanks for the suggestions - I did indeed have many things that didn't quite do what I wanted. I have a follow on question that I'm hoping you might help with. Here is the my current `assert-check` code: https://gist.github.com/callendorph/65eecc48e41be29bd79f644da55b2f88 I'm not winning any beauty pageants with this implementation. But what I'm struggling to figure out is how to differentiate between symbols that are variables/values in the runtime and operators or other special symbols that are values. For example, in my test program I now do: ``` val b = 1 val a = 2 assert( (a > b) ) ``` And if I compile the assert macro: ``` callendorph@aft-gpu3:~/Documents/Jitx/assert$ stanza extend assert-check.stanza -o assertx
callendorph@aft-gpu3:~/Documents/Jitx/assert$ ./assertx compile test.stanza -o asdf |& head -n 20
Symbols[3]: (b < a)
Code: (if not (a < b) : (println (@do "ASSERT: (a < b) = %~" % (@tuple (a < b))) println (@do "LOC: test.stanza:10.13") println (@do "Symbol: b = %~" % (@tuple b)) println (@do "Fail Here")))
callendorph@aft-gpu3:~/Documents/Jitx/assert$ ./asdf
asdf
ASSERT: (a < b) = false
LOC: test.stanza:10.13
Symbol: b = 1
Fail Here
``` This all works great when I just print out symbols like `a` or `b`. But I'm trying to figure out how to differentiate between `a` and the `<` operator. If I just try to format it - I get a runtime error during `./assertx compile` step: ``` callendorph@aft-gpu3:~/Documents/Jitx/assert$ ./assertx compile test.stanza -o asdf |& head -n 20
Errors occurred during parsing:
test.stanza:10.18: Syntax Error: Expression expected here.
Symbols[3]: (b < a)
Code: (if not (a < b) : (println (@do "ASSERT: (a < b) = %~" % (@tuple (a < b))) println (@do "LOC: test.stanza:10.13") println (@do "Symbol: < = %~" % (@tuple <)) println (@do "Fail Here")))
```
That makes sense because the `parse-syntax` step (at least as I understand it) is basically parsing and expanding the `form` code into actual excutable statements. It sees `println("Symbol: < = %~" % [<])` and says "thats not right" and bails. My best guess at this point is to use a `try/catch` like approach on the `to-string` of the symbol. At first glance that seems inefficient. How do I differentiate between symbols that are variables from symbols that are not variables? |
|
The following might be useful. In general, it is impossible to ask the system whether a symbol corresponds to a legitimate variable or not, because the macroexpansion phase happens (and must happen) before the compiler runs any analysis on the program. But, the following might be enough to accomplish what you're going after.
The trick is that the argument to the assert is directly parsed as a Stanza
expression. And all of the basic comparison operators: e.g. So the macro can assume that it has that form, and pull out the names of the variables in the arguments. If you compile the above with some code that looks like:
The compiler prints out:
Is that close to what you're going after? Thanks for the questions, Patrick |
|
carl@...
Ah - very interesting. So I think there are a few things to unpack here:
So the macro can assume that it has that form, and pull out the names of the variables in the arguments. Yes - so there is a standard form here that applies to a lot of the type of expressions that I would want to handle. That makes life a lot easier. Great - Thank you! |
|
Hi Carl!
That's correct. The implementation of the
The docs for the macro system are under development cause it's considered an advanced feature. The
That's correct. So this approach is decently robust. Most syntactical shorthands in Stanza turn into some sort of function call, so this works on many things. Here's another form that it would work on as well:
The above expands into: |
|
carl@...
OK - so I'm really close :)
With your help understanding the expression production rule concept and then using the `nested` concept as part of the `fill-template` I was able to get something that worked. Here is my latest: https://gist.github.com/callendorph/f69cdb54f24650be7a153a9bcd8a8286 In LINUX - I can do asserts and it prints out all the information I want:
I'm now trying to get this to compile and build in windows 10 - I'm using stanza version 0.17.22. This is the version of gcc I'm currently trying. I've tried some other versions too. This seems to build the extended stanza version fine - I get an `assertx.exe` file.
Full listing here with verbose flag: https://gist.github.com/callendorph/9acb8a7affd21ba2b846715fa7d52eca It seems to be erroring out before it even calls GCC so I don't think this is related to what version of GCC I'm using. I then backed up and tried compiling a simpler program with my new extended stanza that doesn't reference my new assert macro at all:
This also throws the same error. If I compile that simple program with just `stanza.exe` - it compiles and runs as expected. I checked the `.stanza` configuration file and it had: ``` experimental: jit ``` So I commented that out and tried again - still same issue. Any ideas why this stanza `extend` operation won't work on Windows but will work in Linux? |
|
Ah! Well the good news is that your macro is working! And it's a pretty fancy one too. The latest issue you're seeing is actually a bug in the Stanza compiler. We actually just ran into that particular error late last week, and just pushed out a fix today in Stanza 0.17.26. This is the bleeding edge though, and it's still going through a cycle of testing before it gets released with the JITX product. Sorry! If everything looks good after testing, the next release should have the new updates. |
|
carl@...
> The latest issue you're seeing is actually a bug in the Stanza compiler. We actually just ran into that particular error late last week, and just pushed out a fix today in Stanza 0.17.26.
Confirmed - I just downloaded the 0.17.26 release and tried in on windows with my setup. The macro compiles and works on windows as expected. Thanks for the tip! Thank you again for all your help. This has been a really good exercise in understanding stanza. |
|
Glad it all worked Carl! Also, I do want to say that you dived head-first into the deep end of Stanza. The macro system is one of the more advanced systems. |
|