Implement list
This commit is contained in:
parent
823bb31305
commit
dd939db924
@ -61,7 +61,7 @@ pub fn eval_with_context(source: &str, context: &mut VariableMap) -> Vec<Result<
|
||||
/// trees that can be run to execute the source code. Each of these trees is an
|
||||
/// [Item][] in the evaluator.
|
||||
#[derive(Debug)]
|
||||
struct Evaluator {
|
||||
pub struct Evaluator {
|
||||
items: Vec<Item>,
|
||||
}
|
||||
|
||||
@ -111,7 +111,7 @@ impl Evaluator {
|
||||
/// to produce a single value or interact with a context by creating or
|
||||
/// referencing variables.
|
||||
#[derive(Debug)]
|
||||
enum Item {
|
||||
pub enum Item {
|
||||
Comment(String),
|
||||
Statement(Statement),
|
||||
}
|
||||
@ -145,12 +145,12 @@ impl Item {
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum Statement {
|
||||
pub enum Statement {
|
||||
Open(Expression),
|
||||
}
|
||||
|
||||
impl Statement {
|
||||
fn new(node: Node, source: &str) -> Result<Self> {
|
||||
pub fn new(node: Node, source: &str) -> Result<Self> {
|
||||
let node = if node.kind() == "statement" {
|
||||
node.child(0).unwrap()
|
||||
} else {
|
||||
@ -180,7 +180,7 @@ impl Statement {
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum Expression {
|
||||
pub enum Expression {
|
||||
Identifier(String),
|
||||
Value(Value),
|
||||
Operation(Box<Operation>),
|
||||
@ -188,7 +188,7 @@ enum Expression {
|
||||
}
|
||||
|
||||
impl Expression {
|
||||
fn new(node: Node, source: &str) -> Result<Self> {
|
||||
pub fn new(node: Node, source: &str) -> Result<Self> {
|
||||
let node = if node.kind() == "expression" {
|
||||
node.child(0).unwrap()
|
||||
} else {
|
||||
@ -218,7 +218,7 @@ impl Expression {
|
||||
}
|
||||
}
|
||||
|
||||
fn run(
|
||||
pub fn run(
|
||||
&self,
|
||||
context: &mut VariableMap,
|
||||
mut cursor: &mut TreeCursor,
|
||||
@ -242,7 +242,7 @@ impl Expression {
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Operation {
|
||||
pub struct Operation {
|
||||
left: Expression,
|
||||
operator: String,
|
||||
right: Expression,
|
||||
@ -291,7 +291,7 @@ impl Operation {
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct ControlFlow {
|
||||
pub struct ControlFlow {
|
||||
if_expression: Expression,
|
||||
then_statement: Statement,
|
||||
else_statement: Option<Statement>,
|
||||
@ -387,9 +387,9 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn evaluate_function() {
|
||||
let function_str = "function <message, answer> {
|
||||
output message;
|
||||
output 'The answer is ' + answer;
|
||||
let function_str = "function <message, number> {
|
||||
output message
|
||||
output number
|
||||
}";
|
||||
|
||||
assert_eq!(
|
||||
@ -417,7 +417,7 @@ mod tests {
|
||||
.insert(vec![Value::String("hiya".to_string()), Value::Integer(42)])
|
||||
.unwrap();
|
||||
table
|
||||
.insert(vec![Value::String("foo".to_string()), Value::Integer(-57)])
|
||||
.insert(vec![Value::String("foo".to_string()), Value::Integer(57)])
|
||||
.unwrap();
|
||||
table
|
||||
.insert(vec![Value::String("bar".to_string()), Value::Float(99.99)])
|
||||
@ -425,21 +425,13 @@ mod tests {
|
||||
|
||||
assert_eq!(
|
||||
eval(
|
||||
"table <messages, numbers>
|
||||
row ('hiya', 42)
|
||||
row ('foo', -57)
|
||||
row ('bar', 99.99)"
|
||||
),
|
||||
vec![Ok(Value::Table(table.clone()))]
|
||||
);
|
||||
assert_eq!(
|
||||
eval(
|
||||
"my_table = table <messages, numbers>
|
||||
row ('hiya', 42);
|
||||
|
||||
my_table += ('foo', -57);
|
||||
my_table += ('bar', 99.99);
|
||||
my_table"
|
||||
"
|
||||
table <messages, numbers> {
|
||||
('hiya', 42)
|
||||
('foo', 57)
|
||||
('bar', 99.99)
|
||||
}
|
||||
"
|
||||
),
|
||||
vec![Ok(Value::Table(table))]
|
||||
);
|
||||
|
@ -1,7 +1,7 @@
|
||||
//! Types that represent runtime values.
|
||||
use crate::{
|
||||
error::{Error, Result},
|
||||
Function, Table, Time, ValueType, VariableMap,
|
||||
Expression, Function, Table, Time, ValueType, VariableMap,
|
||||
};
|
||||
|
||||
use json::JsonValue;
|
||||
@ -64,9 +64,8 @@ impl Value {
|
||||
Ok(Value::Integer(raw))
|
||||
}
|
||||
"string" => {
|
||||
let without_quotes = &value_snippet[1..value_snippet.len() - 1];
|
||||
|
||||
println!("{without_quotes}");
|
||||
let quote_str = &value_snippet.chars().nth(0).unwrap();
|
||||
let without_quotes = value_snippet.trim_matches(*quote_str);
|
||||
|
||||
Ok(Value::String(without_quotes.to_string()))
|
||||
}
|
||||
@ -99,9 +98,44 @@ impl Value {
|
||||
|
||||
Ok(Value::List(values))
|
||||
}
|
||||
"table" => {
|
||||
let child_count = node.child_count();
|
||||
let mut column_names = Vec::new();
|
||||
let mut rows = Vec::new();
|
||||
|
||||
// Skip the first and last nodes because they are pointy braces.
|
||||
for index in 1..child_count - 1 {
|
||||
let child = node.child(index).unwrap();
|
||||
|
||||
if child.kind() == "identifier" {
|
||||
let child_expression = Expression::new(child, source)?;
|
||||
|
||||
if let Expression::Identifier(column_name) = child_expression {
|
||||
column_names.push(column_name)
|
||||
}
|
||||
}
|
||||
|
||||
if child.kind() == "list" {
|
||||
let child_value = Value::new(child, source)?;
|
||||
|
||||
if let Value::List(row) = child_value {
|
||||
rows.push(row);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut table = Table::new(column_names);
|
||||
table.reserve(rows.len());
|
||||
|
||||
for row in rows {
|
||||
table.insert(row)?;
|
||||
}
|
||||
|
||||
Ok(Value::Table(table))
|
||||
}
|
||||
"empty" => Ok(Value::Empty),
|
||||
_ => Err(Error::UnexpectedSourceNode {
|
||||
expected: "integer, string, boolean or empty",
|
||||
expected: "integer, string, boolean, float, list or empty",
|
||||
actual: node.kind(),
|
||||
}),
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user