Thread overview | |||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
|
January 11, 2014 Create mixins from a list of strings | ||||
---|---|---|---|---|
| ||||
Have: enum (or is immutable array better?) array = ["derp", "lala"]; Want: mixin("some syntax" ~ array[0]); mixin("some syntax" ~ array[1]); Basically, to specify a number of similar functions based on a list of strings. Why? Pegged's semantic actions allows only calling a function by name, not specifying parameters. I could probably ask for an extension, but if there's a cool template or whatever way to do this, it would be a lot nicer. :3 |
January 11, 2014 Re: Create mixins from a list of strings | ||||
---|---|---|---|---|
| ||||
Posted in reply to Casper Færgemand | On Saturday, 11 January 2014 at 07:45:31 UTC, Casper Færgemand wrote: > Have: > enum (or is immutable array better?) array = ["derp", "lala"]; > > Want: > mixin("some syntax" ~ array[0]); > mixin("some syntax" ~ array[1]); You can use template argument lists for indexable compile-time lists: --- import std.typetuple : TypeTuple; alias array = TypeTuple!("derp", "lala"); mixin("some syntax" ~ array[0]); mixin("some syntax" ~ array[1]); --- > Basically, to specify a number of similar functions based on a list of strings. > Why? Pegged's semantic actions allows only calling a function by name, not specifying parameters. I could probably ask for an extension, but if there's a cool template or whatever way to do this, it would be a lot nicer. :3 Your problem is probably better solved without string mixins, but we'd probably need to see some code or more elaboration to accurately suggest a solution. |
January 11, 2014 Re: Create mixins from a list of strings | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jakob Ovrum | On Saturday, 11 January 2014 at 07:50:51 UTC, Jakob Ovrum wrote:
> Your problem is probably better solved without string mixins, but we'd probably need to see some code or more elaboration to accurately suggest a solution.
enum semanticArray = ["test"];
mixin(`T ` ~ semanticArray[0] ~ `(T)(T t) {
t.name ~= "` ~ semanticArray[0] ~ `";
return t;
}`);
This will mixin a single templated function named "test", which changes an AST node's name to whatever it was concatenated with "test". I want this to happen automatically for any length of semanticArray.
|
January 11, 2014 Re: Create mixins from a list of strings | ||||
---|---|---|---|---|
| ||||
Posted in reply to Casper Færgemand | Maybe you could use just one name and put the dispatching code inside it? T actor(T)(T t) { switch (t.name) { case "Gramm.Expr": return foo(t); case "Gramm.FunctionCall": return foo(t); case "Gramm.Declaration": return foo(t); default: throw new Exception("..."); } } or do it with a template, holding function names as aliases: alias actor = dispatcher!(foo, bar, baz); |
January 11, 2014 Re: Create mixins from a list of strings | ||||
---|---|---|---|---|
| ||||
Posted in reply to Philippe Sigaud | On Saturday, 11 January 2014 at 09:17:34 UTC, Philippe Sigaud wrote: > case "Gramm.Expr": > return foo(t); > case "Gramm.FunctionCall": > return foo(t); > case "Gramm.Declaration": > return foo(t); > default: > throw new Exception("..."); I can't do this since there will be multiple rules with the same name that require different treatment. The reason I want to use semantic actions is that I don't want to push an already heavy grammar into double or triple size just to name specific rules in a certain way. Semantic actions take up very little space and fit nicely into the syntax. > or do it with a template, holding function names as aliases: > > alias actor = dispatcher!(foo, bar, baz); I have no idea what you mean. :D |
January 11, 2014 Re: Create mixins from a list of strings | ||||
---|---|---|---|---|
| ||||
Posted in reply to Casper Færgemand | On Sat, Jan 11, 2014 at 2:34 PM, <"Casper Færgemand\" <shorttail@hotmail.com>"@puremagic.com> wrote: > On Saturday, 11 January 2014 at 09:17:34 UTC, Philippe Sigaud wrote: >> >> case "Gramm.Expr": >> return foo(t); >> case "Gramm.FunctionCall": >> return foo(t); >> case "Gramm.Declaration": >> return foo(t); >> default: >> throw new Exception("..."); > > > I can't do this since there will be multiple rules with the same name that require different treatment. The reason I want to use semantic actions is that I don't want to push an already heavy grammar into double or triple size just to name specific rules in a certain way. Semantic actions take up very little space and fit nicely into the syntax. OK, fair enough. I'm a bit leery of putting D call syntax into semantic actions, because it'll also explode the Pegged grammar size (I'm fairly sure I'd have to pull in a big part of D if I want to get function calls right). That's one feature I wanted at one time, but I'm not sure it's a good idea. OTOH, you can define a templated semantic action: template foo(string s, int i) { T foo(T)(T t) { writeln("Calling foo"); t.name ~= s ~ to!string(i); return t; } } And then invoke it with a parameter: mixin(grammar(` Test: A <- B { foo!("abc",1) } C { foo!("def",2) } B <- 'b' C <- 'c' `)); I did not test it thoroughly, so I'm not sure every template parameter combination is OK. It's probably better not to have curly braces inside the arg list. Pegged also authorize anonymous functions as semantic actions: https://github.com/PhilippeSigaud/Pegged/wiki/Semantic-Actions#anonymous-functions-as-actions Maybe that could be another solution. Something like B { p => foo(arg1, p) } Note that closures are not (yet) supported in CTFE, because else another solution would be a function-returning function: auto bar(string s, int i) { return (ParseTree p) { p.name ~= s ~ to!string(i); return p; }; } |
January 11, 2014 Re: Create mixins from a list of strings | ||||
---|---|---|---|---|
| ||||
> Note that closures are not (yet) supported in CTFE, because else another solution would be a function-returning function:
>
> auto bar(string s, int i)
> {
> return
> (ParseTree p) {
> p.name ~= s ~ to!string(i);
> return p;
> };
> }
Duh, instead of closures, you can use opCall-ed structs:
import pegged.grammar;
auto foo(string s, int i)
{
return Foo(s,i);
}
struct Foo
{
string s;
int i;
this(string s, int i) { this.s = s; this.i = i;}
ParseTree opCall(ParseTree p)
{
p.name ~= s ~ to!string(i);
return p;
}
}
mixin(grammar(`
Test:
A <- B { foo("abc",1) } C { foo("def",2) }
B <- 'b'
C <- 'c'
`));
void main()
{
enum result = Test("bc"); // Compile-time parsing is still possible
pragma(msg, result);
writeln(result);
}
|
January 11, 2014 Re: Create mixins from a list of strings | ||||
---|---|---|---|---|
| ||||
Posted in reply to Casper Færgemand | On 01/11/2014 09:35 AM, "Casper Færgemand" <shorttail@hotmail.com>" wrote:
> On Saturday, 11 January 2014 at 07:50:51 UTC, Jakob Ovrum wrote:
>> Your problem is probably better solved without string mixins, but we'd
>> probably need to see some code or more elaboration to accurately
>> suggest a solution.
>
> enum semanticArray = ["test"];
>
> mixin(`T ` ~ semanticArray[0] ~ `(T)(T t) {
> t.name ~= "` ~ semanticArray[0] ~ `";
> return t;
> }`);
>
> This will mixin a single templated function named "test", which changes
> an AST node's name to whatever it was concatenated with "test". I want
> this to happen automatically for any length of semanticArray.
import std.string, std.algorithm;
enum semanticArray = ["derp", "lala"];
mixin(semanticArray.map!(a=>`T `~a~`(T)(T t) {
t.name ~= "`~a~`";
return t;
}`).join());
|
January 12, 2014 Re: Create mixins from a list of strings | ||||
---|---|---|---|---|
| ||||
Posted in reply to Philippe Sigaud | On Saturday, 11 January 2014 at 16:07:30 UTC, Philippe Sigaud wrote: > I'm a bit leery of putting D call syntax into semantic actions, > because it'll also explode the Pegged grammar size (I'm fairly sure > I'd have to pull in a big part of D if I want to get function calls > right). That's one feature I wanted at one time, but I'm not sure it's > a good idea. Yes, and I would not be able to argue this is the definite way to handle things anyway. It's a try at type checking with little regard to efficiency. I'm just happy it works with Timon Gehr's extremely simple solution. :3 On Saturday, 11 January 2014 at 20:52:15 UTC, Timon Gehr wrote: > import std.string, std.algorithm; > > enum semanticArray = ["derp", "lala"]; > > mixin(semanticArray.map!(a=>`T `~a~`(T)(T t) { > t.name ~= "`~a~`"; > return t; > }`).join()); Here, have a heart. <3 |
Copyright © 1999-2021 by the D Language Foundation