syntax to match rule only once per update / permanently. or even make matching once per update the default.
- option to scope permanence by a variable
- #stage: { input 3= output } evaluates max 3 times within stage, becomes: #stage: { // must be structured to keep behavior of random rule selection !tmp-counter-123 _ . input = output . tmp-counter-123 2 tmp-counter-123 N . > N 0 . - N 1 N’ . input = output . tmp-counter-123 N’ () = #tmp-cleanup } #tmp-cleanup: { tmp-counter-123 _ = () }
- could also allow integer variables to be used instead of constant e.g. #stage: { $count N . input N= output }
make $ remove instead of preserve, since remove is less common and this makes the stage behavior (#asdf:) consistent with other syntax
ability to put rule output in ‘stage’ scopes e.g. in1 . in2 = out1 { subset = () } === in1 . in2 . subset = out1
test doing initial matching through ecs instead of first atoms (e.g. https://github.com/TomGillen/legion)
- requires a macro to generate rust structs for throne identifiers
- an item of state is then e.g. &[FooAtom::N1, Var::N2, BarAtom::N3, etc..]
- possible matching rules are found using a component query
support marking state phrases immutable in debug builds, logging warning when the state is consumed by a rule. or do compile-time check.
support matching phrases while binding to them, to avoid retyping them in output e.g. (foo A)@FOO . bar = FOO
- could we compile each rule down to a specialized routine with a stack for variable matches to replace test_inputs_with_permutation
- bin each phrase by (atom, atom position) and variable name to speed up matching
add syntax for matching on const lists i.e. (FOO | BAR) matched against (a b c): FOO = a, BAR = (b c)
- e.g. foo FOO = `foo capitalized is` (^capitalize FOO <OUT) instead of foo FOO . ^capitalize FOO OUT = `foo capitalized is` OUT where OUT can also be a wildcard (or omitted?)
- This is currently difficult since the number of times that a rule may be evaluated in an update is not well defined
- e.g. `find_phrases<const N: usize>(pattern: [Option<&Atom>; N], match_pattern_length: bool) -> Vec<&[Token]> { … }`
- replace find_phrase* variants too
measure performance with https://github.com/bodil/smartstring
- [X] Conway’s game of life
- [ ] Chess
- [ ] Tic tac toe
- [ ] Procedural generationn
test with https://github.com/yuulive/mo
- a X . a X = … or a X . b X = … with a (0..N) and b (0..N) triggers an O(N^2) search on each update.
- currently backwards predicates are evaluated left to right in two passes, so > 2 backwards predicates in the wrong order will fail matching e.g. + C 3 D . % B 2 C . + A 1 B = …
- backwards predicates need to be evaluated in order based on variable dependencies.
- could extend ordering based on dependencies to matching in general, including side predicates and normal state matches, to reduce permutations.
- “you might be able to save a lot of hashmap lookups if you replace a `HashMap<K, V>` with a `HashMap<K, usize>` and a `Slab<V>`. This might be very useful if K is something heavy such as a `String`”
- left up to embedder.
- defined as rule without ‘=’: <test A B . + A B C . required state C
- can be compiled by replacing instances of <test _ _ in the full rule, making the appropriate variable name substitutions
- predicate does not consume state, which needs a small change in the matching loop
performance improvement by sorting states by atom indices + jumping to known ranges during matching or do binary search
improve performance by, for each phrase in a rule, recording the states that could match the phrase. needs to be re-evaluated each time state is added or removed.
- attempted in 7d27586, worsened performance.