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>> {
let valid_statements = self.run_type_definitions(context)?;
let valid_statements = self.validate(context)?;
let mut previous_value = None;
for statement in valid_statements {
@ -124,7 +124,7 @@ impl AbstractTree {
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 valid_statements = Vec::new();
@ -152,6 +152,8 @@ impl AbstractTree {
} else {
valid_statements.push(statement)
}
} else {
continue;
}
}

View File

@ -12,12 +12,13 @@ use std::{
vec,
};
use abstract_tree::Type;
use abstract_tree::{AbstractTree, Type};
use ariadne::{Color, Fmt, Label, Report, ReportKind};
use chumsky::prelude::*;
use context::Context;
use error::{Error, RuntimeError, TypeConflict, ValidationError};
use lexer::lex;
use parser::parse;
use parser::{parse, parser};
use rayon::prelude::*;
pub use value::Value;
@ -76,7 +77,7 @@ impl Interpreter {
}
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(include_str!("../../std/io.ds")),
@ -89,7 +90,54 @@ impl Interpreter {
let error = std_sources
.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 {
Err(error)

View File

@ -13,7 +13,7 @@ pub type ParserInput<'src> =
SpannedInput<Token<'src>, SimpleSpan, &'src [(Token<'src>, SimpleSpan)]>;
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()))
.into_result()
.map_err(|errors| {
@ -27,6 +27,7 @@ pub fn parse<'src>(tokens: &'src [(Token<'src>, SimpleSpan)]) -> Result<Abstract
}
pub fn parser<'src>(
allow_built_ins: bool,
) -> impl Parser<'src, ParserInput<'src>, Vec<Statement>, extra::Err<Rich<'src, Token<'src>, SimpleSpan>>>
{
let identifiers: RefCell<HashMap<&str, Identifier>> = RefCell::new(HashMap::new());
@ -154,6 +155,7 @@ pub fn parser<'src>(
});
let statement = recursive(|statement| {
let allow_built_ins = allow_built_ins.clone();
let block = statement
.clone()
.repeated()
@ -165,6 +167,7 @@ pub fn parser<'src>(
.map_with(|statements, state| Block::new(statements).with_position(state.span()));
let expression = recursive(|expression| {
let allow_built_ins = allow_built_ins.clone();
let identifier_expression = identifier.clone().map_with(|identifier, state| {
Expression::Identifier(identifier.with_position(state.span()))
});
@ -269,10 +272,17 @@ pub fn parser<'src>(
.map(|expression| BuiltInFunctionCall::WriteLine(expression)),
))
.then_ignore(just(Token::Control(Control::ParenClose)))
.map_with(|built_in_function_call, state| {
Expression::BuiltInFunctionCall(
.try_map_with(move |built_in_function_call, state| {
if allow_built_ins {
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
@ -602,15 +612,39 @@ mod tests {
#[test]
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!(
parse(&lex("READ_LINE()").unwrap()).unwrap()[0],
statements[0],
Statement::Expression(Expression::BuiltInFunctionCall(
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!(
parse(&lex("WRITE_LINE('hiya')").unwrap()).unwrap()[0],
statements[0],
Statement::Expression(Expression::BuiltInFunctionCall(
Box::new(BuiltInFunctionCall::WriteLine(Expression::Value(
ValueNode::String("hiya".to_string()).with_position((11, 17))