Merge branch 'trunk' into unit-types

This commit is contained in:
Richard Feldman 2020-03-19 22:05:22 -04:00 committed by GitHub
commit b33af811d0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 156 additions and 53 deletions

View file

@ -285,40 +285,19 @@ pub fn build_expr<'a, B: Backend>(
Access { Access {
label, label,
field_layout, field_layout,
struct_layout: Layout::Struct(fields), struct_layout: Layout::Struct(sorted_fields),
record, record,
} => { } => {
let cfg = env.cfg; let cfg = env.cfg;
// Reconstruct the struct to determine the combined layout
// TODO get rid of clones
let mut reconstructed_struct_layout =
Vec::with_capacity_in(fields.len() + 1, env.arena);
for field in fields.iter() {
reconstructed_struct_layout.push(field.clone());
}
reconstructed_struct_layout.push((label.clone(), field_layout.clone()));
reconstructed_struct_layout.sort_by(|a, b| {
a.0.partial_cmp(&b.0)
.expect("TODO: failed to sort struct fields in crane access")
});
// Find the offset we are trying to access // Find the offset we are trying to access
let mut offset = 0; let mut offset = 0;
for (local_label, layout) in reconstructed_struct_layout.iter() { for (local_label, local_field_layout) in sorted_fields.iter() {
if local_label == label { if local_label == label {
break; break;
} }
let field_size = match layout { offset += local_field_layout.stack_size(ptr_bytes);
Layout::Builtin(Builtin::Int64) => std::mem::size_of::<i64>(),
_ => panic!(
"Missing struct field size in offset calculation for struct access for {:?}",
layout
),
};
offset += field_size;
} }
let offset = i32::try_from(offset) let offset = i32::try_from(offset)
@ -326,10 +305,11 @@ pub fn build_expr<'a, B: Backend>(
let mem_flags = MemFlags::new(); let mem_flags = MemFlags::new();
let record = build_expr(env, scope, module, builder, record, procs); let record = build_expr(env, scope, module, builder, record, procs);
let field_type = type_from_layout(cfg, field_layout);
builder builder
.ins() .ins()
.load(cfg.pointer_type(), mem_flags, record, Offset32::new(offset)) .load(field_type, mem_flags, record, Offset32::new(offset))
} }
AccessAtIndex { AccessAtIndex {
index, index,

View file

@ -496,26 +496,14 @@ pub fn build_expr<'a, 'ctx, 'env>(
} }
Access { Access {
label, label,
field_layout, struct_layout: Layout::Struct(sorted_fields),
struct_layout: Layout::Struct(fields),
record, record,
..
} => { } => {
let builder = env.builder; let builder = env.builder;
// Reconstruct struct layout
let mut reconstructed_struct_layout =
Vec::with_capacity_in(fields.len() + 1, env.arena);
for field in fields.iter() {
reconstructed_struct_layout.push(field.clone());
}
reconstructed_struct_layout.push((label.clone(), field_layout.clone()));
reconstructed_struct_layout.sort_by(|a, b| {
a.0.partial_cmp(&b.0)
.expect("TODO: failed to sort struct fields in crane access")
});
// Get index // Get index
let index = reconstructed_struct_layout let index = sorted_fields
.iter() .iter()
.position(|(local_label, _)| local_label == label) .position(|(local_label, _)| local_label == label)
.unwrap() as u32; // TODO .unwrap() as u32; // TODO

View file

@ -1618,4 +1618,43 @@ mod test_gen {
i64 i64
); );
} }
#[test]
fn f64_record() {
assert_evals_to!(
indoc!(
r#"
rec = { y: 17.2, x: 15.1, z: 19.3 }
rec.x
"#
),
15.1,
f64
);
assert_evals_to!(
indoc!(
r#"
rec = { y: 17.2, x: 15.1, z: 19.3 }
rec.y
"#
),
17.2,
f64
);
assert_evals_to!(
indoc!(
r#"
rec = { y: 17.2, x: 15.1, z: 19.3 }
rec.z
"#
),
19.3,
f64
);
}
} }

View file

@ -11,6 +11,32 @@ pub struct Report {
pub text: ReportText, pub text: ReportText,
} }
pub struct Palette {
pub primary: Color,
pub error: Color,
}
pub enum Color {
White,
Red,
}
pub const DEFAULT_PALETTE: Palette = Palette {
primary: Color::White,
error: Color::Red,
};
impl Color {
pub fn render(self, str: &str) -> String {
use Color::*;
match self {
Red => red(str),
White => white(str),
}
}
}
pub fn can_problem(filename: PathBuf, problem: Problem) -> Report { pub fn can_problem(filename: PathBuf, problem: Problem) -> Report {
let mut texts = Vec::new(); let mut texts = Vec::new();
@ -77,6 +103,28 @@ fn newline() -> ReportText {
plain_text("\n") plain_text("\n")
} }
fn red(str: &str) -> String {
let mut buf = String::new();
buf.push_str("\u{001b}[31m");
buf.push_str(str);
buf.push_str("\u{001b}[0m");
buf
}
fn white(str: &str) -> String {
let mut buf = String::new();
buf.push_str("\u{001b}[31m");
buf.push_str(str);
buf.push_str(RESET);
buf
}
const RESET: &str = "\u{001b}[0m";
impl ReportText { impl ReportText {
/// Render to CI console output, where no colors are available. /// Render to CI console output, where no colors are available.
pub fn render_ci( pub fn render_ci(
@ -116,12 +164,12 @@ impl ReportText {
Region(region) => { Region(region) => {
for i in region.start_line..=region.end_line { for i in region.start_line..=region.end_line {
buf.push_str(i.to_string().as_str()); buf.push_str(i.to_string().as_str());
buf.push_str(" |"); buf.push_str(" ");
let line = src_lines[i as usize]; let line = src_lines[i as usize];
if !line.is_empty() { if !line.is_empty() {
buf.push(' '); buf.push_str(" ");
buf.push_str(src_lines[i as usize]); buf.push_str(src_lines[i as usize]);
} }
@ -144,13 +192,21 @@ impl ReportText {
/// Render to a color terminal using ANSI escape sequences /// Render to a color terminal using ANSI escape sequences
pub fn render_color_terminal( pub fn render_color_terminal(
&self, &self,
_buf: &mut String, buf: &mut String,
_subs: &mut Subs, _subs: &mut Subs,
_home: ModuleId, _home: ModuleId,
_src_lines: &[&str], _src_lines: &[&str],
_interns: &Interns, _interns: &Interns,
palette: Palette,
) { ) {
// TODO do the same stuff as render_ci, but with colors via ANSI terminal escape codes! use ReportText::*;
// Examples of how to do this are in the source code of https://github.com/rtfeldman/console-print
match self {
Plain(string) => {
buf.push_str(&palette.primary.render(string));
}
_ => panic!("TODO implement more ReportTexts in render color terminal"),
}
} }
} }

View file

@ -11,7 +11,7 @@ mod helpers;
mod test_report { mod test_report {
use crate::helpers::test_home; use crate::helpers::test_home;
use roc_module::symbol::{Interns, ModuleId}; use roc_module::symbol::{Interns, ModuleId};
use roc_reporting::report::{can_problem, plain_text, Report, ReportText}; use roc_reporting::report::{can_problem, plain_text, Report, ReportText, DEFAULT_PALETTE};
use roc_types::pretty_print::name_all_type_vars; use roc_types::pretty_print::name_all_type_vars;
use roc_types::subs::Subs; use roc_types::subs::Subs;
use roc_types::types; use roc_types::types;
@ -82,6 +82,38 @@ mod test_report {
assert_eq!(buf, expected_rendering); assert_eq!(buf, expected_rendering);
} }
fn report_renders_in_color_from_src(src: &str, report: Report, expected_rendering: &str) {
let (_type_problems, _can_problems, mut subs, home, interns) = infer_expr_help(src);
let mut buf: String = String::new();
let src_lines: Vec<&str> = src.split('\n').collect();
report.text.render_color_terminal(
&mut buf,
&mut subs,
home,
&src_lines,
&interns,
DEFAULT_PALETTE,
);
assert_eq!(buf, expected_rendering);
}
fn report_renders_in_color(report: Report, expected_rendering: &str) {
report_renders_in_color_from_src(
indoc!(
r#"
x = 1
y = 2
x
"#
),
report,
expected_rendering,
)
}
fn report_renders_as(report: Report, expected_rendering: &str) { fn report_renders_as(report: Report, expected_rendering: &str) {
report_renders_as_from_src( report_renders_as_from_src(
indoc!( indoc!(
@ -204,13 +236,21 @@ mod test_report {
r#" r#"
y is not used anywhere in your code. y is not used anywhere in your code.
1 | y = 2 1 y = 2
If you didn't intend on using y then remove it so future readers of your code don't wonder why it is there."# If you didn't intend on using y then remove it so future readers of your code don't wonder why it is there."#
) )
); );
} }
#[test]
fn report_in_color() {
report_renders_in_color(
to_simple_report(plain_text("y")),
"\u{001b}[31my\u{001b}[0m",
);
}
#[test] #[test]
fn report_region() { fn report_region() {
report_renders_as_from_src( report_renders_as_from_src(
@ -231,9 +271,9 @@ mod test_report {
})), })),
indoc!( indoc!(
r#" r#"
1 | y = 2 1 y = 2
2 | f = \a -> a + 4 2 f = \a -> a + 4
3 |"# 3 "#
), ),
); );
} }