Open maetl opened 1 year ago
A potential implementation concept using the dynamic
type from .Net 4. The polymorphism currently built-in to the Grammar.Rule
method does a lot of the heavy-lifting here. Not without its problems, and still needs to be tested/verified in Unity, but is at least a starting point for thinking about the direction for this feature.
using NUnit.Framework;
using Calyx;
using Context = System.Collections.Generic.Dictionary<string, dynamic>;
public class DynamicContext
{
public Grammar BuildGrammar(Context context)
{
Grammar objGrammar = new Grammar(seed: 1234);
foreach(var contextRule in context) {
objGrammar.Rule(contextRule.Key, contextRule.Value);
}
return objGrammar;
}
}
namespace Calyx.Test.Experimental
{
public class DynamicContextTest
{
[Test]
public void SupportsPolymorphicBranchTypesInContext()
{
DynamicContext experiment = new DynamicContext();
Grammar grammar = experiment.BuildGrammar(new Context {
{ "fixedBranch", "one" },
{ "uniformBranch", new[] { "one", "two", "three" } },
{ "weightedBranch", new Dictionary<string, int> {
{ "one", 4 },
{ "two", 2 },
{ "three", 1 }
}
}
});
Result fixedResult = grammar.Generate("fixedBranch");
Result uniformResult = grammar.Generate("uniformBranch");
Result weightedResult = grammar.Generate("weightedBranch");
Assert.That(fixedResult.Text, Is.EqualTo("one"));
Assert.That(uniformResult.Text, Is.EqualTo("three"));
Assert.That(weightedResult.Text, Is.EqualTo("two"));
}
}
}
This is something that came up from working through the documentation guides, converting existing Ruby and JS examples to C#.
The dynamic context feature, where map structures passed to generate get converted to temp rules in the registry at runtime is very much an API feature that emerged from dynamic language thinking and template engine APIs. It’s an important feature to have because it opens up a whole lot of useful patterns that would not be possible with purely static grammars, but translating it to C# well is not as obvious/direct as just flinging around a bunch of untyped data structures as certain other languages encourage.
Example of one of the documentation examples translated to a C# test:
A couple of things here which make the API more complicated to use:
string[]
—there is no shortcut for a uniform branch with one entry to be input as a barestring
, as supported by the static rule API. This is available implicitly in the dynamic language ports, and its absence could be confusing here if people are moving from JavaScript to C#.An example from the JS port that doesn’t currently work in C#:
To improve the usability here, perhaps we could provide a builtin
Context
type which does a little bit of polymorphism housekeeping and internal wrangling on the key types to support simpler injection of dynamic state, rather than the brute force hammer solution of something likeDictionary<string, object>
which potentially opens up a whole new area of bugs and mistakes.