From 5e11ebce9bc0a5b4b15ce9aecbed342d8ca3cd90 2020-02-10 11:57:19 From: Hans-Dieter Hiep Date: 2020-02-10 11:57:19 Subject: [PATCH] Evaluator new_component and new_channel implemented --- diff --git a/src/protocol/ast.rs b/src/protocol/ast.rs index 17a9f472f295125a32ff768347ad64352b79e20b..906334e8f99762e6dc18d200efae566354c12177 100644 --- a/src/protocol/ast.rs +++ b/src/protocol/ast.rs @@ -1353,7 +1353,7 @@ pub struct SourceIdentifier { } impl SourceIdentifier { - fn ident(&self) -> &[u8] { + pub fn ident(&self) -> &[u8] { &self.value } } @@ -1827,6 +1827,12 @@ impl Declaration { pub fn is_function(&self) -> bool { self.signature().is_function() } + pub fn as_defined(&self) -> &DefinedDeclaration { + match self { + Declaration::Defined(result) => result, + _ => panic!("Unable to cast `Declaration` to `DefinedDeclaration`"), + } + } } #[derive(Debug, Clone)] @@ -2178,6 +2184,7 @@ impl BlockStatement { } } pub fn first(&self) -> StatementId { + // It is an invariant (guaranteed by the lexer) that block statements have at least one stmt *self.statements.first().unwrap() } } diff --git a/src/protocol/eval.rs b/src/protocol/eval.rs index 37c4580088d9d32a2d128f9e417d4dfe8ee2435b..90d817ea32288299d69b9bf1e62cc90aab7a010d 100644 --- a/src/protocol/eval.rs +++ b/src/protocol/eval.rs @@ -1375,7 +1375,7 @@ impl Store { match &h[rexpr] { Expression::Variable(var) => { let var = var.declaration.unwrap(); - let value = self.map.get(&var).unwrap(); + let value = self.map.get(&var).expect(&format!("Uninitialized variable {:?}", h[h[var].identifier()])); Ok(value.clone()) } _ => unimplemented!("{:?}", h[rexpr]), @@ -1485,7 +1485,7 @@ pub enum EvalContinuation { Terminal, SyncBlockStart, SyncBlockEnd, - NewComponent(Vec), + NewComponent(DeclarationId, Vec), BlockFires(Value), BlockGet(Value), Put(Value, Value), @@ -1533,7 +1533,12 @@ impl Prompt { // Update store self.store.initialize(h, stmt.variable.upcast(), value); } - LocalStatement::Channel(stmt) => unimplemented!(), + LocalStatement::Channel(stmt) => { + let [from, to] = ctx.new_channel(); + // Store the values in the declared variables + self.store.initialize(h, stmt.from.upcast(), from); + self.store.initialize(h, stmt.to.upcast(), to); + }, } // Continue to next statement self.position = stmt.next(); @@ -1591,6 +1596,28 @@ impl Prompt { self.position = stmt.next; Err(EvalContinuation::SyncBlockEnd) } + Statement::Break(stmt) => { + // Continue to end of while + self.position = stmt.target.map(EndWhileStatementId::upcast); + Err(EvalContinuation::Stepping) + } + Statement::Continue(stmt) => { + // Continue to beginning of while + self.position = stmt.target.map(WhileStatementId::upcast); + Err(EvalContinuation::Stepping) + } + Statement::Assert(stmt) => { + // Evaluate expression + let value = self.store.eval(h, ctx, stmt.expression)?; + if value.as_boolean().0 { + // Continue to next statement + self.position = stmt.next; + Err(EvalContinuation::Stepping) + } else { + // Assertion failed: inconsistent + Err(EvalContinuation::Inconsistent) + } + } Statement::Return(stmt) => { // Evaluate expression let value = self.store.eval(h, ctx, stmt.expression)?; @@ -1602,7 +1629,16 @@ impl Prompt { self.position = stmt.target.map(|x| x.upcast()); Err(EvalContinuation::Stepping) } - Statement::New(stmt) => todo!(), + Statement::New(stmt) => { + let expr = &h[stmt.expression]; + let mut args = Vec::new(); + for &arg in expr.arguments.iter() { + let value = self.store.eval(h, ctx, arg)?; + args.push(value); + } + self.position = stmt.next; + Err(EvalContinuation::NewComponent(expr.declaration.unwrap(), args)) + } Statement::Put(stmt) => { // Evaluate port and message let port = self.store.eval(h, ctx, stmt.port)?; @@ -1619,7 +1655,6 @@ impl Prompt { self.position = stmt.next; Err(EvalContinuation::Stepping) } - _ => unimplemented!("{:?}", stmt), } } else { Err(EvalContinuation::Terminal) @@ -1640,7 +1675,7 @@ impl Prompt { // Functions never encounter any blocking behavior EvalContinuation::SyncBlockStart => unreachable!(), EvalContinuation::SyncBlockEnd => unreachable!(), - EvalContinuation::NewComponent(args) => unreachable!(), + EvalContinuation::NewComponent(_, _) => unreachable!(), EvalContinuation::BlockFires(val) => unreachable!(), EvalContinuation::BlockGet(val) => unreachable!(), EvalContinuation::Put(port, msg) => unreachable!(), @@ -1669,8 +1704,7 @@ mod tests { let mut source = InputSource::from_file(&path).unwrap(); let mut parser = Parser::new(&mut source); let pd = parser.parse(&mut heap).unwrap(); - let test = heap.get_external_identifier(b"test"); - let def = heap[pd].get_definition(&heap, test.upcast()).unwrap(); + let def = heap[pd].get_definition_ident(&heap, b"test").unwrap(); let fun = heap[def].as_function().this; let args = Vec::new(); let result = Prompt::compute_function(&heap, fun, &args).unwrap(); diff --git a/src/protocol/mod.rs b/src/protocol/mod.rs index 5c353dc8115255e9773d0103f60bca8fa76adc94..25731b736c26558cbd8c6e3c780fa77eb0999aab 100644 --- a/src/protocol/mod.rs +++ b/src/protocol/mod.rs @@ -121,8 +121,14 @@ impl ComponentState for ComponentStateImpl { EvalContinuation::SyncBlockStart => return MonoBlocker::SyncBlockStart, // Not possible to end sync block if never entered one EvalContinuation::SyncBlockEnd => unreachable!(), - EvalContinuation::NewComponent(args) => { - todo!(); + EvalContinuation::NewComponent(decl, args) => { + // Look up definition (TODO for now, assume it is a definition) + let h = &pd.heap; + let def = h[decl].as_defined().definition; + println!("Create component: {}", String::from_utf8_lossy(h[h[def].identifier()].ident())); + let init_state = ComponentStateImpl { prompt: Prompt::new(h, def, &args) }; + context.new_component(&args, init_state); + // Continue stepping continue; } // Outside synchronous blocks, no fires/get/put happens @@ -154,7 +160,7 @@ impl ComponentState for ComponentStateImpl { EvalContinuation::SyncBlockStart => unreachable!(), EvalContinuation::SyncBlockEnd => return PolyBlocker::SyncBlockEnd, // Not possible to create component in sync block - EvalContinuation::NewComponent(args) => unreachable!(), + EvalContinuation::NewComponent(_, _) => unreachable!(), EvalContinuation::BlockFires(port) => match port { Value::Output(OutputValue(key)) => { return PolyBlocker::CouldntCheckFiring(key); @@ -214,20 +220,42 @@ impl EvalContext<'_> { match self { EvalContext::None => unreachable!(), EvalContext::Mono(context) => todo!(), - EvalContext::Poly(context) => unreachable!(), + EvalContext::Poly(_) => unreachable!(), } } - fn channel(&mut self) -> (Value, Value) { + fn new_component(&mut self, args: &[Value], init_state: ComponentStateImpl) -> () { match self { EvalContext::None => unreachable!(), - EvalContext::Mono(context) => unreachable!(), - EvalContext::Poly(context) => todo!(), + EvalContext::Mono(context) => { + let mut moved_keys = HashSet::new(); + for arg in args.iter() { + match arg { + Value::Output(OutputValue(key)) => { moved_keys.insert(*key); } + Value::Input(InputValue(key)) => { moved_keys.insert(*key); } + _ => {} + } + } + context.new_component(moved_keys, init_state) + } + EvalContext::Poly(_) => unreachable!(), + } + } + fn new_channel(&mut self) -> [Value; 2] { + match self { + EvalContext::None => unreachable!(), + EvalContext::Mono(context) => { + let [from, to] = context.new_channel(); + let from = Value::Output(OutputValue(from)); + let to = Value::Input(InputValue(to)); + return [from, to]; + } + EvalContext::Poly(_) => unreachable!() } } fn fires(&mut self, port: Value) -> Option { match self { EvalContext::None => unreachable!(), - EvalContext::Mono(context) => unreachable!(), + EvalContext::Mono(_) => unreachable!(), EvalContext::Poly(context) => match port { Value::Output(OutputValue(key)) => context.is_firing(key).map(Value::from), Value::Input(InputValue(key)) => context.is_firing(key).map(Value::from), @@ -238,7 +266,7 @@ impl EvalContext<'_> { fn get(&mut self, port: Value) -> Option { match self { EvalContext::None => unreachable!(), - EvalContext::Mono(context) => unreachable!(), + EvalContext::Mono(_) => unreachable!(), EvalContext::Poly(context) => match port { Value::Output(OutputValue(key)) => { context.read_msg(key).map(Value::receive_message) diff --git a/src/protocol/parser.rs b/src/protocol/parser.rs index bd82d1282afe155610322f311a1f2afa6117fe39..2c97a2a535221cf518513b99c5a093007f325879 100644 --- a/src/protocol/parser.rs +++ b/src/protocol/parser.rs @@ -1082,7 +1082,7 @@ impl LinkStatements { impl Visitor for LinkStatements { fn visit_statement(&mut self, h: &mut Heap, stmt: StatementId) -> VisitorResult { - if let Some(UniqueStatementId(prev)) = std::mem::replace(&mut self.prev, None) { + if let Some(UniqueStatementId(prev)) = self.prev.take() { h[prev].link_next(stmt); } recursive_statement(self, h, stmt) @@ -1105,12 +1105,12 @@ impl Visitor for LinkStatements { h.alloc_end_if_statement(|this| EndIfStatement { this, position, next: None }).upcast(); assert!(self.prev.is_none()); self.visit_statement(h, h[stmt].true_body)?; - if let Some(UniqueStatementId(prev)) = std::mem::replace(&mut self.prev, None) { + if let Some(UniqueStatementId(prev)) = self.prev.take() { h[prev].link_next(pseudo); } assert!(self.prev.is_none()); self.visit_statement(h, h[stmt].false_body)?; - if let Some(UniqueStatementId(prev)) = std::mem::replace(&mut self.prev, None) { + if let Some(UniqueStatementId(prev)) = self.prev.take() { h[prev].link_next(pseudo); } // Use the pseudo-statement as the statement where to update the next pointer diff --git a/src/test/connector.rs b/src/test/connector.rs index 123cd63fe11c3a084e536830b0cadcb3220afacc..13561940914addbd2a98629c6d18215a69e8b545 100644 --- a/src/test/connector.rs +++ b/src/test/connector.rs @@ -524,10 +524,21 @@ fn composite_chain() { /* Alice -->sync-->sync-->A|P-->sync-->sync--> Bob */ + static PDL : &[u8] = +b"primitive sync(in i, out o) { + while(true) synchronous { + if (fires(i)) put(o, get(i)); + } +} +composite sync_2(in i, out o) { + channel x -> y; + new sync(i, x); + new sync(y, o); +}"; let timeout = Duration::from_millis(1_500); let addrs = [next_addr(), next_addr()]; const N: usize = 1; - static MSG: &[u8] = b"Hippity Hoppity"; + static MSG: &[u8] = b"SSS"; assert!(run_connector_set(&[ // &|x| { @@ -543,7 +554,7 @@ fn composite_chain() { }, &|x| { // Bob - x.configure(PDL, b"sync_2").unwrap(); + x.configure(PDL, b"sync").unwrap(); x.bind_port(0, Passive(addrs[0])).unwrap(); x.bind_port(1, Native).unwrap(); x.connect(timeout).unwrap();