diff --git a/src/eval/primop.rs b/src/eval/primop.rs index aa9ffef..464562b 100644 --- a/src/eval/primop.rs +++ b/src/eval/primop.rs @@ -106,6 +106,7 @@ impl Value { 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 Value { }, 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 Value { }, 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 Value { }, 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 Value { }, 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 Value { }, 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 Value { }, 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 Value { }, 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())) } diff --git a/src/eval/primtype.rs b/src/eval/primtype.rs index 3ed2b1c..dc42d1b 100644 --- a/src/eval/primtype.rs +++ b/src/eval/primtype.rs @@ -53,6 +53,8 @@ impl<'a, IR> TryFrom<&'a Value> 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()), )), diff --git a/src/eval/value.rs b/src/eval/value.rs index c31d1ed..a49319b 100644 --- a/src/eval/value.rs +++ b/src/eval/value.rs @@ -18,6 +18,8 @@ pub enum Value { U16(u16), U32(u32), U64(u64), + // a number of unknown type + Number(u64), Closure( Option>, ScopedMap, Value>, @@ -43,6 +45,7 @@ impl Value { 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(value: &Value, 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, "", name), Value::Closure(None, _, _, _) => write!(f, ""), } @@ -115,6 +119,18 @@ impl PartialEq> for Value { 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, } } diff --git a/src/syntax/eval.rs b/src/syntax/eval.rs index 5813702..6f96102 100644 --- a/src/syntax/eval.rs +++ b/src/syntax/eval.rs @@ -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)),