Tree-sitter: Split up ast_node_info table into two tables

This commit is contained in:
Tom Hvitved
2024-03-19 10:01:05 +01:00
parent f025430431
commit cee6f003fd
3 changed files with 86 additions and 64 deletions

View File

@@ -209,10 +209,10 @@ struct Visitor<'a> {
diagnostics_writer: &'a mut diagnostics::LogWriter,
/// A trap::Writer to accumulate trap entries
trap_writer: &'a mut trap::Writer,
/// A counter for top-level child nodes
toplevel_child_counter: usize,
/// Language-specific name of the AST info table
ast_node_info_table_name: String,
/// Language-specific name of the AST location table
ast_node_location_table_name: String,
/// Language-specific name of the AST parent table
ast_node_parent_table_name: String,
/// Language-specific name of the tokeninfo table
tokeninfo_table_name: String,
/// A lookup table from type name to node types
@@ -242,8 +242,8 @@ impl<'a> Visitor<'a> {
source,
diagnostics_writer,
trap_writer,
toplevel_child_counter: 0,
ast_node_info_table_name: format!("{}_ast_node_info", language_prefix),
ast_node_location_table_name: format!("{}_ast_node_location", language_prefix),
ast_node_parent_table_name: format!("{}_ast_node_parent", language_prefix),
tokeninfo_table_name: format!("{}_tokeninfo", language_prefix),
schema,
stack: Vec::new(),
@@ -342,27 +342,29 @@ impl<'a> Visitor<'a> {
})
.unwrap();
let mut valid = true;
let (parent_id, parent_index) = match self.stack.last_mut() {
let parent_info = match self.stack.last_mut() {
Some(p) if !node.is_extra() => {
p.1 += 1;
(p.0, p.1 - 1)
}
_ => {
self.toplevel_child_counter += 1;
(self.file_label, self.toplevel_child_counter - 1)
Some((p.0, p.1 - 1))
}
_ => None,
};
match &table.kind {
EntryKind::Token { kind_id, .. } => {
self.trap_writer.add_tuple(
&self.ast_node_info_table_name,
vec![
trap::Arg::Label(id),
trap::Arg::Label(parent_id),
trap::Arg::Int(parent_index),
trap::Arg::Label(loc_label),
],
&self.ast_node_location_table_name,
vec![trap::Arg::Label(id), trap::Arg::Label(loc_label)],
);
if let Some((parent_id, parent_index)) = parent_info {
self.trap_writer.add_tuple(
&self.ast_node_parent_table_name,
vec![
trap::Arg::Label(id),
trap::Arg::Label(parent_id),
trap::Arg::Int(parent_index),
],
);
};
self.trap_writer.add_tuple(
&self.tokeninfo_table_name,
vec![
@@ -378,14 +380,19 @@ impl<'a> Visitor<'a> {
} => {
if let Some(args) = self.complex_node(&node, fields, &child_nodes, id) {
self.trap_writer.add_tuple(
&self.ast_node_info_table_name,
vec![
trap::Arg::Label(id),
trap::Arg::Label(parent_id),
trap::Arg::Int(parent_index),
trap::Arg::Label(loc_label),
],
&self.ast_node_location_table_name,
vec![trap::Arg::Label(id), trap::Arg::Label(loc_label)],
);
if let Some((parent_id, parent_index)) = parent_info {
self.trap_writer.add_tuple(
&self.ast_node_parent_table_name,
vec![
trap::Arg::Label(id),
trap::Arg::Label(parent_id),
trap::Arg::Int(parent_index),
],
);
};
let mut all_args = vec![trap::Arg::Label(id)];
all_args.extend(args);
self.trap_writer.add_tuple(table_name, all_args);

View File

@@ -52,8 +52,8 @@ pub fn generate(
for language in languages {
let prefix = node_types::to_snake_case(&language.name);
let ast_node_name = format!("{}_ast_node", &prefix);
let node_info_table_name = format!("{}_ast_node_info", &prefix);
let ast_node_parent_name = format!("{}_ast_node_parent", &prefix);
let node_location_table_name = format!("{}_ast_node_location", &prefix);
let node_parent_table_name = format!("{}_ast_node_parent", &prefix);
let token_name = format!("{}_token", &prefix);
let tokeninfo_name = format!("{}_tokeninfo", &prefix);
let reserved_word_name = format!("{}_reserved_word", &prefix);
@@ -72,13 +72,12 @@ pub fn generate(
name: &ast_node_name,
members: ast_node_members,
}),
dbscheme::Entry::Union(dbscheme::Union {
name: &ast_node_parent_name,
members: [&ast_node_name, "file"].iter().cloned().collect(),
}),
dbscheme::Entry::Table(create_ast_node_info_table(
&node_info_table_name,
&ast_node_parent_name,
dbscheme::Entry::Table(create_ast_node_location_table(
&node_location_table_name,
&ast_node_name,
)),
dbscheme::Entry::Table(create_ast_node_parent_table(
&node_parent_table_name,
&ast_node_name,
)),
],
@@ -87,7 +86,8 @@ pub fn generate(
let mut body = vec![
ql::TopLevel::Class(ql_gen::create_ast_node_class(
&ast_node_name,
&node_info_table_name,
&node_location_table_name,
&node_parent_table_name,
)),
ql::TopLevel::Class(ql_gen::create_token_class(&token_name, &tokeninfo_name)),
ql::TopLevel::Class(ql_gen::create_reserved_word_class(&reserved_word_name)),
@@ -335,18 +335,43 @@ fn convert_nodes(
(entries, ast_node_members, token_kinds)
}
/// Creates a dbscheme table specifying the parent node and location for each
/// AST node.
/// Creates a dbscheme table specifying the location for each AST node.
///
/// # Arguments
/// - `name` - the name of the table to create.
/// - `parent_name` - the name of the parent type.
/// - `ast_node_name` - the name of the node child type.
fn create_ast_node_info_table<'a>(
fn create_ast_node_location_table<'a>(
name: &'a str,
parent_name: &'a str,
ast_node_name: &'a str,
) -> dbscheme::Table<'a> {
dbscheme::Table {
name,
columns: vec![
dbscheme::Column {
db_type: dbscheme::DbColumnType::Int,
name: "node",
unique: true,
ql_type: ql::Type::At(ast_node_name),
ql_type_is_ref: true,
},
dbscheme::Column {
unique: false,
db_type: dbscheme::DbColumnType::Int,
name: "loc",
ql_type: ql::Type::At("location_default"),
ql_type_is_ref: true,
},
],
keysets: None,
}
}
/// Creates a dbscheme table specifying the parent node for each AST node.
///
/// # Arguments
/// - `name` - the name of the table to create.
/// - `ast_node_name` - the name of the node child type.
fn create_ast_node_parent_table<'a>(name: &'a str, ast_node_name: &'a str) -> dbscheme::Table<'a> {
dbscheme::Table {
name,
columns: vec![
@@ -361,7 +386,7 @@ fn create_ast_node_info_table<'a>(
db_type: dbscheme::DbColumnType::Int,
name: "parent",
unique: false,
ql_type: ql::Type::At(parent_name),
ql_type: ql::Type::At(ast_node_name),
ql_type_is_ref: true,
},
dbscheme::Column {
@@ -371,13 +396,6 @@ fn create_ast_node_info_table<'a>(
ql_type: ql::Type::Int,
ql_type_is_ref: true,
},
dbscheme::Column {
unique: false,
db_type: dbscheme::DbColumnType::Int,
name: "loc",
ql_type: ql::Type::At("location_default"),
ql_type_is_ref: true,
},
],
keysets: Some(vec!["parent", "parent_index"]),
}

View File

@@ -4,7 +4,11 @@ use crate::{generator::ql, node_types};
/// Creates the hard-coded `AstNode` class that acts as a supertype of all
/// classes we generate.
pub fn create_ast_node_class<'a>(ast_node: &'a str, node_info_table: &'a str) -> ql::Class<'a> {
pub fn create_ast_node_class<'a>(
ast_node: &'a str,
node_location_table: &'a str,
node_parent_table: &'a str,
) -> ql::Class<'a> {
// Default implementation of `toString` calls `this.getAPrimaryQlClass()`
let to_string = ql::Predicate {
qldoc: Some(String::from(
@@ -32,13 +36,8 @@ pub fn create_ast_node_class<'a>(ast_node: &'a str, node_info_table: &'a str) ->
return_type: Some(ql::Type::Normal("L::Location")),
formal_parameters: vec![],
body: ql::Expression::Pred(
node_info_table,
vec![
ql::Expression::Var("this"),
ql::Expression::Var("_"), // parent
ql::Expression::Var("_"), // parent index
ql::Expression::Var("result"), // location
],
node_location_table,
vec![ql::Expression::Var("this"), ql::Expression::Var("result")],
),
};
let get_a_field_or_child = create_none_predicate(
@@ -55,12 +54,11 @@ pub fn create_ast_node_class<'a>(ast_node: &'a str, node_info_table: &'a str) ->
return_type: Some(ql::Type::Normal("AstNode")),
formal_parameters: vec![],
body: ql::Expression::Pred(
node_info_table,
node_parent_table,
vec![
ql::Expression::Var("this"),
ql::Expression::Var("result"),
ql::Expression::Var("_"), // parent index
ql::Expression::Var("_"), // location
ql::Expression::Var("_"),
],
),
};
@@ -74,12 +72,11 @@ pub fn create_ast_node_class<'a>(ast_node: &'a str, node_info_table: &'a str) ->
return_type: Some(ql::Type::Int),
formal_parameters: vec![],
body: ql::Expression::Pred(
node_info_table,
node_parent_table,
vec![
ql::Expression::Var("this"),
ql::Expression::Var("_"), // parent
ql::Expression::Var("result"), // parent index
ql::Expression::Var("_"), // location
ql::Expression::Var("_"),
ql::Expression::Var("result"),
],
),
};