Hi,

I’ve got the following problem. In my language the assignment operation is sometimes an iteration over a collection for which the RHS is assigned. Example:

	Proc a(G:Graph, dist:N_P<Int>, root: Node)
	{
	  G.dist = (_ == root) ? 0 : +INF;
	}

In the example above G.dist refers to the property dist of all of nodes in G. The type of the LHS of the assignment dictates that the assignment is a batch-assignment. When this happens, a variable _ of type N_P<Int> should be defined in the RHS of the assignment. If the assignment is not a batch assignment then _ is not defined. Any clue how I could achieve this? I’m pretty sure that batch-assignments are not distinguishable purely on syntax.

I was thinking of a few options, but i’m not sure which is best or how to achieve them:

  • Have a conditional definition in NaBL. The definition could be enabled/disabled by the success of a property-task.
  • During create-type-task on the LHS = RHS statement, add the definition for _ programmatically.

Thanks.

Submitted by Vlad Vergu on 20 December 2013 at 12:53

On 20 December 2013 at 13:19 Gabriël Konat commented:

I think you can express the check in a nabl-constraint rule. You match on the assignment, create a task to calculate the LHS type, generate an error for each _ if the LHS type is not a node/edge property.

Assigning a type to _ is a bit more hacky. You annotate each _ manually with the LHS type, and in the create-type-task for _ calculate the type (or be untyped) based on that annotation.
Edit: this would be a custom annotation that doesn’t interfere with the type/property annotations from NaBL.

Do you think that works?


On 20 December 2013 at 16:19 Vlad Vergu commented:

Hi Gabriël, thanks for the answer.

I’ve only looked at assigning a type to _ so far. This could work, but i do not know how to create the annotation on the tree. I only know the type of _ during create-type-task, but create-type-task is expected to result a task number and cannot return a tree. Here’s what i’ve tried:

	signature constructors
	  
	  WldType: Term
	
	rules /* assignments */
	  
	  /* special handling for property batch assignment */
	  create-type-task(|ctx):
	    |[ exp0.name = exp1; ]|-> <fail>
	    with
	      exp0-ty := <type-task(|ctx)> exp0;
	      name-ty := <type-lookup(|ctx)> name;
	      name-prop-ty := <type-task-is-property(|ctx)> name-ty
	    with
	      exp0-coll-ty := <type-task-collection-is(|ctx)> exp0-ty;
	      exp0-coll-elem-ty := <type-task-collection-get-elem-type(|ctx)> exp0-coll-ty;
	      coll-prop-same-member := <type-task-has-eq-members(|ctx)> (name-prop-ty, exp0-coll-elem-ty)
	    with
	    	wld-type := <type-is(|ctx, [coll-prop-same-member])> exp0-coll-elem-ty
	    with
	      // push annotation down. How to make it stick because this rule <fails>
	      fail
	  
	  create-type-task(|ctx):
	    w@Wld() -> <get-prop-anno(|WldType())> w

Where, when i see an assignment with a exp.name on the LHS, i try to see if the name is a property of the things stored in the collection exp (the graph case is not handled yet). If this is true then the type of _ is the type of the elements stored in the collection. At this stage i need to remember this, but i’m not allowed to rewrite the tree during create-type-task.

Assuming i have annotated the tree with the calculated type, then (2nd rule) when i see a _ i return the task that was previously created.

I like the solution. I think it is reasonably neat. If we figure out how to remember what the type of _ is until the create-type-task is called on _, then we’re good i think.


On 20 December 2013 at 17:21 Gabriël Konat commented:

You’re right, you cannot change the AST during create-type-task, forgot about that.

After some discussion with Guido we found a better solution. You can implicitly define _ with some type in an assignment:

Assign(a, e):
  implicitly defines Variable "_"
    of type t
    in e
  where a has type t

Then you need to wrap _ within another constructor and calculate the type, for example:

create-type-task(|ctx):
  Wrapped(v) -> t
  where
    v-ty := <type-task(|ctx)> v
  ; t    := <calc_real_type|ctx)> v-ty
  ; <create_error_when_not_batch_assign> t

and you create an error when the type cannot be batch assigned, instead of having a conditional definition.


On 20 December 2013 at 17:32 Vlad Vergu commented:

Thanks. I think it will be fine with a slightly different variant i think. The type of a is not sufficient to figure out if it’s a batch assign. A batch assign happens if the LHS is exp.name and exp is a collection of things of which name is a property of. But i think i can remember a bit more:

	Assign(a, e):
	  implicitly defines Variable "_"
	    of type t
	    of typegenerator a
	    in e
	  where a has type t

And then:

  create-type-task(|ctx):
	  Wrapped(v) -> t
	  where
	    v-ty := <type-task(|ctx)> v
	  ; v-ty-gen := <typegenerator-task(|ctx)> v
	  ; t    := <calc_real_type|ctx)> v-ty-gen
	  ; <create_error_when_not_batch_assign> t

What do you think?


On 8 January 2014 at 13:53 Vlad Vergu commented:

This has worked. Thank you.


On 8 January 2014 at 13:53 Vlad Vergu closed this issue.

Log in to post comments