Add fs.read_file to standard library
This commit is contained in:
parent
d4c0633fab
commit
c8dfbda447
@ -1,4 +1,5 @@
|
||||
use std::{
|
||||
fs::read_to_string,
|
||||
io::{stdin, stdout, Write},
|
||||
thread,
|
||||
time::Duration,
|
||||
@ -16,6 +17,7 @@ use super::{AbstractNode, Expression};
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
|
||||
pub enum BuiltInFunctionCall {
|
||||
ReadFile(Expression),
|
||||
ReadLine,
|
||||
Sleep(Expression),
|
||||
WriteLine(Expression),
|
||||
@ -24,6 +26,7 @@ pub enum BuiltInFunctionCall {
|
||||
impl AbstractNode for BuiltInFunctionCall {
|
||||
fn expected_type(&self, _context: &mut Context) -> Result<Type, ValidationError> {
|
||||
match self {
|
||||
BuiltInFunctionCall::ReadFile(_) => Ok(Type::String),
|
||||
BuiltInFunctionCall::ReadLine => Ok(Type::String),
|
||||
BuiltInFunctionCall::Sleep(_) => Ok(Type::None),
|
||||
BuiltInFunctionCall::WriteLine(_) => Ok(Type::None),
|
||||
@ -36,6 +39,9 @@ impl AbstractNode for BuiltInFunctionCall {
|
||||
_manage_memory: bool,
|
||||
) -> Result<(), ValidationError> {
|
||||
match self {
|
||||
BuiltInFunctionCall::ReadFile(expression) => {
|
||||
expression.validate(_context, _manage_memory)
|
||||
}
|
||||
BuiltInFunctionCall::ReadLine => Ok(()),
|
||||
BuiltInFunctionCall::Sleep(expression) => expression.validate(_context, _manage_memory),
|
||||
BuiltInFunctionCall::WriteLine(expression) => {
|
||||
@ -46,6 +52,24 @@ impl AbstractNode for BuiltInFunctionCall {
|
||||
|
||||
fn run(self, context: &mut Context, _manage_memory: bool) -> Result<Action, RuntimeError> {
|
||||
match self {
|
||||
BuiltInFunctionCall::ReadFile(expression) => {
|
||||
let action = expression.clone().run(context, _manage_memory)?;
|
||||
let value = if let Action::Return(value) = action {
|
||||
value
|
||||
} else {
|
||||
return Err(RuntimeError::ValidationFailure(
|
||||
ValidationError::InterpreterExpectedReturn(expression.position()),
|
||||
));
|
||||
};
|
||||
|
||||
let file_contents = if let ValueInner::String(path) = value.inner().as_ref() {
|
||||
read_to_string(path)?
|
||||
} else {
|
||||
String::with_capacity(0)
|
||||
};
|
||||
|
||||
Ok(Action::Return(Value::string(file_contents)))
|
||||
}
|
||||
BuiltInFunctionCall::ReadLine => {
|
||||
let mut buffer = String::new();
|
||||
|
||||
|
@ -94,6 +94,8 @@ impl AbstractNode for ValueNode {
|
||||
fn validate(&self, context: &mut Context, _manage_memory: bool) -> Result<(), ValidationError> {
|
||||
if let ValueNode::Map(map_assignments) = self {
|
||||
for (_identifier, r#type, expression) in map_assignments {
|
||||
expression.validate(context, _manage_memory)?;
|
||||
|
||||
if let Some(expected_type) = r#type {
|
||||
let actual_type = expression.expected_type(context)?;
|
||||
|
||||
|
@ -52,6 +52,7 @@ pub enum Keyword {
|
||||
Map,
|
||||
None,
|
||||
Range,
|
||||
ReadFile,
|
||||
ReadLine,
|
||||
Sleep,
|
||||
Struct,
|
||||
@ -84,6 +85,7 @@ impl Display for Keyword {
|
||||
Keyword::Loop => write!(f, "loop"),
|
||||
Keyword::While => write!(f, "while"),
|
||||
Keyword::Type => write!(f, "type"),
|
||||
Keyword::ReadFile => write!(f, "READ_FILE"),
|
||||
Keyword::ReadLine => write!(f, "READ_LINE"),
|
||||
Keyword::Sleep => write!(f, "SLEEP"),
|
||||
Keyword::WriteLine => write!(f, "WRITE_LINE"),
|
||||
@ -276,6 +278,7 @@ pub fn lexer<'src>() -> impl Parser<
|
||||
"type" => Token::Keyword(Keyword::Type),
|
||||
"loop" => Token::Keyword(Keyword::Loop),
|
||||
"while" => Token::Keyword(Keyword::While),
|
||||
"READ_FILE" => Token::Keyword(Keyword::ReadFile),
|
||||
"READ_LINE" => Token::Keyword(Keyword::ReadLine),
|
||||
"SLEEP" => Token::Keyword(Keyword::Sleep),
|
||||
"WRITE_LINE" => Token::Keyword(Keyword::WriteLine),
|
||||
|
@ -77,7 +77,11 @@ impl<'a> Interpreter<'a> {
|
||||
}
|
||||
|
||||
pub fn load_std(&mut self) -> Result<(), InterpreterError> {
|
||||
let std_sources: [(Arc<str>, Arc<str>); 2] = [
|
||||
let std_sources: [(Arc<str>, Arc<str>); 3] = [
|
||||
(
|
||||
Arc::from("std/fs.ds"),
|
||||
Arc::from(include_str!("../../std/fs.ds")),
|
||||
),
|
||||
(
|
||||
Arc::from("std/io.ds"),
|
||||
Arc::from(include_str!("../../std/io.ds")),
|
||||
@ -369,3 +373,13 @@ impl InterpreterError {
|
||||
reports
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn load_standard_library() {
|
||||
Interpreter::new(Context::new(None)).load_std().unwrap();
|
||||
}
|
||||
}
|
||||
|
@ -263,6 +263,14 @@ pub fn parser<'src>(
|
||||
);
|
||||
|
||||
let built_in_function_call = choice((
|
||||
just(Token::Keyword(Keyword::ReadFile))
|
||||
.ignore_then(expression.clone())
|
||||
.map_with(|argument, state| {
|
||||
Expression::BuiltInFunctionCall(
|
||||
Box::new(BuiltInFunctionCall::ReadFile(argument))
|
||||
.with_position(state.span()),
|
||||
)
|
||||
}),
|
||||
just(Token::Keyword(Keyword::ReadLine)).map_with(|_, state| {
|
||||
Expression::BuiltInFunctionCall(
|
||||
Box::new(BuiltInFunctionCall::ReadLine).with_position(state.span()),
|
||||
|
Loading…
Reference in New Issue
Block a user