Improve built-in values and errors
This commit is contained in:
parent
bc5cadc446
commit
791610b350
@ -34,7 +34,10 @@ impl AbstractTree for Index {
|
||||
|
||||
expression.node.expected_type(_context)
|
||||
} else {
|
||||
Err(ValidationError::CannotIndex(left_type))
|
||||
Err(ValidationError::CannotIndex {
|
||||
r#type: left_type,
|
||||
position: self.left.position,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -53,7 +56,10 @@ impl AbstractTree for Index {
|
||||
Err(ValidationError::CannotIndexWith(left_type, right_type))
|
||||
}
|
||||
}
|
||||
_ => Err(ValidationError::CannotIndex(left_type)),
|
||||
_ => Err(ValidationError::CannotIndex {
|
||||
r#type: left_type,
|
||||
position: self.left.position,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,7 @@ use std::{
|
||||
use crate::{
|
||||
abstract_tree::{Identifier, Type},
|
||||
error::RwLockPoisonError,
|
||||
value::BuiltInFunction,
|
||||
value::{BuiltInFunction, BuiltInValue},
|
||||
Value,
|
||||
};
|
||||
|
||||
@ -53,7 +53,14 @@ impl Context {
|
||||
}
|
||||
|
||||
pub fn contains(&self, identifier: &Identifier) -> Result<bool, RwLockPoisonError> {
|
||||
Ok(self.inner.read()?.contains_key(identifier))
|
||||
if self.inner.read()?.contains_key(identifier) {
|
||||
Ok(true)
|
||||
} else {
|
||||
match identifier.as_str() {
|
||||
"io" | "output" => Ok(true),
|
||||
_ => Ok(false),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_type(&self, identifier: &Identifier) -> Result<Option<Type>, RwLockPoisonError> {
|
||||
@ -67,6 +74,7 @@ impl Context {
|
||||
}
|
||||
|
||||
let r#type = match identifier.as_str() {
|
||||
"io" => BuiltInValue::Io.r#type(),
|
||||
"output" => BuiltInFunction::Output.r#type(),
|
||||
_ => return Ok(None),
|
||||
};
|
||||
@ -79,6 +87,7 @@ impl Context {
|
||||
Ok(Some(value.clone()))
|
||||
} else {
|
||||
let value = match identifier.as_str() {
|
||||
"io" => BuiltInValue::Io.value(),
|
||||
"output" => Value::built_in_function(BuiltInFunction::Output),
|
||||
_ => return Ok(None),
|
||||
};
|
||||
|
40
src/error.rs
40
src/error.rs
@ -1,6 +1,6 @@
|
||||
use std::{io, ops::Range, sync::PoisonError};
|
||||
|
||||
use ariadne::{Label, ReportBuilder};
|
||||
use ariadne::{Color, Fmt, Label, ReportBuilder};
|
||||
use chumsky::{prelude::Rich, span::Span};
|
||||
|
||||
use crate::{
|
||||
@ -33,6 +33,8 @@ impl Error {
|
||||
self,
|
||||
mut builder: ReportBuilder<'_, Range<usize>>,
|
||||
) -> ReportBuilder<'_, Range<usize>> {
|
||||
let type_color = Color::Green;
|
||||
|
||||
match self {
|
||||
Error::Parse { expected, span } => {
|
||||
let message = match expected.as_str() {
|
||||
@ -66,16 +68,18 @@ impl Error {
|
||||
},
|
||||
Error::Validation { error, position } => match error {
|
||||
ValidationError::ExpectedBoolean { actual, position } => {
|
||||
builder.add_label(
|
||||
Label::new(position.0..position.1)
|
||||
.with_message(format!("Expected boolean but got {actual}.")),
|
||||
);
|
||||
builder.add_label(Label::new(position.0..position.1).with_message(format!(
|
||||
"Expected {} but got {}.",
|
||||
"boolean".fg(type_color),
|
||||
actual.fg(type_color)
|
||||
)));
|
||||
}
|
||||
ValidationError::ExpectedIntegerOrFloat => {
|
||||
builder.add_label(
|
||||
Label::new(position.0..position.1)
|
||||
.with_message("Expected integer or float."),
|
||||
);
|
||||
builder.add_label(Label::new(position.0..position.1).with_message(format!(
|
||||
"Expected {} or {}.",
|
||||
"integer".fg(type_color),
|
||||
"float".fg(type_color)
|
||||
)));
|
||||
}
|
||||
ValidationError::RwLockPoison(_) => todo!(),
|
||||
ValidationError::TypeCheck {
|
||||
@ -86,10 +90,12 @@ impl Error {
|
||||
let TypeConflict { actual, expected } = conflict;
|
||||
|
||||
builder.add_labels([
|
||||
Label::new(expected_postion.0..expected_postion.1)
|
||||
.with_message(format!("Type {expected} established here.")),
|
||||
Label::new(expected_postion.0..expected_postion.1).with_message(format!(
|
||||
"Type {} established here.",
|
||||
expected.fg(type_color)
|
||||
)),
|
||||
Label::new(actual_position.0..actual_position.1)
|
||||
.with_message(format!("Got type {actual} here.")),
|
||||
.with_message(format!("Got type {} here.", actual.fg(type_color))),
|
||||
]);
|
||||
}
|
||||
ValidationError::VariableNotFound(identifier) => {
|
||||
@ -99,7 +105,10 @@ impl Error {
|
||||
.with_priority(1),
|
||||
);
|
||||
}
|
||||
ValidationError::CannotIndex(_) => todo!(),
|
||||
ValidationError::CannotIndex { r#type, position } => builder.add_label(
|
||||
Label::new(position.0..position.1)
|
||||
.with_message(format!("Cannot index into a {}.", r#type.fg(type_color))),
|
||||
),
|
||||
ValidationError::CannotIndexWith(_, _) => todo!(),
|
||||
ValidationError::InterpreterExpectedReturn => todo!(),
|
||||
ValidationError::ExpectedFunction { .. } => todo!(),
|
||||
@ -169,7 +178,10 @@ impl PartialEq for RuntimeError {
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum ValidationError {
|
||||
CannotIndex(Type),
|
||||
CannotIndex {
|
||||
r#type: Type,
|
||||
position: SourcePosition,
|
||||
},
|
||||
CannotIndexWith(Type, Type),
|
||||
ExpectedBoolean {
|
||||
actual: Type,
|
||||
|
24
src/value.rs
24
src/value.rs
@ -377,24 +377,34 @@ impl BuiltInFunction {
|
||||
impl Display for BuiltInFunction {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
match self {
|
||||
BuiltInFunction::Output => write!(f, "(to_output : any) : none rust_magic();"),
|
||||
BuiltInFunction::ReadLine => todo!(),
|
||||
BuiltInFunction::Output => write!(f, "(to_output : any) : none {{ *MAGIC* }}"),
|
||||
BuiltInFunction::ReadLine => write!(f, "() : str {{ *MAGIC* }}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static IO: OnceLock<Value> = OnceLock::new();
|
||||
|
||||
pub enum BuiltInValue {
|
||||
Io,
|
||||
}
|
||||
|
||||
impl BuiltInValue {
|
||||
pub fn io() -> Value {
|
||||
static IO: OnceLock<Value> = OnceLock::new();
|
||||
pub fn value(self) -> Value {
|
||||
match self {
|
||||
BuiltInValue::Io => {
|
||||
let mut properties = BTreeMap::new();
|
||||
|
||||
let mut properties = BTreeMap::new();
|
||||
properties.insert(Identifier::new("read_line"), BuiltInFunction::read_line());
|
||||
|
||||
properties.insert(Identifier::new("read_line"), BuiltInFunction::read_line());
|
||||
IO.get_or_init(|| Value::map(properties)).clone()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IO.get_or_init(|| Value::map(properties)).clone()
|
||||
pub fn r#type(self) -> Type {
|
||||
match self {
|
||||
BuiltInValue::Io => Type::Map,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user