Infer ranged number for chars in patterns

This commit is contained in:
Ayaz Hafiz 2022-10-03 15:57:54 -05:00
parent 811c8554ac
commit 619cd2f629
No known key found for this signature in database
GPG key ID: 0E2A37416A25EF58
8 changed files with 48 additions and 17 deletions

View file

@ -725,7 +725,7 @@ fn deep_copy_pattern_help<C: CopyEnv>(
FloatLiteral(sub!(*v1), sub!(*v2), s.clone(), *n, *bound)
}
StrLiteral(s) => StrLiteral(s.clone()),
SingleQuote(c) => SingleQuote(*c),
SingleQuote(v1, v2, c, bound) => SingleQuote(sub!(*v1), sub!(*v2), *c, *bound),
Underscore => Underscore,
AbilityMemberSpecialization { ident, specializes } => AbilityMemberSpecialization {
ident: *ident,

View file

@ -1884,7 +1884,7 @@ fn pattern_to_vars_by_symbol(
| IntLiteral(..)
| FloatLiteral(..)
| StrLiteral(_)
| SingleQuote(_)
| SingleQuote(..)
| Underscore
| MalformedPattern(_, _)
| UnsupportedPattern(_)

View file

@ -253,7 +253,7 @@ fn sketch_pattern(pattern: &crate::pattern::Pattern) -> SketchedPattern {
}
&FloatLiteral(_, _, _, f, _) => SP::Literal(Literal::Float(f64::to_bits(f))),
StrLiteral(v) => SP::Literal(Literal::Str(v.clone())),
&SingleQuote(c) => SP::Literal(Literal::Byte(c as u8)),
&SingleQuote(_, _, c, _) => SP::Literal(Literal::Byte(c as u8)),
RecordDestructure { destructs, .. } => {
let tag_id = TagId(0);
let mut patterns = std::vec::Vec::with_capacity(destructs.len());

View file

@ -899,7 +899,7 @@ fn fix_values_captured_in_closure_pattern(
| IntLiteral(..)
| FloatLiteral(..)
| StrLiteral(_)
| SingleQuote(_)
| SingleQuote(..)
| Underscore
| Shadowed(..)
| MalformedPattern(_, _)

View file

@ -12,6 +12,7 @@ use roc_parse::ast::{self, StrLiteral, StrSegment};
use roc_parse::pattern::PatternType;
use roc_problem::can::{MalformedPatternProblem, Problem, RuntimeError, ShadowKind};
use roc_region::all::{Loc, Region};
use roc_types::num::SingleQuoteBound;
use roc_types::subs::{VarStore, Variable};
use roc_types::types::{LambdaSet, OptAbleVar, PatternCategory, Type};
@ -59,7 +60,7 @@ pub enum Pattern {
IntLiteral(Variable, Variable, Box<str>, IntValue, IntBound),
FloatLiteral(Variable, Variable, Box<str>, f64, FloatBound),
StrLiteral(Box<str>),
SingleQuote(char),
SingleQuote(Variable, Variable, char, SingleQuoteBound),
Underscore,
/// An identifier that marks a specialization of an ability member.
@ -95,7 +96,7 @@ impl Pattern {
IntLiteral(var, ..) => Some(*var),
FloatLiteral(var, ..) => Some(*var),
StrLiteral(_) => None,
SingleQuote(_) => None,
SingleQuote(..) => None,
Underscore => None,
AbilityMemberSpecialization { .. } => None,
@ -148,7 +149,7 @@ impl Pattern {
IntLiteral(..) => C::Int,
FloatLiteral(..) => C::Float,
StrLiteral(_) => C::Str,
SingleQuote(_) => C::Character,
SingleQuote(..) => C::Character,
Underscore => C::PatternDefault,
AbilityMemberSpecialization { .. } => C::PatternDefault,
@ -456,7 +457,12 @@ pub fn canonicalize_pattern<'a>(
let mut it = string.chars().peekable();
if let Some(char) = it.next() {
if it.peek().is_none() {
Pattern::SingleQuote(char)
Pattern::SingleQuote(
var_store.fresh(),
var_store.fresh(),
char,
SingleQuoteBound::from_char(char),
)
} else {
// multiple chars is found
let problem = MalformedPatternProblem::MultipleCharsInSingleQuote;
@ -724,7 +730,7 @@ impl<'a> BindingsFromPattern<'a> {
| IntLiteral(..)
| FloatLiteral(..)
| StrLiteral(_)
| SingleQuote(_)
| SingleQuote(..)
| Underscore
| Shadowed(_, _, _)
| MalformedPattern(_, _)

View file

@ -71,7 +71,7 @@ fn headers_from_annotation_help(
| NumLiteral(..)
| IntLiteral(..)
| FloatLiteral(..)
| SingleQuote(_)
| SingleQuote(..)
| StrLiteral(_) => true,
RecordDestructure { destructs, .. } => match annotation.value.shallow_dealias() {
@ -320,9 +320,32 @@ pub fn constrain_pattern(
));
}
SingleQuote(_) => {
&SingleQuote(num_var, precision_var, _, bound) => {
// First constraint on the free num var; this improves the resolved type quality in
// case the bound is an alias.
let num_type = builtins::add_numeric_bound_constr(
constraints,
&mut state.constraints,
num_var,
num_var,
bound,
region,
Category::Int,
);
// Link the free num var with the int var and our expectation.
let int_type = builtins::num_int(Type::Variable(precision_var));
state.constraints.push(constraints.equal_types(
num_type.clone(), // TODO check me if something breaks!
Expected::NoExpectation(int_type),
Category::Int,
region,
));
// Also constrain the pattern against the num var, again to reuse aliases if they're present.
state.constraints.push(constraints.equal_pattern_types(
builtins::num_u32(),
num_type,
expected,
PatternCategory::Character,
region,

View file

@ -8889,10 +8889,12 @@ fn from_can_pattern_help<'a>(
IntOrFloatValue::Float(*float),
)),
StrLiteral(v) => Ok(Pattern::StrLiteral(v.clone())),
SingleQuote(c) => Ok(Pattern::IntLiteral(
(*c as i128).to_ne_bytes(),
IntWidth::I32,
)),
SingleQuote(var, _, c, _) => match layout_cache.from_var(env.arena, *var, env.subs) {
Ok(Layout::Builtin(Builtin::Int(width))) => {
Ok(Pattern::IntLiteral((*c as i128).to_ne_bytes(), width))
}
o => internal_error!("an integer width was expected, but we found {:?}", o),
},
Shadowed(region, ident, _new_symbol) => Err(RuntimeError::Shadowing {
original_region: *region,
shadow: ident.clone(),

View file

@ -366,7 +366,7 @@ fn pattern<'a>(
f.text(&**n)
}
StrLiteral(s) => f.text(format!(r#""{}""#, s)),
SingleQuote(c) => f.text(format!("'{}'", c)),
SingleQuote(_, _, c, _) => f.text(format!("'{}'", c)),
Underscore => f.text("_"),
Shadowed(_, _, _) => todo!(),