Skip to content

Commit

Permalink
Can parse if and for with tree sitter
Browse files Browse the repository at this point in the history
  • Loading branch information
VonTum committed Apr 1, 2024
1 parent 91e0134 commit 95eef94
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 53 deletions.
90 changes: 50 additions & 40 deletions src/flattening/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<const ALLOW_MODULES : bool>(&mut self, cursor : &mut Cursor<'l>) -> ModuleOrWrittenType {
Expand All @@ -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<const ALLOW_MODULES : bool>(&mut self, fallback_identifier_type : IdentifierType, declaration_itself_is_not_written_to : bool, cursor : &mut Cursor<'l>) -> FlatID {
fn flatten_declaration_tree<const ALLOW_MODULES : bool, const ALLOW_MODIFIERS : bool>(&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;
}
Expand All @@ -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);

Expand Down Expand Up @@ -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{
Expand Down Expand Up @@ -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>) {
Expand Down Expand Up @@ -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::<false>(var, true, true);
cursor.go_down_no_check(|cursor| {
let loop_var_decl = cursor.field(SUS.for_decl_field, |cursor| self.flatten_declaration_tree::<false, false>(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);
})
}
});
}
Expand Down Expand Up @@ -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::<false>(IdentifierType::Local, true, cursor);
let root = self.flatten_declaration_tree::<false, true>(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
Expand Down Expand Up @@ -1111,7 +1121,7 @@ impl<'l> FlatteningContext<'l> {
let kind = cursor.kind();

if kind == SUS.declaration_kind {
let _ = self.flatten_declaration_tree::<true>(IdentifierType::Local, true, cursor);
let _ = self.flatten_declaration_tree::<true, true>(IdentifierType::Local, true, cursor);
} else { // It's _expression
let _ = self.flatten_expr_tree(cursor);
}
Expand All @@ -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::<false>(identifier_type, true, cursor);
self.flatten_declaration_tree::<false, false>(identifier_type, true, cursor);
})
}

Expand Down Expand Up @@ -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(),
Expand Down
34 changes: 22 additions & 12 deletions src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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"),
Expand Down Expand Up @@ -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"),
Expand All @@ -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) {
Expand All @@ -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.
Expand Down Expand Up @@ -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())
}
}
Expand All @@ -1055,7 +1059,10 @@ impl<'t> Cursor<'t> {
#[track_caller]
pub fn go_down<OT, F : FnOnce(&mut Self) -> 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)
}
Expand All @@ -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<F : FnMut(&mut Self)>(&mut self, kind : u16, mut func : F) {
self.go_down(kind, |self2| {
loop {
Expand All @@ -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<OT>, and from the valid outputs this function constructs a output list
#[track_caller]
pub fn collect_list<OT, F : FnMut(&mut Self) -> Option<OT>>(&mut self, kind : u16, mut func : F) -> Vec<OT> {
let mut result = Vec::new();

Expand All @@ -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, F : FnOnce(&mut Self, Span) -> OT>(&mut self, top_kind : u16, func : F) -> OT {
let outer_span = self.span();
self.go_down(top_kind, |self2| {
Expand Down
2 changes: 1 addition & 1 deletion tree-sitter-sus

0 comments on commit 95eef94

Please sign in to comment.