How should I handle a template string in Xtext? - internationalization

I have the following input:
a: "a is {Foo foo}"
where foo is of type Foo; the business layer will eventually provide a value for the variable. After processing the input, two files will be generated: A properties file and a Java class:
a=a is {0}
public static I18nMessage a( Foo foo ) {
return new I18nMessageBuilder().id( "a" ).args( foo ).build();
}
The idea is that I assign each message an id which gives me a Java class that contains methods (where name == id) and which accepts typed parameters to complete the messages.
My question: How should I handle the text strings in my Xtext grammar? I would like to have code completion for the parameter types (Foo) but I have no idea how to handle the rest of the string which can contain spaces and any valid Unicode character.
Suggestions?

I found a better solution which gives a pretty simple grammar and solves some other problems:
a(Foo foo): "a is " foo;
So the text message is a list of strings and parameters. This way, code completion is very simple and there is no need for escape sequences if you want to add formatters:
a(Date d): "Date is " d( "short" );

Related

Modifying struct

I have a struct such as
type Info struct {
Foo string
FooBar string
Services string
Clown string
}
and lets say I have already populated the first 2 fields
input := &Info{
Foo: "true",
Services: "Massage",
}
Is there a way to "reopen" the struct to add missing elements. Something like this :
input = {
input,
Foobar: "Spaghetti",
Clown: "Carroussel"
}
Instead of
input.Foobar = "Spaghetti"
input.Clown = "Carroussel"
I have multiple fields and just don't really like having many lines input.Fields. I didn't find anything like it. So I was wondering.
No, this is not supported by the language's syntax.
Btw, the solution you want to avoid consists of less lines that the theoretical alternative :) (2 lines vs 4 lines in your example).
One could create a helper function which copies non-zero fields from one instance of a struct to another, so you could create a struct with the additional fields using a composite literal and use that as the source, but this requires using reflection, which is slow, and this solution wouldn't be more readable.
See related: "Merge" fields two structs of same type

Defining a set of pre-populated protobuf messages?

I want to be able to supply a pre-instantiated message by name rather than populating it from scratch. For example, given the following schema:
message Animal {
required int32 num_legs = 1;
required int32 num_eyes = 2;
}
message Zoo {
repeated Animal animals;
}
I want to be able quickly to define a Zoo in my config file by choosing from a set of known animals:
// config.json
zoo: {
animals: [snake, bird]
}
where snake and bird are already defined:
// animals.json
bird: {
num_legs: 2
num_eyes: 2
}
snake: {
num_legs: 0
num_eyes: 2
}
What's the most elegant way to do this?
The protobuf API has methods to convert protobuf⬌JSON. For C++ you can use util::JsonStringToMessage, other languages have their API versions too (you didn't specify a language). Wrap this in a simple helper function and use your language's multi-line string constant syntax to embed the message in JSON format directly into your source.
To get your named predefined messages, use a language that has string interpolation. (Not native to C++, unfortunately, but here is a SO answer talking about ways you might do it.)

Alternate syntax on introspecting modules/classes/etc

I'm rewriting a framework from Perl5 to Perl6 for my work purposes. At some place I need to collect information from other modules/classes by executing a public sub they might provide; or they may not. So, it necessary to find out if the sub is present. This is not a big deal when a module is referenced directly (Foo::<&my-sub>) or by a symbolic name in a string (&::("Foo")::my-sub). But for the simplicity of it I would like to allow to pass module names as-is (lets say collector is the method collecting the info):
self.collector( Foo );
Where Foo could be the following:
module Foo {
use Bar;
use Baz;
our sub my-sub { Bar, 'Baz' }
}
And this is where I'm missing something important from Perl6 syntax because the following:
method collector ( $mod ) {
my $mod-name = $mod.WHO;
my #mods;
with &::($mod-name)::my-sub {
#mods.push: &$_();
}
}
is currently the only way I can perform the task.
I didn't try a type capture yet though. Should work as expected, I guess. So, the question is more about extending my knowelge of the syntax.
The final solution from the exchange with Vadim in the comments on their question. It's arguably insane. They think it's beautiful. And who am I to argue? .oO( Haha, hoho, heehee... )
my $pkg-arg = (Int, 'Int').pick;
my \pkg-sym = $pkg-arg && ::($pkg-arg);
my \sub-ref = &pkg-sym::($subname);
There are two obviously useful ways to refer to a package:
Its symbolic name. Int is the symbolic name of the Int class.
Its string name. 'Int' is the string name of the Int class.
Vadim, reasonably enough, wants a solution for both.
In the solution in this answer I simulate the two types of argument by randomly picking one and assigning it to $pkg-arg:
my $pkg-arg = (Int, 'Int').pick;
Now we need to normalize. If we've got a symbolic name we're good to go. But if it's a string name, we need to turn that into the symbolic name.
Vadim showed a couple ways to do this in the comments on their question. This solution uses a third option:
my \pkg-sym = $pkg-arg && ::($pkg-arg);
If $pkg-arg is a symbolic name, it'll be False. With a False LHS the && short-circuits and returns its LHS. If $pkg-arg is a string name, then the && will instead return its RHS, which is ::($pkg-arg) which is a symbol lookup using $pkg-arg as a string name.
The upshot is that pkg-sym ends up containing a package symbolic name (or a Failure if the lookup failed to find a matching symbolic name).
Which leaves the last line. That looks for a sub named $subname in the package pkg-sym:
my \sub-ref = &pkg-sym::($subname);
The & is needed to ensure the RHS is treated as a reference rather than as an attempt to call a routine. And pkg-sym has to be a sigilless identifier otherwise the code won't work.
At the end of these three lines of code sub-ref contains either a Failure or a reference to the wanted sub.

Using protobuf enum value as a field number

I'm wondering if it is possible to use Google Protocol Buffers' enum constants as a field number of other messages, like
enum Code {
FOO = 100;
BAR = 101;
}
message Message {
required string foo = FOO;
}
This code doesn't work because FOO's type is enum Code and only a number can be used as a field number.
I am trying to build polymorphic message definitions like this animal example, that defines Cat = 1; in enum Type and required Cat animal = 100; as a unique extension number.
I thought it'd be nice to do
message Message {
required string foo = FOO.value;
}
, so that I can ensure the uniqueness of the extension field number without introducing another magic number.
So the question: is it possible to refer an enum's integer value in the protocol buffer language?
No, there is no way to do this. Sorry.
BTW, two enumerants of the same enum type can actually have the same numeric value, so defining these values in an enum does not actually ensure uniqueness.

Explanation of Oslo error "M0197: 'Text' cannot be used in a Type context"?

In Microsoft Oslo SDK CTP 2008 (using Intellipad) the following code compiles fine:
module M {
type T {
Text : Text;
}
}
while compiling the below code leads to the error "M0197: 'Text' cannot be used in a Type context"
module M {
type T {
Text : Text;
Value : Text; // error
}
}
I do not see the difference between the examples, as in the first case Text is also used in a Type context.
UPDATE:
To add to the confusion, consider the following example, which also compiles fine:
module M {
type X;
type T {
X : X;
Y : X;
}
}
The M Language Specification states that:
Field declarations override lexical scoping to prevent the type of a declaration binding to the declaration itself. The ascribed type of a field declaration must not be the declaration itself; however, the declaration may be used in a constraint. Consider the following example:
type A;
type B {
A : A;
}
The lexically enclosing scope for the type ascription of the field declaration A is the entity declaration B. With no exception, the type ascription A would bind to the field declaration in a circular reference which is an error. The exception allows lexical lookup to skip the field declaration in this case.
It seems that user defined types and built-in (intrinsic) types are not treated equal.
UPDATE2:
Note that Value in the above example is not a reserved keyword. The same error results if you rename Value to Y.
Any ideas?
Regards, tamberg
From what I am seeing you have redefined Text:
Text : Text
and then you are attempting to use it for the type of Value:
Value : Text
which is not allowed. Why using a type name as a property redefines a type I'm not entirely clear on (still reading M language specification), but I'm sure there's a good reason for it. Just name Text something that's not already a defined type (escaping it with brackets ([Text]) does not work either).
http://social.msdn.microsoft.com/Forums/en-US/oslo/thread/fcaf10a1-52f9-4ab7-bef5-1ad9f9112948
Here's the problem: in M, you can do tricks like this:
module M
{
type Address;
type Person
{
Addresses : Address*;
FavoriteAddress : Address where value in Addresses;
}
}
In that example, "Addresses" refers to Person.Addresses. The problem, then, is that when you write something innocuous like
module M
{
type T
{
Text : Text;
SomethingElse : Text;
}
}
...then the "Text" in the type ascription for SomethingElse refers not to Language.Text, but to T.Text. And that's what's going wrong. The workaround is to write it like this:
module M
{
type T
{
Text : Text;
SomethingElse : Language.Text;
}
}
(You may wonder why things like "Text : Text" work in the example above. There's a special rule: identifiers in a field's type ascription cannot refer to the field itself. The canonical example for this is "Address : Address".)

Resources