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, PrimitiveValueExpression, RangeExpression, Span, Statement, StructDefinition,
StructExpression, TupleAccessExpression, StructExpression, TupleAccessExpression,
}, },
core_library, parse, Context, ContextError, DustError, Expression, Identifier, StructType, core_library, parse, Context, ContextError, DustError, Expression, Identifier, Rangeable,
Type, RangeableType, StructType, Type,
}; };
/// Analyzes the abstract syntax tree for errors. /// Analyzes the abstract syntax tree for errors.
@ -255,6 +255,18 @@ impl<'recovered, 'a: 'recovered> Analyzer<'a> {
list: list.clone(), 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 { } else {
return Err(AnalysisError::ExpectedType { return Err(AnalysisError::ExpectedType {
expected: Type::Integer, expected: Type::Integer,

View File

@ -16,24 +16,6 @@ pub fn core_library<'a>() -> &'a Context {
(0, 0), (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"), Identifier::new("read_line"),
( (

View File

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

View File

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