λ 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 { match left {
Value::I8(x) => match right { Value::I8(x) => match right {
Value::I8(y) => run_op!(operation, x, *y), Value::I8(y) => run_op!(operation, x, *y),
Value::Number(y) => run_op!(operation, x, *y as i8),
_ => Err(PrimOpError::TypeMismatch( _ => Err(PrimOpError::TypeMismatch(
operation.to_string(), operation.to_string(),
left.clone(), left.clone(),
@@ -114,6 +115,7 @@ impl<IR: Clone> Value<IR> {
}, },
Value::I16(x) => match right { Value::I16(x) => match right {
Value::I16(y) => run_op!(operation, x, *y), Value::I16(y) => run_op!(operation, x, *y),
Value::Number(y) => run_op!(operation, x, *y as i16),
_ => Err(PrimOpError::TypeMismatch( _ => Err(PrimOpError::TypeMismatch(
operation.to_string(), operation.to_string(),
left.clone(), left.clone(),
@@ -122,6 +124,7 @@ impl<IR: Clone> Value<IR> {
}, },
Value::I32(x) => match right { Value::I32(x) => match right {
Value::I32(y) => run_op!(operation, x, *y), Value::I32(y) => run_op!(operation, x, *y),
Value::Number(y) => run_op!(operation, x, *y as i32),
_ => Err(PrimOpError::TypeMismatch( _ => Err(PrimOpError::TypeMismatch(
operation.to_string(), operation.to_string(),
left.clone(), left.clone(),
@@ -130,6 +133,7 @@ impl<IR: Clone> Value<IR> {
}, },
Value::I64(x) => match right { Value::I64(x) => match right {
Value::I64(y) => run_op!(operation, x, *y), Value::I64(y) => run_op!(operation, x, *y),
Value::Number(y) => run_op!(operation, x, *y as i64),
_ => Err(PrimOpError::TypeMismatch( _ => Err(PrimOpError::TypeMismatch(
operation.to_string(), operation.to_string(),
left.clone(), left.clone(),
@@ -138,6 +142,7 @@ impl<IR: Clone> Value<IR> {
}, },
Value::U8(x) => match right { Value::U8(x) => match right {
Value::U8(y) => run_op!(operation, x, *y), Value::U8(y) => run_op!(operation, x, *y),
Value::Number(y) => run_op!(operation, x, *y as u8),
_ => Err(PrimOpError::TypeMismatch( _ => Err(PrimOpError::TypeMismatch(
operation.to_string(), operation.to_string(),
left.clone(), left.clone(),
@@ -146,6 +151,7 @@ impl<IR: Clone> Value<IR> {
}, },
Value::U16(x) => match right { Value::U16(x) => match right {
Value::U16(y) => run_op!(operation, x, *y), Value::U16(y) => run_op!(operation, x, *y),
Value::Number(y) => run_op!(operation, x, *y as u16),
_ => Err(PrimOpError::TypeMismatch( _ => Err(PrimOpError::TypeMismatch(
operation.to_string(), operation.to_string(),
left.clone(), left.clone(),
@@ -154,6 +160,7 @@ impl<IR: Clone> Value<IR> {
}, },
Value::U32(x) => match right { Value::U32(x) => match right {
Value::U32(y) => run_op!(operation, x, *y), Value::U32(y) => run_op!(operation, x, *y),
Value::Number(y) => run_op!(operation, x, *y as u32),
_ => Err(PrimOpError::TypeMismatch( _ => Err(PrimOpError::TypeMismatch(
operation.to_string(), operation.to_string(),
left.clone(), left.clone(),
@@ -162,12 +169,29 @@ impl<IR: Clone> Value<IR> {
}, },
Value::U64(x) => match right { Value::U64(x) => match right {
Value::U64(y) => run_op!(operation, x, *y), Value::U64(y) => run_op!(operation, x, *y),
Value::Number(y) => run_op!(operation, x, *y),
_ => Err(PrimOpError::TypeMismatch( _ => Err(PrimOpError::TypeMismatch(
operation.to_string(), operation.to_string(),
left.clone(), left.clone(),
right.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 => { Value::Closure(_, _, _, _) | Value::Void => {
Err(PrimOpError::BadTypeFor(operation.to_string(), left.clone())) 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::U16(_) => Ok(PrimitiveType::U16),
Value::U32(_) => Ok(PrimitiveType::U32), Value::U32(_) => Ok(PrimitiveType::U32),
Value::U64(_) => Ok(PrimitiveType::U64), Value::U64(_) => Ok(PrimitiveType::U64),
// not sure this is the right call
Value::Number(_) => Ok(PrimitiveType::U64),
Value::Closure(name, _, _, _) => Err(ValuePrimitiveTypeError::CannotConvertFunction( Value::Closure(name, _, _, _) => Err(ValuePrimitiveTypeError::CannotConvertFunction(
name.as_ref().map(|x| (**x).clone()), name.as_ref().map(|x| (**x).clone()),
)), )),

View File

@@ -18,6 +18,8 @@ pub enum Value<IR> {
U16(u16), U16(u16),
U32(u32), U32(u32),
U64(u64), U64(u64),
// a number of unknown type
Number(u64),
Closure( Closure(
Option<ArcIntern<String>>, Option<ArcIntern<String>>,
ScopedMap<ArcIntern<String>, Value<IR>>, ScopedMap<ArcIntern<String>, Value<IR>>,
@@ -43,6 +45,7 @@ impl<IR: Clone> Value<IR> {
Value::I16(x) => Value::I16(*x), Value::I16(x) => Value::I16(*x),
Value::I32(x) => Value::I32(*x), Value::I32(x) => Value::I32(*x),
Value::I64(x) => Value::I64(*x), Value::I64(x) => Value::I64(*x),
Value::Number(x) => Value::Number(*x),
Value::Closure(name, env, args, _) => { Value::Closure(name, env, args, _) => {
let new_env = env.clone().map_values(|x| x.strip()); let new_env = env.clone().map_values(|x| x.strip());
Value::Closure(name.clone(), new_env, args.clone(), ()) 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::U16(x) => write!(f, "{}u16", x),
Value::U32(x) => write!(f, "{}u32", x), Value::U32(x) => write!(f, "{}u32", x),
Value::U64(x) => write!(f, "{}u64", x), Value::U64(x) => write!(f, "{}u64", x),
Value::Number(x) => write!(f, "{}", x),
Value::Closure(Some(name), _, _, _) => write!(f, "<function {}>", name), Value::Closure(Some(name), _, _, _) => write!(f, "<function {}>", name),
Value::Closure(None, _, _, _) => write!(f, "<function>"), Value::Closure(None, _, _, _) => write!(f, "<function>"),
} }
@@ -115,6 +119,18 @@ impl<IR1, IR2> PartialEq<Value<IR2>> for Value<IR1> {
Value::U64(y) => x == y, Value::U64(y) => x == y,
_ => false, _ => 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, Value::Closure(_, _, _, _) => false,
} }
} }

View File

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