You can subscribe to this list here.
2001 |
Jan
|
Feb
|
Mar
|
Apr
|
May
(80) |
Jun
(71) |
Jul
(34) |
Aug
(58) |
Sep
|
Oct
(220) |
Nov
(146) |
Dec
(36) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2002 |
Jan
(28) |
Feb
(152) |
Mar
(293) |
Apr
(213) |
May
(158) |
Jun
(96) |
Jul
(78) |
Aug
(39) |
Sep
(169) |
Oct
(128) |
Nov
(83) |
Dec
(149) |
2003 |
Jan
(155) |
Feb
(14) |
Mar
(60) |
Apr
(86) |
May
(92) |
Jun
(109) |
Jul
(25) |
Aug
(44) |
Sep
(10) |
Oct
(39) |
Nov
(37) |
Dec
(128) |
2004 |
Jan
(71) |
Feb
(199) |
Mar
(192) |
Apr
(360) |
May
(93) |
Jun
(75) |
Jul
(51) |
Aug
(195) |
Sep
(390) |
Oct
(186) |
Nov
(173) |
Dec
(331) |
2005 |
Jan
(102) |
Feb
(154) |
Mar
(160) |
Apr
(88) |
May
(79) |
Jun
(78) |
Jul
(126) |
Aug
(94) |
Sep
(110) |
Oct
(187) |
Nov
(188) |
Dec
(31) |
2006 |
Jan
(12) |
Feb
(40) |
Mar
(123) |
Apr
(102) |
May
(62) |
Jun
(36) |
Jul
(19) |
Aug
(31) |
Sep
(59) |
Oct
(67) |
Nov
(57) |
Dec
(35) |
2007 |
Jan
(153) |
Feb
(53) |
Mar
(27) |
Apr
(11) |
May
(49) |
Jun
(3) |
Jul
(56) |
Aug
(58) |
Sep
(30) |
Oct
(57) |
Nov
(47) |
Dec
(155) |
2008 |
Jan
(71) |
Feb
(68) |
Mar
(79) |
Apr
(72) |
May
(82) |
Jun
(10) |
Jul
(19) |
Aug
(25) |
Sep
(17) |
Oct
(10) |
Nov
(32) |
Dec
(9) |
2009 |
Jan
(26) |
Feb
(1) |
Mar
(1) |
Apr
(12) |
May
(16) |
Jun
(7) |
Jul
(12) |
Aug
(22) |
Sep
(21) |
Oct
|
Nov
(7) |
Dec
|
2010 |
Jan
(3) |
Feb
(3) |
Mar
(1) |
Apr
|
May
(5) |
Jun
(5) |
Jul
|
Aug
|
Sep
(4) |
Oct
(2) |
Nov
|
Dec
(6) |
2011 |
Jan
(3) |
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
(1) |
Aug
|
Sep
(8) |
Oct
|
Nov
|
Dec
|
2012 |
Jan
|
Feb
|
Mar
|
Apr
|
May
(8) |
Jun
|
Jul
(3) |
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2013 |
Jan
|
Feb
(11) |
Mar
(1) |
Apr
(4) |
May
|
Jun
|
Jul
(2) |
Aug
(2) |
Sep
|
Oct
|
Nov
|
Dec
|
2014 |
Jan
(5) |
Feb
|
Mar
|
Apr
(3) |
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
(3) |
Nov
(2) |
Dec
(1) |
2015 |
Jan
(2) |
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(6) |
2016 |
Jan
(8) |
Feb
|
Mar
|
Apr
|
May
(3) |
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
(3) |
Dec
|
2017 |
Jan
(3) |
Feb
|
Mar
|
Apr
(1) |
May
|
Jun
|
Jul
(1) |
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(1) |
2018 |
Jan
(1) |
Feb
|
Mar
(4) |
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
(4) |
Nov
|
Dec
|
2021 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(2) |
2022 |
Jan
(3) |
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
(2) |
Sep
|
Oct
|
Nov
|
Dec
|
2023 |
Jan
|
Feb
|
Mar
(1) |
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2025 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
(1) |
Oct
(1) |
Nov
|
Dec
|
From: Andreas L. <no...@sb...> - 2001-10-21 23:30:36
|
On Mon, 2001-10-22 at 00:24, Eric Bezault wrote: > Andreas Leitner wrote: > > > > Problem fixed. The see code was still looking for EP_EVENT_PARSER, > > whereas it has been renamed to XP_EVENT_PARSER. I have also now > > added code that checks if the class we resolve is actually in the > > system. An exception is raised otherwise. This code is protected > > via an #ifdef and can be enabled by setting ${GOBO_C_DEBUG} before > > executing geant compile in library/xml/impl/expat/spec/c. > > I had a chance to have a look at the C code in > library/xml/impl/expat/spec/c when I tried to > make it work with MSVC++ 6.0 this week, and > personally I don't think that it is a good way > of programming to access the Eiffel routines > from C by name using Cecil. It is no safe (see > the exception raisings that you added), it is > error-prone (see the segfault you got just > because you renamed a class), and it is not > efficient (class names and feature names are > probably searched for in hash tables each time > the corresponding Eiffel routine is to be > called, even if the routine won't change between > two calls. > > A much better solution is to pass the function > pointers of the Eiffel routines from the Eiffel > side to the C side in an initialization routine, > and then the C code has these functions pointers > in global variables once and for all, and there > is no need for Cecil to get them by name anymore. This makes sense. IIRC that dynamic stuff came from Berend. Berend was there any other reason not to use function pointers? > Example: > > In Eiffel code: > > f is > do > ... > end > > g is > do > ... > end > > initialize is > -- Pass function pointers of `f' and > -- `g' to C. > do > c_initialize ($f, $g) > end Ok, we just need to make sure the globals are thread safe. > feature {NONE} -- External > > c_initialize (fp, gp: POINTER) is > -- Pass function pointers of `f' and > -- `g' to C. > external > "C" > end > > In C code: > > EIF_PROCEDURE eif_f, eif_g; > > void c_initialize (EIF_PROCEDURE fp, EIF_PROCEDURE gp) > { > eif_f = fp; > eif_g = gp; > } using something like c_assume_initialize should make this thread safe (if there is a thread issue to begin with - not sure): void c_assure_initialize (EIF_PROCEDURE fp, EIF_PROCEDURE gp) { if (eif_f != null) eif_f = fp; if (eif_g != null) eif_g = gp; } Btw, do you know if procedures can be moved around in ISE? Maybe this sounds like a stupid question, but I really don't know. Meaning do we need to protect the function pointers? Anyway, if Berend has no reason why the other approach doesn't work, I'll convert the code. thanks, Andreas |
From: Andreas L. <no...@sb...> - 2001-10-21 23:21:43
|
On Mon, 2001-10-22 at 00:36, Eric Bezault wrote: > Andreas Leitner wrote: > > > > Yes, but this design assumes we do not get another option. For example > > the xml examples can be compiled with or without expat. Other such > > options will surely come with time. Now do I need for each option touch > > misc/eiffel.eant and add rules (which would clutter it up) that only > > make sense for some projects. > > No, don't add anything to misc/eiffel.eant, just add a new > .eant file in misc (say misc/cc.eant) that inherits from > misc/eiffel.eant and adds the various C compilation rules > parameterized with geant's local variables (in the same way > the 'compile_<compiler>' targets in misc/eiffel.eant are > parameterized). Sure, but let's stick with the xml example build.eant files. You can compile the examples with or without the expat backend enabled. You can decide this on a per example per compile basis. And take into account that more such options are thinkable. For each new (boolean) option I have to double the "compile_" tasks. This does not look attractive to me. So if we start with: compile_ise compile_se compile_hact compile_ve then we want debug builds as well so we double: compile_ise compile_se compile_hact compile_ve compile_ise_debug compile_se_debug compile_hact_debug compile_ve_debug then we want to compile with expat: compile_ise compile_se compile_hact compile_ve compile_ise_debug compile_se_debug compile_hact_debug compile_ve_debug compile_ise_expat compile_se_expat compile_hact_expat compile_ve_expat compile_ise_debug_expat compile_se_debug_expat compile_hact_debug_expat compile_ve_debug_expat then we would like to link against the posix libraries: compile_ise compile_se compile_hact compile_ve compile_ise_debug compile_se_debug compile_hact_debug compile_ve_debug compile_ise_expat compile_se_expat compile_hact_expat compile_ve_expat compile_ise_debug_expat compile_se_debug_expat compile_hact_debug_expat compile_ve_debug_expat compile_ise_posix compile_se_posix compile_hact_posix compile_ve_posix compile_ise_debug_posix compile_se_debug_posix compile_hact_debug_posix compile_ve_debug_posix compile_ise_expat_posix compile_se_expat_posix compile_hact_expat_posix compile_ve_expat_posix compile_ise_debug_expat_posix compile_se_debug_expat_posix compile_hact_debug_expat_posix compile_ve_debug_expat_posix Actually I think the autoconf/autobuild people have a better approach here. They seperate the task of configuring and building a project into two tasks. In the first task you call: ./configure --with-expat --debug --my-other-option and then do a simple make We could do something similar: Have a configure.eant file that stores configuration options. A configure.eant file (that would grows linearly only) could look like this: <configure> <var name="expat" value="true"/> <var name="debug" value="true"/> <var name="posix" value="true"/> </configure> This also much more reflects the usage. I do not switch from debug builds to release builds on every compile. Rather I am doing some work with debug options enabled, then reconfigure, and then I try some stuff in release mode. Some goes for expat, etc. Btw, I think the build options in GOBO will increase as we add components that do not make sense / are not available on every setup. A low-maintainace solution to add/remove options will help here. geant would still work without a configure.eant file. It would just assume the default values. We could also add some tool that manipulates the configure.eant file just like ./configure - if we don't want users to launch their editors. Such a tool could even run in autodectect mode and for example set expat only if it can find the library (similar to what ./configure does). > > That was my first approach, meanwhile I put this clause out again, > > because IMO it is a little ugly. So I added a remark to put a symlink > > from "studio" to "bench". > > It's your point of view, but I find my solution less ugly, > and no need to modify the ISE installation (remember that > Gobo should ideally work out of the box). Well, but you assume that all linux users have the latest beta. Earlier versions do have the old path. Again a ./configure pendant could autodetect such things. Andreas |
From: Andreas L. <no...@sb...> - 2001-10-21 23:20:45
|
From: Eric B. <er...@go...> - 2001-10-21 22:37:40
|
Andreas Leitner wrote: > > Yes, but this design assumes we do not get another option. For example > the xml examples can be compiled with or without expat. Other such > options will surely come with time. Now do I need for each option touch > misc/eiffel.eant and add rules (which would clutter it up) that only > make sense for some projects. No, don't add anything to misc/eiffel.eant, just add a new .eant file in misc (say misc/cc.eant) that inherits from misc/eiffel.eant and adds the various C compilation rules parameterized with geant's local variables (in the same way the 'compile_<compiler>' targets in misc/eiffel.eant are parameterized). > That was my first approach, meanwhile I put this clause out again, > because IMO it is a little ugly. So I added a remark to put a symlink > from "studio" to "bench". It's your point of view, but I find my solution less ugly, and no need to modify the ISE installation (remember that Gobo should ideally work out of the box). > Aehm, sorry, that was a little unclear. What I meant to say was that > makefiles do only tasks they have to do. Based on dependency analysis - > using timestamp checks etc. A similar mechanism will probably be partially implemented in geant. Sven already started to look at how it could be designed. -- Eric Bezault mailto:er...@go... http://www.gobosoft.com |
From: Eric B. <er...@go...> - 2001-10-21 22:25:59
|
Andreas Leitner wrote: > > Problem fixed. The see code was still looking for EP_EVENT_PARSER, > whereas it has been renamed to XP_EVENT_PARSER. I have also now > added code that checks if the class we resolve is actually in the > system. An exception is raised otherwise. This code is protected > via an #ifdef and can be enabled by setting ${GOBO_C_DEBUG} before > executing geant compile in library/xml/impl/expat/spec/c. I had a chance to have a look at the C code in library/xml/impl/expat/spec/c when I tried to make it work with MSVC++ 6.0 this week, and personally I don't think that it is a good way of programming to access the Eiffel routines from C by name using Cecil. It is no safe (see the exception raisings that you added), it is error-prone (see the segfault you got just because you renamed a class), and it is not efficient (class names and feature names are probably searched for in hash tables each time the corresponding Eiffel routine is to be called, even if the routine won't change between two calls. A much better solution is to pass the function pointers of the Eiffel routines from the Eiffel side to the C side in an initialization routine, and then the C code has these functions pointers in global variables once and for all, and there is no need for Cecil to get them by name anymore. Example: In Eiffel code: f is do ... end g is do ... end initialize is -- Pass function pointers of `f' and -- `g' to C. do c_initialize ($f, $g) end feature {NONE} -- External c_initialize (fp, gp: POINTER) is -- Pass function pointers of `f' and -- `g' to C. external "C" end In C code: EIF_PROCEDURE eif_f, eif_g; void c_initialize (EIF_PROCEDURE fp, EIF_PROCEDURE gp) { eif_f = fp; eif_g = gp; } And now you can replace the code: void exml_on_element_declaration (void *eiffel_object, const XML_Char *name, XML_Content *model) { #ifdef ise EIF_PROCEDURE ep; EIF_TYPE_ID tid; tid = eif_type_id ("XP_EVENT_PARSER"); #ifdef GOBO_DEBUG if (tid == EIF_NO_TYPE) eif_panic ("Type XP_EVENT_PARSER not in system."); #endif ep = eif_procedure ("f", tid); if (ep == 0) { eif_panic ("f not found."); } else { (ep) (eif_access(eiffel_object), (void*) name, (void*) model); } #endif } by: void exml_on_element_declaration (void *eiffel_object, const XML_Char *name, XML_Content *model) { #ifdef ise (eif_f) (eif_access(eiffel_object), (void*) name, (void*) model); #endif } It's safer, more robust, more efficient. PS: Note that in `exml_on_element_declaration' there is a extra line in the actual code in the C file: (ep) (eif_access(eiffel_object), (void*) name, (void*) model); which should be removed, otherwise the routine is called twice. -- Eric Bezault mailto:er...@go... http://www.gobosoft.com |
From: Andreas L. <no...@sb...> - 2001-10-21 22:21:03
|
On Mon, 2001-10-22 at 00:03, Eric Bezault wrote: > Andreas Leitner wrote: > > > > *) I need to compile for a special Eiffel compiler / C compiler > > combination. The geant compile_ise_cl approach seems a bit to > > less powerfull as we would need so many rules (n*m). > > A good combination of generic rules in a build file in > $GOBO/misc with a smart use of geant's variables should > make it possible to write these n*m rules once and for > all. For example have look at the file '$GOBO/misc/eiffel.eant' > and the files 'build.eant' in '$GOBO/src/*', or the file > '$GOBO/misc/test.eant' and the file 'build.eant' in > '$GOBO/test/kernel' or those in '$GOBO/example/test/*'. > These are good examples of how code in build files can > be refactored thanks to geant's inheritance mechanism. Yes, but this design assumes we do not get another option. For example the xml examples can be compiled with or without expat. Other such options will surely come with time. Now do I need for each option touch misc/eiffel.eant and add rules (which would clutter it up) that only make sense for some projects. Or I end up adding an endless number of rules in the example itself. I could make a special eiffel.eant for xml project that inherits from misc/eiffel.eant and let my examples inherit from the new eiffel.eant. But still the coupling between the options is to tight. There must be a better way. > > *) The latest ISE Eiffel beta for linux uses > > ${ISE_EIFFEL}/studio/spec/${PLATFORM}/include, on windows > > there is ${ISE_EIFFEL}/bench/spec/${PLATFORM}/include. > > We need some way to check for the existance of a dir and > > set a variable depending on the result. Maybe we should > > come up with some autoconf stuff to overcome all our > > default-value problems ? > > First we can hope that in the next beta versions for Windows > the path will also be named '${ISE_EIFFEL}/studio/...', but > in the meantime here again a smart use of geant's local > variables should do the trick: > > <target name="toto" depend="init"> > <foo bar="${ISE_EIFFEL}/${studio}/spec/${PLATFORM}/include"/> > </target> > > <target name="init"> > <geant target="init_os"/> > ... > </target> > > <target name="init_os"> > <geant target="init_windows"/> > <geant target="init_unix"/> > </target> > > <target name="init_windows" if="${GOBO_OS}=windows"> > <set name="studio" value="bench"/> > ... > </target> > > <target name="init_unix" unless="${GOBO_OS}=windows"> > <set name="studio" value="studio"/> > ... > </target> That was my first approach, meanwhile I put this clause out again, because IMO it is a little ugly. So I added a remark to put a symlink from "studio" to "bench". > As a reminder, note that $GOBO_OS is automatically set > by 'geant'. > > > As for Berends makelib. That looks promising as well. With a > > geant only file we currently have no partial compilation for example. > > What do you mean by "partial compilation"? Aehm, sorry, that was a little unclear. What I meant to say was that makefiles do only tasks they have to do. Based on dependency analysis - using timestamp checks etc. Andreas |
From: Eric B. <er...@go...> - 2001-10-21 22:05:36
|
Eric Bezault wrote: > > I think that the best way to proceed in order to provide such > neat functionality is to add a new command-line option to 'gepp', > such as '-l' and '--line' for example. This is now implemented in the CVS version. The build.eant files in Gobo use this option to generate the Eiffel classes from the .ge files. -- Eric Bezault mailto:er...@go... http://www.gobosoft.com |
From: Eric B. <er...@go...> - 2001-10-21 22:05:35
|
Sven Ehrke wrote: > > geant now supports a simple single inheritance mechanism: The build files in Gobo (except those recently committed to CVS by Andreas) now take this facility into account. This makes the writing of build files much simpler and avoids a lot of code duplication thanks to the combination of generic build files and geant variables. For example see the file '$GOBO/misc/eiffel.eant' and the files 'build.eant' in '$GOBO/src/*', or the file '$GOBO/misc/test.eant' and the file 'build.eant' in '$GOBO/test/kernel' or those in '$GOBO/example/test/*'. Note that I had to fix 2 bugs in GEANT_PROJECT in order to make it work. The first one was to allow environment variables such as $GOBO in the filename specified in the 'inherit' attribute value, and the second was a call to Void target crash when the default target name of a parent build file was not present in the child file. These bugs are fixed now. -- Eric Bezault mailto:er...@go... http://www.gobosoft.com |
From: Eric B. <er...@go...> - 2001-10-21 22:05:15
|
Andreas Leitner wrote: > > *) I need to compile for a special Eiffel compiler / C compiler > combination. The geant compile_ise_cl approach seems a bit to > less powerfull as we would need so many rules (n*m). A good combination of generic rules in a build file in $GOBO/misc with a smart use of geant's variables should make it possible to write these n*m rules once and for all. For example have look at the file '$GOBO/misc/eiffel.eant' and the files 'build.eant' in '$GOBO/src/*', or the file '$GOBO/misc/test.eant' and the file 'build.eant' in '$GOBO/test/kernel' or those in '$GOBO/example/test/*'. These are good examples of how code in build files can be refactored thanks to geant's inheritance mechanism. > *) The latest ISE Eiffel beta for linux uses > ${ISE_EIFFEL}/studio/spec/${PLATFORM}/include, on windows > there is ${ISE_EIFFEL}/bench/spec/${PLATFORM}/include. > We need some way to check for the existance of a dir and > set a variable depending on the result. Maybe we should > come up with some autoconf stuff to overcome all our > default-value problems ? First we can hope that in the next beta versions for Windows the path will also be named '${ISE_EIFFEL}/studio/...', but in the meantime here again a smart use of geant's local variables should do the trick: <target name="toto" depend="init"> <foo bar="${ISE_EIFFEL}/${studio}/spec/${PLATFORM}/include"/> </target> <target name="init"> <geant target="init_os"/> ... </target> <target name="init_os"> <geant target="init_windows"/> <geant target="init_unix"/> </target> <target name="init_windows" if="${GOBO_OS}=windows"> <set name="studio" value="bench"/> ... </target> <target name="init_unix" unless="${GOBO_OS}=windows"> <set name="studio" value="studio"/> ... </target> As a reminder, note that $GOBO_OS is automatically set by 'geant'. > As for Berends makelib. That looks promising as well. With a > geant only file we currently have no partial compilation for example. What do you mean by "partial compilation"? -- Eric Bezault mailto:er...@go... http://www.gobosoft.com |
From: Andreas L. <no...@sb...> - 2001-10-21 20:29:03
|
On Sun, Oct 21, 2001 at 08:31:01PM +0000, Franck Arnaud wrote: > > Regarding the XML parser interface discussions, I agree with > Andreas that the bridge pattern seems to be a bit overkill > and leads to (interface) code duplication, plus it makes > reading the code a bit of a pain (OO spaghetti), especially > because of the callback interface of the parser as it goes > through indirections in all directions. > > In Nenie XML, I have a similar event interface without the > bridge pattern. Still it suffers from some issues mentionned > by Berend. Very interesting idea. What do you think about not using your propriatary XE_INTERFACE as a _streaming source_, but rather KI_OUTPUT_STREAM? Or rather let XE_INTERFACE inherit from KI_OUTPUT_STREAM. The generic type for KI_OUTPUT_STREAM would then be some kind of (named or unamed) TUPLE that holds all parameters. > First, you inherit from a specific implementation (not an > issue in nxml but not nice generally). > > Also, I do various post-processing layers through the > inherited event interface. These layers add more event > procedures, sometimes building on parent events with > Precursor but not always very clearly. This is cumbersome, > layers really have dependencies -- you cannot really > reorder them -- and combining them is not very convenient. > In the end the layering is not very reusable. > > I had some loose thoughts about trying to solve those > issues differently, and with the discussion on this list > starting, I actually wrote a prototype yesterday which > may help. It is available at: > > http://www.nenie.org/eiffel/xml/xmlprototype-oct2001.zip > > It's only compiled with SmallEiffel, not extensively > tested, and uses Nenie XML in one class, but the point > is to show the design rather than the details: it's code > for reading rather than executing (but it does run). You > don't need to know Nenie XML to understand it. > > The two ideas I have implemented are: > > (1) Event processing layer composition is implemented with > delegation rather than inheritance. > > (2) The event interface is simplified to one callback > routine with simple types (enumerations+string). > > Both ideas are to some extent (but not completely, more > later) independent. > > The event interface tries to model all events with three > variable, 2 enumerations and a string: > * location = Attribute | Element | Comment .... > * type = Start | Finish | Name_prefix | Name_local | Data ... > * value = [UC_]STRING > > A short example: > > <!-- comment --> > <a> > <x:b attr='value'>content</b> > </a> > > Would lead to the following event stream: > > LOCATION TYPE VALUE > ------------------------------------------- > Comment Start "" > Comment Data " comment " > Comment Finish "" > Element Start "" > Element Name_local "a" > Attribute Start "" > Attribute Finish "" > Element Start "" > Element Name_prefix "x" > Element Name_local "b" > Attribute Start "" > Attribute Name_local "attr" > Attribute Data "value" > Attribute Finish "" > Element Data "content" > Element Name_prefix "x" > Element Name_local "b" > Element Finish "" > Element Name_local "a" > Element Finish "" > > See XE_INTERFACE for a pseudo-grammar of the event flow. > > Note this does not try to do DTDs and probably wouldn't > scale. I think DTDs are legacy and the issue of having a > clean interface for DTDs is not important, and as Berend > said it's worth having a distinct subset for the core events. > > Layered events are implemented by each descendant forwarding > events to the same interface it responds to: > > deferred class XE_INTERFACE > feature -- Event interface > > on_event (a_where: XE_LOCATION; a_what: XE_TYPE; a_value: STRING) is > -- XML event. > -- See invariant for allowed event sequence. > deferred > .... > > deferred class XE_FILTER_INTERFACE > inherit > XE_INTERFACE > > feature -- Next > next: XE_INTERFACE > > > Actual event processors inherit from XE_FILTER_INTERFACE, and call > next.on_event (...) within the own implementation of on_event. > > Then, using the filters is just a question of making a pipe, > given functions that create filters and bind 'next': > > a_parser.set_interface (debug_printer (null)) > -- XML parser event source -> print events -> null > > a_parser.set_interface (namespace_resolver (pretty_printer (null))) > -- parser -> resolve namespaces -> print canonical xml -> null > > 'null' is a XE_INTERFACE that does nothing, to finish the pipe. > 'a_parser' is the event source starting the pipe. > > This is where the simplified interfaces comes in: filters are > allowed to change or add events. So, the namespace resolver > adds an event with the namespace URI before each 'name, local > part' event. Without the simplified interface, any downstream > event interface would need to be typed with the new event -- e.g. > an extra routine or a replacement routine with a different > signature. > > At the cost of somewhat weaker typing, although it is still > as checkable as before dynamically with contracts, we get > easier composition of filter pipes. This is useful for > filters which can do generic processing and forwards > generically unknown events. An example is a value sharing > filter which reduces the number of live strings: > > class XE_VALUE_SHARER > inherit XE_FILTER_INTERFACE > creation set_next > feature > > on_event (a_where: XE_LOCATION; a_what: XE_TYPE; a_value: STRING) is > -- Event. > do > -- ... > if not values.has (a_value) then > values.force (a_value) > end > next.on_event (a_where, a_what, values.item (a_value)) > end > > feature {NONE} > values: DS_HASH_SET[STRING] > > end > > This filter can be placed before or after the namespace > resolver, it would not be possible if the namespace resolver > changed the static types of the event interface. > > With a simple interface and this composition scheme, no > client code would inherit from a parser, it would just call > set(XE_INTERFACE). If it does use the bridge pattern, the > small size of the interface and forwarding for one routine > makes it more acceptable. > > > So in the end, it seems this design allows: > > - easy composition of layers of event processing > - clean client interface (no inheritance from parser) > - bridge vs. factory does not matter for the parser Yep, all we would have are sources and sinks. And since a source can be a sink, combining and reusing components becomes very easy. Man, I like the stream pattern (; > At the cost of: > > - more dynamic typing of event types > - somewhat different coding style If static typing is really an issue, we can still provide a sink that has the old interface, at the cost of one more dispatch. This would be needed anyway to preserve backward compatibility. > On coding style, the namespace resolver I wrote for the > prototype is 2/3 of the code of the one in Nenie XML while > being more reusable. I'm not sure it is due to the API or > some other reason. The API is different enough, and > the problem small, so that I quickly stopped trying to > copypaste my original code into the new API. > > One thing I considered was having a single polymorphic > parameter in on_event, and then processing either using > something like the visitor pattern or reverse assignments. > The visitor pattern would be dangerously close than the > existing event interfaces (worse with more indirections?) > and reverse assignment type dispatching is ugly. > > A thing I didn't investigate but which may be worth looking > at, is seeing how this integrates with the pipe classes > in Gobo. Well, then we would only have one polymorphic parameter. Whatever that would be. Actually I don't see the problem of the visitor pattern plus stream pattern. It would be just one additional sink, that one can use or choose not to use. I agree that reverse asignement would be ugly. > > I hope people can have a look at the code and comment > whether it could be a good API. It's just a few hours > hack, nothing set in stone even if it were adopted for > Gobo XML (rewriting a similar idea with different details > is not much work). Let's see if others have comments on it as well. Also, performance is one issue. Although I think that with this new approach performance should not suffer. This approach simplifies the whole event interface a lot. The tree interface could drop the bridge pattern then as well, since it was never really needed. I only did it in the beginning to allow for a DOM parser to plug in, but I think in practice this is too cumbersome anyway. regards, Andreas |
From: Andreas L. <no...@sb...> - 2001-10-21 20:04:35
|
On Sun, Oct 21, 2001 at 06:06:18PM +1000, Glenn Maughan wrote: > Andreas, > > > *) The expat backend seems to segfault with ISE on windows and > > linux, gotta look at it in detail. But the current geant file has > > been tested to (at least) compile on linux/gcc/se|ise and > > windows/cl/ise, where linux/gcc/se actually works at runtime too (; Problem fixed. The see code was still looking for EP_EVENT_PARSER, whereas it has been renamed to XP_EVENT_PARSER. I have also now added code that checks if the class we resolve is actually in the system. An exception is raised otherwise. This code is protected via an #ifdef and can be enabled by setting ${GOBO_C_DEBUG} before executing geant compile in library/xml/impl/expat/spec/c. I have tested in on linux. Can somebody confirm that this now works on windows too? Andreas |
From: Franck A. <fr...@ne...> - 2001-10-21 19:32:21
|
Regarding the XML parser interface discussions, I agree with Andreas that the bridge pattern seems to be a bit overkill and leads to (interface) code duplication, plus it makes reading the code a bit of a pain (OO spaghetti), especially because of the callback interface of the parser as it goes through indirections in all directions. In Nenie XML, I have a similar event interface without the bridge pattern. Still it suffers from some issues mentionned by Berend. First, you inherit from a specific implementation (not an issue in nxml but not nice generally). Also, I do various post-processing layers through the inherited event interface. These layers add more event procedures, sometimes building on parent events with Precursor but not always very clearly. This is cumbersome, layers really have dependencies -- you cannot really reorder them -- and combining them is not very convenient. In the end the layering is not very reusable. I had some loose thoughts about trying to solve those issues differently, and with the discussion on this list starting, I actually wrote a prototype yesterday which may help. It is available at: http://www.nenie.org/eiffel/xml/xmlprototype-oct2001.zip It's only compiled with SmallEiffel, not extensively tested, and uses Nenie XML in one class, but the point is to show the design rather than the details: it's code for reading rather than executing (but it does run). You don't need to know Nenie XML to understand it. The two ideas I have implemented are: (1) Event processing layer composition is implemented with delegation rather than inheritance. (2) The event interface is simplified to one callback routine with simple types (enumerations+string). Both ideas are to some extent (but not completely, more later) independent. The event interface tries to model all events with three variable, 2 enumerations and a string: * location = Attribute | Element | Comment .... * type = Start | Finish | Name_prefix | Name_local | Data ... * value = [UC_]STRING A short example: <!-- comment --> <a> <x:b attr='value'>content</b> </a> Would lead to the following event stream: LOCATION TYPE VALUE ------------------------------------------- Comment Start "" Comment Data " comment " Comment Finish "" Element Start "" Element Name_local "a" Attribute Start "" Attribute Finish "" Element Start "" Element Name_prefix "x" Element Name_local "b" Attribute Start "" Attribute Name_local "attr" Attribute Data "value" Attribute Finish "" Element Data "content" Element Name_prefix "x" Element Name_local "b" Element Finish "" Element Name_local "a" Element Finish "" See XE_INTERFACE for a pseudo-grammar of the event flow. Note this does not try to do DTDs and probably wouldn't scale. I think DTDs are legacy and the issue of having a clean interface for DTDs is not important, and as Berend said it's worth having a distinct subset for the core events. Layered events are implemented by each descendant forwarding events to the same interface it responds to: deferred class XE_INTERFACE feature -- Event interface on_event (a_where: XE_LOCATION; a_what: XE_TYPE; a_value: STRING) is -- XML event. -- See invariant for allowed event sequence. deferred .... deferred class XE_FILTER_INTERFACE inherit XE_INTERFACE feature -- Next next: XE_INTERFACE Actual event processors inherit from XE_FILTER_INTERFACE, and call next.on_event (...) within the own implementation of on_event. Then, using the filters is just a question of making a pipe, given functions that create filters and bind 'next': a_parser.set_interface (debug_printer (null)) -- XML parser event source -> print events -> null a_parser.set_interface (namespace_resolver (pretty_printer (null))) -- parser -> resolve namespaces -> print canonical xml -> null 'null' is a XE_INTERFACE that does nothing, to finish the pipe. 'a_parser' is the event source starting the pipe. This is where the simplified interfaces comes in: filters are allowed to change or add events. So, the namespace resolver adds an event with the namespace URI before each 'name, local part' event. Without the simplified interface, any downstream event interface would need to be typed with the new event -- e.g. an extra routine or a replacement routine with a different signature. At the cost of somewhat weaker typing, although it is still as checkable as before dynamically with contracts, we get easier composition of filter pipes. This is useful for filters which can do generic processing and forwards generically unknown events. An example is a value sharing filter which reduces the number of live strings: class XE_VALUE_SHARER inherit XE_FILTER_INTERFACE creation set_next feature on_event (a_where: XE_LOCATION; a_what: XE_TYPE; a_value: STRING) is -- Event. do -- ... if not values.has (a_value) then values.force (a_value) end next.on_event (a_where, a_what, values.item (a_value)) end feature {NONE} values: DS_HASH_SET[STRING] end This filter can be placed before or after the namespace resolver, it would not be possible if the namespace resolver changed the static types of the event interface. With a simple interface and this composition scheme, no client code would inherit from a parser, it would just call set(XE_INTERFACE). If it does use the bridge pattern, the small size of the interface and forwarding for one routine makes it more acceptable. So in the end, it seems this design allows: - easy composition of layers of event processing - clean client interface (no inheritance from parser) - bridge vs. factory does not matter for the parser At the cost of: - more dynamic typing of event types - somewhat different coding style On coding style, the namespace resolver I wrote for the prototype is 2/3 of the code of the one in Nenie XML while being more reusable. I'm not sure it is due to the API or some other reason. The API is different enough, and the problem small, so that I quickly stopped trying to copypaste my original code into the new API. One thing I considered was having a single polymorphic parameter in on_event, and then processing either using something like the visitor pattern or reverse assignments. The visitor pattern would be dangerously close than the existing event interfaces (worse with more indirections?) and reverse assignment type dispatching is ugly. A thing I didn't investigate but which may be worth looking at, is seeing how this integrates with the pipe classes in Gobo. I hope people can have a look at the code and comment whether it could be a good API. It's just a few hours hack, nothing set in stone even if it were adopted for Gobo XML (rewriting a similar idea with different details is not much work). -- fr...@ne... |
From: Glenn M. <gle...@op...> - 2001-10-21 08:01:44
|
Andreas, > *) The expat backend seems to segfault with ISE on windows and > linux, gotta look at it in detail. But the current geant file has > been tested to (at least) compile on linux/gcc/se|ise and > windows/cl/ise, where linux/gcc/se actually works at runtime too (; Make sure the dll built for expat on Windows is in your path. This caused seg faults when I was first using it. I have it running with ISE and Windows. Glenn. |
From: Berend de B. <be...@po...> - 2001-10-20 20:32:30
|
Andreas Leitner <no...@sb...> writes: > As for Berends makelib. That looks promising as well. With a geant only file we currently have no partial compilation for example. Are there features to: > *) Define MACRONS for the C files, depending on the eiffel compiler Use, things like ISE or VE are defined and passed to the C compiler. > *) Define extra include paths Not yet. > *) Define extra include paths, depending eiffel compiler Example? With #ifdefs (C code is bad anyway, so make it more bad isn't a problem :-)) ) you can solve this good enough I think. -- Groetjes, Berend. (-: |
From: Sven E. <sve...@we...> - 2001-10-20 19:15:42
|
>Don't get me wrong. In practice we will end up keeping >`filenames' in KL_DIRECTORY and having the new functionality >in an external class in another library. But in theory I >don't see any difference between the two routines in >terms of functionality and therefore (still in theory) >they should be either both in KL_DIRECTORY or both outside >in a common external class. I agree completely (in theory and practice ;-) ) - Sven |
From: Eric B. <er...@go...> - 2001-10-20 18:55:42
|
Sven Ehrke wrote: > > That's right. But I would prefer to have KL_DIRECTORY.filenames > as it is now rather than having a `filename' which tries to handle all possible > cases (maybe including the ** notation as well). This would either > make `filenames' really complex or result in many more features > in KL_DIRECTORY. I was not suggesting having a more complex `filenames' routine. I was just saying that `filenames' is in the same category of routines as the one we are talking about, so apart from other considerations explained in previous messages, I don't see why we should have one and not the other. > The way it is now it provides the base for extended > functionality which can be built outside. Likewise if `filenames' was not implemented in KL_DIRECTORY. Don't get me wrong. In practice we will end up keeping `filenames' in KL_DIRECTORY and having the new functionality in an external class in another library. But in theory I don't see any difference between the two routines in terms of functionality and therefore (still in theory) they should be either both in KL_DIRECTORY or both outside in a common external class. > Maybe we could call it 'io' to be symmetrical with the kernel? Yes, good idea. -- Eric Bezault mailto:er...@go... http://www.gobosoft.com |
From: Andreas L. <no...@sb...> - 2001-10-20 18:41:13
|
Hi, I have produced a proof of concept geant file for libexml yesterday. You can find it under library/xml/impl/expat/spec/c/buiild.ant There were several difficulties to overcome: *) I need to compile for a special Eiffel compiler / C compiler combination. The geant compile_ise_cl approach seems a bit to less powerfull as we would need so many rules (n*m). For now I offer only a rule per c compiler (which can also be set implicitly via GOBO_CC) and take the eiffel compiler from GOBO_EIFFEL. (which a default to gcc, se) *) The latest ISE Eiffel beta for linux uses ${ISE_EIFFEL}/studio/spec/${PLATFORM}/include, on windows there is ${ISE_EIFFEL}/bench/spec/${PLATFORM}/include. We need some way to check for the existance of a dir and set a variable depending on the result. Maybe we should come up with some autoconf stuff to overcome all our default-value problems ? *) The expat backend seems to segfault with ISE on windows and linux, gotta look at it in detail. But the current geant file has been tested to (at least) compile on linux/gcc/se|ise and windows/cl/ise, where linux/gcc/se actually works at runtime too (; As for Berends makelib. That looks promising as well. With a geant only file we currently have no partial compilation for example. Are there features to: *) Define MACRONS for the C files, depending on the eiffel compiler *) Define extra include paths *) Define extra include paths, depending eiffel compiler regards, Andreas PS: As for the bridge pattern. I totally forgot the advantage of it (thanks Berend for the detailed pro/cons mail) You cannot do what the tree_on_event parser does: Inherit from the event parser and the at runtime plug in any event based parser you want. So we'll stick with the bridge pattern. |
From: Sven E. <sve...@we...> - 2001-10-20 18:34:37
|
On 20/10/2001 at 8:01 PM Eric Bezault wrote: >Sven Ehrke wrote: >> >> I think the functionality of the fileset should not be mixed into >KL_DIRECTORY. > >I agree with that, for the reasons I gave in my previous message. >But on the other hand if you look at KL_DIRECTORY.filenames, isn't >that just a special case of the functionality we are talking about, >where the wildcard regular expression is *? That's right. But I would prefer to have KL_DIRECTORY.filenames as it is now rather than having a `filename' which tries to handle all= possible cases (maybe including the ** notation as well). This would either make `filenames' really complex or result in many more features in KL_DIRECTORY. The way it is now it provides the base for extended functionality which can be built outside. > >> What about somewhere under library/utility? > >Yes. What do you suggest for the cluster name? Maybe we could call it 'io' to be symmetrical with the kernel? If you find that too general we could call it 'filesystem'. - Sven |
From: Eric B. <er...@go...> - 2001-10-20 18:03:42
|
Sven Ehrke wrote: > > I think the functionality of the fileset should not be mixed into KL_DIRECTORY. I agree with that, for the reasons I gave in my previous message. But on the other hand if you look at KL_DIRECTORY.filenames, isn't that just a special case of the functionality we are talking about, where the wildcard regular expression is *? > What about somewhere under library/utility? Yes. What do you suggest for the cluster name? -- Eric Bezault mailto:er...@go... http://www.gobosoft.com |
From: Sven E. <sve...@we...> - 2001-10-20 17:25:43
|
On 20/10/2001 at 6:09 PM Eric Bezault wrote: >Sven, > >I had a look at you implementation of FILE_SET yesterday. >First I had to slightly modify the code to make it compile. >For example in STRING_TOOLS the occurrences of FILESET_SCANNER >should be replaced by WC_TO_RX_CONVERTER, and in >WC_TO_RX_CONVERTER there is an "ensure else" instead of >"ensure then" and the line: > > a_wildcard_pattern :=3D "^" + a_wildcard_pattern + "$" > >should be removed since it is already done in >STRING_TOOLS.convert_wildcardexp_to_regexp. > sorry for the confusion. >Now, more general remarks. I think that using 'gelex' to >parse **/, * and ? is a little bit overkill. It shouldn't Yes, I am aware of this. At the beginning I just did not want to spend too much time on this since it can be optimized now. >be that difficult to implement that "by hand" (if you don't >feel like doing it -- if I remember corretly you told me >that you already tried it unsuccessfully -- I can do it). It would be great if you have the time to do it. > >The routine STRING_TOOLS.string_tokens should definitely go >in a (yet to be implemented) string library (see the archive >of this mailing list for small description I made some months >ago about what classes and routines this string library I am aware of this too. Some stuff from geant could be removed then as well. There is also a class UT_STRING_ROUTINES in library/tools/xace/support which could be removed then. >And now for RX_FILESET_SCANNER, which as far as I understood >will be renamed as FILE_SET, this is surely a reusable class, >but I'm not sure where it should go in the Gobo libraries. >Although it includes directory traversal, I don't want it >to go in library/kernel/io because it uses regexps and as >a rule of thumb the library/kernel should only depend on the >Eiffel compilers' kernel libraries (and nothing else in the >rest of the Gobo libraries). I need some time to think about >that. Otherwise, without this constraint, we could have had >a routine in KL_DIRECTORY which would have taken a regexp >(or a list of regexps) as argument, and would have returned >a list (or set) of filenames either matching or not (one of) >the regexp(s). Hmmm, we could have a descendant of KL_DIRECTORY >outside of library/kernel to do that, but then where do we put >this new class? I think the functionality of the fileset should not be mixed into= KL_DIRECTORY. What about somewhere under library/utility? Another note here: in the current implementation only files are considered= but I could imagine that directories could be taken into account as well. I am= not sure yet if it would make sense to have them in the same class like XX_FILE_SYSTEM_ENTRY_SET or having two classes XX_FILE_SET XX_DIRECTORY_SET with a parent class for the common functionality. > >Now in your last message you spoke about having two different >FILE_SET objects for the included and excluded files. I see >no reason why not doing that. Did you already try to implement >this idea with a small example? Not yet. Although this example is a special case for geant it would be a good starting point. I'll try to make something up this weekend. Thanks for looking into this. - Sven |
From: Eric B. <er...@go...> - 2001-10-20 16:10:54
|
Sven, I had a look at you implementation of FILE_SET yesterday. First I had to slightly modify the code to make it compile. For example in STRING_TOOLS the occurrences of FILESET_SCANNER should be replaced by WC_TO_RX_CONVERTER, and in WC_TO_RX_CONVERTER there is an "ensure else" instead of "ensure then" and the line: a_wildcard_pattern := "^" + a_wildcard_pattern + "$" should be removed since it is already done in STRING_TOOLS.convert_wildcardexp_to_regexp. Now, more general remarks. I think that using 'gelex' to parse **/, * and ? is a little bit overkill. It shouldn't be that difficult to implement that "by hand" (if you don't feel like doing it -- if I remember corretly you told me that you already tried it unsuccessfully -- I can do it). The routine STRING_TOOLS.string_tokens should definitely go in a (yet to be implemented) string library (see the archive of this mailing list for small description I made some months ago about what classes and routines this string library should contain and how it should be organized). This string library (to go in $GOBO/library/string) is still in my TODO list and should start being implemented soon now. And now for RX_FILESET_SCANNER, which as far as I understood will be renamed as FILE_SET, this is surely a reusable class, but I'm not sure where it should go in the Gobo libraries. Although it includes directory traversal, I don't want it to go in library/kernel/io because it uses regexps and as a rule of thumb the library/kernel should only depend on the Eiffel compilers' kernel libraries (and nothing else in the rest of the Gobo libraries). I need some time to think about that. Otherwise, without this constraint, we could have had a routine in KL_DIRECTORY which would have taken a regexp (or a list of regexps) as argument, and would have returned a list (or set) of filenames either matching or not (one of) the regexp(s). Hmmm, we could have a descendant of KL_DIRECTORY outside of library/kernel to do that, but then where do we put this new class? Now in your last message you spoke about having two different FILE_SET objects for the included and excluded files. I see no reason why not doing that. Did you already try to implement this idea with a small example? -- Eric Bezault mailto:er...@go... http://www.gobosoft.com |
From: Eric B. <er...@go...> - 2001-10-20 15:18:18
|
Uwe Sander wrote: > > Damn, I have overseen the export clause. I think that it is more a problem with Eiffel compilers not reporting CAT-calls (or with the Eiffel language not providing an explicit implementation inheritance technique) than a problem with you as a programmer overseeing the export clause (which is a trick anyway). With expanded inheritance as sketched out in ETL3 draft, polymorphism with implementation inheritance would be forbidden (and detected) by the compiler, and therefore we would have a compilation error with that line: stream := file This would make things much clearer that using the convention whereby "export {NONE} all" means implementation inheritance. -- Eric Bezault mailto:er...@go... http://www.gobosoft.com |
From: Uwe S. <us...@on...> - 2001-10-20 14:52:08
|
Hi, > KL_TEXT_INPUT_FILE indirectly inherits from INPUT_STREAM > using implementation inheritance (export {NONE} all), therefore > even though no Eiffel compiler forbids the above assignment > it is theoritically invalid. At least that's the way I consider > it when I write Eiffel code. Damn, I have overseen the export clause. Sorry for the stupid question. Regards Uwe |
From: Eric B. <er...@go...> - 2001-10-20 12:40:41
|
Andreas Leitner wrote: > > Now I wanted to start working on the documentation of the various > implementations. But I remember the in the book "The Pragmatic > Programmer" they talk about too much documentation, documentation > that is redundant that is. They argue that such documentation is > likely to get out of sync and thus it is better to not introduce > redundant documentation in the first place. > > What is your (the list, or better Eric :) opinion on that? I don't exactly remember what "The Pragmatic Progammer" says, but I guess it's something like the doc in the source code gets out of sync with the paper/HTML doc. Here it is different: the header comment documents the routine. If you have two similar routines it's normal that you end up with two similar header comments. It's unlikely (although possible) that the header comment gets out of sync with the body of its routine, however it would be very painful if we would have to go to a similar routine in another class in order to read the header comment of a given routine. So I don't think that the header comments are redundant in this case. It's as if you wouldn't put the header comment in a redefined routine just because it already appears in the ancestor class. I don't think that flat-tools are currently able to display the inherited header comment (they usually display the header comment of the redefined version of the routine), therefore the header comment should be repeated (and possibly improved) for ease of reference. I think we should do the same in your case for the bridge pattern. -- Eric Bezault mailto:er...@go... http://www.gobosoft.com |
From: Eric B. <er...@go...> - 2001-10-20 11:19:08
|
Andreas Leitner wrote: > > I think ideally we should replace the Makefile.* mess in > /library/xml/impl/expat/spec/c with only one maintainable > geant file. I agree. That's why I spoke about "patch" in my previous message: I just wanted to make it work for Glenn in the short term. > The trivial abstraction level would be to create a a compile > and create archive command for each c-compiler (and OS combination?) > and then use conditionals in the geant files. Can we do better? As far as I know we already have a geant task for 'lcc'. So perhaps this could be extended to other supported C compilers. -- Eric Bezault mailto:er...@go... http://www.gobosoft.com |