Skip to content

[spectec] IL AST elaboration#2127

Draft
zilinc wants to merge 6 commits intoWebAssembly:mainfrom
zilinc:il-elab
Draft

[spectec] IL AST elaboration#2127
zilinc wants to merge 6 commits intoWebAssembly:mainfrom
zilinc:il-elab

Conversation

@zilinc
Copy link
Copy Markdown
Contributor

@zilinc zilinc commented Mar 29, 2026

No description provided.

{e1' with note = e.note}
| _ -> SubE (e1', t1', t2') $> e
)
| AnnE (e1, _) -> reduce_exp env e1
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is not enough, unfortunately. We now need to allow AnnE in all beta rules. Or reduce it away in places where it's redundant (e.g., around all intro forms that are already inferable, such as literals).

let as_list_typ phrase env dir t at : typ =
match expand_typ env t with
| IterT (t1, (List | List1 | ListN _)) -> t1
| IterT (t1, (List | List1 | ListN _)) -> t1 (* QUEST(zilinc): Is it possible to be List1 or ListN in a type? *)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Not currently, this was just meant to be future-proof.

| _ -> error e.at "invalid case projection";
)
| OptE _ -> error e.at "cannot infer type of option"
| OptE (Some e1) -> let t1 = infer_exp env e1 in IterT (t1, Opt) $ e1.at
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I have a tendency to leave this as is in favour of treating all OptE's uniformly.

else
error e.at "cannot infer type of concatenation"
| CaseE _ -> e.note (* error e.at "cannot infer type of case constructor" *)
| CaseE _ -> error e.at "cannot infer type of case constructor"
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Yeah, you'll have to leave this alone until I have updated the elaborator.

equiv_typ env t2 t e.at;
sub_typ env t1 t2 e.at

| AnnE (e1, t1) -> valid_typ env t1; valid_exp ~side env e1 t1
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
| AnnE (e1, t1) -> valid_typ env t1; valid_exp ~side env e1 t1
| AnnE (e1, t1)
valid_exp ~side env e1 t1;
valid_typ env t1

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.

Would you please elaborate the reason behind it?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Just for visual uniformity with the other cases.


let map_note f {it; at; note} = {it; at; note = f note}

let erase_note (x: ('a, 'b) note_phrase) = map_note (Fun.const ()) x
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Is this used anywhere?

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.

No, I'll remove. I initially wanted to erase all the notes in the AST, but later realised that the datatypes do not tie the knot, so it wouldn't work.

@@ -1 +1,2 @@
val valid : Ast.script -> unit (* raises Error.Error *)
val elab : Ast.script -> Ast.script
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

FWIW, to extend validation with a note annotation mode, I'd rather make note a mutable field. Then it affects just a couple of lines of code instead of having to turn the entire validator into a mapping function.

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.

With a mutable note field, I would worry very much about the correctness of the code, as there's no type-level guarantee that I've changed all the note fields throughout the AST. There're only a couple of places that use the valid function in the codebase, so I hope it won't require too many changes.So unless you feel very strong about it, I prefer to keep it this way.

Copy link
Copy Markdown
Member

@rossberg rossberg Mar 29, 2026

Choose a reason for hiding this comment

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

I don't think it makes a difference for correctness. In either case, there is a single point where the note is updated. So it is equally easy/hard to screw that up.

OTOH, with mutation the code remains much simpler, plus it preserves its primary structure as a validator. So I think it's preferable overall, the impurity notwithstanding.

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