从语言环境生成代码而无需解释

时间:2013-03-09 21:50:00

标签: scala code-generation isabelle

我希望直接从locale定义生成代码,而无需解释。例如:

(* 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

实例化MyTest的假设是可执行的,我可以为它们生成代码

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 -

我可以定义一个函数来执行任意isInL的{​​{1}}定义。

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)

为什么我要做这样的事情? 我在export_code code_isInL in Scala file - No code equations for MyTest.isInL 的上下文中使用了locale,例如here但有限。测试图表是否有效很容易。现在我想将我的图算法的代码导出到Scala中。当然,代码应该在任意有效图上运行。

我正在考虑类似于这样的Scala类比:

valid_graph

2 个答案:

答案 0 :(得分:2)

解决此问题的一种方法是使用不变量进行数据类型细化(参见isabelle doc codegen第3.3节)。因此,有效性假设(在您的情况下为distinct L)可以移动到新类型中。请考虑以下示例:

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

这定义了一个新类型,其元素都是具有不同元素的列表。我们必须为代码生成器明确设置这种新类型。

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

然后,在语言环境中我们假设“免费”(因为新类型的每个元素都保证它;但是,在某些时候,我们必须将一组基本操作从具有不同元素的列表提升到{{1 }}为s)。

'a dlist

此时,我们能够向代码生成器提供(无条件)方程式。

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

答案 1 :(得分:0)

我找到了一种方法,感谢克里斯的提示。

定义一个函数来测试先决条件/假设以实例化MyTest

definition "can_instance_MyTest L = distinct L"  

命令term MyTest显示MyTest属于string list => bool类型, 这意味着MyTest是一个带谓参数的谓词,并测试此参数是否满足MyTest的假设。 我们引入了一个代码方程([code]),用可执行实例测试程序替换MyTest。 代码生成器现在可以生成例如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 -

我们屈服(我将List[Char]替换为String以提高可读性):

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)

更易读的伪代码:

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

现在我们需要isInL的可执行代码。我们使用预定义的常量undefined。如果L不明显,此代码会抛出异常。

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 -

我们屈服:

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

我们只需要证明code_isInL是正确的:

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)