1
0

Implement tables

This commit is contained in:
Jeff 2023-10-02 23:19:01 -04:00
parent a42b43ed78
commit 5551f40ffd
3 changed files with 241 additions and 162 deletions

View File

@ -5,7 +5,7 @@
use std::fmt::{self, Debug, Formatter}; use std::fmt::{self, Debug, Formatter};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tree_sitter::{Parser, Tree as TSTree, TreeCursor}; use tree_sitter::{Node, Parser, Tree as TSTree, TreeCursor};
use crate::{language, Error, Primitive, Result, Value, VariableMap}; use crate::{language, Error, Primitive, Result, Value, VariableMap};
@ -63,7 +63,7 @@ pub trait EvaluatorTree: Sized {
/// ///
/// If necessary, the source code can be accessed directly by getting the /// If necessary, the source code can be accessed directly by getting the
/// node's byte range. /// node's byte range.
fn new(source: &str, cursor: &mut TreeCursor) -> Result<Self>; fn from_syntax_node(node: Node, source: &str) -> Result<Self>;
/// Execute dust code by traversing the tree /// Execute dust code by traversing the tree
fn run(&self, context: &mut VariableMap) -> Result<Value>; fn run(&self, context: &mut VariableMap) -> Result<Value>;
@ -109,10 +109,8 @@ impl<'context, 'code> Evaluator<'context, 'code> {
assert_eq!(cursor_0.node().kind(), "root"); assert_eq!(cursor_0.node().kind(), "root");
cursor_1.goto_first_child(); for item_node in node.children(&mut cursor_0) {
let item_result = Item::from_syntax_node(item_node, self.source);
for _ in node.children(&mut cursor_0) {
let item_result = Item::new(self.source, &mut cursor_1);
match item_result { match item_result {
Ok(item) => { Ok(item) => {
@ -140,12 +138,10 @@ pub enum Item {
} }
impl EvaluatorTree for Item { impl EvaluatorTree for Item {
fn new(source: &str, cursor: &mut TreeCursor) -> Result<Self> { fn from_syntax_node(node: Node, source: &str) -> Result<Self> {
let node = cursor.node(); debug_assert_eq!(node.kind(), "item");
cursor.goto_first_child();
let child = cursor.node();
assert_eq!(node.kind(), "item"); let child = node.child(0).unwrap();
if child.kind() == "comment" { if child.kind() == "comment" {
let byte_range = child.byte_range(); let byte_range = child.byte_range();
@ -153,7 +149,7 @@ impl EvaluatorTree for Item {
Ok(Item::Comment(comment_text.to_string())) Ok(Item::Comment(comment_text.to_string()))
} else if child.kind() == "statement" { } else if child.kind() == "statement" {
Ok(Item::Statement(Statement::new(source, cursor)?)) Ok(Item::Statement(Statement::from_syntax_node(child, source)?))
} else { } else {
Err(Error::UnexpectedSyntax { Err(Error::UnexpectedSyntax {
expected: "comment or statement", expected: "comment or statement",
@ -182,12 +178,15 @@ pub enum Statement {
} }
impl EvaluatorTree for Statement { impl EvaluatorTree for Statement {
fn new(source: &str, cursor: &mut TreeCursor) -> Result<Self> { fn from_syntax_node(node: Node, source: &str) -> Result<Self> {
cursor.goto_first_child(); debug_assert_eq!(node.kind(), "statement");
let child = cursor.node();
let child = node.child(0).unwrap();
match child.kind() { match child.kind() {
"expression" => Ok(Self::Expression(Expression::new(source, cursor)?)), "expression" => Ok(Self::Expression(Expression::from_syntax_node(
child, source,
)?)),
_ => Err(Error::UnexpectedSyntax { _ => Err(Error::UnexpectedSyntax {
expected: "expression", expected: "expression",
actual: child.kind(), actual: child.kind(),
@ -214,20 +213,24 @@ pub enum Expression {
} }
impl EvaluatorTree for Expression { impl EvaluatorTree for Expression {
fn new(source: &str, cursor: &mut TreeCursor) -> Result<Self> { fn from_syntax_node(node: Node, source: &str) -> Result<Self> {
let node = cursor.node(); debug_assert_eq!(node.kind(), "expression");
cursor.goto_first_child();
let child = cursor.node();
assert_eq!(node.kind(), "expression"); let child = node.child(0).unwrap();
let expression = match child.kind() { let expression = match child.kind() {
"identifier" => Self::Identifier(Identifier::new(source, cursor)?), "identifier" => Self::Identifier(Identifier::from_syntax_node(child, source)?),
"value" => Expression::Value(Value::from_source(source, cursor)?), "value" => Expression::Value(Value::from_syntax_node(child, source)?),
"control_flow" => Expression::ControlFlow(Box::new(ControlFlow::new(source, cursor)?)), "control_flow" => {
"assignment" => Expression::Assignment(Box::new(Assignment::new(source, cursor)?)), Expression::ControlFlow(Box::new(ControlFlow::from_syntax_node(child, source)?))
"math" => Expression::Math(Box::new(Math::new(source, cursor)?)), }
"function_call" => Expression::FunctionCall(FunctionCall::new(source, cursor)?), "assignment" => {
Expression::Assignment(Box::new(Assignment::from_syntax_node(child, source)?))
}
"math" => Expression::Math(Box::new(Math::from_syntax_node(child, source)?)),
"function_call" => {
Expression::FunctionCall(FunctionCall::from_syntax_node(child, source)?)
}
_ => return Err(Error::UnexpectedSyntax { _ => return Err(Error::UnexpectedSyntax {
expected: expected:
"identifier, operation, control_flow, assignment, math, function_call or value", "identifier, operation, control_flow, assignment, math, function_call or value",
@ -265,9 +268,7 @@ impl Identifier {
} }
impl EvaluatorTree for Identifier { impl EvaluatorTree for Identifier {
fn new(source: &str, cursor: &mut TreeCursor) -> Result<Self> { fn from_syntax_node(node: Node, source: &str) -> Result<Self> {
let node = cursor.node();
assert_eq!(node.kind(), "identifier"); assert_eq!(node.kind(), "identifier");
let identifier = &source[node.byte_range()]; let identifier = &source[node.byte_range()];
@ -290,35 +291,26 @@ pub struct ControlFlow {
} }
impl EvaluatorTree for ControlFlow { impl EvaluatorTree for ControlFlow {
fn new(source: &str, cursor: &mut TreeCursor) -> Result<Self> { fn from_syntax_node(node: Node, source: &str) -> Result<Self> {
let node = cursor.node();
assert_eq!(node.kind(), "control_flow"); assert_eq!(node.kind(), "control_flow");
println!("{node:?}");
// Skip the child nodes for the keywords "if", "then" and "else".
let if_node = node.child_by_field_name("if_expression").unwrap(); let if_node = node.child_by_field_name("if_expression").unwrap();
let if_expression = Expression::from_syntax_node(if_node, source)?;
cursor.reset(if_node);
let if_expression = Expression::new(source, cursor)?;
println!("{:?}", cursor.node());
let then_node = node.child_by_field_name("then_statement").unwrap(); let then_node = node.child_by_field_name("then_statement").unwrap();
let then_statement = Statement::from_syntax_node(then_node, source)?;
cursor.reset(then_node); let else_node = node.child_by_field_name("else_statement");
let else_statement = if let Some(node) = else_node {
let position = cursor.node(); Some(Statement::from_syntax_node(node, source)?)
let then_statement = Statement::new(source, cursor)?; } else {
None
cursor.reset(position); };
Ok(ControlFlow { Ok(ControlFlow {
if_expression, if_expression,
then_statement, then_statement,
else_statement: None, else_statement,
}) })
} }
@ -342,18 +334,14 @@ pub struct Assignment {
} }
impl EvaluatorTree for Assignment { impl EvaluatorTree for Assignment {
fn new(source: &str, cursor: &mut TreeCursor) -> Result<Self> { fn from_syntax_node(node: Node, source: &str) -> Result<Self> {
let node = cursor.node();
cursor.goto_first_child();
assert_eq!(node.kind(), "assignment"); assert_eq!(node.kind(), "assignment");
cursor.goto_next_sibling(); let identifier_node = node.child(0).unwrap();
let identifier = Identifier::new(source, cursor)?; let identifier = Identifier::from_syntax_node(identifier_node, source)?;
cursor.goto_next_sibling(); let statement_node = node.child(2).unwrap();
let statement = Statement::new(source, cursor)?; let statement = Statement::from_syntax_node(statement_node, source)?;
cursor.goto_next_sibling();
Ok(Assignment { Ok(Assignment {
identifier, identifier,
@ -379,15 +367,13 @@ pub struct Math {
} }
impl EvaluatorTree for Math { impl EvaluatorTree for Math {
fn new(source: &str, cursor: &mut TreeCursor) -> Result<Self> { fn from_syntax_node(node: Node, source: &str) -> Result<Self> {
let node = cursor.node();
assert_eq!(node.kind(), "math"); assert_eq!(node.kind(), "math");
cursor.goto_first_child(); let left_node = node.child(0).unwrap();
let left = Expression::new(source, cursor)?; let left = Expression::from_syntax_node(left_node, source)?;
cursor.goto_next_sibling(); let operator_node = left_node.next_sibling().unwrap();
let operator_node = cursor.node();
let operator = match operator_node.kind() { let operator = match operator_node.kind() {
"+" => MathOperator::Add, "+" => MathOperator::Add,
"-" => MathOperator::Subtract, "-" => MathOperator::Subtract,
@ -403,8 +389,8 @@ impl EvaluatorTree for Math {
} }
}; };
cursor.goto_next_sibling(); let right_node = operator_node.next_sibling().unwrap();
let right = Expression::new(source, cursor)?; let right = Expression::from_syntax_node(right_node, source)?;
Ok(Math { Ok(Math {
left, left,
@ -444,22 +430,15 @@ pub struct FunctionCall {
} }
impl EvaluatorTree for FunctionCall { impl EvaluatorTree for FunctionCall {
fn new(source: &str, cursor: &mut TreeCursor) -> Result<Self> { fn from_syntax_node(node: Node, source: &str) -> Result<Self> {
let node = cursor.node();
assert_eq!(node.kind(), "function_call"); assert_eq!(node.kind(), "function_call");
cursor.goto_first_child(); let identifier_node = node.child(0).unwrap();
let identifier = Identifier::new(source, cursor)?; let identifier = Identifier::from_syntax_node(identifier_node, source)?;
let mut expressions = Vec::new(); let mut expressions = Vec::new();
for index in 2..node.child_count() - 1 { todo!();
cursor.goto_next_sibling();
let expression = Expression::new(source, cursor)?;
expressions.push(expression);
}
Ok(FunctionCall { Ok(FunctionCall {
identifier, identifier,

View File

@ -37,6 +37,50 @@ pub enum Primitive {
Empty, Empty,
} }
impl Primitive {
fn from_syntax_node(node: Node, source: &str) -> Result<Self> {
match node.kind() {
"integer" => Primitive::integer_from_source(source, node.byte_range()),
"float" => Primitive::float_from_source(source, node.byte_range()),
"boolean" => Primitive::boolean_from_source(source, node.byte_range()),
"string" => Primitive::string_from_source(source, node.byte_range()),
"empty" => Ok(Primitive::Empty),
_ => Err(Error::UnexpectedSyntax {
expected: "integer, float, boolean, string or empty",
actual: node.kind(),
location: node.start_position(),
}),
}
}
pub fn integer_from_source(source: &str, byte_range: Range<usize>) -> Result<Self> {
let value_snippet = &source[byte_range];
let raw = value_snippet.parse::<i64>().unwrap_or_default();
Ok(Primitive::Integer(raw))
}
pub fn float_from_source(source: &str, byte_range: Range<usize>) -> Result<Self> {
let value_snippet = &source[byte_range];
let raw = value_snippet.parse::<f64>().unwrap_or_default();
Ok(Primitive::Float(raw))
}
pub fn boolean_from_source(source: &str, byte_range: Range<usize>) -> Result<Self> {
let value_snippet = &source[byte_range];
let raw = value_snippet.parse::<bool>().unwrap_or_default();
Ok(Primitive::Boolean(raw))
}
pub fn string_from_source(source: &str, byte_range: Range<usize>) -> Result<Self> {
let value_snippet = &source[byte_range];
let without_quotes = &value_snippet[1..value_snippet.len() - 1];
Ok(Primitive::String(without_quotes.to_string()))
}
}
impl Eq for Primitive {} impl Eq for Primitive {}
impl Ord for Primitive { impl Ord for Primitive {
@ -74,53 +118,90 @@ pub enum Value {
} }
impl Value { impl Value {
pub fn from_source(source: &str, mut cursor: &mut TreeCursor) -> Result<Self> { pub fn from_syntax_node(node: Node, source: &str) -> Result<Self> {
let node = cursor.node(); debug_assert_eq!(node.kind(), "value");
cursor.goto_first_child();
let child = cursor.node();
assert_eq!(node.kind(), "value"); let child = node.child(0).unwrap();
match child.kind() { match child.kind() {
"integer" | "float" | "boolean" | "string" | "empty" => { "integer" | "float" | "boolean" | "string" | "empty" => Ok(Value::Primitive(
Value::simple_from_syntax_node(node, source) Primitive::from_syntax_node(child, source)?,
} )),
"list" => { "list" => {
let list_length = child.named_child_count(); let item_count = child.named_child_count();
let mut values = Vec::with_capacity(list_length); let mut values = Vec::with_capacity(item_count);
let mut current_node = child.child(1).unwrap();
cursor.goto_first_child(); while values.len() < item_count {
if current_node.is_named() {
for value_node in child.children_by_field_name("item", &mut cursor) { let value = Value::from_syntax_node(current_node, source)?;
let value = Value::simple_from_syntax_node(value_node, source)?;
values.push(value); values.push(value);
} }
current_node = current_node.next_sibling().unwrap();
}
Ok(Value::List(values)) Ok(Value::List(values))
} }
"table" => { "table" => {
let mut column_names = Vec::new(); let mut current_node = child.child(0).unwrap();
let header_and_row_count = child.named_child_count();
let mut table = Table::new(column_names); let mut headers = Vec::new();
let mut rows = Vec::new();
while headers.len() + rows.len() < header_and_row_count {
println!("{current_node:?}");
if current_node.kind() == "identifier" {
let identifier = Identifier::from_syntax_node(current_node, source)?;
let identifier_text = identifier.take_inner();
headers.push(identifier_text);
}
if current_node.kind() == "list" {
let value = Value::list_from_syntax_node(current_node, source)?;
let row = value.into_inner_list()?;
rows.push(row);
}
if let Some(node) = current_node.next_sibling() {
current_node = node;
} else {
break;
}
}
let table = Table::from_raw_parts(headers, rows);
Ok(Value::Table(table)) Ok(Value::Table(table))
} }
"map" => { "map" => {
let mut map = VariableMap::new(); let mut map = VariableMap::new();
let pair_count = child.named_child_count();
let mut current_key = String::new(); let mut current_key = String::new();
let mut current_node = child.child(0).unwrap();
for key_value_node in child.children_by_field_name("key_value_pair", &mut cursor) { while map.len() < pair_count {
if key_value_node.kind() == "identifier" { if current_node.kind() == "identifier" {
let identifier_text = &source[key_value_node.byte_range()]; let identifier_text = &source[current_node.byte_range()];
current_key = identifier_text.to_string(); current_key = identifier_text.to_string();
} }
if key_value_node.kind() == "value" { if current_node.kind() == "value" {
let value = Value::simple_from_syntax_node(key_value_node, source)?; let value = Value::from_syntax_node(current_node, source)?;
map.set_value(current_key.to_string(), value)?; map.set_value(current_key.to_string(), value)?;
} }
if let Some(node) = current_node.next_sibling() {
current_node = node;
} else {
break;
}
} }
Ok(Value::Map(map)) Ok(Value::Map(map))
@ -133,17 +214,17 @@ impl Value {
for index in 0..child_count { for index in 0..child_count {
let child = child.child(index).unwrap(); let child = child.child(index).unwrap();
if child.kind() == "identifier" { // if child.kind() == "identifier" {
let identifier = Identifier::new(source, cursor)?; // let identifier = Identifier::new(source, cursor)?;
identifiers.push(identifier) // identifiers.push(identifier)
} // }
if child.kind() == "statement" { // if child.kind() == "statement" {
let statement = Statement::new(source, cursor)?; // let statement = Statement::new(source, cursor)?;
statements.push(statement) // statements.push(statement)
} // }
} }
Ok(Value::Function(Function::new(identifiers, statements))) Ok(Value::Function(Function::new(identifiers, statements)))
@ -156,56 +237,53 @@ impl Value {
} }
} }
/// Creates a simple value from the given source code and a node in the pub fn list_from_syntax_node(node: Node, source: &str) -> Result<Self> {
/// syntax tree. debug_assert_eq!(node.kind(), "list");
///
///
pub fn simple_from_syntax_node(node: Node, source: &str) -> Result<Self> {
let child = node.child(0).unwrap();
match child.kind() { let item_count = node.named_child_count();
"integer" => Value::integer_from_source(source, child.byte_range()), let mut values = Vec::with_capacity(item_count);
"float" => Value::float_from_source(source, child.byte_range()), let mut current_node = node.child(1).unwrap();
"boolean" => Value::boolean_from_source(source, child.byte_range()),
"string" => Value::string_from_source(source, child.byte_range()), while values.len() < item_count {
"empty" => Ok(Value::Primitive(Primitive::Empty)), if current_node.is_named() {
_ => Err(Error::UnexpectedSyntax { let value = Value::from_syntax_node(current_node, source)?;
expected: "integer, float, boolean, string or empty",
actual: child.kind(), values.push(value);
location: child.start_position(),
}),
}
} }
pub fn integer_from_source(source: &str, byte_range: Range<usize>) -> Result<Self> { current_node = current_node.next_sibling().unwrap();
let value_snippet = &source[byte_range];
let raw = value_snippet.parse::<i64>().unwrap_or_default();
Ok(Value::Primitive(Primitive::Integer(raw)))
} }
pub fn float_from_source(source: &str, byte_range: Range<usize>) -> Result<Self> { Ok(Value::List(values))
let value_snippet = &source[byte_range];
let raw = value_snippet.parse::<f64>().unwrap_or_default();
Ok(Value::Primitive(Primitive::Float(raw)))
} }
pub fn boolean_from_source(source: &str, byte_range: Range<usize>) -> Result<Self> { // pub fn integer_from_source(source: &str, byte_range: Range<usize>) -> Result<Self> {
let value_snippet = &source[byte_range]; // let value_snippet = &source[byte_range];
let raw = value_snippet.parse::<bool>().unwrap_or_default(); // let raw = value_snippet.parse::<i64>().unwrap_or_default();
Ok(Value::Primitive(Primitive::Boolean(raw))) // Ok(Primitive::Integer(raw))
} // }
pub fn string_from_source(source: &str, byte_range: Range<usize>) -> Result<Self> { // pub fn float_from_source(source: &str, byte_range: Range<usize>) -> Result<Self> {
let value_snippet = &source[byte_range]; // let value_snippet = &source[byte_range];
let without_quotes = &value_snippet[1..value_snippet.len() - 1]; // let raw = value_snippet.parse::<f64>().unwrap_or_default();
Ok(Value::Primitive(Primitive::String( // Ok(Primitive::Float(raw))
without_quotes.to_string(), // }
)))
} // pub fn boolean_from_source(source: &str, byte_range: Range<usize>) -> Result<Self> {
// let value_snippet = &source[byte_range];
// let raw = value_snippet.parse::<bool>().unwrap_or_default();
// Ok(Primitive::Boolean(raw))
// }
// pub fn string_from_source(source: &str, byte_range: Range<usize>) -> Result<Self> {
// let value_snippet = &source[byte_range];
// let without_quotes = &value_snippet[1..value_snippet.len() - 1];
// Ok(Primitive::String(without_quotes.to_string()))
// }
pub fn value_type(&self) -> ValueType { pub fn value_type(&self) -> ValueType {
ValueType::from(self) ValueType::from(self)
@ -532,7 +610,13 @@ impl Display for Value {
Value::Primitive(Primitive::Integer(int)) => write!(f, "{}", int), Value::Primitive(Primitive::Integer(int)) => write!(f, "{}", int),
Value::Primitive(Primitive::Boolean(boolean)) => write!(f, "{}", boolean), Value::Primitive(Primitive::Boolean(boolean)) => write!(f, "{}", boolean),
Value::Primitive(Primitive::Empty) => write!(f, "()"), Value::Primitive(Primitive::Empty) => write!(f, "()"),
Value::List(list) => Table::from(list).fmt(f), Value::List(list) => {
write!(f, "(")?;
for value in list {
write!(f, " {value} ")?;
}
write!(f, ")")
}
Value::Map(map) => write!(f, "{map}"), Value::Map(map) => write!(f, "{map}"),
Value::Table(table) => write!(f, "{table}"), Value::Table(table) => write!(f, "{table}"),
Value::Function(function) => write!(f, "{function}"), Value::Function(function) => write!(f, "{function}"),

View File

@ -8,26 +8,42 @@ use std::{
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Table { pub struct Table {
header: Vec<String>, headers: Vec<String>,
rows: Vec<Vec<Value>>, rows: Vec<Vec<Value>>,
primary_key_index: usize, primary_key_index: usize,
} }
impl Table { impl Table {
pub fn new(column_names: Vec<String>) -> Self { pub fn new(headers: Vec<String>) -> Self {
Table { Table {
header: column_names, headers,
rows: Vec::new(), rows: Vec::new(),
primary_key_index: 0, primary_key_index: 0,
} }
} }
pub fn with_capacity(capacity: usize, headers: Vec<String>) -> Self {
Table {
headers,
rows: Vec::with_capacity(capacity),
primary_key_index: 0,
}
}
pub fn from_raw_parts(headers: Vec<String>, rows: Vec<Vec<Value>>) -> Self {
Table {
headers,
rows,
primary_key_index: 0,
}
}
pub fn reserve(&mut self, additional: usize) { pub fn reserve(&mut self, additional: usize) {
self.rows.reserve(additional); self.rows.reserve(additional);
} }
pub fn column_names(&self) -> &Vec<String> { pub fn column_names(&self) -> &Vec<String> {
&self.header &self.headers
} }
pub fn rows(&self) -> &Vec<Vec<Value>> { pub fn rows(&self) -> &Vec<Vec<Value>> {
@ -47,9 +63,9 @@ impl Table {
} }
pub fn insert(&mut self, row: Vec<Value>) -> Result<()> { pub fn insert(&mut self, row: Vec<Value>) -> Result<()> {
if row.len() != self.header.len() { if row.len() != self.headers.len() {
return Err(Error::WrongColumnAmount { return Err(Error::WrongColumnAmount {
expected: self.header.len(), expected: self.headers.len(),
actual: row.len(), actual: row.len(),
}); });
} }
@ -82,10 +98,10 @@ impl Table {
let mut new_row = Vec::new(); let mut new_row = Vec::new();
for (i, value) in row.iter().enumerate() { for (i, value) in row.iter().enumerate() {
let column_name = self.header.get(i).unwrap(); let column_name = self.headers.get(i).unwrap();
let new_table_column_index = let new_table_column_index =
new_table new_table
.header .headers
.iter() .iter()
.enumerate() .enumerate()
.find_map(|(index, new_column_name)| { .find_map(|(index, new_column_name)| {
@ -125,7 +141,7 @@ impl Table {
} }
pub fn filter(&self, column_name: &str, expected: &Value) -> Option<Table> { pub fn filter(&self, column_name: &str, expected: &Value) -> Option<Table> {
let mut filtered = Table::new(self.header.clone()); let mut filtered = Table::new(self.headers.clone());
let column_index = self.get_column_index(column_name)?; let column_index = self.get_column_index(column_name)?;
for row in &self.rows { for row in &self.rows {
@ -140,7 +156,7 @@ impl Table {
} }
pub fn get_column_index(&self, column_name: &str) -> Option<usize> { pub fn get_column_index(&self, column_name: &str) -> Option<usize> {
let column_names = &self.header; let column_names = &self.headers;
for (i, column) in column_names.iter().enumerate() { for (i, column) in column_names.iter().enumerate() {
if column == column_name { if column == column_name {
return Some(i); return Some(i);
@ -157,7 +173,7 @@ impl Display for Table {
table table
.load_preset("││──├─┼┤│ ┬┴╭╮╰╯") .load_preset("││──├─┼┤│ ┬┴╭╮╰╯")
.set_content_arrangement(ContentArrangement::Dynamic) .set_content_arrangement(ContentArrangement::Dynamic)
.set_header(&self.header); .set_header(&self.headers);
for row in &self.rows { for row in &self.rows {
let row = row.iter().map(|value| { let row = row.iter().map(|value| {
@ -209,7 +225,7 @@ impl Display for Table {
table.add_row(row); table.add_row(row);
} }
if self.header.is_empty() { if self.headers.is_empty() {
table.set_header(["empty"]); table.set_header(["empty"]);
} }
@ -360,7 +376,7 @@ impl Eq for Table {}
impl PartialEq for Table { impl PartialEq for Table {
fn eq(&self, other: &Self) -> bool { fn eq(&self, other: &Self) -> bool {
if self.header != other.header { if self.headers != other.headers {
return false; return false;
} }
@ -370,12 +386,12 @@ impl PartialEq for Table {
impl PartialOrd for Table { impl PartialOrd for Table {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> { fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
self.header.partial_cmp(&other.header) self.headers.partial_cmp(&other.headers)
} }
} }
impl Ord for Table { impl Ord for Table {
fn cmp(&self, other: &Self) -> Ordering { fn cmp(&self, other: &Self) -> Ordering {
self.header.cmp(&other.header) self.headers.cmp(&other.headers)
} }
} }