Continue revising built-in functions
This commit is contained in:
parent
fb78798a1d
commit
dbbb912b82
@ -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<Type, crate::error::ValidationError> {
|
||||
todo!()
|
||||
fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> {
|
||||
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<Action, RuntimeError> {
|
||||
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!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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))
|
||||
))
|
||||
);
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
io = {
|
||||
read_line = () str {
|
||||
__READ_LINE__()
|
||||
READ_LINE()
|
||||
}
|
||||
|
||||
write_line = (output: any) none {
|
||||
__WRITE_LINE__(output)
|
||||
WRITE_LINE(output)
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
thread = {
|
||||
sleep = (milliseconds: int) none {
|
||||
__SLEEP__(milliseconds)
|
||||
SLEEP(milliseconds)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user