A grammar_t instance now deep-copies potential grammars it includes and each call to parse_grammar() returns a new unique instance.
The latter allows mutating the grammar (by the parser) and the former ensures that grammars are not left with expired pointers (to other grammars) when bundle items are updated.
Using GCD actually makes the code slower — it might have to do with locking overhead from std::shared_ptr and onig_region_new/region_free.
Worth trying again once use of std::shared_ptr has been removed from the parser, and oniguruma regions are preallocated.
Previously we had to test if the patterns contained \A, \G, or \z, and if so, rewrite those anchors based on wether or not the current line/match position could match them.
This is instead of keeping a std::set with rule identifiers. Keeping the information in the grammar is a lot faster (about 25%) as we can update the status in O(1) without any memory allocation.
The downside is that the grammar is now being mutated by the parser. This is currently safe because only a single thread is used for parsing. When we switch to allowing multiple threads to perform parsing, we should make a copy of the grammar for each instance.
Another downside is that we only tag rules that have begin/match patterns, so rules that are wrappers for a set of rules, or rules that are including another rule, are never rejected, even if already visited, but the target rules they resolve to will be, though if an include (indirectly) include itself, we will no longer break such cycle (though it is clearly a bug in the grammar, if this happens, and we could preprocess the grammar to catch it).
This makes loading time roughly twice as fast, although some of the speed gain is because we no longer need to convert CFPropertyListRef → plist::any_t.
Previously this had to be done via global constructor functions but it would seem the execution of these may happen before initialization of global data.
Building with clang 3.2 (binary distribution) results in “illegal instruction” when adding 3 seconds to the steady clock, so I just replaced the code.
The reason the code was using std::chrono was to be able to provide better debug output, as dispatch_time_t is an abstracted time representation (according to the documentation).
A DFA node may be disposed as part of DFA construction (because the node is redundant) and here it would have “next” pointers setup, which it should not follow in its destructor, since those nodes could still be used.
Fixes#1086
For example when creating a new bundle (‘foo.tmBundle’) and then saving a new snippet in this bundle (‘bar.tmSnippet’) we may ask to rescan the ‘Snippets’ folder (in the bundle) before the bundle itself does a content (re)scan, which effectively makes the ‘Snippets’ rescan a no-op.
Should fix#1034
Previously it would only observe NSViewBoundsDidChange from the clip view containing the text view, and while it worked most of the time, it failed to see notifications when a text view was smaller than the clip view’s view port and grew, yet still staying smaller than the view port.
If libcurl is built with the default DNS resolver then it will handle a timeout by using SIGALRM, though since we are using threads, and signals are not compatible with threads, this may have led to a crash in Curl_resolv_timeout (for users where a DNS lookup could take longer than the timeout, presumably 300 seconds).
I’m seeing a crash in ‘-[OakDocumentView dealloc]’ stating that “selectionString” is not being observed. This would indicate that a OakDocumentView instance is created that doesn’t go through the designated initializer, how that can happen is beyond me, but with the reshuffled code, if it happens, it should no longer cause a crash in dealloc.
This is to avoid cyclic dependencies since it was previously in a somewhat high-level framework, so everything that framework depended on, could not augment crash reports.