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)
|
expression.node.expected_type(_context)
|
||||||
} else {
|
} 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::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::{
|
use crate::{
|
||||||
abstract_tree::{Identifier, Type},
|
abstract_tree::{Identifier, Type},
|
||||||
error::RwLockPoisonError,
|
error::RwLockPoisonError,
|
||||||
value::BuiltInFunction,
|
value::{BuiltInFunction, BuiltInValue},
|
||||||
Value,
|
Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -53,7 +53,14 @@ impl Context {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn contains(&self, identifier: &Identifier) -> Result<bool, RwLockPoisonError> {
|
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> {
|
pub fn get_type(&self, identifier: &Identifier) -> Result<Option<Type>, RwLockPoisonError> {
|
||||||
@ -67,6 +74,7 @@ impl Context {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let r#type = match identifier.as_str() {
|
let r#type = match identifier.as_str() {
|
||||||
|
"io" => BuiltInValue::Io.r#type(),
|
||||||
"output" => BuiltInFunction::Output.r#type(),
|
"output" => BuiltInFunction::Output.r#type(),
|
||||||
_ => return Ok(None),
|
_ => return Ok(None),
|
||||||
};
|
};
|
||||||
@ -79,6 +87,7 @@ impl Context {
|
|||||||
Ok(Some(value.clone()))
|
Ok(Some(value.clone()))
|
||||||
} else {
|
} else {
|
||||||
let value = match identifier.as_str() {
|
let value = match identifier.as_str() {
|
||||||
|
"io" => BuiltInValue::Io.value(),
|
||||||
"output" => Value::built_in_function(BuiltInFunction::Output),
|
"output" => Value::built_in_function(BuiltInFunction::Output),
|
||||||
_ => return Ok(None),
|
_ => return Ok(None),
|
||||||
};
|
};
|
||||||
|
40
src/error.rs
40
src/error.rs
@ -1,6 +1,6 @@
|
|||||||
use std::{io, ops::Range, sync::PoisonError};
|
use std::{io, ops::Range, sync::PoisonError};
|
||||||
|
|
||||||
use ariadne::{Label, ReportBuilder};
|
use ariadne::{Color, Fmt, Label, ReportBuilder};
|
||||||
use chumsky::{prelude::Rich, span::Span};
|
use chumsky::{prelude::Rich, span::Span};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -33,6 +33,8 @@ impl Error {
|
|||||||
self,
|
self,
|
||||||
mut builder: ReportBuilder<'_, Range<usize>>,
|
mut builder: ReportBuilder<'_, Range<usize>>,
|
||||||
) -> ReportBuilder<'_, Range<usize>> {
|
) -> ReportBuilder<'_, Range<usize>> {
|
||||||
|
let type_color = Color::Green;
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
Error::Parse { expected, span } => {
|
Error::Parse { expected, span } => {
|
||||||
let message = match expected.as_str() {
|
let message = match expected.as_str() {
|
||||||
@ -66,16 +68,18 @@ impl Error {
|
|||||||
},
|
},
|
||||||
Error::Validation { error, position } => match error {
|
Error::Validation { error, position } => match error {
|
||||||
ValidationError::ExpectedBoolean { actual, position } => {
|
ValidationError::ExpectedBoolean { actual, position } => {
|
||||||
builder.add_label(
|
builder.add_label(Label::new(position.0..position.1).with_message(format!(
|
||||||
Label::new(position.0..position.1)
|
"Expected {} but got {}.",
|
||||||
.with_message(format!("Expected boolean but got {actual}.")),
|
"boolean".fg(type_color),
|
||||||
);
|
actual.fg(type_color)
|
||||||
|
)));
|
||||||
}
|
}
|
||||||
ValidationError::ExpectedIntegerOrFloat => {
|
ValidationError::ExpectedIntegerOrFloat => {
|
||||||
builder.add_label(
|
builder.add_label(Label::new(position.0..position.1).with_message(format!(
|
||||||
Label::new(position.0..position.1)
|
"Expected {} or {}.",
|
||||||
.with_message("Expected integer or float."),
|
"integer".fg(type_color),
|
||||||
);
|
"float".fg(type_color)
|
||||||
|
)));
|
||||||
}
|
}
|
||||||
ValidationError::RwLockPoison(_) => todo!(),
|
ValidationError::RwLockPoison(_) => todo!(),
|
||||||
ValidationError::TypeCheck {
|
ValidationError::TypeCheck {
|
||||||
@ -86,10 +90,12 @@ impl Error {
|
|||||||
let TypeConflict { actual, expected } = conflict;
|
let TypeConflict { actual, expected } = conflict;
|
||||||
|
|
||||||
builder.add_labels([
|
builder.add_labels([
|
||||||
Label::new(expected_postion.0..expected_postion.1)
|
Label::new(expected_postion.0..expected_postion.1).with_message(format!(
|
||||||
.with_message(format!("Type {expected} established here.")),
|
"Type {} established here.",
|
||||||
|
expected.fg(type_color)
|
||||||
|
)),
|
||||||
Label::new(actual_position.0..actual_position.1)
|
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) => {
|
ValidationError::VariableNotFound(identifier) => {
|
||||||
@ -99,7 +105,10 @@ impl Error {
|
|||||||
.with_priority(1),
|
.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::CannotIndexWith(_, _) => todo!(),
|
||||||
ValidationError::InterpreterExpectedReturn => todo!(),
|
ValidationError::InterpreterExpectedReturn => todo!(),
|
||||||
ValidationError::ExpectedFunction { .. } => todo!(),
|
ValidationError::ExpectedFunction { .. } => todo!(),
|
||||||
@ -169,7 +178,10 @@ impl PartialEq for RuntimeError {
|
|||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub enum ValidationError {
|
pub enum ValidationError {
|
||||||
CannotIndex(Type),
|
CannotIndex {
|
||||||
|
r#type: Type,
|
||||||
|
position: SourcePosition,
|
||||||
|
},
|
||||||
CannotIndexWith(Type, Type),
|
CannotIndexWith(Type, Type),
|
||||||
ExpectedBoolean {
|
ExpectedBoolean {
|
||||||
actual: Type,
|
actual: Type,
|
||||||
|
24
src/value.rs
24
src/value.rs
@ -377,24 +377,34 @@ impl BuiltInFunction {
|
|||||||
impl Display for BuiltInFunction {
|
impl Display for BuiltInFunction {
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
BuiltInFunction::Output => write!(f, "(to_output : any) : none rust_magic();"),
|
BuiltInFunction::Output => write!(f, "(to_output : any) : none {{ *MAGIC* }}"),
|
||||||
BuiltInFunction::ReadLine => todo!(),
|
BuiltInFunction::ReadLine => write!(f, "() : str {{ *MAGIC* }}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static IO: OnceLock<Value> = OnceLock::new();
|
||||||
|
|
||||||
pub enum BuiltInValue {
|
pub enum BuiltInValue {
|
||||||
Io,
|
Io,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BuiltInValue {
|
impl BuiltInValue {
|
||||||
pub fn io() -> Value {
|
pub fn value(self) -> Value {
|
||||||
static IO: OnceLock<Value> = OnceLock::new();
|
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