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