Implement function calls; Remove Time

This commit is contained in:
Jeff 2023-10-06 17:11:50 -04:00
parent 3e87d8b322
commit 31e9cb61bb
15 changed files with 58 additions and 157 deletions

View File

@ -1,7 +1,7 @@
use serde::{Deserialize, Serialize};
use tree_sitter::Node;
use crate::{tool::ToolCall, AbstractTree, Error, Identifier, Result, Value, VariableMap};
use crate::{tool::Tool, AbstractTree, Error, Identifier, Result, Value, VariableMap};
use super::{function_call::FunctionCall, logic::Logic, math::Math};
@ -12,7 +12,7 @@ pub enum Expression {
Math(Box<Math>),
Logic(Box<Logic>),
FunctionCall(FunctionCall),
ToolCall(Box<ToolCall>),
ToolCall(Box<Tool>),
}
impl AbstractTree for Expression {
@ -29,9 +29,7 @@ impl AbstractTree for Expression {
"function_call" => {
Expression::FunctionCall(FunctionCall::from_syntax_node(child, source)?)
}
"tool_call" => {
Expression::ToolCall(Box::new(ToolCall::from_syntax_node(child, source)?))
}
"tool_call" => Expression::ToolCall(Box::new(Tool::from_syntax_node(child, source)?)),
_ => {
return Err(Error::UnexpectedSyntax {
expected: "value, identifier, math or function_call",

View File

@ -39,12 +39,28 @@ impl AbstractTree for FunctionCall {
fn run(&self, context: &mut VariableMap) -> Result<Value> {
let identifier = &self.identifier;
let definition = if let Some(value) = context.get_value(identifier.inner())? {
value
value.as_function().cloned()?
} else {
return Err(crate::Error::FunctionIdentifierNotFound(identifier.clone()));
};
let mut arguments = Vec::with_capacity(self.expressions.len());
Ok(Value::List(arguments))
let id_expr_pairs = definition.identifiers().iter().zip(self.expressions.iter());
for (identifier, expression) in id_expr_pairs {
let key = identifier.clone().take_inner();
let value = expression.run(context)?;
context.set_value(key, value)?;
}
let mut results = Vec::with_capacity(self.expressions.len());
for statement in definition.statements() {
let result = statement.run(context)?;
results.push(result);
}
Ok(Value::List(results))
}
}

View File

@ -12,11 +12,11 @@ use crate::{AbstractTree, Result, Value, VariableMap};
pub struct Match {}
impl AbstractTree for Match {
fn from_syntax_node(node: Node, source: &str) -> Result<Self> {
fn from_syntax_node(_node: Node, _source: &str) -> Result<Self> {
todo!()
}
fn run(&self, context: &mut VariableMap) -> Result<Value> {
fn run(&self, _context: &mut VariableMap) -> Result<Value> {
todo!()
}
}

View File

@ -2,7 +2,7 @@ use serde::{Deserialize, Serialize};
use tree_sitter::Node;
use crate::{
tool::ToolCall, AbstractTree, Assignment, Error, Expression, IfElse, Match, Result, Value,
tool::Tool, AbstractTree, Assignment, Error, Expression, IfElse, Match, Result, Value,
VariableMap,
};
@ -16,7 +16,7 @@ pub enum Statement {
Expression(Expression),
IfElse(Box<IfElse>),
Match(Match),
Tool(ToolCall),
Tool(Tool),
}
impl AbstractTree for Statement {

View File

@ -4,21 +4,21 @@ use tree_sitter::Node;
use crate::{AbstractTree, Error, Expression, Result, Value, VariableMap};
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
pub enum ToolCall {
pub enum Tool {
Output(Expression),
}
impl AbstractTree for ToolCall {
impl AbstractTree for Tool {
fn from_syntax_node(node: Node, source: &str) -> Result<Self> {
let tool_node = node.child(1).unwrap();
let tool_name = tool_node.kind();
match tool_name {
"output" => {
let expression_node = node.child(1).unwrap();
let expression_node = tool_node.child(1).unwrap();
let expression = Expression::from_syntax_node(expression_node, source)?;
Ok(ToolCall::Output(expression))
Ok(Tool::Output(expression))
}
_ => Err(Error::UnexpectedSyntax {
expected: "output",
@ -29,9 +29,9 @@ impl AbstractTree for ToolCall {
}
}
fn run(&self, context: &mut VariableMap) -> Result<crate::Value> {
fn run(&self, context: &mut VariableMap) -> Result<Value> {
match self {
ToolCall::Output(expression) => {
Tool::Output(expression) => {
let value = expression.run(context)?;
println!("{value}")

View File

@ -283,7 +283,7 @@ impl From<toml::de::Error> for Error {
}
impl Error {
pub(crate) fn expect_function_argument_amount(
pub(crate) fn _expect_function_argument_amount(
identifier: &str,
actual: usize,
expected: usize,
@ -299,7 +299,7 @@ impl Error {
}
}
pub(crate) fn expected_minimum_function_argument_amount(
pub(crate) fn _expected_minimum_function_argument_amount(
identifier: &str,
actual: usize,
minimum: usize,

View File

@ -109,9 +109,7 @@ impl<'context, 'code> Evaluator<'context, 'code> {
mod tests {
use crate::{
abstract_tree::{expression::Expression, identifier::Identifier, statement::Statement},
tool::ToolCall,
value::variable_map,
Function, FunctionCall, Table,
Function, Table,
};
use super::*;
@ -290,20 +288,19 @@ mod tests {
#[test]
fn evaluate_function_call() {
let mut context = VariableMap::new();
let function = Function::new(
vec![Identifier::new("message".to_string())],
vec![Statement::Expression(Expression::Identifier(
Identifier::new("message".to_string()),
))],
);
context
.set_value("foobar".to_string(), Value::Function(function))
.unwrap();
assert_eq!(
evaluate("(foobar 'Hiya')"),
vec![Ok(Value::String("Hiya".to_string()))]
evaluate_with_context(
"
foobar = function <message> { message }
(foobar 'Hiya')
",
&mut context
),
vec![
Ok(Value::Empty),
Ok(Value::List(vec![Value::String("Hiya".to_string())]))
]
);
}

View File

@ -9,8 +9,7 @@ pub use crate::{
error::*,
evaluator::*,
value::{
function::Function, table::Table, time::Time, value_type::ValueType,
variable_map::VariableMap, Value,
function::Function, table::Table, value_type::ValueType, variable_map::VariableMap, Value,
},
};

View File

@ -17,6 +17,14 @@ impl Function {
statements,
}
}
pub fn identifiers(&self) -> &Vec<Identifier> {
&self.identifiers
}
pub fn statements(&self) -> &Vec<Statement> {
&self.statements
}
}
impl Display for Function {

View File

@ -1,7 +1,7 @@
//! Types that represent runtime values.
use crate::{
error::{Error, Result},
AbstractTree, Function, Identifier, Statement, Table, Time, ValueType, VariableMap,
AbstractTree, Function, Identifier, Statement, Table, ValueType, VariableMap,
};
use json::JsonValue;
@ -23,7 +23,6 @@ use std::{
pub mod function;
pub mod iter;
pub mod table;
pub mod time;
pub mod value_type;
pub mod variable_map;
@ -37,7 +36,6 @@ pub enum Value {
List(Vec<Value>),
Map(VariableMap),
Table(Table),
Time(Time),
Function(Function),
String(String),
Float(f64),
@ -347,15 +345,6 @@ impl Value {
}
}
/// Borrows the value stored in `self` as `Time`, or returns `Err` if
/// `self` is not a `Value::Time`.
pub fn as_time(&self) -> Result<&Time> {
match self {
Value::Time(time) => Ok(time),
value => Err(Error::expected_function(value.clone())),
}
}
/// Returns `()`, or returns`Err` if `self` is not a `Value::Tuple`.
pub fn as_empty(&self) -> Result<()> {
match self {
@ -442,7 +431,6 @@ impl PartialEq for Value {
(Value::List(left), Value::List(right)) => left == right,
(Value::Map(left), Value::Map(right)) => left == right,
(Value::Table(left), Value::Table(right)) => left == right,
(Value::Time(left), Value::Time(right)) => left == right,
(Value::Function(left), Value::Function(right)) => left == right,
(Value::Empty, Value::Empty) => true,
_ => false,
@ -475,8 +463,6 @@ impl Ord for Value {
(Value::Table(_), _) => Ordering::Greater,
(Value::Function(left), Value::Function(right)) => left.cmp(right),
(Value::Function(_), _) => Ordering::Greater,
(Value::Time(left), Value::Time(right)) => left.cmp(right),
(Value::Time(_), _) => Ordering::Greater,
(Value::Empty, Value::Empty) => Ordering::Equal,
(Value::Empty, _) => Ordering::Less,
}
@ -506,7 +492,6 @@ impl Serialize for Value {
Value::Map(inner) => inner.serialize(serializer),
Value::Table(inner) => inner.serialize(serializer),
Value::Function(inner) => inner.serialize(serializer),
Value::Time(inner) => inner.serialize(serializer),
}
}
}
@ -529,7 +514,6 @@ impl Display for Value {
Value::Map(map) => write!(f, "{map}"),
Value::Table(table) => write!(f, "{table}"),
Value::Function(function) => write!(f, "{function}"),
Value::Time(time) => write!(f, "{time}"),
}
}
}

View File

@ -279,7 +279,6 @@ impl From<&Value> for Table {
table
}
Value::Time(_) => todo!(),
}
}
}

View File

@ -1,99 +0,0 @@
//! Representation of a moment in time.
//!
//! Dust tries to represent time values correctly. To do this, there must be a clear separation
//! between monotonic timestamps, naive times that do not know their locale and those that have a ..
//! timezone.
//!
//! Only monotonic time instances are guaranteed not to repeat, although an Instant can be used to
//! create and of these variants. Users generally want the timezone included, so the `as_local` is
//! included, which will use no timezone offset if one is not available.
use std::{
fmt::{self, Display, Formatter},
time::{Instant, SystemTime},
};
use chrono::{DateTime, FixedOffset, Local as LocalTime, NaiveDateTime};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum Time {
Utc(NaiveDateTime),
Local(DateTime<LocalTime>),
Monotonic(Instant),
}
impl Time {
pub fn utc(instant: Instant) -> Self {
let utc =
NaiveDateTime::from_timestamp_micros(instant.elapsed().as_micros() as i64).unwrap();
Time::Utc(utc)
}
pub fn from_timestamp(microseconds: i64) -> Self {
let utc = NaiveDateTime::from_timestamp_micros(microseconds).unwrap();
Time::Utc(utc)
}
pub fn local(instant: Instant) -> Self {
let local = DateTime::from_local(
NaiveDateTime::from_timestamp_micros(instant.elapsed().as_micros() as i64).unwrap(),
FixedOffset::west_opt(0).unwrap(),
);
Time::Local(local)
}
pub fn monotonic(instant: Instant) -> Self {
Time::Monotonic(instant)
}
pub fn as_local(&self) -> String {
let date_time = match *self {
Time::Utc(utc) => DateTime::from_utc(utc, FixedOffset::west_opt(0).unwrap()),
Time::Local(local) => local,
Time::Monotonic(instant) => DateTime::from_utc(
NaiveDateTime::from_timestamp_millis(instant.elapsed().as_millis() as i64).unwrap(),
FixedOffset::west_opt(0).unwrap(),
),
};
date_time.to_rfc2822()
}
}
impl Display for Time {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
Time::Utc(inner) => write!(f, "{}", inner),
Time::Local(inner) => write!(f, "{}", inner),
Time::Monotonic(inner) => write!(f, "{:?}", inner),
}
}
}
impl Serialize for Time {
fn serialize<S>(&self, _serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
todo!()
}
}
impl<'de> Deserialize<'de> for Time {
fn deserialize<D>(_deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
todo!()
}
}
impl From<SystemTime> for Time {
fn from(value: SystemTime) -> Self {
Time::Local(value.into())
}
}

View File

@ -107,7 +107,6 @@ impl From<&Value> for ValueType {
Value::Map(_) => ValueType::Map,
Value::Table { .. } => ValueType::Table,
Value::Function(_) => ValueType::Function,
Value::Time(_) => ValueType::Time,
}
}
}

View File

@ -4,7 +4,7 @@ use std::{
fmt::{self, Display, Formatter},
};
use crate::{value::Value, AbstractTree, Error, Result, Table};
use crate::{value::Value, Error, Result, Table};
/// A collection dust variables comprised of key-value pairs.
///

@ -1 +1 @@
Subproject commit 03c566485155076983ff78689c62839c59b47327
Subproject commit a3dbb19ecc40bc49487730c7679358389307559d