Forums

Multi-target assignment bug

General discussion about Cobra. Releases and general news will also be posted here.
Feel free to ask questions or just say "Hello".

Multi-target assignment bug

Postby Charles » Wed Aug 17, 2011 3:34 am

Distilled:
class A
pass

class B inherits A
pass

class C inherits A
pass

class P

def main
b = B()
c = C()
b, c = B(), C()

Code: Select all
x.cobra(15): error: Incompatible types. Cannot assign value of type A on the right to B on the left.
x.cobra(15): error: Incompatible types. Cannot assign value of type A on the right to C on the left.
Charles
 
Posts: 2515
Location: Los Angeles, CA

Re: Multi-target assignment bug

Postby Charles » Wed Aug 17, 2011 4:18 am

Thinking out loud here:

The MultiTargetAssignStatement class uses a generic List instance for some cases, which has the side effect of inferring all the rvalue types as their greatest common denominator:
Code: Select all
// Cobra:
// b, c = B(), C()
// C#:
System.Collections.Generic.List<A> lh_mt_1001 = null;
A b = null;
A c = null;
{
lh_mt_1001=CobraLangInternal.CobraImp.MakeList<A>(typeof(System.Collections.Generic.List<A>), new global::B(), new global::C());
b=(lh_mt_1001[0]);
c=(lh_mt_1001[1]);
}

Since it is not used for all cases, some cases such as "a, b = 5, false" work while others do not.

One idea to fix this is to switch from using a list to a customer helper class that can maintain the type of each element like so:

class RightValues<of T1, T2, T3>
""" Utility class for MultiTargetAssignStatement. """

cue init(value1 as T1)
base.init
_value1 = value1

cue init(value1 as T1, value2 as T2)
base.init
_value1 = value1
_value2 = value2

cue init(value1 as T1, value2 as T2, value3 as T3)
base.init
_value1 = value1
_value2 = value2
_value3 = value3

get value1 from var as T1
get value2 from var as T2
get value3 from var as T3
# to-do: extend to value9

Create that instead of the list and get the values as .value1, .value2 etc. instead of [0], [1], etc.

I refrained from chaining the initializers to avoid having a 9-call overhead if this goes out to T9. Btw the multi-target assignment would then limit the number of rvalues to however many targets this class supports which I don't think would be a problem in practice.

Time for sleep.
Charles
 
Posts: 2515
Location: Los Angeles, CA

Re: Multi-target assignment bug

Postby Charles » Wed Aug 17, 2011 11:42 pm

Fix is on the way.
Charles
 
Posts: 2515
Location: Los Angeles, CA

Re: Multi-target assignment bug

Postby Charles » Thu Aug 18, 2011 12:15 am

Another bug bites the dust.
Charles
 
Posts: 2515
Location: Los Angeles, CA

Re: Multi-target assignment bug

Postby hopscc » Thu Aug 18, 2011 8:54 pm

If you rename the RightValues implementation to something like NTuple (say or CobraTuple or MultiTuple or ...) and put it in Cobra.Lang.dll you'll be able
to close ticket:137
(and provide a little bit more Cobra unbearable goodness).
hopscc
 
Posts: 632
Location: New Plymouth, Taranaki, New Zealand

Re: Multi-target assignment bug

Postby Charles » Thu Aug 18, 2011 10:13 pm

I kept my scope limited on this fix. To accomplish what you suggest, I think I'd have to make 9 generic overloads of the class like Microsoft did with their .NET 4 tuple class:
http://msdn.microsoft.com/en-us/library/dd387036.aspx

Those are the Create convenience methods. Each one returns a different type.

Or I'd have to create a first class language feature.

ticket:39 is next on my hit list btw.
Charles
 
Posts: 2515
Location: Los Angeles, CA

Re: Multi-target assignment bug

Postby hopscc » Fri Aug 19, 2011 8:56 am

Yes but the overloads would be individually simpler and collectively shorter (and overall more useful)
viz:
# .platform. clr

# immutable Tuples up to length 9
class NTuple<of T1, T2>
var value1 as T1 is readonly
var value2 as T2 is readonly

cue init(value1 as T1)
base.init
.value1 = value1

cue init(value1 as T1, value2 as T2)
base.init
.value1 = value1
.value2 = value2

class NTuple<of T1, T2, T3> inherits NTuple<of T1, T2>
var value3 as T3 is readonly

cue init(value1 as T1, value2 as T2, value3 as T3)
base.init(value1, value2)
.value3 = value3

class NTuple<of T1, T2, T3, T4> inherits NTuple<of T1, T2, T3>
var value4 as T4 is readonly

cue init(v1 as T1, v2 as T2, v3 as T3, v4 as T4)
base.init(v1, v2, v3)
.value4 = v4

class NTuple<of T1, T2, T3, T4, T5> inherits NTuple<of T1, T2, T3, T4>
var value5 as T5 is readonly

cue init(v1 as T1, v2 as T2, v3 as T3, v4 as T4, v5 as T5)
base.init(v1, v2, v3, v4)
.value5 = v5

class NTuple<of T1, T2, T3, T4, T5, T6> inherits NTuple<of T1, T2, T3, T4, T5>
var value6 as T6 is readonly

cue init(v1 as T1, v2 as T2, v3 as T3, v4 as T4, v5 as T5, v6 as T6)
base.init(v1, v2, v3, v4, v5)
.value6 = v6

class NTuple<of T1, T2, T3, T4, T5, T6, T7> inherits NTuple<of T1, T2, T3, T4, T5, T6>
var value7 as T7 is readonly

cue init(v1 as T1, v2 as T2, v3 as T3, v4 as T4, v5 as T5, v6 as T6, v7 as T7)
base.init(v1, v2, v3, v4, v5, v6)
.value7 = v7

class NTuple<of T1, T2, T3, T4, T5, T6, T7, T8> inherits NTuple<of T1, T2, T3, T4, T5, T6, T7>
var value8 as T8 is readonly

cue init(v1 as T1, v2 as T2, v3 as T3, v4 as T4, v5 as T5, v6 as T6, v7 as T7, v8 as T8)
base.init(v1, v2, v3, v4, v5, v6, v7)
.value8 = v8

class NTuple<of T1, T2, T3, T4, T5, T6, T7, T8, T9> inherits NTuple<of T1, T2, T3, T4, T5, T6, T7, T8>
var value9 as T9 is readonly

cue init(v1 as T1, v2 as T2, v3 as T3, v4 as T4, v5 as T5, v6 as T6, v7 as T7, v8 as T8, v9 as T9)
base.init(v1, v2, v3, v4, v5, v6, v7, v8)
.value9 = v9


Below is in a Codeblock cos a Cobrablock eats the content between backTicks (`)
Code: Select all
class NTupleTry
   def main is shared
      t0 = NTuple<of String,int>('waka')
      assert t0.value1 == 'waka'

      t = NTuple<of int, String>(0, 'waka')
      assert t.value1.getType == int
      assert t.value1 == 0
      assert t.value2 == 'waka'
      assert t.getType.toString.startsWith('NTuple`2')
      #t.value1 = 22
      
      t1 = NTuple<of int, String, decimal>(1, 'waka',10.1)
      assert t1.value1 == 1
      assert t1.value2 == 'waka'
      assert t1.value3 == 10.1
      assert t1.getType.toString.startsWith('NTuple`3')
   
   
      t2 = NTuple<of int, String, int8, char>(2, 'wakka',1 , c'x')
      assert t2.value1 == 2
      assert t2.value2 == 'wakka'
      assert t2.value3.getType == int8
      assert t2.value3 == 1
      assert t2.value4 == c'x'
      assert t2.getType.toString.startsWith('NTuple`4')

      t9 = NTuple<of int, String, int8, char, int, int, char, char, char>(9, 'waka',1, c'x', 10, 11, c'y', c'z', c'0')
      assert t9.value1.getType == int
      assert t9.value1 == 9
      assert t9.value2.getType == String
      assert t9.value2 == 'waka'
      assert t9.value3.getType == int8
      assert t9.value3 == 1
      assert t9.value4.getType == char
      assert t9.value4 == c'x'
      assert t9.value5.getType == int
      assert t9.value5 == 10
      assert t9.value6.getType == int
      assert t9.value6 == 11
      assert t9.value7.getType == char
      assert t9.value7 == c'y'
      assert t9.value8.getType == char
      assert t9.value8 == c'z'
      assert t9.value9.getType == char
      assert t9.value9 == c'0'
      assert t9.getType.toString.startsWith('NTuple`9')


ticket:204 goes with 34 but
I've found that the change from
ticket:230 is used more often.
hopscc
 
Posts: 632
Location: New Plymouth, Taranaki, New Zealand

Re: Multi-target assignment bug

Postby Charles » Fri Aug 19, 2011 11:08 pm

If you installed for .NET 4, this already works with no extra code:
class P

def main
t1 = Tuple<of int, String, decimal>(1, 'waka', 10.1)
assert t1.item1 == 1
assert t1.item2 == 'waka'
assert t1.item3 == 10.1

Although I suppose we'll need something for other back-ends that may not have Tuple.

But note that the .NET approach of using the Tuple.create methods makes even more sense because then you don't have to specify the types--they are inferred. Unfortunately, that does not currently work in Cobra.

Regarding your tuple classes above, they have the problem I mentioned before that number of method calls grows with the number of elements in the tuple. There is no need for that overhead.

Regarding tickets, you can comment on them, even with just the word "bump" if you want to make them show up higher in the report that I always use, Report #12: "Tickets Recently Updated, sans Closed".
Charles
 
Posts: 2515
Location: Los Angeles, CA

Re: Multi-target assignment bug

Postby hopscc » Sat Aug 20, 2011 12:23 am

right - if you're not using .Net4 you dont get anything .

The Type inference would need some sort of compiler support ( or C# to support varargs-like typing in its Generic templates).

The class/method growth is a consequence of how C# does its generic templates so I dont see how you can say its unnecessary (undesirable yes).
The point was that the multi inherited class version is shorter ( 60 something to 80 something lines), clearer ( to my view at least - single classes+method vs a 1-9 arg overloaded methods in a single class) and more flexible or less obscured( in that to use it you dont need to always specify 9 types, some number of which will most usually be ignored )


Tickets:
Yeah well at various stages I've commented and bumped and tweaked yet still they endure...
perhaps this would be a better report to be following
Custom Query (tickets patched and assigned)
(periodically at least).
...

I should have been a bit clearer above - if you're looking at ticket:34 you may be better looking at patch on ticket:204 since it includes/uses the patch from 34 (plus some).
hopscc
 
Posts: 632
Location: New Plymouth, Taranaki, New Zealand

Re: Multi-target assignment bug

Postby Charles » Tue Aug 23, 2011 5:20 am

hopscc wrote:I should have been a bit clearer above - if you're looking at ticket:34 you may be better looking at patch on ticket:204 since it includes/uses the patch from 34 (plus some).

Did you mean to say ticket:39 which is what I said two messages ago?
Charles
 
Posts: 2515
Location: Los Angeles, CA

Next

Return to Discussion

Who is online

Users browsing this forum: No registered users and 27 guests