Thread: [Seed7-users] Dynamic dispatch strange behaviour
Interpreter and compiler for the Seed7 programming language.
Brought to you by:
thomas_mertes
From: Leonardo C. <leo...@gm...> - 2008-02-11 08:41:27
|
Hi. I was reading the new manual chapter (it's the chapter I was looking for) I discovered a strange issue. I don't know if it's a bug but I can't explain to myself the behaviour of the following program: $ include "seed7_05.s7i"; const type: strangeInterface is new interface; const func string: getNome(in strangeInterface param) is DYNAMIC; const type: astronave is new struct var string: nome is ""; end struct; type_implements_interface(astronave, strangeInterface); const func astronave: astronave(in string: nome) is func result var astronave: result is astronave.value; begin result.nome := nome; end func; const func string: getNome(in astronave: a1) is func result var string: result is ""; begin result:=a1.nome; end func; const proc: main is func local var strangeInterface: enterprise is astronave("Enterprise galactica"); begin writeln("one"); writeln("the name:" & getNome(enterprise)); writeln("two"); end func; The result is: C:\msys\1.0\home\lcecchi\seed7\src>hi provadue.sd7 HI INTERPRETER Version 4.5.3082 Copyright (c) 1990-2008 Thomas Mertes 259 C:/msys/1.0/home/lcecchi/seed7/lib/syntax.s7i 3395 C:/msys/1.0/home/lcecchi/seed7/lib/seed7_05.s7i 31 provadue.sd7 3685 lines total 118870 lines per second 1628430 bytes one So the execution is blocked at the line with "the name" and the line who writes "two" it's never executed. Where I'm wrong? Thanks, Leonardo |
From: Thomas M. <tho...@gm...> - 2008-02-11 10:59:47
|
"Leonardo Cecchi" <leo...@gm...> wrote: > I was reading the new manual chapter (it's the chapter I was looking > for) I discovered a strange issue. > I don't know if it's a bug but I can't explain to myself the behaviour > of the following program: > > $ include "seed7_05.s7i"; > > const type: strangeInterface is new interface; > const func string: getNome(in strangeInterface param) is DYNAMIC; > > const type: astronave is new struct > var string: nome is ""; > end struct; > type_implements_interface(astronave, strangeInterface); > > const func astronave: astronave(in string: nome) is func > result > var astronave: result is astronave.value; > begin > result.nome := nome; > end func; > > const func string: getNome(in astronave: a1) is func > result > var string: result is ""; > begin > result:=a1.nome; > end func; > > const proc: main is func > local > var strangeInterface: enterprise is astronave("Enterprise galactica"); > begin > writeln("one"); > writeln("the name:" & getNome(enterprise)); > writeln("two"); > end func; As far as I can see you discovered a bug. It has to do with the initialisation of interface variables. When you change the 'main' program to const proc: main is func local var strangeInterface: enterprise is astronave("Enterprise galactica"); begin enterprise := astronave("Enterprise galactica"); writeln("one"); writeln("the name:" & getNome(enterprise)); writeln("two"); end func; it works (at least for me). Does it work for you? I have not investigated more about the bug than that. It is obvious that I need to revise the initialisation of interface variables. In the meantime it is necessary to assign a value with := to an interface variable. There is more to revise in this area: It can happen that several interface variables point to one implementation value. Since this is sometimes desired and sometimes not I may move to the use of an explicit 'new' function. What do you think? Greetings Thomas Mertes Seed7 Homepage: http://seed7.sourceforge.net Seed7 - The extensible programming language: User defined statements and operators, abstract data types, templates without special syntax, OO with interfaces and multiple dispatch. -- Der GMX SmartSurfer hilft bis zu 70% Ihrer Onlinekosten zu sparen! Ideal für Modem und ISDN: http://www.gmx.net/de/go/smartsurfer |
From: Thomas M. <tho...@gm...> - 2008-02-11 21:49:24
|
"Leonardo Cecchi" <leo...@gm...> wrote (off-list): > I've another question about dynamic dispatching. > In the new chapter you say: > > "Although there is a 'draw' function declared for 'circle' it is not > called directly. Instead the 'draw' interface function for 'shape' is > called. When the program is analyzed (in the interpreter or compiler) > *interface functions take precedence over normal functions* when both > are to be considered." > > I've made a little test: > > $ include "seed7_05.s7i"; > > const type: strangeInterface is new interface; > const func string: getNome(in strangeInterface param) is DYNAMIC; > > const type: astronave is new struct > var string: nome is ""; > end struct; > type_implements_interface(astronave, strangeInterface); > > const type: astronaveBetter is sub astronave struct > var integer: power is 0; > end struct; > type_implements_interface(astronaveBetter, strangeInterface); > > const func astronave: astronave(in string: nome) is func > result > var astronave: result is astronave.value; > begin > result.nome := nome; > end func; > > const func string: getNome(in astronave: a1) is func > result > var string: result is ""; > begin > result:=a1.nome; > end func; > > const func astronaveBetter: astronaveBetter(in string: nome, in > integer:power) is func > result > var astronaveBetter: result is astronaveBetter.value; > begin > result.nome := nome; > result.power := power; > end func; > > const func string: getNome(in astronaveBetter: a1) is func > result > var string: result is ""; > begin > result:=a1.nome & " better"; > end func; > > const proc: main is func > local > var astronaveBetter: myBetter is astronaveBetter("Enterprise > galactica ", 1500); > var strangeInterface: enterprise is astronave.value; > var astronave: myAstro is astronave.value; > begin > enterprise:=myBetter; > myAstro:=myBetter; > > writeln(getNome(enterprise)); > writeln(getNome(myAstro)); > end func; > > The output of this program is the following: > > C:\msys\1.0\home\lcecchi\seed7\src>hi provatre.sd7 > HI INTERPRETER Version 4.5.3082 Copyright (c) 1990-2008 Thomas Mertes > 259 C:/msys/1.0/home/lcecchi/seed7/lib/syntax.s7i > 3395 C:/msys/1.0/home/lcecchi/seed7/lib/seed7_05.s7i > 55 provatre.sd7 > 3709 lines total > 119645 lines per second > 1673829 bytes > Enterprise galactica better > Enterprise galactica > > I don't understand why it doesn't do a dynamic dispatching on the > second instruction. > The functions to be considered are: > > const func string: getNome(in strangeInterface param) is DYNAMIC; > const func string: getNome(in astronave: a1); > const func string: getNome(in astronaveBetter: a1); > > So the interface should have precedence on the other functions > considering that either "astronave" or "astronaveBetter" implements > the interface "strangeInterface". > I haven't understood something... Where I'm wrong? > Thanks, > > Leonardo The local variable 'myAstro' has the type 'astronave' which is a structure. Assignments of structures do a (deep) copy. The struct 'astronaveBetter' has more elements than 'astronave', but only the elements present in both structures are copied. The assignment 'myAstro:=myBetter' does a copy of the structure (The element 'nome' is copied). With that copy the information that 'myBetter' had the type 'astronaveBetter' is lost. My description of the process: "Although there is a 'draw' function declared for 'circle' it is not called directly. Instead the 'draw' interface function for 'shape' is called. When the program is analyzed (in the interpreter or compiler) *interface functions take precedence over normal functions* when both are to be considered." is right, but does not have the desired effect here. The variable 'myAstro' is not a reference to a value, but the value itself. The process described above makes sense for parameters (except for a value parameter where the value is copied). For structs the parameters 'in', 'ref' and 'inout' are reference parameters. In this cases a parameter of type 'astronave' can point to a value of type 'astronaveBetter'. In this cases a parameter of type 'astronave' behaves iside a function (method) like a parameter of type 'strangeInterface'. If you add to your example: const func integer: getPower (in strangeInterface param) is DYNAMIC; const func integer: getPower (in astronave: a1) is return 0; const func integer: getPower (in astronaveBetter: a2) is return a2.power; const func string: getPowerName (in astronave: a1) is return getNome(a1) & "-" & str(getPower(a1)); and add to the main program: writeln(getPowerName(myBetter)); you will get: Enterprise galactica better-1500 which is exactly what you expect. Something is clear now: My description of the process of dynamic dispatch is not precise enough and needs improvement. May be my idea of having value copy for implementation objects and reference copy for interface objects is too confusing. May be I should describe the role of assignments in more detail. What do you think about my concepts and their description? BTW.: If possible I would prefer the discussion to be on see...@li... That way others can also follow the discussion. Greetings Thomas Mertes Seed7 Homepage: http://seed7.sourceforge.net Seed7 - The extensible programming language: User defined statements and operators, abstract data types, templates without special syntax, OO with interfaces and multiple dispatch. -- Psssst! Schon vom neuen GMX MultiMessenger gehört? Der kann`s mit allen: http://www.gmx.net/de/go/multimessenger |
From: Leonardo C. <leo...@gm...> - 2008-02-12 11:02:47
|
2008/2/11, Thomas Mertes <tho...@gm...>: > The variable 'myAstro' is not a reference to a value, but the > value itself. The process described above makes sense for parameters > (except for a value parameter where the value is copied). > For structs the parameters 'in', 'ref' and 'inout' are reference > parameters. You have been really clear. In the manual chapter about parameters (chapter 6) I haven't found anything about structures but only about arrays. "For arrays 'in' parameters are equal to 'ref' parameters" Probably the structs behaviour may be inferred from what you said about arrays and from the sources but I think that specifying it would be better. > Something is clear now: My description of the process > of dynamic dispatch is not precise enough and needs improvement. I think the description is good: I simply wasn't aware that implementation objects have value-copy semantics. > May be my idea of having value copy for implementation objects > and reference copy for interface objects is too confusing. > May be I should describe the role of assignments in more detail. > What do you think about my concepts and their description? I think the idea it's not confusing but can be better documented. Thanks, Leonardo |