use crate::{eval::*, parse::Identifier, r#type::*};
use microcad_core::Id;
use thiserror::Error;
#[derive(Debug, Error)]
pub enum EvalError {
#[error("{0}")]
CustomError(String),
#[error("Invalid operator: {0}")]
InvalidOperator(String),
#[error("Incompatible types {0} and {1} for addition")]
AddIncompatibleTypes(Type, Type),
#[error("Incompatible types {0} and {1} for subtraction")]
SubIncompatibleTypes(Type, Type),
#[error("Incompatible types {0} and {1} for multiplication")]
MulIncompatibleTypes(Type, Type),
#[error("Incompatible types {0} and {1} for division")]
DivIncompatibleTypes(Type, Type),
#[error("Invalid type: {0}")]
InvalidType(Type),
#[error("List index out of bounds: {index} >= {len}")]
ListIndexOutOfBounds {
index: usize,
len: usize,
},
#[error("Type mismatch for parameter: expected {expected}, got {found}")]
ParameterTypeMismatch {
name: Identifier,
expected: Type,
found: Type,
},
#[error("Return type mismatch: expected {expected}, got {found}")]
ReturnTypeMismatch {
name: Identifier,
expected: Type,
found: Type,
},
#[error("Namespace symbol expected, got {0}")]
NamespaceSymbolExpected(Symbol),
#[error("Cannot evaluate to type: {0}")]
EvaluateToTypeError(Type),
#[error("Cannot use {0}")]
CannotUse(Symbol),
#[error("Unknown qualified name: {0}")]
UnknownQualifiedName(Id),
#[error("Unknown method: {0}")]
UnknownMethod(Identifier),
#[error("Elements of list have different types")]
ListElementsDifferentTypes,
#[error("Function call missing argument: {0}")]
FunctionCallMissingArgument(Id),
#[error("Function must return a value")]
FunctionCallMissingReturn,
#[error("Symbol not found: {0}")]
SymbolNotFound(Id),
#[error("No matching initializer for module definition `{0}`")]
NoMatchingInitializer(Identifier),
#[error("Multiple matching initializer for module definition `{0}`")]
MultipleMatchingInitializer(Identifier),
#[error("Expected range in for loop, got {0}")]
ExpectedRangeInForLoop(Type),
#[error("Expected iterable, got {0}")]
ExpectedIterable(Type),
#[error("Argument count mismatch: expected {expected}, got {found}")]
ArgumentCountMismatch {
expected: usize,
found: usize,
},
#[error("Invalid argument type: {0}")]
InvalidArgumentType(Type),
#[error("Expected module: {0}")]
ExpectedModule(Id),
#[error("Cannot nest symbol: {0}")]
CannotNestSymbol(Symbol),
#[error("Cannot nest item: {0}")]
CannotNestItem(crate::parse::NestedItem),
#[error("Missing arguments: {0:?}")]
MissingArguments(ParameterValueList),
#[error("Parameter missing type or value: {0}")]
ParameterMissingTypeOrValue(Id),
#[error("Unexpected argument: {0}")]
UnexpectedArgument(Id),
#[error("Duplicate call argument: {0}")]
DuplicateCallArgument(Id),
#[error("Duplicate parameter: {0}")]
DuplicateParameter(Id),
#[error("Assertion failed: {0}")]
AssertionFailed(String),
#[error("Assertion failed: {0} with ")]
AssertionFailedWithCondition(String, String),
#[error("Ambiguous symbol: {0}")]
AmbiguousSymbol(Symbol),
#[error("Unknown field: {0}")]
UnknownField(Identifier),
#[error("Tuple length mismatch for operator {operator}: lhs={lhs}, rhs={rhs}")]
TupleLengthMismatchForOperator {
operator: char,
lhs: usize,
rhs: usize,
},
#[error("Type cannot be a key in a map: {0}")]
InvalidMapKeyType(Type),
#[error("Invalid node marker: {0}")]
InvalidNodeMarker(Identifier),
#[error("Cannot convert value {0} to {1}")]
CannotConvert(Value, String),
#[error("Cannot convert value into boolean: {0}")]
CannotConvertToBool(Value),
#[error("Cannot add unit to a value that has already a unit: {0}")]
CannotAddUnitToValueWithUnit(Value),
#[error("Cannot concat two vec with different types {0} and {1}")]
CannotCombineVecOfDifferentType(Type, Type),
#[error("Symbol is not callable: {0}")]
SymbolNotCallable(Symbol),
#[error("Error limit reached: Stopped evaluation after {0} errors")]
ErrorLimitReached(u32),
#[error("Unexpected empty stack")]
UnexpectedEmptyStack,
#[error("Tuple item not found {0}")]
TupleItemNotFound(Identifier),
}
pub type EvalResult<T> = std::result::Result<T, EvalError>;