**** BEGIN LOGGING AT Sun Jun 11 09:03:03 2006 Jun 11 09:03:03 * Now talking on #gsv Jun 11 09:03:07 hi there Jun 11 09:03:08 hi Jun 11 09:03:18 I'd like to speak a bit about SoC Jun 11 09:03:29 that's cool :) Jun 11 09:03:35 can you update me on the progresses? Jun 11 09:03:48 so we can take some decision about next steps Jun 11 09:04:29 hi muntyan Jun 11 09:04:59 well, no progress really Jun 11 09:05:40 i didn't have time yet to do what we decided to do Jun 11 09:05:45 hmm... plans, thoughts, etc. Jun 11 09:05:56 the sorting + processing changes that fall into the batch Jun 11 09:06:12 um, did you read our conversation with pbor and barisione? Jun 11 09:06:19 no Jun 11 09:06:23 oh, ok Jun 11 09:06:27 I'm going to read it now Jun 11 09:06:35 then, the plan and stuff is: Jun 11 09:06:39 pbor: is it already on l.g.o? Jun 11 09:07:23 attaching Jun 11 09:07:28 there is a problem with highlighting which seems (seems, nobody knows really why it happens) to occur because sorting the modifications queue is not enough Jun 11 09:07:38 so the plan is: Jun 11 09:07:59 http://live.gnome.org/GtkSourceView/SummerOfCode2006?action=AttachFile&do=view&target=2006-06-07.txt Jun 11 09:08:00 is it me or l.g.o has broken CSS today? Jun 11 09:08:24 make the function which processes a batch take all the modifications from queue which intersect with the batch Jun 11 09:08:37 then see what happens - whether the problem is fixed or not Jun 11 09:09:03 if the problem is fixed, then it means highlighting basically works (hopefully), and we can think of speed issues and whatnot Jun 11 09:09:33 i guess it wasn't really clear :) Jun 11 09:09:43 paolo: how much do you know about how the engine works? Jun 11 09:10:02 little, so I need details to understand the problems Jun 11 09:10:25 * paolo is reading the old IRC log Jun 11 09:10:25 okay, i'll try to explain it Jun 11 09:11:01 what engine does is: 1) it analyzes the buffer from the beginning to the end; 2) it updates syntax after buffer changes Jun 11 09:11:17 1) is done by processing batch by batch, in an obvius way Jun 11 09:11:21 now, about modifications: Jun 11 09:12:01 when text is inserted or deleted, engine records the modification as offset where it happened, and the length of text inserted/removed Jun 11 09:12:11 then it puts this modification into the queue Jun 11 09:12:47 then it queues updating (or processes modification immediately, but it's irrelevant) Jun 11 09:13:30 idle_worker (for simplicity assume it's always idle_worker who does the analysis and everything) does the following: Jun 11 09:14:06 it peeks the first modification from the queue, and updates syntax in a batch which includes changed region Jun 11 09:14:34 if it can't merge old and new syntax regions in this one batch, it analyzes the remainder of buffer as it does it with new buffer Jun 11 09:15:01 if there are no modifications in the queue, it processes not analyzed remainder of the buffer Jun 11 09:15:14 so, there are bunch of problems here: Jun 11 09:16:28 1) it needs to sort modifications and update them. for example, if you delete text at position 100, and then delete text at position 10, then the at-pos-10 modification must be processed first, and the second modification should have offset corrected (it was 100, but after second deletion it should be 100-(how many chars deleted)) Jun 11 09:17:29 2) what seems to be the problem now: when engine processes a modification, it takes a big batch, and potentially it changes syntax in whole batch, so the changed area may include modifications which are still in the queue Jun 11 09:17:54 the plan for the nearest future is to fix 2) and see what happen Jun 11 09:17:59 the end. Jun 11 09:18:00 :) Jun 11 09:18:37 first question: how are batches computed? What is a batch in this context? Jun 11 09:18:46 4000 chars, roughly Jun 11 09:18:56 ok Jun 11 09:19:05 it calculates the length according to how fast it processed previous batches, but that's details Jun 11 09:19:25 yep Jun 11 09:20:33 you said the whole buffer is analyzed, batch by batch? Is this a sync operation? Jun 11 09:20:51 no, idle_worker processes one batch Jun 11 09:21:11 what does it happens if a change is queued before the whole buffer has been analyzed for the first time? Jun 11 09:21:37 it keeps worker_last_offset - how much of the buffer has been analyzed Jun 11 09:21:49 if the modification is after last_offset, it's just ignored Jun 11 09:22:09 what does it happen if I'm going to "show" a part of the buffer that still need to be analyzed? Jun 11 09:22:54 if it's before, then the modification is processed; if it could merge old and new in one batch, it processes the region after last_offset as usual (in next idle run); if not, then it sets last_offset to the end of the batch, and then proceeds as usual Jun 11 09:23:50 when part of buffer is exposed, then it's asked to apply tags in the exposed area; if it's not analyzed yet, there are no tags Jun 11 09:24:48 i looked at the sources, and: Jun 11 09:25:44 it checks last_offset. if exposed area is before last_offset, it applied tags; if not, it records the region to apply tags later, then it will be analyzed Jun 11 09:26:25 yes, the code there is pretty much what current sourceview does as far as I can tell Jun 11 09:26:39 (except for some details I don't like) Jun 11 09:26:44 also, when it updates syntax somewhere, it emits signal so that view can queue redraw in the updated area; then expose will ask to apply correct tags Jun 11 09:26:49 seems to be correct Jun 11 09:26:54 how fast is the first analysis of the whole buffer (for example on a 10000 lines C file) Jun 11 09:27:44 good question Jun 11 09:28:08 worker_last_offset is the last analyzed offset, right? Jun 11 09:28:19 yep Jun 11 09:29:01 it looks "fast enough", i didn't measure it Jun 11 09:29:11 the analisys of the whole doc on open seems of acceptable performance to me too Jun 11 09:30:10 one of the issues with the queue instead is that if you have something like d'n'd, an expose event forces to apply tags between the remove and the add part of the dnd Jun 11 09:30:21 which leads to flicker Jun 11 09:30:41 I was thinking about making a very fast first analysis that only splits the document in first level contexts and the re-analyze on demands the current context before displaying it to apply the correct tags Jun 11 09:30:44 pbor: no, if you process more than one modification at a time Jun 11 09:30:57 this is what's needed to be done Jun 11 09:31:19 yes, I am just exposing one of the issues there are now Jun 11 09:31:26 didn't say it's unfixable Jun 11 09:31:27 :) Jun 11 09:31:40 paolo: that would work only if first-level contexts don't need children to know where they end Jun 11 09:31:49 this is one of things i wanted to talk about Jun 11 09:32:23 hmm... what do you mean? Jun 11 09:33:36 1) child context may decide to terminate its parent Jun 11 09:34:09 2) it seems to be nicer if many rules may decide when to terminate context Jun 11 09:34:28 at the moment contexts have start and end conditions (regexes or chars, or something) Jun 11 09:34:39 i think they should have more than that Jun 11 09:34:54 e.g. here i have a lang file which has #pop#pop Jun 11 09:35:12 it means it terminates itself and parent Jun 11 09:35:19 did you understand something? Jun 11 09:36:04 yep, but can you report a specific use case for this? Jun 11 09:36:29 Jun 11 09:36:29 Jun 11 09:36:29 Jun 11 09:36:47 some crazy thing from kate Jun 11 09:36:51 's bash lang file Jun 11 09:38:03 Is it so important to support this feature? Are there other ways to support the same feature? Jun 11 09:38:25 i have no idea Jun 11 09:38:37 the .lang files by barisione support this feature? Jun 11 09:38:44 but i don't like that contexts have end attribute Jun 11 09:38:52 paolo: the engine doesn't know about such a thing Jun 11 09:39:10 context has end which is defined by regex, and that's it Jun 11 09:39:46 besides, what happens when context and its child are both terminated by same thing, e.g. end of line? Jun 11 09:40:16 like Jun 11 09:40:19 #ewfwe //ewfwef Jun 11 09:40:22 in a C file Jun 11 09:40:45 (not with gtksourceview's c.lang, it doesn't know that preprocessor directive is whole line, not only word after #) Jun 11 09:40:54 it seems the .lang files by barisione do not require an "end" attribute for contexts Jun 11 09:41:16 they don't reuiqre it for "simple" contexts Jun 11 09:41:30 those simple contexts are just regions matched by certain regex Jun 11 09:41:49 but container contexts do require end attribute Jun 11 09:42:00 (at least in my reading code and lang files :) Jun 11 09:42:24 ok Jun 11 09:43:00 (this is a question to ask to barisione, please collect all the open questions in a mail to send later) Jun 11 09:43:18 ok Jun 11 09:43:21 mmm... isn't the end regex of a container context done by ORing all the possible ends of the child context which terminate the parent? Jun 11 09:44:09 no Jun 11 09:44:15 it can't work, can it? Jun 11 09:44:33 you can't just match anything, contexts may jump like crazy Jun 11 09:44:33 well, yes Jun 11 09:44:58 for this to work you need *everything* be controlled by end regexes Jun 11 09:45:05 e.g. ends-at-line-end breaks it Jun 11 09:45:07 i think Jun 11 09:45:09 but you need to use a stack of context also during the fast analysis Jun 11 09:45:55 ends-at-line-end it is one of the ORed possible ends Jun 11 09:46:24 but child may opt not to terminate there Jun 11 09:46:28 while parent may temrinate Jun 11 09:46:36 it's how trailing \ is done Jun 11 09:46:39 ok Jun 11 09:47:12 the parent (preprocessor) ends at line-end, but it has child context that consumes end of line, so the parent won't see it Jun 11 09:47:14 we can analyse this problem later Jun 11 09:47:24 let us return to the current problems Jun 11 09:47:39 it seems to me the mother of all the problems is the queue of changes Jun 11 09:47:50 (regular expressions can encapsulate arbitrarily complex thing, but noone will understand it) Jun 11 09:47:54 I have a question... do we really need it? Jun 11 09:48:06 well, yes if we don't want to touch contexts tree Jun 11 09:48:17 context tree is the mother of the problems Jun 11 09:48:29 it keeps offsets in the nodes Jun 11 09:48:31 what is the "context tree"? Jun 11 09:48:39 ok Jun 11 09:48:46 stupid question Jun 11 09:48:56 not really stupid Jun 11 09:48:59 so the problem is not the context tree per se Jun 11 09:49:25 well, it depends on how you look at it Jun 11 09:49:29 let me explain Jun 11 09:49:40 there are two things in here: Jun 11 09:50:08 1) the 'state machine', the tree of contexts which represents how contexts may be there, how parents include children and such Jun 11 09:50:42 2) the sequence of segments of text, where each segment corresponds to some state of that state machine, or to some node of the contexts tree Jun 11 09:50:58 in the engine these two are one thing, the "contexts tree" Jun 11 09:51:25 if it's right, then the queue is the problem, but it can't be removed Jun 11 09:51:36 if it's not right, then the contexts tree is the problem Jun 11 09:51:37 :) Jun 11 09:52:54 the *real* problem is that the engine has no idea about the fact that buffer can be modified many times and in any order; the rest is implementation details ;) Jun 11 09:53:11 and we are free to solve it in any way we like Jun 11 09:53:31 (saying this just to make sure noone is afraid of removeing queue or something) Jun 11 09:54:09 well, it seems to me we need a contexts tree (or syntax tree) Jun 11 09:54:17 do all agree on this? Jun 11 09:55:11 and if I have understand the problem, the current algorithms does not support multiple changes Jun 11 09:55:25 but only single changes, right? Jun 11 09:55:46 well, I guess there are other data structures which could hold the syntax informations Jun 11 09:56:10 we do need one tree, for sure Jun 11 09:56:16 in particular all the regex work is based on analyzing lines Jun 11 09:56:28 while the context tree has no idea about lines Jun 11 09:56:35 but we don't necessarily need to have syntax segments in the contexts tree Jun 11 09:57:13 and yes, current algorithms do not really support multiple changes Jun 11 09:57:39 ok, explain me how do you see the prefect context tree Jun 11 09:58:01 I mean we have some code, it is not working for several reasons Jun 11 09:58:07 i wish i knew what perfect context tree is :) Jun 11 09:58:14 i guess i'd start implementing it Jun 11 09:58:19 there are not millions of lines Jun 11 09:58:34 so we can rewrite part of it without too much worrying Jun 11 09:58:47 i can describe what i have in my engine: Jun 11 09:58:52 ok Jun 11 09:59:21 1) the contexts tree, which is just a tree of contexts and their children, nodes are added when corresponding context is met in the buffer Jun 11 09:59:22 may be explain also how it is different from the gsv one Jun 11 10:00:06 2) the text part is kept in a separate structure: each line has list of segments, each segment keeps pointer to a node of contexts tree Jun 11 10:00:45 this makes it easy to invalidate parts of buffer - just erase segments on the lines Jun 11 10:01:06 it's still not convenient for modifications inside of the line though Jun 11 10:01:20 err, this is a bit not what i am describing :) Jun 11 10:01:52 well, if you invalidate part of the buffer you also need to remove nodes from the tree, right? Jun 11 10:01:54 so, the main thing is: contexts are the states in the state machine; segments in texts are segments which "are in this state" Jun 11 10:02:01 paolo: no Jun 11 10:02:08 why not? Jun 11 10:02:18 i have one node for top-level comments, for example Jun 11 10:02:29 regardless of how many comments are in the buffer Jun 11 10:02:46 i have many text segments that point to "top-level C comment" node Jun 11 10:03:17 basically your tree describes the possible state transitions for a language Jun 11 10:04:01 right Jun 11 10:04:17 (not all possible, only those that actually occur in the text) Jun 11 10:04:25 it contains a subset of the state machine for the specific language Jun 11 10:04:31 right Jun 11 10:05:01 what's good in this (or bad in gtksourceview's) is the following: Jun 11 10:05:17 in mine, i can merge two segments simply by comparing the nodes Jun 11 10:05:32 in gtksourceview's, it needs nodes to be the same with all parents Jun 11 10:06:17 not sure it's really very good, but it is simple Jun 11 10:06:54 there is a potential problem in gtksourceview, related to this: Jun 11 10:07:24 when text is modified, the engine takes a batch of text, and reanalyzes it, trying to merge old and new nodes Jun 11 10:07:44 if it can't do it in this batch, it simply reanalyzes whole remainder of the buffer Jun 11 10:08:01 even if contexts can be merged in the next batch Jun 11 10:08:23 hmmm... actually I think we need what is normally called a "concrete syntax tree" Jun 11 10:08:32 what's that? Jun 11 10:08:36 see http://en.wikipedia.org/wiki/Concrete_syntax_tree Jun 11 10:09:24 it looks like the tree in gtksourcecontextengine Jun 11 10:09:39 yep, that's what the context tree is right now Jun 11 10:09:50 the problem is that it's not modification-friendly Jun 11 10:10:11 that is a tree that represents the current state of the whole buffer Jun 11 10:10:12 just coloring is only half of work; we need to recolor as well :) Jun 11 10:11:45 building a tree like muntyan's one would also give us the chance to share it across files Jun 11 10:11:48 hm, does colorer support modifications? Jun 11 10:11:56 that is one tree for all C files open Jun 11 10:12:12 muntyan: yes, it's the engine used in eclipse I think Jun 11 10:13:10 colorer should support modifications Jun 11 10:13:14 it is not used in eclipse Jun 11 10:13:44 when barisione started his work we planned to rewrite colorer in a glib friendly way Jun 11 10:14:01 but it seems it was not a good solution Jun 11 10:14:08 I don't remember the details Jun 11 10:15:19 paolo: http://colorer.sourceforge.net/sshots/e2.png Jun 11 10:15:30 paolo: though maybe it's just an additional plugin Jun 11 10:15:39 there is a plugin for ecplise based on colorer Jun 11 10:17:03 muntyan: can you tell us more about the other data structure you use? that is the one that holds the segments... Jun 11 10:17:22 it is not clear to me why a tree like the one I said should not work Jun 11 10:17:28 muntyan: I know it's a btree, but I don't totally grok why Jun 11 10:17:30 ? Jun 11 10:17:42 paolo: it's already there, and it doesn't work :) Jun 11 10:17:55 paolo: the tree itself will work, why not? but it needs some stuff to support it Jun 11 10:18:10 yep, I agree on this Jun 11 10:18:36 well, it could also work without additional data structures Jun 11 10:18:40 pbor: btree because it has easy insertion and deletion Jun 11 10:18:50 paolo: how to deal woth modifications? Jun 11 10:18:54 wih Jun 11 10:18:56 with Jun 11 10:19:22 invalidating part of the tree when a modification happens Jun 11 10:19:37 don't forget about tags Jun 11 10:19:54 'tags are applied in the buffer, and they need to be removed when new highlighting is ready Jun 11 10:20:00 muntyan: I mean, what do you cache in the nodes? for instance GtkTextBTree allows to know if there is a tag without checking all the leafs/segments Jun 11 10:20:18 at the moment tree keeps offsets, and with modifications queue you always can tell where tags are applied Jun 11 10:20:41 pbor: let me look at it :) Jun 11 10:21:30 I don't think tags are a problem here Jun 11 10:21:52 suppose you invalidate a part of the tree (a subtree) Jun 11 10:21:59 pbor: i keep number of line marks in nodes; and leaf nodes contain highlighting stuff and the marks Jun 11 10:22:06 a subtree represent a part of the buffer Jun 11 10:22:13 paolo: tags are not a problem, the problem is having offsets in the tree nodes Jun 11 10:22:21 you have to remove the tags from that part of the buffer Jun 11 10:22:34 paolo: but you can't do it until you have new tags Jun 11 10:22:48 muntyan: why not? Jun 11 10:23:02 because there is nothing to delete until then Jun 11 10:23:07 pbor: since we need to use relative offset Jun 11 10:23:12 paolo: yes, but how do you map a subtree to an area of the buffer? Jun 11 10:23:13 if you delete text, there is no region to delete tags from Jun 11 10:23:13 pbor: not absolute ones Jun 11 10:23:22 you need to analyze it first Jun 11 10:23:34 or if you insert text, same thing Jun 11 10:24:02 you can mark position as "invalid", but you don't know in advance what *area* really changed Jun 11 10:24:42 hmm... it is difficult to explain without figures Jun 11 10:25:09 let me try step by step Jun 11 10:25:16 don't think to the current implementation Jun 11 10:25:23 hm, actually i don't see why what i'm saying makes sense Jun 11 10:25:38 suppose you have a syntax tree Jun 11 10:25:57 like the one in the wikipedia figure Jun 11 10:27:41 suppose you add a piece of text between "the" and "ball", then you invalidate a part of the tree Jun 11 10:28:12 if the text does not create a new context, then you only need to add a new node (without invalidating other nodes) Jun 11 10:28:31 otherwise you will have to invalidate part (or all) the tree Jun 11 10:29:34 let us speak about text offset now Jun 11 10:29:57 ATM we use absolute offset Jun 11 10:30:04 i'll be back in ten minutes, son is hungry Jun 11 10:30:36 so "Jonh" is [0-4], "hit" is [5-8]" and so on Jun 11 10:30:55 I think we should use relative offset Jun 11 10:31:08 where relative is according to the "father" node Jun 11 10:31:46 in this way it will be easier to make changes without visiting all the tree Jun 11 10:32:10 and the queue will contain "nodes" and not text segments Jun 11 10:32:16 what do you think? Jun 11 10:32:34 using relative offsets may be better for the tree merging, but I don't see how it helps us: Jun 11 10:32:57 the fact is that the real analisys happens async, in the idle Jun 11 10:33:25 so a second modification can happen before you analyzed the first one Jun 11 10:33:47 wait Jun 11 10:33:51 and you can't put the nodes in queue, since it means analyzing right away Jun 11 10:34:19 we can split analysis in a sync part (i.e. updating or invalidating the tree) Jun 11 10:34:45 and a second aync part "rebuilding" the invalidate part of the tree Jun 11 10:35:48 i,e. always having a fast analysis computing only the "first" level of the subtree Jun 11 10:36:04 well, that depends on how fast the tree invalidation is... Jun 11 10:36:37 it only works on the tree, so I think it should be fast enough Jun 11 10:37:26 it may also have other problems for performance (though here is all moot without numbers) Jun 11 10:38:05 for instance a 'paste' inserts many chuncks of text (one for each tag toggle) Jun 11 10:38:26 so you would do many invalidations before reanalizying Jun 11 10:38:45 how do you invalidate part between contexts? Jun 11 10:38:59 e.g. top-level no-contexts text Jun 11 10:39:14 2) merging is still hard Jun 11 10:39:29 merging will be always hard :) Jun 11 10:39:43 not if you don't keep segments in the tree Jun 11 10:39:49 invalidating part between contexts means adding a new context Jun 11 10:40:03 and updating the offset of the following siblings Jun 11 10:40:30 it is the easiest update Jun 11 10:41:41 what I mean is that syntax trees are historically the most important data structure in language analysis Jun 11 10:41:57 and I don't think we have to invent new structures Jun 11 10:42:19 well, let me play angry: Jun 11 10:42:57 i have working highlighting without any knowledge of history; and there is broken engine which didn't invent new data structures Jun 11 10:42:57 What about trying to look at eclipse code and at colorer to see what they are using?) Jun 11 10:43:03 * muntyan stops playing angry Jun 11 10:43:22 hehe :) Jun 11 10:43:30 what i want to say is that we need something that will work and is good. "history" is zero weight argument here, imho Jun 11 10:44:37 sheesh, color tarball doesn't have single toplevel dir! Jun 11 10:44:41 colorer Jun 11 10:44:45 good it's in /tmp Jun 11 10:44:45 well, history is always important... if you want call it a "design pattern" :) Jun 11 10:45:03 i don't give a shit to that, it means too little these days Jun 11 10:45:11 everybody uses "design patterns" ;) Jun 11 10:45:35 paolo: well, the fact that a tree can be used to represent a syntax is no news, but the real question is what do we need the tree for? Jun 11 10:45:40 anyway, if a tree is good, it's good. but we need to know for sure what we choose, and why Jun 11 10:46:43 I mean, the engine is keeping a tree of the whole buffer syntax up to date, but as far as I can see it's not really using it Jun 11 10:47:22 for highlighting it just wants to know which tag apply to each segment Jun 11 10:47:38 and to do this you have to walk the whole segments Jun 11 10:47:57 be it be going trough a list, walking a tree or whatever Jun 11 10:49:00 i personally worry about modifications, they have proven to be the hard part ;) Jun 11 10:49:27 maybe the whole syntax tree can be very useful for stuff like folding, or for indenters... but I am missing the compelling reason to have a full tree representation of the syntax of the text in the buffer Jun 11 10:50:04 to avoid to re-analyze part of the buffer during modifications Jun 11 10:50:18 and put the basis for further analysis Jun 11 10:51:22 but for hl I just want to iter through the text and know at which point of the syntax 'stack' I am in Jun 11 10:52:08 that is, I just need to know the parent context, not all the ancestors Jun 11 10:52:31 (except for the #pop#pop case muntyan said before) Jun 11 10:52:32 in either case we have a tree, just maybe implicitly; question is whether we really need a big tree with number of nodes equal number of syntax regions in the buffer Jun 11 10:53:00 pbor: we do need all the ancestors; but once we have parent, we have its parent, and so on Jun 11 10:53:29 muntyan: yes, sure Jun 11 10:54:21 anyway, I think that invalidating the tree right away could solve the issues with the queue Jun 11 10:54:38 what has to be seen is if we can do that fast enough Jun 11 10:55:28 should be fast Jun 11 10:58:08 as far as I can see that is also orthogonal to the relative offset issue Jun 11 10:59:10 what do you mean? Jun 11 10:59:45 that you can invalidate a part of a tree even with absolute offsets Jun 11 10:59:49 can't you? Jun 11 11:00:36 yep, they are relative problems Jun 11 11:00:44 I mean ortogonal Jun 11 11:00:54 but if offsets are absoulte, you need to walk all the nodes? Jun 11 11:01:17 using relative offset enable in some cases very fast changes without the need to walking all the subtree Jun 11 11:01:35 relative offsets rule Jun 11 11:01:41 absolute offsets suck Jun 11 11:01:43 :) Jun 11 11:02:47 yes, we all agree that relative offsets are better Jun 11 11:03:01 I'd say: can we try to write down the "modification" algorithm in pseudo code (so we can also use it for documentation)? Jun 11 11:04:25 I think a modification can only have 3 effects: Jun 11 11:04:31 - adding a context Jun 11 11:05:15 - invalidating a subtree of contexts Jun 11 11:05:50 well they are only 2 Jun 11 11:06:33 actually we could reduce "adding a context" as a sub-case of "invalidating a subtree" Jun 11 11:06:34 comments in colorer look like it reparses everything after modification Jun 11 11:07:09 pbor: do you still have the thesis of barisione? Jun 11 11:07:15 paolo: yes Jun 11 11:07:21 what does "invalidating subtree" mean? invalidating whole subtree and reanalyzing it? Jun 11 11:07:28 are therec omments con colorer? Jun 11 11:08:28 it means removing it from the context tree and mark the linked buffer segment as "to-be-analyzed" Jun 11 11:09:13 paolo: not really... just a small paragraph where it says why implementing sourceview instead of using colorer Jun 11 11:09:29 well, no, it means: Jun 11 11:09:37 - removing the subtree Jun 11 11:09:41 paolo: and the arguments are: overcomplex, C++, ugly lang files Jun 11 11:09:59 i am thinking about inserting text at the top level Jun 11 11:10:01 - leaving the root (marked as "to-be-analyzed") Jun 11 11:10:18 you don't want to remove anything, i.e. adding a node is not invalidating a subtree Jun 11 11:10:50 http://rafb.net/paste/results/bXZKT725.html Jun 11 11:10:55 ok, I agree Jun 11 11:11:12 that's from colorer header, looks rather nasty Jun 11 11:11:36 ok Jun 11 11:11:53 anyway, who is colorer? Jun 11 11:11:59 does it work in any decent editor? Jun 11 11:12:12 see the homepage :) Jun 11 11:12:24 I have never tried the cited editors Jun 11 11:12:31 eclipse is shit, mc doesn't have live updating on modifications Jun 11 11:12:38 dunno about far Jun 11 11:13:44 eclipse is great :) Jun 11 11:13:51 but it is not using colorer Jun 11 11:15:00 eclipse is great? you have strong nerves then :) Jun 11 11:15:08 or using java Jun 11 11:15:52 using java Jun 11 11:16:04 it must be great then :) Jun 11 11:18:14 eclipse is a great IDE for Java... but it sucks for C/C++ Jun 11 11:21:50 so, to sum things up, do we have a plan? Jun 11 11:24:04 muntyan: how much effort is to 'fix' the queue for the 'debug thing'? if it's not much maybe it would be nice to fix it just to see if something else bites us before touching the context tree... Jun 11 11:25:25 I think the plan is: Jun 11 11:25:31 lot of effort Jun 11 11:25:59 1. writing the modification algorithm in pseudo-code Jun 11 11:26:10 2. validating it by hand Jun 11 11:26:39 3. modifying the current context tree according to 1 (using relative offsets) Jun 11 11:26:45 do you agree? Jun 11 11:26:52 3. is really really hard Jun 11 11:27:06 why? Jun 11 11:27:07 for me it besically means rewriting everything Jun 11 11:27:22 it could be Jun 11 11:27:56 trying to preserve most code is possible Jun 11 11:28:19 or cutting and pasting in the new code most old-code is possible Jun 11 11:28:38 I'm thinking to the code performing parsing Jun 11 11:28:51 one needs to understand the code first ;) Jun 11 11:28:55 do you guys agree in my action plans? Jun 11 11:29:07 honestly, i don't like it Jun 11 11:29:14 why? Jun 11 11:29:18 we did not discuss all the issues Jun 11 11:29:31 let us discuss them, then Jun 11 11:29:42 and this plan is a big plan, it's not something "for now to see what happens" Jun 11 11:30:09 how to merge old and new trees? Jun 11 11:30:24 do we want to give up after N characters and reanalyze reminder of the buffer? Jun 11 11:31:45 well, that is something that need measuring Jun 11 11:32:01 it really depends on how much slower is try to merge the old tree Jun 11 11:32:20 it's important Jun 11 11:32:25 well, this is what point 1 needs to Jun 11 11:32:35 if we want not to give up, we need to keep new and old stuff around Jun 11 11:33:41 what do you mean with "merging old and new trees"? Jun 11 11:34:42 when some text is modified, it potentially changes highlighting after the modification place Jun 11 11:35:01 so we need to merge what we get after analyzing modified text and what we had before Jun 11 11:35:18 paolo: the current algorith is: "when a modification is made find the upper context affected, detach the subtree, fix its offsets. then start reanalyzin. at each step see if the old tree merges, if yes use it and stop reanalyizing" Jun 11 11:35:29 what happens is that we have old tree, covering all the buffer; and we have new branches growing from the modified region Jun 11 11:35:45 we need to glue those branches and old tree, and throw away wrong old nodes Jun 11 11:36:30 well, "invalidating" really means marking an 'old' subtree in the tree Jun 11 11:36:37 why it is useful merging with the old tree? Why we cannot simple replace it? Jun 11 11:36:53 paolo: we can't simply reanalyze all the reminder of the buffer Jun 11 11:36:54 paolo: because analyzing is slow Jun 11 11:37:01 insert one char, for example Jun 11 11:37:07 you don't want to analyze whole file Jun 11 11:37:53 yeah, if it weren't slow, we wouldn't have any problem :) Jun 11 11:38:57 ok, I see Jun 11 11:39:23 but still this is what point 1 is needed for Jun 11 11:39:39 we need to try to write down the algorithm Jun 11 11:39:45 point 1 is useful in any situation Jun 11 11:39:52 but we need to know the algorythm first Jun 11 11:40:10 point 1 is "design the real-algorithm" Jun 11 11:40:41 we have discussed about an intuition, about guide-lines, we need to design the details Jun 11 11:40:45 you are assuming that the algorithm is exactly the tree as you described it, and exactly doing what you said Jun 11 11:40:55 we didn't decide we do it, did we? Jun 11 11:41:20 well, it seems to me we decided about two points: Jun 11 11:41:26 - using relative offset Jun 11 11:41:56 - using a "concrete syntax tree" Jun 11 11:42:17 err, it seems you really decided to do it :) Jun 11 11:42:19 now we have to figure how the syntax tree must be modified when a modification happens Jun 11 11:42:46 well, the algorithm is asaics not much different from the current one: leaving relative offset aside, currently we put the modifications in a queue, then the idle runs peeks a modifications find the affected tree node and do the analyze/merge magic Jun 11 11:43:03 with the new idea we just dump the queue Jun 11 11:43:12 exactly Jun 11 11:43:17 do the 'find affected node' sync Jun 11 11:43:35 and the idle walks the tree and finds the first node that needs updating Jun 11 11:43:51 the queue becomes a list of "nodes" to be analyzed in a more detailed way Jun 11 11:44:10 well, we don't even need such queu IMHO Jun 11 11:44:18 may be no Jun 11 11:44:24 the idle handler can simply walk the tree Jun 11 11:44:56 and find the upmost node that needs analisys Jun 11 11:45:04 that is that is marked invalid Jun 11 11:45:47 'detaches' the old tree at that node and then do the analyze/merge pretty much as it does now Jun 11 11:46:38 the problem is that the current analyze algo use the modification 'delt' Jun 11 11:46:41 *delta Jun 11 11:47:03 it uses delta only to update offsets, i think; it's not a problem Jun 11 11:47:12 okay even better Jun 11 11:47:21 but merging won't magically work! Jun 11 11:47:30 no it won't Jun 11 11:47:32 and that question is still open Jun 11 11:47:43 do we want to give up after analyzing one batch? Jun 11 11:48:27 why is this so important? Jun 11 11:48:30 but as far as I can see the merging works at the moment, doesn't it (apart from the offsets screwed by the async queue)? Jun 11 11:48:47 it does work now Jun 11 11:48:56 and it will work Jun 11 11:49:10 how is this going to influence the algorithm we are trying to design? It seems to me an implementation detail we can evaluate later. Am I wrong? Jun 11 11:49:19 yes Jun 11 11:49:51 if you are more confortable you can make it always try to merge Jun 11 11:49:56 or no, but it's an extremely important detail Jun 11 11:50:04 and we can see how it goes Jun 11 11:50:05 which takes half of the code Jun 11 11:50:20 well, not really as far as I can see Jun 11 11:50:28 sure it is important, but we can see it in a second step Jun 11 11:50:35 pbor: the code is simple now because it does give up Jun 11 11:50:38 giving up is easy Jun 11 11:50:45 "simple" Jun 11 11:51:09 well, is giving after a batch up so costly? Jun 11 11:51:59 it depends on how good the batch is Jun 11 11:52:23 with single modification, giving up is right, assuming the tree is a good idea Jun 11 11:52:39 i.e. with the tree as it is, it's too expensive not to give up Jun 11 11:52:46 and in most cases it works fine Jun 11 11:52:59 well, giving up at some point seems like a correct euristic to me... if you can't merge after X lines the probability of merging later goes down Jun 11 11:53:08 what needs tweaking is X Jun 11 11:53:24 that is how hard try before giving up Jun 11 11:53:34 multiple modifications break this euristic :) Jun 11 11:53:41 but that's just a knob in the Reader objectt Jun 11 11:54:09 you are assuming that the modification is in the beginning of the batch, and there is nothing modified after it Jun 11 11:54:18 it's the case for hand-editing Jun 11 11:54:52 if now we mark 'invalid' in the tree directly we should be able to be smarter Jun 11 11:54:53 (though even in this case, you have #if 0 ... #endif on 1001 lines, and batch of 1000 line, and boom) Jun 11 11:55:18 we can see if two modifications are for indipendent branches of the tree Jun 11 11:55:50 it doesn't matter, in such bad cases Jun 11 11:56:19 thing is that you change one char, and it can modify arbitrarily big part of the buffer Jun 11 11:56:24 I don't think the algorithm for all seasons exists Jun 11 11:56:26 it can kill all the contexts after it Jun 11 11:56:30 so there are trade off Jun 11 11:56:34 it does exist Jun 11 11:56:43 we can start giving up after a batch Jun 11 11:56:50 not having such a tree is such an algorithm :) Jun 11 11:56:52 and then implement a better algo in a second step Jun 11 11:57:38 I really don't see why your data structure is better Jun 11 11:57:54 because merging is easy Jun 11 11:57:59 nothing to merge Jun 11 11:58:10 why not? Jun 11 11:58:19 because there are no nodes to merge Jun 11 11:58:22 a bit far fetched but it's something like DOM vs SAX, isn't it? :) Jun 11 11:58:28 you don't operate with nodes, you operate with segments Jun 11 11:59:16 ok, but then you cannot use the info for code folding or other context sensitive analysis Jun 11 11:59:35 why can't you? Jun 11 11:59:47 the state machine is there, you have the tree of contexts Jun 11 12:00:03 um, got it Jun 11 12:00:15 yes, you need another tree for that Jun 11 12:00:24 (though, say for code folding you need it anyway) Jun 11 12:00:58 indeed, hacing a tree is good Jun 11 12:01:04 but merging is awful Jun 11 12:01:34 besides, does it play well with those context-sensitive things? (if we consider it as an argument, then we need to consider what happens when we invalidate nodes) Jun 11 12:01:52 I'm still not convinced about the need of merging, but may be I'm missing some details Jun 11 12:02:13 okay, what happens when you insert a character? Jun 11 12:02:25 you invalidate a node, what then? Jun 11 12:05:26 that's it, you invalidate the node instead of pushing the modification in the queue Jun 11 12:05:33 if it creates a new context, then invalidate all the following siblings Jun 11 12:05:35 yes Jun 11 12:05:40 what does the analyzer do Jun 11 12:06:00 simple case Jun 11 12:06:06 you are typing in: Jun 11 12:06:08 "wefwef Jun 11 12:06:12 and then you insert " Jun 11 12:06:14 in a C file Jun 11 12:06:36 you must merge stuff Jun 11 12:06:51 you invalidate the parent Jun 11 12:07:09 and then it will be re-analyzed in an async way Jun 11 12:07:12 parent is NULL Jun 11 12:07:20 so, how it will be reanalyzed? Jun 11 12:07:30 okay, let me give more details Jun 11 12:07:33 no, parent cannot be null Jun 11 12:07:35 you have a C file: Jun 11 12:07:36 wait Jun 11 12:07:37 so Jun 11 12:07:43 --------------- Jun 11 12:07:44 "efwefwefwef Jun 11 12:07:51 int a (void) Jun 11 12:07:52 ------------ Jun 11 12:08:02 and then you insert " after ewfwef Jun 11 12:08:17 you invalidate the top top context, fine Jun 11 12:08:37 what will idle_worker do after it closes the string context, what will it do on the next line? Jun 11 12:08:48 you don't want to reanalyze the next line, there is nothing to reanalyze Jun 11 12:09:04 so you need to merge what was before and what you have now Jun 11 12:10:30 in the idle handler you find the invalidated node in the tree and split the tree there, Jun 11 12:10:38 then you analize the first line Jun 11 12:10:42 pbor: i am trying to convince we need to do it Jun 11 12:10:49 then you try to merge the split node Jun 11 12:10:50 pbor: the splitting and merging Jun 11 12:10:57 err, to convince paolo Jun 11 12:11:11 yes, we defintely need to split and merge Jun 11 12:11:53 if you add a ", you have to: Jun 11 12:12:08 'invalidating in the tree' is just a different way to tell where to split instead of using an offset Jun 11 12:12:12 - invalidate the parent node (toplevel root in this case) Jun 11 12:12:50 and analyze the part of the buffer associated with the node Jun 11 12:12:57 in this case the entire buffer Jun 11 12:13:06 hmm... no Jun 11 12:13:30 since in C with have string ending with end of line Jun 11 12:13:54 so you need to: Jun 11 12:14:01 - invalidate the root (as before) Jun 11 12:14:03 right, and it could be anything ending anywhere, say after char "Z" Jun 11 12:14:23 - analyzing the node Jun 11 12:15:10 ok... I see what you mean with merging Jun 11 12:15:41 but I don't see why it is so difficult to achieve Jun 11 12:18:08 because ten nodes go to trash, and you end up with node of depth 8 on the left, and node of depth 4 on the right, having different top-level ancestors Jun 11 12:18:19 or vice versa Jun 11 12:18:24 it's really nasty Jun 11 12:18:42 oh, forgot about important detail Jun 11 12:18:58 you also have no idea if you can merge nodes after ten next chars Jun 11 12:19:18 i.e. you don't know if you need to throw away everything (give up) or look a bit further Jun 11 12:19:34 dunno, it's very dirty business Jun 11 12:20:36 besides, about folding Jun 11 12:20:51 imagine you have a big function body, longer than a batch Jun 11 12:21:10 well, this is due to the fact you want to manage merging in a very smart way Jun 11 12:22:05 I think we should try to manage simple cases as special cases Jun 11 12:22:14 good ppint Jun 11 12:22:16 point Jun 11 12:22:19 and then use a generic brutal approach for the general case Jun 11 12:22:40 still, it's not obvious to me that cases like " after C string or > in xml file are really easy Jun 11 12:22:52 * muntyan draws Jun 11 12:22:52 I mean adding a single character is a special very frequent case Jun 11 12:22:58 other are less frequents Jun 11 12:23:06 no! Jun 11 12:23:12 in gedit, maybe Jun 11 12:23:19 it Jun 11 12:23:29 s very important to handle search/replace, for example Jun 11 12:23:40 or my active strings, i like my active strings Jun 11 12:23:46 hm, snippets? Jun 11 12:24:22 sure, but how frequently are the user using it? May be a more brutal generic approach is fast enough for that cases Jun 11 12:24:23 err, "less" is true, but "less frequent" doesn't mean "not frequent" Jun 11 12:24:40 paolo: often :) Jun 11 12:25:08 well, we really need a way to mark 'interactive' changes in a way different from 'one-char-lenght'... Jun 11 12:25:14 BTW, merging is an important part of the algorithm implementation Jun 11 12:25:21 but that's a separate issue IMHO Jun 11 12:25:26 I still would like to see "the" algorithm Jun 11 12:26:04 i would LOVE to see it :) Jun 11 12:26:34 so, is it the final decision to have the tree as you described it? Jun 11 12:29:20 the final decision is up to you too Jun 11 12:29:33 you are the guy, I'm only the "observer" :) Jun 11 12:29:35 well... Jun 11 12:29:40 you are the boss :) Jun 11 12:29:51 hehe Jun 11 12:29:59 i still do not see why "tree" is better than "no tree" Jun 11 12:30:11 historical and "no new stuff" arguments do not count Jun 11 12:30:32 the folding and such are good arguments, but it's not clear why the tree will be *really* good for those Jun 11 12:30:59 since you can decide to fold at the "node" level Jun 11 12:31:06 note, i am not saying that my idea is better. if i thought so, i'd say it. but i want to know for sure what i am doing Jun 11 12:31:17 paolo: you can do it with no-tree too Jun 11 12:31:23 paolo: since the tree is still there Jun 11 12:31:34 paolo: and, it's not clear how folding will play with modifications Jun 11 12:31:38 exactly, this is why I don't see no-tree is better Jun 11 12:31:39 in either case Jun 11 12:31:53 you have the same info in a different, IMO less clean, way Jun 11 12:32:06 i'd say it is more clean Jun 11 12:32:18 because you don't mix syntax and text segments Jun 11 12:32:29 text segments know about syntax, but syntax tree doesn't Jun 11 12:32:32 and it doesn't need to Jun 11 12:32:41 i.e. it depends on point of view :0 Jun 11 12:32:50 main thing is that merging is easy with no-tree Jun 11 12:33:05 why? Jun 11 12:33:18 explain the above example with your data structure Jun 11 12:33:44 you insert a char, you mark line as invalid Jun 11 12:33:49 then, you reanalyze the line Jun 11 12:34:06 then, if the expected-on-next-line context is the same as the actual one, you stop Jun 11 12:34:17 and what does it happen if the context span multiple lines? Jun 11 12:34:28 same thing, you invalidate next line Jun 11 12:34:36 until you have won Jun 11 12:34:54 honestly, I don't see why it is different Jun 11 12:35:07 merging is extremely easy Jun 11 12:35:14 no splitting, no merging Jun 11 12:35:21 actually I think it is less efficient since you always invalidate the entire line Jun 11 12:35:28 paolo: you always have to Jun 11 12:35:41 in either approach Jun 11 12:35:55 you can optimize it by looking at regexes, also with either approach Jun 11 12:35:58 why? Jun 11 12:36:02 suppose you have Jun 11 12:36:04 there is look-ahead and look-behind Jun 11 12:36:10 /* ciao Jun 11 12:36:13 you always have to reanalyze whole line Jun 11 12:36:13 ciao ciao Jun 11 12:36:45 */ ciao / ciao */ Jun 11 12:36:54 if you add a * after / Jun 11 12:37:02 you don't have to invalidate the entire line Jun 11 12:37:18 only because *you* *know* C syntax Jun 11 12:37:28 in general case you must analyze whole line Jun 11 12:37:39 because you are using a tree Jun 11 12:37:46 (and it can be optimized, by looking at children, regexes and whatnot) Jun 11 12:37:48 paolo: nope Jun 11 12:37:50 and so you know the syntax Jun 11 12:38:13 i know the syntax with my approach, i have the same information as with the tree Jun 11 12:39:03 what i meant by "you know" is "you, paolo, know" Jun 11 12:39:16 you know that the C syntax doesn't have fancy things in that case Jun 11 12:39:28 but in general, one char can change *everything* Jun 11 12:39:32 whole buffer Jun 11 12:39:39 (in weird cases :) Jun 11 12:40:21 you have to analyze the line (note that "analyze" doesn't mean "remove and apply tags", it means "check what's already there") Jun 11 12:40:49 anyway, I don't see why it is different Jun 11 12:40:50 say, shebang line Jun 11 12:40:52 #!/eiohfierwog Jun 11 12:40:57 ! changes whole line Jun 11 12:41:09 paolo: the difference is in the merging process Jun 11 12:41:17 paolo: with my approach, no merging process Jun 11 12:41:30 paolo: with the tree, it's fairly complicated Jun 11 12:41:58 ask pbor :) Jun 11 12:42:42 ATM you invalidate the entire line, ok Jun 11 12:42:52 why can't you do the same with the tree? Jun 11 12:43:00 you invalidate all the nodes of the line Jun 11 12:43:06 invalidating is easy Jun 11 12:43:11 merging is hard Jun 11 12:43:11 you have the same effect Jun 11 12:43:38 does you code perform merging? Jun 11 12:43:59 it doesn't have to Jun 11 12:44:16 it checks whether expected next-line context matches one which is already theer Jun 11 12:44:17 there Jun 11 12:44:27 if it matches, we are done; if not, analyze next line Jun 11 12:44:31 why you cannot do it with the tree? Jun 11 12:45:12 you can, actually Jun 11 12:45:18 but, tree doesn't know about lines Jun 11 12:45:20 if next sibling matches you are done, if not give invalidate it, and analyze next one Jun 11 12:46:35 let me smoke a bit, looks like everything is fine, and i really can throw away the merging part Jun 11 12:47:08 argh.... smoke is dangerous :) Jun 11 12:47:19 yeah, it kills Jun 11 12:47:43 I hope not before the end of SoC ;) Jun 11 12:47:55 hm, if we split all contexts on line breaks, it should work Jun 11 12:48:40 but how to do that? do we need line breaks? Jun 11 12:48:51 the merging part is what is really killing me Jun 11 12:48:57 i hate it, and it hates me Jun 11 12:49:26 I don't see why you are so "bind" to line breaks... they are chars like the other ones Jun 11 12:49:39 no, splitting contexts on line breaks may do all this stuff every inefficient Jun 11 12:49:45 we you need to split context at line breaks if not needed Jun 11 12:49:45 paolo: they are not Jun 11 12:49:53 paolo: "\r\n" vs "\n" Jun 11 12:50:18 line breaks are very special places in the buffer, unfortunately Jun 11 12:50:30 why? Jun 11 12:50:37 "\r\n" vs "\n" Jun 11 12:50:42 they are not chars Jun 11 12:50:46 they are special places Jun 11 12:51:07 ok, but they are not special from the "syntax hl" point of view Jun 11 12:51:09 but why do i want to split contexts? Jun 11 12:51:14 paolo: they are Jun 11 12:51:21 why? Jun 11 12:51:35 paolo: every normal language knows what "line" is, and doesn't care about line terminators Jun 11 12:51:41 or what do you mean? Jun 11 12:51:52 they can end some kind of contexts Jun 11 12:52:31 ^blah rules are not rare too Jun 11 12:52:35 but for other contexts they have no importance and so you don't need to threat them in a special case in those contexts Jun 11 12:52:44 anyway, thing is that line end is not a char Jun 11 12:52:51 think to "multiline C comments" Jun 11 12:53:16 ok, they are places Jun 11 12:53:20 yes, it's not right to split everything Jun 11 12:53:32 but their importance is related to the current context Jun 11 12:53:48 so there is no need to always split Jun 11 12:54:01 (sorry, /me reads the backlog) Jun 11 12:54:02 you split only if the current context can end with a line break Jun 11 12:54:23 * paolo is trying to convert muntyan to the word of trees :) Jun 11 12:54:49 he will become a naturalist before the end of the project :) Jun 11 12:54:55 my research area is groups of tree automorphisms :) Jun 11 12:55:07 finite automata, and stuff Jun 11 12:55:24 anyway, i don't see now why no-tree is better than tree Jun 11 12:55:28 so, why I'm speaking about Jun 11 12:55:37 so i guess i agree with those points Jun 11 12:55:40 you should use trees everywhere Jun 11 12:56:01 well, my no-tree approach involves having a BTree :) Jun 11 12:56:08 trees are everywhere :) Jun 11 12:57:42 to summarize (my wife called, so I need to go home, in order to avoid physical damages :) Jun 11 12:58:19 - we are going to use a tree with relative offset Jun 11 12:58:39 - probably merging is not so difficult as we thought Jun 11 12:59:01 - splitting should be not a problem Jun 11 12:59:50 - queue will not contain the buffer modifications, but (if we really need a queue) the invalidated nodes Jun 11 13:00:06 i think queue is not needed at all Jun 11 13:00:27 we can have two flags - invalid, and some-child-is-invalid Jun 11 13:00:31 and then just walk the tree Jun 11 13:00:48 and maybe some first-invalid link, or index, or something Jun 11 13:00:54 * muntyan hates the queue :) Jun 11 13:01:40 ok Jun 11 13:03:15 there is one problem with lines, but it desrves an email, i think Jun 11 13:03:26 in any case it's not quick, and doesn't change things to do now Jun 11 13:04:15 muntyan: can you please write down a little summary of the discussion we had today and save the log on l.g.o for future reference Jun 11 13:04:34 at least the conclusions Jun 11 13:04:46 i am not a good writer... Jun 11 13:04:48 and send it by mail to me, pbor and barisione Jun 11 13:04:52 ok Jun 11 13:04:52 a few lines Jun 11 13:05:36 them you can start designing/implementing the algorithm Jun 11 13:06:30 ok Jun 11 13:07:35 err, can we close the meeting? i'm afraid there will be two injured... Jun 11 13:08:08 yes Jun 11 13:08:46 paolo, pbor, see you later then Jun 11 13:08:54 * paolo didn't backup his notebook again Jun 11 13:09:03 later Jun 11 13:09:10 bye Jun 11 13:09:10 * pbor needs to go too Jun 11 13:09:17 * paolo has quit (Ex-Chat) Jun 11 13:10:00 pbor: four hours!!! **** ENDING LOGGING AT Sun Jun 11 13:11:19 2006