more refactoring of names

This commit is contained in:
Nick Rolfe
2020-11-16 15:55:06 +00:00
parent 83a0e5fea6
commit bbe7c70d34
4 changed files with 102 additions and 97 deletions

View File

@@ -1,4 +1,4 @@
use node_types::{escape_name, EntryKind, Field, NodeTypeMap, Storage, TypeName};
use node_types::{EntryKind, Field, NodeTypeMap, Storage, TypeName};
use std::collections::BTreeMap as Map;
use std::collections::BTreeSet as Set;
use std::fmt;
@@ -328,8 +328,10 @@ impl Visitor<'_> {
);
self.token_counter += 1;
}
EntryKind::Table { fields, .. } => {
let table_name = escape_name(&format!("{}_def", &table.flattened_name));
EntryKind::Table {
fields,
name: table_name,
} => {
if let Some(args) = self.complex_node(&node, fields, child_nodes, id) {
let mut all_args = Vec::new();
all_args.push(Arg::Label(id));
@@ -409,7 +411,7 @@ impl Visitor<'_> {
for field in fields {
let child_ids = &map.get(&field.name).unwrap().1;
match &field.storage {
Storage::Column => {
Storage::Column { name: column_name } => {
if child_ids.len() == 1 {
args.push(Arg::Label(*child_ids.first().unwrap()));
} else {
@@ -424,11 +426,14 @@ impl Visitor<'_> {
"too many values"
},
node.kind(),
&field.get_name()
column_name
)
}
}
Storage::Table(has_index) => {
Storage::Table {
name: table_name,
has_index,
} => {
for (index, child_id) in child_ids.iter().enumerate() {
if !*has_index && index > 0 {
error!(
@@ -436,15 +441,10 @@ impl Visitor<'_> {
&self.path,
node.start_position().row + 1,
node.kind(),
&field.get_name()
table_name,
);
break;
}
let table_name = escape_name(&format!(
"{}_{}",
self.schema.get(&field.parent).unwrap().flattened_name,
field.get_name()
));
let mut args = Vec::new();
args.push(Arg::Label(parent_id));
if *has_index {

View File

@@ -29,15 +29,15 @@ fn make_field_type(
// type to represent them.
let members: Set<String> = types
.iter()
.map(|t| node_types::escape_name(&nodes.get(t).unwrap().flattened_name))
.map(|t| nodes.get(t).unwrap().dbscheme_name.clone())
.collect();
entries.push(dbscheme::Entry::Union(dbscheme::Union {
name: node_types::escape_name(&dbscheme_union),
name: dbscheme_union.clone(),
members,
}));
dbscheme_union.clone()
}
node_types::FieldTypeInfo::Single(t) => nodes.get(&t).unwrap().flattened_name.clone(),
node_types::FieldTypeInfo::Single(t) => nodes.get(&t).unwrap().dbscheme_name.clone(),
}
}
@@ -49,18 +49,20 @@ fn add_field(
entries: &mut Vec<dbscheme::Entry>,
nodes: &node_types::NodeTypeMap,
) {
let field_name = field.get_name();
let parent_name = &nodes.get(&field.parent).unwrap().flattened_name;
let parent_name = &nodes.get(&field.parent).unwrap().dbscheme_name;
match &field.storage {
node_types::Storage::Table(has_index) => {
node_types::Storage::Table {
name: table_name,
has_index,
} => {
// This field can appear zero or multiple times, so put
// it in an auxiliary table.
let field_type = node_types::escape_name(&make_field_type(&field, entries, nodes));
let field_type = make_field_type(&field, entries, nodes);
let parent_column = dbscheme::Column {
unique: !*has_index,
db_type: dbscheme::DbColumnType::Int,
name: node_types::escape_name(&parent_name),
ql_type: ql::Type::AtType(node_types::escape_name(&parent_name)),
name: parent_name.clone(),
ql_type: ql::Type::AtType(parent_name.clone()),
ql_type_is_ref: true,
};
let index_column = dbscheme::Column {
@@ -78,7 +80,7 @@ fn add_field(
ql_type_is_ref: true,
};
let field_table = dbscheme::Table {
name: node_types::escape_name(&format!("{}_{}", parent_name, field_name)),
name: table_name.clone(),
columns: if *has_index {
vec![parent_column, index_column, field_column]
} else {
@@ -87,25 +89,22 @@ fn add_field(
// In addition to the field being unique, the combination of
// parent+index is unique, so add a keyset for them.
keysets: if *has_index {
Some(vec![
node_types::escape_name(&parent_name),
"index".to_string(),
])
Some(vec![parent_name.clone(), "index".to_string()])
} else {
None
},
};
entries.push(dbscheme::Entry::Table(field_table));
}
node_types::Storage::Column => {
node_types::Storage::Column { name: column_name } => {
// This field must appear exactly once, so we add it as
// a column to the main table for the node type.
let field_type = make_field_type(&field, entries, nodes);
main_table.columns.push(dbscheme::Column {
unique: false,
db_type: dbscheme::DbColumnType::Int,
name: node_types::escape_name(&field_name),
ql_type: ql::Type::AtType(node_types::escape_name(&field_type)),
name: column_name.clone(),
ql_type: ql::Type::AtType(field_type),
ql_type_is_ref: true,
});
}
@@ -130,12 +129,12 @@ fn convert_nodes(nodes: &node_types::NodeTypeMap) -> Vec<dbscheme::Entry> {
.iter()
.filter_map(|(_, node)| match &node.kind {
node_types::EntryKind::Token { kind_id } => {
Some((node.flattened_name.clone(), *kind_id))
Some((node.dbscheme_name.clone(), *kind_id))
}
_ => None,
})
.collect();
ast_node_members.insert(node_types::escape_name("token"));
ast_node_members.insert("token".to_owned());
for (_, node) in nodes {
match &node.kind {
@@ -144,27 +143,27 @@ fn convert_nodes(nodes: &node_types::NodeTypeMap) -> Vec<dbscheme::Entry> {
// type.
let members: Set<String> = n_members
.iter()
.map(|n| node_types::escape_name(&nodes.get(n).unwrap().flattened_name))
.map(|n| nodes.get(n).unwrap().dbscheme_name.clone())
.collect();
entries.push(dbscheme::Entry::Union(dbscheme::Union {
name: node_types::escape_name(&node.flattened_name),
name: node.dbscheme_name.clone(),
members,
}));
}
node_types::EntryKind::Table { fields } => {
node_types::EntryKind::Table { name, fields } => {
// It's a product type, defined by a table.
let mut main_table = dbscheme::Table {
name: node_types::escape_name(&(format!("{}_def", &node.flattened_name))),
name: name.clone(),
columns: vec![dbscheme::Column {
db_type: dbscheme::DbColumnType::Int,
name: "id".to_string(),
unique: true,
ql_type: ql::Type::AtType(node_types::escape_name(&node.flattened_name)),
ql_type: ql::Type::AtType(node.dbscheme_name.clone()),
ql_type_is_ref: false,
}],
keysets: None,
};
ast_node_members.insert(node_types::escape_name(&node.flattened_name));
ast_node_members.insert(node.dbscheme_name.clone());
// If the type also has fields or children, then we create either
// auxiliary tables or columns in the defining table for them.
@@ -262,7 +261,7 @@ fn add_tokeninfo_table(entries: &mut Vec<dbscheme::Entry>, token_kinds: Map<Stri
}));
let branches: Vec<(usize, String)> = token_kinds
.iter()
.map(|(name, kind_id)| (*kind_id, node_types::escape_name(name)))
.map(|(name, kind_id)| (*kind_id, name.clone()))
.collect();
entries.push(dbscheme::Entry::Case(dbscheme::Case {
name: "token".to_owned(),

View File

@@ -309,7 +309,6 @@ fn create_field_getters(
main_table_name: &str,
main_table_arity: usize,
main_table_column_index: &mut usize,
parent_name: &str,
field: &node_types::Field,
nodes: &node_types::NodeTypeMap,
) -> (ql::Predicate, ql::Expression) {
@@ -323,7 +322,7 @@ fn create_field_getters(
} => ql_class.clone(),
}));
match &field.storage {
node_types::Storage::Column => {
node_types::Storage::Column { name: _ } => {
let result = (
ql::Predicate {
name: predicate_name,
@@ -345,32 +344,32 @@ fn create_field_getters(
*main_table_column_index += 1;
result
}
node_types::Storage::Table(has_index) => {
let field_table_name = format!("{}_{}", parent_name, &field.get_name());
(
ql::Predicate {
name: predicate_name,
overridden: false,
return_type,
formal_parameters: if *has_index {
vec![ql::FormalParameter {
name: "i".to_owned(),
param_type: ql::Type::Int,
}]
} else {
vec![]
},
body: create_get_field_expr_for_table_storage(
&field_table_name,
if *has_index { Some("i") } else { None },
),
node_types::Storage::Table {
name: field_table_name,
has_index,
} => (
ql::Predicate {
name: predicate_name,
overridden: false,
return_type,
formal_parameters: if *has_index {
vec![ql::FormalParameter {
name: "i".to_owned(),
param_type: ql::Type::Int,
}]
} else {
vec![]
},
create_get_field_expr_for_table_storage(
body: create_get_field_expr_for_table_storage(
&field_table_name,
if *has_index { Some("_") } else { None },
if *has_index { Some("i") } else { None },
),
)
}
},
create_get_field_expr_for_table_storage(
&field_table_name,
if *has_index { Some("_") } else { None },
),
),
}
}
@@ -398,7 +397,7 @@ pub fn convert_nodes(nodes: &node_types::NodeTypeMap) -> Vec<ql::TopLevel> {
if type_name.named {
let describe_ql_class = create_describe_ql_class(&node.ql_class_name);
let mut supertypes: BTreeSet<ql::Type> = BTreeSet::new();
supertypes.insert(ql::Type::AtType(node.flattened_name.to_owned()));
supertypes.insert(ql::Type::AtType(node.dbscheme_name.to_owned()));
supertypes.insert(ql::Type::Normal("Token".to_owned()));
classes.push(ql::TopLevel::Class(ql::Class {
name: node.ql_class_name.clone(),
@@ -416,7 +415,7 @@ pub fn convert_nodes(nodes: &node_types::NodeTypeMap) -> Vec<ql::TopLevel> {
name: node.ql_class_name.clone(),
is_abstract: false,
supertypes: vec![
ql::Type::AtType(node_types::escape_name(&node.flattened_name)),
ql::Type::AtType(node.dbscheme_name.clone()),
ql::Type::Normal("AstNode".to_owned()),
]
.into_iter()
@@ -425,7 +424,10 @@ pub fn convert_nodes(nodes: &node_types::NodeTypeMap) -> Vec<ql::TopLevel> {
predicates: vec![],
}));
}
node_types::EntryKind::Table { fields } => {
node_types::EntryKind::Table {
name: main_table_name,
fields,
} => {
// Count how many columns there will be in the main table.
// There will be:
// - one for the id
@@ -437,19 +439,16 @@ pub fn convert_nodes(nodes: &node_types::NodeTypeMap) -> Vec<ql::TopLevel> {
} else {
fields
.iter()
.filter(|&f| matches!(f.storage, node_types::Storage::Column))
.filter(|&f| matches!(f.storage, node_types::Storage::Column{..}))
.count()
};
let escaped_name = node_types::escape_name(&node.flattened_name);
let main_class_name = &node.ql_class_name;
let main_table_name =
node_types::escape_name(&format!("{}_def", &node.flattened_name));
let mut main_class = ql::Class {
name: main_class_name.clone(),
is_abstract: false,
supertypes: vec![
ql::Type::AtType(escaped_name),
ql::Type::AtType(node.dbscheme_name.clone()),
ql::Type::Normal("AstNode".to_owned()),
]
.into_iter()
@@ -478,7 +477,6 @@ pub fn convert_nodes(nodes: &node_types::NodeTypeMap) -> Vec<ql::TopLevel> {
&main_table_name,
main_table_arity,
&mut main_table_column_index,
&node.flattened_name,
field,
nodes,
);

View File

@@ -10,7 +10,7 @@ pub type NodeTypeMap = BTreeMap<TypeName, Entry>;
#[derive(Debug)]
pub struct Entry {
pub flattened_name: String,
pub dbscheme_name: String,
pub ql_class_name: String,
pub kind: EntryKind,
}
@@ -18,7 +18,7 @@ pub struct Entry {
#[derive(Debug)]
pub enum EntryKind {
Union { members: Set<TypeName> },
Table { fields: Vec<Field> },
Table { name: String, fields: Vec<Field> },
Token { kind_id: usize },
}
@@ -61,10 +61,6 @@ fn name_for_field_or_child(name: &Option<String>) -> String {
}
impl Field {
pub fn get_name(&self) -> String {
name_for_field_or_child(&self.name)
}
pub fn get_getter_name(&self) -> String {
format!(
"get{}",
@@ -76,10 +72,10 @@ impl Field {
#[derive(Debug)]
pub enum Storage {
/// the field is stored as a column in the parent table
Column,
Column { name: String },
/// the field is stored in a link table, and may or may not have an
/// associated index column
Table(bool),
Table { name: String, has_index: bool },
}
pub fn read_node_types(node_types_path: &Path) -> std::io::Result<NodeTypeMap> {
@@ -109,8 +105,9 @@ pub fn convert_nodes(nodes: Vec<NodeInfo>) -> NodeTypeMap {
let mut entries = NodeTypeMap::new();
let mut token_kinds = Set::new();
for node in nodes {
let flattened_name = node_type_name(&node.kind, node.named);
let ql_class_name = dbscheme_name_to_class_name(&escape_name(&flattened_name));
let flattened_name = &node_type_name(&node.kind, node.named);
let dbscheme_name = escape_name(&flattened_name);
let ql_class_name = dbscheme_name_to_class_name(&dbscheme_name);
if let Some(subtypes) = &node.subtypes {
// It's a tree-sitter supertype node, for which we create a union
// type.
@@ -120,7 +117,7 @@ pub fn convert_nodes(nodes: Vec<NodeInfo>) -> NodeTypeMap {
named: node.named,
},
Entry {
flattened_name,
dbscheme_name,
ql_class_name,
kind: EntryKind::Union {
members: convert_types(&subtypes),
@@ -139,6 +136,7 @@ pub fn convert_nodes(nodes: Vec<NodeInfo>) -> NodeTypeMap {
kind: node.kind,
named: node.named,
};
let table_name = escape_name(&(format!("{}_def", &flattened_name)));
let mut fields = Vec::new();
// If the type also has fields or children, then we create either
@@ -160,9 +158,12 @@ pub fn convert_nodes(nodes: Vec<NodeInfo>) -> NodeTypeMap {
entries.insert(
type_name,
Entry {
flattened_name,
dbscheme_name,
ql_class_name,
kind: EntryKind::Table { fields },
kind: EntryKind::Table {
name: table_name,
fields,
},
},
);
}
@@ -173,13 +174,13 @@ pub fn convert_nodes(nodes: Vec<NodeInfo>) -> NodeTypeMap {
counter += 1;
let unprefixed_name = node_type_name(&type_name.kind, true);
Entry {
flattened_name: format!("token_{}", &unprefixed_name),
dbscheme_name: escape_name(&format!("token_{}", &unprefixed_name)),
ql_class_name: dbscheme_name_to_class_name(&escape_name(&unprefixed_name)),
kind: EntryKind::Token { kind_id: counter },
}
} else {
Entry {
flattened_name: "reserved_word".to_owned(),
dbscheme_name: "reserved_word".to_owned(),
ql_class_name: "ReservedWord".to_owned(),
kind: EntryKind::Token { kind_id: 0 },
}
@@ -195,18 +196,25 @@ fn add_field(
field_info: &FieldInfo,
fields: &mut Vec<Field>,
) {
let parent_flattened_name = node_type_name(&parent_type_name.kind, parent_type_name.named);
let storage = if !field_info.multiple && field_info.required {
// This field must appear exactly once, so we add it as
// a column to the main table for the node type.
Storage::Column
} else if !field_info.multiple {
// This field is optional but can occur at most once. Put it in an
// auxiliary table without an index.
Storage::Table(false)
Storage::Column {
name: escape_name(&name_for_field_or_child(&field_name)),
}
} else {
// This field can occur multiple times. Put it in an auxiliary table
// with an associated index.
Storage::Table(true)
// Put the field in an auxiliary table.
let has_index = field_info.multiple;
let field_table_name = escape_name(&format!(
"{}_{}",
parent_flattened_name,
&name_for_field_or_child(&field_name)
));
Storage::Table {
has_index,
name: field_table_name,
}
};
let type_info = if field_info.types.len() == 1 {
FieldTypeInfo::Single(convert_type(field_info.types.iter().next().unwrap()))
@@ -216,7 +224,7 @@ fn add_field(
types: convert_types(&field_info.types),
dbscheme_union: format!(
"{}_{}_type",
&node_type_name(&parent_type_name.kind, parent_type_name.named),
&parent_flattened_name,
&name_for_field_or_child(&field_name)
),
ql_class: "AstNode".to_owned(),
@@ -277,7 +285,7 @@ const RESERVED_KEYWORDS: [&'static str; 14] = [
/// Returns a string that's a copy of `name` but suitably escaped to be a valid
/// QL identifier.
pub fn escape_name(name: &str) -> String {
fn escape_name(name: &str) -> String {
let mut result = String::new();
// If there's a leading underscore, replace it with 'underscore_'.