diff --git a/lib/Event.rakumod b/lib/Event.rakumod index c1d47df..38fa4cb 100644 --- a/lib/Event.rakumod +++ b/lib/Event.rakumod @@ -1,26 +1,49 @@ use QueryStorage; unit class Event is Any; +my QueryStorage $storage .= new; + has Event $.parent; -has UInt $.pos = 0; -has Str $.rule; -has $.event; -has QueryStorage $.storage .= new; +has Str $.rule = 'TOP'; +has @.pos; +has UInt $.index = 0; +has $.hash-event; +has QueryStorage $.storage = $storage; has $.actions; has $.made; +has Capture $.args; + +sub run(\match ( :$rule, :$args, | )) { + match."$rule"(|$args.Capture) +} -method parse(Supply $supply, Str :$rule = "TOP") { - my $parent = self.^run: $rule; +method parse(Supply $supply, Str :$rule = "TOP", |args) { + my $match := run self.new: :$rule, :args(args); + say $match; supply { whenever $supply -> $event { - say $parent; - $parent.^step: $event + for $storage.search: $event -> \match { + say match; + run match; + } } } } -method event(*%pars) { - my multi run(0) { +method clone(*%p) { + my sub to-map(\match --> Map()) { + match.^attributes.map(-> $a { + $a.name.substr(2) => .<> with $a.get_value(match) + }) + } + + $.new: |to-map(self), |%p +} + +use Pattern; +my $pattern = Pattern.bless: :name; +$pattern.add-step: my method (*%pars) { + say 'step: 1'; my %query is Map = %pars.kv.map: -> $key, $value { do if $value !~~ Associative { $key => %("==" => $value) @@ -28,14 +51,14 @@ method event(*%pars) { $key => $value } } - note "\$!storage.add: %query<>, {self.gist}"; - $!storage.add: %query, self - } - my multi run($) { - note "run: {self.gist}"; - $.^return - } + HandledReturn::AddToStorage.new: :match(self), :$!storage, :%query +} - run $.pos; - self +$pattern.add-step: my method (*%pars) { + say 'step: 2'; + note "RUNNING: {self.gist}" } +::?CLASS.^add_method: 'event', $pattern; +say $pattern; + + diff --git a/lib/MetamodelX/Event.rakumod b/lib/MetamodelX/Event.rakumod index 3a779aa..4e1513a 100644 --- a/lib/MetamodelX/Event.rakumod +++ b/lib/MetamodelX/Event.rakumod @@ -6,47 +6,3 @@ method new_type(|c) { $type.^add_parent: Event; $type } - -method to-map(\match --> Map()) { - match.^attributes.map(-> $a { - $a.name.substr(2) => .<> with $a.get_value(match) - }) -} - -method clone(\match, *%p) { - match.new: |match.^to-map, |%p -} - -method step(\match, $event) { - my @nexts = match.storage.search: $event; - for @nexts -> $match { - $match.^run-next: $event - } -} - -method return(\match) { - my $rule = match.rule; - ."$rule"(match) with match.actions; - note "emit: {match.gist}"; - return emit match unless match.parent; - # Should it emit match.made if it exist? - match.parent.run-next: :parent(match) -} - -multi method store-submatch(\match, Str $rule) { - match.run-next(:hash(%(|match.hash, $rule => match.parent))) -} - -multi method store-submatch(\match) { - match.run-next(:list((|match.list, match.parent))) -} - -method run(\match, Str $rule, UInt $pos = 0, |c) { - match.new(:$rule, :$pos, :parent(match))."$rule"(|c) -} - -method run-next(\match, $event?, *%pars, |c) { - note "run-next: {match.gist}, $event"; - my $rule = match.rule; - match.clone(|(:$event with $event), :pos(match.pos + 1), |%pars)."$rule"(|c) # TODO: validate if pos exist -} diff --git a/lib/Pattern.rakumod b/lib/Pattern.rakumod index 4039af2..d73a2b4 100644 --- a/lib/Pattern.rakumod +++ b/lib/Pattern.rakumod @@ -1,44 +1,120 @@ -my class Step { - has Numeric $.min = 1; - has Numeric $.max = 1; - has Callable @.steps; +class HandledReturn {} +class HandledReturn::Next is HandledReturn {} +class HandledReturn::End is HandledReturn {} +class HandledReturn::AddToStorage { + has $.storage is required; + has %.query is required; + has $.match is required; +} + +my role Nextable { + method elems {...} + method choose-callable(UInt $i) {...} + method run(\match ( :@pos, UInt :$index, | )) { + return $.run: match.clone(:pos(|@pos, 0)) unless $index + 1 <= @pos; + my $current = @pos[$index]; + dd @pos; + dd $current; + return HandledReturn::End unless $current + 1 <= $.elems; + my &callable = self.choose-callable: $current; + self.handle-return: match, callable match, |match.args.Capture + } + multi method handle-return(\match ( :@pos, UInt :$index, | ), HandledReturn::Next) { + my $max = $.elems - 1; + my $current = @pos[$index]; + return HandledReturn::Next unless $current <= $max; + self.run: match.clone: :pos(@pos.&{ |.head($current), .[$current] + 1, |.tail: * - $current - 1 }) + } + multi method handle-return(\match, HandledReturn::End) { + say "END: {match.gist}"; + } + multi method handle-return(\match, HandledReturn::AddToStorage ( :$match ( :$index, :@pos, | ), :$storage, :%query, | )) { + note "\$storage.add: %query<>, {$match.gist}"; + $storage.add: %query, $match.clone: :pos(|$.next-pos: match) + } + multi method handle-return(@returns) { + $.handle-return: $_ for @returns + } + multi method handle-return(|) { } + method next-pos(\match ( :$index, :@pos, | )) { + my $current = @pos[$index]; + Array[UInt].new: do if $current + 1 >= $.elems { + @pos.head($index - 1), @pos[$index - 1] + 1 + } else { + |@pos.head($index), $current + 1, |@pos.tail: * - $index - 1 + } + } +} + +my class Step does Nextable is Method { + method name {'step'} + has Callable @.steps handles ; + + method choose-callable(UInt $i) { + @!steps[$i] + } multi method add-step(&callable) { @!steps.push: &callable; self } - multi method add-step(@callables, :$max = 1, :$min = 1) { - my Step $step .= new: :$min, :$max; + multi method add-step(@callables) { + my Step $step .= new; $step.add-step: $_ for @callables; self } + + method CALL-ME(\match ( :@pos, UInt :$index, | ), |) { + say 'here!!!'; + $.run: match + } } -my class Or { - has Callable @.options; +my class Repeat is Method { + method name {'repeat'} + has Numeric $.min = 1; + has Numeric $.max = 1; + + method elems { $!max } - multi method add-option(&opt) { - @!options.push: &opt + method CALL-ME(\match ( :@pos, UInt :$index, | ), |) { + $.run: match } +} - multi method add-option(@opts) { - @!options.push: $_ for @opts +my class Or is Method { + method name {'or'} + has Step @.options; + + multi method add-option($opt) { + my $step = Step.bless; + $step.add-step: $_ for |$opt; + @!options.push: $step; + self } - method CALL-ME(\match, |c) { + multi method add-option(Step $opt) { + @!options.push: $opt; + self + } + + method CALL-ME(\match, |) { # FIXME: what happens if there is no rule as first step? for @!options { - .(match, |c) + .(match, |match.args.Capture) # last if match } } } class Pattern is Method { + has Str $.name; has Str $.source; - has Step $.steps handles .= new; + has Step $.steps handles .= bless; method CALL-ME(\match, |c) { - $!steps(match, |c) + my $m = match.clone: :args(c), :rule($.name); + say $m; + $!steps($m) } } diff --git a/lib/QueryStorage/Branch.rakumod b/lib/QueryStorage/Branch.rakumod index e62a3a1..e8dbc09 100644 --- a/lib/QueryStorage/Branch.rakumod +++ b/lib/QueryStorage/Branch.rakumod @@ -9,15 +9,12 @@ has %!map = |@!types.map: { .op => $_ } method map($op) { %!map{$op}.new } -proto method add(|c) {note c; {*}} multi method add(::?CLASS:U: Pair $test, $value) { - note 1; my ::?CLASS $obj .= new; $obj.add: $test, $value; $obj } multi method add(::?CLASS:D: (:$key, :$value), $value2) { - note 2; (%!lists{$key} //= self.map: $key) .= add: $value, $value2; self }