1
0

Continue revising built-in functions

This commit is contained in:
Jeff 2024-04-21 21:33:21 -04:00
parent 4726288b9a
commit 3d64883e2a
3 changed files with 97 additions and 13 deletions

View File

@ -99,7 +99,7 @@ impl AbstractTree {
} }
pub fn run(self, context: &Context) -> Result<Option<Value>, Vec<Error>> { pub fn run(self, context: &Context) -> Result<Option<Value>, Vec<Error>> {
let valid_statements = self.run_type_definitions(context)?; let valid_statements = self.validate(context)?;
let mut previous_value = None; let mut previous_value = None;
for statement in valid_statements { for statement in valid_statements {
@ -124,7 +124,7 @@ impl AbstractTree {
Ok(previous_value) Ok(previous_value)
} }
fn run_type_definitions(self, context: &Context) -> Result<Vec<Statement>, Vec<Error>> { fn validate(self, context: &Context) -> Result<Vec<Statement>, Vec<Error>> {
let mut errors = Vec::new(); let mut errors = Vec::new();
let mut valid_statements = Vec::new(); let mut valid_statements = Vec::new();
@ -152,6 +152,8 @@ impl AbstractTree {
} else { } else {
valid_statements.push(statement) valid_statements.push(statement)
} }
} else {
continue;
} }
} }

View File

@ -12,12 +12,13 @@ use std::{
vec, vec,
}; };
use abstract_tree::Type; use abstract_tree::{AbstractTree, Type};
use ariadne::{Color, Fmt, Label, Report, ReportKind}; use ariadne::{Color, Fmt, Label, Report, ReportKind};
use chumsky::prelude::*;
use context::Context; use context::Context;
use error::{Error, RuntimeError, TypeConflict, ValidationError}; use error::{Error, RuntimeError, TypeConflict, ValidationError};
use lexer::lex; use lexer::lex;
use parser::parse; use parser::{parse, parser};
use rayon::prelude::*; use rayon::prelude::*;
pub use value::Value; pub use value::Value;
@ -76,7 +77,7 @@ impl Interpreter {
} }
pub fn load_std(&mut self) -> Result<(), InterpreterError> { pub fn load_std(&mut self) -> Result<(), InterpreterError> {
let std_sources = [ let std_sources: [(Arc<str>, Arc<str>); 2] = [
( (
Arc::from("std/io.ds"), Arc::from("std/io.ds"),
Arc::from(include_str!("../../std/io.ds")), Arc::from(include_str!("../../std/io.ds")),
@ -89,7 +90,54 @@ impl Interpreter {
let error = std_sources let error = std_sources
.into_par_iter() .into_par_iter()
.find_map_any(|(source_id, source)| self.run(source_id, source).err()); .find_map_any(|(source_id, source)| {
self.sources
.write()
.unwrap()
.push((source_id.clone(), source.clone()));
let lex_result = lex(source.as_ref()).map_err(|errors| InterpreterError {
source_id: source_id.clone(),
errors,
});
let tokens = match lex_result {
Ok(tokens) => tokens,
Err(error) => return Some(error),
};
let parse_result = parser(true)
.parse(tokens.spanned((tokens.len()..tokens.len()).into()))
.into_result()
.map_err(|errors| InterpreterError {
source_id: source_id.clone(),
errors: errors
.into_iter()
.map(|error| {
let expected = error
.expected()
.into_iter()
.map(|pattern| pattern.to_string())
.collect();
let span = error.span();
Error::Parse {
expected,
span: (span.start(), span.end()),
reason: error.reason().to_string(),
}
})
.collect(),
});
let abstract_tree = match parse_result {
Ok(statements) => AbstractTree::new(statements),
Err(error) => return Some(error),
};
abstract_tree
.run(&self.context)
.map_err(|errors| InterpreterError { source_id, errors })
.err()
});
if let Some(error) = error { if let Some(error) = error {
Err(error) Err(error)

View File

@ -13,7 +13,7 @@ pub type ParserInput<'src> =
SpannedInput<Token<'src>, SimpleSpan, &'src [(Token<'src>, SimpleSpan)]>; SpannedInput<Token<'src>, SimpleSpan, &'src [(Token<'src>, SimpleSpan)]>;
pub fn parse<'src>(tokens: &'src [(Token<'src>, SimpleSpan)]) -> Result<AbstractTree, Vec<Error>> { pub fn parse<'src>(tokens: &'src [(Token<'src>, SimpleSpan)]) -> Result<AbstractTree, Vec<Error>> {
let statements = parser() let statements = parser(false)
.parse(tokens.spanned((tokens.len()..tokens.len()).into())) .parse(tokens.spanned((tokens.len()..tokens.len()).into()))
.into_result() .into_result()
.map_err(|errors| { .map_err(|errors| {
@ -27,6 +27,7 @@ pub fn parse<'src>(tokens: &'src [(Token<'src>, SimpleSpan)]) -> Result<Abstract
} }
pub fn parser<'src>( pub fn parser<'src>(
allow_built_ins: bool,
) -> impl Parser<'src, ParserInput<'src>, Vec<Statement>, extra::Err<Rich<'src, Token<'src>, SimpleSpan>>> ) -> impl Parser<'src, ParserInput<'src>, Vec<Statement>, extra::Err<Rich<'src, Token<'src>, SimpleSpan>>>
{ {
let identifiers: RefCell<HashMap<&str, Identifier>> = RefCell::new(HashMap::new()); let identifiers: RefCell<HashMap<&str, Identifier>> = RefCell::new(HashMap::new());
@ -154,6 +155,7 @@ pub fn parser<'src>(
}); });
let statement = recursive(|statement| { let statement = recursive(|statement| {
let allow_built_ins = allow_built_ins.clone();
let block = statement let block = statement
.clone() .clone()
.repeated() .repeated()
@ -165,6 +167,7 @@ pub fn parser<'src>(
.map_with(|statements, state| Block::new(statements).with_position(state.span())); .map_with(|statements, state| Block::new(statements).with_position(state.span()));
let expression = recursive(|expression| { let expression = recursive(|expression| {
let allow_built_ins = allow_built_ins.clone();
let identifier_expression = identifier.clone().map_with(|identifier, state| { let identifier_expression = identifier.clone().map_with(|identifier, state| {
Expression::Identifier(identifier.with_position(state.span())) Expression::Identifier(identifier.with_position(state.span()))
}); });
@ -269,10 +272,17 @@ pub fn parser<'src>(
.map(|expression| BuiltInFunctionCall::WriteLine(expression)), .map(|expression| BuiltInFunctionCall::WriteLine(expression)),
)) ))
.then_ignore(just(Token::Control(Control::ParenClose))) .then_ignore(just(Token::Control(Control::ParenClose)))
.map_with(|built_in_function_call, state| { .try_map_with(move |built_in_function_call, state| {
Expression::BuiltInFunctionCall( if allow_built_ins {
Box::new(built_in_function_call).with_position(state.span()), Ok(Expression::BuiltInFunctionCall(
) Box::new(built_in_function_call).with_position(state.span()),
))
} else {
Err(Rich::custom(
state.span(),
"Built-in function calls can only be used by the standard library.",
))
}
}); });
let structure_field = identifier let structure_field = identifier
@ -602,15 +612,39 @@ mod tests {
#[test] #[test]
fn built_in_function() { fn built_in_function() {
let tokens = lex("READ_LINE()").unwrap();
let statements = parser(true)
.parse(tokens.spanned((tokens.len()..tokens.len()).into()))
.into_result()
.map_err(|errors| {
errors
.into_iter()
.map(|error| Error::from(error))
.collect::<Vec<Error>>()
})
.unwrap();
assert_eq!( assert_eq!(
parse(&lex("READ_LINE()").unwrap()).unwrap()[0], statements[0],
Statement::Expression(Expression::BuiltInFunctionCall( Statement::Expression(Expression::BuiltInFunctionCall(
Box::new(BuiltInFunctionCall::ReadLine).with_position((0, 11)) Box::new(BuiltInFunctionCall::ReadLine).with_position((0, 11))
)) ))
); );
let tokens = lex("WRITE_LINE('hiya')").unwrap();
let statements = parser(true)
.parse(tokens.spanned((tokens.len()..tokens.len()).into()))
.into_result()
.map_err(|errors| {
errors
.into_iter()
.map(|error| Error::from(error))
.collect::<Vec<Error>>()
})
.unwrap();
assert_eq!( assert_eq!(
parse(&lex("WRITE_LINE('hiya')").unwrap()).unwrap()[0], statements[0],
Statement::Expression(Expression::BuiltInFunctionCall( Statement::Expression(Expression::BuiltInFunctionCall(
Box::new(BuiltInFunctionCall::WriteLine(Expression::Value( Box::new(BuiltInFunctionCall::WriteLine(Expression::Value(
ValueNode::String("hiya".to_string()).with_position((11, 17)) ValueNode::String("hiya".to_string()).with_position((11, 17))