Generating code from locales without interpretation

 ̄綄美尐妖づ 提交于 2020-01-06 23:57:29

问题


I would love to generate code from locale definitions directly, without interpretation. Example:

(* A locale, from the code point of view, similar to a class *)
locale MyTest =
  fixes L :: "string list"
  assumes distinctL: "distinct L"
  begin
    definition isInL :: "string => bool" where
      "isInL s = (s ∈ set L)"
  end

The assumptions to instantiate MyTest are executable and I can generate code for them

definition "can_instance_MyTest L = distinct L"  
lemma "can_instance_MyTest L = MyTest L"
  by(simp add: MyTest_def can_instance_MyTest_def)
export_code can_instance_MyTest in Scala file -

I can define a function to execute the isInL definition for arbitrary MyTest.

definition code_isInL :: "string list ⇒ string ⇒ bool option" where
"code_isInL L s = (if can_instance_MyTest L then Some (MyTest.isInL L s) else None)"

lemma "code_isInL L s = Some b ⟷ MyTest L ∧ MyTest.isInL L s = b"
  by(simp add: code_isInL_def MyTest_def can_instance_MyTest_def)

However, code export fails:

export_code code_isInL in Scala file -
No code equations for MyTest.isInL

Why do I want to do such a thing? I'm working with a locale in the context of a valid_graph similar to e.g. here but finite. Testing that a graph is valid is easy. Now I want to export the code of my graph algorithms into Scala. Of course, the code should run on arbitrary valid graphs.

I'm thinking of the Scala analogy similar to something like this:

class MyTest(L: List[String]) {
require(L.distinct)
def isInL(s: String): Bool = L contains s
}

回答1:


One way to solve this is datatype refinement using invariants (see isabelle doc codegen section 3.3). Thereby the validity assumption (distinct L, in your case) can be moved into a new type. Consider the following example:

typedef 'a dlist = "{xs::'a list. distinct xs}"
morphisms undlist dlist
proof
  show "[] ∈ ?dlist" by auto
qed

This defines a new type whose elements are all lists with distinct elements. We have to explicitly set up this new type for the code generator.

lemma [code abstype]: "dlist (undlist d) = d"
  by (fact undlist_inverse)

Then, in the locale we have the assumption "for free" (since every element of the new type guarantees it; however, at some point we have to lift a basic set of operations from lists with distinct element to 'a dlists).

locale MyTest =
  fixes L :: "string dlist"
begin
  definition isInL :: "string => bool" where
    "isInL s = (s ∈ set (undlist L))"
end

At this point, we are able to give (unconditional) equations to the code generator.

lemma [code]: "MyTest.isInL L s ⟷ s ∈ set (undlist L)"
  by (fact MyTest.isInL_def)

export_code MyTest.isInL in Haskell file -



回答2:


I found a method, thanks to chris' tips.

Define a function to test the prerequisites/assumptions to instantiate a MyTest

definition "can_instance_MyTest L = distinct L"  

The command term MyTest reveals that MyTest is of type string list => bool, this means that MyTest is a predicate that takes a parameter and tests if this parameter fulfills MyTest's assumptions. We introduce a code equation ([code]) that replaces MyTest with the executable instance tester. The code generator can now produce code for occurrences of e.g., MyTest [a,b,c]

lemma [code]: "MyTest = can_instance_MyTest"
  by(simp add:fun_eq_iff MyTest_def can_instance_MyTest_def)

export_code MyTest in Scala file -

We yield (I replaced List[Char] with String for readability):

def can_instance_MyTest[A : HOL.equal](l: List[A]): Boolean =
  Lista.distinct[A](l)

def myTest: (List[String]) => Boolean =
  (a: List[String]) => can_instance_MyTest[String](a)

More readable pseudo-code:

def myTest(l: List[String]): Boolean = l.isDistinct

Now we need executable code for isInL. We utilize the predefined constant undefined. This code throws an exception if L is not distinct.

definition code_isInL :: "string list ⇒ string ⇒ bool" where
"code_isInL L s = (if can_instance_MyTest L then s ∈ set L else undefined)"

export_code code_isInL in Scala file -

We yield:

def code_isInL(l: List[String], s:String): Boolean =
  (if (can_instance_MyTest[String](l)) Lista.member[String](l, s)
    else sys.error("undefined"))*)

We just need to show that the code_isInL is correct:

lemma "b ≠ undefined ⟹ code_isInL L s = b ⟷ MyTest L ∧ MyTest.isInL L s = b"
  by(simp add: code_isInL_def MyTest_def can_instance_MyTest_def MyTest.isInL_def)


(* Unfortunately, the other direction does not hold. The price of undefined. *)
lemma "¬ MyTest L  ⟹ code_isInL L s = undefined"
  by(simp add: code_isInL_def can_instance_MyTest_def MyTest_def)


来源:https://stackoverflow.com/questions/15316313/generating-code-from-locales-without-interpretation

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!