Message handling

This commit is contained in:
Tony Garnock-Jones 2021-10-07 22:03:29 +02:00
parent fb744082b9
commit e101258473
1 changed files with 46 additions and 20 deletions

View File

@ -54,7 +54,12 @@ pub enum Instruction {
target: String, target: String,
template: AnyValue, template: AnyValue,
}, },
React { During {
target: String,
pattern_template: AnyValue,
body: Box<Instruction>,
},
OnMessage {
target: String, target: String,
pattern_template: AnyValue, pattern_template: AnyValue,
body: Box<Instruction>, body: Box<Instruction>,
@ -375,6 +380,21 @@ impl Env {
} }
} }
fn bind_and_run(
&self,
t: &mut Activation,
binding_names: &Vec<String>,
captures: AnyValue,
body: &Instruction,
) -> ActorResult {
if let Some(captures) = captures.value_owned().into_sequence() {
let mut env = self.clone();
env.extend(binding_names, captures);
env.safe_eval(t, body);
}
Ok(())
}
pub fn eval(&mut self, t: &mut Activation, i: &Instruction) -> io::Result<()> { pub fn eval(&mut self, t: &mut Activation, i: &Instruction) -> io::Result<()> {
match i { match i {
Instruction::Assert { target, template } => { Instruction::Assert { target, template } => {
@ -383,18 +403,22 @@ impl Env {
Instruction::Message { target, template } => { Instruction::Message { target, template } => {
self.lookup_target(target)?.message(t, &(), &self.instantiate_value(template)?); self.lookup_target(target)?.message(t, &(), &self.instantiate_value(template)?);
} }
Instruction::React { target, pattern_template, body } => { Instruction::During { target, pattern_template, body } => {
let (binding_names, pattern) = self.instantiate_pattern(pattern_template)?; let (binding_names, pattern) = self.instantiate_pattern(pattern_template)?;
let observer = during::entity(self.clone()) let observer = during::entity(self.clone())
.on_asserted_facet(enclose!( .on_asserted_facet(enclose!((binding_names, body) move |env, t, cs: AnyValue| {
(binding_names, body) move |env, t, captures: AnyValue| { env.bind_and_run(t, &binding_names, cs, &*body) }))
if let Some(captures) = captures.value_owned().into_sequence() { .create_cap(t);
let mut env = env.clone(); self.lookup_target(target)?.assert(t, language(), &dataspace::Observe {
env.extend(&binding_names, captures); pattern,
env.safe_eval(t, &*body); observer,
});
} }
Ok(()) Instruction::OnMessage { target, pattern_template, body } => {
})) let (binding_names, pattern) = self.instantiate_pattern(pattern_template)?;
let observer = during::entity(self.clone())
.on_message(enclose!((binding_names, body) move |env, t, cs: AnyValue| {
env.bind_and_run(t, &binding_names, cs, &*body) }))
.create_cap(t); .create_cap(t);
self.lookup_target(target)?.assert(t, language(), &dataspace::Observe { self.lookup_target(target)?.assert(t, language(), &dataspace::Observe {
pattern, pattern,
@ -653,10 +677,14 @@ impl<'t> Parser<'t> {
Symbolic::Binder(s) => { Symbolic::Binder(s) => {
self.drop(); self.drop();
if s.len() > 0 { let ctor = match s.as_ref() {
return self.error(format!( "" => |target, pattern_template, body| {
"Invalid use of pattern binder in target: ?{}", s)); Instruction::During { target, pattern_template, body } },
} "?" => |target, pattern_template, body| {
Instruction::OnMessage { target, pattern_template, body } },
_ => return self.error(format!(
"Invalid use of pattern binder in target: ?{}", s)),
};
if self.ateof() { if self.ateof() {
return self.error("Missing pattern and instruction in react"); return self.error("Missing pattern and instruction in react");
@ -671,11 +699,9 @@ impl<'t> Parser<'t> {
Parsed::Skip => Parsed::Skip =>
Parsed::Skip, Parsed::Skip,
Parsed::Value(body) => Parsed::Value(body) =>
Parsed::Value(Instruction::React { Parsed::Value(ctor(target.to_owned(),
target: target.to_owned(),
pattern_template, pattern_template,
body: Box::new(body), Box::new(body))),
}),
}; };
} }
Symbolic::Discard => { Symbolic::Discard => {