diff --git a/dust-lang/src/abstract_tree/built_in_function_call.rs b/dust-lang/src/abstract_tree/built_in_function_call.rs index 026c8f7..79a09d9 100644 --- a/dust-lang/src/abstract_tree/built_in_function_call.rs +++ b/dust-lang/src/abstract_tree/built_in_function_call.rs @@ -1,17 +1,14 @@ -use std::{ - fmt::{self, Display, Formatter}, - io::stdin, - thread, - time::Duration, -}; +use std::{io::stdin, thread, time::Duration}; use crate::{ abstract_tree::{Action, Type}, context::Context, - error::RuntimeError, + error::{RuntimeError, ValidationError}, + value::ValueInner, + Value, }; -use super::{AbstractNode, Expression, WithPosition}; +use super::{AbstractNode, Expression}; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] pub enum BuiltInFunctionCall { @@ -21,15 +18,46 @@ pub enum BuiltInFunctionCall { } impl AbstractNode for BuiltInFunctionCall { - fn expected_type(&self, context: &Context) -> Result { - todo!() + fn expected_type(&self, _context: &Context) -> Result { + match self { + BuiltInFunctionCall::ReadLine => Ok(Type::String), + BuiltInFunctionCall::Sleep(_) => Ok(Type::None), + BuiltInFunctionCall::WriteLine(_) => Ok(Type::None), + } } - fn validate(&self, context: &Context) -> Result<(), crate::error::ValidationError> { - todo!() + fn validate(&self, _context: &Context) -> Result<(), ValidationError> { + Ok(()) } fn run(self, context: &Context) -> Result { - todo!() + match self { + BuiltInFunctionCall::ReadLine => { + let mut buffer = String::new(); + + stdin().read_line(&mut buffer)?; + + Ok(Action::Return(Value::string(buffer))) + } + BuiltInFunctionCall::Sleep(expression) => { + let expression_run = expression.clone().run(context)?; + let expression_value = if let Action::Return(value) = expression_run { + value + } else { + return Err(RuntimeError::ValidationFailure( + ValidationError::InterpreterExpectedReturn(expression.position()), + )); + }; + + if let ValueInner::Integer(milliseconds) = expression_value.inner().as_ref() { + thread::sleep(Duration::from_millis(*milliseconds as u64)); + + Ok(Action::None) + } else { + panic!("Expected an integer."); + } + } + BuiltInFunctionCall::WriteLine(_) => todo!(), + } } } diff --git a/dust-lang/src/abstract_tree/expression.rs b/dust-lang/src/abstract_tree/expression.rs index 7325f5a..3048eee 100644 --- a/dust-lang/src/abstract_tree/expression.rs +++ b/dust-lang/src/abstract_tree/expression.rs @@ -55,7 +55,9 @@ 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!(), + Expression::BuiltInFunctionCall(built_in_function_call) => { + built_in_function_call.node.expected_type(_context) + } } } @@ -77,7 +79,9 @@ 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!(), + Expression::BuiltInFunctionCall(built_in_function_call) => { + built_in_function_call.node.validate(context) + } } } @@ -101,7 +105,9 @@ 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!(), + Expression::BuiltInFunctionCall(built_in_function_call) => { + built_in_function_call.node.run(_context) + } } } } diff --git a/dust-lang/src/parser.rs b/dust-lang/src/parser.rs index da1c20e..fd34e67 100644 --- a/dust-lang/src/parser.rs +++ b/dust-lang/src/parser.rs @@ -255,22 +255,25 @@ pub fn parser<'src>( }, ); - 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 built_in_function_call = choice(( + just(Token::Keyword(Keyword::ReadLine)) + .ignore_then(just(Token::Control(Control::ParenOpen))) + .to(BuiltInFunctionCall::ReadLine), + just(Token::Keyword(Keyword::Sleep)) + .ignore_then(just(Token::Control(Control::ParenOpen))) + .ignore_then(expression.clone()) + .map(|expression| BuiltInFunctionCall::Sleep(expression)), + just(Token::Keyword(Keyword::WriteLine)) + .ignore_then(just(Token::Control(Control::ParenOpen))) + .ignore_then(expression.clone()) + .map(|expression| BuiltInFunctionCall::WriteLine(expression)), + )) + .then_ignore(just(Token::Control(Control::ParenClose))) + .map_with(|built_in_function_call, state| { + Expression::BuiltInFunctionCall( + Box::new(built_in_function_call).with_position(state.span()), + ) + }); let structure_field = identifier .clone() @@ -600,19 +603,19 @@ mod tests { #[test] fn built_in_function() { assert_eq!( - parse(&lex("__READ_LINE__").unwrap()).unwrap()[0], + parse(&lex("READ_LINE()").unwrap()).unwrap()[0], Statement::Expression(Expression::BuiltInFunctionCall( - Box::new(BuiltInFunctionCall::ReadLine).with_position((0, 13)) + Box::new(BuiltInFunctionCall::ReadLine).with_position((0, 11)) )) ); assert_eq!( - parse(&lex("__WRITE_LINE 'hiya'__").unwrap()).unwrap()[0], + 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)) + ValueNode::String("hiya".to_string()).with_position((11, 17)) ))) - .with_position((0, 21)) + .with_position((0, 18)) )) ); } diff --git a/std/io.ds b/std/io.ds index 953a7b7..3d7a986 100644 --- a/std/io.ds +++ b/std/io.ds @@ -1,9 +1,9 @@ io = { read_line = () str { - __READ_LINE__() + READ_LINE() } write_line = (output: any) none { - __WRITE_LINE__(output) + WRITE_LINE(output) } } diff --git a/std/thread.ds b/std/thread.ds index 8e5a6e2..4d69122 100644 --- a/std/thread.ds +++ b/std/thread.ds @@ -1,5 +1,5 @@ thread = { sleep = (milliseconds: int) none { - __SLEEP__(milliseconds) + SLEEP(milliseconds) } }