Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Specialize exprs merge #7243

Open
wants to merge 42 commits into
base: main
Choose a base branch
from
Open

Specialize exprs merge #7243

wants to merge 42 commits into from

Conversation

agu-z
Copy link
Collaborator

@agu-z agu-z commented Nov 23, 2024

Merges the WIP new mono implementation so we can collaborate on it without drifting much from main. This shouldn't affect the behavior of the compiler.

@agu-z agu-z requested a review from rtfeldman November 23, 2024 05:27
Copy link
Collaborator

@smores56 smores56 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I looked through every file except for 5 or 6 200+ line files in specialize_types, this looks generally OK to me. I left some minor comments, you're good to ignore all of them for now since this is just a "get stuff in the main branch" PR.

The one thing that we may want to handle before merging is something @rtfeldman mentioned to me he wanted to do at some point: move stuff from the compiler folder to two folders, check for parsing, typechecking, mono, etc. and build for codegen-related crates. Before we have to move a bunch of files around in the future, I'd vote for moving specialize_types to check/specialize_types preemptively. Utility crates like test_compile can stay in the crates root folder.

pub fn as_str_plural(&self) -> &'static str {
match self {
AliasKind::Structural => "aliases",
AliasKind::Opaque => "opaques",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick: "aliases" is a sensible plural, but "opaques" seems weird. maybe we can do "opaque types" ?

.append(alloc.reflow(alias_kind.as_str()))
.append(alloc.reflow("es is only allowed if recursion happens behind a tagged union, at least one variant of which is not recursive."));
.append(alloc.reflow(alias_kind.as_str_plural()))
.append(alloc.reflow(" is only allowed if recursion happens behind a tagged union, at least one variant of which is not recursive."));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
.append(alloc.reflow(" is only allowed if recursion happens behind a tagged union, at least one variant of which is not recursive."));
.append(alloc.reflow(" are only allowed if recursion happens behind a tagged union, at least one variant of which is not recursive."));


#[allow(dead_code)]
#[derive(Default)]
pub struct ConstrainedExpr {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick: I think we should use past tense for output post-compiler phase, e.g. ConstrainedExprOut or in my opinion ConstrainedExpr, and present tense for before the phase, e.g. ConstrainExpr. The same would apply to the other compiler phases in this crate.

impl Default for ParseExpr {
fn default() -> Self {
Self {
arena: Bump::with_capacity(4096),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider moving this magic number to a constant. Why 4kb? Page size?

for line in input
.lines()
// Keep skipping until we hit a line that is neither empty nor all spaces.
.skip_while(|line| line.chars().all(|ch| ch == ' '))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we also ignore tabs?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think tabs aren't currently allowed by the parser

}
}

pub fn into_nonempty_slice(&self) -> Option<NonEmptySlice<T>> {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick: the into_ prefix in Rust usually takes ownership, I'd use as_ for non-consuming APIs.

@@ -7,6 +8,8 @@ use core::{

use crate::soa_slice::Slice;

pub type Id<T> = Index<T>;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick: This seems unnecessarily opaque

U128(u128),
F32(f32),
F64(f64),
Dec(f64),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To avoid floating point errors, should this be u64/u128?

/// [ A, .., B ] -> patterns = [A, B], rest = 1
/// [ A, B, .. ] -> patterns = [A, B], rest = 2
/// Optionally, the rest pattern can be named - e.g. `[ A, B, ..others ]`
opt_rest: Option<(u16, Option<IdentId>)>,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For future-proofing ourselves, it may be a good idea to use a list type here, e.g.

rests: Slice<(u16, Option<IdentId>)>

In case we end up supporting multiple in the future.

I understand this was copied from the other file, so NBD.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you think we need to future proof? Personally, I prefer types to model the current reality. We can change it later and just follow the compiler.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking of how easy it was to implement early returns (barring some minor bugs) in the mono code + codegen. Though I don't know if early returns were ever planned, the refcounting code Just Worked when I converted all early returns can::Exprs to Stmt::Ret naively.

With how complex Roc is at 300k LoC and growing, it's nice to make code work in a more generic way to avoid future contributors needing to figure out how the whole thing works before making changes.

That said, it's minor, and I can see why we'd rather them need to understand how things work before making changes. I'm totally fine if we don't go for the "future-proof" approach.

pub struct MonoModule {
mono_types: MonoTypes,
foreign_symbols: ForeignSymbols,
interned_strings: Vec<String>,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe add a TODO here to use a string interner?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants