#![allow(unused, unused_assignments)]
use crate::{
eval::*,
lower::{LowerError, ir},
model::OutputType,
resolve::*,
ty::*,
value::*,
};
use microcad_lang_base::{DiagError, Identifier, SrcRef};
use miette::Diagnostic;
use thiserror::Error;
#[derive(Debug, Error, Diagnostic)]
#[allow(missing_docs)]
pub enum EvalError {
#[error("Not implemented: {0}")]
Todo(String),
#[error("List index out of bounds: {index} >= {len}")]
ListIndexOutOfBounds {
index: usize,
len: usize,
},
#[error("Type mismatch for `{id}`: expected {expected}, got {found}")]
TypeMismatch {
id: Identifier,
expected: Type,
found: Type,
},
#[error("Array elements have different types: {0}")]
ArrayElementsDifferentTypes(TypeList),
#[error("Symbol {0} not found.")]
SymbolNotFound(ir::QualifiedName),
#[error("Symbol `{0}` cannot be called.")]
SymbolCannotBeCalled(ir::QualifiedName),
#[error("Ambiguous symbol {0} might be one of the following: {1}")]
AmbiguousSymbol(ir::QualifiedName, ir::QualifiedNames),
#[error("Local symbol not found: {0}")]
LocalNotFound(Identifier),
#[error("Property not found: {0}")]
PropertyNotFound(Identifier),
#[error("Not a property id: {0}")]
NoPropertyId(ir::QualifiedName),
#[error("Argument count mismatch: expected {expected}, got {found} in {args}")]
ArgumentCountMismatch {
args: String,
expected: usize,
found: usize,
},
#[error("Assertion failed: {0}")]
AssertionFailed(String),
#[error("Expected type `{expected}`, found type `{found}")]
ExpectedType {
expected: Type,
found: Type,
},
#[error("Diagnostic error: {0}")]
DiagError(#[from] DiagError),
#[error("Local stack needed to store {0}")]
LocalStackEmpty(Identifier),
#[error("Unexpected stack frame of type '{1}' cannot store {0}")]
WrongStackFrame(Identifier, &'static str),
#[error("Value Error: {0}")]
ValueError(#[from] ValueError),
#[error("Unknown method `{0}`")]
UnknownMethod(ir::QualifiedName),
#[error("Parsing error {0}")]
LowerError(#[from] LowerError),
#[error("Unexpected {0} {1} within expression")]
UnexpectedNested(&'static str, Identifier),
#[error("Missing arguments: {0}")]
MissingArguments(ir::IdentifierList),
#[error("Too many arguments: {0}")]
TooManyArguments(ir::IdentifierList),
#[error("Arguments match by identifier but have incompatible types: {0}")]
IdMatchButNotType(String),
#[error("Builtin error: {0}")]
BuiltinError(String),
#[error("Multiplicity not allowed '{0}'")]
MultiplicityNotAllowed(ir::IdentifierList),
#[error("Cannot mix 2d and 3d geometries")]
CannotMixGeometry,
#[error("If condition is not a boolean: {condition}")]
IfConditionIsNotBool {
condition: String,
#[label("Not a boolean")]
src_ref: SrcRef,
},
#[error("Workbench {name} cannot find initialization for those arguments")]
#[diagnostic(help("Possible initializations: \n\t{}", possible_params.join("\n\t")))]
NoInitializationFound {
#[label("Got: {name}( {actual_params} )")]
src_ref: SrcRef,
name: Identifier,
actual_params: String,
possible_params: Vec<String>,
},
#[error("Workbench {name} has ambiguous initialization for those arguments")]
#[diagnostic(help("Ambiguous initializations: \n\t{}", ambiguous_params.join("\n\t")))]
AmbiguousInitialization {
#[label("Got: {name}( {actual_params} )")]
src_ref: SrcRef,
name: Identifier,
actual_params: String,
ambiguous_params: Vec<String>,
},
#[error("Building plan incomplete. Missing properties: {0}")]
BuildingPlanIncomplete(ir::IdentifierList),
#[error("This expression statement did not produce any model")]
EmptyModelExpression,
#[error("The {kind} workbench produced a {produced} output, but expected a {expected} output.")]
WorkbenchInvalidOutput {
kind: ir::WorkbenchKind,
produced: OutputType,
expected: OutputType,
},
#[error("Resolve error: {0}")]
#[diagnostic(transparent)]
ResolveError(ResolveError),
#[error("Cannot call operation without workpiece.")]
CannotCallOperationWithoutWorkpiece,
#[error("Missing model in workbench")]
NoModelInWorkbench,
#[error("Value {name} already in defined: {value}")]
#[diagnostic(help("Values in microcad are immutable"))]
ValueAlreadyDefined {
#[label(primary, "{name} is already defined")]
location: SrcRef,
name: Identifier,
value: String,
#[label("Previously defined here")]
previous_location: SrcRef,
},
#[error("Assignment failed because {0} is not an l-value")]
NotAnLValue(Identifier),
#[error("Symbol {what} is private from within {within}")]
SymbolIsPrivate {
what: ir::QualifiedName,
within: ir::QualifiedName,
},
#[error("Unused global symbol {0}.")]
UnusedGlobalSymbol(String),
#[error("Unused local {0}.")]
UnusedLocal(Identifier),
#[error("Evaluation aborted because of prior resolve errors!")]
ResolveFailed,
#[error("Bad range, first number ({0}) must be smaller than last ({1})")]
BadRange(i64, i64),
#[error("Ambiguous type '{ty}' in tuple")]
AmbiguousType {
ty: Type,
#[label(
"Some unnamed values in this tuple share the same type '{ty}'.\nMaybe check the units or use identifiers in this tuple."
)]
src_ref: SrcRef,
},
}
pub type EvalResult<T> = std::result::Result<T, Box<EvalError>>;
impl From<ResolveError> for EvalError {
fn from(err: ResolveError) -> Self {
match err {
ResolveError::SymbolNotFound(name) => EvalError::SymbolNotFound(name),
other => EvalError::ResolveError(other),
}
}
}
impl From<Box<EvalError>> for miette::Report {
fn from(value: Box<EvalError>) -> Self {
miette::Report::new(*value)
}
}
impl From<DiagError> for Box<EvalError> {
fn from(value: DiagError) -> Self {
Box::new(value.into())
}
}
impl From<ValueError> for Box<EvalError> {
fn from(value: ValueError) -> Self {
Box::new(value.into())
}
}
impl From<ResolveError> for Box<EvalError> {
fn from(value: ResolveError) -> Self {
Box::new(value.into())
}
}