Begin changing value type
This commit is contained in:
parent
956def5ec6
commit
87bced9719
@ -7,7 +7,7 @@ use std::{
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{Identifier, Type, Value};
|
||||
use crate::{Identifier, Type, Value, ValueData, ValueError};
|
||||
|
||||
/// Integrated function that can be called from Dust code.
|
||||
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||
@ -84,21 +84,17 @@ impl BuiltInFunction {
|
||||
|
||||
match self {
|
||||
BuiltInFunction::ToString => {
|
||||
Ok(Some(Value::String(value_arguments.unwrap()[0].to_string())))
|
||||
Ok(Some(Value::string(value_arguments.unwrap()[0].to_string())))
|
||||
}
|
||||
BuiltInFunction::IsEven => {
|
||||
if let Value::Integer(integer) = value_arguments.unwrap()[0] {
|
||||
Ok(Some(Value::Boolean(integer % 2 == 0)))
|
||||
} else {
|
||||
Err(BuiltInFunctionError::ExpectedInteger)
|
||||
}
|
||||
let is_even = value_arguments.unwrap()[0].is_even()?;
|
||||
|
||||
Ok(Some(is_even))
|
||||
}
|
||||
BuiltInFunction::IsOdd => {
|
||||
if let Value::Integer(integer) = value_arguments.unwrap()[0] {
|
||||
Ok(Some(Value::Boolean(integer % 2 != 0)))
|
||||
} else {
|
||||
Err(BuiltInFunctionError::ExpectedInteger)
|
||||
}
|
||||
let is_odd = value_arguments.unwrap()[0].is_odd()?;
|
||||
|
||||
Ok(Some(is_odd))
|
||||
}
|
||||
BuiltInFunction::ReadLine => {
|
||||
let mut input = String::new();
|
||||
@ -108,15 +104,45 @@ impl BuiltInFunction {
|
||||
Ok(Some(Value::string(input.trim_end_matches('\n'))))
|
||||
}
|
||||
BuiltInFunction::WriteLine => {
|
||||
if let Value::String(string) = &value_arguments.unwrap()[0] {
|
||||
let first_argument = &value_arguments.unwrap()[0];
|
||||
|
||||
match first_argument {
|
||||
Value::Raw(ValueData::String(string)) => {
|
||||
let mut stdout = stdout();
|
||||
|
||||
stdout.write_all(string.as_bytes())?;
|
||||
stdout.write_all(b"\n")?;
|
||||
|
||||
Ok(None)
|
||||
} else {
|
||||
Err(BuiltInFunctionError::ExpectedString)
|
||||
}
|
||||
|
||||
Value::Reference(reference) => match reference.as_ref() {
|
||||
ValueData::String(string) => {
|
||||
let mut stdout = stdout();
|
||||
|
||||
stdout.write_all(string.as_bytes())?;
|
||||
stdout.write_all(b"\n")?;
|
||||
|
||||
Ok(None)
|
||||
}
|
||||
_ => Err(BuiltInFunctionError::ExpectedString),
|
||||
},
|
||||
Value::Mutable(locked) => {
|
||||
let value_data = &*locked.read().unwrap();
|
||||
let string = match value_data {
|
||||
ValueData::String(string) => string,
|
||||
_ => return Err(BuiltInFunctionError::ExpectedString),
|
||||
};
|
||||
|
||||
let mut stdout = stdout();
|
||||
|
||||
stdout.write_all(string.as_bytes())?;
|
||||
stdout.write_all(b"\n")?;
|
||||
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
_ => Err(BuiltInFunctionError::ExpectedString),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -132,6 +158,7 @@ impl Display for BuiltInFunction {
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum BuiltInFunctionError {
|
||||
Io(io::ErrorKind),
|
||||
ValueError(ValueError),
|
||||
|
||||
ExpectedString,
|
||||
ExpectedList,
|
||||
@ -140,6 +167,12 @@ pub enum BuiltInFunctionError {
|
||||
WrongNumberOfValueArguments,
|
||||
}
|
||||
|
||||
impl From<ValueError> for BuiltInFunctionError {
|
||||
fn from(v: ValueError) -> Self {
|
||||
Self::ValueError(v)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<io::Error> for BuiltInFunctionError {
|
||||
fn from(error: io::Error) -> Self {
|
||||
Self::Io(error.kind())
|
||||
@ -152,6 +185,9 @@ impl Display for BuiltInFunctionError {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
BuiltInFunctionError::Io(error_kind) => write!(f, "I/O error: {}", error_kind),
|
||||
BuiltInFunctionError::ValueError(value_error) => {
|
||||
write!(f, "Value error: {}", value_error)
|
||||
}
|
||||
BuiltInFunctionError::ExpectedInteger => write!(f, "Expected an integer"),
|
||||
BuiltInFunctionError::ExpectedString => write!(f, "Expected a string"),
|
||||
BuiltInFunctionError::ExpectedList => write!(f, "Expected a list"),
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -22,7 +22,7 @@ use crate::{
|
||||
},
|
||||
core_library, parse, Analyzer, BuiltInFunctionError, Constructor, Context, ContextData,
|
||||
ContextError, DustError, Expression, Function, FunctionCallError, Identifier, ParseError,
|
||||
StructType, Type, Value, ValueError,
|
||||
StructType, Type, Value, ValueData, ValueError,
|
||||
};
|
||||
|
||||
/// Run the source code and return the result.
|
||||
@ -200,7 +200,8 @@ impl Vm {
|
||||
let position = value.position();
|
||||
let value = self
|
||||
.run_expression(value, collect_garbage)?
|
||||
.expect_value(position)?;
|
||||
.expect_value(position)?
|
||||
.into_reference();
|
||||
|
||||
self.context
|
||||
.set_variable_value(identifier.inner, value)
|
||||
@ -367,22 +368,33 @@ impl Vm {
|
||||
let start = self
|
||||
.run_expression(start, collect_garbage)?
|
||||
.expect_value(start_position)?;
|
||||
|
||||
let start_data = match start {
|
||||
Value::Raw(data) => data,
|
||||
Value::Reference(reference) => reference.as_ref().clone(),
|
||||
Value::Mutable(locked) => locked.read().unwrap().clone(),
|
||||
};
|
||||
let end_position = end.position();
|
||||
let end = self
|
||||
.run_expression(end, collect_garbage)?
|
||||
.expect_value(end_position)?;
|
||||
let end_data = match end {
|
||||
Value::Raw(data) => data,
|
||||
Value::Reference(reference) => reference.as_ref().clone(),
|
||||
Value::Mutable(locked) => locked.read().unwrap().clone(),
|
||||
};
|
||||
|
||||
match (start, end) {
|
||||
(Value::Byte(start), Value::Byte(end)) => {
|
||||
match (start_data, end_data) {
|
||||
(ValueData::Byte(start), ValueData::Byte(end)) => {
|
||||
Ok(Evaluation::Return(Some(Value::range(start, end))))
|
||||
}
|
||||
(Value::Character(start), Value::Character(end)) => {
|
||||
(ValueData::Character(start), ValueData::Character(end)) => {
|
||||
Ok(Evaluation::Return(Some(Value::range(start, end))))
|
||||
}
|
||||
(Value::Float(start), Value::Float(end)) => {
|
||||
(ValueData::Float(start), ValueData::Float(end)) => {
|
||||
Ok(Evaluation::Return(Some(Value::range(start, end))))
|
||||
}
|
||||
(Value::Integer(start), Value::Integer(end)) => {
|
||||
(ValueData::Integer(start), ValueData::Integer(end)) => {
|
||||
Ok(Evaluation::Return(Some(Value::range(start, end))))
|
||||
}
|
||||
_ => Err(RuntimeError::InvalidRange {
|
||||
@ -396,22 +408,33 @@ impl Vm {
|
||||
let start = self
|
||||
.run_expression(start, collect_garbage)?
|
||||
.expect_value(start_position)?;
|
||||
|
||||
let start_data = match start {
|
||||
Value::Raw(data) => data,
|
||||
Value::Reference(reference) => reference.as_ref().clone(),
|
||||
Value::Mutable(locked) => locked.read().unwrap().clone(),
|
||||
};
|
||||
let end_position = end.position();
|
||||
let end = self
|
||||
.run_expression(end, collect_garbage)?
|
||||
.expect_value(end_position)?;
|
||||
let end_data = match end {
|
||||
Value::Raw(data) => data,
|
||||
Value::Reference(reference) => reference.as_ref().clone(),
|
||||
Value::Mutable(locked) => locked.read().unwrap().clone(),
|
||||
};
|
||||
|
||||
match (start, end) {
|
||||
(Value::Byte(start), Value::Byte(end)) => {
|
||||
match (start_data, end_data) {
|
||||
(ValueData::Byte(start), ValueData::Byte(end)) => {
|
||||
Ok(Evaluation::Return(Some(Value::range_inclusive(start, end))))
|
||||
}
|
||||
(Value::Character(start), Value::Character(end)) => {
|
||||
(ValueData::Character(start), ValueData::Character(end)) => {
|
||||
Ok(Evaluation::Return(Some(Value::range_inclusive(start, end))))
|
||||
}
|
||||
(Value::Float(start), Value::Float(end)) => {
|
||||
(ValueData::Float(start), ValueData::Float(end)) => {
|
||||
Ok(Evaluation::Return(Some(Value::range_inclusive(start, end))))
|
||||
}
|
||||
(Value::Integer(start), Value::Integer(end)) => {
|
||||
(ValueData::Integer(start), ValueData::Integer(end)) => {
|
||||
Ok(Evaluation::Return(Some(Value::range_inclusive(start, end))))
|
||||
}
|
||||
_ => Err(RuntimeError::InvalidRange {
|
||||
@ -441,7 +464,7 @@ impl Vm {
|
||||
map.insert(identifier.inner, value);
|
||||
}
|
||||
|
||||
Ok(Evaluation::Return(Some(Value::Map(map))))
|
||||
Ok(Evaluation::Return(Some(Value::map(map))))
|
||||
}
|
||||
|
||||
fn run_operator(
|
||||
@ -483,41 +506,25 @@ impl Vm {
|
||||
let right_value = self
|
||||
.run_expression(right, collect_garbage)?
|
||||
.expect_value(right_position)?;
|
||||
let outcome =
|
||||
match operator.inner {
|
||||
let result = match operator.inner {
|
||||
ComparisonOperator::Equal => left_value.equal(&right_value),
|
||||
ComparisonOperator::NotEqual => left_value.not_equal(&right_value),
|
||||
ComparisonOperator::GreaterThan => left_value
|
||||
.greater_than(&right_value)
|
||||
.map_err(|error| RuntimeError::ValueError {
|
||||
error,
|
||||
left_position,
|
||||
right_position,
|
||||
})?,
|
||||
ComparisonOperator::GreaterThanOrEqual => left_value
|
||||
.greater_than_or_equal(&right_value)
|
||||
.map_err(|error| RuntimeError::ValueError {
|
||||
error,
|
||||
left_position,
|
||||
right_position,
|
||||
})?,
|
||||
ComparisonOperator::LessThan => left_value
|
||||
.less_than(&right_value)
|
||||
.map_err(|error| RuntimeError::ValueError {
|
||||
error,
|
||||
left_position,
|
||||
right_position,
|
||||
})?,
|
||||
ComparisonOperator::LessThanOrEqual => left_value
|
||||
.less_than_or_equal(&right_value)
|
||||
.map_err(|error| RuntimeError::ValueError {
|
||||
error,
|
||||
left_position,
|
||||
right_position,
|
||||
})?,
|
||||
ComparisonOperator::GreaterThan => left_value.greater_than(&right_value),
|
||||
ComparisonOperator::GreaterThanOrEqual => {
|
||||
left_value.greater_than_or_equal(&right_value)
|
||||
}
|
||||
ComparisonOperator::LessThan => left_value.less_than(&right_value),
|
||||
ComparisonOperator::LessThanOrEqual => {
|
||||
left_value.less_than_or_equal(&right_value)
|
||||
}
|
||||
};
|
||||
let value = result.map_err(|error| RuntimeError::ValueError {
|
||||
error,
|
||||
left_position,
|
||||
right_position,
|
||||
})?;
|
||||
|
||||
Ok(Evaluation::Return(Some(outcome)))
|
||||
Ok(Evaluation::Return(Some(value)))
|
||||
}
|
||||
OperatorExpression::CompoundAssignment {
|
||||
assignee,
|
||||
@ -554,10 +561,11 @@ impl Vm {
|
||||
let value = self
|
||||
.run_expression(expression, collect_garbage)?
|
||||
.expect_value(position)?;
|
||||
let integer = value
|
||||
.as_integer()
|
||||
.ok_or(RuntimeError::ExpectedBoolean { position })?;
|
||||
let negated = Value::Integer(-integer);
|
||||
let negated = value.negate().map_err(|error| RuntimeError::ValueError {
|
||||
error,
|
||||
left_position: position,
|
||||
right_position: position,
|
||||
})?;
|
||||
|
||||
Ok(Evaluation::Return(Some(negated)))
|
||||
}
|
||||
@ -566,10 +574,11 @@ impl Vm {
|
||||
let value = self
|
||||
.run_expression(expression, collect_garbage)?
|
||||
.expect_value(position)?;
|
||||
let boolean = value
|
||||
.as_boolean()
|
||||
.ok_or(RuntimeError::ExpectedBoolean { position })?;
|
||||
let not = Value::Boolean(!boolean);
|
||||
let not = value.not().map_err(|error| RuntimeError::ValueError {
|
||||
error,
|
||||
left_position: position,
|
||||
right_position: position,
|
||||
})?;
|
||||
|
||||
Ok(Evaluation::Return(Some(not)))
|
||||
}
|
||||
@ -666,14 +675,14 @@ impl Vm {
|
||||
fn run_literal(&self, literal: LiteralExpression) -> Result<Evaluation, RuntimeError> {
|
||||
let value = match literal {
|
||||
LiteralExpression::BuiltInFunction(built_in_function) => {
|
||||
Value::Function(Function::BuiltIn(built_in_function))
|
||||
Value::function(Function::BuiltIn(built_in_function))
|
||||
}
|
||||
LiteralExpression::String(string) => Value::String(string),
|
||||
LiteralExpression::String(string) => Value::string(string),
|
||||
LiteralExpression::Primitive(primitive_expression) => match primitive_expression {
|
||||
PrimitiveValueExpression::Boolean(boolean) => Value::Boolean(boolean),
|
||||
PrimitiveValueExpression::Character(character) => Value::Character(character),
|
||||
PrimitiveValueExpression::Integer(integer) => Value::Integer(integer),
|
||||
PrimitiveValueExpression::Float(float) => Value::Float(float),
|
||||
PrimitiveValueExpression::Boolean(boolean) => Value::boolean(boolean),
|
||||
PrimitiveValueExpression::Character(character) => Value::character(character),
|
||||
PrimitiveValueExpression::Integer(integer) => Value::integer(integer),
|
||||
PrimitiveValueExpression::Float(float) => Value::float(float),
|
||||
},
|
||||
};
|
||||
|
||||
@ -699,14 +708,14 @@ impl Vm {
|
||||
|
||||
let get_index =
|
||||
list_value
|
||||
.get_index(index_value)
|
||||
.index(&index_value)
|
||||
.map_err(|error| RuntimeError::ValueError {
|
||||
error,
|
||||
left_position: list_position,
|
||||
right_position: index_position,
|
||||
})?;
|
||||
|
||||
Ok(Evaluation::Return(get_index))
|
||||
Ok(Evaluation::Return(Some(get_index)))
|
||||
}
|
||||
|
||||
fn run_call(
|
||||
@ -728,14 +737,33 @@ impl Vm {
|
||||
.expect_value(container_position)?;
|
||||
|
||||
let function = if let Some(value) = container_value.get_field(&field.inner) {
|
||||
if let Value::Function(function) = value {
|
||||
function
|
||||
} else {
|
||||
match value {
|
||||
Value::Raw(ValueData::Function(function)) => function,
|
||||
Value::Reference(arc) => match arc.as_ref().clone() {
|
||||
ValueData::Function(function) => function,
|
||||
_ => {
|
||||
return Err(RuntimeError::ExpectedFunction {
|
||||
actual: value,
|
||||
position: container_position,
|
||||
actual: container_value,
|
||||
});
|
||||
}
|
||||
},
|
||||
Value::Mutable(locked) => match locked.read().unwrap().clone() {
|
||||
ValueData::Function(function) => function,
|
||||
_ => {
|
||||
return Err(RuntimeError::ExpectedFunction {
|
||||
position: container_position,
|
||||
actual: container_value,
|
||||
});
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
return Err(RuntimeError::ExpectedFunction {
|
||||
position: container_position,
|
||||
actual: container_value,
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return Err(RuntimeError::UndefinedField {
|
||||
value: container_value,
|
||||
@ -798,13 +826,32 @@ impl Vm {
|
||||
}
|
||||
},
|
||||
Evaluation::Return(Some(value)) => {
|
||||
let function = if let Value::Function(function) = value {
|
||||
function
|
||||
} else {
|
||||
let function = match value {
|
||||
Value::Raw(ValueData::Function(function)) => function,
|
||||
Value::Reference(arc) => match arc.as_ref() {
|
||||
ValueData::Function(function) => function.clone(),
|
||||
_ => {
|
||||
return Err(RuntimeError::ExpectedFunction {
|
||||
actual: value.to_owned(),
|
||||
position: invoker_position,
|
||||
actual: Value::Reference(arc.clone()),
|
||||
});
|
||||
}
|
||||
},
|
||||
Value::Mutable(locked) => match locked.read().unwrap().clone() {
|
||||
ValueData::Function(function) => function,
|
||||
_ => {
|
||||
return Err(RuntimeError::ExpectedFunction {
|
||||
position: invoker_position,
|
||||
actual: Value::Mutable(locked.clone()),
|
||||
});
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
return Err(RuntimeError::ExpectedFunction {
|
||||
position: invoker_position,
|
||||
actual: value,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
let mut value_arguments: Option<Vec<Value>> = None;
|
||||
@ -880,13 +927,13 @@ impl Vm {
|
||||
.run_expression(repeat_operand, collect_garbage)?
|
||||
.expect_value(position)?;
|
||||
|
||||
Ok(Evaluation::Return(Some(Value::List(vec![
|
||||
Ok(Evaluation::Return(Some(Value::list(vec![
|
||||
value;
|
||||
length as usize
|
||||
]))))
|
||||
}
|
||||
ListExpression::Ordered(expressions) => {
|
||||
let mut values = Vec::new();
|
||||
let mut values = Vec::with_capacity(expressions.len());
|
||||
|
||||
for expression in expressions {
|
||||
let position = expression.position();
|
||||
@ -897,7 +944,7 @@ impl Vm {
|
||||
values.push(value);
|
||||
}
|
||||
|
||||
Ok(Evaluation::Return(Some(Value::List(values))))
|
||||
Ok(Evaluation::Return(Some(Value::list(values))))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user