Get things compiling

This commit is contained in:
Richard Feldman 2020-08-26 21:12:44 -04:00
parent 70bef827a7
commit f35e43768a
18 changed files with 541 additions and 253 deletions

View file

@ -14,7 +14,7 @@ use roc_module::ident::{Lowercase, TagName};
use roc_module::low_level::LowLevel;
use roc_module::operator::CalledVia;
use roc_module::symbol::Symbol;
use roc_parse::ast;
use roc_parse::ast::{self, StrLiteral, StrSegment};
use roc_parse::pattern::PatternType::*;
use roc_problem::can::{PrecedenceProblem, Problem, RuntimeError};
use roc_region::all::{Located, Region};
@ -55,8 +55,10 @@ pub enum Expr {
// Int and Float store a variable to generate better error messages
Int(Variable, i64),
Float(Variable, f64),
Str(Box<str>),
BlockStr(Box<str>),
Str {
interpolations: Vec<(Box<str>, Symbol)>,
suffix: Box<str>,
},
List {
list_var: Variable, // required for uniqueness of the list
elem_var: Variable,
@ -247,12 +249,7 @@ pub fn canonicalize_expr<'a>(
)
}
}
ast::Expr::Str(string) => (Str((*string).into()), Output::default()),
ast::Expr::BlockStr(lines) => {
let joined = lines.iter().copied().collect::<Vec<&str>>().join("\n");
(BlockStr(joined.into()), Output::default())
}
ast::Expr::Str(literal) => flatten_str_literal(env, scope, literal),
ast::Expr::List(loc_elems) => {
if loc_elems.is_empty() {
(
@ -1045,8 +1042,7 @@ pub fn inline_calls(var_store: &mut VarStore, scope: &mut Scope, expr: Expr) ->
other @ Num(_, _)
| other @ Int(_, _)
| other @ Float(_, _)
| other @ Str(_)
| other @ BlockStr(_)
| other @ Str { .. }
| other @ RuntimeError(_)
| other @ EmptyRecord
| other @ Accessor { .. }
@ -1323,3 +1319,78 @@ pub fn inline_calls(var_store: &mut VarStore, scope: &mut Scope, expr: Expr) ->
}
}
}
fn flatten_str_literal(
env: &mut Env<'_>,
scope: &mut Scope,
literal: &StrLiteral<'_>,
) -> (Expr, Output) {
use ast::StrLiteral::*;
match literal {
PlainLine(str_slice) => (
Expr::Str {
interpolations: Vec::new(),
suffix: (*str_slice).into(),
},
Output::default(),
),
LineWithEscapes(segments) => flatten_str_lines(env, scope, &[segments]),
Block(lines) => flatten_str_lines(env, scope, lines),
}
}
fn flatten_str_lines(
env: &mut Env<'_>,
scope: &mut Scope,
lines: &[&[StrSegment<'_>]],
) -> (Expr, Output) {
use StrSegment::*;
let mut buf = String::new();
let mut interpolations = Vec::new();
let mut output = Output::default();
for line in lines {
for segment in line.iter() {
match segment {
Plaintext(string) => {
buf.push_str(string);
}
Unicode(loc_digits) => {
todo!("parse unicode digits {:?}", loc_digits);
}
Interpolated {
module_name,
ident,
region,
} => {
let (expr, new_output) =
canonicalize_lookup(env, scope, module_name, ident, region.clone());
output.union(new_output);
match expr {
Expr::Var(symbol) => {
interpolations.push((buf.into(), symbol));
}
_ => {
todo!("TODO gracefully handle non-ident in string interpolation.");
}
}
buf = String::new();
}
EscapedChar(ch) => buf.push(*ch),
}
}
}
(
Expr::Str {
interpolations,
suffix: buf.into(),
},
output,
)
}

View file

@ -68,8 +68,6 @@ pub fn desugar_expr<'a>(arena: &'a Bump, loc_expr: &'a Located<Expr<'a>>) -> &'a
| Nested(NonBase10Int { .. })
| Str(_)
| Nested(Str(_))
| BlockStr(_)
| Nested(BlockStr(_))
| AccessorFunction(_)
| Nested(AccessorFunction(_))
| Var { .. }

View file

@ -4,7 +4,7 @@ use crate::num::{finish_parsing_base, finish_parsing_float, finish_parsing_int};
use crate::scope::Scope;
use roc_module::ident::{Ident, Lowercase, TagName};
use roc_module::symbol::Symbol;
use roc_parse::ast;
use roc_parse::ast::{self, StrLiteral, StrSegment};
use roc_parse::pattern::PatternType;
use roc_problem::can::{MalformedPatternProblem, Problem, RuntimeError};
use roc_region::all::{Located, Region};
@ -230,16 +230,8 @@ pub fn canonicalize_pattern<'a>(
ptype => unsupported_pattern(env, ptype, region),
},
StrLiteral(string) => match pattern_type {
WhenBranch => {
// TODO report whether string was malformed
Pattern::StrLiteral((*string).into())
}
ptype => unsupported_pattern(env, ptype, region),
},
BlockStrLiteral(_lines) => match pattern_type {
WhenBranch => todo!("TODO block string literal pattern"),
StrLiteral(literal) => match pattern_type {
WhenBranch => flatten_str_literal(literal),
ptype => unsupported_pattern(env, ptype, region),
},
@ -473,3 +465,38 @@ fn add_bindings_from_patterns(
| UnsupportedPattern(_) => (),
}
}
fn flatten_str_literal(literal: &StrLiteral<'_>) -> Pattern {
use ast::StrLiteral::*;
match literal {
PlainLine(str_slice) => Pattern::StrLiteral((*str_slice).into()),
LineWithEscapes(segments) => flatten_str_lines(&[segments]),
Block(lines) => flatten_str_lines(lines),
}
}
fn flatten_str_lines(lines: &[&[StrSegment<'_>]]) -> Pattern {
use StrSegment::*;
let mut buf = String::new();
for line in lines {
for segment in line.iter() {
match segment {
Plaintext(string) => {
buf.push_str(string);
}
Unicode(loc_digits) => {
todo!("parse unicode digits {:?}", loc_digits);
}
Interpolated { region, .. } => {
return Pattern::UnsupportedPattern(region.clone());
}
EscapedChar(ch) => buf.push(*ch),
}
}
}
Pattern::StrLiteral(buf.into())
}