diff --git a/src/flattening/mod.rs b/src/flattening/mod.rs index 6b508b8..15c6d2e 100644 --- a/src/flattening/mod.rs +++ b/src/flattening/mod.rs @@ -747,7 +747,7 @@ impl<'l> FlatteningContext<'l> { } } else if kind == SUS.array_type_kind { self.flatten_array_type_tree(span, cursor) - } else {cursor.unreachable(&self.linker.file.file_text)} + } else {cursor.could_not_match()} } fn flatten_module_or_type_tree(&mut self, cursor : &mut Cursor<'l>) -> ModuleOrWrittenType { @@ -767,17 +767,17 @@ impl<'l> FlatteningContext<'l> { } } else if kind == SUS.array_type_kind { ModuleOrWrittenType::WrittenType(self.flatten_array_type_tree(span, cursor)) - } else {cursor.unreachable(&self.linker.file.file_text)} + } else {cursor.could_not_match()} } - fn flatten_declaration_tree(&mut self, fallback_identifier_type : IdentifierType, declaration_itself_is_not_written_to : bool, cursor : &mut Cursor<'l>) -> FlatID { + fn flatten_declaration_tree(&mut self, fallback_identifier_type : IdentifierType, declaration_itself_is_not_written_to : bool, cursor : &mut Cursor<'l>) -> FlatID { let read_only = fallback_identifier_type == IdentifierType::Input; cursor.go_down(SUS.declaration_kind, |cursor| { let identifier_type = cursor.optional_field(SUS.declaration_modifiers_field, |cursor| { let (modifier_kind, modifier_span) = cursor.kind_span(); - if fallback_identifier_type != IdentifierType::Local { + if !ALLOW_MODIFIERS { self.errors.error_basic(modifier_span, "Inputs and outputs of a module cannot be decorated with 'state' or 'gen'"); return fallback_identifier_type; } @@ -787,7 +787,7 @@ impl<'l> FlatteningContext<'l> { } else if modifier_kind == SUS.gen_kw { IdentifierType::Generative } else { - cursor.unreachable(&self.linker.file.file_text) + cursor.could_not_match() } }).unwrap_or(fallback_identifier_type); @@ -907,7 +907,7 @@ impl<'l> FlatteningContext<'l> { // Function desugaring or using threw an error WireSource::Constant(Value::Error) } else { - cursor.unreachable(&self.linker.file.file_text) + cursor.could_not_match() }; let wire_instance = WireInstance{ @@ -943,7 +943,32 @@ impl<'l> FlatteningContext<'l> { } else if kind == SUS.binary_op_kind {self.errors.error_basic(span, "Cannot assign to the result of an operator"); None } else if kind == SUS.func_call_kind {self.errors.error_basic(span, "Cannot assign to submodule call"); None } else if kind == SUS.global_identifier_kind {self.errors.error_basic(span, "Cannot assign to global"); None - } else {cursor.unreachable(&self.linker.file.file_text)} + } else {cursor.could_not_match()} + } + + fn flatten_if_statement(&mut self, cursor : &mut Cursor<'l>) { + cursor.go_down(SUS.if_statement_kind, |cursor| { + let condition = cursor.field(SUS.condition_field, |cursor| self.flatten_expr_tree(cursor)); + + let if_id = self.instructions.alloc(Instruction::IfStatement(IfStatement{condition, then_start : UUID::PLACEHOLDER, then_end_else_start : UUID::PLACEHOLDER, else_end : UUID::PLACEHOLDER})); + let then_start = self.instructions.get_next_alloc_id(); + + cursor.field(SUS.then_block_field, |cursor| self.flatten_code_tree(cursor)); + let then_end_else_start = self.instructions.get_next_alloc_id(); + cursor.optional_field(SUS.else_block_field, |cursor| { + if cursor.kind() == SUS.if_statement_kind { + self.flatten_if_statement(cursor); // Chained if statements + } else { + self.flatten_code_tree(cursor) + } + }); + let else_end = self.instructions.get_next_alloc_id(); + + let Instruction::IfStatement(if_stmt) = &mut self.instructions[if_id] else {unreachable!()}; + if_stmt.then_start = then_start; + if_stmt.then_end_else_start = then_end_else_start; + if_stmt.else_end = else_end; + }) } fn flatten_code_tree(&mut self, cursor : &mut Cursor<'l>) { @@ -1011,41 +1036,26 @@ impl<'l> FlatteningContext<'l> { } else if kind == SUS.block_kind { self.flatten_code_tree(cursor); } else if kind == SUS.if_statement_kind { - //Statement::If{condition : condition_expr, then, els} => { - /*let condition = self.flatten_expr(condition_expr); - - let if_id = self.instructions.alloc(Instruction::IfStatement(IfStatement{condition, then_start : UUID::PLACEHOLDER, then_end_else_start : UUID::PLACEHOLDER, else_end : UUID::PLACEHOLDER})); - let then_start = self.instructions.get_next_alloc_id(); - - self.flatten_code(then); - let then_end_else_start = self.instructions.get_next_alloc_id(); - if let Some(e) = els { - self.flatten_code(e); - } - let else_end = self.instructions.get_next_alloc_id(); - - let Instruction::IfStatement(if_stmt) = &mut self.instructions[if_id] else {cursor.unreachable(&self.linker.file.file_text)}; - if_stmt.then_start = then_start; - if_stmt.then_end_else_start = then_end_else_start; - if_stmt.else_end = else_end;*/ + self.flatten_if_statement(cursor); } else if kind == SUS.for_statement_kind { - //Statement::For{var, range, code} => { - /*let loop_var_decl = self.flatten_declaration::(var, true, true); + cursor.go_down_no_check(|cursor| { + let loop_var_decl = cursor.field(SUS.for_decl_field, |cursor| self.flatten_declaration_tree::(IdentifierType::Local, true, cursor)); - let start = self.flatten_expr(&range.from); - let end = self.flatten_expr(&range.to); - - let for_id = self.instructions.alloc(Instruction::ForStatement(ForStatement{loop_var_decl, start, end, loop_body: UUIDRange(UUID::PLACEHOLDER, UUID::PLACEHOLDER)})); + let start = cursor.field(SUS.from_field, |cursor| self.flatten_expr_tree(cursor)); + let end = cursor.field(SUS.to_field, |cursor| self.flatten_expr_tree(cursor)); + + let for_id = self.instructions.alloc(Instruction::ForStatement(ForStatement{loop_var_decl, start, end, loop_body: UUIDRange(UUID::PLACEHOLDER, UUID::PLACEHOLDER)})); - let code_start = self.instructions.get_next_alloc_id(); + let code_start = self.instructions.get_next_alloc_id(); - self.flatten_code(code); - - let code_end = self.instructions.get_next_alloc_id(); + cursor.field(SUS.block_field, |cursor| self.flatten_code_tree(cursor)); + + let code_end = self.instructions.get_next_alloc_id(); - let Instruction::ForStatement(for_stmt) = &mut self.instructions[for_id] else {cursor.unreachable(&self.linker.file.file_text)}; + let Instruction::ForStatement(for_stmt) = &mut self.instructions[for_id] else {unreachable!()}; - for_stmt.loop_body = UUIDRange(code_start, code_end);*/ + for_stmt.loop_body = UUIDRange(code_start, code_end); + }) } }); } @@ -1080,7 +1090,7 @@ impl<'l> FlatteningContext<'l> { let (kind, span) = cursor.kind_span(); if kind == SUS.declaration_kind { - let root = self.flatten_declaration_tree::(IdentifierType::Local, true, cursor); + let root = self.flatten_declaration_tree::(IdentifierType::Local, true, cursor); let flat_root_decl = self.instructions[root].extract_wire_declaration(); Some(ConnectionWrite{root, root_span : flat_root_decl.name_span, path: Vec::new(), span, is_declared_in_this_module: true, write_modifiers}) } else { // It's _expression @@ -1111,7 +1121,7 @@ impl<'l> FlatteningContext<'l> { let kind = cursor.kind(); if kind == SUS.declaration_kind { - let _ = self.flatten_declaration_tree::(IdentifierType::Local, true, cursor); + let _ = self.flatten_declaration_tree::(IdentifierType::Local, true, cursor); } else { // It's _expression let _ = self.flatten_expr_tree(cursor); } @@ -1123,7 +1133,7 @@ impl<'l> FlatteningContext<'l> { fn flatten_declaration_list_tree(&mut self, is_input : bool, cursor : &mut Cursor<'l>) { cursor.list(SUS.declaration_list_kind, |cursor| { let identifier_type = if is_input {IdentifierType::Input} else {IdentifierType::Output}; - self.flatten_declaration_tree::(identifier_type, true, cursor); + self.flatten_declaration_tree::(identifier_type, true, cursor); }) } @@ -1467,7 +1477,7 @@ impl FlattenedModule { let global_resolver = GlobalResolver::new(linker, module.link_info.file); // The given span should correspond perfectly to this, so impossible we don't find the node. - let mut cursor = Cursor::new_for_node(&global_resolver.file.tree, module.link_info.span, SUS.module_kind); + let mut cursor = Cursor::new_for_node(&global_resolver.file.tree, &global_resolver.file.file_text, module.link_info.span, SUS.module_kind); let mut context = FlatteningContext{ instructions : FlatAlloc::new(), diff --git a/src/parser.rs b/src/parser.rs index 88660d5..769283e 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -815,7 +815,6 @@ pub struct SusTreeSitterSingleton { pub func_call_kind : u16, pub parenthesis_expression_kind : u16, pub array_bracket_expression_kind : u16, - pub range_kind : u16, pub block_kind : u16, pub decl_assign_statement_kind : u16, pub assign_left_side_kind : u16, @@ -852,7 +851,6 @@ pub struct SusTreeSitterSingleton { pub then_block_field : NonZeroU16, pub else_block_field : NonZeroU16, pub for_decl_field : NonZeroU16, - pub for_range_field : NonZeroU16, pub content_field : NonZeroU16, pub item_field : NonZeroU16 @@ -890,7 +888,6 @@ impl SusTreeSitterSingleton { func_call_kind : node_kind("func_call"), parenthesis_expression_kind : node_kind("parenthesis_expression"), array_bracket_expression_kind : node_kind("array_bracket_expression"), - range_kind : node_kind("range"), block_kind : node_kind("block"), decl_assign_statement_kind : node_kind("decl_assign_statement"), assign_left_side_kind : node_kind("assign_left_side"), @@ -927,7 +924,6 @@ impl SusTreeSitterSingleton { then_block_field : field("then_block"), else_block_field : field("else_block"), for_decl_field : field("for_decl"), - for_range_field : field("for_range"), content_field : field("content"), item_field : field("item"), @@ -941,20 +937,20 @@ impl SusTreeSitterSingleton { pub static SUS : SusTreeSitterSingleton = SusTreeSitterSingleton::new(); pub struct Cursor<'t> { - cursor : TreeCursor<'t> + cursor : TreeCursor<'t>, + file_text : &'t FileText } impl<'t> Cursor<'t> { #[track_caller] - pub fn new_for_node(tree : &'t tree_sitter::Tree, span : Span, kind : u16) -> Self { + pub fn new_for_node(tree : &'t Tree, file_text : &'t FileText, span : Span, kind : u16) -> Self { let mut cursor = tree.walk(); let _ = cursor.goto_first_child_for_byte(span.into_range().start).unwrap(); let start_node = cursor.node(); assert!(start_node.kind_id() == kind); assert!(start_node.byte_range() == span.into_range()); - Self{cursor} - + Self{cursor, file_text} } pub fn kind_span(&self) -> (u16, Span) { @@ -973,15 +969,21 @@ impl<'t> Cursor<'t> { } #[track_caller] - pub fn unreachable(&mut self, file_text : &FileText) -> ! { + pub fn print_stack(&mut self) { let this_node_kind = self.cursor.node().kind(); let this_node_span = self.span(); println!("Stack:"); loop { - print_current_node_indented(file_text, &self.cursor); + print_current_node_indented(self.file_text, &self.cursor); if !self.cursor.goto_parent() {break;} } - panic!("Could not match the current node: {this_node_kind}, {this_node_span}"); + println!("Current node: {this_node_kind}, {this_node_span}"); + } + + #[track_caller] + pub fn could_not_match(&mut self) -> ! { + self.print_stack(); + panic!(); } /// The cursor advances to the next field, regardless if it is the requested field. If the found field is the requested field, the function is called. @@ -1033,10 +1035,12 @@ impl<'t> Cursor<'t> { self.cursor.goto_next_sibling(); return result; } else { + self.print_stack(); panic!("Did not find required field '{}', found field '{}' instead!", SUS.language.field_name_for_id(field_id.into()).unwrap(), SUS.language.field_name_for_id(found.into()).unwrap()); } } else { if !self.cursor.goto_next_sibling() { + self.print_stack(); panic!("Reached the end of child nodes without finding field '{}'", SUS.language.field_name_for_id(field_id.into()).unwrap()) } } @@ -1055,7 +1059,10 @@ impl<'t> Cursor<'t> { #[track_caller] pub fn go_down OT>(&mut self, kind : u16, func : F) -> OT { let node = self.cursor.node(); - assert_eq!(node.kind_id(), kind, "Was {} instead", node.kind()); + if node.kind_id() != kind { + self.print_stack(); + panic!("Expected {}, Was {} instead", SUS.language.node_kind_for_id(kind).unwrap(), node.kind()); + } self.go_down_no_check(func) } @@ -1073,6 +1080,7 @@ impl<'t> Cursor<'t> { // Some specialized functions for SUS Language /// Goes down the current node, checks it's kind, and then iterates through 'item' fields. + #[track_caller] pub fn list(&mut self, kind : u16, mut func : F) { self.go_down(kind, |self2| { loop { @@ -1090,6 +1098,7 @@ impl<'t> Cursor<'t> { /// Goes down the current node, checks it's kind, and then iterates through 'item' fields. /// /// The function given should return Option, and from the valid outputs this function constructs a output list + #[track_caller] pub fn collect_list Option>(&mut self, kind : u16, mut func : F) -> Vec { let mut result = Vec::new(); @@ -1103,6 +1112,7 @@ impl<'t> Cursor<'t> { } /// Goes down the current node, checks it's kind, and then selects the 'content' field. Useful for constructs like seq('[', field('content', $.expr), ']') + #[track_caller] pub fn go_down_content OT>(&mut self, top_kind : u16, func : F) -> OT { let outer_span = self.span(); self.go_down(top_kind, |self2| { diff --git a/tree-sitter-sus b/tree-sitter-sus index 6380a6b..49abf5b 160000 --- a/tree-sitter-sus +++ b/tree-sitter-sus @@ -1 +1 @@ -Subproject commit 6380a6b7e2b415d482b232199608a15545662300 +Subproject commit 49abf5baac20363237293843565985c0204f83b5