mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-30 15:21:12 +00:00
Merge branch 'trunk' into unit-types
This commit is contained in:
commit
b33af811d0
5 changed files with 156 additions and 53 deletions
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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"),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 ┆"#
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue