From fb78798a1dfccff337ed8aaa440b037605c4cf2e Mon Sep 17 00:00:00 2001 From: Jeff Date: Sun, 21 Apr 2024 17:00:08 -0400 Subject: [PATCH] Begin revising built-in functions --- .../abstract_tree/built_in_function_call.rs | 35 ++++++++ dust-lang/src/abstract_tree/expression.rs | 9 +- dust-lang/src/abstract_tree/function_call.rs | 22 ++--- dust-lang/src/abstract_tree/mod.rs | 2 + dust-lang/src/abstract_tree/value_node.rs | 8 -- dust-lang/src/built_in_functions.rs | 88 ------------------- dust-lang/src/lexer.rs | 33 +++---- dust-lang/src/lib.rs | 1 - dust-lang/src/parser.rs | 47 ++++++---- dust-lang/src/value.rs | 85 +++++++----------- 10 files changed, 132 insertions(+), 198 deletions(-) create mode 100644 dust-lang/src/abstract_tree/built_in_function_call.rs delete mode 100644 dust-lang/src/built_in_functions.rs diff --git a/dust-lang/src/abstract_tree/built_in_function_call.rs b/dust-lang/src/abstract_tree/built_in_function_call.rs new file mode 100644 index 0000000..026c8f7 --- /dev/null +++ b/dust-lang/src/abstract_tree/built_in_function_call.rs @@ -0,0 +1,35 @@ +use std::{ + fmt::{self, Display, Formatter}, + io::stdin, + thread, + time::Duration, +}; + +use crate::{ + abstract_tree::{Action, Type}, + context::Context, + error::RuntimeError, +}; + +use super::{AbstractNode, Expression, WithPosition}; + +#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] +pub enum BuiltInFunctionCall { + ReadLine, + Sleep(Expression), + WriteLine(Expression), +} + +impl AbstractNode for BuiltInFunctionCall { + fn expected_type(&self, context: &Context) -> Result { + todo!() + } + + fn validate(&self, context: &Context) -> Result<(), crate::error::ValidationError> { + todo!() + } + + fn run(self, context: &Context) -> Result { + todo!() + } +} diff --git a/dust-lang/src/abstract_tree/expression.rs b/dust-lang/src/abstract_tree/expression.rs index 37f0015..7325f5a 100644 --- a/dust-lang/src/abstract_tree/expression.rs +++ b/dust-lang/src/abstract_tree/expression.rs @@ -5,12 +5,13 @@ use crate::{ }; use super::{ - AbstractNode, Action, FunctionCall, ListIndex, Logic, MapIndex, Math, SourcePosition, Type, - ValueNode, WithPosition, + AbstractNode, Action, BuiltInFunctionCall, FunctionCall, ListIndex, Logic, MapIndex, Math, + SourcePosition, Type, ValueNode, WithPosition, }; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] pub enum Expression { + BuiltInFunctionCall(WithPosition>), FunctionCall(WithPosition), Identifier(WithPosition), MapIndex(WithPosition>), @@ -30,6 +31,7 @@ impl Expression { Expression::Logic(inner) => inner.position, Expression::Math(inner) => inner.position, Expression::Value(inner) => inner.position, + Expression::BuiltInFunctionCall(inner) => inner.position, } } } @@ -53,6 +55,7 @@ impl AbstractNode for Expression { Expression::Logic(logic) => logic.node.expected_type(_context), Expression::Math(math) => math.node.expected_type(_context), Expression::Value(value_node) => value_node.node.expected_type(_context), + Expression::BuiltInFunctionCall(_) => todo!(), } } @@ -74,6 +77,7 @@ impl AbstractNode for Expression { Expression::Logic(logic) => logic.node.validate(context), Expression::Math(math) => math.node.validate(context), Expression::Value(value_node) => value_node.node.validate(context), + Expression::BuiltInFunctionCall(_) => todo!(), } } @@ -97,6 +101,7 @@ impl AbstractNode for Expression { Expression::Logic(logic) => logic.node.run(_context), Expression::Math(math) => math.node.run(_context), Expression::Value(value_node) => value_node.node.run(_context), + Expression::BuiltInFunctionCall(_) => todo!(), } } } diff --git a/dust-lang/src/abstract_tree/function_call.rs b/dust-lang/src/abstract_tree/function_call.rs index 66c6294..e9206f5 100644 --- a/dust-lang/src/abstract_tree/function_call.rs +++ b/dust-lang/src/abstract_tree/function_call.rs @@ -1,7 +1,7 @@ use crate::{ context::Context, error::{RuntimeError, ValidationError}, - value::{Function, ParsedFunction, ValueInner}, + value::ValueInner, }; use super::{AbstractNode, Action, Expression, Type, WithPosition}; @@ -133,20 +133,16 @@ impl AbstractNode for FunctionCall { let function_context = Context::new(); - if let Function::Parsed(ParsedFunction { - type_parameters, .. - }) = function + for (type_parameter, type_argument) in function + .type_parameters() + .iter() + .map(|r#type| r#type.node.clone()) + .zip(self.type_arguments.into_iter().map(|r#type| r#type.node)) { - for (type_parameter, type_argument) in type_parameters - .iter() - .map(|r#type| r#type.node.clone()) - .zip(self.type_arguments.into_iter().map(|r#type| r#type.node)) - { - if let Type::Argument(identifier) = type_parameter { - function_context.set_type(identifier, type_argument)?; - } + if let Type::Argument(identifier) = type_parameter { + function_context.set_type(identifier, type_argument)?; } - }; + } function_context.inherit_data_from(&context)?; function.clone().call(arguments, function_context) diff --git a/dust-lang/src/abstract_tree/mod.rs b/dust-lang/src/abstract_tree/mod.rs index 6951b5c..8c78271 100644 --- a/dust-lang/src/abstract_tree/mod.rs +++ b/dust-lang/src/abstract_tree/mod.rs @@ -1,6 +1,7 @@ pub mod assignment; pub mod async_block; pub mod block; +pub mod built_in_function_call; pub mod expression; pub mod function_call; pub mod if_else; @@ -23,6 +24,7 @@ pub use self::{ assignment::{Assignment, AssignmentOperator}, async_block::AsyncBlock, block::Block, + built_in_function_call::BuiltInFunctionCall, expression::Expression, function_call::FunctionCall, if_else::IfElse, diff --git a/dust-lang/src/abstract_tree/value_node.rs b/dust-lang/src/abstract_tree/value_node.rs index c9a9d93..3308ad8 100644 --- a/dust-lang/src/abstract_tree/value_node.rs +++ b/dust-lang/src/abstract_tree/value_node.rs @@ -1,7 +1,6 @@ use std::{cmp::Ordering, collections::BTreeMap, ops::Range}; use crate::{ - built_in_functions::BuiltInFunction, context::Context, error::{RuntimeError, ValidationError}, identifier::Identifier, @@ -13,7 +12,6 @@ use super::{AbstractNode, Action, Block, Expression, Type, WithPos, WithPosition #[derive(Clone, Debug, PartialEq)] pub enum ValueNode { Boolean(bool), - BuiltInFunction(BuiltInFunction), Float(f64), Integer(i64), List(Vec), @@ -88,7 +86,6 @@ impl AbstractNode for ValueNode { fields: types, } } - ValueNode::BuiltInFunction(built_in_function) => built_in_function.r#type(), }; Ok(r#type) @@ -260,9 +257,6 @@ impl AbstractNode for ValueNode { Value::structure(name, fields) } - ValueNode::BuiltInFunction(built_in_function) => { - Value::built_in_function(built_in_function) - } }; Ok(Action::Return(value)) @@ -358,8 +352,6 @@ impl Ord for ValueNode { } } (Structure { .. }, _) => Ordering::Greater, - (BuiltInFunction(_), BuiltInFunction(_)) => todo!(), - (BuiltInFunction(_), _) => todo!(), } } } diff --git a/dust-lang/src/built_in_functions.rs b/dust-lang/src/built_in_functions.rs deleted file mode 100644 index 307d56c..0000000 --- a/dust-lang/src/built_in_functions.rs +++ /dev/null @@ -1,88 +0,0 @@ -use std::{ - fmt::{self, Display, Formatter}, - io::stdin, - thread, - time::Duration, -}; - -use crate::{ - abstract_tree::{Action, Type, WithPos}, - context::Context, - error::RuntimeError, - value::ValueInner, - Value, -}; - -#[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord)] -pub enum BuiltInFunction { - ReadLine, - Sleep, - WriteLine, -} - -impl BuiltInFunction { - pub fn name(&self) -> &'static str { - match self { - BuiltInFunction::ReadLine => "__READ_LINE__", - BuiltInFunction::Sleep => "__SLEEP__", - BuiltInFunction::WriteLine => "__WRITE_LINE__", - } - } - - pub fn as_value(self) -> Value { - Value::built_in_function(self) - } - - pub fn r#type(&self) -> Type { - match self { - BuiltInFunction::WriteLine => Type::Function { - parameter_types: vec![Type::String.with_position((0, 0))], - return_type: Box::new(Type::None.with_position((0, 0))), - }, - _ => { - todo!() - } - } - } - - pub fn call(&self, arguments: Vec, _context: &Context) -> Result { - match self { - // "INT_RANDOM_RANGE" => { - // let range = arguments.get(0).unwrap(); - - // if let ValueInner::Range(range) = range.inner().as_ref() { - // let random = thread_rng().gen_range(range.clone()); - - // Ok(Action::Return(Value::integer(random))) - // } else { - // panic!("Built-in function cannot have a non-function type.") - // } - // } - BuiltInFunction::ReadLine => { - let mut input = String::new(); - - stdin().read_line(&mut input)?; - - Ok(Action::Return(Value::string(input))) - } - BuiltInFunction::Sleep => { - if let ValueInner::Integer(milliseconds) = arguments[0].inner().as_ref() { - thread::sleep(Duration::from_millis(*milliseconds as u64)); - } - - Ok(Action::None) - } - BuiltInFunction::WriteLine => { - println!("{}", arguments[0]); - - Ok(Action::None) - } - } - } -} - -impl Display for BuiltInFunction { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { - write!(f, "{}", self.name()) - } -} diff --git a/dust-lang/src/lexer.rs b/dust-lang/src/lexer.rs index 282f494..7d90a09 100644 --- a/dust-lang/src/lexer.rs +++ b/dust-lang/src/lexer.rs @@ -5,12 +5,11 @@ use std::{ use chumsky::prelude::*; -use crate::{built_in_functions::BuiltInFunction, error::Error}; +use crate::error::Error; #[derive(Copy, Clone, Debug, PartialEq)] pub enum Token<'src> { Boolean(bool), - BuiltInFunction(BuiltInFunction), Integer(i64), Float(f64), String(&'src str), @@ -24,7 +23,6 @@ impl<'src> Display for Token<'src> { fn fmt(&self, f: &mut Formatter) -> fmt::Result { match self { Token::Boolean(boolean) => write!(f, "{boolean}"), - Token::BuiltInFunction(built_in_function) => write!(f, "{built_in_function}"), Token::Integer(integer) => write!(f, "{integer}"), Token::Float(float) => write!(f, "{float}"), Token::String(string) => write!(f, "{string}"), @@ -51,11 +49,14 @@ pub enum Keyword { Map, None, Range, + ReadLine, + Sleep, Struct, Str, Type, Loop, While, + WriteLine, } impl Display for Keyword { @@ -79,6 +80,9 @@ impl Display for Keyword { Keyword::Loop => write!(f, "loop"), Keyword::While => write!(f, "while"), Keyword::Type => write!(f, "type"), + Keyword::ReadLine => write!(f, "READ_LINE"), + Keyword::Sleep => write!(f, "SLEEP"), + Keyword::WriteLine => write!(f, "WRITE_LINE"), } } } @@ -146,6 +150,7 @@ pub enum Control { Semicolon, SkinnyArrow, FatArrow, + DoubleUnderscore, } impl Display for Control { @@ -167,6 +172,7 @@ impl Display for Control { Control::DoubleDot => write!(f, ".."), Control::SkinnyArrow => write!(f, "->"), Control::FatArrow => write!(f, "=>"), + Control::DoubleUnderscore => write!(f, "__"), } } } @@ -272,6 +278,7 @@ pub fn lexer<'src>() -> impl Parser< just("..").to(Control::DoubleDot), just(".").to(Control::Dot), just("$").to(Control::Dollar), + just("__").to(Control::DoubleUnderscore), )) .map(Token::Control); @@ -294,26 +301,14 @@ pub fn lexer<'src>() -> impl Parser< just("type").to(Keyword::Type), just("loop").to(Keyword::Loop), just("while").to(Keyword::While), + just("READ_LINE").to(Keyword::ReadLine), + just("SLEEP").to(Keyword::Sleep), + just("WRITE_LINE").to(Keyword::WriteLine), )) .map(Token::Keyword); - let built_in_function = choice(( - just(BuiltInFunction::ReadLine.name()).to(BuiltInFunction::ReadLine), - just(BuiltInFunction::Sleep.name()).to(BuiltInFunction::Sleep), - just(BuiltInFunction::WriteLine.name()).to(BuiltInFunction::WriteLine), - )) - .map(Token::BuiltInFunction); - choice(( - boolean, - float, - integer, - string, - keyword, - identifier, - control, - operator, - built_in_function, + boolean, float, integer, string, keyword, identifier, control, operator, )) .map_with(|token, state| (token, state.span())) .padded() diff --git a/dust-lang/src/lib.rs b/dust-lang/src/lib.rs index a60a2d1..da7e841 100644 --- a/dust-lang/src/lib.rs +++ b/dust-lang/src/lib.rs @@ -1,5 +1,4 @@ pub mod abstract_tree; -pub mod built_in_functions; pub mod context; pub mod error; pub mod identifier; diff --git a/dust-lang/src/parser.rs b/dust-lang/src/parser.rs index 655c5c6..da1c20e 100644 --- a/dust-lang/src/parser.rs +++ b/dust-lang/src/parser.rs @@ -255,16 +255,22 @@ pub fn parser<'src>( }, ); - let built_in_function = { - select! { - Token::BuiltInFunction(built_in_function) => built_in_function, - } - } - .map_with(|built_in_function, state| { - Expression::Value( - ValueNode::BuiltInFunction(built_in_function).with_position(state.span()), - ) - }); + let built_in_function_call = just(Token::Control(Control::DoubleUnderscore)) + .ignore_then(choice(( + just(Token::Keyword(Keyword::ReadLine)).to(BuiltInFunctionCall::ReadLine), + just(Token::Keyword(Keyword::Sleep)) + .ignore_then(expression.clone()) + .map(|expression| BuiltInFunctionCall::Sleep(expression)), + just(Token::Keyword(Keyword::WriteLine)) + .ignore_then(expression.clone()) + .map(|expression| BuiltInFunctionCall::WriteLine(expression)), + ))) + .then_ignore(just(Token::Control(Control::DoubleUnderscore))) + .map_with(|built_in_function_call, state| { + Expression::BuiltInFunctionCall( + Box::new(built_in_function_call).with_position(state.span()), + ) + }); let structure_field = identifier .clone() @@ -307,7 +313,6 @@ pub fn parser<'src>( range.clone(), structure_instance.clone(), parsed_function.clone(), - built_in_function.clone(), list.clone(), map.clone(), basic_value.clone(), @@ -475,11 +480,11 @@ pub fn parser<'src>( )); choice(( + built_in_function_call, logic_math_indexes_and_function_calls, range, structure_instance, parsed_function, - built_in_function, list, map, basic_value, @@ -588,7 +593,7 @@ pub fn parser<'src>( #[cfg(test)] mod tests { - use crate::{built_in_functions::BuiltInFunction, lexer::lex}; + use crate::lexer::lex; use super::*; @@ -596,10 +601,20 @@ mod tests { fn built_in_function() { assert_eq!( parse(&lex("__READ_LINE__").unwrap()).unwrap()[0], - Statement::Expression(Expression::Value( - ValueNode::BuiltInFunction(BuiltInFunction::ReadLine).with_position((0, 13)) + Statement::Expression(Expression::BuiltInFunctionCall( + Box::new(BuiltInFunctionCall::ReadLine).with_position((0, 13)) )) - ) + ); + + assert_eq!( + parse(&lex("__WRITE_LINE 'hiya'__").unwrap()).unwrap()[0], + Statement::Expression(Expression::BuiltInFunctionCall( + Box::new(BuiltInFunctionCall::WriteLine(Expression::Value( + ValueNode::String("hiya".to_string()).with_position((13, 19)) + ))) + .with_position((0, 21)) + )) + ); } #[test] diff --git a/dust-lang/src/value.rs b/dust-lang/src/value.rs index cb6d2f2..4df9962 100644 --- a/dust-lang/src/value.rs +++ b/dust-lang/src/value.rs @@ -14,7 +14,6 @@ use stanza::{ use crate::{ abstract_tree::{AbstractNode, Action, Block, Type, WithPos, WithPosition}, - built_in_functions::BuiltInFunction, context::Context, error::{RuntimeError, ValidationError}, identifier::Identifier, @@ -62,24 +61,18 @@ impl Value { return_type: WithPosition, body: WithPosition, ) -> Self { - Value(Arc::new(ValueInner::Function(Function::Parsed( - ParsedFunction { - type_parameters: type_arguments, - parameters, - return_type, - body, - }, - )))) + Value(Arc::new(ValueInner::Function(Function { + type_parameters: type_arguments, + parameters, + return_type, + body, + }))) } pub fn structure(name: WithPosition, fields: Vec<(Identifier, Value)>) -> Self { Value(Arc::new(ValueInner::Structure { name, fields })) } - pub fn built_in_function(function: BuiltInFunction) -> Self { - Value(Arc::new(ValueInner::Function(Function::BuiltIn(function)))) - } - pub fn r#type(&self, context: &Context) -> Result { self.0.r#type(context) } @@ -139,12 +132,12 @@ impl Display for Value { } ValueInner::Range(_) => todo!(), ValueInner::String(string) => write!(f, "{string}"), - ValueInner::Function(Function::Parsed(ParsedFunction { + ValueInner::Function(Function { type_parameters: type_arguments, parameters, return_type, body, - })) => { + }) => { if !type_arguments.is_empty() { write!(f, "(")?; @@ -167,8 +160,8 @@ impl Display for Value { write!(f, "): {} {:?}", return_type.node, body.node) } - ValueInner::Function(Function::BuiltIn(built_in_function)) => { - write!(f, "{built_in_function}") + ValueInner::Function(function) => { + write!(f, "{function}") } ValueInner::Structure { name, fields } => { let mut table = create_table(); @@ -231,18 +224,13 @@ impl ValueInner { ValueInner::Map(_) => Type::Map, ValueInner::Range(_) => Type::Range, ValueInner::String(_) => Type::String, - ValueInner::Function(function) => match function { - Function::Parsed(parsed_function) => Type::Function { - parameter_types: parsed_function - .parameters - .iter() - .map(|(_, r#type)| r#type.clone()) - .collect(), - return_type: Box::new(parsed_function.return_type.clone()), - }, - Function::BuiltIn(built_in_function) => { - built_in_function.clone().as_value().r#type(context)? - } + ValueInner::Function(function) => Type::Function { + parameter_types: function + .parameters + .iter() + .map(|(_, r#type)| r#type.clone()) + .collect(), + return_type: Box::new(function.return_type.clone()), }, ValueInner::Structure { name, .. } => { if let Some(r#type) = context.get_type(&name.node)? { @@ -321,34 +309,29 @@ impl Ord for ValueInner { } #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] -pub enum Function { - Parsed(ParsedFunction), - BuiltIn(BuiltInFunction), +pub struct Function { + type_parameters: Vec>, + parameters: Vec<(Identifier, WithPosition)>, + return_type: WithPosition, + body: WithPosition, } impl Function { + pub fn type_parameters(&self) -> &Vec> { + &self.type_parameters + } + pub fn call(self, arguments: Vec, context: Context) -> Result { - let action = match self { - Function::Parsed(ParsedFunction { - parameters, body, .. - }) => { - for ((identifier, _), value) in parameters.into_iter().zip(arguments.into_iter()) { - context.set_value(identifier.clone(), value)?; - } + for ((identifier, _), value) in self.parameters.into_iter().zip(arguments.into_iter()) { + context.set_value(identifier.clone(), value)?; + } - body.node.run(&context)? - } - Function::BuiltIn(built_in_function) => built_in_function.call(arguments, &context)?, - }; - - Ok(action) + self.body.node.run(&context) } } -#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] -pub struct ParsedFunction { - pub type_parameters: Vec>, - pub parameters: Vec<(Identifier, WithPosition)>, - pub return_type: WithPosition, - pub body: WithPosition, +impl Display for Function { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + todo!() + } }