Implement use statement; Rework value generation
This commit is contained in:
parent
97447d6d8b
commit
83390b53a7
@ -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",
|
||||
|
@ -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() {
|
||||
|
@ -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;
|
||||
|
@ -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),
|
||||
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
@ -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());
|
||||
|
||||
|
@ -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 })
|
||||
|
10
src/main.rs
10
src/main.rs
@ -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()
|
||||
|
@ -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()),
|
||||
|
@ -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)))
|
||||
|
@ -108,8 +108,7 @@ x:(y):0
|
||||
(expression
|
||||
(identifier))
|
||||
(expression
|
||||
(function_call
|
||||
(identifier)))))
|
||||
(identifier))))
|
||||
(expression
|
||||
(value
|
||||
(integer)))))))
|
||||
|
@ -33,6 +33,9 @@ x -> (foo) -> (bar) -> (abc)
|
||||
(yield
|
||||
(expression
|
||||
(identifier))
|
||||
(identifier)))
|
||||
(identifier)))
|
||||
(identifier)))))
|
||||
(expression
|
||||
(identifier))))
|
||||
(expression
|
||||
(identifier))))
|
||||
(expression
|
||||
(identifier))))))
|
||||
|
@ -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),
|
||||
)),
|
||||
|
||||
|
@ -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",
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user