diff --git a/prover/build b/prover/build index 58551a797..34e6ec78f 100755 --- a/prover/build +++ b/prover/build @@ -18,9 +18,11 @@ proj = KProject() # Matching Logic Prover # ===================== -other_md_files = [ 'lang/smt-lang.md' +other_md_files = [ 'lang/coq-lang.md' + , 'lang/smt-lang.md' , 'lang/kore-lang.md' , 'drivers/base.md' + , 'drivers/coq-driver.md' , 'drivers/smt-driver.md' , 'drivers/kore-driver.md' , 'strategies/apply-equation.md' @@ -34,6 +36,7 @@ other_md_files = [ 'lang/smt-lang.md' , 'strategies/replace-evar-with-func-constant.md' , 'strategies/simplification.md' , 'strategies/search-bound.md' + , 'strategies/typecheck.md' , 'strategies/smt.md' , 'strategies/unfolding.md' , 'utils/load-named.md' @@ -53,6 +56,7 @@ def prover(alias, flags = None): prover_kore = prover('prover-kore', '--main-module DRIVER-KORE --syntax-module DRIVER-KORE-SYNTAX') prover_smt = prover('prover-smt', '--main-module DRIVER-SMT --syntax-module DRIVER-SMT-SYNTAX' ) +prover_coq = prover('prover-coq', '--main-module DRIVER-COQ --syntax-module DRIVER-COQ-SYNTAX' ) # Functional tests # ---------------- @@ -60,6 +64,8 @@ prover_smt = prover('prover-smt', '--main-module DRIVER-SMT --syntax-module D # prover_kore.tests(inputs = glob('t/*.kore'), implicit_inputs = glob('t/definitions/*.kore'), flags = '-cCOMMANDLINE=.CommandLine') # prover_smt .tests(inputs = glob('t/*.smt2'), flags = '-cCOMMANDLINE=.CommandLine') +prover_coq .tests(inputs = glob('t/coq-tests/*.v'), flags = '-cCOMMANDLINE=.CommandLine') + def log_on_success(file, message): return proj.rule( 'log-to-success' , description = '$out: $message' diff --git a/prover/coq_rules/coq_rules.pdf b/prover/coq_rules/coq_rules.pdf new file mode 100644 index 000000000..28d4b684f Binary files /dev/null and b/prover/coq_rules/coq_rules.pdf differ diff --git a/prover/coq_rules/coq_rules.tex b/prover/coq_rules/coq_rules.tex new file mode 100644 index 000000000..e214d8a6c --- /dev/null +++ b/prover/coq_rules/coq_rules.tex @@ -0,0 +1,528 @@ +\documentclass{article} + +\usepackage{amsmath,amssymb,amsthm} +\usepackage{fullpage} +\usepackage{hyperref} +\usepackage{longtable} +\usepackage{mathtools} +\usepackage{prftree} +\usepackage[dvipsnames]{xcolor} +\usepackage{xspace} + +\input{newcommands} + +\title{All Coq Rules in One Place} +\author{Xiaohong Chen \and Lucas Pe{\~{n}}a} + +\begin{document} + +\maketitle + +\begin{abstract} +This document summarizes all the proof rules of the Coq proof assistant, +as listed in +\url{https://coq.inria.fr/distrib/current/refman/language/cic.html}. +\end{abstract} + +\section{Syntax} + +Let us fix a countably infinite set $\V$ of \emph{variables}, denoted +$x,y,\dots$. +Let us fix a countably infinite set $\C$ of \emph{constants}, denoted +$c,d,\dots$. + +\begin{definition} +We define the set \CoqTerm to be the smallest set that satisfies the following +conditions: +\begin{enumerate} +\item $\SProp,\Prop,\Set \in \CoqTerm$; $\Type(i) \in \CoqTerm$ for every $i +\in \NNp$. +\item $\V \subseteq \CoqTerm$. +\item $\C \subseteq \CoqTerm$. +\item If $x \in \V$ and $T,U \in \CoqTerm$, + then $\cfa{x}{T}{U} \in \CoqTerm$. +\item If $x \in \V$ and $T,u \in \CoqTerm$, + then $\clm{x}{T}{u} \in \CoqTerm$. +\item If $t,u \in \CoqTerm$, + then $\cpp{t}{u} \in \CoqTerm$, called \emph{application}. +\item If $x \in \V$ and $t,T,u \in \CoqTerm$, + then $\clt{x}{t}{T}{u} \in \CoqTerm$. +\end{enumerate} +where $\cfa{x}{T}{U}$ binds $x$ to $U$ +and $\clm{x}{T}{u}$ binds $x$ to $u$. +We use $\FV(T) \subseteq \V$ to denote the set of free variables in $T \in +\CoqTerm$. +For $T,U \in \CoqTerm$ and $x \in \V$, +we use $\sbs{T}{U}{x}$ to denote the result of substituting $U$ for $x$ in $T$, +where $\alpha$-renaming happens implicitly to prevent variable capture. +\end{definition} + +\begin{definition} +We define the set +$\CoqSort = \{\SProp,\Prop,\Set\} \cup \{\Type(i) \mid i \in \NN\}$. +Note that $\CoqSort \subseteq \CoqTerm$. +Elements in $\CoqSort$ are called \emph{sorts} and denoted as $s$, +possibly with subscripts. +\end{definition} + +\begin{definition} +A \emph{local assumption} is written $\lasm{x}{T}$, where $x \in \V$ and $T \in +\CoqTerm$. +A \emph{local definition} is written $\ldef{x}{u}{T}$, +where $x \in \V$ and $u,T \in \CoqTerm$. +In both cases, we call $x$ the \emph{declared variable}. +A \emph{local context} is an ordered list of local assumptions and local +definitions, such that the declared variables are all distinct. +We use $\Gamma$, possibly with subscripts, to denote local contexts. +\end{definition} + +\begin{notation}\label{not:ldcl} +We use the notation $[\lasm{x}{T} \scln \ldef{y}{u}{U} \scln \lasm{z}{V}]$ +to denote the local context that consists of +the local assumption $\lasm{x}{T}$, +the local definition $\ldef{y}{u}{U}$ +and the local assumption $\lasm{z}{V}$, +with the implicit requirement that $x,y,z$ are all distinct. +The empty local context is written as $[]$. +Let $\Gamma$ be a local context. +We write $x \in \Gamma$ to mean that $x$ is declared in $\Gamma$. +We write $(\lasm{x}{T}) \in \Gamma$ to mean that the local assumption +$\lasm{x}{T}$ is in $\Gamma$, or that +the local definition $\ldef{x}{u}{T}$ is in $\Gamma$ for some $u \in \CoqTerm$. +We write $(\ldef{x}{u}{T}) \in \Gamma$ to mean that +the local definition $\ldef{x}{u}{T}$ is in $\Gamma$. +We write $\Gamma \dcln ( \lasm{x}{T} )$ to denote the local context +that enriches $\Gamma$ with $\lasm{x}{T}$, with the implicit requirement that +$x \not\in \Gamma$. +Similarly, we write +$\Gamma \dcln ( \ldef{x}{u}{T} )$ to denote the local context +that enriches $\Gamma$ with $\ldef{x}{u}{T}$, with the implicit requirement +that $x \not\in \Gamma$. +We write $\Gamma_1 \scln \Gamma_2$ to mean the local context +obtained by concatenating $\Gamma_1$ and $\Gamma_2$, with the implicit +requirement that all variables declared in $\Gamma_2$ are not declared in +$\Gamma_1$. +\end{notation} + +\begin{definition} +A \emph{global assumption} is written $(\gasm{c}{T})$, +with the parentheses, where $c \in \C$ and $T \in +\CoqTerm$. +A \emph{global definition} is written $\gldef{c}{u}{T}$, +where $c \in \C$ and $u,T \in \CoqTerm$. +In both cases, we call $c$ the \emph{declared constant}. +A \emph{global environment} is an ordered list of global assumptions and global +definitions, and also \emph{declarations of inductive objects}, which are +defined later. +We use $E$, possibly with subscripts, to denote global environments. +\end{definition} + +\begin{notation} +We use the notation $\gasm{c_1}{T} \scln \gldef{c_2}{u}{U} \scln \gasm{c_3}{V}$ +to denote the local context that consists of +the global assumption $\gasm{c_1}{T}$, +the global definition $\gldef{c_2}{u}{U}$ +and the global assumption $\gasm{c_3}{V}$. +The empty global context is written as $[]$. % TODO: is this right? +Let $E$ be a local context. +We write $c \in E$ to mean that $c$ is declared in $E$. +We write $(\gasm{c}{T}) \in E$ to mean that the global assumption +$\gasm{c}{T}$ is in $E$, or that +the global definition $\gldef{c}{u}{T}$ is in $E$ for some $u \in \CoqTerm$. +We write $(\gldef{c}{u}{T}) \in E$ to mean that +the global definition $\gldef{c}{u}{T}$ is in $E$. +We write $E \scln \gasm{c}{T}$ to denote the global context +that enriches $E$ with $\gasm{c}{T}$. +Similarly, we write +$E \scln \gldef{c}{u}{T}$ to denote the global context +that enriches $E$ with $( \gldef{c}{u}{T} )$. +\end{notation} + +\begin{notation} +We write $E[\Gamma] \proves \lasm{u}{T}$ to mean that $u$ is \emph{well-typed} +with type $T$ in global environment $E$ and local environment $\Gamma$. +We write $\wf(E)[\Gamma]$ to mean that the global environment $E$ is +\emph{well-formed} +and $\Gamma$ is a \emph{valid local context} in $E$. +\end{notation} + +\begin{definition} +A term $u$ is \emph{well-typed} in a global environment $E$ if there is a +local context $\Gamma$ and type $T$ such that +$E[\Gamma] \proves \lasm{u}{T}$ is derivable with the rules below. +\end{definition} + +\section{Coq Rules} + +In this section we list all Coq rules. +A \emph{rule} consists of a set of \emph{premises} and one \emph{conclusion}, +separated by a horizontal bar. +For readability, we put \emph{side conditions} alongside the premises. +Side conditions are typed in $\sd{\text{green}}$, to distinguish +from the premises. + + +\subsection{Basic Typing Rules} + +There are 18 basic typing rules, as shown below. + + +\begin{center} +\bgroup +\def\arraystretch{4} +\begin{longtable}{llp{5cm}} +\textbf{Names} & \textbf{Rules} & \textbf{Comments} \\\hline +\prule{W-Empty}& +$\prftree{\cdot}{\wf([])[]}$ & +The empty global environment is well-formed, and the empty local context is a +valid local context in the empty global environment.\\ +\prule{W-Local-Assum}& +$\prftree{E[\Gamma]\vdash T \cln s} +{\sd{s \in S}} +{\sd{x \not\in \Gamma}} +{\wf(E)[\Gamma \dcln (x \cln T)]}$& +The side condition $x \not\in \Gamma$ needs not to be specified because +it is implicit +in the notation $\Gamma \dcln (x \cln T)$; see Notation~\ref{not:ldcl}.\\ +\prule{W-Local-Def}& +$\prftree{E[\Gamma]\vdash t \cln T} +{\sd{x \not\in \Gamma}} +{\wf(E)[\Gamma \dcln (\ldef{x}{t}{T})]}$& +The side condition $x \not\in \Gamma$ needs not to be specified because +it is implicitly implied +by the notation $\Gamma \dcln (\ldef{x}{t}{T})$; see Notation~\ref{not:ldcl}.\\ +\prule{W-Global-Assum}& +$ +\prftree +{E[]\vdash T \cln s} +{\sd{s \in S}} +{\sd{c \not\in E}} +{\wf(E ; c \cln T)[]} +$ & \\ +\prule{W-Global-Def} & +$ +\prftree +{E[]\vdash t \cln T} +{\sd{c \not\in E}} +{\wf(E ; \gldef{c}{t}{T})[]} +$ & \\ +\prule{Ax-SProp} & +$ +\prftree{\wf(E)[\Gamma]} +{E[\Gamma] \vdash \SProp \cln \Type(1)} +$ &\\ +\prule{Ax-Prop} & +$ +\prftree{\wf(E)[\Gamma]} +{E[\Gamma] \vdash \Prop \cln \Type(1)} +$ &\\ +\prule{Ax-Set} & +$ +\prftree{\wf(E)[\Gamma]} +{E[\Gamma] \vdash \Set \cln \Type(1)} +$ &\\ +\prule{Ax-Type} & +$ +\prftree{\wf(E)[\Gamma]} +{E[\Gamma] \vdash \Type(i) \cln \Type(i+1)} +$ & Here, $i \in \NNp$ is any positive natural number. \\ +\prule{Var} & +\multicolumn{2}{l}{ +$ +\prftree{\wf(E)[\Gamma]} +{\sd{\text{$(\lasm{x}{T} \in \Gamma)$, or $(\ldef{x}{t}{T}) \in \Gamma$ for +some $t \in \CoqTerm$}}} +{E[\Gamma] \vdash x \cln T} +$} \\ +\prule{Const} & +\multicolumn{2}{l}{ +$ +\prftree{\wf(E)[\Gamma]} +{\sd{\text{$(\lasm{c}{T} \in E)$, or $(\ldef{c}{t}{T}) \in E$ for +some $t \in \CoqTerm$}}} +{E[\Gamma] \vdash c \cln T} +$} \\ +\prule{Prod-SProp} & +$ +\prftree +{E[\Gamma] \vdash T \cln s} +{\sd{s \in S}} +{E[\Gamma \dcln (x \cln T)] \vdash U \cln \SProp} +{E[\Gamma]\vdash \cfa{x}{T}{U} \cln \SProp} +$ &\\ +\prule{Prod-Prop} & +$ +\prftree +{E[\Gamma] \vdash T \cln s} +{\sd{s \in S}} +{E[\Gamma \dcln (x \cln T)] \vdash U \cln \Prop} +{E[\Gamma]\vdash \cfa{x}{T}{U} \cln \Prop} +$ &\\ +\prule{Prod-Set} & +\multicolumn{2}{l}{ +$ +\prftree +{E[\Gamma] \vdash T \cln s} +{\sd{s \in \{\SProp,\Prop,\Set\}}} +{E[\Gamma \dcln (x \cln T)] \vdash U \cln \Set} +{E[\Gamma]\vdash \cfa{x}{T}{U} \cln \Set} +$ +} \\ +\prule{Prod-Type} & +\multicolumn{2}{l}{ +$ +\prftree +{E[\Gamma] \vdash T \cln s} +{\sd{s \in \{\SProp,\Type(i)\}}} +{E[\Gamma \dcln (x \cln T)] \vdash U \cln \Type(i)} +{E[\Gamma]\vdash \cfa{x}{T}{U} \cln \Type(i)} +$ +} \\ +\prule{Lam} & +$ +\prftree +{E[\Gamma] \vdash \cfa{x}{T}{U} \cln s} +{\sd{s \in S}} +{E[\Gamma \dcln (x \cln T)] \vdash t \cln U} +{E[\Gamma] \vdash \clm{x}{T}{t} \cln \cfa{x}{T}{U}} +$ &\\ +\prule{App} & +$ +\prftree +{E[\Gamma] \vdash t \cln \cfa{x}{U}{T}} +{E[\Gamma] \vdash u \cln U} +{E[\Gamma] \vdash (t \, u) \cln T[u/x]} +$ &\\ +\prule{Let} & +$\prftree +{E[\Gamma] \vdash t \cln T} +{E[\Gamma \dcln (\ldef{x}{t}{T})] \vdash u \cln U} +{E[\Gamma] \vdash \clt{x}{t}{T}{u} \cln U[t/x]} +$ +\end{longtable} +\egroup +\end{center} + +\subsection{Conversion Rules} +In this section, we define what it means for two Coq programs to be +\emph{intentionally equal}, or \emph{convertible}. + +\begin{center} +\bgroup +\def\arraystretch{4} +\begin{longtable}{llp{5cm}} +\textbf{Names} & \textbf{Rules} & \textbf{Comments} \\\hline +\prule{Beta}& +$\prftree{E[\Gamma] \vdash ((\clm{x}{T}{t}) u) \red_{\beta} \sbs{t}{x}{u}}$& +We say that $\sbs{t}{x}{u}$ is the \emph{$\beta$-contraction} of +$((\clm{x}{T}{t}) u)$, and that $((\clm{x}{T}{t}) u)$ is the +\emph{$\beta$-expansion} of $\sbs{t}{x}{u}$ \\ +&& +$\iota$-reduction rules to be defined later \\ +\prule{Delta-Local}& +$\prftree +{\wf(E)[\Gamma]} +{(\ldef{x}{t}{T}) \in \Gamma} +{E[\Gamma] \vdash x \red_{\Delta} t}$& +Reducing variable defined in local context \\ +\prule{Delta-Local}& +$\prftree +{\wf(E)[\Gamma]} +{(\gldef{c}{t}{T}) \in E} +{E[\Gamma] \vdash c \red_{\delta} t}$& +Reducing constant defined in global context \\ +\prule{Zeta}& +$\prftree +{\wf(E)[\Gamma]} +{E[\Gamma] \vdash \lasm{u}{U}} +{E[\Gamma \dcln (\ldef{x}{u}{U})] \vdash \lasm{t}{T}} +{E[\Gamma] \vdash \clt{x}{u}{U}{t} \red_{\zeta} \sbs{t}{x}{x}}$& +Remove local definitions occurring in terms \\ +\end{longtable} +\egroup +\end{center} +In addition to the above convertibility rules, we also allow identifying a term +$t$ of type $\cfa{x}{t}{U}$ with its \emph{$\eta$-expansion} $\clm{x}{T}{(t x)}$ +for $x$ fresh in $t$. Note \emph{$\eta$-reduction} is deliberately not defined. +% TODO: show example? + +\begin{notation} +We write $E[\Gamma] \vdash t \red u$ for the contextual closure of the rules +defined above. That is, $t$ reduces to $u$ with global environment $E$ and local +context $\Gamma$ with one of the previous reductions $\beta, \Delta, \delta, +\iota,$ or $\zeta$. +\end{notation} + +\begin{definition} +Two terms are called \emph{irrelevant} if they share a common type of a strict +proposition $\gasm{A}{\SProp}$. Irrelevant terms can be identified. +\end{definition} + +\begin{definition} +Two terms $t_1, t_2$ are called \emph{$\beta\delta\iota\zeta\eta$-convertible}, or +\emph{convertible}, or \emph{equivalent} in global environment $E$ and local +context $\Gamma$ iff there exists $t_1, t_2$ such that +\[ E[\Gamma] \vdash t_1 \red \ldots \red u_1 \text{ and } E[\Gamma] \vdash t_2 \red \ldots \red u_2 \] +and either $u_1$ and $u_2$ are identical up irrelevant subterms, or they are +convertible up to $\eta$-exxpansion. We denote this as +$E[\Gamma] \vdash t_1 \conveq t_2$ +\end{definition} + +\subsection{Subtyping Rules} +The \emph{subtyping} relation is inductively defined as follows: +% TODO: display as proof rules? +\begin{itemize} +\item if $E[\Gamma] \vdash t \conveq u$, then $E[\Gamma] \vdash t \subty u$ +\item if $i \leq j$, then $E[\Gamma] \vdash \Type(i) \subty \Type(j)$ +\item $E[\Gamma] \vdash \Set \subty \Type(i)$ for all $i$ +\item $E[\Gamma] \vdash \Prop \subty \Set$ +\item if $E[\Gamma] \vdash T \conveq U$ and + $E[\Gamma \dcln (\lasm{x}{T})] \vdash T' \subty U'$, then + $E[\Gamma] \vdash \cfa{x}{T}{T'} \subty \cfa{x}{U}{U'}$ +\end{itemize} + +\subsection{Conversion/Subtyping: Polymorphic Universes} + +\subsection{Conversion Typing Rule} +We now have the infrastructure to define the typing rule for conversion: +\[ +\prule{Conv}\hspace{5ex} +\prftree +{E[\Gamma] \vdash \lasm{U}{s}} +{E[\Gamma] \vdash \lasm{t}{T}} +{E[\Gamma] T \subty U} +{E[\Gamma] \vdash \lasm{t}{U}} +\] + +\subsection{Inductive Definitions} +\begin{definition} +We represent an \emph{inductive definition} as $\Ind{p}{\Gamma_I}{\Gamma_C}$ where +\begin{itemize} +\item $p$ represents the number of parameters of the inductive types +\item $\Gamma_I$ represents the names and types of inductive types +\item $\Gamma_C$ represents the names and types of the constructors of the inductive types +\end{itemize} +\end{definition} + +\begin{definition} +Let $\Ind{p}{\Gamma_I}{\Gamma_C}$ be an inductive definition and let $T$ be such +that $(t \cln T) \in \Gamma_I \cup \Gamma_C$. Then, there exists a +$\Gamma_P = [a_1 \cln A_1 \scln \ldots \scln a_p \cln A_p]$ such that $T$ can be +written as $\forall \Gamma_P, T'$ for some $T'$. Here $\Gamma_P$ is called the +\emph{context of paramters}. + +Additionaly, if $(t \cln T) \in \Gamma_I$, then $T$ can be written as +$\forall \Gamma_P, \Gamma_{\mathit{Arr}(t)}, s$. Here, $\mathit{Arr}(t)$ is +called the \emph{Arity} of the inductive type $t$ and $s$ is called the sort of +$t$. +\end{definition} + +\begin{example} +The inductive definition for parameterized lists is: +\[ +\Ind{1}{\begin{bmatrix} \mathsf{list} \cln \Set \rightarrow \Set \end{bmatrix}} + {\begin{bmatrix*}[l] + \mathsf{nil}\, &: \,\forall A \cln \Set,\, \mathsf{list}\, A \\ + \mathsf{cons}\, &: \, \forall A \cln \Set,\, A\, \rightarrow\, \mathsf{list}\, A\, + \rightarrow\, \mathsf{list}\, A + \end{bmatrix*}} +\] +This corresponds to the Coq definition: +\begin{verbatim} +Inductive list (A:Set) : Set := +| nil : list A +| cons : A -> list A -> list A. +\end{verbatim} +\end{example} + +Below are rules for types of constants in a global environment that contain an +inductive definition: +\[ +\prule{Ind}\hspace{5ex} +\prftree +{\wf(E)[\Gamma]} +{\Ind{p}{\Gamma_I}{\Gamma_C} \in E} +{\lasm{a}{A} \in \Gamma_I} +{E[\Gamma] \vdash \lasm{a}{A}} +\] +\[ +\prule{Constr}\hspace{5ex} +\prftree +{\wf(E)[\Gamma]} +{\Ind{p}{\Gamma_I}{\Gamma_C} \in E} +{\lasm{c}{C} \in \Gamma_C} +{E[\Gamma] \vdash \lasm{c}{C}} +\] + +\begin{definition} +A type $T$ is an \emph{arity of sort $s$} if it converts to the sort $s$ or to a +product $\cfa{x}{T}{U}$ with $U$ an arity of sort $s$. +\end{definition} +\begin{definition} +A type $T$ is an \emph{arity} if there is an $s \in S$ such that $T$ is an arity +of sort $s$. +\end{definition} + +\begin{definition} +A type $T$ is a \emph{type of constructor of $I$} if $T$ is $(I\, t_1 \ldots t_n)$ or +$T$ is $\cfa{x}{U}{T'}$ where $T'$ is a type of constructor of $I$. +\end{definition} + +\begin{definition} +A type of constructor $T$ is said to \emph{satisfy the positivity condition} for +$X$ if $T = (X\, t_1 \ldots t_n)$ and $X$ does not occur free in any $t_i$, or +$T = \cfa{x}{U}{V}$ where $X$ occurs only strictly positively in $U$ and +$V$ satisfies the positivity condition for $X$. +\end{definition} +\begin{definition} +A constant $X$ occurs \emph{strictly positive} in $T$ if one of the following +cases hold: +\begin{itemize} +\item $X$ does not occur in $T$ +\item $T$ converts to $(X\, t_1 \ldots t_n)$ and $X$ does not occur in any $T_i$ +\item $T$ converts to $\cfa{x}{U}{V}$ where $X$ does not occur in $U$ and + $X$ occurs strictly positively in $V$ +\item $T$ converts to $(I\, a_1\ldots a_m\, t_1\ldots t_p)$ where $I$ represents + the inductive definition + \[\Ind{m}{\lasm{I}{A}}{\lasm{c_1}{\forall p_1 \cln P_1, \ldots \forall p_m \cln P_m, C_1} + \scln \ldots \lasm{c_n}{\forall p_1 \cln P_1, \ldots \forall p_m \cln P_m, C_n}} + \] + and $X$ does not occur in any of the $t_i$, and all instantiated types of + constructors $C_i\{p_j/a_j\}_{j=1\ldots m}$ satisfy the nested positivity + condition for $X$ +\end{itemize} +\end{definition} +\begin{definition} +A type of constructor $T$ of $I$ is said to \emph{satisfy the nested positivity + condition} for $X$ if $T = (I\, b_1 \ldots b_n u_1 \ldots u_p)$ where $I$ is +an inductive type with $m$ paramters and $X$ does not occur in any $u_i$, or +$T = \cfa{x}{U}{V}$ where $X$ occurs only strictly positively in $U$ and $V$ +satisfies the nested positivity condition for $X$. +\end{definition} + +\subsubsection{Correctness Rules} +Let $E$ be a global environment and $\Gamma_P, \Gamma_I, \Gamma_C$ be contexts +such that $\Gamma_I$ is +$[I_1\cln \forall\Gamma_P, A_1 \scln \ldots I_k\cln \forall \Gamma_P, A_k]$ +and $\Gamma_C$ is +$[c_1\cln \forall\Gamma_P, C_1 \scln \ldots c_n\cln \forall \Gamma_P, C_n]$. +Then we have the following well-formedness rule: +\[ +\prule{Ind}\hspace{5ex} +\prftree +{\wf(E)[\Gamma_P]} +{(E[\Gamma_I\scln\Gamma_P] \vdash \lasm{C_i}{s_{q_i}})_i=1\ldots n} +{\wf(E\scln \Ind{p}{\Gamma_I}{\Gamma_C})[]} +\] +provided the following side conditions hold: +\begin{itemize} +\item $k > 0$ and all $I_j$ and $c_i$ are distinct names for $j=1\ldots k$ and + $i=1\ldots n$ +\item $p$ is the number of parameters of $\Ind{p}{\Gamma_I}{\Gamma_C}$ and + $\Gamma_P$ is the context of paramters +\item for $j=1\ldots k$, $A_j$ is an arity of sort $s_j$ and $I_j \not\in E$ +\item for $i=1\ldots n$, $C_i$ is a type of constructor of $I_{q_i}$ which + satisfies the positivity condition for $I_1 \ldots I_k$ and $c_i \not\in E$ +\end{itemize} + +\end{document} diff --git a/prover/coq_rules/newcommands.tex b/prover/coq_rules/newcommands.tex new file mode 100644 index 000000000..b40e2d2e3 --- /dev/null +++ b/prover/coq_rules/newcommands.tex @@ -0,0 +1,42 @@ +\theoremstyle{definition} +\newtheorem{definition}{Definition}[section] +\newtheorem{notation}[definition]{Notation} +\newtheorem{example}[definition]{Example} + +\newcommand{\CoqTerm}{\textnormal{\textit{Term}}\xspace} +\newcommand{\CoqSort}{\textnormal{\textit{Sort}}\xspace} + +\newcommand{\SProp}{\mathsf{SProp}} +\newcommand{\Prop}{\mathsf{Prop}} +\newcommand{\Set}{\mathsf{Set}} +\newcommand{\Type}{\mathsf{Type}} +\newcommand{\NN}{\mathbb{N}} +\newcommand{\NNp}{{\NN_{\ge 1}}} +\newcommand{\V}{V} +\newcommand{\C}{C} +\newcommand{\cln}{{\,:\,}} +\newcommand{\scln}{\mathbin{;}} +\newcommand{\dcln}{\mathbin{::}} +\newcommand{\FV}{\mathrm{FV}} +\newcommand{\sbs}[3]{#1 [ #2 / #3 ]} + +\newcommand{\cfa}[3]{\forall #1 \cln #2 , #3} +\newcommand{\clm}[3]{\lambda #1 \cln #2 . #3} +\newcommand{\cpp}[2]{(#1 \, #2)} +\newcommand{\clt}[4]{\textsf{let} \, #1 \coloneqq #2 \cln #3 \,\textsf{in}\, #4} + +\newcommand{\lasm}[2]{#1 \cln #2} +\newcommand{\gasm}[2]{#1 \cln #2} +\newcommand{\ldef}[3]{#1 \coloneqq #2 \cln #3} +\newcommand{\gldef}[3]{#1 \coloneqq #2 \cln #3} + +\newcommand{\proves}{\vdash} +\newcommand{\wf}{\mathcal{W\!F}} +\newcommand{\prule}[1]{\textsc{(#1)}} +\newcommand{\sd}[1]{{{\color{JungleGreen} #1}}} + +\newcommand{\red}{\triangleright} +\newcommand{\conveq}{=_{\beta\delta\iota\zeta\eta}} +\newcommand{\subty}{\leq_{\beta\delta\iota\zeta\eta}} + +\newcommand{\Ind}[3]{\mathsf{Ind}[#1]\left(#2 \coloneqq #3\right)} diff --git a/prover/drivers/base.md b/prover/drivers/base.md index 9ec7a5afb..d13fa8c8c 100644 --- a/prover/drivers/base.md +++ b/prover/drivers/base.md @@ -79,6 +79,7 @@ module DRIVER-BASE imports STRATEGY-UNFOLDING imports STRATEGY-KNASTER-TARSKI imports STRATEGY-REPLACE-EVAR-WITH-FUNC-CONSTANT + imports STRATEGY-TYPECHECK imports SYNTACTIC-MATCH-RULES imports VISITOR imports PATTERN-LENGTH diff --git a/prover/drivers/coq-driver.md b/prover/drivers/coq-driver.md new file mode 100644 index 000000000..06fe7b0bb --- /dev/null +++ b/prover/drivers/coq-driver.md @@ -0,0 +1,168 @@ +Coq Driver +========== + +This file is responsible for loading definitions in the Coq format. + +```k +module DRIVER-COQ-COMMON + imports COQ + imports STRATEGIES-EXPORTED-SYNTAX + syntax Pgm ::= CoqSentences +endmodule +``` + +```k +module DRIVER-COQ-SYNTAX + imports DRIVER-BASE-SYNTAX + imports DRIVER-COQ-COMMON + imports COQ-SYNTAX +endmodule +``` + +```k +module DRIVER-COQ + imports DRIVER-KORE + imports DRIVER-COQ-COMMON + imports KORE + imports PROVER-CONFIGURATION + imports PROVER-CORE-SYNTAX + imports STRATEGIES-EXPORTED-SYNTAX + +// Add sort "Term" to declarations + rule CS:CoqSentence CSs:CoqSentences => CS ~> CSs ... + ( .Bag + => sort #token("Term", "UpperName") + ) ... + + +// Add symbol (of sort Term) and equality axiom corresponding to each definition + rule Definition ID : TYPE := TERM . + => .K + ... + + ( .Bag + => symbol CoqIdentToSymbol(ID)(.Sorts) : #token("Term", "UpperName") + axiom getFreshGlobalAxiomName() : \equals(CoqIdentToSymbol(ID), CoqTermToPattern(TERM)) + ) ... + + + ( .Bag => + + !N:ClaimName + true:Bool + .K + \type(CoqIdentToSymbol(ID), CoqTermToPattern(TYPE)) + typecheck + success + .Bag + .K + + ) + ... + + + +// Translate inductive cases + rule Inductive ID BINDERs : TERM := .CoqIndCases . + => .K + ... + + ( .Bag + => symbol CoqIdentToSymbol(ID)(.Sorts) : #token("Term", "UpperName") + ) ... + + + rule Inductive ID BINDERs : TERM := (IDC BINDERCs : TERMC) | CASEs . + => Inductive ID BINDERs : TERM := CASEs . + ... + + ( .Bag + => symbol CoqIdentToSymbol(IDC)(.Sorts) : #token("Term", "UpperName") + axiom getFreshGlobalAxiomName() : \type(CoqIdentToSymbol(IDC)(.Patterns), CoqTermToPattern(TERMC)) + ) ... + + +// Converting Term to Pattern + syntax Pattern ::= CoqTermToPattern(CoqTerm) [function] + rule CoqTermToPattern(UN:UpperName) => CoqIdentToSymbol(UN) + rule CoqTermToPattern(LN:LowerName) => CoqIdentToSymbol(LN) + rule CoqTermToPattern(#token("Prop", "CoqSort")) => #token("Term", "UpperName") + rule CoqTermToPattern(fun BINDERs => TERM) => \lambda { CoqBindersToPatterns(BINDERs) } CoqTermToPattern(TERM) + rule CoqTermToPattern(forall BINDERs, TERM) => \pi { CoqBindersToPatterns(BINDERs) } CoqTermToPattern(TERM) + rule CoqTermToPattern(match Ts return P with EQs end) => CoqTermToPattern(match Ts with EQs end) + rule CoqTermToPattern(match Ts with .CoqEquations end) => \bottom() + rule CoqTermToPattern(match Ts with (| MP:CoqMultPattern => TM:CoqTerm) | EQs end) + => CoqTermToPattern(match Ts with (MP:CoqMultPattern => TM:CoqTerm) | EQs end) + rule CoqTermToPattern(match Ts with (MP:CoqMultPattern => TM:CoqTerm) | EQs end) => + \or( #flattenOrs( + \or( \exists { CoqMultPatternToBinders(MP) } + \and( #equals(CoqMatchItemsToPatterns(Ts), CoqMultPatternToPatterns(MP)) + ++Patterns + CoqTermToPattern(TM) + ) + ++Patterns + CoqTermToPattern(match Ts with EQs end) + ), .Patterns)) + rule CoqTermToPattern(TM:CoqTerm ARG) => CoqTermToPattern(TM)(CoqArgToPatterns(ARG)) + rule CoqTermToPattern(fix ID BINDERs ANN:CoqAnnotation : TY := TM) => CoqTermToPattern(fix ID BINDERs : TY := TM) + rule CoqTermToPattern(fix ID BINDERs : TY := TM) => \mu { # CoqNameToVariableName(ID) } CoqTermToPattern(fun BINDERs => TM) + rule CoqTermToPattern(@ QID:CoqQualID TM:CoqTerm) => CoqIdentToSymbol(QID)(CoqTermToPattern(TM)) + // TODO: incorporate qualfied name + rule CoqTermToPattern(QID:CoqQualID . ID:CoqIdent) => CoqIdentToSymbol(ID) + // TODO: do we need to do anything with the type here? + rule CoqTermToPattern((TM:CoqTerm : TY:CoqTerm):CoqTerm) => CoqTermToPattern(TM) + + syntax Patterns ::= CoqArgToPatterns(CoqArg) [function] + rule CoqArgToPatterns(ARG1 ARG2) => CoqArgToPatterns(ARG1) ++Patterns CoqArgToPatterns(ARG2) + rule CoqArgToPatterns(TM:CoqTerm) => CoqTermToPattern(TM), .Patterns + [owise] + + syntax Patterns ::= CoqMatchItemsToPatterns(CoqMatchItems) [function] + syntax Pattern ::= CoqMatchItemToPattern(CoqMatchItem) [function] + rule CoqMatchItemsToPatterns(.CoqMatchItems) => .Patterns + rule CoqMatchItemsToPatterns(MI:CoqMatchItem, MIs) => CoqMatchItemToPattern(MI), .Patterns + + rule CoqMatchItemToPattern(MI:CoqTerm) => CoqTermToPattern(MI) + // TODO: is this right? + rule CoqMatchItemToPattern(MI:CoqTerm as N:CoqName) => CoqTermToPattern(MI) + + syntax Patterns ::= #equals(Patterns, Patterns) [function] + rule #equals(.Patterns, .Patterns) => .Patterns + rule #equals((P1, Ps1), (P2, Ps2)) => \equals(P1, P2), #equals(Ps1, Ps2) + + syntax Pattern ::= CoqPatternToPattern(CoqPattern) [function] + syntax Patterns ::= CoqPatternToPatterns(CoqPattern) [function] + syntax Patterns ::= CoqMultPatternToPatterns(CoqMultPattern) [function] + rule CoqMultPatternToPatterns(.CoqMultPattern) => .Patterns + rule CoqMultPatternToPatterns(MP, MPs) => CoqPatternToPattern(MP), CoqMultPatternToPatterns(MPs) + + rule CoqPatternToPattern(ID:CoqQualID) => CoqIdentToSymbol(ID) + syntax Symbol ::= #stuck() [function] + rule CoqPatternToPattern(ID:CoqQualID P:CoqPattern) => CoqIdentToSymbol(ID)(CoqPatternToPatterns(P)) + rule CoqPatternToPatterns(ID:CoqQualID) => CoqIdentToSymbol(ID), .Patterns + rule CoqPatternToPatterns(ID:CoqQualID P:CoqPattern) => CoqIdentToSymbol(ID) ++Patterns CoqPatternToPatterns(P) + rule CoqPatternToPatterns(U:Underscore P:CoqPattern) => !S:Symbol ++Patterns CoqPatternToPatterns(P) + +// Get binders from MultPattern + syntax Patterns ::= CoqMultPatternToBinders(CoqMultPattern) [function] + syntax Patterns ::= CoqPatternToBinders(CoqMultPattern) [function] + rule CoqMultPatternToBinders(ID:CoqQualID) => .Patterns + rule CoqMultPatternToBinders(ID:CoqQualID P:CoqPattern) => CoqPatternToBinders(P) + rule CoqPatternToBinders(ID:CoqQualID) => CoqIdentToSymbol(ID), .Patterns + rule CoqPatternToBinders(ID:CoqQualID P:CoqPattern) => CoqIdentToSymbol(ID), CoqPatternToBinders(P) + rule CoqPatternToBinders(U:Underscore P:CoqPattern) => !S:Symbol, CoqPatternToBinders(P) + + syntax Patterns ::= CoqBindersToPatterns(CoqBinders) [function] + rule CoqBindersToPatterns(.CoqBinders) => .Patterns + rule CoqBindersToPatterns(BINDER BINDERs:CoqBinders) => + CoqBinderToPatterns(BINDER) ++Patterns CoqBindersToPatterns(BINDERs) + + syntax Patterns ::= CoqBinderToPatterns(CoqBinder) [function] + rule CoqBinderToPatterns(NAME:CoqName) => CoqNameToVariableName(NAME) { #token("Term", "UpperName") } + rule CoqBinderToPatterns((.CoqNames : TYPE:CoqTerm)) => .Patterns + rule CoqBinderToPatterns(((NAME:CoqName NAMES:CoqNames) : TYPE:CoqTerm)) => CoqNameToVariableName(NAME) { #token("Term", "UpperName") }, CoqBinderToPatterns((NAMES : TYPE)) +``` + +```k +endmodule +``` diff --git a/prover/ext/k b/prover/ext/k index 0d2819ac8..8ebd956aa 160000 --- a/prover/ext/k +++ b/prover/ext/k @@ -1 +1 @@ -Subproject commit 0d2819ac873a6c9a448de4da3060b1ba1e682bb2 +Subproject commit 8ebd956aa1e344ed1d2e0ce15b22b251435839c3 diff --git a/prover/lang/coq-lang.md b/prover/lang/coq-lang.md new file mode 100644 index 000000000..275688611 --- /dev/null +++ b/prover/lang/coq-lang.md @@ -0,0 +1,125 @@ +```k +module COQ-SYNTAX + imports TOKENS-SYNTAX + imports COQ +endmodule + +module COQ + imports INT-SYNTAX + imports BOOL-SYNTAX + imports STRING + imports KORE-HELPERS + +// Identifiers + syntax CoqIdent ::= LowerName + | UpperName + syntax CoqQualID ::= CoqIdent + | CoqQualID "." CoqIdent + | Underscore + syntax CoqName ::= CoqIdent + | Underscore + syntax CoqNames ::= List{CoqName, ""} [klabel(CoqNames)] + +// Sorts + syntax CoqSort ::= "SProp" [token] + | "Prop" [token] + // | "Set" [token] + | "Type" [token] + +// Seralize to String: + syntax String ::= CoqNameToString(CoqName) [function, functional, hook(STRING.token2string)] + +// Sort conversions + syntax Symbol ::= CoqIdentToSymbol(CoqIdent) [function] + rule CoqIdentToSymbol(IDENT:UpperName) => IDENT + rule CoqIdentToSymbol(IDENT:LowerName) => IDENT + + syntax Symbol ::= CoqQualIDToSymbol(CoqQualID) [function] + rule CoqQualIDToSymbol(ID:CoqIdent) => CoqIdentToSymbol(ID) + + syntax VariableName ::= CoqNameToVariableName(CoqName) [function] + rule CoqNameToVariableName(NAME) => StringToVariableName(CoqNameToString(NAME)) + + syntax Sorts ::= CoqNamesToSorts(CoqNames) [function] + rule CoqNamesToSorts(.CoqNames) => .Sorts + rule CoqNamesToSorts(NAME:CoqName NAMEs) => StringToSort("Term"), CoqNamesToSorts(NAMEs) + +// Terms + syntax CoqTerm ::= "fun" CoqBinders "=>" CoqTerm + | "fix" CoqFixBodies + | "cofix" CoqCofixBodies + | "let" CoqIdent ":=" CoqTerm "in" CoqTerm + | "let" CoqIdent CoqBinders ":" CoqTerm ":=" CoqTerm "in" CoqTerm + | "@" CoqQualID CoqTerm + | "match" CoqMatchItems "with" CoqEquations "end" + | "match" CoqMatchItems CoqReturnType "with" CoqEquations "end" + | CoqTerm ":" CoqTerm + > CoqTerm CoqArg [right] + | CoqQualID + | CoqSort + | Int + | Underscore + > "forall" CoqBinders "," CoqTerm + > "(" CoqTerm ")" [bracket] + + syntax CoqBinder ::= CoqName + | "(" CoqNames ":" CoqTerm ")" + syntax CoqBinders ::= List{CoqBinder, ""} [klabel(CoqBinders)] + + syntax CoqArg ::= CoqArg CoqArg + | "(" CoqIdent ":=" CoqTerm ")" + > CoqTerm + syntax CoqTerms ::= List{CoqTerm, ""} [klabel(CoqTerms)] + + syntax CoqFixBody ::= CoqIdent CoqBinders ":" CoqTerm ":=" CoqTerm + | CoqIdent CoqBinders CoqAnnotation ":" CoqTerm ":=" CoqTerm + syntax CoqFixBodyList ::= List{CoqFixBody, "with"} + syntax CoqFixBodies ::= CoqFixBody + | CoqFixBody CoqFixBodyList "for" CoqIdent + syntax CoqAnnotation ::= "{" "struct" CoqIdent "}" + + syntax CoqCofixBody ::= CoqIdent CoqBinders ":" CoqTerm ":=" CoqTerm + syntax CoqCofixBodyList ::= List{CoqCofixBody, "with"} + syntax CoqCofixBodies ::= CoqCofixBody + | CoqCofixBody CoqCofixBodyList "for" CoqIdent + + syntax CoqMatchItem ::= CoqTerm + | CoqTerm "as" CoqName + syntax CoqMatchItems ::= List{CoqMatchItem, ","} [klabel(CoqMatchItems)] + + syntax CoqReturnType ::= "return" CoqTerm + + syntax CoqEquation ::= CoqMultPattern "=>" CoqTerm + | "|" CoqMultPattern "=>" CoqTerm + syntax CoqEquations ::= List{CoqEquation, "|"} [klabel(CoqEquations)] + + syntax CoqPattern ::= CoqQualID CoqPattern + | "@" CoqQualID CoqPattern + // | CoqPattern CoqPattern + | CoqPattern "as" CoqIdent + | CoqPattern "%" CoqIdent + | CoqQualID + | Underscore [prefer] + | Int + + syntax CoqMultPattern ::= List{CoqPattern, ","} [klabel(CoqMultPattern)] + syntax CoqPatterns ::= NeList{CoqPattern, ""} [klabel(CoqPatterns)] + +// Vernacular + syntax CoqSentence ::= CoqDefinition + | CoqInductive + // | CoqCoInductive + syntax CoqSentences ::= List{CoqSentence, ""} [klabel(CoqSentences), format(%1%n%2 %3)] + syntax CoqDefinition ::= "Definition" CoqIdent ":" CoqTerm ":=" CoqTerm "." +// | "Definition" CoqIdent CoqBinders ":" CoqTerm ":=" CoqTerm "." + + syntax CoqInductive ::= "Inductive" CoqIndBody "." + syntax CoqIndBody ::= CoqIdent CoqBinders ":" CoqTerm ":=" CoqIndCases + syntax CoqIndCase ::= CoqIdent CoqBinders ":" CoqTerm + syntax CoqIndCases ::= List{CoqIndCase, "|"} [klabel(CoqIndCases)] + +``` + +```k +endmodule +``` diff --git a/prover/lang/kore-lang.md b/prover/lang/kore-lang.md index 6bf8c1062..43aae4bd6 100644 --- a/prover/lang/kore-lang.md +++ b/prover/lang/kore-lang.md @@ -9,6 +9,7 @@ module TOKENS syntax ColonName syntax PipeQID syntax Decimal + syntax Underscore // Abstract syntax Symbol ::= UpperName | LowerName @@ -118,6 +119,7 @@ module TOKENS-SYNTAX syntax ColonName ::= r":[a-z][A-Za-z\\-0-9'\\#\\_]*" [token, autoReject] syntax Decimal ::= r"[0-9][0-9]*\\.[0-9][0-9]*" [token, autoreject] | "2.0" [token] + syntax Underscore ::= "_" [token] endmodule module KORE @@ -135,11 +137,13 @@ is to be used for generating fresh variables. *The second variety must be used only in this scenario*. ```k - syntax Variable ::= VariableName "{" Sort "}" [klabel(sortedVariable)] + syntax Variable ::= VariableName "{" Sort "}" [klabel(sortedVariable)] + syntax SetVariable ::= "#" VariableName [klabel(setVariable)] syntax Pattern ::= Int | Variable + | SetVariable | Symbol - | Symbol "(" Patterns ")" [klabel(apply)] + | Pattern "(" Patterns ")" [klabel(apply)] | "\\top" "(" ")" [klabel(top)] | "\\bottom" "(" ")" [klabel(bottom)] @@ -153,6 +157,9 @@ only in this scenario*. | "\\exists" "{" Patterns "}" Pattern [klabel(exists)] | "\\forall" "{" Patterns "}" Pattern [klabel(forall)] + | "\\mu" "{" Patterns "}" Pattern [klabel(mu)] + | "\\nu" "{" Patterns "}" Pattern [klabel(nu)] + /* Sugar for \iff, \mu and application */ | "\\iff-lfp" "(" Pattern "," Pattern ")" [klabel(ifflfp)] @@ -162,6 +169,11 @@ only in this scenario*. | "heap" "(" Sort "," Sort ")" // Location, Data | "\\hole" "(" ")" [klabel(Phole)] + // for Coq translation + | "\\lambda" "{" Patterns "}" Pattern [klabel(lambda)] + | "\\pi" "{" Patterns "}" Pattern [klabel(pi)] + | "\\type" "(" Pattern "," Pattern ")" [klabel(type)] + rule \top() => \and(.Patterns) [anywhere] rule \bottom() => \or(.Patterns) [anywhere] @@ -207,6 +219,9 @@ module KORE-HELPERS syntax String ::= SortToString(Sort) [function, functional, hook(STRING.token2string)] syntax String ::= SymbolToString(Symbol) [function, functional, hook(STRING.token2string)] syntax LowerName ::= StringToSymbol(String) [function, functional, hook(STRING.string2token)] + syntax UpperName ::= StringToSort(String) [function, functional, hook(STRING.string2token)] + + syntax VariableName ::= StringToVariableName(String) [function, functional, hook(STRING.string2token)] syntax Symbol ::= parameterizedSymbol(Symbol, Sort) [function] rule parameterizedSymbol(SYMBOL, SORT) => StringToSymbol(SymbolToString(SYMBOL) +String "_" +String SortToString(SORT)) @@ -434,6 +449,10 @@ and values, passed to K's substitute. syntax Patterns ::= makeFreshVariables(Patterns) [function] rule makeFreshVariables(P, REST) => !V1:VariableName { getReturnSort(P) }, makeFreshVariables(REST) rule makeFreshVariables(.Patterns) => .Patterns + + syntax Symbol ::= String2Symbol(String) [function, functional, hook(STRING.string2token)] + syntax Symbol ::= freshSymbol(Int) [freshGenerator, function, functional] + rule freshSymbol(I:Int) => String2Symbol("F" +String Int2String(I)) ``` ```k diff --git a/prover/lang/smt-lang.md b/prover/lang/smt-lang.md index e1a092d2a..f999a7d4a 100644 --- a/prover/lang/smt-lang.md +++ b/prover/lang/smt-lang.md @@ -103,6 +103,7 @@ module SMTLIB2-HELPERS imports K-IO imports SMTLIB2 imports PROVER-CORE-SYNTAX + imports KORE-HELPERS syntax SMTLIB2AttributeValue ::= CheckSATResult syntax CheckSATResult ::= "error" "(" K ")" @@ -116,7 +117,6 @@ module SMTLIB2-HELPERS // Converting between Sorts: - syntax VariableName ::= StringToVariableName(String) [function, functional, hook(STRING.string2token)] syntax VariableName ::= SMTLIB2SimpleSymbolToVariableName(SMTLIB2SimpleSymbol) [function] rule SMTLIB2SimpleSymbolToVariableName(SYMBOL) => StringToVariableName("V" +String SMTLIB2SimpleSymbolToString(SYMBOL)) diff --git a/prover/prover b/prover/prover index 4ba575218..031dd38e4 100755 --- a/prover/prover +++ b/prover/prover @@ -18,6 +18,12 @@ KDefinition( proj , directory = proj.builddir('defn/prover-smt') , krun_flags = '--interpret' ) +KDefinition( proj + , alias = 'prover-coq' + , backend = 'ocaml' + , directory = proj.builddir('defn/prover-coq') + , krun_flags = '--interpret' + ) KDefinition( proj , alias = 'test-driver' , backend = 'llvm' diff --git a/prover/prover.md b/prover/prover.md index 8b928190d..834c3b44e 100644 --- a/prover/prover.md +++ b/prover/prover.md @@ -1,5 +1,7 @@ ```k requires "lang/kore-lang.k" +requires "lang/coq-lang.k" +requires "drivers/coq-driver.k" requires "drivers/smt-driver.k" requires "drivers/kore-driver.k" requires "drivers/base.k" @@ -11,6 +13,7 @@ requires "strategies/intros.k" requires "strategies/knaster-tarski.k" requires "strategies/matching.k" requires "strategies/search-bound.k" +requires "strategies/typecheck.k" requires "strategies/simplification.k" requires "strategies/smt.k" requires "strategies/reflexivity.k" @@ -68,6 +71,7 @@ module STRATEGIES-EXPORTED-SYNTAX "in:" AxiomName "," "vars:" VariableNames "," "with:" Patterns ")" + | "typecheck" syntax RewriteDirection ::= "->" | "<-" diff --git a/prover/strategies/typecheck.md b/prover/strategies/typecheck.md new file mode 100644 index 000000000..73604058d --- /dev/null +++ b/prover/strategies/typecheck.md @@ -0,0 +1,34 @@ +# typecheck - for Coq terms + +```k +module STRATEGY-TYPECHECK + imports PROVER-CORE + imports STRATEGIES-EXPORTED-SYNTAX + + rule + \type(ID:Symbol, TYPE) => \type(TERM, TYPE) + typecheck ... + axiom AXID : \equals(ID, TERM) + + rule + \type(TYPE, TYPE) + typecheck => success ... + + // axiom: (Term, Term, Term) + // TODO: use Term as constant + rule + \type(\pi { VARs } TYPE, #token("Term", "UpperName")) + typecheck => success ... + + // lambda + rule + \type(\lambda { VARs1 } TERM, \pi { VARs2 } TYPE) => \type(TERM, TYPE) + typecheck ... + + // application + rule + \type(TERM1 ( TERM2 ), TYPE) => \type(TERM1, \pi { !X:VariableName { #token("Term", "UpperName") } } TYPE) + typecheck ... + +endmodule +``` diff --git a/prover/t/coq-tests/Logic.v b/prover/t/coq-tests/Logic.v new file mode 100644 index 000000000..42c98d955 --- /dev/null +++ b/prover/t/coq-tests/Logic.v @@ -0,0 +1,46 @@ +// Inductive True : Prop := +// I : True . + +// Inductive False : Prop := . + +// Inductive nat : Prop := +// Z : nat +// | S : (forall (x : nat), nat) . + +Definition not : (forall (x : Prop), Prop) := + fun (A: Prop) => (forall (x : A), False) . + +Definition iff : (forall (x : Prop), (forall (y : Prop), Prop)) := + (and (forall (x : A), B)) (forall (y : B), A) . + +Definition IF_then_else : (forall (x : Prop), (forall (y : Prop), (forall (z : Prop), Prop))) := + (or (and P Q)) (and (not P) R) . + +// Inductive ex1 (A : Type) (P : forall (x : A), Prop) : Prop := +// ex_intro1 : forall (x : A), forall (y : (P x)), ex1 A P . + +// Inductive ex2 (A : Type) (P : forall (x : A), Prop) : Prop := +// ex_intro2 : forall (x : A), forall (y : (P x)), ex2 P . + +// // Inductive ex3 (A : Type) (P : forall (x : A), Prop) : Prop := +// // ex_intro3 : forall (x : A), forall (y : (P x)), ex3 (A:=A) P . + +// Inductive ex4 (A : Type) (P : forall (x : A), Prop) : Prop := +// ex_intro4 : forall (x : A), forall (y : (P x)), @ ex4 A P . + +Definition AndComm : (forall (A B : Prop), (forall (c : and A B), and B A)) := + fun (A B : Prop) (H : and A B) => + match H with + conj H0 H1 => conj H1 H0 + end + . + +// // Inductive and (A B : Prop) : Prop := +// // conj : forall (x : A), forall (y : B), and A B . +// // +// // Inductive or (A B : Prop) : Prop := +// // or_introl : forall (x : A), or A B +// // | or_intror : forall (y : A), or A B . +// // +// // Inductive eq (A:Type) (x:A) : forall (_:A), Prop := +// // eq_refl : @ eq A x x . diff --git a/prover/t/coq-tests/Logic.v.expected b/prover/t/coq-tests/Logic.v.expected new file mode 100644 index 000000000..e70bbc419 --- /dev/null +++ b/prover/t/coq-tests/Logic.v.expected @@ -0,0 +1,84 @@ + + + .CoqSentences + + + 1 + + + .GoalCellSet + + + + axiom \equals ( AndComm , \lambda { A { Term } , B { Term } , H { Term } , .Patterns } \or ( \exists { H0 , H1 , .Patterns } \and ( \equals ( H , conj ( H0 , H1 , .Patterns ) ) , conj ( H1 , H0 , .Patterns ) , .Patterns ) , .Patterns ) ) + + axiom \equals ( IF_then_else , or ( and , P , Q , .Patterns ) ( and , not , P , R , .Patterns ) ) + + axiom \equals ( iff , and ( \forall { x { Term } , .Patterns } B , .Patterns ) ( \forall { y { Term } , .Patterns } A , .Patterns ) ) + + axiom \equals ( not , \lambda { A { Term } , .Patterns } \forall { x { Term } , .Patterns } False ) + + axiom \type ( I ( .Patterns ) , True ) + + axiom \type ( S ( .Patterns ) , nat ( - , > , nat , .Patterns ) ) + + axiom \type ( Z ( .Patterns ) , nat ) + + axiom \type ( conj ( .Patterns ) , \forall { x { Term } , .Patterns } \forall { y { Term } , .Patterns } ( and ( A , B , .Patterns ) ) ) + + axiom \type ( ex_intro1 ( .Patterns ) , \forall { x { Term } , .Patterns } \forall { y { Term } , .Patterns } ( ex1 ( A , P , .Patterns ) ) ) + + axiom \type ( ex_intro2 ( .Patterns ) , \forall { x { Term } , .Patterns } \forall { y { Term } , .Patterns } ( ex2 ( P , .Patterns ) ) ) + + axiom \type ( ex_intro4 ( .Patterns ) , \forall { x { Term } , .Patterns } \forall { y { Term } , .Patterns } ( ex4 ( A , .Patterns ) ( P , .Patterns ) ) ) + + axiom \type ( or_introl ( .Patterns ) , \forall { x { Term } , .Patterns } ( or ( A , B , .Patterns ) ) ) + + axiom \type ( or_intror ( .Patterns ) , \forall { y { Term } , .Patterns } ( or ( A , B , .Patterns ) ) ) + + sort Term + + symbol AndComm ( .Sorts ) : Term + + symbol False ( .Sorts ) : Term + + symbol I ( .Sorts ) : Term + + symbol IF_then_else ( .Sorts ) : Term + + symbol S ( .Sorts ) : Term + + symbol True ( .Sorts ) : Term + + symbol Z ( .Sorts ) : Term + + symbol and ( .Sorts ) : Term + + symbol conj ( .Sorts ) : Term + + symbol ex1 ( .Sorts ) : Term + + symbol ex2 ( .Sorts ) : Term + + symbol ex4 ( .Sorts ) : Term + + symbol ex_intro1 ( .Sorts ) : Term + + symbol ex_intro2 ( .Sorts ) : Term + + symbol ex_intro4 ( .Sorts ) : Term + + symbol iff ( .Sorts ) : Term + + symbol nat ( .Sorts ) : Term + + symbol not ( .Sorts ) : Term + + symbol or ( .Sorts ) : Term + + symbol or_introl ( .Sorts ) : Term + + symbol or_intror ( .Sorts ) : Term + + + diff --git a/prover/t/coq-tests/ml_coq_verbose.v b/prover/t/coq-tests/ml_coq_verbose.v new file mode 100644 index 000000000..875648b29 --- /dev/null +++ b/prover/t/coq-tests/ml_coq_verbose.v @@ -0,0 +1,75 @@ +Inductive and' (A B : Prop) : Prop := + conj' : forall (_ : A) (_ : B), and' A B . + +Definition and'_ind_verbose : forall (A B P : Prop) (_ : forall (_ : A) (_ : B), P)(_ : and' A B), P := +fun (A B P : Prop) (f : forall (_ : A) (_ : B), P) (a : and' A B) => +match a return P with +| conj' _ _ x x0 => f x x0 +end . + +Definition and'_rec_verbose : forall (A B : Prop) (P : Set) (_ : forall (_ : A) (_ : B), P)(_ : and' A B), P := +fun (A B : Prop) (P : Set) => and'_rect A B P . + +Definition and'_rect_verbose : forall (A B : Prop) (P : Type) (_ : forall (_ : A) (_ : B), P)(_ : and' A B), P := +fun (A B : Prop) (P : Type) (f : forall (_ : A) (_ : B), P) + (a : and' A B) => +match a return P with +| conj' _ _ x x0 => f x x0 +end . + +Inductive ex1 (A : Type) (P : forall (_ : A), Prop) : Prop := + ex_intro1 : forall (x : A) (_ : P x), ex1 A P . + +Definition ex1_ind_verbose : forall (A : Type) (P : forall (_ : A), Prop)(P0 : Prop) (_ : forall (x : A) (_ : P x), P0)(_ : ex1 A P), P0 := +fun (A : Type) (P : forall (_ : A), Prop) (P0 : Prop) + (f : forall (x : A) (_ : P x), P0) (e : ex1 A P) => +match e return P0 with +| ex_intro1 _ _ x x0 => f x x0 +end . + +Definition False_ind : forall (P : Prop) (_ : False), P := +fun (P : Prop) (f : False) => match f return P with + end . + +Definition add_ind' : forall (_ : nat) (_ : nat), nat := +fix add (n m : nat) {struct n} : nat := + match n return nat with + | O => m + | S p => S (add p m) + end . + +Definition nat_ind' : forall (P : forall (_ : nat), Prop) (_ : P O)(_ : forall (n : nat) (_ : P n), P (S n))(n : nat), P n := +fun (P : forall (_ : nat), Prop) (f : P O) + (f0 : forall (n : nat) (_ : P n), P (S n)) => +fix F (n : nat) : P n := + match n as n0 return (P n0) with + | O => f + | S n0 => f0 n0 (F n0) + end . + +Definition AddZero : forall (n : nat), @eq nat (Nat.add n O) n := +fun (n : nat) => +nat_ind (fun (n0 : nat) => @eq nat (Nat.add n0 O) n0) + (@eq_refl nat O : @eq nat (Nat.add O O) O) + (fun (n0 : nat) (IHn : @eq nat (Nat.add n0 O) n0) => + @eq_ind_r nat n0 (fun (n1 : nat) => @eq nat (S n1) (S n0)) + (@eq_refl nat (S n0)) (Nat.add n0 O) IHn + : + @eq nat (Nat.add (S n0) O) (S n0)) n . + +Definition AndComm : forall (A B : Prop) (_ : and A B), and B A := +fun (A B : Prop) (H : and A B) => +match H return (and B A) with +| conj H0 H1 => @conj B A H1 H0 +end . + +Definition AndComm' : forall (A B : Prop) (_ : and A B), and B A := +fun (A B : Prop) (H : and A B) => +match H return (and B A) with +| conj H0 H1 => @conj B A H1 H0 +end . + +Definition AndComm'' : forall (A B : Prop) (_ : and A B), and B A := +AndComm' . + +Definition test : forall (_ : Prop), Prop := fun (_ : Prop) => True . diff --git a/prover/t/coq-tests/nat_ind.v b/prover/t/coq-tests/nat_ind.v new file mode 100644 index 000000000..f3c9036b3 --- /dev/null +++ b/prover/t/coq-tests/nat_ind.v @@ -0,0 +1,22 @@ +Inductive nat : Type := Z : nat | S : forall (x : nat), nat . + +// symbol nat() : Term +// symbol Z() : Term +// symbol S() : Term + +// axiom \type(Z(), nat()) + +Definition nat_ind : (forall (P : (forall (x : nat), Prop)), + (forall (y : P 0), + (forall (l : (forall (n : nat), + (forall (y : P n), P (S n)))), + (forall (n : nat), P n)))) := +fun (P : (forall (n : nat), Prop)) (f : P 0) (f0 : forall (n : nat), (forall (x : P n), P (S n))) => +fix F (n : nat) := match n with + Z => f + | S n0 => f0 n0 (F n0) + end +. + +// forall P : nat -> Prop, P 0 -> (forall n : nat, P n -> P (S n)) -> forall n : nat, P n +// tr(fun ... ) \mu { F {{ Term }} } tr( fun n => match ) ... ) diff --git a/prover/t/coq-tests/nat_ind.v.expected b/prover/t/coq-tests/nat_ind.v.expected new file mode 100644 index 000000000..d64c4c59b --- /dev/null +++ b/prover/t/coq-tests/nat_ind.v.expected @@ -0,0 +1,30 @@ + + + .CoqSentences + + + 1 + + + .GoalCellSet + + + + axiom \equals ( nat_ind , \lambda { P { Term } , f { Term } , f0 { Term } , .Patterns } \mu { F {{ Term }} , .Patterns } \lambda { n { Term } , .Patterns } \or ( \exists { .Patterns } \and ( \equals ( n , Z ) , f , .Patterns ) , \exists { n0 , .Patterns } \and ( \equals ( n , S ( n0 , .Patterns ) ) , f0 ( n0 , F , n0 , .Patterns ) , .Patterns ) , .Patterns ) ) + + axiom \type ( S ( .Patterns ) , \forall { x { Term } , .Patterns } nat ) + + axiom \type ( Z ( .Patterns ) , nat ) + + sort Term + + symbol S ( .Sorts ) : Term + + symbol Z ( .Sorts ) : Term + + symbol nat ( .Sorts ) : Term + + symbol nat_ind ( .Sorts ) : Term + + +