diff --git a/src/collections/mod.rs b/src/collections/mod.rs index f46f2b472b55f67be2680ae64498f01088e18d9e..243c723d50aa4a11c695146cb31f1874e164c268 100644 --- a/src/collections/mod.rs +++ b/src/collections/mod.rs @@ -5,4 +5,4 @@ mod sets; pub(crate) use string_pool::{StringPool, StringRef}; pub(crate) use scoped_buffer::{ScopedBuffer, ScopedSection}; -pub(crate) use sets::{DequeSet, VecSet}; \ No newline at end of file +pub(crate) use sets::DequeSet; \ No newline at end of file diff --git a/src/collections/sets.rs b/src/collections/sets.rs index 96f7df9fbdfeb228cc51882a6cc6d2dcf58604ce..634862349b71ee77c202954f62f467b900184ab3 100644 --- a/src/collections/sets.rs +++ b/src/collections/sets.rs @@ -1,3 +1,5 @@ +#![allow(dead_code)] // For now, come back to this when compiler has matured -- MH 27/05/21 + use std::collections::VecDeque; /// Simple double ended queue that ensures that all elements are unique. Queue diff --git a/src/protocol/arena.rs b/src/protocol/arena.rs index d85e21152016c3fc054927aa31a18220acaae87c..10c90a1186f6bcb9d75f73502bc6b69fc305cb0d 100644 --- a/src/protocol/arena.rs +++ b/src/protocol/arena.rs @@ -58,9 +58,6 @@ impl Arena { } // Compiler-internal direct retrieval - pub(crate) fn get(&self, idx: usize) -> &T { - return &self.store[idx] - } pub(crate) fn get_id(&self, idx: usize) -> Id { debug_assert!(idx < self.store.len()); return Id::new(idx as i32); diff --git a/src/protocol/ast.rs b/src/protocol/ast.rs index fb2a3c6cd3524b61af5ba30a3e9b10d9b3aa6950..43e2694f36c3442237d9133e20e31adb791933ab 100644 --- a/src/protocol/ast.rs +++ b/src/protocol/ast.rs @@ -114,7 +114,6 @@ macro_rules! define_new_ast_id { define_aliased_ast_id!(RootId, Id, index(Root, protocol_descriptions), alloc(alloc_protocol_description)); define_aliased_ast_id!(PragmaId, Id, index(Pragma, pragmas), alloc(alloc_pragma)); define_aliased_ast_id!(ImportId, Id, index(Import, imports), alloc(alloc_import)); -define_aliased_ast_id!(ParserTypeId, Id, index(ParserType, parser_types), alloc(alloc_parser_type)); define_aliased_ast_id!(VariableId, Id, index(Variable, variables), alloc(alloc_variable)); define_aliased_ast_id!(DefinitionId, Id, index(Definition, definitions)); @@ -158,7 +157,6 @@ define_new_ast_id!(CastExpressionId, ExpressionId, index(CastExpression, Express define_new_ast_id!(CallExpressionId, ExpressionId, index(CallExpression, Expression::Call, expressions), alloc(alloc_call_expression)); define_new_ast_id!(VariableExpressionId, ExpressionId, index(VariableExpression, Expression::Variable, expressions), alloc(alloc_variable_expression)); -// TODO: @cleanup - pub qualifiers can be removed once done #[derive(Debug)] pub struct Heap { // Root arena, contains the entry point for different modules. Each root @@ -167,7 +165,6 @@ pub struct Heap { // Contents of a file, these are the elements the `Root` elements refer to pragmas: Arena, pub(crate) imports: Arena, - pub(crate) parser_types: Arena, pub(crate) variables: Arena, pub(crate) definitions: Arena, pub(crate) statements: Arena, @@ -181,7 +178,6 @@ impl Heap { protocol_descriptions: Arena::new(), pragmas: Arena::new(), imports: Arena::new(), - parser_types: Arena::new(), variables: Arena::new(), definitions: Arena::new(), statements: Arena::new(), @@ -235,7 +231,6 @@ pub struct Root { } impl Root { - // TODO: @Cleanup pub fn get_definition_ident(&self, h: &Heap, id: &[u8]) -> Option { for &def in self.definitions.iter() { if h[def].identifier().value.as_bytes() == id { @@ -473,16 +468,6 @@ impl<'a> Iterator for ParserTypeIter<'a> { } } -/// Specifies whether the symbolic type points to an actual user-defined type, -/// or whether it points to a polymorphic argument within the definition (e.g. -/// a defined variable `T var` within a function `int func()` -#[derive(Debug, Clone)] -pub enum SymbolicParserTypeVariant { - Definition(DefinitionId), - // TODO: figure out if I need the DefinitionId here - PolyArg(DefinitionId, usize), // index of polyarg in the definition -} - /// ConcreteType is the representation of a type after resolving symbolic types /// and performing type inference #[derive(Debug, Clone, Copy, Eq, PartialEq)] @@ -515,88 +500,6 @@ impl Default for ConcreteType { } } -// TODO: Remove at some point -#[derive(Debug, Clone, PartialEq, Eq)] -pub enum PrimitiveType { - Unassigned, - Input, - Output, - Message, - Boolean, - Byte, - Short, - Int, - Long, -} - -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct Type { - pub primitive: PrimitiveType, - pub array: bool, -} - -#[allow(dead_code)] -impl Type { - pub const UNASSIGNED: Type = Type { primitive: PrimitiveType::Unassigned, array: false }; - - pub const INPUT: Type = Type { primitive: PrimitiveType::Input, array: false }; - pub const OUTPUT: Type = Type { primitive: PrimitiveType::Output, array: false }; - pub const MESSAGE: Type = Type { primitive: PrimitiveType::Message, array: false }; - pub const BOOLEAN: Type = Type { primitive: PrimitiveType::Boolean, array: false }; - pub const BYTE: Type = Type { primitive: PrimitiveType::Byte, array: false }; - pub const SHORT: Type = Type { primitive: PrimitiveType::Short, array: false }; - pub const INT: Type = Type { primitive: PrimitiveType::Int, array: false }; - pub const LONG: Type = Type { primitive: PrimitiveType::Long, array: false }; - - pub const INPUT_ARRAY: Type = Type { primitive: PrimitiveType::Input, array: true }; - pub const OUTPUT_ARRAY: Type = Type { primitive: PrimitiveType::Output, array: true }; - pub const MESSAGE_ARRAY: Type = Type { primitive: PrimitiveType::Message, array: true }; - pub const BOOLEAN_ARRAY: Type = Type { primitive: PrimitiveType::Boolean, array: true }; - pub const BYTE_ARRAY: Type = Type { primitive: PrimitiveType::Byte, array: true }; - pub const SHORT_ARRAY: Type = Type { primitive: PrimitiveType::Short, array: true }; - pub const INT_ARRAY: Type = Type { primitive: PrimitiveType::Int, array: true }; - pub const LONG_ARRAY: Type = Type { primitive: PrimitiveType::Long, array: true }; -} - -impl Display for Type { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - match &self.primitive { - PrimitiveType::Unassigned => { - write!(f, "unassigned")?; - } - PrimitiveType::Input => { - write!(f, "in")?; - } - PrimitiveType::Output => { - write!(f, "out")?; - } - PrimitiveType::Message => { - write!(f, "msg")?; - } - PrimitiveType::Boolean => { - write!(f, "boolean")?; - } - PrimitiveType::Byte => { - write!(f, "byte")?; - } - PrimitiveType::Short => { - write!(f, "short")?; - } - PrimitiveType::Int => { - write!(f, "int")?; - } - PrimitiveType::Long => { - write!(f, "long")?; - } - } - if self.array { - write!(f, "[]") - } else { - Ok(()) - } - } -} - #[derive(Debug, Clone, Copy)] pub enum Scope { Definition(DefinitionId), @@ -805,11 +708,11 @@ pub struct StructFieldDefinition { pub struct StructDefinition { pub this: StructDefinitionId, pub defined_in: RootId, - // Phase 1: symbol scanning + // Symbol scanning pub span: InputSpan, pub identifier: Identifier, pub poly_vars: Vec, - // Phase 2: parsing + // Parsing pub fields: Vec } @@ -983,24 +886,12 @@ pub enum Statement { } impl Statement { - pub fn is_block(&self) -> bool { - match self { - Statement::Block(_) => true, - _ => false, - } - } pub fn as_block(&self) -> &BlockStatement { match self { Statement::Block(result) => result, _ => panic!("Unable to cast `Statement` to `BlockStatement`"), } } - pub fn as_block_mut(&mut self) -> &mut BlockStatement { - match self { - Statement::Block(result) => result, - _ => panic!("Unable to cast `Statement` to `BlockStatement`"), - } - } pub fn as_local(&self) -> &LocalStatement { match self { Statement::Local(result) => result, @@ -1013,132 +904,14 @@ impl Statement { pub fn as_channel(&self) -> &ChannelStatement { self.as_local().as_channel() } - pub fn as_labeled(&self) -> &LabeledStatement { - match self { - Statement::Labeled(result) => result, - _ => panic!("Unable to cast `Statement` to `LabeledStatement`"), - } - } - pub fn as_labeled_mut(&mut self) -> &mut LabeledStatement { - match self { - Statement::Labeled(result) => result, - _ => panic!("Unable to cast `Statement` to `LabeledStatement`"), - } - } - pub fn as_if(&self) -> &IfStatement { - match self { - Statement::If(result) => result, - _ => panic!("Unable to cast `Statement` to `IfStatement`"), - } - } - pub fn as_if_mut(&mut self) -> &mut IfStatement { - match self { - Statement::If(result) => result, - _ => panic!("Unable to cast 'Statement' to 'IfStatement'"), - } - } - pub fn as_end_if(&self) -> &EndIfStatement { - match self { - Statement::EndIf(result) => result, - _ => panic!("Unable to cast `Statement` to `EndIfStatement`"), - } - } - pub fn is_while(&self) -> bool { - match self { - Statement::While(_) => true, - _ => false, - } - } - pub fn as_while(&self) -> &WhileStatement { - match self { - Statement::While(result) => result, - _ => panic!("Unable to cast `Statement` to `WhileStatement`"), - } - } - pub fn as_while_mut(&mut self) -> &mut WhileStatement { - match self { - Statement::While(result) => result, - _ => panic!("Unable to cast `Statement` to `WhileStatement`"), - } - } - pub fn as_end_while(&self) -> &EndWhileStatement { - match self { - Statement::EndWhile(result) => result, - _ => panic!("Unable to cast `Statement` to `EndWhileStatement`"), - } - } - pub fn as_break(&self) -> &BreakStatement { - match self { - Statement::Break(result) => result, - _ => panic!("Unable to cast `Statement` to `BreakStatement`"), - } - } - pub fn as_break_mut(&mut self) -> &mut BreakStatement { - match self { - Statement::Break(result) => result, - _ => panic!("Unable to cast `Statement` to `BreakStatement`"), - } - } - pub fn as_continue(&self) -> &ContinueStatement { - match self { - Statement::Continue(result) => result, - _ => panic!("Unable to cast `Statement` to `ContinueStatement`"), - } - } - pub fn as_continue_mut(&mut self) -> &mut ContinueStatement { - match self { - Statement::Continue(result) => result, - _ => panic!("Unable to cast `Statement` to `ContinueStatement`"), - } - } - pub fn as_synchronous(&self) -> &SynchronousStatement { - match self { - Statement::Synchronous(result) => result, - _ => panic!("Unable to cast `Statement` to `SynchronousStatement`"), - } - } - pub fn as_synchronous_mut(&mut self) -> &mut SynchronousStatement { - match self { - Statement::Synchronous(result) => result, - _ => panic!("Unable to cast `Statement` to `SynchronousStatement`"), - } - } - pub fn as_end_synchronous(&self) -> &EndSynchronousStatement { - match self { - Statement::EndSynchronous(result) => result, - _ => panic!("Unable to cast `Statement` to `EndSynchronousStatement`"), - } - } - pub fn as_return(&self) -> &ReturnStatement { - match self { - Statement::Return(result) => result, - _ => panic!("Unable to cast `Statement` to `ReturnStatement`"), - } - } - pub fn as_goto(&self) -> &GotoStatement { - match self { - Statement::Goto(result) => result, - _ => panic!("Unable to cast `Statement` to `GotoStatement`"), - } - } - pub fn as_goto_mut(&mut self) -> &mut GotoStatement { - match self { - Statement::Goto(result) => result, - _ => panic!("Unable to cast `Statement` to `GotoStatement`"), - } - } + pub fn as_new(&self) -> &NewStatement { match self { Statement::New(result) => result, _ => panic!("Unable to cast `Statement` to `NewStatement`"), } } - pub fn as_expression(&self) -> &ExpressionStatement { - match self { - Statement::Expression(result) => result, - _ => panic!("Unable to cast `Statement` to `ExpressionStatement`"), - } - } + pub fn span(&self) -> InputSpan { match self { Statement::Block(v) => v.span, @@ -1435,72 +1208,13 @@ pub enum Expression { } impl Expression { - pub fn as_assignment(&self) -> &AssignmentExpression { - match self { - Expression::Assignment(result) => result, - _ => panic!("Unable to cast `Expression` to `AssignmentExpression`"), - } - } - pub fn as_conditional(&self) -> &ConditionalExpression { - match self { - Expression::Conditional(result) => result, - _ => panic!("Unable to cast `Expression` to `ConditionalExpression`"), - } - } - pub fn as_binary(&self) -> &BinaryExpression { - match self { - Expression::Binary(result) => result, - _ => panic!("Unable to cast `Expression` to `BinaryExpression`"), - } - } - pub fn as_unary(&self) -> &UnaryExpression { - match self { - Expression::Unary(result) => result, - _ => panic!("Unable to cast `Expression` to `UnaryExpression`"), - } - } - pub fn as_indexing(&self) -> &IndexingExpression { - match self { - Expression::Indexing(result) => result, - _ => panic!("Unable to cast `Expression` to `IndexingExpression`"), - } - } - pub fn as_slicing(&self) -> &SlicingExpression { - match self { - Expression::Slicing(result) => result, - _ => panic!("Unable to cast `Expression` to `SlicingExpression`"), - } - } - pub fn as_select(&self) -> &SelectExpression { - match self { - Expression::Select(result) => result, - _ => panic!("Unable to cast `Expression` to `SelectExpression`"), - } - } - pub fn as_call(&self) -> &CallExpression { - match self { - Expression::Call(result) => result, - _ => panic!("Unable to cast `Expression` to `CallExpression`"), - } - } - pub fn as_call_mut(&mut self) -> &mut CallExpression { - match self { - Expression::Call(result) => result, - _ => panic!("Unable to cast `Expression` to `CallExpression`"), - } - } pub fn as_variable(&self) -> &VariableExpression { match self { Expression::Variable(result) => result, _ => panic!("Unable to cast `Expression` to `VariableExpression`"), } } - pub fn as_variable_mut(&mut self) -> &mut VariableExpression { - match self { - Expression::Variable(result) => result, - _ => panic!("Unable to cast `Expression` to `VariableExpression`"), - } - } + pub fn span(&self) -> InputSpan { match self { Expression::Assignment(expr) => expr.span, @@ -1542,23 +1256,6 @@ impl Expression { None } } - // TODO: @cleanup - pub fn set_parent(&mut self, parent: ExpressionParent) { - match self { - Expression::Assignment(expr) => expr.parent = parent, - Expression::Binding(expr) => expr.parent = parent, - Expression::Conditional(expr) => expr.parent = parent, - Expression::Binary(expr) => expr.parent = parent, - Expression::Unary(expr) => expr.parent = parent, - Expression::Indexing(expr) => expr.parent = parent, - Expression::Slicing(expr) => expr.parent = parent, - Expression::Select(expr) => expr.parent = parent, - Expression::Literal(expr) => expr.parent = parent, - Expression::Cast(expr) => expr.parent = parent, - Expression::Call(expr) => expr.parent = parent, - Expression::Variable(expr) => expr.parent = parent, - } - } pub fn get_unique_id_in_definition(&self) -> i32 { match self { @@ -1803,14 +1500,6 @@ impl Literal { } } - pub(crate) fn as_struct_mut(&mut self) -> &mut LiteralStruct { - if let Literal::Struct(literal) = self{ - literal - } else { - unreachable!("Attempted to obtain {:?} as Literal::Struct", self) - } - } - pub(crate) fn as_enum(&self) -> &LiteralEnum { if let Literal::Enum(literal) = self { literal diff --git a/src/protocol/ast_printer.rs b/src/protocol/ast_printer.rs index e85620bd2d8bf499dc08b014c255c736bcccc044..95a47ea43f4b4996e1fdb4e701237dd1cd475b49 100644 --- a/src/protocol/ast_printer.rs +++ b/src/protocol/ast_printer.rs @@ -549,7 +549,6 @@ impl ASTWriter { let expr = &heap[expr_id]; let indent2 = indent + 1; let indent3 = indent2 + 1; - let def_id = self.cur_definition.unwrap(); match expr { Expression::Assignment(expr) => { diff --git a/src/protocol/eval/executor.rs b/src/protocol/eval/executor.rs index 9bcb1c55e0fa8754e1cfd8d6372692502a435bf6..298d1c01b01250e1db3213df35d670c4dbd44485 100644 --- a/src/protocol/eval/executor.rs +++ b/src/protocol/eval/executor.rs @@ -183,7 +183,7 @@ impl Frame { self.serialize_expression(heap, *arg_expr_id); } }, - Expression::Variable(expr) => { + Expression::Variable(_expr) => { // No subexpressions } } @@ -338,7 +338,7 @@ impl Prompt { cur_frame.expr_values.push_back(result); self.store.drop_value(val.get_heap_pos()); }, - Expression::Indexing(expr) => { + Expression::Indexing(_expr) => { // Evaluate index. Never heap allocated so we do // not have to drop it. let index = cur_frame.expr_values.pop_back().unwrap(); @@ -353,7 +353,7 @@ impl Prompt { let subject = cur_frame.expr_values.pop_back().unwrap(); - let (deallocate_heap_pos, value_to_push, subject_heap_pos) = match subject { + let (deallocate_heap_pos, value_to_push) = match subject { Value::Ref(value_ref) => { // Our expression stack value is a reference to something that // exists in the normal stack/heap. We don't want to deallocate @@ -370,7 +370,7 @@ impl Prompt { return Err(construct_array_error(self, modules, heap, expr_id, subject_heap_pos, index)); } - (None, Value::Ref(ValueId::Heap(subject_heap_pos, index as u32)), subject_heap_pos) + (None, Value::Ref(ValueId::Heap(subject_heap_pos, index as u32))) }, _ => { // Our value lives on the expression stack, hence we need to @@ -387,7 +387,7 @@ impl Prompt { } let subject_indexed = Value::Ref(ValueId::Heap(subject_heap_pos, index as u32)); - (Some(subject_heap_pos), self.store.clone_value(subject_indexed), subject_heap_pos) + (Some(subject_heap_pos), self.store.clone_value(subject_indexed)) }, }; @@ -717,19 +717,19 @@ impl Prompt { debug_log!("Frame [{:?}] at {:?}", cur_frame.definition, cur_frame.position); if debug_enabled!() { debug_log!("Expression value stack (size = {}):", cur_frame.expr_values.len()); - for (stack_idx, stack_val) in cur_frame.expr_values.iter().enumerate() { - debug_log!(" [{:03}] {:?}", stack_idx, stack_val); + for (_stack_idx, _stack_val) in cur_frame.expr_values.iter().enumerate() { + debug_log!(" [{:03}] {:?}", _stack_idx, _stack_val); } debug_log!("Stack (size = {}):", self.store.stack.len()); - for (stack_idx, stack_val) in self.store.stack.iter().enumerate() { - debug_log!(" [{:03}] {:?}", stack_idx, stack_val); + for (_stack_idx, _stack_val) in self.store.stack.iter().enumerate() { + debug_log!(" [{:03}] {:?}", _stack_idx, _stack_val); } debug_log!("Heap:"); - for (heap_idx, heap_region) in self.store.heap_regions.iter().enumerate() { - let is_free = self.store.free_regions.iter().any(|idx| *idx as usize == heap_idx); - debug_log!(" [{:03}] in_use: {}, len: {}, vals: {:?}", heap_idx, !is_free, heap_region.values.len(), &heap_region.values); + for (_heap_idx, _heap_region) in self.store.heap_regions.iter().enumerate() { + let _is_free = self.store.free_regions.iter().any(|idx| *idx as usize == _heap_idx); + debug_log!(" [{:03}] in_use: {}, len: {}, vals: {:?}", _heap_idx, !_is_free, heap_region.values.len(), &_heap_region.values); } } // No (more) expressions to evaluate. So evaluate statement (that may @@ -827,7 +827,7 @@ impl Prompt { Ok(EvalContinuation::SyncBlockEnd) }, - Statement::Return(stmt) => { + Statement::Return(_stmt) => { debug_assert!(heap[cur_frame.definition].is_function()); debug_assert_eq!(cur_frame.expr_values.len(), 1, "expected one expr value for return statement"); diff --git a/src/protocol/eval/value.rs b/src/protocol/eval/value.rs index 0f8dd46cbe48ed7d5afd0fadff97de3c50bd0b26..f5e06c522cbafce1755cac8be4eccad043a6257d 100644 --- a/src/protocol/eval/value.rs +++ b/src/protocol/eval/value.rs @@ -798,6 +798,7 @@ pub(crate) fn apply_inequality_operator(store: &Store, lhs: &Value, rhs: &Value) Value::SInt16(v) => *v != rhs.as_sint16(), Value::SInt32(v) => *v != rhs.as_sint32(), Value::SInt64(v) => *v != rhs.as_sint64(), + Value::Array(lhs_pos) => eval_inequality_heap(store, *lhs_pos, rhs.as_array()), Value::Enum(v) => *v != rhs.as_enum(), Value::Union(lhs_tag, lhs_pos) => { let (rhs_tag, rhs_pos) = rhs.as_union(); @@ -806,7 +807,7 @@ pub(crate) fn apply_inequality_operator(store: &Store, lhs: &Value, rhs: &Value) } eval_inequality_heap(store, *lhs_pos, rhs_pos) }, - Value::String(lhs_pos) => eval_inequality_heap(store, *lhs_pos, rhs.as_struct()), + Value::Struct(lhs_pos) => eval_inequality_heap(store, *lhs_pos, rhs.as_struct()), _ => unreachable!("apply_inequality_operator to lhs {:?}", lhs) } } diff --git a/src/protocol/eval_old.rs b/src/protocol/eval_old.rs deleted file mode 100644 index 5d5ffb3faa1ec7f0e1685dda67a376e1a7f0ce28..0000000000000000000000000000000000000000 --- a/src/protocol/eval_old.rs +++ /dev/null @@ -1,1807 +0,0 @@ -use std::collections::HashMap; -use std::fmt; -use std::fmt::{Debug, Display, Formatter}; -use std::{i16, i32, i64, i8}; - -use crate::common::*; - -use crate::protocol::ast::*; -use crate::protocol::EvalContext; - -// const MAX_RECURSION: usize = 1024; - -const BYTE_MIN: i64 = i8::MIN as i64; -const BYTE_MAX: i64 = i8::MAX as i64; -const SHORT_MIN: i64 = i16::MIN as i64; -const SHORT_MAX: i64 = i16::MAX as i64; -const INT_MIN: i64 = i32::MIN as i64; -const INT_MAX: i64 = i32::MAX as i64; - -const MESSAGE_MAX_LENGTH: i64 = SHORT_MAX; - -const ONE: Value = Value::Byte(ByteValue(1)); - -// TODO: All goes one day anyway, so dirty typechecking hack -trait ValueImpl { - fn exact_type(&self) -> Type; - fn is_type_compatible(&self, h: &Heap, t: &[ParserTypeElement]) -> bool { - Self::is_type_compatible_hack(h, t) - } - fn is_type_compatible_hack(h: &Heap, t: &[ParserTypeElement]) -> bool; -} - -#[derive(Debug, Clone)] -pub enum Value { - Unassigned, - Input(InputValue), - Output(OutputValue), - Message(MessageValue), - Boolean(BooleanValue), - Byte(ByteValue), - Short(ShortValue), - Int(IntValue), - Long(LongValue), - InputArray(InputArrayValue), - OutputArray(OutputArrayValue), - MessageArray(MessageArrayValue), - BooleanArray(BooleanArrayValue), - ByteArray(ByteArrayValue), - ShortArray(ShortArrayValue), - IntArray(IntArrayValue), - LongArray(LongArrayValue), -} -impl Value { - pub fn receive_message(buffer: &Payload) -> Value { - Value::Message(MessageValue(Some(buffer.clone()))) - } - fn create_message(length: Value) -> Value { - match length { - Value::Byte(_) | Value::Short(_) | Value::Int(_) | Value::Long(_) => { - let length: i64 = i64::from(length); - if length < 0 || length > MESSAGE_MAX_LENGTH { - // Only messages within the expected length are allowed - Value::Message(MessageValue(None)) - } else { - Value::Message(MessageValue(Some(Payload::new(length as usize)))) - } - } - _ => unimplemented!(), - } - } - fn from_constant(constant: &Literal) -> Value { - match constant { - Literal::Null => Value::Message(MessageValue(None)), - Literal::True => Value::Boolean(BooleanValue(true)), - Literal::False => Value::Boolean(BooleanValue(false)), - Literal::Integer(val) => { - // Convert raw ASCII data to UTF-8 string - let mut integer_value = val.unsigned_value as i64; // TODO: @Int - if val.negated { integer_value = -integer_value; }; - - if integer_value >= BYTE_MIN && integer_value <= BYTE_MAX { - Value::Byte(ByteValue(integer_value as i8)) - } else if integer_value >= SHORT_MIN && integer_value <= SHORT_MAX { - Value::Short(ShortValue(integer_value as i16)) - } else if integer_value >= INT_MIN && integer_value <= INT_MAX { - Value::Int(IntValue(integer_value as i32)) - } else { - Value::Long(LongValue(integer_value)) - } - } - Literal::Character(_data) => unimplemented!(), - Literal::String(_data) => unimplemented!(), - Literal::Struct(_data) => unimplemented!(), - Literal::Enum(_data) => unimplemented!(), - Literal::Union(_data) => unimplemented!(), - Literal::Array(_expressions) => unimplemented!(), - } - } - fn set(&mut self, index: &Value, value: &Value) -> Option { - // The index must be of integer type, and non-negative - let the_index: usize; - match index { - Value::Byte(_) | Value::Short(_) | Value::Int(_) | Value::Long(_) => { - let index = i64::from(index); - if index < 0 || index >= MESSAGE_MAX_LENGTH { - // It is inconsistent to update out of bounds - return None; - } - the_index = index.try_into().unwrap(); - } - _ => unreachable!(), - } - // The subject must be either a message or an array - // And the value and the subject must be compatible - match (self, value) { - (Value::Message(MessageValue(None)), _) => { - // It is inconsistent to update the null message - None - } - (Value::Message(MessageValue(Some(payload))), Value::Byte(ByteValue(b))) => { - if *b < 0 { - // It is inconsistent to update with a negative value - return None; - } - if let Some(slot) = payload.as_mut_vec().get_mut(the_index) { - *slot = (*b).try_into().unwrap(); - Some(value.clone()) - } else { - // It is inconsistent to update out of bounds - None - } - } - (Value::Message(MessageValue(Some(payload))), Value::Short(ShortValue(b))) => { - if *b < 0 || *b > BYTE_MAX as i16 { - // It is inconsistent to update with a negative value or a too large value - return None; - } - if let Some(slot) = payload.as_mut_vec().get_mut(the_index) { - *slot = (*b).try_into().unwrap(); - Some(value.clone()) - } else { - // It is inconsistent to update out of bounds - None - } - } - (Value::InputArray(_), Value::Input(_)) => todo!(), - (Value::OutputArray(_), Value::Output(_)) => todo!(), - (Value::MessageArray(_), Value::Message(_)) => todo!(), - (Value::BooleanArray(_), Value::Boolean(_)) => todo!(), - (Value::ByteArray(_), Value::Byte(_)) => todo!(), - (Value::ShortArray(_), Value::Short(_)) => todo!(), - (Value::IntArray(_), Value::Int(_)) => todo!(), - (Value::LongArray(_), Value::Long(_)) => todo!(), - _ => unreachable!(), - } - } - fn get(&self, index: &Value) -> Option { - // The index must be of integer type, and non-negative - let the_index: usize; - match index { - Value::Byte(_) | Value::Short(_) | Value::Int(_) | Value::Long(_) => { - let index = i64::from(index); - if index < 0 || index >= MESSAGE_MAX_LENGTH { - // It is inconsistent to update out of bounds - return None; - } - the_index = index.try_into().unwrap(); - } - _ => unreachable!(), - } - // The subject must be either a message or an array - match self { - Value::Message(MessageValue(None)) => { - // It is inconsistent to read from the null message - None - } - Value::Message(MessageValue(Some(payload))) => { - if let Some(slot) = payload.as_slice().get(the_index) { - Some(Value::Short(ShortValue((*slot).try_into().unwrap()))) - } else { - // It is inconsistent to update out of bounds - None - } - } - _ => panic!("Can only get from port value"), - } - } - fn length(&self) -> Option { - // The subject must be either a message or an array - match self { - Value::Message(MessageValue(None)) => { - // It is inconsistent to get length from the null message - None - } - Value::Message(MessageValue(Some(buffer))) => { - Some(Value::Int(IntValue((buffer.len()).try_into().unwrap()))) - } - Value::InputArray(InputArrayValue(vec)) => { - Some(Value::Int(IntValue((vec.len()).try_into().unwrap()))) - } - Value::OutputArray(OutputArrayValue(vec)) => { - Some(Value::Int(IntValue((vec.len()).try_into().unwrap()))) - } - Value::MessageArray(MessageArrayValue(vec)) => { - Some(Value::Int(IntValue((vec.len()).try_into().unwrap()))) - } - Value::BooleanArray(BooleanArrayValue(vec)) => { - Some(Value::Int(IntValue((vec.len()).try_into().unwrap()))) - } - Value::ByteArray(ByteArrayValue(vec)) => { - Some(Value::Int(IntValue((vec.len()).try_into().unwrap()))) - } - Value::ShortArray(ShortArrayValue(vec)) => { - Some(Value::Int(IntValue((vec.len()).try_into().unwrap()))) - } - Value::IntArray(IntArrayValue(vec)) => { - Some(Value::Int(IntValue((vec.len()).try_into().unwrap()))) - } - Value::LongArray(LongArrayValue(vec)) => { - Some(Value::Int(IntValue((vec.len()).try_into().unwrap()))) - } - _ => unreachable!(), - } - } - fn plus(&self, other: &Value) -> Value { - match (self, other) { - (Value::Byte(ByteValue(s)), Value::Byte(ByteValue(o))) => { - Value::Byte(ByteValue(*s + *o)) - } - (Value::Byte(ByteValue(s)), Value::Short(ShortValue(o))) => { - Value::Short(ShortValue(*s as i16 + *o)) - } - (Value::Byte(ByteValue(s)), Value::Int(IntValue(o))) => { - Value::Int(IntValue(*s as i32 + *o)) - } - (Value::Byte(ByteValue(s)), Value::Long(LongValue(o))) => { - Value::Long(LongValue(*s as i64 + *o)) - } - (Value::Short(ShortValue(s)), Value::Byte(ByteValue(o))) => { - Value::Short(ShortValue(*s + *o as i16)) - } - (Value::Short(ShortValue(s)), Value::Short(ShortValue(o))) => { - Value::Short(ShortValue(*s + *o)) - } - (Value::Short(ShortValue(s)), Value::Int(IntValue(o))) => { - Value::Int(IntValue(*s as i32 + *o)) - } - (Value::Short(ShortValue(s)), Value::Long(LongValue(o))) => { - Value::Long(LongValue(*s as i64 + *o)) - } - (Value::Int(IntValue(s)), Value::Byte(ByteValue(o))) => { - Value::Int(IntValue(*s + *o as i32)) - } - (Value::Int(IntValue(s)), Value::Short(ShortValue(o))) => { - Value::Int(IntValue(*s + *o as i32)) - } - (Value::Int(IntValue(s)), Value::Int(IntValue(o))) => Value::Int(IntValue(*s + *o)), - (Value::Int(IntValue(s)), Value::Long(LongValue(o))) => { - Value::Long(LongValue(*s as i64 + *o)) - } - (Value::Long(LongValue(s)), Value::Byte(ByteValue(o))) => { - Value::Long(LongValue(*s + *o as i64)) - } - (Value::Long(LongValue(s)), Value::Short(ShortValue(o))) => { - Value::Long(LongValue(*s + *o as i64)) - } - (Value::Long(LongValue(s)), Value::Int(IntValue(o))) => { - Value::Long(LongValue(*s + *o as i64)) - } - (Value::Long(LongValue(s)), Value::Long(LongValue(o))) => { - Value::Long(LongValue(*s + *o)) - } - - (Value::Message(MessageValue(s)), Value::Message(MessageValue(o))) => { - let payload = if let [Some(s), Some(o)] = [s, o] { - let mut payload = s.clone(); - payload.concatenate_with(o); - Some(payload) - } else { - None - }; - Value::Message(MessageValue(payload)) - } - _ => unimplemented!(), - } - } - fn minus(&self, other: &Value) -> Value { - match (self, other) { - (Value::Byte(ByteValue(s)), Value::Byte(ByteValue(o))) => { - Value::Byte(ByteValue(*s - *o)) - } - (Value::Byte(ByteValue(s)), Value::Short(ShortValue(o))) => { - Value::Short(ShortValue(*s as i16 - *o)) - } - (Value::Byte(ByteValue(s)), Value::Int(IntValue(o))) => { - Value::Int(IntValue(*s as i32 - *o)) - } - (Value::Byte(ByteValue(s)), Value::Long(LongValue(o))) => { - Value::Long(LongValue(*s as i64 - *o)) - } - (Value::Short(ShortValue(s)), Value::Byte(ByteValue(o))) => { - Value::Short(ShortValue(*s - *o as i16)) - } - (Value::Short(ShortValue(s)), Value::Short(ShortValue(o))) => { - Value::Short(ShortValue(*s - *o)) - } - (Value::Short(ShortValue(s)), Value::Int(IntValue(o))) => { - Value::Int(IntValue(*s as i32 - *o)) - } - (Value::Short(ShortValue(s)), Value::Long(LongValue(o))) => { - Value::Long(LongValue(*s as i64 - *o)) - } - (Value::Int(IntValue(s)), Value::Byte(ByteValue(o))) => { - Value::Int(IntValue(*s - *o as i32)) - } - (Value::Int(IntValue(s)), Value::Short(ShortValue(o))) => { - Value::Int(IntValue(*s - *o as i32)) - } - (Value::Int(IntValue(s)), Value::Int(IntValue(o))) => Value::Int(IntValue(*s - *o)), - (Value::Int(IntValue(s)), Value::Long(LongValue(o))) => { - Value::Long(LongValue(*s as i64 - *o)) - } - (Value::Long(LongValue(s)), Value::Byte(ByteValue(o))) => { - Value::Long(LongValue(*s - *o as i64)) - } - (Value::Long(LongValue(s)), Value::Short(ShortValue(o))) => { - Value::Long(LongValue(*s - *o as i64)) - } - (Value::Long(LongValue(s)), Value::Int(IntValue(o))) => { - Value::Long(LongValue(*s - *o as i64)) - } - (Value::Long(LongValue(s)), Value::Long(LongValue(o))) => { - Value::Long(LongValue(*s - *o)) - } - _ => unimplemented!(), - } - } - fn modulus(&self, other: &Value) -> Value { - match (self, other) { - (Value::Byte(ByteValue(s)), Value::Byte(ByteValue(o))) => { - Value::Byte(ByteValue(*s % *o)) - } - (Value::Byte(ByteValue(s)), Value::Short(ShortValue(o))) => { - Value::Short(ShortValue(*s as i16 % *o)) - } - (Value::Byte(ByteValue(s)), Value::Int(IntValue(o))) => { - Value::Int(IntValue(*s as i32 % *o)) - } - (Value::Byte(ByteValue(s)), Value::Long(LongValue(o))) => { - Value::Long(LongValue(*s as i64 % *o)) - } - (Value::Short(ShortValue(s)), Value::Byte(ByteValue(o))) => { - Value::Short(ShortValue(*s % *o as i16)) - } - (Value::Short(ShortValue(s)), Value::Short(ShortValue(o))) => { - Value::Short(ShortValue(*s % *o)) - } - (Value::Short(ShortValue(s)), Value::Int(IntValue(o))) => { - Value::Int(IntValue(*s as i32 % *o)) - } - (Value::Short(ShortValue(s)), Value::Long(LongValue(o))) => { - Value::Long(LongValue(*s as i64 % *o)) - } - (Value::Int(IntValue(s)), Value::Byte(ByteValue(o))) => { - Value::Int(IntValue(*s % *o as i32)) - } - (Value::Int(IntValue(s)), Value::Short(ShortValue(o))) => { - Value::Int(IntValue(*s % *o as i32)) - } - (Value::Int(IntValue(s)), Value::Int(IntValue(o))) => Value::Int(IntValue(*s % *o)), - (Value::Int(IntValue(s)), Value::Long(LongValue(o))) => { - Value::Long(LongValue(*s as i64 % *o)) - } - (Value::Long(LongValue(s)), Value::Byte(ByteValue(o))) => { - Value::Long(LongValue(*s % *o as i64)) - } - (Value::Long(LongValue(s)), Value::Short(ShortValue(o))) => { - Value::Long(LongValue(*s % *o as i64)) - } - (Value::Long(LongValue(s)), Value::Int(IntValue(o))) => { - Value::Long(LongValue(*s % *o as i64)) - } - (Value::Long(LongValue(s)), Value::Long(LongValue(o))) => { - Value::Long(LongValue(*s % *o)) - } - _ => unimplemented!(), - } - } - fn eq(&self, other: &Value) -> Value { - match (self, other) { - (Value::Byte(ByteValue(s)), Value::Byte(ByteValue(o))) => { - Value::Boolean(BooleanValue(*s == *o)) - } - (Value::Byte(ByteValue(s)), Value::Short(ShortValue(o))) => { - Value::Boolean(BooleanValue(*s as i16 == *o)) - } - (Value::Byte(ByteValue(s)), Value::Int(IntValue(o))) => { - Value::Boolean(BooleanValue(*s as i32 == *o)) - } - (Value::Byte(ByteValue(s)), Value::Long(LongValue(o))) => { - Value::Boolean(BooleanValue(*s as i64 == *o)) - } - (Value::Short(ShortValue(s)), Value::Byte(ByteValue(o))) => { - Value::Boolean(BooleanValue(*s == *o as i16)) - } - (Value::Short(ShortValue(s)), Value::Short(ShortValue(o))) => { - Value::Boolean(BooleanValue(*s == *o)) - } - (Value::Short(ShortValue(s)), Value::Int(IntValue(o))) => { - Value::Boolean(BooleanValue(*s as i32 == *o)) - } - (Value::Short(ShortValue(s)), Value::Long(LongValue(o))) => { - Value::Boolean(BooleanValue(*s as i64 == *o)) - } - (Value::Int(IntValue(s)), Value::Byte(ByteValue(o))) => { - Value::Boolean(BooleanValue(*s == *o as i32)) - } - (Value::Int(IntValue(s)), Value::Short(ShortValue(o))) => { - Value::Boolean(BooleanValue(*s == *o as i32)) - } - (Value::Int(IntValue(s)), Value::Int(IntValue(o))) => { - Value::Boolean(BooleanValue(*s == *o)) - } - (Value::Int(IntValue(s)), Value::Long(LongValue(o))) => { - Value::Boolean(BooleanValue(*s as i64 == *o)) - } - (Value::Long(LongValue(s)), Value::Byte(ByteValue(o))) => { - Value::Boolean(BooleanValue(*s == *o as i64)) - } - (Value::Long(LongValue(s)), Value::Short(ShortValue(o))) => { - Value::Boolean(BooleanValue(*s == *o as i64)) - } - (Value::Long(LongValue(s)), Value::Int(IntValue(o))) => { - Value::Boolean(BooleanValue(*s == *o as i64)) - } - (Value::Long(LongValue(s)), Value::Long(LongValue(o))) => { - Value::Boolean(BooleanValue(*s == *o)) - } - (Value::Message(MessageValue(s)), Value::Message(MessageValue(o))) => { - Value::Boolean(BooleanValue(*s == *o)) - } - _ => unimplemented!(), - } - } - fn neq(&self, other: &Value) -> Value { - match (self, other) { - (Value::Byte(ByteValue(s)), Value::Byte(ByteValue(o))) => { - Value::Boolean(BooleanValue(*s != *o)) - } - (Value::Byte(ByteValue(s)), Value::Short(ShortValue(o))) => { - Value::Boolean(BooleanValue(*s as i16 != *o)) - } - (Value::Byte(ByteValue(s)), Value::Int(IntValue(o))) => { - Value::Boolean(BooleanValue(*s as i32 != *o)) - } - (Value::Byte(ByteValue(s)), Value::Long(LongValue(o))) => { - Value::Boolean(BooleanValue(*s as i64 != *o)) - } - (Value::Short(ShortValue(s)), Value::Byte(ByteValue(o))) => { - Value::Boolean(BooleanValue(*s != *o as i16)) - } - (Value::Short(ShortValue(s)), Value::Short(ShortValue(o))) => { - Value::Boolean(BooleanValue(*s != *o)) - } - (Value::Short(ShortValue(s)), Value::Int(IntValue(o))) => { - Value::Boolean(BooleanValue(*s as i32 != *o)) - } - (Value::Short(ShortValue(s)), Value::Long(LongValue(o))) => { - Value::Boolean(BooleanValue(*s as i64 != *o)) - } - (Value::Int(IntValue(s)), Value::Byte(ByteValue(o))) => { - Value::Boolean(BooleanValue(*s != *o as i32)) - } - (Value::Int(IntValue(s)), Value::Short(ShortValue(o))) => { - Value::Boolean(BooleanValue(*s != *o as i32)) - } - (Value::Int(IntValue(s)), Value::Int(IntValue(o))) => { - Value::Boolean(BooleanValue(*s != *o)) - } - (Value::Int(IntValue(s)), Value::Long(LongValue(o))) => { - Value::Boolean(BooleanValue(*s as i64 != *o)) - } - (Value::Long(LongValue(s)), Value::Byte(ByteValue(o))) => { - Value::Boolean(BooleanValue(*s != *o as i64)) - } - (Value::Long(LongValue(s)), Value::Short(ShortValue(o))) => { - Value::Boolean(BooleanValue(*s != *o as i64)) - } - (Value::Long(LongValue(s)), Value::Int(IntValue(o))) => { - Value::Boolean(BooleanValue(*s != *o as i64)) - } - (Value::Long(LongValue(s)), Value::Long(LongValue(o))) => { - Value::Boolean(BooleanValue(*s != *o)) - } - (Value::Message(MessageValue(s)), Value::Message(MessageValue(o))) => { - Value::Boolean(BooleanValue(*s != *o)) - } - _ => unimplemented!(), - } - } - fn lt(&self, other: &Value) -> Value { - // TODO: match value directly (as done above) - assert!(!self.exact_type().array); - assert!(!other.exact_type().array); - match (self.exact_type().primitive, other.exact_type().primitive) { - (PrimitiveType::Byte, PrimitiveType::Byte) => { - Value::Boolean(BooleanValue(i8::from(self) < i8::from(other))) - } - (PrimitiveType::Byte, PrimitiveType::Short) => { - Value::Boolean(BooleanValue(i16::from(self) < i16::from(other))) - } - (PrimitiveType::Byte, PrimitiveType::Int) => { - Value::Boolean(BooleanValue(i32::from(self) < i32::from(other))) - } - (PrimitiveType::Byte, PrimitiveType::Long) => { - Value::Boolean(BooleanValue(i64::from(self) < i64::from(other))) - } - (PrimitiveType::Short, PrimitiveType::Byte) => { - Value::Boolean(BooleanValue(i16::from(self) < i16::from(other))) - } - (PrimitiveType::Short, PrimitiveType::Short) => { - Value::Boolean(BooleanValue(i16::from(self) < i16::from(other))) - } - (PrimitiveType::Short, PrimitiveType::Int) => { - Value::Boolean(BooleanValue(i32::from(self) < i32::from(other))) - } - (PrimitiveType::Short, PrimitiveType::Long) => { - Value::Boolean(BooleanValue(i64::from(self) < i64::from(other))) - } - (PrimitiveType::Int, PrimitiveType::Byte) => { - Value::Boolean(BooleanValue(i32::from(self) < i32::from(other))) - } - (PrimitiveType::Int, PrimitiveType::Short) => { - Value::Boolean(BooleanValue(i32::from(self) < i32::from(other))) - } - (PrimitiveType::Int, PrimitiveType::Int) => { - Value::Boolean(BooleanValue(i32::from(self) < i32::from(other))) - } - (PrimitiveType::Int, PrimitiveType::Long) => { - Value::Boolean(BooleanValue(i64::from(self) < i64::from(other))) - } - (PrimitiveType::Long, PrimitiveType::Byte) => { - Value::Boolean(BooleanValue(i64::from(self) < i64::from(other))) - } - (PrimitiveType::Long, PrimitiveType::Short) => { - Value::Boolean(BooleanValue(i64::from(self) < i64::from(other))) - } - (PrimitiveType::Long, PrimitiveType::Int) => { - Value::Boolean(BooleanValue(i64::from(self) < i64::from(other))) - } - (PrimitiveType::Long, PrimitiveType::Long) => { - Value::Boolean(BooleanValue(i64::from(self) < i64::from(other))) - } - _ => unimplemented!(), - } - } - fn lte(&self, other: &Value) -> Value { - assert!(!self.exact_type().array); - assert!(!other.exact_type().array); - match (self.exact_type().primitive, other.exact_type().primitive) { - (PrimitiveType::Byte, PrimitiveType::Byte) => { - Value::Boolean(BooleanValue(i8::from(self) <= i8::from(other))) - } - (PrimitiveType::Byte, PrimitiveType::Short) => { - Value::Boolean(BooleanValue(i16::from(self) <= i16::from(other))) - } - (PrimitiveType::Byte, PrimitiveType::Int) => { - Value::Boolean(BooleanValue(i32::from(self) <= i32::from(other))) - } - (PrimitiveType::Byte, PrimitiveType::Long) => { - Value::Boolean(BooleanValue(i64::from(self) <= i64::from(other))) - } - (PrimitiveType::Short, PrimitiveType::Byte) => { - Value::Boolean(BooleanValue(i16::from(self) <= i16::from(other))) - } - (PrimitiveType::Short, PrimitiveType::Short) => { - Value::Boolean(BooleanValue(i16::from(self) <= i16::from(other))) - } - (PrimitiveType::Short, PrimitiveType::Int) => { - Value::Boolean(BooleanValue(i32::from(self) <= i32::from(other))) - } - (PrimitiveType::Short, PrimitiveType::Long) => { - Value::Boolean(BooleanValue(i64::from(self) <= i64::from(other))) - } - (PrimitiveType::Int, PrimitiveType::Byte) => { - Value::Boolean(BooleanValue(i32::from(self) <= i32::from(other))) - } - (PrimitiveType::Int, PrimitiveType::Short) => { - Value::Boolean(BooleanValue(i32::from(self) <= i32::from(other))) - } - (PrimitiveType::Int, PrimitiveType::Int) => { - Value::Boolean(BooleanValue(i32::from(self) <= i32::from(other))) - } - (PrimitiveType::Int, PrimitiveType::Long) => { - Value::Boolean(BooleanValue(i64::from(self) <= i64::from(other))) - } - (PrimitiveType::Long, PrimitiveType::Byte) => { - Value::Boolean(BooleanValue(i64::from(self) <= i64::from(other))) - } - (PrimitiveType::Long, PrimitiveType::Short) => { - Value::Boolean(BooleanValue(i64::from(self) <= i64::from(other))) - } - (PrimitiveType::Long, PrimitiveType::Int) => { - Value::Boolean(BooleanValue(i64::from(self) <= i64::from(other))) - } - (PrimitiveType::Long, PrimitiveType::Long) => { - Value::Boolean(BooleanValue(i64::from(self) <= i64::from(other))) - } - _ => unimplemented!(), - } - } - fn gt(&self, other: &Value) -> Value { - assert!(!self.exact_type().array); - assert!(!other.exact_type().array); - match (self.exact_type().primitive, other.exact_type().primitive) { - (PrimitiveType::Byte, PrimitiveType::Byte) => { - Value::Boolean(BooleanValue(i8::from(self) > i8::from(other))) - } - (PrimitiveType::Byte, PrimitiveType::Short) => { - Value::Boolean(BooleanValue(i16::from(self) > i16::from(other))) - } - (PrimitiveType::Byte, PrimitiveType::Int) => { - Value::Boolean(BooleanValue(i32::from(self) > i32::from(other))) - } - (PrimitiveType::Byte, PrimitiveType::Long) => { - Value::Boolean(BooleanValue(i64::from(self) > i64::from(other))) - } - (PrimitiveType::Short, PrimitiveType::Byte) => { - Value::Boolean(BooleanValue(i16::from(self) > i16::from(other))) - } - (PrimitiveType::Short, PrimitiveType::Short) => { - Value::Boolean(BooleanValue(i16::from(self) > i16::from(other))) - } - (PrimitiveType::Short, PrimitiveType::Int) => { - Value::Boolean(BooleanValue(i32::from(self) > i32::from(other))) - } - (PrimitiveType::Short, PrimitiveType::Long) => { - Value::Boolean(BooleanValue(i64::from(self) > i64::from(other))) - } - (PrimitiveType::Int, PrimitiveType::Byte) => { - Value::Boolean(BooleanValue(i32::from(self) > i32::from(other))) - } - (PrimitiveType::Int, PrimitiveType::Short) => { - Value::Boolean(BooleanValue(i32::from(self) > i32::from(other))) - } - (PrimitiveType::Int, PrimitiveType::Int) => { - Value::Boolean(BooleanValue(i32::from(self) > i32::from(other))) - } - (PrimitiveType::Int, PrimitiveType::Long) => { - Value::Boolean(BooleanValue(i64::from(self) > i64::from(other))) - } - (PrimitiveType::Long, PrimitiveType::Byte) => { - Value::Boolean(BooleanValue(i64::from(self) > i64::from(other))) - } - (PrimitiveType::Long, PrimitiveType::Short) => { - Value::Boolean(BooleanValue(i64::from(self) > i64::from(other))) - } - (PrimitiveType::Long, PrimitiveType::Int) => { - Value::Boolean(BooleanValue(i64::from(self) > i64::from(other))) - } - (PrimitiveType::Long, PrimitiveType::Long) => { - Value::Boolean(BooleanValue(i64::from(self) > i64::from(other))) - } - _ => unimplemented!(), - } - } - fn gte(&self, other: &Value) -> Value { - assert!(!self.exact_type().array); - assert!(!other.exact_type().array); - match (self.exact_type().primitive, other.exact_type().primitive) { - (PrimitiveType::Byte, PrimitiveType::Byte) => { - Value::Boolean(BooleanValue(i8::from(self) >= i8::from(other))) - } - (PrimitiveType::Byte, PrimitiveType::Short) => { - Value::Boolean(BooleanValue(i16::from(self) >= i16::from(other))) - } - (PrimitiveType::Byte, PrimitiveType::Int) => { - Value::Boolean(BooleanValue(i32::from(self) >= i32::from(other))) - } - (PrimitiveType::Byte, PrimitiveType::Long) => { - Value::Boolean(BooleanValue(i64::from(self) >= i64::from(other))) - } - (PrimitiveType::Short, PrimitiveType::Byte) => { - Value::Boolean(BooleanValue(i16::from(self) >= i16::from(other))) - } - (PrimitiveType::Short, PrimitiveType::Short) => { - Value::Boolean(BooleanValue(i16::from(self) >= i16::from(other))) - } - (PrimitiveType::Short, PrimitiveType::Int) => { - Value::Boolean(BooleanValue(i32::from(self) >= i32::from(other))) - } - (PrimitiveType::Short, PrimitiveType::Long) => { - Value::Boolean(BooleanValue(i64::from(self) >= i64::from(other))) - } - (PrimitiveType::Int, PrimitiveType::Byte) => { - Value::Boolean(BooleanValue(i32::from(self) >= i32::from(other))) - } - (PrimitiveType::Int, PrimitiveType::Short) => { - Value::Boolean(BooleanValue(i32::from(self) >= i32::from(other))) - } - (PrimitiveType::Int, PrimitiveType::Int) => { - Value::Boolean(BooleanValue(i32::from(self) >= i32::from(other))) - } - (PrimitiveType::Int, PrimitiveType::Long) => { - Value::Boolean(BooleanValue(i64::from(self) >= i64::from(other))) - } - (PrimitiveType::Long, PrimitiveType::Byte) => { - Value::Boolean(BooleanValue(i64::from(self) >= i64::from(other))) - } - (PrimitiveType::Long, PrimitiveType::Short) => { - Value::Boolean(BooleanValue(i64::from(self) >= i64::from(other))) - } - (PrimitiveType::Long, PrimitiveType::Int) => { - Value::Boolean(BooleanValue(i64::from(self) >= i64::from(other))) - } - (PrimitiveType::Long, PrimitiveType::Long) => { - Value::Boolean(BooleanValue(i64::from(self) >= i64::from(other))) - } - _ => unimplemented!(), - } - } - fn as_boolean(&self) -> &BooleanValue { - match self { - Value::Boolean(result) => result, - _ => panic!("Unable to cast `Value` to `BooleanValue`"), - } - } -} - -impl From for Value { - fn from(b: bool) -> Self { - Value::Boolean(BooleanValue(b)) - } -} -impl From for bool { - fn from(val: Value) -> Self { - match val { - Value::Boolean(BooleanValue(b)) => b, - _ => unimplemented!(), - } - } -} -impl From<&Value> for bool { - fn from(val: &Value) -> Self { - match val { - Value::Boolean(BooleanValue(b)) => *b, - _ => unimplemented!(), - } - } -} - -impl From for i8 { - fn from(val: Value) -> Self { - match val { - Value::Byte(ByteValue(b)) => b, - _ => unimplemented!(), - } - } -} -impl From<&Value> for i8 { - fn from(val: &Value) -> Self { - match val { - Value::Byte(ByteValue(b)) => *b, - _ => unimplemented!(), - } - } -} - -impl From for i16 { - fn from(val: Value) -> Self { - match val { - Value::Byte(ByteValue(b)) => i16::from(b), - Value::Short(ShortValue(s)) => s, - _ => unimplemented!(), - } - } -} -impl From<&Value> for i16 { - fn from(val: &Value) -> Self { - match val { - Value::Byte(ByteValue(b)) => i16::from(*b), - Value::Short(ShortValue(s)) => *s, - _ => unimplemented!(), - } - } -} - -impl From for i32 { - fn from(val: Value) -> Self { - match val { - Value::Byte(ByteValue(b)) => i32::from(b), - Value::Short(ShortValue(s)) => i32::from(s), - Value::Int(IntValue(i)) => i, - _ => unimplemented!(), - } - } -} -impl From<&Value> for i32 { - fn from(val: &Value) -> Self { - match val { - Value::Byte(ByteValue(b)) => i32::from(*b), - Value::Short(ShortValue(s)) => i32::from(*s), - Value::Int(IntValue(i)) => *i, - _ => unimplemented!(), - } - } -} - -impl From for i64 { - fn from(val: Value) -> Self { - match val { - Value::Byte(ByteValue(b)) => i64::from(b), - Value::Short(ShortValue(s)) => i64::from(s), - Value::Int(IntValue(i)) => i64::from(i), - Value::Long(LongValue(l)) => l, - _ => unimplemented!(), - } - } -} -impl From<&Value> for i64 { - fn from(val: &Value) -> Self { - match val { - Value::Byte(ByteValue(b)) => i64::from(*b), - Value::Short(ShortValue(s)) => i64::from(*s), - Value::Int(IntValue(i)) => i64::from(*i), - Value::Long(LongValue(l)) => *l, - _ => unimplemented!(), - } - } -} - -impl ValueImpl for Value { - fn exact_type(&self) -> Type { - match self { - Value::Unassigned => Type::UNASSIGNED, - Value::Input(val) => val.exact_type(), - Value::Output(val) => val.exact_type(), - Value::Message(val) => val.exact_type(), - Value::Boolean(val) => val.exact_type(), - Value::Byte(val) => val.exact_type(), - Value::Short(val) => val.exact_type(), - Value::Int(val) => val.exact_type(), - Value::Long(val) => val.exact_type(), - Value::InputArray(val) => val.exact_type(), - Value::OutputArray(val) => val.exact_type(), - Value::MessageArray(val) => val.exact_type(), - Value::BooleanArray(val) => val.exact_type(), - Value::ByteArray(val) => val.exact_type(), - Value::ShortArray(val) => val.exact_type(), - Value::IntArray(val) => val.exact_type(), - Value::LongArray(val) => val.exact_type(), - } - } - fn is_type_compatible(&self, h: &Heap, t: &[ParserTypeElement]) -> bool { - match self { - Value::Unassigned => true, - Value::Input(_) => InputValue::is_type_compatible_hack(h, t), - Value::Output(_) => OutputValue::is_type_compatible_hack(h, t), - Value::Message(_) => MessageValue::is_type_compatible_hack(h, t), - Value::Boolean(_) => BooleanValue::is_type_compatible_hack(h, t), - Value::Byte(_) => ByteValue::is_type_compatible_hack(h, t), - Value::Short(_) => ShortValue::is_type_compatible_hack(h, t), - Value::Int(_) => IntValue::is_type_compatible_hack(h, t), - Value::Long(_) => LongValue::is_type_compatible_hack(h, t), - Value::InputArray(_) => InputArrayValue::is_type_compatible_hack(h, t), - Value::OutputArray(_) => OutputArrayValue::is_type_compatible_hack(h, t), - Value::MessageArray(_) => MessageArrayValue::is_type_compatible_hack(h, t), - Value::BooleanArray(_) => BooleanArrayValue::is_type_compatible_hack(h, t), - Value::ByteArray(_) => ByteArrayValue::is_type_compatible_hack(h, t), - Value::ShortArray(_) => ShortArrayValue::is_type_compatible_hack(h, t), - Value::IntArray(_) => InputArrayValue::is_type_compatible_hack(h, t), - Value::LongArray(_) => LongArrayValue::is_type_compatible_hack(h, t), - } - } - fn is_type_compatible_hack(_h: &Heap, _t: &[ParserTypeElement]) -> bool { false } -} - -impl Display for Value { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - let disp: &dyn Display; - match self { - Value::Unassigned => disp = &Type::UNASSIGNED, - Value::Input(val) => disp = val, - Value::Output(val) => disp = val, - Value::Message(val) => disp = val, - Value::Boolean(val) => disp = val, - Value::Byte(val) => disp = val, - Value::Short(val) => disp = val, - Value::Int(val) => disp = val, - Value::Long(val) => disp = val, - Value::InputArray(val) => disp = val, - Value::OutputArray(val) => disp = val, - Value::MessageArray(val) => disp = val, - Value::BooleanArray(val) => disp = val, - Value::ByteArray(val) => disp = val, - Value::ShortArray(val) => disp = val, - Value::IntArray(val) => disp = val, - Value::LongArray(val) => disp = val, - } - disp.fmt(f) - } -} - -#[derive(Debug, Clone)] -pub struct InputValue(pub PortId); - -impl Display for InputValue { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - write!(f, "#in") - } -} - -impl ValueImpl for InputValue { - fn exact_type(&self) -> Type { - Type::INPUT - } - fn is_type_compatible_hack(_h: &Heap, t: &[ParserTypeElement]) -> bool { - use ParserTypeVariant::*; - match &t[0].variant { - Input | Inferred | Definition(_, _) => true, - _ => false, - } - } -} - -#[derive(Debug, Clone)] -pub struct OutputValue(pub PortId); - -impl Display for OutputValue { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - write!(f, "#out") - } -} - -impl ValueImpl for OutputValue { - fn exact_type(&self) -> Type { - Type::OUTPUT - } - fn is_type_compatible_hack(_h: &Heap, t: &[ParserTypeElement]) -> bool { - use ParserTypeVariant::*; - match &t[0].variant { - Output | Inferred | Definition(_, _) => true, - _ => false, - } - } -} - -#[derive(Debug, Clone)] -pub struct MessageValue(pub Option); - -impl Display for MessageValue { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - match &self.0 { - None => write!(f, "null"), - Some(payload) => { - // format print up to 10 bytes - let mut slice = payload.as_slice(); - if slice.len() > 10 { - slice = &slice[..10]; - } - f.debug_list().entries(slice.iter().copied()).finish() - } - } - } -} - -impl ValueImpl for MessageValue { - fn exact_type(&self) -> Type { - Type::MESSAGE - } - fn is_type_compatible_hack(_h: &Heap, t: &[ParserTypeElement]) -> bool { - use ParserTypeVariant::*; - match &t[0].variant { - Message | Inferred | Definition(_, _) => true, - _ => false, - } - } -} - -#[derive(Debug, Clone)] -pub struct BooleanValue(bool); - -impl Display for BooleanValue { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - write!(f, "{}", self.0) - } -} - -impl ValueImpl for BooleanValue { - fn exact_type(&self) -> Type { - Type::BOOLEAN - } - fn is_type_compatible_hack(_h: &Heap, t: &[ParserTypeElement]) -> bool { - use ParserTypeVariant::*; - match &t[0].variant { - Definition(_, _) | Inferred | Bool | - UInt8 | UInt16 | UInt32 | UInt64 | - SInt8 | SInt16 | SInt32 | SInt64 => true, - _ => false - } - } -} - -#[derive(Debug, Clone)] -pub struct ByteValue(i8); - -impl Display for ByteValue { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - write!(f, "{}", self.0) - } -} - -impl ValueImpl for ByteValue { - fn exact_type(&self) -> Type { - Type::BYTE - } - fn is_type_compatible_hack(_h: &Heap, t: &[ParserTypeElement]) -> bool { - use ParserTypeVariant::*; - match &t[0].variant { - Definition(_, _) | Inferred | - UInt8 | UInt16 | UInt32 | UInt64 | - SInt8 | SInt16 | SInt32 | SInt64 => true, - _ => false - } - } -} - -#[derive(Debug, Clone)] -pub struct ShortValue(i16); - -impl Display for ShortValue { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - write!(f, "{}", self.0) - } -} - -impl ValueImpl for ShortValue { - fn exact_type(&self) -> Type { - Type::SHORT - } - fn is_type_compatible_hack(_h: &Heap, t: &[ParserTypeElement]) -> bool { - use ParserTypeVariant::*; - match &t[0].variant { - Definition(_, _) | Inferred | - UInt16 | UInt32 | UInt64 | - SInt16 | SInt32 | SInt64=> true, - _ => false - } - } -} - -#[derive(Debug, Clone)] -pub struct IntValue(i32); - -impl Display for IntValue { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - write!(f, "{}", self.0) - } -} - -impl ValueImpl for IntValue { - fn exact_type(&self) -> Type { - Type::INT - } - fn is_type_compatible_hack(_h: &Heap, t: &[ParserTypeElement]) -> bool { - use ParserTypeVariant::*; - match t[0].variant { - Definition(_, _) | Inferred | - UInt32 | UInt64 | - SInt32 | SInt64 => true, - _ => false - } - } -} - -#[derive(Debug, Clone)] -pub struct LongValue(i64); - -impl Display for LongValue { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - write!(f, "{}", self.0) - } -} - -impl ValueImpl for LongValue { - fn exact_type(&self) -> Type { - Type::LONG - } - fn is_type_compatible_hack(_h: &Heap, t: &[ParserTypeElement]) -> bool { - use ParserTypeVariant::*; - match &t[0].variant { - UInt64 | SInt64 | Inferred | Definition(_, _) => true, - _ => false, - } - } -} - -fn get_array_inner(t: &[ParserTypeElement]) -> Option<&[ParserTypeElement]> { - if t[0].variant == ParserTypeVariant::Array { - return Some(&t[1..]) - } else { - return None; - } -} - -#[derive(Debug, Clone)] -pub struct InputArrayValue(Vec); - -impl Display for InputArrayValue { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - write!(f, "{{")?; - let mut first = true; - for v in self.0.iter() { - if !first { - write!(f, ",")?; - } - write!(f, "{}", v)?; - first = false; - } - write!(f, "}}") - } -} - -impl ValueImpl for InputArrayValue { - fn exact_type(&self) -> Type { - Type::INPUT_ARRAY - } - fn is_type_compatible_hack(h: &Heap, t: &[ParserTypeElement]) -> bool { - get_array_inner(t) - .map(|v| InputValue::is_type_compatible_hack(h, v)) - .unwrap_or(false) - } -} - -#[derive(Debug, Clone)] -pub struct OutputArrayValue(Vec); - -impl Display for OutputArrayValue { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - write!(f, "{{")?; - let mut first = true; - for v in self.0.iter() { - if !first { - write!(f, ",")?; - } - write!(f, "{}", v)?; - first = false; - } - write!(f, "}}") - } -} - -impl ValueImpl for OutputArrayValue { - fn exact_type(&self) -> Type { - Type::OUTPUT_ARRAY - } - fn is_type_compatible_hack(h: &Heap, t: &[ParserTypeElement]) -> bool { - get_array_inner(t) - .map(|v| OutputValue::is_type_compatible_hack(h, v)) - .unwrap_or(false) - } -} - -#[derive(Debug, Clone)] -pub struct MessageArrayValue(Vec); - -impl Display for MessageArrayValue { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - write!(f, "{{")?; - let mut first = true; - for v in self.0.iter() { - if !first { - write!(f, ",")?; - } - write!(f, "{}", v)?; - first = false; - } - write!(f, "}}") - } -} - -impl ValueImpl for MessageArrayValue { - fn exact_type(&self) -> Type { - Type::MESSAGE_ARRAY - } - fn is_type_compatible_hack(h: &Heap, t: &[ParserTypeElement]) -> bool { - get_array_inner(t) - .map(|v| MessageValue::is_type_compatible_hack(h, v)) - .unwrap_or(false) - } -} - -#[derive(Debug, Clone)] -pub struct BooleanArrayValue(Vec); - -impl Display for BooleanArrayValue { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - write!(f, "{{")?; - let mut first = true; - for v in self.0.iter() { - if !first { - write!(f, ",")?; - } - write!(f, "{}", v)?; - first = false; - } - write!(f, "}}") - } -} - -impl ValueImpl for BooleanArrayValue { - fn exact_type(&self) -> Type { - Type::BOOLEAN_ARRAY - } - fn is_type_compatible_hack(h: &Heap, t: &[ParserTypeElement]) -> bool { - get_array_inner(t) - .map(|v| BooleanValue::is_type_compatible_hack(h, v)) - .unwrap_or(false) - } -} - -#[derive(Debug, Clone)] -pub struct ByteArrayValue(Vec); - -impl Display for ByteArrayValue { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - write!(f, "{{")?; - let mut first = true; - for v in self.0.iter() { - if !first { - write!(f, ",")?; - } - write!(f, "{}", v)?; - first = false; - } - write!(f, "}}") - } -} - -impl ValueImpl for ByteArrayValue { - fn exact_type(&self) -> Type { - Type::BYTE_ARRAY - } - fn is_type_compatible_hack(h: &Heap, t: &[ParserTypeElement]) -> bool { - get_array_inner(t) - .map(|v| ByteValue::is_type_compatible_hack(h, v)) - .unwrap_or(false) - } -} - -#[derive(Debug, Clone)] -pub struct ShortArrayValue(Vec); - -impl Display for ShortArrayValue { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - write!(f, "{{")?; - let mut first = true; - for v in self.0.iter() { - if !first { - write!(f, ",")?; - } - write!(f, "{}", v)?; - first = false; - } - write!(f, "}}") - } -} - -impl ValueImpl for ShortArrayValue { - fn exact_type(&self) -> Type { - Type::SHORT_ARRAY - } - fn is_type_compatible_hack(h: &Heap, t: &[ParserTypeElement]) -> bool { - get_array_inner(t) - .map(|v| ShortValue::is_type_compatible_hack(h, v)) - .unwrap_or(false) - } -} - -#[derive(Debug, Clone)] -pub struct IntArrayValue(Vec); - -impl Display for IntArrayValue { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - write!(f, "{{")?; - let mut first = true; - for v in self.0.iter() { - if !first { - write!(f, ",")?; - } - write!(f, "{}", v)?; - first = false; - } - write!(f, "}}") - } -} - -impl ValueImpl for IntArrayValue { - fn exact_type(&self) -> Type { - Type::INT_ARRAY - } - fn is_type_compatible_hack(h: &Heap, t: &[ParserTypeElement]) -> bool { - get_array_inner(t) - .map(|v| IntValue::is_type_compatible_hack(h, v)) - .unwrap_or(false) - } -} - -#[derive(Debug, Clone)] -pub struct LongArrayValue(Vec); - -impl Display for LongArrayValue { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - write!(f, "{{")?; - let mut first = true; - for v in self.0.iter() { - if !first { - write!(f, ",")?; - } - write!(f, "{}", v)?; - first = false; - } - write!(f, "}}") - } -} - -impl ValueImpl for LongArrayValue { - fn exact_type(&self) -> Type { - Type::LONG_ARRAY - } - fn is_type_compatible_hack(h: &Heap, t: &[ParserTypeElement]) -> bool { - get_array_inner(t) - .map(|v| LongValue::is_type_compatible_hack(h, v)) - .unwrap_or(false) - } -} - -#[derive(Debug, Clone)] -struct Store { - map: HashMap, -} -impl Store { - fn new() -> Self { - Store { map: HashMap::new() } - } - fn initialize(&mut self, h: &Heap, var: VariableId, value: Value) { - // Ensure value is compatible with type of variable - let parser_type = match &h[var] { - Variable::Local(v) => &v.parser_type, - Variable::Parameter(v) => &v.parser_type, - }; - assert!(value.is_type_compatible(h, &parser_type.elements)); - // Overwrite mapping - self.map.insert(var, value.clone()); - } - fn update( - &mut self, - h: &Heap, - ctx: &mut EvalContext, - lexpr: ExpressionId, - value: Value, - ) -> EvalResult { - match &h[lexpr] { - Expression::Variable(var) => { - let var = var.declaration.unwrap(); - // Ensure value is compatible with type of variable - let parser_type = match &h[var] { - Variable::Local(v) => &v.parser_type, - Variable::Parameter(v) => &v.parser_type - }; - assert!(value.is_type_compatible(h, &parser_type.elements)); - // Overwrite mapping - self.map.insert(var, value.clone()); - Ok(value) - } - Expression::Indexing(indexing) => { - // Evaluate index expression, which must be some integral type - let index = self.eval(h, ctx, indexing.index)?; - // Mutable reference to the subject - let subject; - match &h[indexing.subject] { - Expression::Variable(var) => { - let var = var.declaration.unwrap(); - subject = self.map.get_mut(&var).unwrap(); - } - _ => unreachable!(), - } - match subject.set(&index, &value) { - Some(value) => Ok(value), - None => Err(EvalContinuation::Inconsistent), - } - } - _ => unimplemented!("{:?}", h[lexpr]), - } - } - fn get(&mut self, h: &Heap, ctx: &mut EvalContext, rexpr: ExpressionId) -> EvalResult { - match &h[rexpr] { - Expression::Variable(var) => { - let var_id = var.declaration.unwrap(); - let value = self - .map - .get(&var_id) - .expect(&format!("Uninitialized variable {:?}", var.identifier.value.as_str())); - Ok(value.clone()) - } - Expression::Indexing(indexing) => { - // Evaluate index expression, which must be some integral type - let index = self.eval(h, ctx, indexing.index)?; - // Reference to subject - let subject; - match &h[indexing.subject] { - Expression::Variable(var) => { - let var = var.declaration.unwrap(); - subject = self.map.get(&var).unwrap(); - } - q => unreachable!("Reached {:?}", q), - } - match subject.get(&index) { - Some(value) => Ok(value), - None => Err(EvalContinuation::Inconsistent), - } - } - Expression::Select(selecting) => { - // Reference to subject - let subject; - match &h[selecting.subject] { - Expression::Variable(var) => { - let var = var.declaration.unwrap(); - subject = self.map.get(&var).unwrap(); - } - q => unreachable!("Reached {:?}", q), - } - match subject.length() { - Some(value) => Ok(value), - None => Err(EvalContinuation::Inconsistent), - } - } - _ => unimplemented!("{:?}", h[rexpr]), - } - } - fn eval(&mut self, h: &Heap, ctx: &mut EvalContext, expr: ExpressionId) -> EvalResult { - match &h[expr] { - Expression::Assignment(expr) => { - let value = self.eval(h, ctx, expr.right)?; - match expr.operation { - AssignmentOperator::Set => { - self.update(h, ctx, expr.left, value.clone())?; - } - AssignmentOperator::Added => { - let old = self.get(h, ctx, expr.left)?; - self.update(h, ctx, expr.left, old.plus(&value))?; - } - AssignmentOperator::Subtracted => { - let old = self.get(h, ctx, expr.left)?; - self.update(h, ctx, expr.left, old.minus(&value))?; - } - _ => unimplemented!("{:?}", expr), - } - Ok(value) - } - Expression::Binding(_expr) => { - unimplemented!("eval binding expression"); - } - Expression::Conditional(expr) => { - let test = self.eval(h, ctx, expr.test)?; - if test.as_boolean().0 { - self.eval(h, ctx, expr.true_expression) - } else { - self.eval(h, ctx, expr.false_expression) - } - } - Expression::Binary(expr) => { - let left = self.eval(h, ctx, expr.left)?; - let right; - match expr.operation { - BinaryOperator::LogicalAnd => { - if left.as_boolean().0 == false { - return Ok(left); - } - right = self.eval(h, ctx, expr.right)?; - right.as_boolean(); // panics if not a boolean - return Ok(right); - } - BinaryOperator::LogicalOr => { - if left.as_boolean().0 == true { - return Ok(left); - } - right = self.eval(h, ctx, expr.right)?; - right.as_boolean(); // panics if not a boolean - return Ok(right); - } - _ => {} - } - right = self.eval(h, ctx, expr.right)?; - match expr.operation { - BinaryOperator::Equality => Ok(left.eq(&right)), - BinaryOperator::Inequality => Ok(left.neq(&right)), - BinaryOperator::LessThan => Ok(left.lt(&right)), - BinaryOperator::LessThanEqual => Ok(left.lte(&right)), - BinaryOperator::GreaterThan => Ok(left.gt(&right)), - BinaryOperator::GreaterThanEqual => Ok(left.gte(&right)), - BinaryOperator::Remainder => Ok(left.modulus(&right)), - BinaryOperator::Add => Ok(left.plus(&right)), - _ => unimplemented!("{:?}", expr.operation), - } - } - Expression::Unary(expr) => { - let mut value = self.eval(h, ctx, expr.expression)?; - match expr.operation { - UnaryOperator::PostIncrement => { - self.update(h, ctx, expr.expression, value.plus(&ONE))?; - } - UnaryOperator::PreIncrement => { - value = value.plus(&ONE); - self.update(h, ctx, expr.expression, value.clone())?; - } - UnaryOperator::PostDecrement => { - self.update(h, ctx, expr.expression, value.minus(&ONE))?; - } - UnaryOperator::PreDecrement => { - value = value.minus(&ONE); - self.update(h, ctx, expr.expression, value.clone())?; - } - _ => unimplemented!(), - } - Ok(value) - } - Expression::Indexing(expr) => self.get(h, ctx, expr.this.upcast()), - Expression::Slicing(_expr) => unimplemented!(), - Expression::Select(expr) => self.get(h, ctx, expr.this.upcast()), - Expression::Literal(expr) => Ok(Value::from_constant(&expr.value)), - Expression::Call(expr) => match &expr.method { - Method::Get => { - assert_eq!(1, expr.arguments.len()); - let value = self.eval(h, ctx, expr.arguments[0])?; - match ctx.get(value.clone()) { - None => Err(EvalContinuation::BlockGet(value)), - Some(result) => Ok(result), - } - } - Method::Put => { - assert_eq!(2, expr.arguments.len()); - let port_value = self.eval(h, ctx, expr.arguments[0])?; - let msg_value = self.eval(h, ctx, expr.arguments[1])?; - if ctx.did_put(port_value.clone()) { - // Return bogus, replacing this at some point anyway - Ok(Value::Message(MessageValue(None))) - } else { - Err(EvalContinuation::Put(port_value, msg_value)) - } - } - Method::Fires => { - assert_eq!(1, expr.arguments.len()); - let value = self.eval(h, ctx, expr.arguments[0])?; - match ctx.fires(value.clone()) { - None => Err(EvalContinuation::BlockFires(value)), - Some(result) => Ok(result), - } - } - Method::Create => { - assert_eq!(1, expr.arguments.len()); - let length = self.eval(h, ctx, expr.arguments[0])?; - Ok(Value::create_message(length)) - }, - Method::Length => { - todo!("implement") - }, - Method::Assert => { - let value = self.eval(h, ctx, expr.arguments[0])?; - if value.as_boolean().0 { - // Return bogus - Ok(Value::Unassigned) - } else { - // Failed assertion - Err(EvalContinuation::Inconsistent) - } - }, - Method::UserFunction => unimplemented!(), - Method::UserComponent => unreachable!(), - }, - Expression::Variable(expr) => self.get(h, ctx, expr.this.upcast()), - } - } -} - -type EvalResult = Result; -pub enum EvalContinuation { - Stepping, - Inconsistent, - Terminal, - SyncBlockStart, - SyncBlockEnd, - NewComponent(DefinitionId, Vec), - BlockFires(Value), - BlockGet(Value), - Put(Value, Value), -} - -#[derive(Debug, Clone)] -pub(crate) struct Prompt { - definition: DefinitionId, - store: Store, - position: Option, -} - -impl Prompt { - pub fn new(h: &Heap, def: DefinitionId, args: &Vec) -> Self { - let mut prompt = - Prompt { definition: def, store: Store::new(), position: Some((&h[def]).body().upcast()) }; - prompt.set_arguments(h, args); - prompt - } - fn set_arguments(&mut self, h: &Heap, args: &Vec) { - let def = &h[self.definition]; - let params = def.parameters(); - assert_eq!(params.len(), args.len()); - for (param, value) in params.iter().zip(args.iter()) { - let hparam = &h[*param]; - assert!(value.is_type_compatible(h, &hparam.parser_type.elements)); - self.store.initialize(h, param.upcast(), value.clone()); - } - } - pub fn step(&mut self, h: &Heap, ctx: &mut EvalContext) -> EvalResult { - if self.position.is_none() { - return Err(EvalContinuation::Terminal); - } - - let stmt = &h[self.position.unwrap()]; - match stmt { - Statement::Block(stmt) => { - // Continue to first statement - self.position = Some(stmt.first()); - Err(EvalContinuation::Stepping) - } - Statement::Local(stmt) => { - match stmt { - LocalStatement::Memory(stmt) => { - // Update store - self.store.initialize(h, stmt.variable.upcast(), Value::Unassigned); - } - 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(); - Err(EvalContinuation::Stepping) - } - Statement::Labeled(stmt) => { - // Continue to next statement - self.position = Some(stmt.body); - Err(EvalContinuation::Stepping) - } - Statement::If(stmt) => { - // Evaluate test - let value = self.store.eval(h, ctx, stmt.test)?; - // Continue with either branch - if value.as_boolean().0 { - self.position = Some(stmt.true_body.upcast()); - } else if let Some(false_body) = stmt.false_body { - self.position = Some(false_body.upcast()); - } else { - // No false body - self.position = Some(stmt.end_if.unwrap().upcast()); - } - Err(EvalContinuation::Stepping) - } - Statement::EndIf(stmt) => { - // Continue to next statement - self.position = stmt.next; - Err(EvalContinuation::Stepping) - } - Statement::While(stmt) => { - // Evaluate test - let value = self.store.eval(h, ctx, stmt.test)?; - // Either continue with body, or go to next - if value.as_boolean().0 { - self.position = Some(stmt.body.upcast()); - } else { - self.position = stmt.end_while.map(|x| x.upcast()); - } - Err(EvalContinuation::Stepping) - } - Statement::EndWhile(stmt) => { - // Continue to next statement - self.position = stmt.next; - Err(EvalContinuation::Stepping) - } - Statement::Synchronous(stmt) => { - // Continue to next statement, and signal upward - self.position = Some(stmt.body.upcast()); - Err(EvalContinuation::SyncBlockStart) - } - Statement::EndSynchronous(stmt) => { - // Continue to next statement, and signal upward - 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::Return(stmt) => { - // Evaluate expression - debug_assert_eq!(stmt.expressions.len(), 1); - let value = self.store.eval(h, ctx, stmt.expressions[0])?; - // Done with evaluation - Ok(value) - } - Statement::Goto(stmt) => { - // Continue to target - self.position = stmt.target.map(|x| x.upcast()); - Err(EvalContinuation::Stepping) - } - 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; - match &expr.method { - Method::UserComponent => { - Err(EvalContinuation::NewComponent(expr.definition, args)) - }, - _ => unreachable!("not a symbolic call expression") - } - } - Statement::Expression(stmt) => { - // Evaluate expression - let _value = self.store.eval(h, ctx, stmt.expression)?; - // Continue to next statement - self.position = stmt.next; - Err(EvalContinuation::Stepping) - } - } - } - // fn compute_function(_h: &Heap, _fun: FunctionId, _args: &Vec) -> Option { - // let mut prompt = Self::new(h, fun.upcast(), args); - // let mut context = EvalContext::None; - // loop { - // let result = prompt.step(h, &mut context); - // match result { - // Ok(val) => return Some(val), - // Err(cont) => match cont { - // EvalContinuation::Stepping => continue, - // EvalContinuation::Inconsistent => return None, - // // Functions never terminate without returning - // EvalContinuation::Terminal => unreachable!(), - // // Functions never encounter any blocking behavior - // EvalContinuation::SyncBlockStart => unreachable!(), - // EvalContinuation::SyncBlockEnd => unreachable!(), - // EvalContinuation::NewComponent(_, _) => unreachable!(), - // EvalContinuation::BlockFires(val) => unreachable!(), - // EvalContinuation::BlockGet(val) => unreachable!(), - // EvalContinuation::Put(port, msg) => unreachable!(), - // }, - // } - // } - // } -} - -// #[cfg(test)] -// mod tests { -// extern crate test_generator; - -// use std::fs::File; -// use std::io::Read; -// use std::path::Path; -// use test_generator::test_resources; - -// use super::*; - -// #[test_resources("testdata/eval/positive/*.pdl")] -// fn batch1(resource: &str) { -// let path = Path::new(resource); -// let expect = path.with_extension("txt"); -// let mut heap = Heap::new(); -// let mut source = InputSource::from_file(&path).unwrap(); -// let mut parser = Parser::new(&mut source); -// let pd = parser.parse(&mut heap).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(); -// let valstr: String = format!("{}", result); -// println!("{}", valstr); - -// let mut cev: Vec = Vec::new(); -// let mut f = File::open(expect).unwrap(); -// f.read_to_end(&mut cev).unwrap(); -// let lavstr = String::from_utf8_lossy(&cev); -// println!("{}", lavstr); - -// assert_eq!(valstr, lavstr); -// } -// } diff --git a/src/protocol/input_source.rs b/src/protocol/input_source.rs index 0c26d2f4f8e291ffc1998c2eb5f6dae7ede85787..e730f9ba3c38c91210d6eeea67924c7498124a88 100644 --- a/src/protocol/input_source.rs +++ b/src/protocol/input_source.rs @@ -446,24 +446,11 @@ impl ParseError { )) } } - pub fn with_at_pos(mut self, error_type: StatementKind, source: &InputSource, position: InputPosition, message: String) -> Self { - self.statements.push(ErrorStatement::from_source_at_pos(error_type, source, position, message)); - self - } - pub fn with_at_span(mut self, error_type: StatementKind, source: &InputSource, span: InputSpan, message: String) -> Self { self.statements.push(ErrorStatement::from_source_at_span(error_type, source, span, message.to_string())); self } - pub fn with_info_at_pos(self, source: &InputSource, position: InputPosition, msg: String) -> Self { - self.with_at_pos(StatementKind::Info, source, position, msg) - } - - pub fn with_info_str_at_pos(self, source: &InputSource, position: InputPosition, msg: &str) -> Self { - self.with_at_pos(StatementKind::Info, source, position, msg.to_string()) - } - pub fn with_info_at_span(self, source: &InputSource, span: InputSpan, msg: String) -> Self { self.with_at_span(StatementKind::Info, source, span, msg) } diff --git a/src/protocol/mod.rs b/src/protocol/mod.rs index 87fa277bad3bfc9d4ed0b3c8ea381e10d7033a43..0a4427df8bd9cc7fe1bc6395f40b123590c8049b 100644 --- a/src/protocol/mod.rs +++ b/src/protocol/mod.rs @@ -337,10 +337,6 @@ impl EvalContext<'_> { EvalContext::None => unreachable!(), EvalContext::Nonsync(_) => unreachable!(), EvalContext::Sync(context) => match port { - Value::Output(port) => { - debug_assert!(false, "Getting from an output port? Am I mad?"); - unreachable!(); - } Value::Input(port) => { let payload = context.read_msg(port); if payload.is_none() { return None; } @@ -367,8 +363,7 @@ impl EvalContext<'_> { Value::Output(port) => { context.did_put_or_get(port) }, - Value::Input(_) => unreachable!("did_put on input port"), - _ => unreachable!("did_put on non-port value") + _ => unreachable!("did_put on non-output port value") } } } diff --git a/src/protocol/parser/mod.rs b/src/protocol/parser/mod.rs index eec169504fa74878f086f8d9c160003360749417..a9f8ea8a948cce14f0dded45d58f1240bdac95ce 100644 --- a/src/protocol/parser/mod.rs +++ b/src/protocol/parser/mod.rs @@ -31,7 +31,6 @@ use crate::protocol::ast_printer::ASTWriter; #[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] pub enum ModuleCompilationPhase { - Source, // only source is set Tokenized, // source is tokenized SymbolsScanned, // all definitions are linked to their type class ImportsResolved, // all imports are added to the symbol table @@ -59,18 +58,22 @@ pub struct PassCtx<'a> { } pub struct Parser { + // Storage of all information created/gathered during compilation. pub(crate) heap: Heap, - pub(crate) string_pool: StringPool, + pub(crate) string_pool: StringPool, // Do not deallocate, holds all strings pub(crate) modules: Vec, pub(crate) symbol_table: SymbolTable, pub(crate) type_table: TypeTable, - // Compiler passes + // Compiler passes, used as little state machine that keep their memory + // around. pass_tokenizer: PassTokenizer, pass_symbols: PassSymbols, pass_import: PassImport, pass_definitions: PassDefinitions, pass_validation: PassValidationLinking, pass_typing: PassTyping, + // Compiler options + pub write_ast_to: Option, } impl Parser { @@ -87,6 +90,7 @@ impl Parser { pass_definitions: PassDefinitions::new(), pass_validation: PassValidationLinking::new(), pass_typing: PassTyping::new(), + write_ast_to: None, }; parser.symbol_table.insert_scope(None, SymbolScope::Global); @@ -131,7 +135,7 @@ impl Parser { ], quick_type(&[PTV::UInt32]) // TODO: @PtrInt )); - insert_builtin_function(&mut parser, "assert", &[], |id| ( + insert_builtin_function(&mut parser, "assert", &[], |_id| ( vec![ ("condition", quick_type(&[PTV::Bool])), ], @@ -227,9 +231,11 @@ impl Parser { } } - // let mut writer = ASTWriter::new(); - // let mut file = std::fs::File::create(std::path::Path::new("ast.txt")).unwrap(); - // writer.write_ast(&mut file, &self.heap); + if let Some(filename) = &self.write_ast_to { + let mut writer = ASTWriter::new(); + let mut file = std::fs::File::create(std::path::Path::new(filename)).unwrap(); + writer.write_ast(&mut file, &self.heap); + } Ok(()) } diff --git a/src/protocol/parser/pass_typing.rs b/src/protocol/parser/pass_typing.rs index c490a2a446035402fd5845e6b00d04daeba2e2c7..5bb7e41f992484673c1511184ce7d95a750fe4a5 100644 --- a/src/protocol/parser/pass_typing.rs +++ b/src/protocol/parser/pass_typing.rs @@ -1039,13 +1039,13 @@ impl Visitor2 for PassTyping { debug_log!("Visiting function '{}': {}", func_def.identifier.value.as_str(), id.0.index); if debug_log_enabled!() { debug_log!("Polymorphic variables:"); - for (idx, poly_var) in self.poly_vars.iter().enumerate() { + for (_idx, poly_var) in self.poly_vars.iter().enumerate() { let mut infer_type_parts = Vec::new(); for concrete_part in &poly_var.parts { infer_type_parts.push(InferenceTypePart::from(*concrete_part)); } - let infer_type = InferenceType::new(false, true, infer_type_parts); - debug_log!(" - [{:03}] {:?}", idx, infer_type.display_name(&ctx.heap)); + let _infer_type = InferenceType::new(false, true, infer_type_parts); + debug_log!(" - [{:03}] {:?}", _idx, _infer_type.display_name(&ctx.heap)); } } debug_log!("{}", "-".repeat(50)); @@ -1394,7 +1394,8 @@ impl Visitor2 for PassTyping { } impl PassTyping { - fn temp_get_display_name(&self, ctx: &Ctx, expr_id: ExpressionId) -> String { + #[allow(dead_code)] // used when debug flag at the top of this file is true. + fn debug_get_display_name(&self, ctx: &Ctx, expr_id: ExpressionId) -> String { let expr_idx = ctx.heap[expr_id].get_unique_id_in_definition(); let expr_type = &self.expr_types[expr_idx as usize].expr_type; expr_type.display_name(&ctx.heap) @@ -1619,9 +1620,9 @@ impl PassTyping { debug_log!("Assignment expr '{:?}': {}", expr.operation, upcast_id.index); debug_log!(" * Before:"); - debug_log!(" - Arg1 type: {}", self.temp_get_display_name(ctx, arg1_expr_id)); - debug_log!(" - Arg2 type: {}", self.temp_get_display_name(ctx, arg2_expr_id)); - debug_log!(" - Expr type: {}", self.temp_get_display_name(ctx, upcast_id)); + debug_log!(" - Arg1 type: {}", self.debug_get_display_name(ctx, arg1_expr_id)); + debug_log!(" - Arg2 type: {}", self.debug_get_display_name(ctx, arg2_expr_id)); + debug_log!(" - Expr type: {}", self.debug_get_display_name(ctx, upcast_id)); // Assignment does not return anything (it operates like a statement) let progress_expr = self.apply_forced_constraint(ctx, upcast_id, &VOID_TEMPLATE)?; @@ -1643,9 +1644,9 @@ impl PassTyping { debug_assert!(if progress_forced { progress_arg2 } else { true }); debug_log!(" * After:"); - debug_log!(" - Arg1 type [{}]: {}", progress_forced || progress_arg1, self.temp_get_display_name(ctx, arg1_expr_id)); - debug_log!(" - Arg2 type [{}]: {}", progress_arg2, self.temp_get_display_name(ctx, arg2_expr_id)); - debug_log!(" - Expr type [{}]: {}", progress_expr, self.temp_get_display_name(ctx, upcast_id)); + debug_log!(" - Arg1 type [{}]: {}", progress_forced || progress_arg1, self.debug_get_display_name(ctx, arg1_expr_id)); + debug_log!(" - Arg2 type [{}]: {}", progress_arg2, self.debug_get_display_name(ctx, arg2_expr_id)); + debug_log!(" - Expr type [{}]: {}", progress_expr, self.debug_get_display_name(ctx, upcast_id)); if progress_expr { self.queue_expr_parent(ctx, upcast_id); } @@ -1682,9 +1683,9 @@ impl PassTyping { debug_log!("Conditional expr: {}", upcast_id.index); debug_log!(" * Before:"); - debug_log!(" - Arg1 type: {}", self.temp_get_display_name(ctx, arg1_expr_id)); - debug_log!(" - Arg2 type: {}", self.temp_get_display_name(ctx, arg2_expr_id)); - debug_log!(" - Expr type: {}", self.temp_get_display_name(ctx, upcast_id)); + debug_log!(" - Arg1 type: {}", self.debug_get_display_name(ctx, arg1_expr_id)); + debug_log!(" - Arg2 type: {}", self.debug_get_display_name(ctx, arg2_expr_id)); + debug_log!(" - Expr type: {}", self.debug_get_display_name(ctx, upcast_id)); // I keep confusing myself: this applies equality of types between the // condition branches' types, and the result from the conditional @@ -1695,9 +1696,9 @@ impl PassTyping { )?; debug_log!(" * After:"); - debug_log!(" - Arg1 type [{}]: {}", progress_arg1, self.temp_get_display_name(ctx, arg1_expr_id)); - debug_log!(" - Arg2 type [{}]: {}", progress_arg2, self.temp_get_display_name(ctx, arg2_expr_id)); - debug_log!(" - Expr type [{}]: {}", progress_expr, self.temp_get_display_name(ctx, upcast_id)); + debug_log!(" - Arg1 type [{}]: {}", progress_arg1, self.debug_get_display_name(ctx, arg1_expr_id)); + debug_log!(" - Arg2 type [{}]: {}", progress_arg2, self.debug_get_display_name(ctx, arg2_expr_id)); + debug_log!(" - Expr type [{}]: {}", progress_expr, self.debug_get_display_name(ctx, upcast_id)); if progress_expr { self.queue_expr_parent(ctx, upcast_id); } if progress_arg1 { self.queue_expr(ctx, arg1_expr_id); } @@ -1718,9 +1719,9 @@ impl PassTyping { debug_log!("Binary expr '{:?}': {}", expr.operation, upcast_id.index); debug_log!(" * Before:"); - debug_log!(" - Arg1 type: {}", self.temp_get_display_name(ctx, arg1_id)); - debug_log!(" - Arg2 type: {}", self.temp_get_display_name(ctx, arg2_id)); - debug_log!(" - Expr type: {}", self.temp_get_display_name(ctx, upcast_id)); + debug_log!(" - Arg1 type: {}", self.debug_get_display_name(ctx, arg1_id)); + debug_log!(" - Arg2 type: {}", self.debug_get_display_name(ctx, arg2_id)); + debug_log!(" - Expr type: {}", self.debug_get_display_name(ctx, upcast_id)); let (progress_expr, progress_arg1, progress_arg2) = match expr.operation { BO::Concatenate => { @@ -1787,9 +1788,9 @@ impl PassTyping { }; debug_log!(" * After:"); - debug_log!(" - Arg1 type [{}]: {}", progress_arg1, self.temp_get_display_name(ctx, arg1_id)); - debug_log!(" - Arg2 type [{}]: {}", progress_arg2, self.temp_get_display_name(ctx, arg2_id)); - debug_log!(" - Expr type [{}]: {}", progress_expr, self.temp_get_display_name(ctx, upcast_id)); + debug_log!(" - Arg1 type [{}]: {}", progress_arg1, self.debug_get_display_name(ctx, arg1_id)); + debug_log!(" - Arg2 type [{}]: {}", progress_arg2, self.debug_get_display_name(ctx, arg2_id)); + debug_log!(" - Expr type [{}]: {}", progress_expr, self.debug_get_display_name(ctx, upcast_id)); if progress_expr { self.queue_expr_parent(ctx, upcast_id); } if progress_arg1 { self.queue_expr(ctx, arg1_id); } @@ -1807,8 +1808,8 @@ impl PassTyping { debug_log!("Unary expr '{:?}': {}", expr.operation, upcast_id.index); debug_log!(" * Before:"); - debug_log!(" - Arg type: {}", self.temp_get_display_name(ctx, arg_id)); - debug_log!(" - Expr type: {}", self.temp_get_display_name(ctx, upcast_id)); + debug_log!(" - Arg type: {}", self.debug_get_display_name(ctx, arg_id)); + debug_log!(" - Expr type: {}", self.debug_get_display_name(ctx, upcast_id)); let (progress_expr, progress_arg) = match expr.operation { UO::Positive | UO::Negative => { @@ -1836,8 +1837,8 @@ impl PassTyping { }; debug_log!(" * After:"); - debug_log!(" - Arg type [{}]: {}", progress_arg, self.temp_get_display_name(ctx, arg_id)); - debug_log!(" - Expr type [{}]: {}", progress_expr, self.temp_get_display_name(ctx, upcast_id)); + debug_log!(" - Arg type [{}]: {}", progress_arg, self.debug_get_display_name(ctx, arg_id)); + debug_log!(" - Expr type [{}]: {}", progress_expr, self.debug_get_display_name(ctx, upcast_id)); if progress_expr { self.queue_expr_parent(ctx, upcast_id); } if progress_arg { self.queue_expr(ctx, arg_id); } @@ -1853,9 +1854,9 @@ impl PassTyping { debug_log!("Indexing expr: {}", upcast_id.index); debug_log!(" * Before:"); - debug_log!(" - Subject type: {}", self.temp_get_display_name(ctx, subject_id)); - debug_log!(" - Index type: {}", self.temp_get_display_name(ctx, index_id)); - debug_log!(" - Expr type: {}", self.temp_get_display_name(ctx, upcast_id)); + debug_log!(" - Subject type: {}", self.debug_get_display_name(ctx, subject_id)); + debug_log!(" - Index type: {}", self.debug_get_display_name(ctx, index_id)); + debug_log!(" - Expr type: {}", self.debug_get_display_name(ctx, upcast_id)); // Make sure subject is arraylike and index is integerlike let progress_subject_base = self.apply_template_constraint(ctx, subject_id, &ARRAYLIKE_TEMPLATE)?; @@ -1866,9 +1867,9 @@ impl PassTyping { self.apply_equal2_constraint(ctx, upcast_id, upcast_id, 0, subject_id, 1)?; debug_log!(" * After:"); - debug_log!(" - Subject type [{}]: {}", progress_subject_base || progress_subject, self.temp_get_display_name(ctx, subject_id)); - debug_log!(" - Index type [{}]: {}", progress_index, self.temp_get_display_name(ctx, index_id)); - debug_log!(" - Expr type [{}]: {}", progress_expr, self.temp_get_display_name(ctx, upcast_id)); + debug_log!(" - Subject type [{}]: {}", progress_subject_base || progress_subject, self.debug_get_display_name(ctx, subject_id)); + debug_log!(" - Index type [{}]: {}", progress_index, self.debug_get_display_name(ctx, index_id)); + debug_log!(" - Expr type [{}]: {}", progress_expr, self.debug_get_display_name(ctx, upcast_id)); if progress_expr { self.queue_expr_parent(ctx, upcast_id); } if progress_subject_base || progress_subject { self.queue_expr(ctx, subject_id); } @@ -1886,10 +1887,10 @@ impl PassTyping { debug_log!("Slicing expr: {}", upcast_id.index); debug_log!(" * Before:"); - debug_log!(" - Subject type: {}", self.temp_get_display_name(ctx, subject_id)); - debug_log!(" - FromIdx type: {}", self.temp_get_display_name(ctx, from_id)); - debug_log!(" - ToIdx type: {}", self.temp_get_display_name(ctx, to_id)); - debug_log!(" - Expr type: {}", self.temp_get_display_name(ctx, upcast_id)); + debug_log!(" - Subject type: {}", self.debug_get_display_name(ctx, subject_id)); + debug_log!(" - FromIdx type: {}", self.debug_get_display_name(ctx, from_id)); + debug_log!(" - ToIdx type: {}", self.debug_get_display_name(ctx, to_id)); + debug_log!(" - Expr type: {}", self.debug_get_display_name(ctx, upcast_id)); // Make sure subject is arraylike and indices are of equal integerlike let progress_subject_base = self.apply_template_constraint(ctx, subject_id, &ARRAYLIKE_TEMPLATE)?; @@ -1903,10 +1904,10 @@ impl PassTyping { debug_log!(" * After:"); - debug_log!(" - Subject type [{}]: {}", progress_subject_base || progress_subject, self.temp_get_display_name(ctx, subject_id)); - debug_log!(" - FromIdx type [{}]: {}", progress_idx_base || progress_from, self.temp_get_display_name(ctx, from_id)); - debug_log!(" - ToIdx type [{}]: {}", progress_idx_base || progress_to, self.temp_get_display_name(ctx, to_id)); - debug_log!(" - Expr type [{}]: {}", progress_expr, self.temp_get_display_name(ctx, upcast_id)); + debug_log!(" - Subject type [{}]: {}", progress_subject_base || progress_subject, self.debug_get_display_name(ctx, subject_id)); + debug_log!(" - FromIdx type [{}]: {}", progress_idx_base || progress_from, self.debug_get_display_name(ctx, from_id)); + debug_log!(" - ToIdx type [{}]: {}", progress_idx_base || progress_to, self.debug_get_display_name(ctx, to_id)); + debug_log!(" - Expr type [{}]: {}", progress_expr, self.debug_get_display_name(ctx, upcast_id)); if progress_expr_base || progress_expr { self.queue_expr_parent(ctx, upcast_id); } if progress_subject_base || progress_subject { self.queue_expr(ctx, subject_id); } @@ -1921,8 +1922,8 @@ impl PassTyping { debug_log!("Select expr: {}", upcast_id.index); debug_log!(" * Before:"); - debug_log!(" - Subject type: {}", self.temp_get_display_name(ctx, ctx.heap[id].subject)); - debug_log!(" - Expr type: {}", self.temp_get_display_name(ctx, upcast_id)); + debug_log!(" - Subject type: {}", self.debug_get_display_name(ctx, ctx.heap[id].subject)); + debug_log!(" - Expr type: {}", self.debug_get_display_name(ctx, upcast_id)); let subject_id = ctx.heap[id].subject; let subject_expr_idx = ctx.heap[subject_id].get_unique_id_in_definition(); @@ -2074,8 +2075,8 @@ impl PassTyping { if progress_expr { self.queue_expr_parent(ctx, upcast_id); } debug_log!(" * After:"); - debug_log!(" - Subject type [{}]: {}", progress_subject, self.temp_get_display_name(ctx, subject_id)); - debug_log!(" - Expr type [{}]: {}", progress_expr, self.temp_get_display_name(ctx, upcast_id)); + debug_log!(" - Subject type [{}]: {}", progress_subject, self.debug_get_display_name(ctx, subject_id)); + debug_log!(" - Expr type [{}]: {}", progress_expr, self.debug_get_display_name(ctx, upcast_id)); Ok(()) } @@ -2088,7 +2089,7 @@ impl PassTyping { debug_log!("Literal expr: {}", upcast_id.index); debug_log!(" * Before:"); - debug_log!(" - Expr type: {}", self.temp_get_display_name(ctx, upcast_id)); + debug_log!(" - Expr type: {}", self.debug_get_display_name(ctx, upcast_id)); let progress_expr = match &expr.value { Literal::Null => { @@ -2334,7 +2335,7 @@ impl PassTyping { let expr_elements = data.clone(); // TODO: @performance debug_log!("Array expr ({} elements): {}", expr_elements.len(), upcast_id.index); debug_log!(" * Before:"); - debug_log!(" - Expr type: {}", self.temp_get_display_name(ctx, upcast_id)); + debug_log!(" - Expr type: {}", self.debug_get_display_name(ctx, upcast_id)); // All elements should have an equal type let progress = self.apply_equal_n_constraint(ctx, upcast_id, &expr_elements)?; @@ -2361,14 +2362,14 @@ impl PassTyping { } debug_log!(" * After:"); - debug_log!(" - Expr type [{}]: {}", progress_expr, self.temp_get_display_name(ctx, upcast_id)); + debug_log!(" - Expr type [{}]: {}", progress_expr, self.debug_get_display_name(ctx, upcast_id)); progress_expr }, }; debug_log!(" * After:"); - debug_log!(" - Expr type: {}", self.temp_get_display_name(ctx, upcast_id)); + debug_log!(" - Expr type: {}", self.debug_get_display_name(ctx, upcast_id)); if progress_expr { self.queue_expr_parent(ctx, upcast_id); } @@ -2382,8 +2383,8 @@ impl PassTyping { debug_log!("Casting expr: {}", upcast_id.index); debug_log!(" * Before:"); - debug_log!(" - Expr type: {}", self.temp_get_display_name(ctx, upcast_id)); - debug_log!(" - Subject type: {}", self.temp_get_display_name(ctx, expr.subject)); + debug_log!(" - Expr type: {}", self.debug_get_display_name(ctx, upcast_id)); + debug_log!(" - Subject type: {}", self.debug_get_display_name(ctx, expr.subject)); // The cast expression might have its output type fixed by the // programmer, so apply that type to the output. Apart from that casting @@ -2400,7 +2401,7 @@ impl PassTyping { // Check if the two types are compatible debug_log!(" * After:"); - debug_log!(" - Expr type [{}]: {}", expr_progress, self.temp_get_display_name(ctx, upcast_id)); + debug_log!(" - Expr type [{}]: {}", expr_progress, self.debug_get_display_name(ctx, upcast_id)); debug_log!(" - Note that the subject type can never be inferred"); debug_log!(" * Decision:"); @@ -2461,7 +2462,7 @@ impl PassTyping { debug_log!("Call expr '{}': {}", ctx.heap[expr.definition].identifier().value.as_str(), upcast_id.index); debug_log!(" * Before:"); - debug_log!(" - Expr type: {}", self.temp_get_display_name(ctx, upcast_id)); + debug_log!(" - Expr type: {}", self.debug_get_display_name(ctx, upcast_id)); debug_log!(" * During (inferring types from arguments and return type):"); let extra = &mut self.extra_data[extra_idx as usize]; @@ -2561,7 +2562,7 @@ impl PassTyping { } debug_log!(" * After:"); - debug_log!(" - Expr type: {}", self.temp_get_display_name(ctx, upcast_id)); + debug_log!(" - Expr type: {}", self.debug_get_display_name(ctx, upcast_id)); Ok(()) } @@ -2575,7 +2576,7 @@ impl PassTyping { debug_log!("Variable expr '{}': {}", ctx.heap[var_id].identifier.value.as_str(), upcast_id.index); debug_log!(" * Before:"); debug_log!(" - Var type: {}", self.var_types.get(&var_id).unwrap().var_type.display_name(&ctx.heap)); - debug_log!(" - Expr type: {}", self.temp_get_display_name(ctx, upcast_id)); + debug_log!(" - Expr type: {}", self.debug_get_display_name(ctx, upcast_id)); // Retrieve shared variable type and expression type and apply inference let var_data = self.var_types.get_mut(&var_id).unwrap(); @@ -2660,7 +2661,7 @@ impl PassTyping { debug_log!(" * After:"); debug_log!(" - Var type [{}]: {}", progress_var, self.var_types.get(&var_id).unwrap().var_type.display_name(&ctx.heap)); - debug_log!(" - Expr type [{}]: {}", progress_expr, self.temp_get_display_name(ctx, upcast_id)); + debug_log!(" - Expr type [{}]: {}", progress_expr, self.debug_get_display_name(ctx, upcast_id)); Ok(()) diff --git a/src/protocol/parser/symbol_table.rs b/src/protocol/parser/symbol_table.rs index 1e0b7cd6a6b1b9a74af356007f4d81690deba7aa..0d64b4d7d5515fa4c0c530f8dc43dff3d74f36b6 100644 --- a/src/protocol/parser/symbol_table.rs +++ b/src/protocol/parser/symbol_table.rs @@ -55,7 +55,6 @@ impl DefinitionClass { } struct ScopedSymbols { - scope: SymbolScope, parent_scope: Option, child_scopes: Vec, symbols: Vec, @@ -197,7 +196,6 @@ impl SymbolTable { } let scope = ScopedSymbols { - scope: new_scope, parent_scope, child_scopes: Vec::with_capacity(RESERVED_SYMBOLS), symbols: Vec::with_capacity(RESERVED_SYMBOLS) diff --git a/src/protocol/parser/type_table.rs b/src/protocol/parser/type_table.rs index f178a29928c532aefee9a3eec0892ea1bec350c3..0bb7a04d0837de12c17fe319d6a67f6a8da476af 100644 --- a/src/protocol/parser/type_table.rs +++ b/src/protocol/parser/type_table.rs @@ -1,5 +1,5 @@ use std::fmt::{Formatter, Result as FmtResult}; -use std::collections::{HashMap, VecDeque}; +use std::collections::HashMap; use crate::protocol::ast::*; use crate::protocol::parser::symbol_table::SymbolScope; @@ -161,7 +161,6 @@ pub struct ProcedureMonomorph { /// variants to be equal to one another. pub struct EnumType { pub variants: Vec, - pub representation: PrimitiveType, pub monomorphs: Vec, } @@ -176,7 +175,6 @@ pub struct EnumVariant { /// a single subtype. pub struct UnionType { pub variants: Vec, - pub tag_representation: PrimitiveType, pub monomorphs: Vec, } @@ -287,9 +285,6 @@ pub struct TypeTable { /// Iterator over `(module, definition)` tuples used as workspace to make sure /// that each base definition of all a type's subtypes are resolved. iter: TypeIterator, - /// Iterator over `parser type`s during the process where `parser types` are - /// resolved into a `(module, definition)` tuple. - parser_type_iter: VecDeque, } impl TypeTable { @@ -297,8 +292,7 @@ impl TypeTable { pub(crate) fn new() -> Self { Self{ lookup: HashMap::new(), - iter: TypeIterator::new(), - parser_type_iter: VecDeque::with_capacity(64), + iter: TypeIterator::new(), } } @@ -307,7 +301,6 @@ impl TypeTable { debug_assert!(modules.iter().all(|m| m.phase >= ModuleCompilationPhase::DefinitionsParsed)); debug_assert!(self.lookup.is_empty()); debug_assert!(self.iter.top().is_none()); - debug_assert!(self.parser_type_iter.is_empty()); if cfg!(debug_assertions) { for (index, module) in modules.iter().enumerate() { @@ -514,7 +507,6 @@ impl TypeTable { ast_definition: definition_id, definition: DefinedTypeVariant::Enum(EnumType{ variants, - representation: Self::enum_tag_type(min_enum_value, max_enum_value), monomorphs: Vec::new(), }), poly_vars, @@ -592,7 +584,6 @@ impl TypeTable { ast_definition: definition_id, definition: DefinedTypeVariant::Union(UnionType{ variants, - tag_representation: Self::enum_tag_type(-1, tag_value), monomorphs: Vec::new(), }), poly_vars, @@ -978,19 +969,4 @@ impl TypeTable { } } } - - fn enum_tag_type(min_tag_value: i64, max_tag_value: i64) -> PrimitiveType { - // TODO: @consistency tag values should be handled correctly - debug_assert!(min_tag_value <= max_tag_value); - let abs_max_value = min_tag_value.abs().max(max_tag_value.abs()); - if abs_max_value <= u8::max_value() as i64 { - PrimitiveType::Byte - } else if abs_max_value <= u16::max_value() as i64 { - PrimitiveType::Short - } else if abs_max_value <= u32::max_value() as i64 { - PrimitiveType::Int - } else { - PrimitiveType::Long - } - } } \ No newline at end of file diff --git a/src/protocol/tests/utils.rs b/src/protocol/tests/utils.rs index a30ad950705bd70ef81abb8446908270ed6d7b8a..072e3601ba67992e8ee3874a49f4f94f6130f906 100644 --- a/src/protocol/tests/utils.rs +++ b/src/protocol/tests/utils.rs @@ -589,7 +589,6 @@ impl<'a> FunctionTester<'a> { pub(crate) fn call_ok(self, expected_result: Option) -> Self { use crate::protocol::*; - use crate::runtime::*; let (prompt, result) = self.eval_until_end(); match result {