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>),
Math(Box<Math>),
Logic(Box<Logic>),
FunctionCall(FunctionCall),
FunctionCall(Box<FunctionCall>),
Tool(Box<BuiltInFunction>),
Yield(Yield),
Yield(Box<Yield>),
}
impl AbstractTree for Expression {
@ -37,10 +37,10 @@ impl AbstractTree for Expression {
"math" => Expression::Math(Box::new(Math::from_syntax_node(source, child)?)),
"logic" => Expression::Logic(Box::new(Logic::from_syntax_node(source, child)?)),
"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)?)),
"yield" => Expression::Yield(Yield::from_syntax_node(source, child)?),
"yield" => Expression::Yield(Box::new(Yield::from_syntax_node(source, child)?)),
_ => {
return Err(Error::UnexpectedSyntaxNode {
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 super::{expression::Expression, identifier::Identifier};
use super::expression::Expression;
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
pub enum FunctionCall {
BuiltIn(Box<BuiltInFunction>),
ContextDefined {
name: Identifier,
name: Expression,
arguments: Vec<Expression>,
},
}
@ -36,12 +36,9 @@ impl AbstractTree for FunctionCall {
FunctionCall::BuiltIn(Box::new(function))
} else {
let identifier = Identifier::from_syntax_node(source, function_node)?;
let name = Expression::from_syntax_node(source, function_node)?;
FunctionCall::ContextDefined {
name: identifier,
arguments,
}
FunctionCall::ContextDefined { name, arguments }
};
Ok(function_call)
@ -53,11 +50,18 @@ impl AbstractTree for FunctionCall {
FunctionCall::ContextDefined { name, arguments } => (name, arguments),
};
let definition = if let Some(value) = context.variables()?.get(name.inner()) {
value.as_function().cloned()?
let definition = if let Expression::Identifier(identifier) = name {
if let Some(value) = context.variables()?.get(identifier.inner()) {
value.as_function().cloned()
} else {
return Err(Error::FunctionIdentifierNotFound(identifier.clone()));
}
} else {
return Err(Error::FunctionIdentifierNotFound(name.clone()));
};
let name_run = name.run(source, context)?;
name_run.as_function().cloned()
}?;
let mut function_context = Map::clone_from(context)?;
if let Some(parameters) = definition.identifiers() {

View File

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

View File

@ -3,7 +3,7 @@ use tree_sitter::Node;
use crate::{
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.
@ -21,6 +21,7 @@ pub enum Statement {
Filter(Box<Filter>),
Find(Box<Find>),
Remove(Box<Remove>),
Use(Use),
Select(Box<Select>),
Insert(Box<Insert>),
IndexAssignment(Box<IndexAssignment>),
@ -74,6 +75,7 @@ impl AbstractTree for Statement {
"select" => Ok(Statement::Select(Box::new(Select::from_syntax_node(
source, child,
)?))),
"use" => Ok(Statement::Use(Use::from_syntax_node(source, child)?)),
"insert" => Ok(Statement::Insert(Box::new(Insert::from_syntax_node(
source, child,
)?))),
@ -103,6 +105,7 @@ impl AbstractTree for Statement {
Statement::Filter(filter) => filter.run(source, context),
Statement::Find(find) => find.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::Insert(insert) => insert.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 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)]
pub struct Use {
path: ValueNode,
path: String,
}
impl AbstractTree for Use {
fn from_syntax_node(source: &str, node: Node) -> Result<Self> {
let path_node = node.child(1).unwrap();
let value_node = ValueNode::from_syntax_node(source, path_node)?;
fn from_syntax_node(source: &str, node: tree_sitter::Node) -> crate::Result<Self> {
Error::expect_syntax_node(source, "use", 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> {
let run_node = self.path.run(source, context)?;
let path = run_node.as_string()?;
let file_contents = read_to_string(path)?;
let mut temp_context = VariableMap::new();
let eval_result = evaluate_with_context(&file_contents, &mut temp_context)?;
fn run(&self, _source: &str, _context: &mut Map) -> Result<Value> {
let file_contents = read_to_string(&self.path)?;
let mut file_context = Map::new();
while let Some((key, value)) = temp_context.inner_mut().pop_first() {
context.set_value(key, value)?;
}
evaluate_with_context(&file_contents, &mut file_context)?;
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 tree_sitter::Node;
@ -11,21 +11,12 @@ use crate::{
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
pub struct ValueNode {
value_type: ValueType,
start_byte: usize,
end_byte: usize,
source: String,
}
impl ValueNode {
pub fn new(value_type: ValueType, start_byte: usize, end_byte: usize) -> Self {
Self {
value_type,
start_byte,
end_byte,
}
}
pub fn byte_range(&self) -> Range<usize> {
self.start_byte..self.end_byte
pub fn new(value_type: ValueType, source: String) -> Self {
Self { value_type, source }
}
}
@ -136,23 +127,21 @@ impl AbstractTree for ValueNode {
Ok(ValueNode {
value_type,
start_byte: child.start_byte(),
end_byte: child.end_byte(),
source: source[child.byte_range()].to_string(),
})
}
fn run(&self, source: &str, context: &mut Map) -> Result<Value> {
let value_source = &source[self.byte_range()];
let value = match &self.value_type {
ValueType::Any => todo!(),
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())
}
ValueType::Float => Value::Float(value_source.parse().unwrap()),
ValueType::Integer => Value::Integer(value_source.parse().unwrap()),
ValueType::Boolean => Value::Boolean(value_source.parse().unwrap()),
ValueType::Float => Value::Float(self.source.parse().unwrap()),
ValueType::Integer => Value::Integer(self.source.parse().unwrap()),
ValueType::Boolean => Value::Boolean(self.source.parse().unwrap()),
ValueType::List(nodes) => {
let mut values = Vec::with_capacity(nodes.len());

View File

@ -1,7 +1,7 @@
use serde::{Deserialize, Serialize};
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)]
pub struct Yield {
@ -33,12 +33,9 @@ impl AbstractTree for Yield {
FunctionCall::BuiltIn(Box::new(function))
} else {
let identifier = Identifier::from_syntax_node(source, function_node)?;
let name = Expression::from_syntax_node(source, function_node)?;
FunctionCall::ContextDefined {
name: identifier,
arguments,
}
FunctionCall::ContextDefined { name, arguments }
};
Ok(Yield { call })

View File

@ -1,5 +1,4 @@
//! Command line interface for the dust programming language.
use async_std::fs::read_to_string;
use clap::Parser;
use rustyline::{
completion::FilenameCompleter,
@ -11,7 +10,7 @@ use rustyline::{
};
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};
@ -39,8 +38,7 @@ struct Args {
path: Option<String>,
}
#[async_std::main]
async fn main() {
fn main() {
let args = Args::parse();
if args.path.is_none() && args.command.is_none() {
@ -48,7 +46,7 @@ async fn main() {
}
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 {
command.clone()
} else {
@ -65,7 +63,7 @@ async fn main() {
}
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
.variables_mut()

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff