Skip to content

Commit

Permalink
feat(rewrite): rewrite it. Make it interal to the language
Browse files Browse the repository at this point in the history
  • Loading branch information
Fernando Corrêa de Oliveira committed Aug 28, 2024
1 parent cdc7a24 commit 835dcf2
Show file tree
Hide file tree
Showing 15 changed files with 559 additions and 87 deletions.
14 changes: 0 additions & 14 deletions examples/fire-risk

This file was deleted.

28 changes: 28 additions & 0 deletions examples/fire-risk.rakumod
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
use lib "lib";
use EEL;

event fire-risk {
has Rat $.temperature = $<temp><value>;
has Rat $.humidity = $<hum><value>;
has Str $.area = $<temp><area> // $<hum><area>;

pattern TOP {
[
| <temp> <hum>
| <hum> <temp>
] 5min
<{ $<temp><area> eq $<hum><area> }>
}

pattern temp {
<temperature=event(:type<temperature>)>
<{ $<temperature><value> > 40 }>
{ $!area = $<temperature><area> }
}

pattern hum {
<humidity=event(:type<humidity>)>
<{ $<humidity><value> < 20 }>
{ $!area = $<humidity><area> }
}
}
File renamed without changes.
43 changes: 43 additions & 0 deletions fire-risk-all.rakumod
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
use lib "lib";

role Event is Capture {
has Pair @.pos;
method match(Supply $supply, Str :$rule = "TOP") {
supply {
whenever $supply -> $ev {
self!step($ev, :$rule)
}
}
}

method !step($ev, Str :$rule) {
my @*pos = @!pos;
}
}

class fire-risk does Event {
has Rat $.temperature = $<temp><value>;
has Rat $.humidity = $<hum><value>;
has Str $.area = $<temp><area> // $<hum><area>;

pattern TOP {
[
| <temp> <hum>
| <hum> <temp>
] 5min
<{ $<temp><area> eq $<hum><area> }>
}

pattern temp {
<temperature=event(:type<temperature>)>
<{ $<temperature><value> > 40 }>
{ $!area = $<temperature><area> }
}

pattern hum {
<humidity=event(:type<humidity>)>
<{ $<humidity><value> < 20 }>
{ $!area = $<humidity><area> }
}
}

56 changes: 32 additions & 24 deletions lib/EEL.rakumod
Original file line number Diff line number Diff line change
@@ -1,27 +1,35 @@
use EELParser;
use EventTranslator;
use Event::Runner;
use Event::AST;
unit class EEL;
# use EELParser;
# use EventTranslator;
# use Event::Runner;
# use Event::AST;
# unit class EEL;
#
# has Supply $.input;
# has EELParser $.parser .= new;
# has EventTranslator $.trans;
# has Str $.file;
# has Str $.code;
# has Event::AST:D @.ast = $!file.defined
# ?? $!parser.parse-file: $!file
# !! $!parser.parse: $!code
# ;
# has @.rules = EventTranslator.new.translate: @!ast;
# has Event::Runner $.runner .= new: :$!input, :@!rules;
# has Supply:D $.output handles * = $!runner.run;
#
# proto eel ($, :$code, :$file) is export {*}
# multi eel(@inputs, |c) { nextwith Supply.merge(@inputs), |c }
# multi eel(Supply:D $input, :$code! --> EEL) {
# EEL.new: :$input, :$code
# }
# multi eel(Supply:D $input, :$file! --> EEL) {
# EEL.new: :$input, :$file
# }

has Supply $.input;
has EELParser $.parser .= new;
has EventTranslator $.trans;
has Str $.file;
has Str $.code;
has Event::AST:D @.ast = $!file.defined
?? $!parser.parse-file: $!file
!! $!parser.parse: $!code
;
has @.rules = EventTranslator.new.translate: @!ast;
has Event::Runner $.runner .= new: :$!input, :@!rules;
has Supply:D $.output handles * = $!runner.run;
use MetamodelX::Event;

proto eel ($, :$code, :$file) is export {*}
multi eel(@inputs, |c) { nextwith Supply.merge(@inputs), |c }
multi eel(Supply:D $input, :$code! --> EEL) {
EEL.new: :$input, :$code
my package EXPORTHOW {
package DECLARE {
constant event = MetamodelX::Event;
}
}
multi eel(Supply:D $input, :$file! --> EEL) {
EEL.new: :$input, :$file
}
41 changes: 41 additions & 0 deletions lib/Event.rakumod
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
use QueryStorage;
unit class Event is Any;

has Event $.parent;
has UInt $.pos = 0;
has Str $.rule;
has $.event;
has QueryStorage $.storage .= new;
has $.actions;
has $.made;

method parse(Supply $supply, Str :$rule = "TOP") {
my $parent = self.^run: $rule;
supply {
whenever $supply -> $event {
say $parent;
$parent.^step: $event
}
}
}

method event(*%pars) {
my multi run(0) {
my %query is Map = %pars.kv.map: -> $key, $value {
do if $value !~~ Associative {
$key => %("==" => $value)
} else {
$key => $value
}
}
note "\$!storage.add: %query<>, {self.gist}";
$!storage.add: %query, self
}
my multi run($) {
note "run: {self.gist}";
$.^return
}

run $.pos;
self
}
52 changes: 52 additions & 0 deletions lib/MetamodelX/Event.rakumod
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
use Event;
unit class MetamodelX::Event is Metamodel::ClassHOW;

method new_type(|c) {
my $type = callsame;
$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
}
5 changes: 3 additions & 2 deletions lib/QueryStorage.rakumod
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ multi method add(%tests, \value) {
# TODO: Fix, do not override.
for %tests.pairs.sort.kv -> UInt $i, (:$key, :value($test)) {
$value = $i + 1 == %tests ?? value !! ::?CLASS.new;
%branches{$key} .= add: $test, $value;
note "($key).add: $test.gist(), $value";
%branches{$key} .= add: $test<>, $value;
%branches := $value.branches if $value ~~ ::?CLASS
}
self
Expand All @@ -27,4 +28,4 @@ method search(%obj) {
}
}
}
}
}
13 changes: 8 additions & 5 deletions lib/QueryStorage/Branch.rakumod
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,20 @@ has %!map = |@!types.map: { .op => $_ }

method map($op) { %!map{$op}.new }

multi method add(::?CLASS:U: |c) {
proto method add(|c) {note c; {*}}
multi method add(::?CLASS:U: Pair $test, $value) {
note 1;
my ::?CLASS $obj .= new;
$obj.add: |c;
$obj.add: $test, $value;
$obj
}
multi method add(::?CLASS:D: (:$key, :$value), \value) {
(%!lists{$key} //= self.map: $key) .= add: $value, value;
multi method add(::?CLASS:D: (:$key, :$value), $value2) {
note 2;
(%!lists{$key} //= self.map: $key) .= add: $value, $value2;
self
}
method search(|c) {
gather for %!lists.values {
.take for .search: |c
}
}
}
26 changes: 9 additions & 17 deletions mindstorm/FireRisk.rakumod
Original file line number Diff line number Diff line change
@@ -1,30 +1,22 @@
########################
# Emits a FireRisk event if its too hot and too dry on a given area
########################

event Temperature is generic-hash-event { has Int $.area; has Rat $.value }
event Humidity is generic-hash-event { has Int $.area; has Rat $.value }
use lib 'lib';
use EEL;

event FireRisk {
has Int $.area;
has Rat $.temparature;
has Rat $.humidity;

pattern TOP {
[
[ <hot> & <dry> ]
<?{ $<hot>.area == $<dry>.area }>
{ $!area = $<hot>.area }
] in 5min
{ $!temperature = $<hot>.value }
{ $!humidity = $<dry>.value }
| <hot> <dry($<hot><event><area>)>
| <dry> <hot($<dry><event><area>)>
] 5min
}

pattern hot {
<Temperature> <?{ $<Temperature>.value > 40 }>
pattern hot($area) {
<event(|(:$area with $area), :type<temperature>, :value{'>' => 40 })>
}

pattern dry {
<Humidity> <?{ $<Humidity>.value < 20 }>
pattern dry($area) {
<event(|(:$area with $area), :type<humidity>, :value{'<' => 20 })>
}
}
38 changes: 13 additions & 25 deletions mindstorm/Login.rakumod
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,6 @@
# Emits a Login event after getting the login page, 0, 1 or more login tries and a succefull login
########################

event Request is generic-log-entry(&line-to-hash) {
has Str $.method;
has UInt $.status;
has Str $.path;
has %.data;
has DateTime $.timestamp;
has Str() %.headers
}

event Login {
has UUID() $.session-id;
has UInt $.tries;
Expand All @@ -22,34 +13,31 @@ event Login {
:my $form-id = $<login-form>.data<form-id>;
<failures=.login-action-fail($form-id)>*
<success=.login-action-success($form-id)>
{ $!session-id = $<success>.headers<session-id> }
{ $!tries = $<failures>.elems + 1 }
{ $!start = $<get>.timestamp }
{ $!end = $<success>.timestamp }

{ $!session-id = $<success><headers><session-id> }
{ $!tries = $<failures>.elems + 1 }
{ $!start = $<get><timestamp> }
{ $!end = $<success><timestamp> }
}

pattern login-page {
<req=.Request> <?{ $<req>.path eq "/login" }>
pattern login-page(*%pars) {
<req=.event(:path</login>, |%pars)>
}

pattern login-form {
<page=.login-page>
<?{ $<page>.method eq "GET" && $<page>.status == 200 }>
<page=.login-page(:method<GET>, :200status)>
}

pattern login-action(UUID() $form-id) {
<page=.login-page>
<?{ $<page>.method eq "POST" && $<page>.data<form-id> eq $form-id }>
pattern login-action(UUID() $form-id, *%pars) {
<page=.login-page(:method<POST>, "data.form-id" => $form-id, |%pars)>
}

pattern login-action-fail(UUID() $form-id) {
<action=.login-action($form-id)>
<?{ $<action>.status div 100 != 2 }>
pattern login-action-fail(UUID() $form-id) {
<action=.login-action($form-id, :status['<' => 200, '>=' => 300])>
}

pattern login-action-success(UUID() $form-id) {
<action=.login-action($form-id)>
<?{ $<action>.status div 100 == 2 }>
<action=.login-action($form-id, :status{'>=' => 200, '<' => 300})>
}
}

Loading

0 comments on commit 835dcf2

Please sign in to comment.