This commit is contained in:
Jeff 2024-08-20 19:44:22 -04:00
parent e1e40cf931
commit 956def5ec6
4 changed files with 49 additions and 46 deletions

View File

@ -17,8 +17,8 @@ use crate::{
PrimitiveValueExpression, RangeExpression, Span, Statement, StructDefinition,
StructExpression, TupleAccessExpression,
},
core_library, parse, Context, ContextError, DustError, Expression, Identifier, StructType,
Type,
core_library, parse, Context, ContextError, DustError, Expression, Identifier, Rangeable,
RangeableType, StructType, Type,
};
/// Analyzes the abstract syntax tree for errors.
@ -255,6 +255,18 @@ impl<'recovered, 'a: 'recovered> Analyzer<'a> {
list: list.clone(),
});
}
} else if let Type::Range { r#type } = &index_type {
if let RangeableType::Integer = r#type {
// Ok
} else {
return Err(AnalysisError::ExpectedType {
expected: Type::Range {
r#type: RangeableType::Integer,
},
actual: index_type,
actual_expression: index.clone(),
});
}
} else {
return Err(AnalysisError::ExpectedType {
expected: Type::Integer,

View File

@ -16,24 +16,6 @@ pub fn core_library<'a>() -> &'a Context {
(0, 0),
),
),
(
Identifier::new("is_even"),
(
ContextData::VariableValue(Value::Function(Function::BuiltIn(
BuiltInFunction::IsEven,
))),
(0, 0),
),
),
(
Identifier::new("is_odd"),
(
ContextData::VariableValue(Value::Function(Function::BuiltIn(
BuiltInFunction::IsOdd,
))),
(0, 0),
),
),
(
Identifier::new("read_line"),
(

View File

@ -234,27 +234,36 @@ impl Value {
}
pub fn get_field(&self, field: &Identifier) -> Option<Value> {
let built_in_function = match field.as_str() {
"to_string" => BuiltInFunction::ToString,
"length" => {
return match self {
if let Value::Mutable(locked) = self {
return locked.read().unwrap().get_field(field);
}
match field.as_str() {
"is_even" => match self {
Value::Integer(integer) => Some(Value::Boolean(integer % 2 == 0)),
Value::Float(float) => Some(Value::Boolean(float % 2.0 == 0.0)),
_ => None,
},
"is_odd" => match self {
Value::Integer(integer) => Some(Value::Boolean(integer % 2 != 0)),
Value::Float(float) => Some(Value::Boolean(float % 2.0 != 0.0)),
_ => None,
},
"to_string" => Some(Value::Function(Function::BuiltIn(
BuiltInFunction::ToString,
))),
"length" => match self {
Value::List(values) => Some(Value::Integer(values.len() as i64)),
Value::String(string) => Some(Value::Integer(string.len() as i64)),
Value::Map(map) => Some(Value::Integer(map.len() as i64)),
_ => None,
}
}
_ => {
return match self {
Value::Mutable(inner) => inner.read().unwrap().get_field(field),
},
_ => match self {
Value::Struct(Struct::Fields { fields, .. }) => fields.get(field).cloned(),
Value::Map(pairs) => pairs.get(field).cloned(),
_ => None,
};
},
}
};
Some(Value::Function(Function::BuiltIn(built_in_function)))
}
pub fn get_index(&self, index: Value) -> Result<Option<Value>, ValueError> {

View File

@ -737,7 +737,7 @@ impl Vm {
});
}
} else {
return Err(RuntimeError::UndefinedProperty {
return Err(RuntimeError::UndefinedField {
value: container_value,
value_position: container_position,
property: field.inner,
@ -1130,7 +1130,7 @@ pub enum RuntimeError {
identifier: Identifier,
position: Span,
},
UndefinedProperty {
UndefinedField {
value: Value,
value_position: Span,
property: Identifier,
@ -1175,7 +1175,7 @@ impl RuntimeError {
} => (start_position.0, end_position.1),
Self::UndefinedType { position, .. } => *position,
Self::UndefinedProperty {
Self::UndefinedField {
property_position, ..
} => *property_position,
}
@ -1326,7 +1326,7 @@ impl Display for RuntimeError {
"Identifier \"{identifier}\" is not associated with a value or constructor"
)
}
Self::UndefinedProperty {
Self::UndefinedField {
value, property, ..
} => {
write!(f, "Value {} does not have the property {}", value, property)
@ -1672,14 +1672,14 @@ mod tests {
#[test]
fn is_even() {
let input = "is_even(42)";
let input = "42.is_even";
assert_eq!(run(input), Ok(Some(Value::Boolean(true))));
}
#[test]
fn is_odd() {
let input = "is_odd(42)";
let input = "42.is_odd";
assert_eq!(run(input), Ok(Some(Value::Boolean(false))));
}