How to check return type in xtext using xbase - code-generation

With xtext I'm trying to develop a small language.
def sum(Integer a, Integer b):Integer {
return (a+b)
}
This is the grammar I use for this:
Function:
'def' name=ValidID
'('(params+=FullJvmFormalParameter (',' params+=FullJvmFormalParameter)*)? ')'
':' type=JvmTypeReference
body=XBlockExpression;
For reasons obvious to me it complains that "Void functions cannot return a value". How do I link the type of the return expression with the type in my function declaration?

You have to put the expression into the context of a JvmOperation. Please refer to the domain model example, the docs and the 7-languages if you want to learn more about the inferred JVM model.
Basically, what you have to do is something along these lines:
def dispatch infer(MyLanguageConcept concept, IJvmDeclaredTypeAcceptor acceptor, boolean prelinking) {
acceptor.accept(
concept.toClass( concept.fullyQualifiedName )
).initializeLater [
for ( definition : concept.getDefinitions ) {
members += definition.toMethod(
definition.name,
definition.type) [
for (p : definition.params) {
parameters += p.toParameter(p.name, p.parameterType)
}
body = definition.body
]
}
]
}

Related

Rescript Record: Key as Array

In Rescript, one can define a Record in this format:
type record1 = {
a : String
}
but NOT:
type record2 = {
[a] : String
}
I am looking to write a record that compiles to JS like:
{
[Op.or]: [12,13]
}
The use case above comes from Sequelize, and the reference is here.
My current solution:
%raw(`{[Op.or]:[12,13]}`)
It's not entirely clear how you intend to interface with the Op construct, whether you can bind to it or not, but here's an example that does, and along with Js.Dict.t effectively produces the same output:
module Op = {
#val external or: string = "Op.or"
}
Js.Dict.fromList(list{
(Op.or, [12, 23])
})
It does not directly compile to the JS you want, however, which might be a problem if you rely on something that actually parses the source code. But short of that, I believe this should do what you ask for.

How to make an parametrized enum build macro?

Now Solved
I want to build an enum with a macro, including defining its type parameters.
There are a couple of sources describing adding enum fields with macros , but I havent found any which describe how to build an enum with specified parameter types using macros. There is a documentation entry made for limitations of macros here regarding parameter types, but that is still left empty.
The idea is to use a macro to generate a specified number of Either enums with increasing amount of parameter types.
//Either.hx
#:build(macros.build.EitherBuildMacro.build(10))
// enum Either {} <- this isnt sufficient as we need to generated several
// enums (in this example 10 of them) with parameter types...
//And it should generate
enum Either2<A,B>{
_1(value:A);
_2(value:B);
}
enum Either3<A,B,C>{
_1(value:A);
_2(value:B);
_3(value:C);
}
enum Either4<A,B,C,D>{
_1(value:A);
_2(value:B);
_3(value:C);
_4(value:D);
}
//etc until enum Either10<A,B,C,D,E,F,G,H,I,J>
As I showed earlier in this post there is an article describing how to add fields, but not types. I am clueless how to set these parameter types by a macro and it seems like there are some limitations, yet undocumented. Any pointers which command to use for that are highly appreciated. Defining series of Enums with increasing parameterization is typically something you rather want to do with build macros, than to do by hand. Especially since you could pare each macro generated EitherN with a macro generated OneOfN abstract
abstract OneOf2<A, B>(Either<A, B>) from Either<A, B> to Either<A, B> {
#:from inline static function fromA<A, B>(value:A):OneOf<A, B> {
return _1(a);
}
#:from inline static function fromB<A, B>(value:B):OneOf<A, B> {
return _2(b);
}
#:to inline function toA():Null<A> return switch(this) {
case _1(value): value;
default: null;
}
#:to inline function toB():Null<B> return switch(this) {
case _2(value): value;
default: null;
}
}
abstract OneOf3<A, B, C>(Either<A, B, C>) from Either<A, B, C> to Either<A, B, C> {
#:from inline static function fromA<A, B, C>(value:A):OneOf<A, B, C> {
return _1(value);
}
#:from inline static function fromB<A, B, C>(value:B):OneOf<A, B, C> {
return _2(value);
}
#:from inline static function fromC<A, B, C>(value:C):OneOf<A, B, C> {
return _3(value);
}
#:to inline function toA():Null<A> return switch(this) {
case _1(value): value;
default: null;
}
#:to inline function toB():Null<B> return switch(this) {
case _2(value): value;
default: null;
}
#:to inline function toC():Null<C> return switch(this) {
case _3(value): value;
default: null;
}
}
//etc
The same idea would be handy to generate series of Tuples and Functions with increasing amount of parameter types. Would be a efficient and flexible way to generate the right amount of enums, abstracts and typedefs
#:build() indeed isn't the right approach here, since that just builds one particular type. Instead, you could use an initialization macro in combination with Context.defineType():
--macro Macro.init()
import haxe.macro.Context;
class Macro {
public static function init() {
for (i in 2...11) {
Context.defineType({
pack: [],
name: "Either" + i,
pos: Context.currentPos(),
kind: TDEnum,
fields: [
for (j in 0...i) {
name: "_" + (j + 1),
kind: FFun({
args: [
{
name: "value",
type: TPath({
name: String.fromCharCode(65 + j),
pack: []
})
}
],
ret: null,
expr: null
}),
pos: Context.currentPos()
}
],
params: [
for (j in 0...i) {
name: String.fromCharCode(65 + j)
}
]
});
}
}
}
With -D dump=pretty you can see that this generates Either2-10:
With for instance Either2.dump looking like this:
#:used
enum Either2<A : Either2.A,B : Either2.B> {
_1(value:Either2.A);
_2(value:Either2.B);
}
Alternatively, you could consider using #:genericBuild() in combination with a Rest type parameter. That would essentially do the same and still use Context.defineType(), with a few advantges:
it would allow you to avoid encoding the number of type parameters into the type name (so it would just be Either instead of Either2 / 3 / etc)
the amount of type parameters would not be limited to an arbitrary amount such as 10
types would only be generated "on demand"
You can find an example here.

Accessing Fantom class' members from a member function in a constructor it-block?

If I define this Fantom class
const class Mixed
{
const Int whole
const Int numerator
const Int denominator
const | -> Int[]| convertToFrac
new make( |This| func ) { func( this ) }
}
And I want to create an instance defining the convertToFrac function, like this:
class Example
{
Void main( Str args )
{
mixed := Mixed {
whole = 2
numerator = 3
denominator = 8
convertToFrac = |->Int[]| {
return [ whole * denominator + numerator, denominator ]
}
}
}
}
The compiler complains saying:
Unknown variable 'numerator'
Unknown variable 'denominator'
Unknown variable 'whole'
Is there any way to refer to the object "mixed" being created from within the function "convertToFrac", also being defined, without passing the "mixed" object as a parameter of the function?
If I prepend each variable with "mixed", like so:
return [ mixed.whole * mixed.denominator + mixed.numerator, mixed.denominator ]
The compiler complains: Unknown variable 'mixed'.
Using this.whole doesn't make sense as it refers to the Example class.
Using it.whole doesn't make sense either as it refers to the Function.
Can anyone please suggest the way to access the "mixed" object from within the "convertToFrac" function?
As you correctly assessed, the issue is that you're using an it-block inside an it-block, and because you're using an implicit it (i.e. you're don't have any it qualifiers) there is confusion as to what's being referenced.
I'll write out the it qualifiers out long hand so you can see what's going on:
mixed := Mixed {
// 'it' is the Mixed instance
it.whole = 2
it.numerator = 3
it.denominator = 8
it.convertToFrac = |->Int[]| {
// 'it' is now the func param
// 'it.whole' doesn't exist, because there is no func param
return [ it.whole * it.denominator + it.numerator, it.denominator ]
}
}
Your idea of using the mixed variable qualifier was a good one but, unfortunately, whilst processing the ctor the mixed variable hasn't been created yet so can't be referenced.
But you can create your own mixed variable in the it-block, and the following compiles and runs quite happily:
mixed := Mixed {
// 'mixed' doesn't exist here yet, because we're still creating a value to assign to it
it.whole = 2
it.numerator = 3
it.denominator = 8
// assign `it` to our own `mixed` variable
mixed := it
it.convertToFrac = |->Int[]| {
// use our own `mixed` variable
return [ mixed.whole * mixed.denominator + mixed.numerator, mixed.denominator ]
}
}

Ordering macro argument execution

I'm using a library for string interning (string-cache), that uses macros to efficient create elements (atom!). However for simplification here is a similar macro that demonstrates the problem
macro_rules! string_intern {
("d") => ("Found D");
}
say I need to call this macro from another macro and give it a string version of an identifier.
macro_rules! print_ident {
($id:ident) => (
string_intern!(stringify!($id));
);
}
However calling this macro
fn main() {
print_ident!(d);
}
Fails with error:
error: no rules expected the token `stringify`
--> <anon>:7:24
|
7 | string_intern!(stringify!($id));
| ^^^^^^^^^
Playground link
I know stringify! correctly converts to identifier d to string "d", because giving it to println! works as expected. Is there a way to pass the identifier I want turned into string to string_intern?
println! lets you do this because it uses format_args! under the covers, which is a compiler-provided "intrinsic" that forcibly evaluates its first argument before using it. You cannot do this from a user-defined macro; you'd have to write a compiler plugin (which requires a nightly compiler and no guarantee of stability).
So, yeah; you can't. Sorry. The only thing you can do is redefine the macro in such a way that you don't need an actual string literal, or change how you invoke it.
Your definition of string_intern! is expecting a literal "d" and nothing else, but you are passing in these tokens: stringify, !, ... which why it fails. The definition of string_intern! that you want is probably:
macro_rules! string_intern {
($e:expr) => {
match $e {
"d" => "Found D",
_ => "Not found",
}
}
}
which can accept any expression that evaluates to a string type.

Can I implement operator overrides in typescript?

Say I am creating a Dictionary class in typescript. Is there a way to have operator overrides so I can define the operator "[string]" instead of having to use the function get(string)?
No, you cannot have operator overloading. JavaScript does not have a notion of this.
You can override toString, though:
class Thing {
toString() {
return 'I am a Thing!';
}
}
var x = new Thing();
console.log('X says ' + x); // Prints "X says I am a Thing!"