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

Lean: add support for vectors and register vectors #911

Merged
merged 8 commits into from
Jan 28, 2025

Conversation

lfrenot
Copy link
Collaborator

@lfrenot lfrenot commented Jan 27, 2025

This also updates the lean version to have the recent updates to Vector, and adds neq and if then else support to have proper access functions.

@lfrenot lfrenot requested review from bacam, javra and ineol January 27, 2025 11:59
Copy link

github-actions bot commented Jan 27, 2025

Test Results

   12 files  ±0     24 suites  ±0   0s ⏱️ ±0s
  754 tests +3    754 ✅ +3  0 💤 ±0  0 ❌ ±0 
2 498 runs  +3  2 498 ✅ +3  0 💤 ±0  0 ❌ ±0 

Results for commit 2bf1cc8. ± Comparison against base commit 68c1009.

♻️ This comment has been updated with latest results.

@@ -377,7 +380,9 @@ let rec doc_exp (as_monadic : bool) ctx (E_aux (e, (l, annot)) as full_exp) =
let d_args = List.map d_of_arg args in
let fn_monadic = not (Effects.function_is_pure f ctx.global.effect_info) in
nest 2 (wrap_with_pure (as_monadic && fn_monadic) (parens (flow (break 1) (d_id :: d_args))))
| E_vector vals -> failwith "vector found"
| E_vector vals ->
let vals = List.map (doc_exp false ctx) vals in
Copy link
Contributor

Choose a reason for hiding this comment

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

Does this work for effectful subexpressions? Tuples use d_of_arg, for example.

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 have not tested that, but using the same method as tuples is probably correct, I'll change it accordingly

lib/flow.sail Outdated
@@ -75,7 +75,7 @@ val eq_int = pure {ocaml: "eq_int", interpreter: "eq_int", lem: "eq", coq: "Z.eq

val eq_bool = pure {ocaml: "eq_bool", interpreter: "eq_bool", lem: "eq", coq: "Bool.eqb", lean: "Eq", _: "eq_bool"} : (bool, bool) -> bool

val neq_int = pure {lem: "neq"} : forall 'n 'm. (int('n), int('m)) -> bool('n != 'm)
val neq_int = pure {lem: "neq", lean: "¬ Eq"} : forall 'n 'm. (int('n), int('m)) -> bool('n != 'm)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Could we use Ne instead?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes, done

lib/vector.sail Outdated
@@ -175,6 +175,7 @@ val bitvector_access = pure {
interpreter: "access",
lem: "access_vec_dec",
coq: "access_vec_dec",
lean: "vectorAccess",
Copy link
Collaborator

Choose a reason for hiding this comment

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

Hmmm... shouldn't bitvector access use a bitvector operation, like bv.getLsbD i instead of a vecctor operation?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Right, these edits weren't needed

lib/vector.sail Outdated
@@ -183,6 +184,7 @@ val bitvector_access = pure {
interpreter: "access_inc",
lem: "access_vec_inc",
coq: "access_vec_inc",
lean: "vectorAccess",
Copy link
Collaborator

Choose a reason for hiding this comment

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

Same as above

def GPRs : Vector (RegisterRef RegisterType (BitVec 64)) 31 :=
[Reg R30, Reg R29, Reg R28, Reg R27, Reg R26, Reg R25, Reg R24, Reg R23, Reg R22, Reg R21, Reg R20,
Reg R19, Reg R18, Reg R17, Reg R16, Reg R15, Reg R14, Reg R13, Reg R12, Reg R11, Reg R10, Reg R9,
Reg R8, Reg R7, Reg R6, Reg R5, Reg R4, Reg R3, Reg R2, Reg R1, Reg R0].toArray.toVector
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think you can use this for vector literals. #v[a, b, c] but I haven't tried

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Thanks that's better

@ineol
Copy link
Collaborator

ineol commented Jan 27, 2025

FYI, I added this function and it worked fine!

function monad_test(r : reg_index) -> bit = {
  if rX(r) == 0x0000000000000000 then
    bitone
  else if rX(r) == 0x0000000000000001 then
    bitone
  else
    bitzero
}

Copy link
Collaborator

@ineol ineol left a comment

Choose a reason for hiding this comment

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

Looks good to me now!


val rX : reg_index -> bits(64)

function rX(n) = {
Copy link
Collaborator

Choose a reason for hiding this comment

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

I would be good to have a test with else if to exercise this part of the translation. Also, example with monadic things in the condition and in the branches (at least to see where we're at)

Copy link
Collaborator

Choose a reason for hiding this comment

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

We could also do the whole if else thing in a separate PR

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've added Leo's monad_test function to register_vector.sail and a separate ite.sail test file for additional things.

| _ -> failwith ("Expression " ^ string_of_exp_con full_exp ^ " " ^ string_of_exp full_exp ^ " not translatable yet.")

and doc_fexp with_arrow ctx (FE_aux (FE_fexp (field, e), _)) =
doc_id_ctor field ^^ string " := " ^^ wrap_with_left_arrow with_arrow (doc_exp false ctx e)

and if_exp (ctxt : context) (full_env : env) (full_typ : typ) (elseif : bool) (as_monadic : bool) c t e =
let if_pp = string (if elseif then "else if" else "if") in
let c_pp = doc_exp as_monadic ctxt c in
Copy link
Collaborator

Choose a reason for hiding this comment

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

I don't think that's right. You need to check whether c is monadic and use that as an argument to both the call of doc_exp and then add a call to wrap_with_left_arrow to pull the monadic value out in this case.

Copy link
Collaborator

Choose a reason for hiding this comment

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

This is what I have locally as a minimal implementation, not thoroughly tested though:

| E_if (i, t, e) ->
    let condition_monadic = effectful (effect_of i) in
    nest 2 (string "if" ^^ space ^^ wrap_with_left_arrow condition_monadic (doc_exp condition_monadic ctx i)) ^^ hardline ^^
    nest 2 (string "then" ^^ space ^^ doc_exp as_monadic ctx t) ^^ hardline ^^
    nest 2 (string "else" ^^ space ^^ doc_exp as_monadic ctx e)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes you're correct, I've changed it to something closer to your implementation

default := .Reg _PC

def GPRs : Vector (RegisterRef RegisterType (BitVec 64)) 31 :=
#v[Reg R30, Reg R29, Reg R28, Reg R27, Reg R26, Reg R25, Reg R24, Reg R23, Reg R22, Reg R21, Reg R20,
Copy link
Collaborator

Choose a reason for hiding this comment

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

Indentation

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Fixed


open Sail

def reg_index := Nat
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'd rather have abbrev RegIndex := Nat here. The def instead of abbrev will make the new type have no usable instances on it.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This is a bit out of the scope of this PR, but I have changed it

string "else" ^/^ doc_exp as_monadic ctxt (E_aux (E_internal_plet (pat, exp1, exp2), ann))
| _ -> prefix 2 1 (string "else") (doc_exp as_monadic ctxt e)
in
prefix 2 1 (soft_surround 2 1 if_pp c_pp (string "then")) t_pp ^^ break 1 ^^ else_pp
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is this copied over from the Coq printer? If so maybe mark it as such so we can improve it later.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes it was, it's not here anymore, but I have marked the other part that was copied from the Coq printer

@@ -73,7 +73,7 @@ let opt_lean_output_dir : string option ref = ref None

let opt_lean_force_output : bool ref = ref false

let lean_version : string = "lean4:nightly-2024-09-25"
let lean_version : string = "lean4:nightly-2025-01-22"
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why was this bumped?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

It was bumped because nightly-2024-09-25 used a different implementation of Vectors

This also adds a test file for ite, and an additional test in register_vector
@@ -413,6 +418,14 @@ let rec doc_exp (as_monadic : bool) ctx (E_aux (e, (l, annot)) as full_exp) =
| LE_deref e' -> string "writeRegRef " ^^ doc_exp false ctx e' ^^ space ^^ doc_exp false ctx e
| _ -> failwith ("assign " ^ string_of_lexp le ^ "not implemented yet")
)
| E_if (i, t, e) ->
let statements_monadic = as_monadic || effectful (effect_of t) || effectful (effect_of e) in
nest 2 (string "if" ^^ space ^^ nest 1 (doc_exp false ctx i))
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think this still ignores the monadicity of the condition?

Copy link
Collaborator

Choose a reason for hiding this comment

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

But yes, let's ignore that for now and fix it when we need to fix it.

Copy link
Collaborator Author

@lfrenot lfrenot Jan 28, 2025

Choose a reason for hiding this comment

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

It does because the condition should never be monadic (it should be a Bool and not a SailM Bool), instead the responsibility is on doc_exp, see line 352

The responsibility needs to be moved like that, because we want to be able to handle both if (Eq (← (rX r)) 0) and if (← readReg B)

@bacam bacam merged commit dde655a into rems-project:sail2 Jan 28, 2025
3 checks passed
lfrenot added a commit to lfrenot/sail that referenced this pull request Jan 29, 2025
bacam pushed a commit that referenced this pull request Jan 29, 2025
@lfrenot lfrenot deleted the lean-vector branch February 3, 2025 10:14
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.

None yet

4 participants