Add fs.read_file to standard library

This commit is contained in:
Jeff 2024-05-25 11:48:43 -04:00
parent d4c0633fab
commit c8dfbda447
6 changed files with 57 additions and 1 deletions

View File

@ -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();

View File

@ -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)?;

View File

@ -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),

View File

@ -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();
}
}

View File

@ -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()),

5
std/fs.ds Normal file
View File

@ -0,0 +1,5 @@
fs = {
read_file = fn (path: str) str {
READ_FILE path
}
}