Skip to content

Add open enums and enum methods with tests - #631

Open
eliotmoss wants to merge 7 commits into
titzer:masterfrom
eliotmoss:open_enums3
Open

Add open enums and enum methods with tests#631
eliotmoss wants to merge 7 commits into
titzer:masterfrom
eliotmoss:open_enums3

Conversation

@eliotmoss

Copy link
Copy Markdown
Contributor

This combines the open enums work into a single commit. There were few minor conflicts, which have been worked out. Passes all CI locally.

Comment thread aeneas/src/core/Eval.v3
return b == null;
}
CLASS_QUERY, VARIANT_QUERY => {
if (EnumType.?(tt)) {

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

From this it's clear to me that enums need to be desugared to variants earlier in a more general way. Claude has just smeared special cases from front to middle to backend. There shouldn't be any need to alter the evaluation of operators like this.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I'm willing to work on simplifying such things. I'm not 100% clear on the desugaring you're hoping for, though. I can see that enums are kind of like variants that have no variant fields. Of course enums have their own "fields", that are implemented as arrays indexed by tag. If the two are to be unified into a single whole, we need some place to hang both kinds of fields. Also while enum class structure mirrors variant class structure (in the case of no generic parameters), enums themselves are single values (or have unique single values associated with them) while variant cases are types (unless they have no fields, in which case they have the same "ambiguity" as enums). If you have a little more guidance I would be more confident revising code ...

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Ah, forgive me. It used to be that enums were immediately desugared to a single class declaration. At some point I split off the implementation entirely. If open enums were desugared into open variants instead (i.e. adding a class per enum case), then enum method dispatch would just be variant dispatch. Enum fields would still be implemented via field arrays and use VariantGetTag as the index. Unboxing will just eliminate the overhead of boxing enum values.

@eliotmoss eliotmoss Apr 2, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I get the idea but am foggy as to the particulars. Specifically I wonder about the field arrays, and maybe also enumsets. Is the desugaring proposed to happen in VstSsaGen, so that enums are mostly washed away once we have SSA, but the distinction is more visible in parsing (of course) and verification? This would make sense in that, once verified, enums could be mapped down to other structures (variants, field arrays) and marked to be unboxed (always). I'd have to get more deeply into it to see where issues might come up with enumsets, but again, suitable use of VariantGetTag would get the raw numeric values required. So, I could try to combine processing in verification (and maybe parts of parsing), but strive to eliminate separate processing once in SSA.

Comment thread aeneas/src/ir/Ir.v3 Outdated
}
def newIrClass(ctype: Type, superClass: IrClass, decl: VstCompound) -> IrClass {
var ic = IrBuilder.new(ctype, superClass).buildClass(decl);
var builder = IrBuilder.new(ctype, superClass);

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

I don't know why it feels the need to add the IR module to the builder now.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Apparently the field and this code are dead, so I'm removing it.

if (rc.isUnboxed()) {
// move flattened data type receiver to function sig
ftype = Function.prependParamTypes(rc.variantNorm.sub, ftype);
} else if (EnumType.?(rc.oldType)) {

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

If enums are properly desugared to variants, this will just fall out of the normal unboxing.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

isUnboxed means that normalization did the unboxing - but enums are implicitly already unboxed, so the test doesn't work for them. Unifying these more would be a bigger change. Is that how you would prefer to go?

rm.norm.flags |= IrFlag.M_OVERRIDE;
sm.norm.flags |= IrFlag.M_OVERRIDDEN;
}
// For enum methods, M_OVERRIDDEN must be transferred from original

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

I don't know why it thinks this.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Ultimately this appears necessary because enums don't use regular vtables so their overrides are processed differently. That don't use regular vtables because individual enum cases are not types and thus don't have a corresponding RaClass, etc. Again, is this deeper change one you would prefer to happen?

setMtable(l.head, rv);
}
}
def layoutEnumMtable(rv: RaVirtual, rm: RaMethod, rc: RaClass) {

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

More replications with special cases from our AI friends. As this is very tricky, we definitely don't want to do this again.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Part of the same effects from enum cases not having an RaClass and thus not lining up with the existing dispatch mechanisms.

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.

2 participants