I’ve been hung up for a while here on simplifying my meta syntax for Meta# since I am not real happy with the way my current prototype works. What I should say is that I have, so far, gone with a purely declarative syntax that ends up very verbose, much like XAML. This isn’t very fun for code that is supposed to be user readable.
I’m thinking of changing the {…} syntax to always mean binding to the model and [|…|] to be meta code. I am also thinking of creating a special expand keyword that allows you to switch into a code generation mode. For example, something like this:
template Blah:
int count = 0;
expand f in {Foo} where {Bar as int} < 100 && count % 2 == 0:
private field {Type} _{Name};
[| count++; |]
end
end
|
Which is an ugly example but you get the point. So inside of a template you are writing literally generated code unless you have an expand statement. The expand statement would allow you to specify some things you want to expand upon and an optional where clause to turn sections of the template into meta code. If you want to inject logic in the middle of an expansion block you would use the [|…|] operators to switch back into generating literal code. This is essentially the opposite of Boo, where you write everything in literal code then use the [|…|] to indicate meta blocks rather than literal logic. The sample above would generate to code such as this:
public class BlahTemplate : Template
{
protected override IEnumerable<CodeObject> Generate(object Blah)
{
int count = 0;
foreach(object f in Binder.Bind(“Foo”, Blah))
{
if(Binder.Bind<int>(“Bar”, f) < 100 && count % 2 == 0)
{
string code = “private field {0} _{1};”;
yield return Compile(string.Format(code, Binder.Bind(“Type”, f), Binder.Bind(“Name”, f)));
code++;
}
}
}
}
|
(Except it would be a for block not foreach due to limitations in the CodeDom)
I think I like this a little better (still deciding) because most of the time you won’t need anything other than binding statements inside of your expansion block and then you end up with very clean looking template code. The other thing I like is that using the {…} purely for binding makes it a lot simpler. I was encountering an issue where the property you are trying to bind to was actually a string due the way MGrammar works but you want it to be treated as an int. Doing it purely as a Binding syntax makes this a lot simpler I think {Property(.SubProperty)* (as Type)?}. The only question that concerns me is if you’ll ever actually need anything other than these keywords to solve any problem. I suppose I can always add more…
So if you were doing this for the song sample it might look like this:
template Song:
expand s in {Song}:
public sealed class {Name} implements Song:
public constructor:
expand b in {Bars}:
this.bars.Add(new Bar([|{Note1}|], [|{Note2}|], [|{Note3}|], [|{Note4}|]);
end
end
end
end
end
|
The meta statement surrounding the bound notes would be because the Note is actually a string but what you really want is a PrimitiveExpression(string). Using the meta statement syntax would force the string to be interpreted as a code block instead of string. I might be able to figure out a way to not need that but as of now I think it’s necessary.
The other weird thing is how to handle mixed binding expressions. For example this is easy to figure out:
public field {f.Type} {f.Name};
But how do you handle this:
Public field {f.Type} _{f.Name};
Here, for the fields name we have a mix of a string and a binding expression where as in the first sample it was just a binding expression. What I’m thinking is to expand the syntax for a Binding expression to be any token that contains {…} rather than starts and ends with it. It will basically translate everything inside of the brackets into a string format to a Binder call such as:
_{f.Name} -> string.Format(“_{0}”, Binder.Bind(“Name”, f))
Here the bind method knows how to get values out of basic objects with properties using reflection or MGrammar sequence elements using the MGrammar API.
Also, if anyone has something better than “: end” for blocks other than “{ }” please let me know.
You must log in to post a comment.