λ Support functions! #5

Open
acw wants to merge 59 commits from awick/functions into develop
4 changed files with 48 additions and 1 deletions
Showing only changes of commit 7101b62efb - Show all commits

View File

@@ -106,6 +106,7 @@ impl<IR: Clone> Value<IR> {
match left {
Value::I8(x) => match right {
Value::I8(y) => run_op!(operation, x, *y),
Value::Number(y) => run_op!(operation, x, *y as i8),
_ => Err(PrimOpError::TypeMismatch(
operation.to_string(),
left.clone(),
@@ -114,6 +115,7 @@ impl<IR: Clone> Value<IR> {
},
Value::I16(x) => match right {
Value::I16(y) => run_op!(operation, x, *y),
Value::Number(y) => run_op!(operation, x, *y as i16),
_ => Err(PrimOpError::TypeMismatch(
operation.to_string(),
left.clone(),
@@ -122,6 +124,7 @@ impl<IR: Clone> Value<IR> {
},
Value::I32(x) => match right {
Value::I32(y) => run_op!(operation, x, *y),
Value::Number(y) => run_op!(operation, x, *y as i32),
_ => Err(PrimOpError::TypeMismatch(
operation.to_string(),
left.clone(),
@@ -130,6 +133,7 @@ impl<IR: Clone> Value<IR> {
},
Value::I64(x) => match right {
Value::I64(y) => run_op!(operation, x, *y),
Value::Number(y) => run_op!(operation, x, *y as i64),
_ => Err(PrimOpError::TypeMismatch(
operation.to_string(),
left.clone(),
@@ -138,6 +142,7 @@ impl<IR: Clone> Value<IR> {
},
Value::U8(x) => match right {
Value::U8(y) => run_op!(operation, x, *y),
Value::Number(y) => run_op!(operation, x, *y as u8),
_ => Err(PrimOpError::TypeMismatch(
operation.to_string(),
left.clone(),
@@ -146,6 +151,7 @@ impl<IR: Clone> Value<IR> {
},
Value::U16(x) => match right {
Value::U16(y) => run_op!(operation, x, *y),
Value::Number(y) => run_op!(operation, x, *y as u16),
_ => Err(PrimOpError::TypeMismatch(
operation.to_string(),
left.clone(),
@@ -154,6 +160,7 @@ impl<IR: Clone> Value<IR> {
},
Value::U32(x) => match right {
Value::U32(y) => run_op!(operation, x, *y),
Value::Number(y) => run_op!(operation, x, *y as u32),
_ => Err(PrimOpError::TypeMismatch(
operation.to_string(),
left.clone(),
@@ -162,12 +169,29 @@ impl<IR: Clone> Value<IR> {
},
Value::U64(x) => match right {
Value::U64(y) => run_op!(operation, x, *y),
Value::Number(y) => run_op!(operation, x, *y),
_ => Err(PrimOpError::TypeMismatch(
operation.to_string(),
left.clone(),
right.clone(),
)),
},
Value::Number(x) => match right {
Value::Number(y) => run_op!(operation, x, *y),
Value::U8(y) => run_op!(operation, (*x as u8), *y),
Value::U16(y) => run_op!(operation, (*x as u16), *y),
Value::U32(y) => run_op!(operation, (*x as u32), *y),
Value::U64(y) => run_op!(operation, x, *y),
Value::I8(y) => run_op!(operation, (*x as i8), *y),
Value::I16(y) => run_op!(operation, (*x as i16), *y),
Value::I32(y) => run_op!(operation, (*x as i32), *y),
Value::I64(y) => run_op!(operation, (*x as i64), *y),
_ => Err(PrimOpError::TypeMismatch(
operation.to_string(),
left.clone(),
right.clone(),
)),
}
Value::Closure(_, _, _, _) | Value::Void => {
Err(PrimOpError::BadTypeFor(operation.to_string(), left.clone()))
}

View File

@@ -53,6 +53,8 @@ impl<'a, IR> TryFrom<&'a Value<IR>> for PrimitiveType {
Value::U16(_) => Ok(PrimitiveType::U16),
Value::U32(_) => Ok(PrimitiveType::U32),
Value::U64(_) => Ok(PrimitiveType::U64),
// not sure this is the right call
Value::Number(_) => Ok(PrimitiveType::U64),
Value::Closure(name, _, _, _) => Err(ValuePrimitiveTypeError::CannotConvertFunction(
name.as_ref().map(|x| (**x).clone()),
)),

View File

@@ -18,6 +18,8 @@ pub enum Value<IR> {
U16(u16),
U32(u32),
U64(u64),
// a number of unknown type
Number(u64),
Closure(
Option<ArcIntern<String>>,
ScopedMap<ArcIntern<String>, Value<IR>>,
@@ -43,6 +45,7 @@ impl<IR: Clone> Value<IR> {
Value::I16(x) => Value::I16(*x),
Value::I32(x) => Value::I32(*x),
Value::I64(x) => Value::I64(*x),
Value::Number(x) => Value::Number(*x),
Value::Closure(name, env, args, _) => {
let new_env = env.clone().map_values(|x| x.strip());
Value::Closure(name.clone(), new_env, args.clone(), ())
@@ -62,6 +65,7 @@ fn format_value<IR>(value: &Value<IR>, f: &mut fmt::Formatter<'_>) -> fmt::Resul
Value::U16(x) => write!(f, "{}u16", x),
Value::U32(x) => write!(f, "{}u32", x),
Value::U64(x) => write!(f, "{}u64", x),
Value::Number(x) => write!(f, "{}", x),
Value::Closure(Some(name), _, _, _) => write!(f, "<function {}>", name),
Value::Closure(None, _, _, _) => write!(f, "<function>"),
}
@@ -115,6 +119,18 @@ impl<IR1, IR2> PartialEq<Value<IR2>> for Value<IR1> {
Value::U64(y) => x == y,
_ => false,
},
Value::Number(x) => match other {
Value::I8(y) => (*x as i8) == *y,
Value::I16(y) => (*x as i16) == *y,
Value::I32(y) => (*x as i32) == *y,
Value::I64(y) => (*x as i64) == *y,
Value::U8(y) => (*x as u8) == *y,
Value::U16(y) => (*x as u16) == *y,
Value::U32(y) => (*x as u32) == *y,
Value::U64(y) => x == y,
Value::Number(y) => x == y,
_ => false,
}
Value::Closure(_, _, _, _) => false,
}
}

View File

@@ -45,6 +45,11 @@ impl Program {
let value = env
.get(&name.clone().intern())
.ok_or_else(|| EvalError::LookupFailed(loc.clone(), name.name.clone()))?;
let value = if let Value::Number(x) = value {
Value::U64(*x)
} else {
value.clone()
};
let line = format!("{} = {}\n", name, value);
stdout.push_str(&line);
last_result = Value::Void;
@@ -64,7 +69,7 @@ impl Expression {
match self {
Expression::Value(_, v) => match v {
super::Value::Number(_, ty, v) => match ty {
None => Ok(Value::U64(*v)),
None => Ok(Value::Number(*v)),
// FIXME: make these types validate their input size
Some(ConstantType::Void) => Ok(Value::Void),
Some(ConstantType::I8) => Ok(Value::I8(*v as i8)),