mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-03 08:34:33 +00:00
Get it all to compile!
This commit is contained in:
parent
555478cdf0
commit
8272ea876f
21 changed files with 217 additions and 21 deletions
|
@ -746,6 +746,7 @@ fn pattern_to_vars_by_symbol(
|
||||||
| IntLiteral(_, _, _)
|
| IntLiteral(_, _, _)
|
||||||
| FloatLiteral(_, _, _)
|
| FloatLiteral(_, _, _)
|
||||||
| StrLiteral(_)
|
| StrLiteral(_)
|
||||||
|
| SingleQuote(_)
|
||||||
| Underscore
|
| Underscore
|
||||||
| MalformedPattern(_, _)
|
| MalformedPattern(_, _)
|
||||||
| UnsupportedPattern(_) => {}
|
| UnsupportedPattern(_) => {}
|
||||||
|
|
|
@ -58,6 +58,7 @@ pub enum Expr {
|
||||||
Int(Variable, Variable, Box<str>, i128),
|
Int(Variable, Variable, Box<str>, i128),
|
||||||
Float(Variable, Variable, Box<str>, f64),
|
Float(Variable, Variable, Box<str>, f64),
|
||||||
Str(Box<str>),
|
Str(Box<str>),
|
||||||
|
SingleQuote(char),
|
||||||
List {
|
List {
|
||||||
elem_var: Variable,
|
elem_var: Variable,
|
||||||
loc_elems: Vec<Located<Expr>>,
|
loc_elems: Vec<Located<Expr>>,
|
||||||
|
@ -305,6 +306,26 @@ pub fn canonicalize_expr<'a>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast::Expr::Str(literal) => flatten_str_literal(env, var_store, scope, literal),
|
ast::Expr::Str(literal) => flatten_str_literal(env, var_store, scope, literal),
|
||||||
|
ast::Expr::SingleQuote(string) => {
|
||||||
|
let mut it = string.chars().peekable();
|
||||||
|
if let Some(char) = it.next() {
|
||||||
|
if it.peek().is_none() {
|
||||||
|
(Expr::SingleQuote(char), Output::default())
|
||||||
|
} else {
|
||||||
|
// multiple chars is found
|
||||||
|
let error = roc_problem::can::RuntimeError::MulitpleCharsInSingleQuote(region);
|
||||||
|
let answer = Expr::RuntimeError(error.clone());
|
||||||
|
|
||||||
|
(answer, Output::default())
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// no characters found
|
||||||
|
let error = roc_problem::can::RuntimeError::EmptySingleQuote(region);
|
||||||
|
let answer = Expr::RuntimeError(error.clone());
|
||||||
|
|
||||||
|
(answer, Output::default())
|
||||||
|
}
|
||||||
|
}
|
||||||
ast::Expr::List {
|
ast::Expr::List {
|
||||||
items: loc_elems, ..
|
items: loc_elems, ..
|
||||||
} => {
|
} => {
|
||||||
|
@ -1238,6 +1259,7 @@ pub fn inline_calls(var_store: &mut VarStore, scope: &mut Scope, expr: Expr) ->
|
||||||
| other @ Int(_, _, _, _)
|
| other @ Int(_, _, _, _)
|
||||||
| other @ Float(_, _, _, _)
|
| other @ Float(_, _, _, _)
|
||||||
| other @ Str { .. }
|
| other @ Str { .. }
|
||||||
|
| other @ SingleQuote(_)
|
||||||
| other @ RuntimeError(_)
|
| other @ RuntimeError(_)
|
||||||
| other @ EmptyRecord
|
| other @ EmptyRecord
|
||||||
| other @ Accessor { .. }
|
| other @ Accessor { .. }
|
||||||
|
|
|
@ -386,6 +386,7 @@ fn fix_values_captured_in_closure_pattern(
|
||||||
| IntLiteral(_, _, _)
|
| IntLiteral(_, _, _)
|
||||||
| FloatLiteral(_, _, _)
|
| FloatLiteral(_, _, _)
|
||||||
| StrLiteral(_)
|
| StrLiteral(_)
|
||||||
|
| SingleQuote(_)
|
||||||
| Underscore
|
| Underscore
|
||||||
| Shadowed(_, _)
|
| Shadowed(_, _)
|
||||||
| MalformedPattern(_, _)
|
| MalformedPattern(_, _)
|
||||||
|
@ -442,6 +443,7 @@ fn fix_values_captured_in_closure_expr(
|
||||||
| Int(_, _, _, _)
|
| Int(_, _, _, _)
|
||||||
| Float(_, _, _, _)
|
| Float(_, _, _, _)
|
||||||
| Str(_)
|
| Str(_)
|
||||||
|
| SingleQuote(_)
|
||||||
| Var(_)
|
| Var(_)
|
||||||
| EmptyRecord
|
| EmptyRecord
|
||||||
| RuntimeError(_)
|
| RuntimeError(_)
|
||||||
|
|
|
@ -125,6 +125,7 @@ pub fn desugar_expr<'a>(arena: &'a Bump, loc_expr: &'a Located<Expr<'a>>) -> &'a
|
||||||
| Num(_)
|
| Num(_)
|
||||||
| NonBase10Int { .. }
|
| NonBase10Int { .. }
|
||||||
| Str(_)
|
| Str(_)
|
||||||
|
| SingleQuote(_)
|
||||||
| AccessorFunction(_)
|
| AccessorFunction(_)
|
||||||
| Var { .. }
|
| Var { .. }
|
||||||
| Underscore { .. }
|
| Underscore { .. }
|
||||||
|
|
|
@ -29,6 +29,7 @@ pub enum Pattern {
|
||||||
NumLiteral(Variable, Box<str>, i64),
|
NumLiteral(Variable, Box<str>, i64),
|
||||||
FloatLiteral(Variable, Box<str>, f64),
|
FloatLiteral(Variable, Box<str>, f64),
|
||||||
StrLiteral(Box<str>),
|
StrLiteral(Box<str>),
|
||||||
|
SingleQuote(char),
|
||||||
Underscore,
|
Underscore,
|
||||||
|
|
||||||
// Runtime Exceptions
|
// Runtime Exceptions
|
||||||
|
@ -89,6 +90,7 @@ pub fn symbols_from_pattern_help(pattern: &Pattern, symbols: &mut Vec<Symbol>) {
|
||||||
| IntLiteral(_, _, _)
|
| IntLiteral(_, _, _)
|
||||||
| FloatLiteral(_, _, _)
|
| FloatLiteral(_, _, _)
|
||||||
| StrLiteral(_)
|
| StrLiteral(_)
|
||||||
|
| SingleQuote(_)
|
||||||
| Underscore
|
| Underscore
|
||||||
| MalformedPattern(_, _)
|
| MalformedPattern(_, _)
|
||||||
| UnsupportedPattern(_) => {}
|
| UnsupportedPattern(_) => {}
|
||||||
|
@ -237,6 +239,23 @@ pub fn canonicalize_pattern<'a>(
|
||||||
ptype => unsupported_pattern(env, ptype, region),
|
ptype => unsupported_pattern(env, ptype, region),
|
||||||
},
|
},
|
||||||
|
|
||||||
|
SingleQuote(string) => {
|
||||||
|
let mut it = string.chars().peekable();
|
||||||
|
if let Some(char) = it.next() {
|
||||||
|
if it.peek().is_none() {
|
||||||
|
Pattern::SingleQuote(char)
|
||||||
|
} else {
|
||||||
|
// multiple chars is found
|
||||||
|
let problem = MalformedPatternProblem::MulitpleCharsInSingleQuote;
|
||||||
|
malformed_pattern(env, problem, region)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// no characters found
|
||||||
|
let problem = MalformedPatternProblem::EmptySingleQuote;
|
||||||
|
malformed_pattern(env, problem, region)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SpaceBefore(sub_pattern, _) | SpaceAfter(sub_pattern, _) => {
|
SpaceBefore(sub_pattern, _) | SpaceAfter(sub_pattern, _) => {
|
||||||
return canonicalize_pattern(env, var_store, scope, pattern_type, sub_pattern, region)
|
return canonicalize_pattern(env, var_store, scope, pattern_type, sub_pattern, region)
|
||||||
}
|
}
|
||||||
|
@ -476,6 +495,7 @@ fn add_bindings_from_patterns(
|
||||||
| IntLiteral(_, _, _)
|
| IntLiteral(_, _, _)
|
||||||
| FloatLiteral(_, _, _)
|
| FloatLiteral(_, _, _)
|
||||||
| StrLiteral(_)
|
| StrLiteral(_)
|
||||||
|
| SingleQuote(_)
|
||||||
| Underscore
|
| Underscore
|
||||||
| Shadowed(_, _)
|
| Shadowed(_, _)
|
||||||
| MalformedPattern(_, _)
|
| MalformedPattern(_, _)
|
||||||
|
|
|
@ -158,6 +158,16 @@ pub fn num_signed64() -> Type {
|
||||||
builtin_alias(Symbol::NUM_SIGNED64, vec![], Box::new(alias_content))
|
builtin_alias(Symbol::NUM_SIGNED64, vec![], Box::new(alias_content))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn num_unsigned32() -> Type {
|
||||||
|
let alias_content = Type::TagUnion(
|
||||||
|
vec![(TagName::Private(Symbol::NUM_AT_UNSIGNED32), vec![])],
|
||||||
|
Box::new(Type::EmptyTagUnion),
|
||||||
|
);
|
||||||
|
|
||||||
|
builtin_alias(Symbol::NUM_UNSIGNED32, vec![], Box::new(alias_content))
|
||||||
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn num_integer(range: Type) -> Type {
|
pub fn num_integer(range: Type) -> Type {
|
||||||
let alias_content = Type::TagUnion(
|
let alias_content = Type::TagUnion(
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
use crate::builtins::{empty_list_type, float_literal, int_literal, list_type, str_type};
|
use crate::builtins::{
|
||||||
|
empty_list_type, float_literal, int_literal, list_type, num_unsigned32, str_type,
|
||||||
|
};
|
||||||
use crate::pattern::{constrain_pattern, PatternState};
|
use crate::pattern::{constrain_pattern, PatternState};
|
||||||
use roc_can::annotation::IntroducedVariables;
|
use roc_can::annotation::IntroducedVariables;
|
||||||
use roc_can::constraint::Constraint::{self, *};
|
use roc_can::constraint::Constraint::{self, *};
|
||||||
|
@ -217,6 +219,7 @@ pub fn constrain_expr(
|
||||||
exists(vars, And(cons))
|
exists(vars, And(cons))
|
||||||
}
|
}
|
||||||
Str(_) => Eq(str_type(), expected, Category::Str, region),
|
Str(_) => Eq(str_type(), expected, Category::Str, region),
|
||||||
|
SingleQuote(_) => Eq(num_unsigned32(), expected, Category::Character, region),
|
||||||
List {
|
List {
|
||||||
elem_var,
|
elem_var,
|
||||||
loc_elems,
|
loc_elems,
|
||||||
|
|
|
@ -59,6 +59,7 @@ fn headers_from_annotation_help(
|
||||||
| NumLiteral(_, _, _)
|
| NumLiteral(_, _, _)
|
||||||
| IntLiteral(_, _, _)
|
| IntLiteral(_, _, _)
|
||||||
| FloatLiteral(_, _, _)
|
| FloatLiteral(_, _, _)
|
||||||
|
| SingleQuote(_)
|
||||||
| StrLiteral(_) => true,
|
| StrLiteral(_) => true,
|
||||||
|
|
||||||
RecordDestructure { destructs, .. } => match annotation.value.shallow_dealias() {
|
RecordDestructure { destructs, .. } => match annotation.value.shallow_dealias() {
|
||||||
|
@ -181,6 +182,15 @@ pub fn constrain_pattern(
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SingleQuote(_) => {
|
||||||
|
state.constraints.push(Constraint::Pattern(
|
||||||
|
region,
|
||||||
|
PatternCategory::Character,
|
||||||
|
builtins::num_unsigned32(),
|
||||||
|
expected,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
RecordDestructure {
|
RecordDestructure {
|
||||||
whole_var,
|
whole_var,
|
||||||
ext_var,
|
ext_var,
|
||||||
|
|
|
@ -27,6 +27,7 @@ impl<'a> Formattable<'a> for Expr<'a> {
|
||||||
Float(_)
|
Float(_)
|
||||||
| Num(_)
|
| Num(_)
|
||||||
| NonBase10Int { .. }
|
| NonBase10Int { .. }
|
||||||
|
| SingleQuote(_)
|
||||||
| Access(_, _)
|
| Access(_, _)
|
||||||
| AccessorFunction(_)
|
| AccessorFunction(_)
|
||||||
| Var { .. }
|
| Var { .. }
|
||||||
|
@ -228,6 +229,11 @@ impl<'a> Formattable<'a> for Expr<'a> {
|
||||||
Num(string) | Float(string) | GlobalTag(string) | PrivateTag(string) => {
|
Num(string) | Float(string) | GlobalTag(string) | PrivateTag(string) => {
|
||||||
buf.push_str(string)
|
buf.push_str(string)
|
||||||
}
|
}
|
||||||
|
SingleQuote(string) => {
|
||||||
|
buf.push('\'');
|
||||||
|
buf.push_str(string);
|
||||||
|
buf.push('\'');
|
||||||
|
}
|
||||||
NonBase10Int {
|
NonBase10Int {
|
||||||
base,
|
base,
|
||||||
string,
|
string,
|
||||||
|
|
|
@ -35,6 +35,7 @@ impl<'a> Formattable<'a> for Pattern<'a> {
|
||||||
| Pattern::NonBase10Literal { .. }
|
| Pattern::NonBase10Literal { .. }
|
||||||
| Pattern::FloatLiteral(_)
|
| Pattern::FloatLiteral(_)
|
||||||
| Pattern::StrLiteral(_)
|
| Pattern::StrLiteral(_)
|
||||||
|
| Pattern::SingleQuote(_)
|
||||||
| Pattern::Underscore(_)
|
| Pattern::Underscore(_)
|
||||||
| Pattern::Malformed(_)
|
| Pattern::Malformed(_)
|
||||||
| Pattern::MalformedIdent(_, _)
|
| Pattern::MalformedIdent(_, _)
|
||||||
|
@ -127,6 +128,11 @@ impl<'a> Formattable<'a> for Pattern<'a> {
|
||||||
StrLiteral(literal) => {
|
StrLiteral(literal) => {
|
||||||
todo!("Format string literal: {:?}", literal);
|
todo!("Format string literal: {:?}", literal);
|
||||||
}
|
}
|
||||||
|
SingleQuote(string) => {
|
||||||
|
buf.push('\'');
|
||||||
|
buf.push_str(string);
|
||||||
|
buf.push('\'');
|
||||||
|
}
|
||||||
Underscore(name) => {
|
Underscore(name) => {
|
||||||
buf.push('_');
|
buf.push('_');
|
||||||
buf.push_str(name);
|
buf.push_str(name);
|
||||||
|
|
|
@ -1676,7 +1676,11 @@ fn pattern_to_when<'a>(
|
||||||
(symbol, Located::at_zero(wrapped_body))
|
(symbol, Located::at_zero(wrapped_body))
|
||||||
}
|
}
|
||||||
|
|
||||||
IntLiteral(_, _, _) | NumLiteral(_, _, _) | FloatLiteral(_, _, _) | StrLiteral(_) => {
|
IntLiteral(_, _, _)
|
||||||
|
| NumLiteral(_, _, _)
|
||||||
|
| FloatLiteral(_, _, _)
|
||||||
|
| StrLiteral(_)
|
||||||
|
| roc_can::pattern::Pattern::SingleQuote(_) => {
|
||||||
// These patters are refutable, and thus should never occur outside a `when` expression
|
// These patters are refutable, and thus should never occur outside a `when` expression
|
||||||
// They should have been replaced with `UnsupportedPattern` during canonicalization
|
// They should have been replaced with `UnsupportedPattern` during canonicalization
|
||||||
unreachable!("refutable pattern {:?} where irrefutable pattern is expected. This should never happen!", pattern.value)
|
unreachable!("refutable pattern {:?} where irrefutable pattern is expected. This should never happen!", pattern.value)
|
||||||
|
@ -2837,6 +2841,13 @@ pub fn with_hole<'a>(
|
||||||
hole,
|
hole,
|
||||||
),
|
),
|
||||||
|
|
||||||
|
SingleQuote(character) => Stmt::Let(
|
||||||
|
assigned,
|
||||||
|
Expr::Literal(Literal::Int(character as _)),
|
||||||
|
Layout::Builtin(Builtin::Int32),
|
||||||
|
hole,
|
||||||
|
),
|
||||||
|
|
||||||
Num(var, num_str, num) => {
|
Num(var, num_str, num) => {
|
||||||
// first figure out what kind of number this is
|
// first figure out what kind of number this is
|
||||||
match num_argument_to_int_or_float(env.subs, env.ptr_bytes, var, false) {
|
match num_argument_to_int_or_float(env.subs, env.ptr_bytes, var, false) {
|
||||||
|
@ -7025,6 +7036,7 @@ fn from_can_pattern_help<'a>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
StrLiteral(v) => Ok(Pattern::StrLiteral(v.clone())),
|
StrLiteral(v) => Ok(Pattern::StrLiteral(v.clone())),
|
||||||
|
SingleQuote(c) => Ok(Pattern::IntLiteral(*c as _, IntPrecision::I32)),
|
||||||
Shadowed(region, ident) => Err(RuntimeError::Shadowing {
|
Shadowed(region, ident) => Err(RuntimeError::Shadowing {
|
||||||
original_region: *region,
|
original_region: *region,
|
||||||
shadow: ident.clone(),
|
shadow: ident.clone(),
|
||||||
|
|
|
@ -92,7 +92,7 @@ pub enum Expr<'a> {
|
||||||
/// e.g. `.foo`
|
/// e.g. `.foo`
|
||||||
AccessorFunction(&'a str),
|
AccessorFunction(&'a str),
|
||||||
/// eg 'b'
|
/// eg 'b'
|
||||||
SingleQuote(char),
|
SingleQuote(&'a str),
|
||||||
|
|
||||||
// Collection Literals
|
// Collection Literals
|
||||||
List {
|
List {
|
||||||
|
@ -360,7 +360,7 @@ pub enum Pattern<'a> {
|
||||||
FloatLiteral(&'a str),
|
FloatLiteral(&'a str),
|
||||||
StrLiteral(StrLiteral<'a>),
|
StrLiteral(StrLiteral<'a>),
|
||||||
Underscore(&'a str),
|
Underscore(&'a str),
|
||||||
SingleQuote(char),
|
SingleQuote(&'a str),
|
||||||
|
|
||||||
// Space
|
// Space
|
||||||
SpaceBefore(&'a Pattern<'a>, &'a [CommentOrNewline<'a>]),
|
SpaceBefore(&'a Pattern<'a>, &'a [CommentOrNewline<'a>]),
|
||||||
|
|
|
@ -1492,6 +1492,7 @@ fn expr_to_pattern_help<'a>(arena: &'a Bump, expr: &Expr<'a>) -> Result<Pattern<
|
||||||
| Expr::UnaryOp(_, _) => Err(()),
|
| Expr::UnaryOp(_, _) => Err(()),
|
||||||
|
|
||||||
Expr::Str(string) => Ok(Pattern::StrLiteral(*string)),
|
Expr::Str(string) => Ok(Pattern::StrLiteral(*string)),
|
||||||
|
Expr::SingleQuote(string) => Ok(Pattern::SingleQuote(*string)),
|
||||||
Expr::MalformedIdent(string, _problem) => Ok(Pattern::Malformed(string)),
|
Expr::MalformedIdent(string, _problem) => Ok(Pattern::Malformed(string)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
use std::convert::TryInto;
|
|
||||||
|
|
||||||
use crate::ast::{EscapedChar, StrLiteral, StrSegment};
|
use crate::ast::{EscapedChar, StrLiteral, StrSegment};
|
||||||
use crate::expr;
|
use crate::expr;
|
||||||
use crate::parser::Progress::*;
|
use crate::parser::Progress::*;
|
||||||
|
@ -48,8 +46,8 @@ macro_rules! advance_state {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_single_quote<'a>() -> impl Parser<'a, char, EString<'a>> {
|
pub fn parse_single_quote<'a>() -> impl Parser<'a, &'a str, EString<'a>> {
|
||||||
move |_arena: &'a Bump, mut state: State<'a>| {
|
move |arena: &'a Bump, mut state: State<'a>| {
|
||||||
if state.bytes.starts_with(b"\'") {
|
if state.bytes.starts_with(b"\'") {
|
||||||
// we will be parsing a single-quote-string
|
// we will be parsing a single-quote-string
|
||||||
} else {
|
} else {
|
||||||
|
@ -73,9 +71,11 @@ pub fn parse_single_quote<'a>() -> impl Parser<'a, char, EString<'a>> {
|
||||||
state = advance_state!(state, 1)?;
|
state = advance_state!(state, 1)?;
|
||||||
// since we checked the current char between the single quotes we
|
// since we checked the current char between the single quotes we
|
||||||
// know they are valid UTF-8, allowing us to use 'from_u32_unchecked'
|
// know they are valid UTF-8, allowing us to use 'from_u32_unchecked'
|
||||||
|
let test = unsafe { char::from_u32_unchecked(ch as u32) };
|
||||||
|
|
||||||
return Ok((
|
return Ok((
|
||||||
MadeProgress,
|
MadeProgress,
|
||||||
unsafe { char::from_u32_unchecked(ch as u32) },
|
&*arena.alloc_str(&test.to_string()),
|
||||||
state,
|
state,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -112,6 +112,8 @@ pub fn parse_single_quote<'a>() -> impl Parser<'a, char, EString<'a>> {
|
||||||
let mut bytes = state.bytes.iter();
|
let mut bytes = state.bytes.iter();
|
||||||
let mut end_index = 1;
|
let mut end_index = 1;
|
||||||
|
|
||||||
|
// Copy paste problem in mono
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
match bytes.next() {
|
match bytes.next() {
|
||||||
Some(b'\'') => {
|
Some(b'\'') => {
|
||||||
|
@ -138,19 +140,14 @@ pub fn parse_single_quote<'a>() -> impl Parser<'a, char, EString<'a>> {
|
||||||
|
|
||||||
// happy case -> we have some bytes that will fit into a u32
|
// happy case -> we have some bytes that will fit into a u32
|
||||||
// ending up w/ a slice of bytes that we want to convert into an integer
|
// ending up w/ a slice of bytes that we want to convert into an integer
|
||||||
let bytes_array: [u8; 4] = match state.bytes[1..end_index].try_into() {
|
let raw_bytes = &state.bytes[0..end_index - 1];
|
||||||
Ok(bytes) => bytes,
|
|
||||||
Err(_) => {
|
|
||||||
return Err((NoProgress, EString::Open(state.line, state.column), state));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
state = advance_state!(state, end_index)?;
|
state = advance_state!(state, end_index)?;
|
||||||
match char::from_u32(u32::from_ne_bytes(bytes_array)) {
|
match std::str::from_utf8(raw_bytes) {
|
||||||
Some(ch) => {
|
Ok(string) => {
|
||||||
return Ok((MadeProgress, ch, state));
|
return Ok((MadeProgress, string, state));
|
||||||
}
|
}
|
||||||
None => {
|
Err(_) => {
|
||||||
// invalid UTF-8
|
// invalid UTF-8
|
||||||
return Err((
|
return Err((
|
||||||
NoProgress,
|
NoProgress,
|
||||||
|
|
|
@ -421,6 +421,12 @@ mod test_parse {
|
||||||
assert_parses_to(num.to_string().as_str(), Float(num.to_string().as_str()));
|
assert_parses_to(num.to_string().as_str(), Float(num.to_string().as_str()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SINGLE QUOTE LITERAL
|
||||||
|
#[test]
|
||||||
|
fn single_quote() {
|
||||||
|
assert_parses_to("'b'", Expr::SingleQuote("b"));
|
||||||
|
}
|
||||||
|
|
||||||
// RECORD LITERALS
|
// RECORD LITERALS
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -172,6 +172,11 @@ pub enum RuntimeError {
|
||||||
VoidValue,
|
VoidValue,
|
||||||
|
|
||||||
ExposedButNotDefined(Symbol),
|
ExposedButNotDefined(Symbol),
|
||||||
|
|
||||||
|
/// where ''
|
||||||
|
EmptySingleQuote(Region),
|
||||||
|
/// where 'aa'
|
||||||
|
MulitpleCharsInSingleQuote(Region),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
|
@ -182,4 +187,6 @@ pub enum MalformedPatternProblem {
|
||||||
Unknown,
|
Unknown,
|
||||||
QualifiedIdentifier,
|
QualifiedIdentifier,
|
||||||
BadIdent(roc_parse::ident::BadIdent),
|
BadIdent(roc_parse::ident::BadIdent),
|
||||||
|
EmptySingleQuote,
|
||||||
|
MulitpleCharsInSingleQuote,
|
||||||
}
|
}
|
||||||
|
|
|
@ -843,13 +843,17 @@ fn pretty_runtime_error<'b>(
|
||||||
}
|
}
|
||||||
Unknown => " ",
|
Unknown => " ",
|
||||||
QualifiedIdentifier => " qualified ",
|
QualifiedIdentifier => " qualified ",
|
||||||
|
EmptySingleQuote => " empty character literal ",
|
||||||
|
MulitpleCharsInSingleQuote => " overfull literal ",
|
||||||
};
|
};
|
||||||
|
|
||||||
let tip = match problem {
|
let tip = match problem {
|
||||||
MalformedInt | MalformedFloat | MalformedBase(_) => alloc
|
MalformedInt | MalformedFloat | MalformedBase(_) => alloc
|
||||||
.tip()
|
.tip()
|
||||||
.append(alloc.reflow("Learn more about number literals at TODO")),
|
.append(alloc.reflow("Learn more about number literals at TODO")),
|
||||||
Unknown | BadIdent(_) => alloc.nil(),
|
EmptySingleQuote | MulitpleCharsInSingleQuote | Unknown | BadIdent(_) => {
|
||||||
|
alloc.nil()
|
||||||
|
}
|
||||||
QualifiedIdentifier => alloc.tip().append(
|
QualifiedIdentifier => alloc.tip().append(
|
||||||
alloc.reflow("In patterns, only private and global tags can be qualified"),
|
alloc.reflow("In patterns, only private and global tags can be qualified"),
|
||||||
),
|
),
|
||||||
|
@ -1122,6 +1126,37 @@ fn pretty_runtime_error<'b>(
|
||||||
|
|
||||||
title = MISSING_DEFINITION;
|
title = MISSING_DEFINITION;
|
||||||
}
|
}
|
||||||
|
RuntimeError::EmptySingleQuote(region) => {
|
||||||
|
let tip = alloc
|
||||||
|
.tip()
|
||||||
|
.append(alloc.reflow("Learn more about character literals at TODO"));
|
||||||
|
|
||||||
|
doc = alloc.stack(vec![
|
||||||
|
alloc.concat(vec![alloc.reflow("This character literal is empty.")]),
|
||||||
|
alloc.region(region),
|
||||||
|
tip,
|
||||||
|
]);
|
||||||
|
|
||||||
|
title = SYNTAX_PROBLEM;
|
||||||
|
}
|
||||||
|
RuntimeError::MulitpleCharsInSingleQuote(region) => {
|
||||||
|
let tip = alloc
|
||||||
|
.tip()
|
||||||
|
.append(alloc.reflow("Learn more about character literals at TODO"));
|
||||||
|
|
||||||
|
doc = alloc.stack(vec![
|
||||||
|
alloc.concat(vec![
|
||||||
|
alloc.reflow("This character literal contains more than one code point.")
|
||||||
|
]),
|
||||||
|
alloc.region(region),
|
||||||
|
alloc.concat(vec![
|
||||||
|
alloc.reflow("Character literals can only contain one code point.")
|
||||||
|
]),
|
||||||
|
tip,
|
||||||
|
]);
|
||||||
|
|
||||||
|
title = SYNTAX_PROBLEM;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
(doc, title)
|
(doc, title)
|
||||||
|
|
|
@ -981,6 +981,7 @@ fn add_category<'b>(
|
||||||
this_is,
|
this_is,
|
||||||
alloc.text(" a value in a string interpolation, which was of type:"),
|
alloc.text(" a value in a string interpolation, which was of type:"),
|
||||||
]),
|
]),
|
||||||
|
Character => alloc.concat(vec![this_is, alloc.text(" a character of type:")]),
|
||||||
|
|
||||||
Lambda => alloc.concat(vec![this_is, alloc.text(" an anonymous function of type:")]),
|
Lambda => alloc.concat(vec![this_is, alloc.text(" an anonymous function of type:")]),
|
||||||
|
|
||||||
|
@ -1262,7 +1263,8 @@ fn add_pattern_category<'b>(
|
||||||
Str => alloc.reflow(" strings:"),
|
Str => alloc.reflow(" strings:"),
|
||||||
Num => alloc.reflow(" numbers:"),
|
Num => alloc.reflow(" numbers:"),
|
||||||
Int => alloc.reflow(" integers:"),
|
Int => alloc.reflow(" integers:"),
|
||||||
Float => alloc.reflow(" floats"),
|
Float => alloc.reflow(" floats:"),
|
||||||
|
Character => alloc.reflow(" characters:"),
|
||||||
};
|
};
|
||||||
|
|
||||||
alloc.concat(vec![i_am_trying_to_match, rest])
|
alloc.concat(vec![i_am_trying_to_match, rest])
|
||||||
|
|
|
@ -1159,6 +1159,7 @@ pub enum Category {
|
||||||
Num,
|
Num,
|
||||||
List,
|
List,
|
||||||
Str,
|
Str,
|
||||||
|
Character,
|
||||||
|
|
||||||
// records
|
// records
|
||||||
Record,
|
Record,
|
||||||
|
@ -1180,6 +1181,7 @@ pub enum PatternCategory {
|
||||||
Num,
|
Num,
|
||||||
Int,
|
Int,
|
||||||
Float,
|
Float,
|
||||||
|
Character,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
|
|
|
@ -1285,6 +1285,15 @@ pub fn constrain_pattern<'a>(
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CharacterLiteral(_) => {
|
||||||
|
state.constraints.push(Constraint::Pattern(
|
||||||
|
region,
|
||||||
|
PatternCategory::Character,
|
||||||
|
num_unsigned32(env.pool),
|
||||||
|
expected,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
RecordDestructure {
|
RecordDestructure {
|
||||||
whole_var,
|
whole_var,
|
||||||
ext_var,
|
ext_var,
|
||||||
|
@ -1696,6 +1705,27 @@ fn _num_signed64(pool: &mut Pool) -> Type2 {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn num_unsigned32(pool: &mut Pool) -> Type2 {
|
||||||
|
let alias_content = Type2::TagUnion(
|
||||||
|
PoolVec::new(
|
||||||
|
vec![(
|
||||||
|
TagName::Private(Symbol::NUM_UNSIGNED32),
|
||||||
|
PoolVec::empty(pool),
|
||||||
|
)]
|
||||||
|
.into_iter(),
|
||||||
|
pool,
|
||||||
|
),
|
||||||
|
pool.add(Type2::EmptyTagUnion),
|
||||||
|
);
|
||||||
|
|
||||||
|
Type2::Alias(
|
||||||
|
Symbol::NUM_UNSIGNED32,
|
||||||
|
PoolVec::empty(pool),
|
||||||
|
pool.add(alias_content),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn _num_integer(pool: &mut Pool, range: TypeId) -> Type2 {
|
fn _num_integer(pool: &mut Pool, range: TypeId) -> Type2 {
|
||||||
let range_type = pool.get(range);
|
let range_type = pool.get(range);
|
||||||
|
|
|
@ -28,6 +28,7 @@ pub enum Pattern2 {
|
||||||
IntLiteral(IntVal), // 16B
|
IntLiteral(IntVal), // 16B
|
||||||
FloatLiteral(FloatVal), // 16B
|
FloatLiteral(FloatVal), // 16B
|
||||||
StrLiteral(PoolStr), // 8B
|
StrLiteral(PoolStr), // 8B
|
||||||
|
CharacterLiteral(char), // 4B
|
||||||
Underscore, // 0B
|
Underscore, // 0B
|
||||||
GlobalTag {
|
GlobalTag {
|
||||||
whole_var: Variable, // 4B
|
whole_var: Variable, // 4B
|
||||||
|
@ -217,6 +218,26 @@ pub fn to_pattern2<'a>(
|
||||||
ptype => unsupported_pattern(env, ptype, region),
|
ptype => unsupported_pattern(env, ptype, region),
|
||||||
},
|
},
|
||||||
|
|
||||||
|
SingleQuote(string) => match pattern_type {
|
||||||
|
WhenBranch => {
|
||||||
|
let mut it = string.chars().peekable();
|
||||||
|
if let Some(char) = it.next() {
|
||||||
|
if it.peek().is_none() {
|
||||||
|
Pattern2::CharacterLiteral(char)
|
||||||
|
} else {
|
||||||
|
// multiple chars is found
|
||||||
|
let problem = MalformedPatternProblem::MulitpleCharsInSingleQuote;
|
||||||
|
malformed_pattern(env, problem, region)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// no characters found
|
||||||
|
let problem = MalformedPatternProblem::EmptySingleQuote;
|
||||||
|
malformed_pattern(env, problem, region)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ptype => unsupported_pattern(env, ptype, region),
|
||||||
|
},
|
||||||
|
|
||||||
GlobalTag(name) => {
|
GlobalTag(name) => {
|
||||||
// Canonicalize the tag's name.
|
// Canonicalize the tag's name.
|
||||||
Pattern2::GlobalTag {
|
Pattern2::GlobalTag {
|
||||||
|
@ -472,6 +493,7 @@ pub fn symbols_from_pattern(pool: &Pool, initial: &Pattern2) -> Vec<Symbol> {
|
||||||
| IntLiteral(_)
|
| IntLiteral(_)
|
||||||
| FloatLiteral(_)
|
| FloatLiteral(_)
|
||||||
| StrLiteral(_)
|
| StrLiteral(_)
|
||||||
|
| CharacterLiteral(_)
|
||||||
| Underscore
|
| Underscore
|
||||||
| MalformedPattern(_, _)
|
| MalformedPattern(_, _)
|
||||||
| Shadowed { .. }
|
| Shadowed { .. }
|
||||||
|
@ -521,6 +543,7 @@ pub fn symbols_and_variables_from_pattern(
|
||||||
| IntLiteral(_)
|
| IntLiteral(_)
|
||||||
| FloatLiteral(_)
|
| FloatLiteral(_)
|
||||||
| StrLiteral(_)
|
| StrLiteral(_)
|
||||||
|
| CharacterLiteral(_)
|
||||||
| Underscore
|
| Underscore
|
||||||
| MalformedPattern(_, _)
|
| MalformedPattern(_, _)
|
||||||
| Shadowed { .. }
|
| Shadowed { .. }
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue