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

feat(compiler)!: Refactor enum constructors #1211

Merged
merged 3 commits into from
Jan 10, 2023
Merged

Conversation

ibdafna
Copy link
Contributor

@ibdafna ibdafna commented May 9, 2022

Signed-off-by: Itay Dafna i.b.dafna@gmail.com

Closes #1021
Closes #1502

This PR changes how enum variant constructors work in Grain, making individual variants handled separately from functions. This change allows us to build variant types into the language rather than just the standard library, which will allow us to provide better error messages, allow for disambiguation of variants from multiple types with the same name, and open up opportunities for features like optional arguments. The tradeoff is that the names of variant constructors are no longer functions, but this feature was only seldom used (only appearing once in Grain's entire standard library). Wrapper functions can be used to provide the same functionality.

Before:

List.map(Some, [1, 2, 3])

After:

List.map(x => Some(x), [1, 2, 3])

@phated phated marked this pull request as draft May 14, 2022 18:37
@ospencer ospencer force-pushed the ibd_comp branch 4 times, most recently from 149f1df to 2c0dd5b Compare December 24, 2022 01:39
@ospencer ospencer changed the title [WIP] Implement PExpConstruct/TExpConstruct feat(compiler)!: Refactor enum constructors Dec 24, 2022
Comment on lines -73 to -81
let assertion_error_ident = Ident.create_persistent("AssertionError");
let assertion_error_closure_ident =
Ident.create_persistent("GRAIN$EXPORT$AssertionError");
let index_out_of_bounds_ident =
Ident.create_persistent("GRAIN$EXPORT$IndexOutOfBounds");
let index_non_integer_ident =
Ident.create_persistent("GRAIN$EXPORT$IndexNonInteger");
let match_failure_ident =
Ident.create_persistent("GRAIN$EXPORT$MatchFailure");
Copy link
Member

Choose a reason for hiding this comment

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

There are no identifiers or closures for variants anymore.

@@ -90,6 +81,7 @@ let console_mod = "console";
let tracepoint_ident = Ident.create_persistent("tracepoint");

let grain_main = "_gmain";
let grain_type_metadata = "_gtype_metadata";
Copy link
Member

Choose a reason for hiding this comment

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

Type metadata is now explicitly provided by a special type metadata function in the module. This allows modules to choose to define only types but still have type information loaded.

| Runtime_errors.AssertionError => (
assertion_error_closure_ident,
Some(get_wasm_imported_name(exception_mod, assertion_error_ident)),
/** Heap allocations. */
Copy link
Member

Choose a reason for hiding this comment

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

None of this has changed, it's just moved higher so we can do allocations for exceptions (which was previously just calling a function).

@@ -2484,6 +2388,9 @@ let compile_prim1 = (wasm_mod, env, p1, arg, loc): Expression.t => {
Expression.Unreachable.make(wasm_mod),
],
)
| Assert => failwith("Unreachable case; should never get here: Assert")
| BuiltinId =>
Copy link
Member

Choose a reason for hiding this comment

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

This BuiltinId will be how print will be able to know about built-in types.


let grain_main = "_gmain";
let grain_start = "_start";
let hard_dependencies: Hashtbl.t(string, unit) = Hashtbl.create(10);
Copy link
Member

Choose a reason for hiding this comment

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

Hard dependencies are ones that require code to be loaded from the module, whereas soft dependencies just require type information be loaded.

@@ -301,17 +285,25 @@ let rec globalize_names = (~function_names, ~global_names, ~label_names, expr) =
};

let table_offset = ref(0);
let module_id = ref(0);
let module_id = ref(Comp_utils.encoded_int32(0));
Copy link
Member

Choose a reason for hiding this comment

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

This was a really sad bug that took away a week of my life.

Copy link
Member

Choose a reason for hiding this comment

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

Can you explain it a bit?

Copy link
Member

Choose a reason for hiding this comment

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

As defined in the data representations doc, module IDs are always tagged and thus GC-able. Except during linking, the linker assigned non-tagged IDS 🤦‍♂️

This wasn't a problem before because the IDs were treated by the runtime as untagged, but some updates while working on this PR caused them to be treated as regular values and made the bug show up.

let dependencies =
Topo.fold((dep, acc) => [dep, ...acc], dependency_graph, []);

let dependencies = Module_resolution.get_dependencies();
Copy link
Member

Choose a reason for hiding this comment

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

This gives us the full dependency graph, which includes files that might not contain necessary code.

@@ -21,12 +21,11 @@ open Path;
open Types;
open Btype;

let builtin_idents = ref([]);
let builtin_decls = ref([]);
let builtin_idents = Hashtbl.create(64);
Copy link
Member

Choose a reason for hiding this comment

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

The hash lets us look these up quickly versus having to traverse the list.

@@ -46,42 +46,33 @@ enum StringList {
primitive _RUNTIME_TYPE_METADATA_PTR: WasmI32 = "@heap.type_metadata"

@unsafe
let findTypeMetadata = (moduleId, typeId) => {
let findTypeMetadata = typeId => {
Copy link
Member

Choose a reason for hiding this comment

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

This function is now quite a bit less efficient since it traverses all type information. It should be converted to something faster like a binary tree or a hash, though it's tricky to implement because the metadata itself lives in runtime land where arbitrary allocations are not available. Regardless, I felt that optimization didn't need to be included in this PR and could come separately.

@ospencer ospencer marked this pull request as ready for review December 24, 2022 02:19
Copy link
Member

@phated phated left a comment

Choose a reason for hiding this comment

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

Thanks for the comments inline, they helped a ton! I had one question about the parser (and I'll probably spend a little more time looking at snapshots).

compiler/src/parsing/parser.mly Show resolved Hide resolved
Copy link
Member

@marcusroberts marcusroberts left a comment

Choose a reason for hiding this comment

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

I had a good read through this - nice to see list constructors cleaned up as well and looks like some nice changes as well as a deep bug fixed. Really nice work!

Hopefully with the new code owner rules I can approve this releasing it as a lot of the changes are beyond my current comprehension but I liked the changes I did understand and the code changes read well.

@ospencer
Copy link
Member

ospencer commented Jan 1, 2023

Note to self: need to update store_type and store_extension in env.re to stop adding constructors as binding names to the environment

ibdafna and others added 2 commits January 9, 2023 08:50
Signed-off-by: Itay Dafna <i.b.dafna@gmail.com>
@ospencer
Copy link
Member

ospencer commented Jan 9, 2023

store_type and store_extension updated.

Copy link
Member

@phated phated left a comment

Choose a reason for hiding this comment

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

Love this!

@ospencer ospencer merged commit 8d465b7 into grain-lang:main Jan 10, 2023
marcusroberts pushed a commit that referenced this pull request Jan 14, 2023
Co-authored-by: Oscar Spencer <oscar@grain-lang.org>
Closes #1021
Closes #1502
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
No open projects
Status: Done
5 participants