Implement use statement; Rework value generation

This commit is contained in:
Jeff 2023-11-17 20:10:07 -05:00
parent 97447d6d8b
commit 83390b53a7
16 changed files with 12991 additions and 12452 deletions

View File

@ -15,9 +15,9 @@ pub enum Expression {
Index(Box<Index>), Index(Box<Index>),
Math(Box<Math>), Math(Box<Math>),
Logic(Box<Logic>), Logic(Box<Logic>),
FunctionCall(FunctionCall), FunctionCall(Box<FunctionCall>),
Tool(Box<BuiltInFunction>), Tool(Box<BuiltInFunction>),
Yield(Yield), Yield(Box<Yield>),
} }
impl AbstractTree for Expression { impl AbstractTree for Expression {
@ -37,10 +37,10 @@ impl AbstractTree for Expression {
"math" => Expression::Math(Box::new(Math::from_syntax_node(source, child)?)), "math" => Expression::Math(Box::new(Math::from_syntax_node(source, child)?)),
"logic" => Expression::Logic(Box::new(Logic::from_syntax_node(source, child)?)), "logic" => Expression::Logic(Box::new(Logic::from_syntax_node(source, child)?)),
"function_call" => { "function_call" => {
Expression::FunctionCall(FunctionCall::from_syntax_node(source, child)?) Expression::FunctionCall(Box::new(FunctionCall::from_syntax_node(source, child)?))
} }
"tool" => Expression::Tool(Box::new(BuiltInFunction::from_syntax_node(source, child)?)), "tool" => Expression::Tool(Box::new(BuiltInFunction::from_syntax_node(source, child)?)),
"yield" => Expression::Yield(Yield::from_syntax_node(source, child)?), "yield" => Expression::Yield(Box::new(Yield::from_syntax_node(source, child)?)),
_ => { _ => {
return Err(Error::UnexpectedSyntaxNode { return Err(Error::UnexpectedSyntaxNode {
expected: "value, identifier, index, math, logic, function_call or yield", expected: "value, identifier, index, math, logic, function_call or yield",

View File

@ -3,13 +3,13 @@ use tree_sitter::Node;
use crate::{AbstractTree, BuiltInFunction, Error, Map, Result, Value}; use crate::{AbstractTree, BuiltInFunction, Error, Map, Result, Value};
use super::{expression::Expression, identifier::Identifier}; use super::expression::Expression;
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
pub enum FunctionCall { pub enum FunctionCall {
BuiltIn(Box<BuiltInFunction>), BuiltIn(Box<BuiltInFunction>),
ContextDefined { ContextDefined {
name: Identifier, name: Expression,
arguments: Vec<Expression>, arguments: Vec<Expression>,
}, },
} }
@ -36,12 +36,9 @@ impl AbstractTree for FunctionCall {
FunctionCall::BuiltIn(Box::new(function)) FunctionCall::BuiltIn(Box::new(function))
} else { } else {
let identifier = Identifier::from_syntax_node(source, function_node)?; let name = Expression::from_syntax_node(source, function_node)?;
FunctionCall::ContextDefined { FunctionCall::ContextDefined { name, arguments }
name: identifier,
arguments,
}
}; };
Ok(function_call) Ok(function_call)
@ -53,11 +50,18 @@ impl AbstractTree for FunctionCall {
FunctionCall::ContextDefined { name, arguments } => (name, arguments), FunctionCall::ContextDefined { name, arguments } => (name, arguments),
}; };
let definition = if let Some(value) = context.variables()?.get(name.inner()) { let definition = if let Expression::Identifier(identifier) = name {
value.as_function().cloned()? if let Some(value) = context.variables()?.get(identifier.inner()) {
value.as_function().cloned()
} else { } else {
return Err(Error::FunctionIdentifierNotFound(name.clone())); return Err(Error::FunctionIdentifierNotFound(identifier.clone()));
}; }
} else {
let name_run = name.run(source, context)?;
name_run.as_function().cloned()
}?;
let mut function_context = Map::clone_from(context)?; let mut function_context = Map::clone_from(context)?;
if let Some(parameters) = definition.identifiers() { if let Some(parameters) = definition.identifiers() {

View File

@ -26,6 +26,7 @@ pub mod remove;
pub mod select; pub mod select;
pub mod statement; pub mod statement;
pub mod transform; pub mod transform;
pub mod r#use;
pub mod value_node; pub mod value_node;
pub mod r#while; pub mod r#while;
pub mod r#yield; pub mod r#yield;
@ -33,8 +34,8 @@ pub mod r#yield;
pub use { pub use {
assignment::*, block::*, built_in_function::*, expression::*, filter::*, find::*, assignment::*, block::*, built_in_function::*, expression::*, filter::*, find::*,
function_call::*, identifier::*, if_else::*, index::*, index_assignment::IndexAssignment, function_call::*, identifier::*, if_else::*, index::*, index_assignment::IndexAssignment,
insert::*, logic::*, math::*, r#for::*, r#match::*, r#while::*, r#yield::*, remove::*, insert::*, logic::*, math::*, r#for::*, r#match::*, r#use::*, r#while::*, r#yield::*,
select::*, statement::*, transform::*, value_node::*, remove::*, select::*, statement::*, transform::*, value_node::*,
}; };
use tree_sitter::Node; use tree_sitter::Node;

View File

@ -3,7 +3,7 @@ use tree_sitter::Node;
use crate::{ use crate::{
AbstractTree, Assignment, Block, Error, Expression, Filter, Find, For, IfElse, IndexAssignment, AbstractTree, Assignment, Block, Error, Expression, Filter, Find, For, IfElse, IndexAssignment,
Insert, Map, Match, Remove, Result, Select, Transform, Value, While, Insert, Map, Match, Remove, Result, Select, Transform, Use, Value, While,
}; };
/// Abstract representation of a statement. /// Abstract representation of a statement.
@ -21,6 +21,7 @@ pub enum Statement {
Filter(Box<Filter>), Filter(Box<Filter>),
Find(Box<Find>), Find(Box<Find>),
Remove(Box<Remove>), Remove(Box<Remove>),
Use(Use),
Select(Box<Select>), Select(Box<Select>),
Insert(Box<Insert>), Insert(Box<Insert>),
IndexAssignment(Box<IndexAssignment>), IndexAssignment(Box<IndexAssignment>),
@ -74,6 +75,7 @@ impl AbstractTree for Statement {
"select" => Ok(Statement::Select(Box::new(Select::from_syntax_node( "select" => Ok(Statement::Select(Box::new(Select::from_syntax_node(
source, child, source, child,
)?))), )?))),
"use" => Ok(Statement::Use(Use::from_syntax_node(source, child)?)),
"insert" => Ok(Statement::Insert(Box::new(Insert::from_syntax_node( "insert" => Ok(Statement::Insert(Box::new(Insert::from_syntax_node(
source, child, source, child,
)?))), )?))),
@ -103,6 +105,7 @@ impl AbstractTree for Statement {
Statement::Filter(filter) => filter.run(source, context), Statement::Filter(filter) => filter.run(source, context),
Statement::Find(find) => find.run(source, context), Statement::Find(find) => find.run(source, context),
Statement::Remove(remove) => remove.run(source, context), Statement::Remove(remove) => remove.run(source, context),
Statement::Use(run) => run.run(source, context),
Statement::Select(select) => select.run(source, context), Statement::Select(select) => select.run(source, context),
Statement::Insert(insert) => insert.run(source, context), Statement::Insert(insert) => insert.run(source, context),
Statement::IndexAssignment(index_assignment) => index_assignment.run(source, context), Statement::IndexAssignment(index_assignment) => index_assignment.run(source, context),

View File

@ -1,34 +1,32 @@
use std::fs::read_to_string; use std::fs::read_to_string;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tree_sitter::Node;
use crate::{evaluate_with_context, AbstractTree, Result, Value, ValueNode, VariableMap}; use crate::{evaluate_with_context, AbstractTree, Error, Map, Result, Value};
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
pub struct Use { pub struct Use {
path: ValueNode, path: String,
} }
impl AbstractTree for Use { impl AbstractTree for Use {
fn from_syntax_node(source: &str, node: Node) -> Result<Self> { fn from_syntax_node(source: &str, node: tree_sitter::Node) -> crate::Result<Self> {
let path_node = node.child(1).unwrap(); Error::expect_syntax_node(source, "use", node)?;
let value_node = ValueNode::from_syntax_node(source, path_node)?;
Ok(Use { path: value_node }) let string_node = node.child(1).unwrap();
let path = source[string_node.start_byte() + 1..string_node.end_byte() - 1].to_string();
println!("{path}");
Ok(Use { path })
} }
fn run(&self, source: &str, context: &mut VariableMap) -> Result<Value> { fn run(&self, _source: &str, _context: &mut Map) -> Result<Value> {
let run_node = self.path.run(source, context)?; let file_contents = read_to_string(&self.path)?;
let path = run_node.as_string()?; let mut file_context = Map::new();
let file_contents = read_to_string(path)?;
let mut temp_context = VariableMap::new();
let eval_result = evaluate_with_context(&file_contents, &mut temp_context)?;
while let Some((key, value)) = temp_context.inner_mut().pop_first() { evaluate_with_context(&file_contents, &mut file_context)?;
context.set_value(key, value)?;
}
Ok(eval_result) Ok(Value::Map(file_context))
} }
} }

View File

@ -1,4 +1,4 @@
use std::{collections::BTreeMap, ops::Range}; use std::collections::BTreeMap;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tree_sitter::Node; use tree_sitter::Node;
@ -11,21 +11,12 @@ use crate::{
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
pub struct ValueNode { pub struct ValueNode {
value_type: ValueType, value_type: ValueType,
start_byte: usize, source: String,
end_byte: usize,
} }
impl ValueNode { impl ValueNode {
pub fn new(value_type: ValueType, start_byte: usize, end_byte: usize) -> Self { pub fn new(value_type: ValueType, source: String) -> Self {
Self { Self { value_type, source }
value_type,
start_byte,
end_byte,
}
}
pub fn byte_range(&self) -> Range<usize> {
self.start_byte..self.end_byte
} }
} }
@ -136,23 +127,21 @@ impl AbstractTree for ValueNode {
Ok(ValueNode { Ok(ValueNode {
value_type, value_type,
start_byte: child.start_byte(), source: source[child.byte_range()].to_string(),
end_byte: child.end_byte(),
}) })
} }
fn run(&self, source: &str, context: &mut Map) -> Result<Value> { fn run(&self, source: &str, context: &mut Map) -> Result<Value> {
let value_source = &source[self.byte_range()];
let value = match &self.value_type { let value = match &self.value_type {
ValueType::Any => todo!(), ValueType::Any => todo!(),
ValueType::String => { ValueType::String => {
let without_quotes = &value_source[1..value_source.len() - 1]; let without_quotes = &self.source[1..self.source.len() - 1];
Value::String(without_quotes.to_string()) Value::String(without_quotes.to_string())
} }
ValueType::Float => Value::Float(value_source.parse().unwrap()), ValueType::Float => Value::Float(self.source.parse().unwrap()),
ValueType::Integer => Value::Integer(value_source.parse().unwrap()), ValueType::Integer => Value::Integer(self.source.parse().unwrap()),
ValueType::Boolean => Value::Boolean(value_source.parse().unwrap()), ValueType::Boolean => Value::Boolean(self.source.parse().unwrap()),
ValueType::List(nodes) => { ValueType::List(nodes) => {
let mut values = Vec::with_capacity(nodes.len()); let mut values = Vec::with_capacity(nodes.len());

View File

@ -1,7 +1,7 @@
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tree_sitter::Node; use tree_sitter::Node;
use crate::{AbstractTree, BuiltInFunction, Expression, FunctionCall, Identifier, Result, Value}; use crate::{AbstractTree, BuiltInFunction, Expression, FunctionCall, Result, Value};
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
pub struct Yield { pub struct Yield {
@ -33,12 +33,9 @@ impl AbstractTree for Yield {
FunctionCall::BuiltIn(Box::new(function)) FunctionCall::BuiltIn(Box::new(function))
} else { } else {
let identifier = Identifier::from_syntax_node(source, function_node)?; let name = Expression::from_syntax_node(source, function_node)?;
FunctionCall::ContextDefined { FunctionCall::ContextDefined { name, arguments }
name: identifier,
arguments,
}
}; };
Ok(Yield { call }) Ok(Yield { call })

View File

@ -1,5 +1,4 @@
//! Command line interface for the dust programming language. //! Command line interface for the dust programming language.
use async_std::fs::read_to_string;
use clap::Parser; use clap::Parser;
use rustyline::{ use rustyline::{
completion::FilenameCompleter, completion::FilenameCompleter,
@ -11,7 +10,7 @@ use rustyline::{
}; };
use tree_sitter::Parser as TSParser; use tree_sitter::Parser as TSParser;
use std::borrow::Cow; use std::{borrow::Cow, fs::read_to_string};
use dust_lang::{evaluate_with_context, language, Evaluator, Map, Value}; use dust_lang::{evaluate_with_context, language, Evaluator, Map, Value};
@ -39,8 +38,7 @@ struct Args {
path: Option<String>, path: Option<String>,
} }
#[async_std::main] fn main() {
async fn main() {
let args = Args::parse(); let args = Args::parse();
if args.path.is_none() && args.command.is_none() { if args.path.is_none() && args.command.is_none() {
@ -48,7 +46,7 @@ async fn main() {
} }
let source = if let Some(path) = &args.path { let source = if let Some(path) = &args.path {
read_to_string(path).await.unwrap() read_to_string(path).unwrap()
} else if let Some(command) = &args.command { } else if let Some(command) = &args.command {
command.clone() command.clone()
} else { } else {
@ -65,7 +63,7 @@ async fn main() {
} }
if let Some(path) = args.input_path { if let Some(path) = args.input_path {
let file_contents = read_to_string(path).await.unwrap(); let file_contents = read_to_string(path).unwrap();
context context
.variables_mut() .variables_mut()

View File

@ -106,7 +106,12 @@ impl From<&Value> for ValueType {
let value_nodes = list let value_nodes = list
.items() .items()
.iter() .iter()
.map(|value| Expression::Value(ValueNode::new(value.value_type(), 0, 0))) .map(|value| {
Expression::Value(ValueNode::new(
value.value_type(),
String::with_capacity(0),
))
})
.collect(); .collect();
ValueType::List(value_nodes) ValueType::List(value_nodes)
@ -116,7 +121,7 @@ impl From<&Value> for ValueType {
for (key, value) in map.variables().unwrap().iter() { for (key, value) in map.variables().unwrap().iter() {
let value_type = value.value_type(); let value_type = value.value_type();
let value_node = ValueNode::new(value_type, 0, 0); let value_node = ValueNode::new(value_type, String::with_capacity(0));
let statement = Statement::Expression(Expression::Value(value_node)); let statement = Statement::Expression(Expression::Value(value_node));
value_nodes.insert(key.to_string(), statement); value_nodes.insert(key.to_string(), statement);
@ -132,8 +137,7 @@ impl From<&Value> for ValueType {
.collect(), .collect(),
rows: Box::new(Expression::Value(ValueNode::new( rows: Box::new(Expression::Value(ValueNode::new(
ValueType::List(Vec::with_capacity(0)), ValueType::List(Vec::with_capacity(0)),
0, String::with_capacity(0),
0,
))), ))),
}, },
Value::Function(function) => ValueType::Function(function.clone()), Value::Function(function) => ValueType::Function(function.clone()),

View File

@ -52,7 +52,8 @@ Function Call
(statement (statement
(expression (expression
(function_call (function_call
(identifier) (expression
(identifier))
(expression (expression
(value (value
(string))))))) (string)))))))
@ -109,7 +110,8 @@ Complex Function Call
(statement (statement
(expression (expression
(function_call (function_call
(identifier) (expression
(identifier))
(expression (expression
(value (value
(string))) (string)))

View File

@ -108,8 +108,7 @@ x:(y):0
(expression (expression
(identifier)) (identifier))
(expression (expression
(function_call (identifier))))
(identifier)))))
(expression (expression
(value (value
(integer))))))) (integer)))))))

View File

@ -33,6 +33,9 @@ x -> (foo) -> (bar) -> (abc)
(yield (yield
(expression (expression
(identifier)) (identifier))
(identifier))) (expression
(identifier))) (identifier))))
(identifier))))) (expression
(identifier))))
(expression
(identifier))))))

View File

@ -33,6 +33,7 @@ module.exports = grammar({
$.match, $.match,
$.return, $.return,
$.select, $.select,
$.use,
$.while, $.while,
), ),
optional(';'), optional(';'),
@ -43,6 +44,11 @@ module.exports = grammar({
$.expression, $.expression,
), ),
use: $ => seq(
'use',
$.string,
),
expression: $ => prec.right(choice( expression: $ => prec.right(choice(
$._expression_kind, $._expression_kind,
seq('(', $._expression_kind, ')'), seq('(', $._expression_kind, ')'),
@ -268,7 +274,7 @@ module.exports = grammar({
)), )),
_context_defined_function: $ => prec.right(1, seq( _context_defined_function: $ => prec.right(1, seq(
$.identifier, $.expression,
optional($._expression_list), optional($._expression_list),
)), )),

View File

@ -98,6 +98,10 @@
"type": "SYMBOL", "type": "SYMBOL",
"name": "select" "name": "select"
}, },
{
"type": "SYMBOL",
"name": "use"
},
{ {
"type": "SYMBOL", "type": "SYMBOL",
"name": "while" "name": "while"
@ -132,6 +136,19 @@
} }
] ]
}, },
"use": {
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "use"
},
{
"type": "SYMBOL",
"name": "string"
}
]
},
"expression": { "expression": {
"type": "PREC_RIGHT", "type": "PREC_RIGHT",
"value": 0, "value": 0,
@ -1127,7 +1144,7 @@
"members": [ "members": [
{ {
"type": "SYMBOL", "type": "SYMBOL",
"name": "identifier" "name": "expression"
}, },
{ {
"type": "CHOICE", "type": "CHOICE",

View File

@ -199,10 +199,6 @@
{ {
"type": "expression", "type": "expression",
"named": true "named": true
},
{
"type": "identifier",
"named": true
} }
] ]
} }
@ -523,6 +519,10 @@
"type": "select", "type": "select",
"named": true "named": true
}, },
{
"type": "use",
"named": true
},
{ {
"type": "while", "type": "while",
"named": true "named": true
@ -549,6 +549,21 @@
] ]
} }
}, },
{
"type": "use",
"named": true,
"fields": {},
"children": {
"multiple": false,
"required": true,
"types": [
{
"type": "string",
"named": true
}
]
}
},
{ {
"type": "value", "type": "value",
"named": true, "named": true,
@ -626,10 +641,6 @@
{ {
"type": "expression", "type": "expression",
"named": true "named": true
},
{
"type": "identifier",
"named": true
} }
] ]
} }
@ -926,6 +937,10 @@
"type": "type", "type": "type",
"named": false "named": false
}, },
{
"type": "use",
"named": false
},
{ {
"type": "while", "type": "while",
"named": false "named": false

File diff suppressed because it is too large Load Diff