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

Missing operators #189

Open
samuelgruetter opened this issue Jun 18, 2021 · 1 comment
Open

Missing operators #189

samuelgruetter opened this issue Jun 18, 2021 · 1 comment

Comments

@samuelgruetter
Copy link
Contributor

samuelgruetter commented Jun 18, 2021

Compared to C, bedrock2 is missing quite a few operators:

Unary operators:

  • unary minus -
  • logical not !
  • bitwise not ~

Binary operators:

  • unsigned division / and modulo %: unsigned variants are already in AST bopname, but no notations
  • unsigned <=, >, >=
  • not equal !=
  • lazy boolean &&/||

More missing operators that I'd postpone for later:

  • ternary conditional _ ? _ : _
  • signed <=, >, >=
  • signed division and modulo
  • pre and post ++ and -- (won't add because we don't want expressions with side-effects, maybe as a statement, though)
  • record access . and ->
  • array access []
  • compound assignment

This absence of operators can lead to more bugs, defeating the point of using bedrock2: When transcribing C to bedrock2, one has to work around missing operators, trying to emulate them with existing ones, and (based on experience), bugs can be introduced in this process. (Hopefully, they will be found during verification, but if one only verifies memory safety, they could be missed).

Most of these operators could be implemented as notations in terms of other operators:

Unary operators:

  • "- x" := (0 - x)
  • "! x" := (1 - (x != 0)), or "! x" := (x ? 0 : 1), or a primitive?
  • "~ x" := x ^ (-1)

Binary operators:

  • "/" := (expr.op divu)
  • "%" := (expr.op remu)
  • "x <= y" := (!(y < x))
  • "x > y" := (y < x)
  • "x >= y" := (!(x < y))
  • "x != y" := (! (x == y))
  • && and ||: as primitives, added to bopname, or maybe using a ternary if?

However, the above definitions are circular: ! is defined in terms of !=, and != is defined in terms of !.

A disadvantage of using notations is also that the C pretty printer won't print them (unless we add extra logic that detects the patterns), and that if the compiler wants to treat them specially, it also has to detect the pattern rather than just writing a case of an inductive constructor.

Overall, it seems that in order to support these operators, the at least some additions to the expr AST need to be made, while others can be implemented as notations, and that there is some flexibility as to what's a notation and what goes into the AST.
I'm a bit undecided regarding what should be notation vs in the expr AST. Opinions by @andres-erbsen or @jadephilipoom or others welcome 😉

@andres-erbsen
Copy link
Contributor

I don't see any real reasons to prefer notations to new bopnames as long as the operation is generally useful. If giving semantics directly would result in nicer proof obligations, I'd say let's prefer adding bopnames.

I think you could do "! x" := (x == 0) if you wanted, though?

&& and ||: as primitives, added to bopname, or maybe using a ternary if?

I think we should only add them if we are going to match the semantics of C and its predecessors (and at that point we could indeed add conditional expressions as well). In particular 0 && *0 should be a safe expression. We could totally do this (heck, with the confidence we now have about postcondition-style semantics I'd feel fine even going to everything-is-an-expression land), but my hunch is that it's not the most impactful thing to work on right now.

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

No branches or pull requests

2 participants