Implement function calls; Remove Time
This commit is contained in:
parent
3e87d8b322
commit
31e9cb61bb
@ -1,7 +1,7 @@
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tree_sitter::Node;
|
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};
|
use super::{function_call::FunctionCall, logic::Logic, math::Math};
|
||||||
|
|
||||||
@ -12,7 +12,7 @@ pub enum Expression {
|
|||||||
Math(Box<Math>),
|
Math(Box<Math>),
|
||||||
Logic(Box<Logic>),
|
Logic(Box<Logic>),
|
||||||
FunctionCall(FunctionCall),
|
FunctionCall(FunctionCall),
|
||||||
ToolCall(Box<ToolCall>),
|
ToolCall(Box<Tool>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AbstractTree for Expression {
|
impl AbstractTree for Expression {
|
||||||
@ -29,9 +29,7 @@ impl AbstractTree for Expression {
|
|||||||
"function_call" => {
|
"function_call" => {
|
||||||
Expression::FunctionCall(FunctionCall::from_syntax_node(child, source)?)
|
Expression::FunctionCall(FunctionCall::from_syntax_node(child, source)?)
|
||||||
}
|
}
|
||||||
"tool_call" => {
|
"tool_call" => Expression::ToolCall(Box::new(Tool::from_syntax_node(child, source)?)),
|
||||||
Expression::ToolCall(Box::new(ToolCall::from_syntax_node(child, source)?))
|
|
||||||
}
|
|
||||||
_ => {
|
_ => {
|
||||||
return Err(Error::UnexpectedSyntax {
|
return Err(Error::UnexpectedSyntax {
|
||||||
expected: "value, identifier, math or function_call",
|
expected: "value, identifier, math or function_call",
|
||||||
|
@ -39,12 +39,28 @@ impl AbstractTree for FunctionCall {
|
|||||||
fn run(&self, context: &mut VariableMap) -> Result<Value> {
|
fn run(&self, context: &mut VariableMap) -> Result<Value> {
|
||||||
let identifier = &self.identifier;
|
let identifier = &self.identifier;
|
||||||
let definition = if let Some(value) = context.get_value(identifier.inner())? {
|
let definition = if let Some(value) = context.get_value(identifier.inner())? {
|
||||||
value
|
value.as_function().cloned()?
|
||||||
} else {
|
} else {
|
||||||
return Err(crate::Error::FunctionIdentifierNotFound(identifier.clone()));
|
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))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,11 +12,11 @@ use crate::{AbstractTree, Result, Value, VariableMap};
|
|||||||
pub struct Match {}
|
pub struct Match {}
|
||||||
|
|
||||||
impl AbstractTree for 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!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(&self, context: &mut VariableMap) -> Result<Value> {
|
fn run(&self, _context: &mut VariableMap) -> Result<Value> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ use serde::{Deserialize, Serialize};
|
|||||||
use tree_sitter::Node;
|
use tree_sitter::Node;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
tool::ToolCall, AbstractTree, Assignment, Error, Expression, IfElse, Match, Result, Value,
|
tool::Tool, AbstractTree, Assignment, Error, Expression, IfElse, Match, Result, Value,
|
||||||
VariableMap,
|
VariableMap,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -16,7 +16,7 @@ pub enum Statement {
|
|||||||
Expression(Expression),
|
Expression(Expression),
|
||||||
IfElse(Box<IfElse>),
|
IfElse(Box<IfElse>),
|
||||||
Match(Match),
|
Match(Match),
|
||||||
Tool(ToolCall),
|
Tool(Tool),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AbstractTree for Statement {
|
impl AbstractTree for Statement {
|
||||||
|
@ -4,21 +4,21 @@ use tree_sitter::Node;
|
|||||||
use crate::{AbstractTree, Error, Expression, Result, Value, VariableMap};
|
use crate::{AbstractTree, Error, Expression, Result, Value, VariableMap};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
||||||
pub enum ToolCall {
|
pub enum Tool {
|
||||||
Output(Expression),
|
Output(Expression),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AbstractTree for ToolCall {
|
impl AbstractTree for Tool {
|
||||||
fn from_syntax_node(node: Node, source: &str) -> Result<Self> {
|
fn from_syntax_node(node: Node, source: &str) -> Result<Self> {
|
||||||
let tool_node = node.child(1).unwrap();
|
let tool_node = node.child(1).unwrap();
|
||||||
let tool_name = tool_node.kind();
|
let tool_name = tool_node.kind();
|
||||||
|
|
||||||
match tool_name {
|
match tool_name {
|
||||||
"output" => {
|
"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)?;
|
let expression = Expression::from_syntax_node(expression_node, source)?;
|
||||||
|
|
||||||
Ok(ToolCall::Output(expression))
|
Ok(Tool::Output(expression))
|
||||||
}
|
}
|
||||||
_ => Err(Error::UnexpectedSyntax {
|
_ => Err(Error::UnexpectedSyntax {
|
||||||
expected: "output",
|
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 {
|
match self {
|
||||||
ToolCall::Output(expression) => {
|
Tool::Output(expression) => {
|
||||||
let value = expression.run(context)?;
|
let value = expression.run(context)?;
|
||||||
|
|
||||||
println!("{value}")
|
println!("{value}")
|
||||||
|
@ -283,7 +283,7 @@ impl From<toml::de::Error> for Error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Error {
|
impl Error {
|
||||||
pub(crate) fn expect_function_argument_amount(
|
pub(crate) fn _expect_function_argument_amount(
|
||||||
identifier: &str,
|
identifier: &str,
|
||||||
actual: usize,
|
actual: usize,
|
||||||
expected: 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,
|
identifier: &str,
|
||||||
actual: usize,
|
actual: usize,
|
||||||
minimum: usize,
|
minimum: usize,
|
||||||
|
@ -109,9 +109,7 @@ impl<'context, 'code> Evaluator<'context, 'code> {
|
|||||||
mod tests {
|
mod tests {
|
||||||
use crate::{
|
use crate::{
|
||||||
abstract_tree::{expression::Expression, identifier::Identifier, statement::Statement},
|
abstract_tree::{expression::Expression, identifier::Identifier, statement::Statement},
|
||||||
tool::ToolCall,
|
Function, Table,
|
||||||
value::variable_map,
|
|
||||||
Function, FunctionCall, Table,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
@ -290,20 +288,19 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn evaluate_function_call() {
|
fn evaluate_function_call() {
|
||||||
let mut context = VariableMap::new();
|
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!(
|
assert_eq!(
|
||||||
evaluate("(foobar 'Hiya')"),
|
evaluate_with_context(
|
||||||
vec![Ok(Value::String("Hiya".to_string()))]
|
"
|
||||||
|
foobar = function <message> { message }
|
||||||
|
(foobar 'Hiya')
|
||||||
|
",
|
||||||
|
&mut context
|
||||||
|
),
|
||||||
|
vec![
|
||||||
|
Ok(Value::Empty),
|
||||||
|
Ok(Value::List(vec![Value::String("Hiya".to_string())]))
|
||||||
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,8 +9,7 @@ pub use crate::{
|
|||||||
error::*,
|
error::*,
|
||||||
evaluator::*,
|
evaluator::*,
|
||||||
value::{
|
value::{
|
||||||
function::Function, table::Table, time::Time, value_type::ValueType,
|
function::Function, table::Table, value_type::ValueType, variable_map::VariableMap, Value,
|
||||||
variable_map::VariableMap, Value,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -17,6 +17,14 @@ impl Function {
|
|||||||
statements,
|
statements,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn identifiers(&self) -> &Vec<Identifier> {
|
||||||
|
&self.identifiers
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn statements(&self) -> &Vec<Statement> {
|
||||||
|
&self.statements
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for Function {
|
impl Display for Function {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
//! Types that represent runtime values.
|
//! Types that represent runtime values.
|
||||||
use crate::{
|
use crate::{
|
||||||
error::{Error, Result},
|
error::{Error, Result},
|
||||||
AbstractTree, Function, Identifier, Statement, Table, Time, ValueType, VariableMap,
|
AbstractTree, Function, Identifier, Statement, Table, ValueType, VariableMap,
|
||||||
};
|
};
|
||||||
|
|
||||||
use json::JsonValue;
|
use json::JsonValue;
|
||||||
@ -23,7 +23,6 @@ use std::{
|
|||||||
pub mod function;
|
pub mod function;
|
||||||
pub mod iter;
|
pub mod iter;
|
||||||
pub mod table;
|
pub mod table;
|
||||||
pub mod time;
|
|
||||||
pub mod value_type;
|
pub mod value_type;
|
||||||
pub mod variable_map;
|
pub mod variable_map;
|
||||||
|
|
||||||
@ -37,7 +36,6 @@ pub enum Value {
|
|||||||
List(Vec<Value>),
|
List(Vec<Value>),
|
||||||
Map(VariableMap),
|
Map(VariableMap),
|
||||||
Table(Table),
|
Table(Table),
|
||||||
Time(Time),
|
|
||||||
Function(Function),
|
Function(Function),
|
||||||
String(String),
|
String(String),
|
||||||
Float(f64),
|
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`.
|
/// Returns `()`, or returns`Err` if `self` is not a `Value::Tuple`.
|
||||||
pub fn as_empty(&self) -> Result<()> {
|
pub fn as_empty(&self) -> Result<()> {
|
||||||
match self {
|
match self {
|
||||||
@ -442,7 +431,6 @@ impl PartialEq for Value {
|
|||||||
(Value::List(left), Value::List(right)) => left == right,
|
(Value::List(left), Value::List(right)) => left == right,
|
||||||
(Value::Map(left), Value::Map(right)) => left == right,
|
(Value::Map(left), Value::Map(right)) => left == right,
|
||||||
(Value::Table(left), Value::Table(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::Function(left), Value::Function(right)) => left == right,
|
||||||
(Value::Empty, Value::Empty) => true,
|
(Value::Empty, Value::Empty) => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
@ -475,8 +463,6 @@ impl Ord for Value {
|
|||||||
(Value::Table(_), _) => Ordering::Greater,
|
(Value::Table(_), _) => Ordering::Greater,
|
||||||
(Value::Function(left), Value::Function(right)) => left.cmp(right),
|
(Value::Function(left), Value::Function(right)) => left.cmp(right),
|
||||||
(Value::Function(_), _) => Ordering::Greater,
|
(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, Value::Empty) => Ordering::Equal,
|
||||||
(Value::Empty, _) => Ordering::Less,
|
(Value::Empty, _) => Ordering::Less,
|
||||||
}
|
}
|
||||||
@ -506,7 +492,6 @@ impl Serialize for Value {
|
|||||||
Value::Map(inner) => inner.serialize(serializer),
|
Value::Map(inner) => inner.serialize(serializer),
|
||||||
Value::Table(inner) => inner.serialize(serializer),
|
Value::Table(inner) => inner.serialize(serializer),
|
||||||
Value::Function(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::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}"),
|
||||||
Value::Time(time) => write!(f, "{time}"),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -279,7 +279,6 @@ impl From<&Value> for Table {
|
|||||||
|
|
||||||
table
|
table
|
||||||
}
|
}
|
||||||
Value::Time(_) => todo!(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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())
|
|
||||||
}
|
|
||||||
}
|
|
@ -107,7 +107,6 @@ impl From<&Value> for ValueType {
|
|||||||
Value::Map(_) => ValueType::Map,
|
Value::Map(_) => ValueType::Map,
|
||||||
Value::Table { .. } => ValueType::Table,
|
Value::Table { .. } => ValueType::Table,
|
||||||
Value::Function(_) => ValueType::Function,
|
Value::Function(_) => ValueType::Function,
|
||||||
Value::Time(_) => ValueType::Time,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ use std::{
|
|||||||
fmt::{self, Display, Formatter},
|
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.
|
/// A collection dust variables comprised of key-value pairs.
|
||||||
///
|
///
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit 03c566485155076983ff78689c62839c59b47327
|
Subproject commit a3dbb19ecc40bc49487730c7679358389307559d
|
Loading…
Reference in New Issue
Block a user