-
Notifications
You must be signed in to change notification settings - Fork 207
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add "macros" option to install global macros in compile API #127
Conversation
So this doesn't quite do what you think it does. The Actually, maybe this is exactly what we want. Force people to use the ES6 module syntax now even though it's not a complete implementation. It should be forward compatible too. Source-map-support looks awesome! Definitely worth adding to Also, just in case you haven't see it, @natefaubion published a sweet.js grunt plugin a few days ago: https://github.com/natefaubion/grunt-sweet.js |
I did figure that out after reading I hadn't seen his grunt plugin, thanks! Mine has a few custom features, like injecting the source-map-support code and automatically loading the global macro file, but eventually we should merge it into one. |
+1 This would let us hide helper macros and avoid obscure names, right? @jlongster My Grunt plugin is very open to contributions. I just put out something simple since people were asking about one and nothing had been made yet. |
@natefaubion cool, I'll merge in a few things I've done and open a PR to see what you think. |
Yep. Cool, we'll do this then. @jlongster do you want to update this PR to have |
We still have to worry about collisions with other 'global' macros though regardless of whether its exported, right? I could potentially see that causing issues. IE, expecting a helper macro to be hidden since you aren't exporting it, but still clashing with other global macros. It very quickly descends into 'we need real modules'. Its a good step for source maps (and macro syntax errors) though. |
Yes, exactly. Both exported and non-exported macros will conflict the other module macros. Last defined wins I think. |
Done. Just tested and it seems to work. Not sure if you want me to commit the rebuilt code of if you want to test it first. I can commit the built code too. |
Awesome! I'll run the build when I merge. Thanks! |
Hm, I'm not sure if this is completely working. Looks like the way we export macros from the global file causes issues. I'm trying to share code, so I wrote a macro like this: macro _destructure {
case { $ctx $x } => { return #{ $x } }
}
export _destructure;
let var = macro {
case { $ctx $l = $r } => {
return #{
_destructure $l
};
}
}
export var This should compile this: { type: 3,
value: 'foo',
lineNumber: 2,
lineStart: 1,
range: [ 5, 8 ],
sm_lineNumber: 2,
sm_lineStart: 1,
sm_range: [ 5, 8 ] }
/Users/james/projects/influx-reboot/node_modules/sweet.js/lib/parser.js:3330
throw e$1134;
^
Error: Line 2: Unexpected identifier
at throwError$721 (/Users/james/projects/influx-reboot/node_modules/sweet.js/lib/parser.js:1082:25)
at throwUnexpected$723 (/Users/james/projects/influx-reboot/node_modules/sweet.js/lib/parser.js:1122:13)
at consumeSemicolon$729 (/Users/james/projects/influx-reboot/node_modules/sweet.js/lib/parser.js:1194:13) It works just fine if I include the 2 macros inline in the file and use it directly. It seems like there's some problem finding the |
I think it's working correctly. It's just that these macros expand |
Err, never mind. That's wrong...too quick to comment. |
This is happening because we don't have hygiene for export right. The |
Cool, thanks. For now, I can just share code with simple js functions and syntax-case macros. |
What do you think is the best way to share code across macros? I haven't found a great solution yet. Here's my use case: I want to implement destructuring, but it should work with The best way in my opinion would be to have something where I could create functions at expand-time in the global scope, something like this: run-at-expand-time {
function helper($x) {
return $x;
}
}
macro foo {
rule { $ctx $x } => {
return helper($x);
}
}
macro bar {
rule { $ctx $x } => {
return helper($x);
}
} Once your fix is in, we could recursively expand forms, but that will require exporting the helper macros, which is probably good enough anyway, but the above would still be cool. |
Back in the Scheme days we used to use an This actually works! macro eval_expand_time {
case { $ctx } => {
eval("bar = function () { console.log('hi'); }");
return [];
}
}
eval_expand_time;
macro foo {
case { $ctx } => {
bar();
return [];
}
}
foo; So what would be really cool is if we could get this to work :) macro eval_expand_time {
case { $ctx $expr ... } => {
eval(codegen.generate(parser.parse(#{ $expr ... })));
return [];
}
}
eval_expand_time helpers = {}
eval_expand_time helpers.bar = function() { console.log("hi"); }; Unfortunately the parser throws an error when trying to do something with location tracking... and codegen isn't available in the macro. Not sure what you think about this, but it could be helpful until we have modules. |
you could do something like this: macro shared_helpers {
rule {} => {
{
hello: function(x) {
console.log(x);
}
}
}
}
macro test {
case { _ } => {
var utils = shared_helpers;
utils.hello('bar');
return [];
}
}
test |
@natefaubion yeah, I did something like that originally. I expanded things out to a helper macro: I just realized that macro-creating macros work, so I can do this, which is actually a very nice way to do it: macro _destructure {
rule { $declare } => {
let $declare = macro {
rule { $id = $val } => { $declare $id = $val }
}
}
}
_destructure var;
_destructure let;
var x = 5;
let y = 5; This outputs:
Not sure why |
Correct, sweet doesn't touch lets or consts. |
That's considered a bug though, right? Seems like it should... Doesn't affect me in this case since I'm not actually introducing any new variables with Sorry that this bug is somewhat derailed, but I think it's good discussion. |
It seems it's just something that hasn't been done, as it has different/more complicated scoping rules than |
Right But the real reason we haven't gotten to them is that I just assumed they wouldn't parse. We're using an older fork of esrpima (issue to upgrade to the ES6 version is #96) and I didn't realize it actually supported About expand-time eval: I really don't want to support that if at all possible. You'll get into headaches once you want to use a macro in your expand-time eval because suddenly you have multiple expand and run times you need to manage by hand. Modules deal with this so hopefully the macro-generating macro trick is sufficient in the interim. |
Haha, understandable. It was always kind of a hack, so don't worry about it. Modules are a much better way to handle the multiple run/expand-times. macro-generating macros are great, and if you fix the export hygiene I think we are good for most things until modules come along. |
If beers help you while you are in your "happy" place, I'm willing to provide as many as needed. This stuff is really impressive and I can't wait to get it even farther. |
haha awesome :) |
All compile-time values defined in the `builtinSource` need to be carried over to the main expasion. This allows exported macros to safely generate non-exported macros.
It should work now. Super easy fix, just had to sleep on it :) |
wooo! It's totally workable now. thanks! |
This is a quick tweak to the compile API that lets you pass in additional macros to install globally. This difference between this and simply concat'ing sources is that this generates correct source map information.
I haven't reflected this in sjs.js, which we probably should do. Whatever is passed to
-m
should probably use this. I'm writing my own Grunt plugin to use it so I just need the lower-level support.Additionally, in my Grunt plugin I'm automatically adding
require('source-map-support').install();
at the beginning of the generated source, which nicely makes node use the sourcemaps in stack traces automatically. It might be worth adding an option tosjs
for this as well. (I'll publish my grunt plugin at some point)Let me know what you think about this, I can continue to tweak this PR based on feedback.