Add support for multiple integer types.
This commit is contained in:
@@ -1,12 +1,11 @@
|
||||
use std::collections::HashSet;
|
||||
|
||||
use crate::syntax::ast::{Expression, Program, Statement, Value};
|
||||
use crate::syntax::ast::{ConstantType, Expression, Program, Statement, Value};
|
||||
use crate::syntax::location::Location;
|
||||
use proptest::sample::select;
|
||||
use proptest::{
|
||||
prelude::{Arbitrary, BoxedStrategy, Strategy},
|
||||
strategy::{Just, Union},
|
||||
};
|
||||
use std::collections::HashMap;
|
||||
|
||||
const VALID_VARIABLE_NAMES: &str = r"[a-z][a-zA-Z0-9_]*";
|
||||
|
||||
@@ -27,36 +26,38 @@ impl Arbitrary for Program {
|
||||
type Strategy = BoxedStrategy<Self>;
|
||||
|
||||
fn arbitrary_with(_: Self::Parameters) -> Self::Strategy {
|
||||
let optionals = Vec::<Option<Name>>::arbitrary();
|
||||
let optionals = Vec::<Option<(Name, ConstantType)>>::arbitrary();
|
||||
|
||||
optionals
|
||||
.prop_flat_map(|mut possible_names| {
|
||||
let mut statements = Vec::new();
|
||||
let mut defined_variables: HashSet<String> = HashSet::new();
|
||||
let mut defined_variables: HashMap<String, ConstantType> = HashMap::new();
|
||||
|
||||
for possible_name in possible_names.drain(..) {
|
||||
match possible_name {
|
||||
None if defined_variables.is_empty() => continue,
|
||||
None => statements.push(
|
||||
Union::new(defined_variables.iter().map(|name| {
|
||||
Union::new(defined_variables.keys().map(|name| {
|
||||
Just(Statement::Print(Location::manufactured(), name.to_string()))
|
||||
}))
|
||||
.boxed(),
|
||||
),
|
||||
Some(new_name) => {
|
||||
Some((new_name, new_type)) => {
|
||||
let closures_name = new_name.0.clone();
|
||||
let retval =
|
||||
Expression::arbitrary_with(Some(defined_variables.clone()))
|
||||
.prop_map(move |exp| {
|
||||
Statement::Binding(
|
||||
Location::manufactured(),
|
||||
closures_name.clone(),
|
||||
exp,
|
||||
)
|
||||
})
|
||||
.boxed();
|
||||
let retval = Expression::arbitrary_with((
|
||||
Some(defined_variables.clone()),
|
||||
Some(new_type),
|
||||
))
|
||||
.prop_map(move |exp| {
|
||||
Statement::Binding(
|
||||
Location::manufactured(),
|
||||
closures_name.clone(),
|
||||
exp,
|
||||
)
|
||||
})
|
||||
.boxed();
|
||||
|
||||
defined_variables.insert(new_name.0);
|
||||
defined_variables.insert(new_name.0, new_type);
|
||||
statements.push(retval);
|
||||
}
|
||||
}
|
||||
@@ -70,7 +71,7 @@ impl Arbitrary for Program {
|
||||
}
|
||||
|
||||
impl Arbitrary for Statement {
|
||||
type Parameters = Option<HashSet<String>>;
|
||||
type Parameters = Option<HashMap<String, ConstantType>>;
|
||||
type Strategy = BoxedStrategy<Self>;
|
||||
|
||||
fn arbitrary_with(args: Self::Parameters) -> Self::Strategy {
|
||||
@@ -79,7 +80,7 @@ impl Arbitrary for Statement {
|
||||
|
||||
let binding_strategy = (
|
||||
VALID_VARIABLE_NAMES,
|
||||
Expression::arbitrary_with(duplicated_args),
|
||||
Expression::arbitrary_with((duplicated_args, None)),
|
||||
)
|
||||
.prop_map(|(name, exp)| Statement::Binding(Location::manufactured(), name, exp))
|
||||
.boxed();
|
||||
@@ -89,7 +90,7 @@ impl Arbitrary for Statement {
|
||||
} else {
|
||||
let print_strategy = Union::new(
|
||||
defined_variables
|
||||
.iter()
|
||||
.keys()
|
||||
.map(|x| Just(Statement::Print(Location::manufactured(), x.to_string()))),
|
||||
)
|
||||
.boxed();
|
||||
@@ -100,20 +101,25 @@ impl Arbitrary for Statement {
|
||||
}
|
||||
|
||||
impl Arbitrary for Expression {
|
||||
type Parameters = Option<HashSet<String>>;
|
||||
type Parameters = (Option<HashMap<String, ConstantType>>, Option<ConstantType>);
|
||||
type Strategy = BoxedStrategy<Self>;
|
||||
|
||||
fn arbitrary_with(args: Self::Parameters) -> Self::Strategy {
|
||||
let defined_variables = args.unwrap_or_default();
|
||||
fn arbitrary_with((env, target_type): Self::Parameters) -> Self::Strategy {
|
||||
let defined_variables = env.unwrap_or_default();
|
||||
let mut acceptable_variables = defined_variables
|
||||
.iter()
|
||||
.filter(|(_, ctype)| Some(**ctype) == target_type)
|
||||
.map(|(x, _)| x)
|
||||
.peekable();
|
||||
|
||||
let value_strategy = Value::arbitrary()
|
||||
let value_strategy = Value::arbitrary_with(target_type)
|
||||
.prop_map(move |x| Expression::Value(Location::manufactured(), x))
|
||||
.boxed();
|
||||
|
||||
let leaf_strategy = if defined_variables.is_empty() {
|
||||
let leaf_strategy = if acceptable_variables.peek().is_none() {
|
||||
value_strategy
|
||||
} else {
|
||||
let reference_strategy = Union::new(defined_variables.iter().map(|x| {
|
||||
let reference_strategy = Union::new(acceptable_variables.map(|x| {
|
||||
Just(Expression::Reference(
|
||||
Location::manufactured(),
|
||||
x.to_owned(),
|
||||
@@ -138,10 +144,10 @@ impl Arbitrary for Expression {
|
||||
}
|
||||
|
||||
impl Arbitrary for Value {
|
||||
type Parameters = ();
|
||||
type Parameters = Option<ConstantType>;
|
||||
type Strategy = BoxedStrategy<Self>;
|
||||
|
||||
fn arbitrary_with(_: Self::Parameters) -> Self::Strategy {
|
||||
fn arbitrary_with(target_type: Self::Parameters) -> Self::Strategy {
|
||||
let base_strategy = Union::new([
|
||||
Just(None::<u8>),
|
||||
Just(Some(2)),
|
||||
@@ -150,10 +156,47 @@ impl Arbitrary for Value {
|
||||
Just(Some(16)),
|
||||
]);
|
||||
|
||||
let value_strategy = i64::arbitrary();
|
||||
let type_strategy = if target_type.is_some() {
|
||||
Just(target_type).boxed()
|
||||
} else {
|
||||
proptest::option::of(ConstantType::arbitrary()).boxed()
|
||||
};
|
||||
let value_strategy = u64::arbitrary();
|
||||
|
||||
(base_strategy, value_strategy)
|
||||
.prop_map(move |(base, value)| Value::Number(base, value))
|
||||
(base_strategy, type_strategy, value_strategy)
|
||||
.prop_map(move |(base, ty, value)| {
|
||||
let converted_value = match ty {
|
||||
Some(ConstantType::I8) => value % (i8::MAX as u64),
|
||||
Some(ConstantType::U8) => value % (u8::MAX as u64),
|
||||
Some(ConstantType::I16) => value % (i16::MAX as u64),
|
||||
Some(ConstantType::U16) => value % (u16::MAX as u64),
|
||||
Some(ConstantType::I32) => value % (i32::MAX as u64),
|
||||
Some(ConstantType::U32) => value % (u32::MAX as u64),
|
||||
Some(ConstantType::I64) => value % (i64::MAX as u64),
|
||||
Some(ConstantType::U64) => value,
|
||||
None => value,
|
||||
};
|
||||
Value::Number(base, ty, converted_value)
|
||||
})
|
||||
.boxed()
|
||||
}
|
||||
}
|
||||
|
||||
impl Arbitrary for ConstantType {
|
||||
type Parameters = ();
|
||||
type Strategy = BoxedStrategy<Self>;
|
||||
|
||||
fn arbitrary_with(_: Self::Parameters) -> Self::Strategy {
|
||||
Union::new([
|
||||
Just(ConstantType::I8),
|
||||
Just(ConstantType::I16),
|
||||
Just(ConstantType::I32),
|
||||
Just(ConstantType::I64),
|
||||
Just(ConstantType::U8),
|
||||
Just(ConstantType::U16),
|
||||
Just(ConstantType::U32),
|
||||
Just(ConstantType::U64),
|
||||
])
|
||||
.boxed()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user