From 1c359901006c1bde7307bb07d666dbd9d7ebe72d Mon Sep 17 00:00:00 2001 From: Aaron Tomb Date: Fri, 31 Oct 2025 15:17:46 -0700 Subject: [PATCH 01/22] Rearrange verso docs Add empty doc for language definition, and rename DDM user manual docs. --- docs/ddm/{StrataDoc.lean => DDMDoc.lean} | 2 +- .../{StrataDocMain.lean => DDMDocMain.lean} | 4 +-- docs/ddm/README.md | 36 +++++++++++++------ docs/ddm/generate.sh | 3 +- docs/ddm/lakefile.toml | 15 +++++--- 5 files changed, 41 insertions(+), 19 deletions(-) rename docs/ddm/{StrataDoc.lean => DDMDoc.lean} (99%) rename docs/ddm/{StrataDocMain.lean => DDMDocMain.lean} (76%) diff --git a/docs/ddm/StrataDoc.lean b/docs/ddm/DDMDoc.lean similarity index 99% rename from docs/ddm/StrataDoc.lean rename to docs/ddm/DDMDoc.lean index 376842f66..20cb2ecd0 100644 --- a/docs/ddm/StrataDoc.lean +++ b/docs/ddm/DDMDoc.lean @@ -18,7 +18,7 @@ set_option pp.rawOnError true #doc (Manual) "The Strata DDM Manual" => %%% authors := ["Joe Hendrix"] -shortTitle := "Strata" +shortTitle := "Strata DDM" %%% The Strata Dialect Definition Mechanism (DDM) is a set of tools for defining diff --git a/docs/ddm/StrataDocMain.lean b/docs/ddm/DDMDocMain.lean similarity index 76% rename from docs/ddm/StrataDocMain.lean rename to docs/ddm/DDMDocMain.lean index 5d5786f7b..2c2ed861f 100644 --- a/docs/ddm/StrataDocMain.lean +++ b/docs/ddm/DDMDocMain.lean @@ -6,7 +6,7 @@ -import StrataDoc +import DDMDoc open Verso.Genre.Manual (Config manualMain) def config : Config where @@ -15,4 +15,4 @@ def config : Config where emitHtmlMulti := false htmlDepth := 2 -def main := manualMain (%doc StrataDoc) (config := config) +def main := manualMain (%doc DDMDoc) (config := config) diff --git a/docs/ddm/README.md b/docs/ddm/README.md index 10e48290e..05c34a620 100644 --- a/docs/ddm/README.md +++ b/docs/ddm/README.md @@ -1,23 +1,37 @@ -# DDM User Manual - -Strata dialects are defined in their own domain-specific language that -can be embededed in Lean or used externally. +# Strata documents created in Verso -This Verso package provides HTML documentation of the Strata dialect -definition language. The documentation can be generated by the command +This Verso package provides documentation of the core Strata language +and the Dialect Definition Mechanism (DDM). The documentation can be +generated by the command ``` -lake exe docs +./generate.sh ``` -The output will be written to `_out/single-page`. Links in Verso +The output will be written to `_out/{document name}`. Links in Verso documentation do not work if the file is opened in the browser directly. Instead, we recommend launching a local web server to view the -documentation. -If Python is available, then this can be done with the command +documentation. If Python is available, then this can be done with the +command + +``` +python3 -m http.server 1080 -d _out/langdef/html-single +``` + +or ``` -python -m http.server 1080 -d _out/html-single +python3 -m http.server 1080 -d _out/ddm/html-single ``` This will print out a URL that can be opened in a browser to view the documentation. + +# Strata Language Definition + +TODO + +# DDM User Manual + +New Strata dialects are defined in their own domain-specific language +that can be embededed in Lean or imported from external files. This +document provides a guide to using that DSL. diff --git a/docs/ddm/generate.sh b/docs/ddm/generate.sh index f458bbe3d..c611570fe 100755 --- a/docs/ddm/generate.sh +++ b/docs/ddm/generate.sh @@ -1,3 +1,4 @@ set -ex -lake exe docs --with-html-single --output _out/html +lake exe ddm --with-html-single --output _out/ddm +lake exe langdef --with-html-single --output _out/langdef diff --git a/docs/ddm/lakefile.toml b/docs/ddm/lakefile.toml index ed849e325..8ebe9d61e 100644 --- a/docs/ddm/lakefile.toml +++ b/docs/ddm/lakefile.toml @@ -1,5 +1,5 @@ name = "StrataDoc" -defaultTargets = ["docs"] +defaultTargets = ["ddm", "langdef"] [[require]] name = "verso" @@ -7,8 +7,15 @@ git = "https://github.com/leanprover/verso" rev = "nightly-testing" [[lean_lib]] -name = "StrataDoc" +name = "DDMDoc" + +[[lean_lib]] +name = "LangDefDoc" + +[[lean_exe]] +name = "ddm" +root = "DDMDocMain" [[lean_exe]] -name = "docs" -root = "StrataDocMain" \ No newline at end of file +name = "langdef" +root = "LangDefDocMain" From c84e0dbfed5d7a7b4bfbf818a71845e1d612aa82 Mon Sep 17 00:00:00 2001 From: Aaron Tomb Date: Fri, 31 Oct 2025 15:18:39 -0700 Subject: [PATCH 02/22] Rename ddm -> verso Now the directory contains two different Verso docs --- docs/{ddm => verso}/.gitignore | 0 docs/{ddm => verso}/DDMDoc.lean | 0 docs/{ddm => verso}/DDMDocMain.lean | 0 docs/{ddm => verso}/README.md | 0 docs/{ddm => verso}/generate.sh | 0 docs/{ddm => verso}/lake-manifest.json | 0 docs/{ddm => verso}/lakefile.toml | 0 docs/{ddm => verso}/lean-toolchain | 0 8 files changed, 0 insertions(+), 0 deletions(-) rename docs/{ddm => verso}/.gitignore (100%) rename docs/{ddm => verso}/DDMDoc.lean (100%) rename docs/{ddm => verso}/DDMDocMain.lean (100%) rename docs/{ddm => verso}/README.md (100%) rename docs/{ddm => verso}/generate.sh (100%) rename docs/{ddm => verso}/lake-manifest.json (100%) rename docs/{ddm => verso}/lakefile.toml (100%) rename docs/{ddm => verso}/lean-toolchain (100%) diff --git a/docs/ddm/.gitignore b/docs/verso/.gitignore similarity index 100% rename from docs/ddm/.gitignore rename to docs/verso/.gitignore diff --git a/docs/ddm/DDMDoc.lean b/docs/verso/DDMDoc.lean similarity index 100% rename from docs/ddm/DDMDoc.lean rename to docs/verso/DDMDoc.lean diff --git a/docs/ddm/DDMDocMain.lean b/docs/verso/DDMDocMain.lean similarity index 100% rename from docs/ddm/DDMDocMain.lean rename to docs/verso/DDMDocMain.lean diff --git a/docs/ddm/README.md b/docs/verso/README.md similarity index 100% rename from docs/ddm/README.md rename to docs/verso/README.md diff --git a/docs/ddm/generate.sh b/docs/verso/generate.sh similarity index 100% rename from docs/ddm/generate.sh rename to docs/verso/generate.sh diff --git a/docs/ddm/lake-manifest.json b/docs/verso/lake-manifest.json similarity index 100% rename from docs/ddm/lake-manifest.json rename to docs/verso/lake-manifest.json diff --git a/docs/ddm/lakefile.toml b/docs/verso/lakefile.toml similarity index 100% rename from docs/ddm/lakefile.toml rename to docs/verso/lakefile.toml diff --git a/docs/ddm/lean-toolchain b/docs/verso/lean-toolchain similarity index 100% rename from docs/ddm/lean-toolchain rename to docs/verso/lean-toolchain From 04d3553bed07dc86674957723c48dbf299ccea4b Mon Sep 17 00:00:00 2001 From: Aaron Tomb Date: Fri, 31 Oct 2025 15:19:22 -0700 Subject: [PATCH 03/22] Add missing files --- docs/verso/LangDefDoc.lean | 24 ++++++++++++++++++++++++ docs/verso/LangDefDocMain.lean | 18 ++++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 docs/verso/LangDefDoc.lean create mode 100644 docs/verso/LangDefDocMain.lean diff --git a/docs/verso/LangDefDoc.lean b/docs/verso/LangDefDoc.lean new file mode 100644 index 000000000..9f83b54f4 --- /dev/null +++ b/docs/verso/LangDefDoc.lean @@ -0,0 +1,24 @@ +/- + Copyright Strata Contributors + + SPDX-License-Identifier: Apache-2.0 OR MIT +-/ + +import VersoManual + +-- This gets access to most of the manual genre +open Verso.Genre Manual + +-- This gets access to Lean code that's in code blocks, elaborated in +-- the same process and environment as Verso +open Verso.Genre.Manual.InlineLean + +set_option pp.rawOnError true + +#doc (Manual) "The Strata Language Definition" => +%%% +authors := ["Aaron Tomb", "TODO"] +shortTitle := "Strata Language" +%%% + +TODO diff --git a/docs/verso/LangDefDocMain.lean b/docs/verso/LangDefDocMain.lean new file mode 100644 index 000000000..9423ab6d1 --- /dev/null +++ b/docs/verso/LangDefDocMain.lean @@ -0,0 +1,18 @@ +/- + Copyright Strata Contributors + + SPDX-License-Identifier: Apache-2.0 OR MIT +-/ + + + +import LangDefDoc +open Verso.Genre.Manual (Config manualMain) + +def config : Config where + emitTeX := false + emitHtmlSingle := true + emitHtmlMulti := false + htmlDepth := 2 + +def main := manualMain (%doc LangDefDoc) (config := config) From a94c6c23afb35caf01d64a384b5c033ad4d29a12 Mon Sep 17 00:00:00 2001 From: Aaron Tomb Date: Wed, 5 Nov 2025 13:23:23 -0800 Subject: [PATCH 04/22] Fix documentation build --- .github/workflows/ci.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1a72dc08f..bcb282c3c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -106,7 +106,7 @@ jobs: run: .github/scripts/checkLeanImport.sh build_doc: - name: Build Documentation + name: Build documentation runs-on: ubuntu-latest permissions: contents: read @@ -116,10 +116,10 @@ jobs: uses: leanprover/lean-action@v1 with: build-args: '--wfail' - lake-package-directory: 'docs/ddm' - - name: Build Documentation - run: lake exe docs - working-directory: docs/ddm + lake-package-directory: 'docs/verso' + - name: Build documentation + run: ./generate.sh + working-directory: docs/verso build_python: name: Build and test Python package From 9c8d1ba38bc81a0f89525ef4dde61e64bb3ca388 Mon Sep 17 00:00:00 2001 From: Aaron Tomb Date: Wed, 5 Nov 2025 13:49:47 -0800 Subject: [PATCH 05/22] Set up langdef doc to import the Strata package This allows us to write definitions in the doc that use Strata types. --- docs/verso/LangDefDoc.lean | 41 ++++++++++++++++++++++++++++++++++- docs/verso/lake-manifest.json | 7 ++++++ docs/verso/lakefile.toml | 4 ++++ 3 files changed, 51 insertions(+), 1 deletion(-) diff --git a/docs/verso/LangDefDoc.lean b/docs/verso/LangDefDoc.lean index 9f83b54f4..3195a1656 100644 --- a/docs/verso/LangDefDoc.lean +++ b/docs/verso/LangDefDoc.lean @@ -6,6 +6,14 @@ import VersoManual +import Strata.DL.Imperative.Cmd +import Strata.DL.Imperative.CmdSemantics +import Strata.DL.Imperative.Stmt +import Strata.DL.Imperative.StmtSemantics +import Strata.DL.Lambda.LExpr +open Imperative +open Lambda + -- This gets access to most of the manual genre open Verso.Genre Manual @@ -21,4 +29,35 @@ authors := ["Aaron Tomb", "TODO"] shortTitle := "Strata Language" %%% -TODO +TODO: below is an example of what including Lean code defining the semantics of +Strata might look like. + +```lean +namespace Imperative + +``` +# Small-Step Operational Semantics for Statements + +Here we define small-step operational semantics for the +`Imperative` dialect's statement constructs. + +First, we define the notion of a configuration, representing the +current execution state. A configuration consists of: +- The current statement or statements being executed +- The current store (for current variable values) +- The initial store (for evaluating Boogie's `old` operator) + +```lean +inductive Config (P : PureExpr) : Type where + | stmt : + Stmt P (Cmd P) → + SemanticStore P → + SemanticStore P → + Config P + | stmts : + List (Stmt P (Cmd P)) → + SemanticStore P → + SemanticStore P → + Config P + | terminal : SemanticStore P → SemanticStore P → Config P +``` diff --git a/docs/verso/lake-manifest.json b/docs/verso/lake-manifest.json index edaee8c6e..8571de8a5 100644 --- a/docs/verso/lake-manifest.json +++ b/docs/verso/lake-manifest.json @@ -11,6 +11,13 @@ "inputRev": "nightly-testing", "inherited": false, "configFile": "lakefile.lean"}, + {"type": "path", + "scope": "", + "name": "Strata", + "manifestFile": "lake-manifest.json", + "inherited": false, + "dir": "../..", + "configFile": "lakefile.toml"}, {"url": "https://github.com/acmepjz/md4lean", "type": "git", "subDir": null, diff --git a/docs/verso/lakefile.toml b/docs/verso/lakefile.toml index 8ebe9d61e..d19859fca 100644 --- a/docs/verso/lakefile.toml +++ b/docs/verso/lakefile.toml @@ -1,6 +1,10 @@ name = "StrataDoc" defaultTargets = ["ddm", "langdef"] +[[require]] +name = "Strata" +path = "../.." + [[require]] name = "verso" git = "https://github.com/leanprover/verso" From 41ee9596d69033f8e8ce23a1534085eb83a1b18d Mon Sep 17 00:00:00 2001 From: Aaron Tomb Date: Wed, 26 Nov 2025 14:49:04 -0800 Subject: [PATCH 06/22] Update docstrings for the Strata language ref --- Strata/DL/Imperative/Cmd.lean | 16 +++-- Strata/DL/Imperative/CmdSemantics.lean | 23 +++++-- Strata/DL/Imperative/NondetStmt.lean | 13 ++++ Strata/DL/Imperative/NondetStmtSemantics.lean | 5 +- Strata/DL/Imperative/Stmt.lean | 20 +++++- .../DL/Imperative/StmtSemanticsSmallStep.lean | 32 ++++++--- Strata/DL/Lambda/LExpr.lean | 31 +++++---- Strata/DL/Lambda/LExprTypeSpec.lean | 31 +++++++-- Strata/DL/Lambda/LTy.lean | 16 ++--- Strata/DL/Lambda/Semantics.lean | 67 ++++++++++++------- 10 files changed, 177 insertions(+), 77 deletions(-) diff --git a/Strata/DL/Imperative/Cmd.lean b/Strata/DL/Imperative/Cmd.lean index 2073321cf..e8cd07a34 100644 --- a/Strata/DL/Imperative/Cmd.lean +++ b/Strata/DL/Imperative/Cmd.lean @@ -28,19 +28,21 @@ variable declaration and assignment, and assertions and assumptions. -/ /-- -A command in the Imperative dialect +A an atomic command in the `Imperative` dialect. + +Commands generally don't involve control flow on their own, and are typically +used as a parameter to `Imperative.Stmt` or other similar types. -/ inductive Cmd (P : PureExpr) : Type where - /-- `init` defines a variable called `name` with type `ty` and - initial value `e`. -/ + /-- Define a variable called `name` with type `ty` and initial value `e`. -/ | init (name : P.Ident) (ty : P.Ty) (e : P.Expr) (md : (MetaData P) := .empty) - /-- `set` assigns `e` to a pre-existing variable `name`. -/ + /-- Assign `e` to a pre-existing variable `name`. -/ | set (name : P.Ident) (e : P.Expr) (md : (MetaData P) := .empty) - /-- `havoc` assigns a pre-existing variable `name` a random value. -/ + /-- Assign a random value to a pre-existing variable `name`. -/ | havoc (name : P.Ident) (md : (MetaData P) := .empty) - /-- `assert` checks whether condition `b` is true. -/ + /-- Check whether condition `b` is true, failing if not. -/ | assert (label : String) (b : P.Expr) (md : (MetaData P) := .empty) - /-- `assume` constrains execution by adding assumption `b`. -/ + /-- Constrain execution to the states in which `b` is true. -/ | assume (label : String) (b : P.Expr) (md : (MetaData P) := .empty) abbrev Cmds (P : PureExpr) := List (Cmd P) diff --git a/Strata/DL/Imperative/CmdSemantics.lean b/Strata/DL/Imperative/CmdSemantics.lean index 3aa6a1b77..b27bb1174 100644 --- a/Strata/DL/Imperative/CmdSemantics.lean +++ b/Strata/DL/Imperative/CmdSemantics.lean @@ -235,10 +235,15 @@ def WellFormedSemanticEvalVar {P : PureExpr} [HasFvar P] (δ : SemanticEval P) def WellFormedSemanticEvalExprCongr {P : PureExpr} [HasVarsPure P P.Expr] (δ : SemanticEval P) : Prop := ∀ e σ₀ σ σ', (∀ x ∈ HasVarsPure.getVars e, σ x = σ' x) → δ σ₀ σ e = δ σ₀ σ' e + /-- -An inductive rule for state update. +Abstract variable update. + +This does not specify how `σ` is represented, only what it maps each variable to. -/ inductive UpdateState : SemanticStore P → P.Ident → P.Expr → SemanticStore P → Prop where + /-- The state `σ'` is be equivalent to `σ` except at `x`, where it maps to + `v`. Requires that `x` mapped to something beforehand. -/ | update : σ x = .some v' → σ' x = .some v → @@ -247,9 +252,13 @@ inductive UpdateState : SemanticStore P → P.Ident → P.Expr → SemanticStore UpdateState σ x v σ' /-- -An inductive rule for state init. +Abtract variable initialization. + +This does not specify how `σ` is represented, only what it maps each variable to. -/ inductive InitState : SemanticStore P → P.Ident → P.Expr → SemanticStore P → Prop where + /-- The state `σ'` is be equivalent to `σ` except at `x`, where it maps to + `v`. Requires that `x` mapped to nothing beforehand. -/ | init : σ x = none → σ' x = .some v → @@ -258,11 +267,12 @@ inductive InitState : SemanticStore P → P.Ident → P.Expr → SemanticStore P InitState σ x v σ' /-- -An inductively-defined operational semantics that depends on -environment lookup and evaluation functions for expressions. +An inductively-defined operational semantics for `Cmd` that depends on variable +lookup (`σ`) and expression evaluation (`δ`) functions. -/ inductive EvalCmd [HasFvar P] [HasBool P] [HasNot P] : SemanticEval P → SemanticStore P → SemanticStore P → Cmd P → SemanticStore P → Prop where + /-- If `e` evaluates to a value `v`, initialize `x` according to `InitState`. -/ | eval_init : δ σ₀ σ e = .some v → InitState P σ x v σ' → @@ -270,6 +280,7 @@ inductive EvalCmd [HasFvar P] [HasBool P] [HasNot P] : --- EvalCmd δ σ₀ σ (.init x _ e _) σ' + /-- If `e` evaluates to a value `v`, assign `x` according to `UpdateState`. -/ | eval_set : δ σ₀ σ e = .some v → UpdateState P σ x v σ' → @@ -277,18 +288,22 @@ inductive EvalCmd [HasFvar P] [HasBool P] [HasNot P] : ---- EvalCmd δ σ₀ σ (.set x e _) σ' + /-- Assign `x` an arbitrary value `v` according to `UpdateState`. -/ | eval_havoc : UpdateState P σ x v σ' → WellFormedSemanticEvalVar δ → ---- EvalCmd δ σ₀ σ (.havoc x _) σ' + /-- If `e` evaluates to true in `σ`, evaluate to the same `σ`. This semantics + does not have a concept of an erroneous execution. -/ | eval_assert : δ σ₀ σ e = .some HasBool.tt → WellFormedSemanticEvalBool δ → ---- EvalCmd δ σ₀ σ (.assert _ e _) σ + /-- If `e` evaluates to true in `σ`, evaluate to the same `σ`. -/ | eval_assume : δ σ₀ σ e = .some HasBool.tt → WellFormedSemanticEvalBool δ → diff --git a/Strata/DL/Imperative/NondetStmt.lean b/Strata/DL/Imperative/NondetStmt.lean index 2eb88f87e..8b22aec85 100644 --- a/Strata/DL/Imperative/NondetStmt.lean +++ b/Strata/DL/Imperative/NondetStmt.lean @@ -22,10 +22,23 @@ Comamnds](https://en.wikipedia.org/wiki/Guarded_Command_Language), and in [Kleene Algebra with Tests](https://www.cs.cornell.edu/~kozen/Papers/kat.pdf). -/ +/-- +A non-deterministic statement, parameterized by a type of pure expressions (`P`) +and a type of commands (`Cmd`). + +This encodes the same types of control flow as `Stmt`, but using only +non-deterministic choices: arbitrarily choosing one of two sub-statements to +execute or executing a sub-statement an arbitrary number of times. Conditions +can be encoded if the command type includes assumptions. +-/ inductive NondetStmt (P : PureExpr) (Cmd : Type) : Type where + /-- An atomic command, of an arbitrary type. -/ | cmd (cmd : Cmd) + /-- Execute `s1` followed by `s2`. -/ | seq (s1 s2 : NondetStmt P Cmd) + /-- Execute either `s1` or `s2`, arbitrarily. -/ | choice (s1 s2 : NondetStmt P Cmd) + /-- Execute `s` an arbitrary number of times (possibly zero). -/ | loop (s : NondetStmt P Cmd) deriving Inhabited diff --git a/Strata/DL/Imperative/NondetStmtSemantics.lean b/Strata/DL/Imperative/NondetStmtSemantics.lean index ba01e3fe5..b871f352f 100644 --- a/Strata/DL/Imperative/NondetStmtSemantics.lean +++ b/Strata/DL/Imperative/NondetStmtSemantics.lean @@ -14,8 +14,9 @@ namespace Imperative mutual /-- An inductively-defined operational semantics for non-deterministic -statements that depends on environment lookup and evaluation functions -for expressions. -/ +statements that depends on environment lookup and evaluation functions for +expressions. **NOTE:** This will probably be replaced with a small-step +semantics. -/ inductive EvalNondetStmt (P : PureExpr) (Cmd : Type) (EvalCmd : EvalCmdParam P Cmd) [HasVarsImp P (List (Stmt P Cmd))] [HasVarsImp P Cmd] [HasFvar P] [HasBool P] [HasNot P] : SemanticEval P → SemanticStore P → SemanticStore P → diff --git a/Strata/DL/Imperative/Stmt.lean b/Strata/DL/Imperative/Stmt.lean index fb9c20d79..50ced1f61 100644 --- a/Strata/DL/Imperative/Stmt.lean +++ b/Strata/DL/Imperative/Stmt.lean @@ -18,18 +18,32 @@ unstructured control-flow. -/ mutual +/-- Imperative statements focused on control flow. + +The `P` parameter specifies the type of expressions that appear in conditional +and loop guards. The `Cmd` parameter specifies the type of atomic command +contained within the `.cmd` constructor. +-/ inductive Stmt (P : PureExpr) (Cmd : Type) : Type where + /-- An atomic command. -/ | cmd (cmd : Cmd) + /-- An block containing a `List` of `Stmt`. -/ | block (label : String) (b : Block P Cmd) (md : MetaData P := .empty) - /-- `ite` (if-then-else) statement provides structured control flow. -/ + /-- A conditional execution statement. -/ | ite (cond : P.Expr) (thenb : Block P Cmd) (elseb : Block P Cmd) (md : MetaData P := .empty) - /-- `loop` Loop statement with optional measure (for termination) and invariant. -/ + /-- An iterated execution statement. Includes an optional measure (for + termination) and invariant. -/ | loop (guard : P.Expr) (measure : Option P.Expr) (invariant : Option P.Expr) (body : Block P Cmd) (md : MetaData P := .empty) - /-- `goto` provides unstructured control flow. -/ + /-- A semi-structured control flow statement transferring control to the given + label. The control flow induced by `goto` must not create cycles. **NOTE:** + This will likely be removed, in favor of an alternative view of imperative + programs that is purely untructured. -/ | goto (label : String) (md : MetaData P := .empty) deriving Inhabited +/-- A list of statements used by the `.block` constructor of `Stmt`. -/ structure Block (P : PureExpr) (Cmd : Type) where + /-- The concrete list of statements. -/ ss : List (Stmt P Cmd) end diff --git a/Strata/DL/Imperative/StmtSemanticsSmallStep.lean b/Strata/DL/Imperative/StmtSemanticsSmallStep.lean index 028f5f579..a337ccd18 100644 --- a/Strata/DL/Imperative/StmtSemanticsSmallStep.lean +++ b/Strata/DL/Imperative/StmtSemanticsSmallStep.lean @@ -19,12 +19,15 @@ dialect's statement constructs. /-- Configuration for small-step semantics, representing the current execution state. A configuration consists of: -- The current statement being executed +- The current statement (or list of statements) being executed - The current store -/ inductive Config (P : PureExpr) (CmdT : Type) : Type where + /-- A single statement to execute next. -/ | stmt : Stmt P CmdT → SemanticStore P → Config P CmdT + /-- A list of statements to execute next, in order. -/ | stmts : List (Stmt P CmdT) → SemanticStore P → Config P CmdT + /-- A terminal configuration, indicating that execution has finished. -/ | terminal : SemanticStore P → Config P CmdT /-- @@ -40,8 +43,7 @@ inductive StepStmt [HasBool P] [HasNot P] : SemanticEval P → SemanticStore P → Config P CmdT → Config P CmdT → Prop where - /-- Command: a command steps to terminal configuration if it - evaluates successfully -/ + /-- A command steps to terminal configuration if it evaluates successfully -/ | step_cmd : EvalCmd δ σ₀ σ c σ' → ---- @@ -49,13 +51,14 @@ inductive StepStmt (.stmt (.cmd c) σ₀) (.terminal σ') - /-- Block: a labeled block steps to its statement list -/ + /-- A labeled block steps to its statement list. -/ | step_block : StepStmt P EvalCmd δ σ₀ (.stmt (.block _ ⟨ss⟩ _) σ) (.stmts ss σ) - /-- Conditional (true): if condition evaluates to true, step to then-branch -/ + /-- If the condition of an `ite` statement evaluates to true, step to the then + branch. -/ | step_ite_true : δ σ₀ σ c = .some HasBool.tt → WellFormedSemanticEvalBool δ → @@ -64,7 +67,8 @@ inductive StepStmt (.stmt (.ite c ⟨tss⟩ ⟨ess⟩ _) σ) (.stmts tss σ) - /-- Conditional (false): if condition evaluates to false, step to else-branch -/ + /-- If the condition of an `ite` statement evaluates to false, step to the else + branch. -/ | step_ite_false : δ σ₀ σ c = .some HasBool.ff → WellFormedSemanticEvalBool δ → @@ -73,7 +77,7 @@ inductive StepStmt (.stmt (.ite c ⟨tss⟩ ⟨ess⟩ _) σ) (.stmts ess σ) - /-- Loop (guard true): if guard is true, execute body then loop again -/ + /-- If a loop guard is true, execute the body and then loop again. -/ | step_loop_enter : δ σ₀ σ g = .some HasBool.tt → WellFormedSemanticEvalBool δ → @@ -82,7 +86,7 @@ inductive StepStmt (.stmt (.loop g m inv ⟨body⟩ md) σ) (.stmts (body ++ [.loop g m inv ⟨body⟩ md]) σ) - /-- Loop (guard false): if guard is false, terminate the loop -/ + /-- If a loop guard is false, terminate the loop. -/ | step_loop_exit : δ σ₀ σ g = .some HasBool.ff → WellFormedSemanticEvalBool δ → @@ -93,14 +97,14 @@ inductive StepStmt /- Goto: not implemented, because we plan to remove it. -/ - /-- Empty statement list: no statements left to execute -/ + /-- An empty list of statements steps to `.terminal` with no state changes. -/ | step_stmts_nil : StepStmt P EvalCmd δ σ₀ (.stmts [] σ) (.terminal σ) - /-- Statement composition: after executing a statement, continue with - remaining statements -/ + /-- To evaluate a sequence of statements, evaluate the first statement and + then evaluate the remaining statements in the resulting state. -/ | step_stmt_cons : StepStmt P EvalCmd δ σ₀ (.stmt s σ) (.terminal σ') → ---- @@ -119,8 +123,14 @@ inductive StepStmtStar [HasVarsImp P CmdT] [HasFvar P] [HasVal P] [HasBool P] [HasNot P] : SemanticEval P → SemanticStore P → Config P CmdT → Config P CmdT → Prop where + + /-- Reflexivity: a configuration `c` can evaluate to itself in zero steps. -/ | refl : StepStmtStar P EvalCmd δ σ₀ c c + + /-- Transitivity: if `c₁` can reach `c₂` in some number of steps and `c₂` can + reach `c₃` in some number of steps, `c₁` can reach `c₃` in some number of + steps. -/ | step : StepStmt P EvalCmd δ σ₀ c₁ c₂ → StepStmtStar P EvalCmd δ σ₀ c₂ c₃ → diff --git a/Strata/DL/Lambda/LExpr.lean b/Strata/DL/Lambda/LExpr.lean index 19bc6939c..5b68f1489 100644 --- a/Strata/DL/Lambda/LExpr.lean +++ b/Strata/DL/Lambda/LExpr.lean @@ -82,7 +82,7 @@ inductive LConst : Type where deriving Repr, DecidableEq /-- -Lambda Expressions with Quantifiers. +Lambda expressions with quantifiers. Like Lean's own expressions, we use the locally nameless representation for this abstract syntax. @@ -93,29 +93,32 @@ We leave placeholders for type annotations only for constants (`.const`), operations (`.op`), binders (`.abs`, `.quant`), and free variables (`.fvar`). -LExpr is parameterized by `TypeType`, which represents -user-allowed type annotations (optional), and `Identifier` for allowed -identifiers. For a fully annotated AST, see `LExprT` that is created after the -type inference transform. +LExpr is parameterized by `TypeType`, which represents user-allowed type +annotations (optional), and `Identifier` for allowed identifiers. Type inference +adds any missing type annotations. -/ inductive LExpr (T : LExprParamsT) : Type where - /-- `.const c ty`: constants (in the sense of literals). -/ + /-- A constant (in the sense of literals). -/ | const (m: T.base.Metadata) (c: LConst) - /-- `.op c ty`: operation names. -/ + /-- A built-in operation, referred to by name. -/ | op (m: T.base.Metadata) (o : Identifier T.base.IDMeta) (ty : Option T.TypeType) - /-- `.bvar deBruijnIndex`: bound variable. -/ + /-- A bound variable, in de Bruijn form. -/ | bvar (m: T.base.Metadata) (deBruijnIndex : Nat) - /-- `.fvar name ty`: free variable, with an option (mono)type annotation. -/ + /-- A free variable, with an optional type annotation. -/ | fvar (m: T.base.Metadata) (name : Identifier T.base.IDMeta) (ty : Option T.TypeType) - /-- `.abs ty e`: abstractions; `ty` the is type of bound variable. -/ + /-- An abstraction, where `ty` the is type of bound variable. -/ | abs (m: T.base.Metadata) (ty : Option T.TypeType) (e : LExpr T) - /-- `.quant k ty tr e`: quantified expressions; `ty` the is type of bound variable, and `tr` the trigger. -/ + /-- A quantified expression, where `k` indicates whether it is universally or + existentially quantified, `ty` the is type of bound variable, and `trigger` is + a trigger pattern (primarily for use with SMT). -/ | quant (m: T.base.Metadata) (k : QuantifierKind) (ty : Option T.TypeType) (trigger: LExpr T) (e : LExpr T) - /-- `.app fn e`: function application. -/ + /-- A function application. -/ | app (m: T.base.Metadata) (fn e : LExpr T) - /-- `.ite c t e`: if-then-else expression. -/ + /-- A conditional expression. This is a constructor rather than a built-in + operation because it occurs so frequently. -/ | ite (m: T.base.Metadata) (c t e : LExpr T) - /-- `.eq e1 e2`: equality expression. -/ + /-- An equality expression. This is a constructor rather than a built-in + operation because it occurs so frequently. -/ | eq (m: T.base.Metadata) (e1 e2 : LExpr T) instance [Repr T.base.Metadata] [Repr T.TypeType] [Repr T.base.IDMeta] : Repr (LExpr T) where diff --git a/Strata/DL/Lambda/LExprTypeSpec.lean b/Strata/DL/Lambda/LExprTypeSpec.lean index c48cc2313..d3d9d6f64 100644 --- a/Strata/DL/Lambda/LExprTypeSpec.lean +++ b/Strata/DL/Lambda/LExprTypeSpec.lean @@ -58,27 +58,45 @@ def LTy.openFull (ty: LTy) (tys: List LMonoTy) : LMonoTy := LMonoTy.subst [(List.zip (LTy.boundVars ty) tys)] (LTy.toMonoTypeUnsafe ty) /-- -Typing relation for `LExpr`s. +Typing relation for `LExpr`s with respect to `LTy`. -/ inductive HasType {T: LExprParams} [DecidableEq T.IDMeta] (C: LContext T): (TContext T.IDMeta) → LExpr T.mono → LTy → Prop where + + /-- A boolean constant has type `.bool` if `bool` is a known type in this + context. -/ | tbool_const : ∀ Γ m b, C.knownTypes.containsName "bool" → HasType C Γ (.boolConst m b) (.forAll [] .bool) + + /-- An integer constant has type `.int` if `int` is a known type in this + context. -/ | tint_const : ∀ Γ m n, C.knownTypes.containsName "int" → HasType C Γ (.intConst m n) (.forAll [] .int) + + /-- A real constant has type `.real` if `real` is a known type in this + context. -/ | treal_const : ∀ Γ m r, C.knownTypes.containsName "real" → HasType C Γ (.realConst m r) (.forAll [] .real) + + /-- A string constant has type `.string` if `string` is a known type in this + context. -/ | tstr_const : ∀ Γ m s, C.knownTypes.containsName "string" → HasType C Γ (.strConst m s) (.forAll [] .string) + + /-- A bit vector constant of size `n` has type `.bitvec n` if `bitvec` is a + known type in this context. -/ | tbitvec_const : ∀ Γ m n b, C.knownTypes.containsName "bitvec" → HasType C Γ (.bitvecConst m n b) (.forAll [] (.bitvec n)) + + /-- A variable has the type recorded for it in `Γ`, if any. -/ | tvar : ∀ Γ m x ty, Γ.types.find? x = some ty → HasType C Γ (.fvar m x none) ty - /- + + /-- For an annotated free variable (or operator, see `top_annotated`), it must be the case that the claimed type `ty_s` is an instantiation of the general type `ty_o`. It suffices to show the existence of a list `tys` that, when @@ -107,7 +125,8 @@ inductive HasType {T: LExprParams} [DecidableEq T.IDMeta] (C: LContext T): HasType C Γ e2 t2 → HasType C Γ (.app m e1 e2) t1 - -- `ty` is more general than `e_ty`, so we can instantiate `ty` with `e_ty`. + /-- If `ty` is more general than `e_ty`, we can instantiate `ty` with `e_ty`. + -/ | tinst : ∀ Γ e ty e_ty x x_ty, HasType C Γ e ty → e_ty = LTy.open x x_ty ty → @@ -122,12 +141,16 @@ inductive HasType {T: LExprParams} [DecidableEq T.IDMeta] (C: LContext T): TContext.isFresh a Γ → HasType C Γ e (LTy.close a ty) + /-- If `e1` and `e2` have the same type `ty`, and `c` has type `.bool`, then + `.ite c e1 e2` has type `ty`. -/ | tif : ∀ Γ m c e1 e2 ty, HasType C Γ c (.forAll [] .bool) → HasType C Γ e1 ty → HasType C Γ e2 ty → HasType C Γ (.ite m c e1 e2) ty + /-- If `e1` and `e2` have the same type `ty`, then `.eq e1 e2` has type + `.bool`. -/ | teq : ∀ Γ m e1 e2 ty, HasType C Γ e1 ty → HasType C Γ e2 ty → @@ -144,7 +167,7 @@ inductive HasType {T: LExprParams} [DecidableEq T.IDMeta] (C: LContext T): C.functions.find? (fun fn => fn.name == op) = some f → f.type = .ok ty → HasType C Γ (.op m op none) ty - /- + /-- See comments in `tvar_annotated`. -/ | top_annotated: ∀ Γ m f op ty_o ty_s tys, diff --git a/Strata/DL/Lambda/LTy.lean b/Strata/DL/Lambda/LTy.lean index ea047d6db..af60a2ae2 100644 --- a/Strata/DL/Lambda/LTy.lean +++ b/Strata/DL/Lambda/LTy.lean @@ -25,16 +25,15 @@ abbrev TyIdentifier := String instance : Coe String TyIdentifier where coe := id -/-- -Types in Lambda: these are mono-types. Note that all free type variables -(`.ftvar`) are implicitly universally quantified. --/ +/-- Monomorphic types in Lambda. Note that all free type variables (`.ftvar`) +are implicitly universally quantified. -/ inductive LMonoTy : Type where - /-- Type variable. -/ + /-- A type variable. -/ | ftvar (name : TyIdentifier) - /-- Type constructor. -/ + /-- A type constructor. -/ | tcons (name : String) (args : List LMonoTy) - /-- Special support for bitvector types of every size. -/ + /-- A bit vector type. This is a special case so that it can be parameterized + by a size. -/ | bitvec (size : Nat) deriving Inhabited, Repr @@ -120,9 +119,10 @@ def LMonoTy.getArrowArgs (t: LMonoTy) : List LMonoTy := | _ => [] /-- -Type schemes (poly-types) in Lambda. +Polymorphic type schemes in Lambda. -/ inductive LTy : Type where + /-- A type containing universally quantified type variables. -/ | forAll (vars : List TyIdentifier) (ty : LMonoTy) deriving Inhabited, Repr diff --git a/Strata/DL/Lambda/Semantics.lean b/Strata/DL/Lambda/Semantics.lean index 40d18eb7f..5c73732d4 100644 --- a/Strata/DL/Lambda/Semantics.lean +++ b/Strata/DL/Lambda/Semantics.lean @@ -27,63 +27,72 @@ def Scopes.toEnv (s:Scopes Tbase) : Env Tbase := fun t => (s.find? t).map (·.snd) /-- -A small-step semantics of LExpr. -Currently only defined for LMonoTy, but it will be expanded to an arbitrary -type in the future. +A small-step semantics for `LExpr`. + +Currently only defined for expressions paremeterized by `LMonoTy`, but it will +be expanded to an arbitrary type in the future. + The order of constructors matter because the `constructor` tactic will rely on it. -This small-step definitions faithfully follows the behavior of LExpr.eval, -except that -(1) This inductive definition may stuck early when there is no -assignment to a free variable available. -(2) This semantics does not describe how the metadata must change, because -metadata must not affect evaluation semantics. Different concrete evaluators -like LExpr.eval can use different strategy for updating metadata. + +This small-step definitions faithfully follows the behavior of `LExpr.eval`, +except that: +1. This inductive definition may get stuck early when there is no + assignment to a free variable available. + +2. This semantics does not describe how metadata must change, because + metadata must not affect evaluation semantics. Different concrete evaluators + like `LExpr.eval` can have different strategy for updating metadata. -/ inductive Step (F:@Factory Tbase) (rf:Env Tbase) : LExpr Tbase.mono → LExpr Tbase.mono → Prop where --- A free variable. Stuck if fvar does not exist in FreeVarMap. +/-- A free variable. Stuck if `fvar` does not exist in `FreeVarMap`. -/ | expand_fvar: ∀ (x:Tbase.Identifier) (e:LExpr Tbase.mono), rf x = .some e → Step F rf (.fvar m x ty) e --- Beta reduction for lambda; Call-by-value semantics. +/-- Call-by-value semantics: beta reduction. -/ | beta: ∀ (e1 v2 eres:LExpr Tbase.mono), LExpr.isCanonicalValue F v2 → eres = LExpr.subst (fun _ => v2) e1 → Step F rf (.app m1 (.abs m2 ty e1) v2) eres --- Call-by-value semantics. +/-- Call-by-value semantics: argument evaluation. -/ | reduce_2: ∀ (v1 e2 e2':LExpr Tbase.mono), LExpr.isCanonicalValue F v1 → Step F rf e2 e2' → Step F rf (.app m v1 e2) (.app m' v1 e2') +/-- Call-by-value semantics: function evaluation. -/ | reduce_1: ∀ (e1 e1' e2:LExpr Tbase.mono), Step F rf e1 e1' → Step F rf (.app m e1 e2) (.app m' e1' e2) --- For ite x e1 e2, do not eagerly evaluate e1 and e2. --- For the reduction order, ite x e1 e2 is interpreted as --- 'ite x (λ.e1) (λ.e2)'. +/-- Lazy evaluation of `ite`: condition is true. To evaluate `ite x e1 e2`, do +not first evaluate `e1` and `e2`. In other words, `ite x e1 e2` is interpreted +as `ite x (λ.e1) (λ.e2)`. -/ | ite_reduce_then: ∀ (ethen eelse:LExpr Tbase.mono), Step F rf (.ite m (.const mc (.boolConst true)) ethen eelse) ethen +/-- Lazy evaluation of `ite`: condition is false. To evaluate `ite x e1 e2`, do +not first evaluate `e1` and `e2`. In other words, `ite x e1 e2` is interpreted +as `ite x (λ.e1) (λ.e2)`. -/ | ite_reduce_else: ∀ (ethen eelse:LExpr Tbase.mono), Step F rf (.ite m (.const mc (.boolConst false)) ethen eelse) eelse +/-- Evaluation of `ite` condition. -/ | ite_reduce_cond: ∀ (econd econd' ethen eelse:LExpr Tbase.mono), Step F rf econd econd' → Step F rf (.ite m econd ethen eelse) (.ite m' econd' ethen eelse) --- Equality. Reduce after both operands evaluate to values. +/-- Evaluation of equality. Reduce after both operands evaluate to values. -/ | eq_reduce: ∀ (e1 e2 eres:LExpr Tbase.mono) (H1:LExpr.isCanonicalValue F e1) @@ -91,21 +100,24 @@ inductive Step (F:@Factory Tbase) (rf:Env Tbase) eres = .const mc (.boolConst (LExpr.eql F e1 e2 H1 H2)) → Step F rf (.eq m e1 e2) eres +/-- Evaluation of the left-hand side of an equality. -/ | eq_reduce_lhs: ∀ (e1 e1' e2:LExpr Tbase.mono), Step F rf e1 e1' → Step F rf (.eq m e1 e2) (.eq m' e1' e2) +/-- Evaluation of the right-hand side of an equality. -/ | eq_reduce_rhs: ∀ (v1 e2 e2':LExpr Tbase.mono), LExpr.isCanonicalValue F v1 → Step F rf e2 e2' → Step F rf (.eq m v1 e2) (.eq m' v1 e2') --- Expand functions and free variables when they are evaluated. --- If the function body is unknown, concreteEval can be instead used. Look at --- the eval_fn constructor below. --- This is consistent with what LExpr.eval does (modulo the "inline" flag). +/-- Evaluate a built-in function when a body expression is available in the +`Factory` argument `F`. This is consistent with what `LExpr.eval` does (modulo +the `inline` flag). Note that it might also be possible to evaluate with +`eval_fn`. A key correctnes property is that doing so will yield the same +result. -/ | expand_fn: ∀ (e callee fnbody new_body:LExpr Tbase.mono) args fn, F.callOfLFunc e = .some (callee,args,fn) → @@ -114,9 +126,10 @@ inductive Step (F:@Factory Tbase) (rf:Env Tbase) new_body = LExpr.substFvars fnbody (fn.inputs.keys.zip args) → Step F rf e new_body --- The second way of evaluating a function call. --- If LFunc has a concrete evaluator, this can be used to 'jump' to the final --- result of the function. +/-- Evaluate a built-in function when a concrete evaluation function is +available in the `Factory` argument `F`. Note that it might also be possible to +evaluate with `expand_fn`. A key correctnes property is that doing so will yield +the same result. -/ | eval_fn: ∀ (e callee:LExpr Tbase.mono) args fn denotefn, F.callOfLFunc e = .some (callee,args,fn) → @@ -138,7 +151,13 @@ Multi-step execution: reflexive transitive closure of single steps. -/ inductive StepStar (F:@Factory Tbase) (rf:Env Tbase) : LExpr Tbase.mono → LExpr Tbase.mono → Prop where + +/-- Reflexivity: an expression `e` can evaluate to itself in zero steps. -/ | refl : StepStar F rf e e + +/-- Transitivity: if `e` can reach `e'` in some number of steps and `e'` can +reach `e''` in some number of steps, `e` can reach `e''` in some number of +steps. -/ | step : ∀ e e' e'', Step F rf e e' → StepStar F rf e' e'' → StepStar F rf e e'' From c98e6464127781cf45e702eb533aec856f3908b3 Mon Sep 17 00:00:00 2001 From: Aaron Tomb Date: Wed, 26 Nov 2025 14:50:04 -0800 Subject: [PATCH 07/22] Consistent version of Lean for Strata, Verso --- docs/verso/lake-manifest.json | 8 ++++---- docs/verso/lakefile.toml | 2 +- docs/verso/lean-toolchain | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/verso/lake-manifest.json b/docs/verso/lake-manifest.json index 8571de8a5..1685d6858 100644 --- a/docs/verso/lake-manifest.json +++ b/docs/verso/lake-manifest.json @@ -5,10 +5,10 @@ "type": "git", "subDir": null, "scope": "", - "rev": "590eac5d96f04c5a75214b3b501afe389c333720", + "rev": "f1010398410d85ca53dd3a7ffbe66d98eaccd882", "name": "verso", "manifestFile": "lake-manifest.json", - "inputRev": "nightly-testing", + "inputRev": "v4.24.0", "inherited": false, "configFile": "lakefile.lean"}, {"type": "path", @@ -22,7 +22,7 @@ "type": "git", "subDir": null, "scope": "", - "rev": "aaee7fa4a1a158bd814d76f642df8a1d19db9f49", + "rev": "66aefec2852d3e229517694e642659f316576591", "name": "MD4Lean", "manifestFile": "lake-manifest.json", "inputRev": "main", @@ -32,7 +32,7 @@ "type": "git", "subDir": null, "scope": "", - "rev": "dd7c477cb8b1898c3ace7bf66a47462eef7ac52c", + "rev": "767f10408ca8abe29a15add2bf111eefdd9522b2", "name": "subverso", "manifestFile": "lake-manifest.json", "inputRev": "main", diff --git a/docs/verso/lakefile.toml b/docs/verso/lakefile.toml index d19859fca..d2fa71c53 100644 --- a/docs/verso/lakefile.toml +++ b/docs/verso/lakefile.toml @@ -8,7 +8,7 @@ path = "../.." [[require]] name = "verso" git = "https://github.com/leanprover/verso" -rev = "nightly-testing" +rev = "v4.24.0" [[lean_lib]] name = "DDMDoc" diff --git a/docs/verso/lean-toolchain b/docs/verso/lean-toolchain index 27770b571..c00a53503 100644 --- a/docs/verso/lean-toolchain +++ b/docs/verso/lean-toolchain @@ -1 +1 @@ -leanprover/lean4:v4.23.0-rc2 \ No newline at end of file +leanprover/lean4:v4.24.0 From c23961306d465c2cf26766cb0c98ea84f33428fb Mon Sep 17 00:00:00 2001 From: Aaron Tomb Date: Wed, 26 Nov 2025 14:50:38 -0800 Subject: [PATCH 08/22] Full skeleton of the Strata Language Definition --- docs/verso/LangDefDoc.lean | 244 +++++++++++++++++++++++++++++++------ 1 file changed, 207 insertions(+), 37 deletions(-) diff --git a/docs/verso/LangDefDoc.lean b/docs/verso/LangDefDoc.lean index 3195a1656..61b6b3980 100644 --- a/docs/verso/LangDefDoc.lean +++ b/docs/verso/LangDefDoc.lean @@ -9,10 +9,12 @@ import VersoManual import Strata.DL.Imperative.Cmd import Strata.DL.Imperative.CmdSemantics import Strata.DL.Imperative.Stmt -import Strata.DL.Imperative.StmtSemantics +import Strata.DL.Imperative.StmtSemanticsSmallStep +import Strata.DL.Imperative.NondetStmt +import Strata.DL.Imperative.NondetStmtSemantics import Strata.DL.Lambda.LExpr -open Imperative -open Lambda +import Strata.DL.Lambda.Semantics +import Strata.DL.Lambda.LExprTypeSpec -- This gets access to most of the manual genre open Verso.Genre Manual @@ -22,42 +24,210 @@ open Verso.Genre Manual open Verso.Genre.Manual.InlineLean set_option pp.rawOnError true +set_option verso.docstring.allowMissing true #doc (Manual) "The Strata Language Definition" => %%% -authors := ["Aaron Tomb", "TODO"] -shortTitle := "Strata Language" +shortTitle := "The Strata Language" %%% -TODO: below is an example of what including Lean code defining the semantics of -Strata might look like. - -```lean -namespace Imperative - -``` -# Small-Step Operational Semantics for Statements - -Here we define small-step operational semantics for the -`Imperative` dialect's statement constructs. - -First, we define the notion of a configuration, representing the -current execution state. A configuration consists of: -- The current statement or statements being executed -- The current store (for current variable values) -- The initial store (for evaluating Boogie's `old` operator) - -```lean -inductive Config (P : PureExpr) : Type where - | stmt : - Stmt P (Cmd P) → - SemanticStore P → - SemanticStore P → - Config P - | stmts : - List (Stmt P (Cmd P)) → - SemanticStore P → - SemanticStore P → - Config P - | terminal : SemanticStore P → SemanticStore P → Config P -``` +# Introduction + +Strata aims to provide the foundation for representing the semantics of +programs, specifications, protocols, architectures, and other aspects of +large-scale distributed systems and their components. It achieves this through +languages of two types. The Dialect Definition Mechanism, described +[here](https://github.com/strata-org/Strata/tree/main/docs/verso/DDMDoc.lean), +provides a way to define the syntax and a simple type system for what we call a +dialect of Strata. At the moment, these dialects do not directly have semantics +(though we may add a mechanism for defining their semantics in the future) but +instead are defined by translation to or from the second notion of language, +Strata’s Core languages. Said another way, each of these dialects is a different +concrete way to write Strata programs, but all of these dialects are ultimately +represented internally using the same Core languages. + +Dialects are used to describe both the initial artifacts being analyzed by +Strata and more low-level representations of those artifacts used to communicate +with external reasoning tools. In both situations, Stata uses dialects as a +mechanism for communicating with external tools (either language front ends or +generic automated reasoning tools like SMT solvers). + +(TODO: funnel diagram showing various dialects in relation to Strata Core) + +The Strata Core languages consist of a few building blocks that can be combined +in different ways. This allows concrete dialects to systematically use different +combinations that still share the majority of their implementation. In Lean (and +in principle in most other source languages that could be used to process Strata +programs), the type system can enforce various structural constraints, ensuring +that only expected language constructs show up. The most common use of the +Strata Core languages is in combination: with an imperative statement type +parameterized by an expression type, and with various more fine-grained +adjustments of other parameters. Because these building blocks are typically +used together, it’s reasonable to think of Strata Core as a single language that +can be configured in various ways for different use cases. + +The two fundamental building blocks of Strata Core are a representation of +functional programs called `Lambda`, and a representation of imperative programs +called `Imperative`. The `Lambda` language is parameterized by a type system +(TODO: and can be constrained to allow or disallow complex features such as +lambda abstractions and quantifiers). `Lambda` is also parameterized by a set of +built-in types and functions. The `Imperative` language is then parameterized by +the type of expressions allowed. Currently, those expressions will almost always +be some instantiation of `Lambda`, but they may be restricted in some way, such +as disallowing quantifiers. Both Core building blocks are parameterized by a +metadata type, which by default is instantiated with a map from keys to +structured values that can contain expressions (typically from `Lambda`). + +The remainder of this document describes the current abstract syntax and +semantics of `Lambda` and `Imperative` in detail, with direct reference to the +Lean source code that defines these languages. We do not consider the Core +language set in stone. It may evolve over time, particularly to add new +fundamental constructs, and this document will be updated as it does. + +# Lambda + +The `Lambda` language is a standard but generic implementation of the lambda +calculus. It is parameterized by a type for metadata and the type of types +(which may be `Unit`). It includes the standard constructs for constants, free +and bound variables, abstractions, and applications. In addition, it includes a +special type of constant, an operator, to represent built-in functions. It +extends the standard lambda calculus by allowing quantifiers (since a key use of +the language is to write logical predicates) and includes constructors for +if-then-else and equality functions, since those are so commonly used. + +Although `Lambda` can be parameterized by an arbitrary type system, the Strata +code base includes an implementation of a polymorphic Hindley-Milner type system +(TODO: link) and inference algorithm (TODO: link) over the type `LTy`. This +allows universal quantification over types and the use of arbitrary named type +constructors (as well as special support for bit vector types, to allow them to +be parameterized by size). + +Type inference and checking with this type system takes as input expressions +parameterized by `Unit` as the type of types, and produces expressions +parameterized by `LTy` as output. + +## Syntax + +The syntax of lambda expressions is provided by the `LExpr` type. + +{docstring Lambda.LExpr} + +## Type System + +Although `LExpr` can be parameterized by an arbitrary type system, Strata +currently implements one, based on the types `LMonoTy` and `LTy`. + +The first, `LMonoTy` represents monomorphic types. It's a separate type because +some contexts allow only monomorphic types. + +{docstring Lambda.LMonoTy} + +The `LTy` type allows monomorphic types to be wrapped in universal type +quantifiers, creating polymorphic types. + +{docstring Lambda.LTy} + +The relationshp between `LExpr` and `LTy` is expressed by the +`Lambda.LExpr.HasType` relation. + +{docstring Lambda.LExpr.HasType} + +(TODO: talk about the type inference implementation?) + +## Operational Semantics + +The semantics of the `LExpr` type are specified using the small-step inductive +relation `Lambda.Step`. + +{docstring Lambda.Step} + +Typically we will want to talk about arbitrarily long sequences of steps, from +an initial expression to a value. The `Lambda.StepStar` relation describes the +reflexive, transitive closure of the `Lambda.Step` relation. + +{docstring Lambda.StepStar} + +(TODO: can we use a generic construct for the reflexive, transitive closure of +an arbitrary relation? Both here and for statements?) + +# Imperative + +The `Imperative` language is a standard core imperative calculus, parameterized +by a type of expressions and divided into two pieces: commands and statements. +Commands represent atomic operations that do not induce control flow (except +possibly in the form of procedure calls that follow a stack discipline). +Statements are parameterized by a command type and describe the control flow +surrounding those commands. Statements exist in three forms, corresponding to +the most common alternative representations. These forms are: + +* Structured deterministic statements, each of which can be: a command, a + sequence of statements in a block, a deterministic conditional, a + deterministic loop with a condition, or a block exit statement. + +* Structured non-deterministic statements, each of which can be: a command, a + sequence of two statements, an arbitrary choice between two statements, or an + iteration of a statement an arbitrary number of times. + +* Unstructured control-flow graphs where each basic block consists of a sequence + of commands followed by a terminator command. A terminator command can be: a + conditional jump to one of two blocks, termination of execution, or a + non-deterministic jump to any one of an arbitrary number of successor blocks. + +Translations exist from structured deterministic statements into either +structured non-deterministic statements or unstructured control-flow graphs. + +## Command Syntax + +The core built-in set of commands includes variable initializations, +deterministic assignments, non-deterministic assignments ("havoc"), assertions, +and assumptions. + +{docstring Imperative.Cmd} + +## Command Operational Semantics + +The semantics of commands are specified in terms of how they interact with a +program state, written `σ`. A state can be applied to a variable to obtain its +current value. And an expression `e` can be evaluated using the evaluation +functin in a given state: `δ σ e` gives the result of evaluating `e` in state +`σ`. This generic description allows the details of the program state +representation to vary, as long as it supports these operations. + +Given a state `σ`, the `InitState` relation describes how a variable obtains its +initial value. + +{docstring Imperative.InitState} + +The `UpdateState` relation then describes how a variable's value can change. + +{docstring Imperative.UpdateState} + +Given these two state relations, the semantics of each command is specified in +the standard way. + +{docstring Imperative.EvalCmd} + +## Structured Deterministic Statement Syntax + +Statements allow commands to be organized into standard control flow +arrangements, including sequencing, alternation, and iteration. + +{docstring Imperative.Stmt} + +{docstring Imperative.Block} + +## Structured Deterministic Statement Operational Semantics + +{docstring Imperative.Config} + +{docstring Imperative.StepStmt} + +{docstring Imperative.StepStmtStar} + +## Structured Non-Deterministic Statement Syntax + +{docstring Imperative.NondetStmt} + +## Structured Non-Deterministic Statement Operational Semantics + +{docstring Imperative.EvalNondetStmt} From e48d140135a9a405a7d4ad02a7ede4ed4442ab39 Mon Sep 17 00:00:00 2001 From: Aaron Tomb Date: Wed, 26 Nov 2025 16:03:24 -0800 Subject: [PATCH 09/22] More Strata Language Definition content --- docs/verso/LangDefDoc.lean | 134 +++++++++++++++++++++++++------------ 1 file changed, 91 insertions(+), 43 deletions(-) diff --git a/docs/verso/LangDefDoc.lean b/docs/verso/LangDefDoc.lean index 61b6b3980..6da87f69a 100644 --- a/docs/verso/LangDefDoc.lean +++ b/docs/verso/LangDefDoc.lean @@ -12,10 +12,14 @@ import Strata.DL.Imperative.Stmt import Strata.DL.Imperative.StmtSemanticsSmallStep import Strata.DL.Imperative.NondetStmt import Strata.DL.Imperative.NondetStmtSemantics +import Strata.DL.Imperative.MetaData import Strata.DL.Lambda.LExpr import Strata.DL.Lambda.Semantics import Strata.DL.Lambda.LExprTypeSpec +open Lambda +open Imperative + -- This gets access to most of the manual genre open Verso.Genre Manual @@ -67,16 +71,16 @@ used together, it’s reasonable to think of Strata Core as a single language th can be configured in various ways for different use cases. The two fundamental building blocks of Strata Core are a representation of -functional programs called `Lambda`, and a representation of imperative programs -called `Imperative`. The `Lambda` language is parameterized by a type system -(TODO: and can be constrained to allow or disallow complex features such as -lambda abstractions and quantifiers). `Lambda` is also parameterized by a set of +functional programs (`Lambda`), and a representation of imperative programs +(`Imperative`). The `Lambda` language is parameterized by a type system (TODO: +and can be constrained to allow or disallow complex features such as lambda +abstractions and quantifiers). `Lambda` is also parameterized by a set of built-in types and functions. The `Imperative` language is then parameterized by -the type of expressions allowed. Currently, those expressions will almost always -be some instantiation of `Lambda`, but they may be restricted in some way, such -as disallowing quantifiers. Both Core building blocks are parameterized by a -metadata type, which by default is instantiated with a map from keys to -structured values that can contain expressions (typically from `Lambda`). +the type of expressions it allows in conditions, assignments, and so on. +Currently, those expressions will almost always be some instantiation of +`Lambda`. Both Core building blocks are parameterized by a metadata type, +which by default is instantiated with a map from keys to structured values that +can contain expressions (typically from `Lambda`). The remainder of this document describes the current abstract syntax and semantics of `Lambda` and `Imperative` in detail, with direct reference to the @@ -88,23 +92,24 @@ fundamental constructs, and this document will be updated as it does. The `Lambda` language is a standard but generic implementation of the lambda calculus. It is parameterized by a type for metadata and the type of types -(which may be `Unit`). It includes the standard constructs for constants, free -and bound variables, abstractions, and applications. In addition, it includes a -special type of constant, an operator, to represent built-in functions. It -extends the standard lambda calculus by allowing quantifiers (since a key use of -the language is to write logical predicates) and includes constructors for -if-then-else and equality functions, since those are so commonly used. +(which may be `Unit`, to describe the untyped lambda calculus). It includes the +standard constructs for constants, free and bound variables, abstractions, and +applications. In addition, it includes a special type of constant, an operator, +to represent built-in functions. It extends the standard lambda calculus by +allowing quantifiers (since a key use of the language is to write logical +predicates) and includes constructors for if-then-else and equality functions, +since those are so commonly used. Although `Lambda` can be parameterized by an arbitrary type system, the Strata code base includes an implementation of a polymorphic Hindley-Milner type system -(TODO: link) and inference algorithm (TODO: link) over the type `LTy`. This -allows universal quantification over types and the use of arbitrary named type -constructors (as well as special support for bit vector types, to allow them to -be parameterized by size). +(TODO: link) and inference algorithm (TODO: link) over the type `LTy` (described +below). This allows universal quantification over types and the use of arbitrary +named type constructors (as well as special support for bit vector types, to +allow them to be parameterized by size). Type inference and checking with this type system takes as input expressions -parameterized by `Unit` as the type of types, and produces expressions -parameterized by `LTy` as output. +parameterized by `Unit` as the type of types (TODO: is this true?), and produces +expressions parameterized by `LTy` as output. ## Syntax @@ -114,21 +119,22 @@ The syntax of lambda expressions is provided by the `LExpr` type. ## Type System -Although `LExpr` can be parameterized by an arbitrary type system, Strata -currently implements one, based on the types `LMonoTy` and `LTy`. +Although {name LExpr}`LExpr` can be parameterized by an arbitrary type system, +Strata currently implements one, based on the types {name LMonoTy}`LMonoTy` and +{name LTy}`LTy`. -The first, `LMonoTy` represents monomorphic types. It's a separate type because +The first, {name LMonoTy}`LMonoTy` represents monomorphic types. It's a separate type because some contexts allow only monomorphic types. {docstring Lambda.LMonoTy} -The `LTy` type allows monomorphic types to be wrapped in universal type +The {name LTy}`LTy` type allows monomorphic types to be wrapped in universal type quantifiers, creating polymorphic types. {docstring Lambda.LTy} -The relationshp between `LExpr` and `LTy` is expressed by the -`Lambda.LExpr.HasType` relation. +The relationshp between {name LExpr}`LExpr` and {name LTy}`LTy` is expressed by the +{name LExpr.HasType}`HasType` relation. {docstring Lambda.LExpr.HasType} @@ -136,14 +142,17 @@ The relationshp between `LExpr` and `LTy` is expressed by the ## Operational Semantics -The semantics of the `LExpr` type are specified using the small-step inductive -relation `Lambda.Step`. +TODO: talk about `Factory` + +The semantics of the {name LExpr}`LExpr` type are specified in a standard way +using the small-step inductive relation {name Lambda.Step}`Lambda.Step`. {docstring Lambda.Step} -Typically we will want to talk about arbitrarily long sequences of steps, from -an initial expression to a value. The `Lambda.StepStar` relation describes the -reflexive, transitive closure of the `Lambda.Step` relation. +Typically we will want to talk about arbitrarily long sequences of steps, such +as from an initial expression to a value. The +{name Lambda.StepStar}`Lambda.StepStar` relation describes the reflexive, +transitive closure of the {name Lambda.Step}`Lambda.Step` relation. {docstring Lambda.StepStar} @@ -155,14 +164,15 @@ an arbitrary relation? Both here and for statements?) The `Imperative` language is a standard core imperative calculus, parameterized by a type of expressions and divided into two pieces: commands and statements. Commands represent atomic operations that do not induce control flow (except -possibly in the form of procedure calls that follow a stack discipline). -Statements are parameterized by a command type and describe the control flow -surrounding those commands. Statements exist in three forms, corresponding to -the most common alternative representations. These forms are: +possibly in the form of procedure calls that follow a stack discipline, though +the current core set of commands does not include calls). Statements are +parameterized by a command type and describe the control flow surrounding those +commands. Statements exist in three forms, corresponding to the most common +alternative representations. These forms are: * Structured deterministic statements, each of which can be: a command, a - sequence of statements in a block, a deterministic conditional, a - deterministic loop with a condition, or a block exit statement. + sequence of statements in a block, a deterministic conditional, a deterministic + loop with a condition, or a block exit statement. (TODO: goto still exists) * Structured non-deterministic statements, each of which can be: a command, a sequence of two statements, an arbitrary choice between two statements, or an @@ -175,6 +185,7 @@ the most common alternative representations. These forms are: Translations exist from structured deterministic statements into either structured non-deterministic statements or unstructured control-flow graphs. +(TODO: point to these translations) ## Command Syntax @@ -189,21 +200,22 @@ and assumptions. The semantics of commands are specified in terms of how they interact with a program state, written `σ`. A state can be applied to a variable to obtain its current value. And an expression `e` can be evaluated using the evaluation -functin in a given state: `δ σ e` gives the result of evaluating `e` in state +function in a given state: `δ σ e` gives the result of evaluating `e` in state `σ`. This generic description allows the details of the program state representation to vary, as long as it supports these operations. -Given a state `σ`, the `InitState` relation describes how a variable obtains its -initial value. +Given a state `σ`, the {name InitState}`InitState` relation describes how a +variable obtains its initial value. {docstring Imperative.InitState} -The `UpdateState` relation then describes how a variable's value can change. +The {name UpdateState}`UpdateState` relation then describes how a variable's +value can change. {docstring Imperative.UpdateState} Given these two state relations, the semantics of each command is specified in -the standard way. +a standard way. {docstring Imperative.EvalCmd} @@ -212,16 +224,32 @@ the standard way. Statements allow commands to be organized into standard control flow arrangements, including sequencing, alternation, and iteration. +(TODO: say more about loop invariants, measures?) + {docstring Imperative.Stmt} {docstring Imperative.Block} ## Structured Deterministic Statement Operational Semantics +The semantics of the {name Stmt}`Stmt` type is defined in terms of +*configurations*, represented by the {name Imperative.Config}`Config` type. A +configuration pairs the statement(s) remaining to be executed with a state, and +each step of execution goes from an initial configuration to a final configuration. + {docstring Imperative.Config} +The {name StepStmt}`StepStmt` type describes how each type of statement +transforms configurations. Like with the other components of Strata, the rules +follow standard conventions. + {docstring Imperative.StepStmt} +Like with `Lambda`, we typically want to talk about arbitrarily long sequences +of steps. The {name StepStmtStar}`Imperative.StepStmtStar` relation describes +the reflexive, transitive closure of the {name StepStmt}`Imperative.StepStmt` +relation. + {docstring Imperative.StepStmtStar} ## Structured Non-Deterministic Statement Syntax @@ -231,3 +259,23 @@ arrangements, including sequencing, alternation, and iteration. ## Structured Non-Deterministic Statement Operational Semantics {docstring Imperative.EvalNondetStmt} + +## Unstructured Control-Flow Graph Syntax + +TODO: fill in once it's merged + +## Unstructured Control-Flow Graph Semantics + +TODO: fill in once it's merged + +# Metadata + +TODO: describe this + +{docstring Imperative.MetaDataElem.Field} + +{docstring Imperative.MetaDataElem.Value} + +{docstring Imperative.MetaDataElem} + +{docstring Imperative.MetaData} From d365c3e61199b358c894492a77619a896fbded49 Mon Sep 17 00:00:00 2001 From: Aaron Tomb Date: Wed, 26 Nov 2025 16:10:05 -0800 Subject: [PATCH 10/22] Temporarily disable `--wfail` There are still some missing docstrings. We should re-enable this before merging. --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b8e2d2875..fc3d5f414 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -125,7 +125,7 @@ jobs: - name: Build documentation package uses: leanprover/lean-action@v1 with: - build-args: '--wfail' + #build-args: '--wfail' lake-package-directory: 'docs/verso' - name: Build documentation run: ./generate.sh From fa14c3ac4670f3752c44693dd25cbdb4f17ede6c Mon Sep 17 00:00:00 2001 From: Josh Cohen Date: Tue, 9 Dec 2025 16:05:41 -0500 Subject: [PATCH 11/22] Add comments to HasType and other changes about LExpr --- Strata/DL/Lambda/LExprTypeSpec.lean | 48 ++++++++++++++++++++++------- docs/verso/LangDefDoc.lean | 11 ++++--- docs/verso/lake-manifest.json | 12 +++++++- 3 files changed, 55 insertions(+), 16 deletions(-) diff --git a/Strata/DL/Lambda/LExprTypeSpec.lean b/Strata/DL/Lambda/LExprTypeSpec.lean index d3d9d6f64..289a40ac1 100644 --- a/Strata/DL/Lambda/LExprTypeSpec.lean +++ b/Strata/DL/Lambda/LExprTypeSpec.lean @@ -59,6 +59,10 @@ def LTy.openFull (ty: LTy) (tys: List LMonoTy) : LMonoTy := /-- Typing relation for `LExpr`s with respect to `LTy`. + +The typing relation is parameterized by two contexts. An `LContext` contains +known types and functions while a `TContext` associates free variables with +their types. -/ inductive HasType {T: LExprParams} [DecidableEq T.IDMeta] (C: LContext T): (TContext T.IDMeta) → LExpr T.mono → LTy → Prop where @@ -93,14 +97,12 @@ inductive HasType {T: LExprParams} [DecidableEq T.IDMeta] (C: LContext T): C.knownTypes.containsName "bitvec" → HasType C Γ (.bitvecConst m n b) (.forAll [] (.bitvec n)) - /-- A variable has the type recorded for it in `Γ`, if any. -/ + /-- An un-annotated variable has the type recorded for it in `Γ`, if any. -/ | tvar : ∀ Γ m x ty, Γ.types.find? x = some ty → HasType C Γ (.fvar m x none) ty /-- - For an annotated free variable (or operator, see `top_annotated`), it must be - the case that the claimed type `ty_s` is an instantiation of the general type - `ty_o`. It suffices to show the existence of a list `tys` that, when - substituted for the bound variables in `ty_o`, results in `ty_s`. + An annotated free variable has its claimed type `ty_s` if `ty_s` is an + instantiation of the type `ty_o` recorded for it in `Γ`. -/ | tvar_annotated : ∀ Γ m x ty_o ty_s tys, Γ.types.find? x = some ty_o → @@ -108,6 +110,11 @@ inductive HasType {T: LExprParams} [DecidableEq T.IDMeta] (C: LContext T): LTy.openFull ty_o tys = ty_s → HasType C Γ (.fvar m x (some ty_s)) (.forAll [] ty_s) + /-- + An abstraction `λ x.e` has type `x_ty → e_ty` if the claimed type of `x` is + `x_ty` or None and if `e` has type `e_ty` when `Γ` is extended with the + binding `(x → x_ty)`. + -/ | tabs : ∀ Γ m x x_ty e e_ty o, LExpr.fresh x e → (hx : LTy.isMonoType x_ty) → @@ -117,6 +124,11 @@ inductive HasType {T: LExprParams} [DecidableEq T.IDMeta] (C: LContext T): HasType C Γ (.abs m o e) (.forAll [] (.tcons "arrow" [(LTy.toMonoType x_ty hx), (LTy.toMonoType e_ty he)])) + + /-- + An application `e₁e₂` has type `t1` if `e₁` has type `t2 → t1` and `e₂` has + type `t2`. + -/ | tapp : ∀ Γ m e1 e2 t1 t2, (h1 : LTy.isMonoType t1) → (h2 : LTy.isMonoType t2) → @@ -125,17 +137,21 @@ inductive HasType {T: LExprParams} [DecidableEq T.IDMeta] (C: LContext T): HasType C Γ e2 t2 → HasType C Γ (.app m e1 e2) t1 - /-- If `ty` is more general than `e_ty`, we can instantiate `ty` with `e_ty`. + /-- + If expression `e` has type `ty` and `ty` is more general than `e_ty`, + then `e` has type `e_ty` (i.e. we can instantiate `ty` with `e_ty`). -/ | tinst : ∀ Γ e ty e_ty x x_ty, HasType C Γ e ty → e_ty = LTy.open x x_ty ty → HasType C Γ e e_ty - -- The generalization rule will let us do things like the following: - -- `(·ftvar "a") → (.ftvar "a")` (or `a → a`) will be generalized to - -- `(.btvar 0) → (.btvar 0)` (or `∀a. a → a`), assuming `a` is not in the - -- context. + /-- + If `e` has type `ty`, it also has type `∀ a. ty` as long as `a` is fresh. + For instance, `(·ftvar "a") → (.ftvar "a")` (or `a → a`) + can be generalized to `(.btvar 0) → (.btvar 0)` (or `∀a. a → a`), assuming + `a` is not in the context. + -/ | tgen : ∀ Γ e a ty, HasType C Γ e ty → TContext.isFresh a Γ → @@ -156,6 +172,11 @@ inductive HasType {T: LExprParams} [DecidableEq T.IDMeta] (C: LContext T): HasType C Γ e2 ty → HasType C Γ (.eq m e1 e2) (.forAll [] .bool) + /-- + A quantifier `∀/∃ {x: tr}.e` has type `bool` if the claimed type of `x` is + `x_ty` or None, and if, when `Γ` is extended with the binding `(x → x_ty)`, + `e` has type `bool` and `tr` is well-typed. + -/ | tquant: ∀ Γ m k tr tr_ty x x_ty e o, LExpr.fresh x e → (hx : LTy.isMonoType x_ty) → @@ -163,12 +184,17 @@ inductive HasType {T: LExprParams} [DecidableEq T.IDMeta] (C: LContext T): HasType C {Γ with types := Γ.types.insert x.fst x_ty} (LExpr.varOpen 0 x tr) tr_ty → o = none ∨ o = some (x_ty.toMonoType hx) → HasType C Γ (.quant m k o tr e) (.forAll [] .bool) + + /-- + An un-annotated operator has the type recorded for it in `C.functions`, if any. + -/ | top: ∀ Γ m f op ty, C.functions.find? (fun fn => fn.name == op) = some f → f.type = .ok ty → HasType C Γ (.op m op none) ty /-- - See comments in `tvar_annotated`. + Similarly to free variables, an annotated operator has its claimed type `ty_s` if `ty_s` is an + instantiation of the type `ty_o` recorded for it in `C.functions`. -/ | top_annotated: ∀ Γ m f op ty_o ty_s tys, C.functions.find? (fun fn => fn.name == op) = some f → diff --git a/docs/verso/LangDefDoc.lean b/docs/verso/LangDefDoc.lean index 6da87f69a..5409352a1 100644 --- a/docs/verso/LangDefDoc.lean +++ b/docs/verso/LangDefDoc.lean @@ -115,6 +115,8 @@ expressions parameterized by `LTy` as output. The syntax of lambda expressions is provided by the `LExpr` type. +{docstring Lambda.LConst} + {docstring Lambda.LExpr} ## Type System @@ -123,7 +125,7 @@ Although {name LExpr}`LExpr` can be parameterized by an arbitrary type system, Strata currently implements one, based on the types {name LMonoTy}`LMonoTy` and {name LTy}`LTy`. -The first, {name LMonoTy}`LMonoTy` represents monomorphic types. It's a separate type because +The first, {name LMonoTy}`LMonoTy`, represents monomorphic types. It's a separate type because some contexts allow only monomorphic types. {docstring Lambda.LMonoTy} @@ -133,7 +135,8 @@ quantifiers, creating polymorphic types. {docstring Lambda.LTy} -The relationshp between {name LExpr}`LExpr` and {name LTy}`LTy` is expressed by the +A expression {name LExpr}`LExpr` parameterized by {name LTy}`LTy` is well-typed +according to the {name LExpr.HasType}`HasType` relation. {docstring Lambda.LExpr.HasType} @@ -142,10 +145,10 @@ The relationshp between {name LExpr}`LExpr` and {name LTy}`LTy` is expressed by ## Operational Semantics -TODO: talk about `Factory` - The semantics of the {name LExpr}`LExpr` type are specified in a standard way using the small-step inductive relation {name Lambda.Step}`Lambda.Step`. +This relation is parameterized by a `Factory`, which describes built-in +functions via an optional body and/or evaluation function. {docstring Lambda.Step} diff --git a/docs/verso/lake-manifest.json b/docs/verso/lake-manifest.json index 1685d6858..4d33a7350 100644 --- a/docs/verso/lake-manifest.json +++ b/docs/verso/lake-manifest.json @@ -37,6 +37,16 @@ "manifestFile": "lake-manifest.json", "inputRev": "main", "inherited": true, - "configFile": "lakefile.lean"}], + "configFile": "lakefile.lean"}, + {"url": "https://github.com/leanprover-community/plausible.git", + "type": "git", + "subDir": null, + "scope": "", + "rev": "b949552f6ca8e223f424b3e3b33f74185bbf1179", + "name": "plausible", + "manifestFile": "lake-manifest.json", + "inputRev": "b949552f6ca8e223f424b3e3b33f74185bbf1179", + "inherited": true, + "configFile": "lakefile.toml"}], "name": "StrataDoc", "lakeDir": ".lake"} From d93ab0e7c851c191c83b2a3fb49ffb155585ae58 Mon Sep 17 00:00:00 2001 From: Aaron Tomb Date: Fri, 5 Dec 2025 14:32:59 -0800 Subject: [PATCH 12/22] Edits to language definition doc --- docs/verso/LangDefDoc.lean | 130 +++++++++++++++++++++++-------------- 1 file changed, 80 insertions(+), 50 deletions(-) diff --git a/docs/verso/LangDefDoc.lean b/docs/verso/LangDefDoc.lean index 5409352a1..b7ba4e618 100644 --- a/docs/verso/LangDefDoc.lean +++ b/docs/verso/LangDefDoc.lean @@ -46,41 +46,41 @@ provides a way to define the syntax and a simple type system for what we call a dialect of Strata. At the moment, these dialects do not directly have semantics (though we may add a mechanism for defining their semantics in the future) but instead are defined by translation to or from the second notion of language, -Strata’s Core languages. Said another way, each of these dialects is a different +Strata’s Core language. Said another way, each of these dialects is a different concrete way to write Strata programs, but all of these dialects are ultimately -represented internally using the same Core languages. +represented internally using the same Core language. Dialects are used to describe both the initial artifacts being analyzed by Strata and more low-level representations of those artifacts used to communicate -with external reasoning tools. In both situations, Stata uses dialects as a -mechanism for communicating with external tools (either language front ends or -generic automated reasoning tools like SMT solvers). +with external reasoning tools such as model checkers or SMT solvers. In both +situations, Stata uses dialects as a mechanism for communicating with external +tools (either language front ends or generic automated reasoning tools like SMT +solvers). (TODO: funnel diagram showing various dialects in relation to Strata Core) -The Strata Core languages consist of a few building blocks that can be combined +The Strata Core language consists of a few building blocks that can be combined in different ways. This allows concrete dialects to systematically use different combinations that still share the majority of their implementation. In Lean (and in principle in most other source languages that could be used to process Strata programs), the type system can enforce various structural constraints, ensuring that only expected language constructs show up. The most common use of the -Strata Core languages is in combination: with an imperative statement type -parameterized by an expression type, and with various more fine-grained -adjustments of other parameters. Because these building blocks are typically -used together, it’s reasonable to think of Strata Core as a single language that -can be configured in various ways for different use cases. +Strata Core language is with an imperative statement type parameterized by an +expression type, and with various more fine-grained adjustments of other +parameters. Because these building blocks are typically used together, it’s +reasonable to think of Strata Core as a single language that can be configured +in various ways for different use cases, even though it consists of multiple +independent types in the Lean implementation. The two fundamental building blocks of Strata Core are a representation of functional programs (`Lambda`), and a representation of imperative programs -(`Imperative`). The `Lambda` language is parameterized by a type system (TODO: -and can be constrained to allow or disallow complex features such as lambda -abstractions and quantifiers). `Lambda` is also parameterized by a set of -built-in types and functions. The `Imperative` language is then parameterized by -the type of expressions it allows in conditions, assignments, and so on. -Currently, those expressions will almost always be some instantiation of -`Lambda`. Both Core building blocks are parameterized by a metadata type, -which by default is instantiated with a map from keys to structured values that -can contain expressions (typically from `Lambda`). +(`Imperative`). The `Lambda` language is parameterized by a type system and a +set of built-in types and functions. The `Imperative` language is then +parameterized by the type of expressions it allows in conditions, assignments, +and so on. Currently, those expressions will almost always be some +instantiation of `Lambda`. Both Core building blocks are parameterized by a +metadata type, which by default is instantiated with a map from keys to +structured values that can contain expressions (typically from `Lambda`). The remainder of this document describes the current abstract syntax and semantics of `Lambda` and `Imperative` in detail, with direct reference to the @@ -98,7 +98,7 @@ applications. In addition, it includes a special type of constant, an operator, to represent built-in functions. It extends the standard lambda calculus by allowing quantifiers (since a key use of the language is to write logical predicates) and includes constructors for if-then-else and equality functions, -since those are so commonly used. +since those are so commonly used. (TODO: we might remove these last two) Although `Lambda` can be parameterized by an arbitrary type system, the Strata code base includes an implementation of a polymorphic Hindley-Milner type system @@ -108,43 +108,80 @@ named type constructors (as well as special support for bit vector types, to allow them to be parameterized by size). Type inference and checking with this type system takes as input expressions -parameterized by `Unit` as the type of types (TODO: is this true?), and produces -expressions parameterized by `LTy` as output. +parameterized by {name Unit}`Unit` as the type of types (TODO: is this true?), +and produces expressions parameterized by {name LTy}`LTy` as output. ## Syntax -The syntax of lambda expressions is provided by the `LExpr` type. +The syntax of lambda expressions is provided by the {name LExpr}`LExpr` type. {docstring Lambda.LConst} {docstring Lambda.LExpr} +Identifiers in lambda expressions, using the {name Identifier}`Identifier` type, +can be annotated with metadata. + +{docstring Lambda.Identifier} + +Specific constructors exist for constants of various scalar types, including +booleans, bit vectors, integers, reals, and strings. + +{docstring Lambda.LConst} + +The {name LExpr}`LExpr` type can be parameterized by the type used to represent +normal metadata and the type used to represent identifier metadata, as well as +the type of types. + +{docstring Lambda.LExprParams} + +{docstring Lambda.LExprParamsT} + ## Type System Although {name LExpr}`LExpr` can be parameterized by an arbitrary type system, Strata currently implements one, based on the types {name LMonoTy}`LMonoTy` and {name LTy}`LTy`. -The first, {name LMonoTy}`LMonoTy`, represents monomorphic types. It's a separate type because -some contexts allow only monomorphic types. +The first, {name LMonoTy}`LMonoTy`, represents monomorphic types. It's a +separate type because some contexts allow only monomorphic types. {docstring Lambda.LMonoTy} +Type variables in {name LMonoTy}`LMonoTy` use the {name TyIdentifier}`TyIdentifier` type. + +{docstring Lambda.TyIdentifier} + The {name LTy}`LTy` type allows monomorphic types to be wrapped in universal type -quantifiers, creating polymorphic types. +quantifiers that bind these type variables, creating polymorphic types. {docstring Lambda.LTy} -A expression {name LExpr}`LExpr` parameterized by {name LTy}`LTy` is well-typed -according to the -{name LExpr.HasType}`HasType` relation. +A expression {name LExpr}`LExpr` parameterized by {name LTy}`LTy` is +well-typed according to the {name LExpr.HasType}`HasType` relation. +This relation depends on two types of context. -{docstring Lambda.LExpr.HasType} +The first of these, {name LContext}`LContext`, contains information that does +not change throughout the type checking process, including built-in functions +and types. TODO: talk about Factory and TypeFactory? -(TODO: talk about the type inference implementation?) +{docstring Lambda.LContext} + +The second context includes two pieces of data that change throughout the type +checking process: a map from free variables in expressions to types, and a list +of type aliases including the name and definition of each alias. + +{docstring Lambda.TContext} + +Given these two pieces of context, the {name LExpr.HasType}`HasType` relation +describes the valid type of each expression form. + +{docstring Lambda.LExpr.HasType} ## Operational Semantics +TODO: talk about how `Factory` fits into the operational semantics + The semantics of the {name LExpr}`LExpr` type are specified in a standard way using the small-step inductive relation {name Lambda.Step}`Lambda.Step`. This relation is parameterized by a `Factory`, which describes built-in @@ -168,9 +205,9 @@ The `Imperative` language is a standard core imperative calculus, parameterized by a type of expressions and divided into two pieces: commands and statements. Commands represent atomic operations that do not induce control flow (except possibly in the form of procedure calls that follow a stack discipline, though -the current core set of commands does not include calls). Statements are +the current core set of commands does not include calls). Statements are parameterized by a command type and describe the control flow surrounding those -commands. Statements exist in three forms, corresponding to the most common +commands. Statements exist in two forms, corresponding to the most common alternative representations. These forms are: * Structured deterministic statements, each of which can be: a command, a @@ -181,14 +218,14 @@ alternative representations. These forms are: sequence of two statements, an arbitrary choice between two statements, or an iteration of a statement an arbitrary number of times. -* Unstructured control-flow graphs where each basic block consists of a sequence - of commands followed by a terminator command. A terminator command can be: a - conditional jump to one of two blocks, termination of execution, or a - non-deterministic jump to any one of an arbitrary number of successor blocks. +A translation exists from structured deterministic statements into structured +non-deterministic statements. -Translations exist from structured deterministic statements into either -structured non-deterministic statements or unstructured control-flow graphs. -(TODO: point to these translations) +We also expect to add unstructured control-flow graphs where each basic block +consists of a sequence of commands followed by a terminator command. A +terminator command can be: a conditional jump to one of two blocks, termination +of execution, or a non-deterministic jump to any one of an arbitrary number of +successor blocks. ## Command Syntax @@ -225,7 +262,8 @@ a standard way. ## Structured Deterministic Statement Syntax Statements allow commands to be organized into standard control flow -arrangements, including sequencing, alternation, and iteration. +arrangements, including sequencing, alternation, and iteration. Sequencing +statements occurs by grouping them into blocks. (TODO: say more about loop invariants, measures?) @@ -263,14 +301,6 @@ relation. {docstring Imperative.EvalNondetStmt} -## Unstructured Control-Flow Graph Syntax - -TODO: fill in once it's merged - -## Unstructured Control-Flow Graph Semantics - -TODO: fill in once it's merged - # Metadata TODO: describe this From 3731cd3fd0495de50e6af3a802057495452832da Mon Sep 17 00:00:00 2001 From: Aaron Tomb Date: Mon, 15 Dec 2025 12:55:44 -0800 Subject: [PATCH 13/22] Update dependencies; fewer TODOs --- docs/verso/LangDefDoc.lean | 33 +++++++++++++++++++++------------ docs/verso/lake-manifest.json | 28 ++++++++++++++-------------- docs/verso/lakefile.toml | 2 +- docs/verso/lean-toolchain | 2 +- 4 files changed, 37 insertions(+), 28 deletions(-) diff --git a/docs/verso/LangDefDoc.lean b/docs/verso/LangDefDoc.lean index dc5c9cd63..cbb894565 100644 --- a/docs/verso/LangDefDoc.lean +++ b/docs/verso/LangDefDoc.lean @@ -108,15 +108,14 @@ predicates) and includes a constructor for if-then-else to allow it to have lazy semantics. Although `Lambda` can be parameterized by an arbitrary type system, the Strata -code base includes an implementation of a polymorphic Hindley-Milner type system -(TODO: link) and inference algorithm (TODO: link) over the type `LTy` (described -below). This allows universal quantification over types and the use of arbitrary -named type constructors (as well as special support for bit vector types, to -allow them to be parameterized by size). - -Type inference and checking with this type system takes as input expressions -parameterized by {name Unit}`Unit` as the type of types (TODO: is this true?), -and produces expressions parameterized by {name LTy}`LTy` as output. +code base includes a +[formalization](https://github.com/strata-org/Strata/blob/main/Strata/DL/Lambda/LExprTypeSpec.lean) +of a polymorphic Hindley-Milner type system and an +[implementation](https://github.com/strata-org/Strata/blob/main/Strata/DL/Lambda/LTyUnify.lean) +of an inference algorithm over the type `LTy` (described below). This allows +universal quantification over types and the use of arbitrary named type +constructors (as well as special support for bit vector types, to allow them to +be parameterized by size). ## Syntax @@ -268,9 +267,9 @@ a standard way. Statements allow commands to be organized into standard control flow arrangements, including sequencing, alternation, and iteration. Sequencing -statements occurs by grouping them into blocks. - -(TODO: say more about loop invariants, measures?) +statements occurs by grouping them into blocks. Loops can be annotated with +optional invariants and decreasing measures, which can be used for deductive +verification. {docstring Imperative.Stmt} @@ -306,10 +305,20 @@ AST. This may include information such as the provenance of specific AST nodes specific analyses, of indications of the goal of a specific analysis, among many other possibilities. +Each metadata element maps a field to a value. A field can be named with a +variable or an arbitrary string. + {docstring Imperative.MetaDataElem.Field} +A value can take the form of an expression or an arbitrary string. + {docstring Imperative.MetaDataElem.Value} +A metadata element pairs a field with a value. + {docstring Imperative.MetaDataElem} +And, finally, the metadata attached to an AST node consists of an array of +metadata elements. + {docstring Imperative.MetaData} diff --git a/docs/verso/lake-manifest.json b/docs/verso/lake-manifest.json index 4d33a7350..aac17d200 100644 --- a/docs/verso/lake-manifest.json +++ b/docs/verso/lake-manifest.json @@ -5,10 +5,10 @@ "type": "git", "subDir": null, "scope": "", - "rev": "f1010398410d85ca53dd3a7ffbe66d98eaccd882", + "rev": "8ba8c1ee844cd4a4ef1957801780c6e99e469897", "name": "verso", "manifestFile": "lake-manifest.json", - "inputRev": "v4.24.0", + "inputRev": "v4.25.1", "inherited": false, "configFile": "lakefile.lean"}, {"type": "path", @@ -18,35 +18,35 @@ "inherited": false, "dir": "../..", "configFile": "lakefile.toml"}, - {"url": "https://github.com/acmepjz/md4lean", + {"url": "https://github.com/leanprover-community/plausible", "type": "git", "subDir": null, "scope": "", - "rev": "66aefec2852d3e229517694e642659f316576591", - "name": "MD4Lean", + "rev": "8864a73bf79aad549e34eff972c606343935106d", + "name": "plausible", "manifestFile": "lake-manifest.json", "inputRev": "main", "inherited": true, - "configFile": "lakefile.lean"}, - {"url": "https://github.com/leanprover/subverso", + "configFile": "lakefile.toml"}, + {"url": "https://github.com/acmepjz/md4lean", "type": "git", "subDir": null, "scope": "", - "rev": "767f10408ca8abe29a15add2bf111eefdd9522b2", - "name": "subverso", + "rev": "66aefec2852d3e229517694e642659f316576591", + "name": "MD4Lean", "manifestFile": "lake-manifest.json", "inputRev": "main", "inherited": true, "configFile": "lakefile.lean"}, - {"url": "https://github.com/leanprover-community/plausible.git", + {"url": "https://github.com/leanprover/subverso", "type": "git", "subDir": null, "scope": "", - "rev": "b949552f6ca8e223f424b3e3b33f74185bbf1179", - "name": "plausible", + "rev": "7347ddaca36e59238bf1fc210a6bf71dd0bccdd6", + "name": "subverso", "manifestFile": "lake-manifest.json", - "inputRev": "b949552f6ca8e223f424b3e3b33f74185bbf1179", + "inputRev": "main", "inherited": true, - "configFile": "lakefile.toml"}], + "configFile": "lakefile.lean"}], "name": "StrataDoc", "lakeDir": ".lake"} diff --git a/docs/verso/lakefile.toml b/docs/verso/lakefile.toml index d2fa71c53..11162158d 100644 --- a/docs/verso/lakefile.toml +++ b/docs/verso/lakefile.toml @@ -8,7 +8,7 @@ path = "../.." [[require]] name = "verso" git = "https://github.com/leanprover/verso" -rev = "v4.24.0" +rev = "v4.25.1" [[lean_lib]] name = "DDMDoc" diff --git a/docs/verso/lean-toolchain b/docs/verso/lean-toolchain index c00a53503..370b26d9c 100644 --- a/docs/verso/lean-toolchain +++ b/docs/verso/lean-toolchain @@ -1 +1 @@ -leanprover/lean4:v4.24.0 +leanprover/lean4:v4.25.2 From 82624d11abdb76dda15a50c87d86cf389efe97b6 Mon Sep 17 00:00:00 2001 From: Aaron Tomb Date: Mon, 15 Dec 2025 13:08:19 -0800 Subject: [PATCH 14/22] A few more docstrings --- Strata/DL/Lambda/Identifiers.lean | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Strata/DL/Lambda/Identifiers.lean b/Strata/DL/Lambda/Identifiers.lean index 3f1b24354..82944ec1c 100644 --- a/Strata/DL/Lambda/Identifiers.lean +++ b/Strata/DL/Lambda/Identifiers.lean @@ -20,7 +20,10 @@ section Identifiers Identifiers with a name and additional metadata -/ structure Identifier (IDMeta : Type) : Type where + /-- A unique name. -/ name : String + /-- Any additional metadata that it would be useful to attach to an + identifier. -/ metadata : IDMeta deriving Repr, DecidableEq, Inhabited From b99da3ada3f97401952e60b5fe666508ae9c0a4d Mon Sep 17 00:00:00 2001 From: Aaron Tomb Date: Mon, 15 Dec 2025 14:35:56 -0800 Subject: [PATCH 15/22] Improve text; add diagram --- docs/verso/LangDefDoc.lean | 39 ++++++++++++++++---------------- docs/verso/generate.sh | 1 + docs/verso/strata-hourglass.png | Bin 0 -> 62032 bytes 3 files changed, 20 insertions(+), 20 deletions(-) create mode 100644 docs/verso/strata-hourglass.png diff --git a/docs/verso/LangDefDoc.lean b/docs/verso/LangDefDoc.lean index cbb894565..80b22c63c 100644 --- a/docs/verso/LangDefDoc.lean +++ b/docs/verso/LangDefDoc.lean @@ -58,11 +58,15 @@ ultimately represented internally using the same Core language. Dialects are used to describe both the initial artifacts being analyzed by Strata and more low-level representations of those artifacts used to communicate with external reasoning tools such as model checkers or SMT solvers. In both -situations, Stata uses dialects as a mechanism for communicating with external +situations, Strata uses dialects as a mechanism for communicating with external tools (either language front ends or generic automated reasoning tools like SMT solvers). -(TODO: hourglass diagram showing various dialects in relation to Strata Core) +The following "hourglass" diagram illustrates how various existing (blue) or +hypothetical (gray) input dialects could be translated into Strata Core and +then into the input language for various back end tools. + +![Strata hourglass diagram](strata-hourglass.png) The Strata Core language is constructed using a few building blocks that can be combined in different ways. This allows concrete dialects to systematically use @@ -92,8 +96,8 @@ fundamental constructs, and this document will be updated as it does. We intend for Strata Core to be close to a superset of [B3](https://b3-lang.org/), but it may at times make different choices to support its goal of being useful for a wide range of analyses, rather than being optimized for deductive verification. - -TODO: for everything below, describe what the parameters for Strata Core are. +In particular, Strata aims to make it possible to encode most input artifacts +without the need for axioms. # Lambda @@ -161,7 +165,7 @@ quantifiers that bind these type variables, creating polymorphic types. {docstring Lambda.LTy} -A expression {name LExpr}`LExpr` parameterized by {name LTy}`LTy` is +An expression {name LExpr}`LExpr` parameterized by {name LTy}`LTy` is well-typed according to the {name LExpr.HasType}`HasType` relation. This relation depends on two types of context. @@ -209,20 +213,15 @@ Commands represent atomic operations that do not induce control flow (except possibly in the form of procedure calls that follow a stack discipline, though the current core set of commands does not include calls). Statements are parameterized by a command type and describe the control flow surrounding those -commands. Statements exist in two forms, corresponding to the most common -alternative representations. These forms are: - -* Structured deterministic statements, each of which can be: a command, a - sequence of statements in a block, a deterministic conditional, a deterministic - loop with a condition, or a forward `goto` statement. (Note: we plan to replace - `goto` with a block exit statement, and have a separate unstructured CFG - representation. - -* Structured non-deterministic statements, each of which can be: a command, a - sequence of two statements, an arbitrary choice between two statements, or an - iteration of a statement an arbitrary number of times. - -A translation exists from structured deterministic statements into structured +commands. Currently, `Imperative` has structured, deterministic statements, each +of which can be: a command, a sequence of statements in a block, a deterministic +conditional, a deterministic loop with a condition, or a forward `goto` +statement. (Note: we plan to replace `goto` with a block exit statement, and +have a separate unstructured CFG representation.) + +We plan to add non-deterministic statements, as in [Kleene Algebra with +Tests](https://www.cs.cornell.edu/~kozen/Papers/kat.pdf), and support a +translation from structured deterministic statements into structured non-deterministic statements. We also expect to add unstructured control-flow graphs where each basic block @@ -302,7 +301,7 @@ relation. Metadata allows additional information to be attached to nodes in the Strata AST. This may include information such as the provenance of specific AST nodes (_e.g._, the locations in source code that gave rise to them), facts inferred by -specific analyses, of indications of the goal of a specific analysis, among many +specific analyses, or indications of the goal of a specific analysis, among many other possibilities. Each metadata element maps a field to a value. A field can be named with a diff --git a/docs/verso/generate.sh b/docs/verso/generate.sh index c611570fe..92a4ba4d9 100755 --- a/docs/verso/generate.sh +++ b/docs/verso/generate.sh @@ -2,3 +2,4 @@ set -ex lake exe ddm --with-html-single --output _out/ddm lake exe langdef --with-html-single --output _out/langdef +cp strata-hourglass.png _out/langdef/html-single/ diff --git a/docs/verso/strata-hourglass.png b/docs/verso/strata-hourglass.png new file mode 100644 index 0000000000000000000000000000000000000000..0048234939e14be22d7fc055ff9c158cfeb2dafe GIT binary patch literal 62032 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 a$rCr1i2r%@EWtD6NAbO?T)B)<@c#hn(ZaL< literal 0 HcmV?d00001 From ad3c77e8b140a5d89ac16a6d47a352e8610fddcc Mon Sep 17 00:00:00 2001 From: Aaron Tomb Date: Wed, 17 Dec 2025 16:00:31 -0800 Subject: [PATCH 16/22] Apply suggestion from @MikaelMayer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Mikaël Mayer --- Strata/DL/Imperative/Cmd.lean | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Strata/DL/Imperative/Cmd.lean b/Strata/DL/Imperative/Cmd.lean index e8cd07a34..df8725137 100644 --- a/Strata/DL/Imperative/Cmd.lean +++ b/Strata/DL/Imperative/Cmd.lean @@ -38,7 +38,7 @@ inductive Cmd (P : PureExpr) : Type where | init (name : P.Ident) (ty : P.Ty) (e : P.Expr) (md : (MetaData P) := .empty) /-- Assign `e` to a pre-existing variable `name`. -/ | set (name : P.Ident) (e : P.Expr) (md : (MetaData P) := .empty) - /-- Assign a random value to a pre-existing variable `name`. -/ + /-- Assigns an arbitrary value to an existing variable `name`. -/ | havoc (name : P.Ident) (md : (MetaData P) := .empty) /-- Check whether condition `b` is true, failing if not. -/ | assert (label : String) (b : P.Expr) (md : (MetaData P) := .empty) From 859a7a7af228f71b4ad0232070b43cfdea123be4 Mon Sep 17 00:00:00 2001 From: Aaron Tomb Date: Wed, 17 Dec 2025 16:00:53 -0800 Subject: [PATCH 17/22] Apply suggestion from @MikaelMayer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Mikaël Mayer --- Strata/DL/Imperative/Cmd.lean | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Strata/DL/Imperative/Cmd.lean b/Strata/DL/Imperative/Cmd.lean index df8725137..09cb3a193 100644 --- a/Strata/DL/Imperative/Cmd.lean +++ b/Strata/DL/Imperative/Cmd.lean @@ -42,7 +42,7 @@ inductive Cmd (P : PureExpr) : Type where | havoc (name : P.Ident) (md : (MetaData P) := .empty) /-- Check whether condition `b` is true, failing if not. -/ | assert (label : String) (b : P.Expr) (md : (MetaData P) := .empty) - /-- Constrain execution to the states in which `b` is true. -/ + /-- Ignore any execution state in which `b` is not true. -/ | assume (label : String) (b : P.Expr) (md : (MetaData P) := .empty) abbrev Cmds (P : PureExpr) := List (Cmd P) From 3ec57aa89c3a189d304678fe02c449ec6b5e2f3c Mon Sep 17 00:00:00 2001 From: Aaron Tomb Date: Wed, 17 Dec 2025 16:13:15 -0800 Subject: [PATCH 18/22] Add final missing docstrings --- Strata/DL/Imperative/MetaData.lean | 6 ++++++ Strata/DL/Lambda/LExpr.lean | 4 ++++ Strata/DL/Lambda/LTy.lean | 1 + 3 files changed, 11 insertions(+) diff --git a/Strata/DL/Imperative/MetaData.lean b/Strata/DL/Imperative/MetaData.lean index 78c7d2180..45ed2ff09 100644 --- a/Strata/DL/Imperative/MetaData.lean +++ b/Strata/DL/Imperative/MetaData.lean @@ -30,7 +30,9 @@ For now, we only track the variables modified by a construct, but we will expand this in the future. -/ inductive MetaDataElem.Field (P : PureExpr) where + /-- Metadata indexed by a Strata variable. -/ | var (v : P.Ident) + /-- Metadata indexed by an arbitrary label. -/ | label (l : String) @[grind] @@ -63,7 +65,9 @@ instance [Repr P.Ident] : Repr (MetaDataElem.Field P) where /-- A metadata value, which can be either an expression or a message. -/ inductive MetaDataElem.Value (P : PureExpr) where + /-- Metadata value in the form of a structured expression. -/ | expr (e : P.Expr) + /-- Metadata value in the form of an arbitrary string. -/ | msg (s : String) instance [ToFormat P.Expr] : ToFormat (MetaDataElem.Value P) where @@ -103,7 +107,9 @@ instance [DecidableEq P.Expr] : DecidableEq (MetaDataElem.Value P) := /-- A metadata element -/ structure MetaDataElem (P : PureExpr) where + /-- The field or key used to identify the metadata. -/ fld : MetaDataElem.Field P + /-- The value of the metadata. -/ value : MetaDataElem.Value P /-- Metadata is an array of tagged elements. -/ diff --git a/Strata/DL/Lambda/LExpr.lean b/Strata/DL/Lambda/LExpr.lean index 4996785bc..ee45f8827 100644 --- a/Strata/DL/Lambda/LExpr.lean +++ b/Strata/DL/Lambda/LExpr.lean @@ -42,7 +42,9 @@ Expected interface for pure expressions that can be used to specialize the Imperative dialect. -/ structure LExprParams : Type 1 where + /-- The type of metadata allowed on expressions. -/ Metadata: Type + /-- The type of metadata allowed on identifiers. -/ IDMeta : Type deriving Inhabited @@ -50,7 +52,9 @@ structure LExprParams : Type 1 where Extended LExprParams that includes TypeType parameter. -/ structure LExprParamsT : Type 1 where + /-- The base parameters, with the types for expression and identifier metadata. -/ base : LExprParams + /-- The type of types used to annotate expressions. -/ TypeType : Type deriving Inhabited diff --git a/Strata/DL/Lambda/LTy.lean b/Strata/DL/Lambda/LTy.lean index af60a2ae2..296644d1a 100644 --- a/Strata/DL/Lambda/LTy.lean +++ b/Strata/DL/Lambda/LTy.lean @@ -20,6 +20,7 @@ namespace Lambda open Std (ToFormat Format format) +/-- Type identifiers. For now, these are just strings. -/ abbrev TyIdentifier := String instance : Coe String TyIdentifier where From ffced95cbefdc3ea93eb819ff38c9a82bb79e677 Mon Sep 17 00:00:00 2001 From: Aaron Tomb Date: Wed, 17 Dec 2025 16:13:37 -0800 Subject: [PATCH 19/22] Move back to build failure on missing docstrings --- .github/workflows/ci.yml | 2 +- docs/verso/LangDefDoc.lean | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fc3d5f414..b8e2d2875 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -125,7 +125,7 @@ jobs: - name: Build documentation package uses: leanprover/lean-action@v1 with: - #build-args: '--wfail' + build-args: '--wfail' lake-package-directory: 'docs/verso' - name: Build documentation run: ./generate.sh diff --git a/docs/verso/LangDefDoc.lean b/docs/verso/LangDefDoc.lean index 80b22c63c..f3307114a 100644 --- a/docs/verso/LangDefDoc.lean +++ b/docs/verso/LangDefDoc.lean @@ -28,7 +28,7 @@ open Verso.Genre Manual open Verso.Genre.Manual.InlineLean set_option pp.rawOnError true -set_option verso.docstring.allowMissing true +set_option verso.docstring.allowMissing false #doc (Manual) "The Strata Language Definition" => %%% From d77d9c5a046d3a1ba455a849e6c77c8dc5ed4acd Mon Sep 17 00:00:00 2001 From: Aaron Tomb Date: Wed, 17 Dec 2025 16:18:18 -0800 Subject: [PATCH 20/22] Resolve comments from @MikaelMayer --- Strata/DL/Imperative/Cmd.lean | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Strata/DL/Imperative/Cmd.lean b/Strata/DL/Imperative/Cmd.lean index 09cb3a193..b297bc723 100644 --- a/Strata/DL/Imperative/Cmd.lean +++ b/Strata/DL/Imperative/Cmd.lean @@ -30,11 +30,12 @@ variable declaration and assignment, and assertions and assumptions. /-- A an atomic command in the `Imperative` dialect. -Commands generally don't involve control flow on their own, and are typically -used as a parameter to `Imperative.Stmt` or other similar types. +Commands don't create local control flow, and are typically used as a parameter +to `Imperative.Stmt` or other similar types. -/ inductive Cmd (P : PureExpr) : Type where - /-- Define a variable called `name` with type `ty` and initial value `e`. -/ + /-- Define a variable called `name` with type `ty` and initial value `e`. + Note: we may make the initial value optional. -/ | init (name : P.Ident) (ty : P.Ty) (e : P.Expr) (md : (MetaData P) := .empty) /-- Assign `e` to a pre-existing variable `name`. -/ | set (name : P.Ident) (e : P.Expr) (md : (MetaData P) := .empty) From 345328aecb4db5a2ae03a7564629692c4a29017f Mon Sep 17 00:00:00 2001 From: Aaron Tomb Date: Thu, 18 Dec 2025 12:52:45 -0800 Subject: [PATCH 21/22] Update hourglass diagram and description It now more clearly indicates what exists and what doesn't so far. --- docs/verso/LangDefDoc.lean | 8 ++++++-- docs/verso/strata-hourglass.png | Bin 62032 -> 58222 bytes 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/verso/LangDefDoc.lean b/docs/verso/LangDefDoc.lean index f3307114a..ceadf0b66 100644 --- a/docs/verso/LangDefDoc.lean +++ b/docs/verso/LangDefDoc.lean @@ -63,8 +63,12 @@ tools (either language front ends or generic automated reasoning tools like SMT solvers). The following "hourglass" diagram illustrates how various existing (blue) or -hypothetical (gray) input dialects could be translated into Strata Core and -then into the input language for various back end tools. +potential (gray) input dialects could be translated into Strata Core and then +into the input language for various back end tools. Solid lines indicate +translation paths that exist (though experimentally in the connection between +Strata Core and CBMC), and dotted lines indicate translations that illustrate +the sorts of use cases we expect Strata to support but that haven't yet been +implemented. ![Strata hourglass diagram](strata-hourglass.png) diff --git a/docs/verso/strata-hourglass.png b/docs/verso/strata-hourglass.png index 0048234939e14be22d7fc055ff9c158cfeb2dafe..44d7261ac1afcaf354f0e7bf2ad4cd6af6bf0005 100644 GIT binary patch literal 58222 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 literal 62032 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 a$rCr1i2r%@EWtD6NAbO?T)B)<@c#hn(ZaL< From 78a55949b7164cf71e470023e0be4a2ff6cf56cf Mon Sep 17 00:00:00 2001 From: Andrew Wells <130512013+andrewmwells-amazon@users.noreply.github.com> Date: Thu, 18 Dec 2025 13:50:49 -0600 Subject: [PATCH 22/22] PyAnalyze While and FloorDiv (#283) Add handling of while loops and FloorDiv. Increase types we support for Mult. By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice. --- Strata/Languages/Python/PythonToBoogie.lean | 96 +++++++++++++-------- 1 file changed, 59 insertions(+), 37 deletions(-) diff --git a/Strata/Languages/Python/PythonToBoogie.lean b/Strata/Languages/Python/PythonToBoogie.lean index faa3cef54..685fe7fe2 100644 --- a/Strata/Languages/Python/PythonToBoogie.lean +++ b/Strata/Languages/Python/PythonToBoogie.lean @@ -41,6 +41,34 @@ def dummyDate : Boogie.Expression.Expr := .fvar () "DUMMY_DATE" none def timedeltaType : Boogie.Expression.Ty := .forAll [] (.tcons "int" []) def dummyTimedelta : Boogie.Expression.Expr := .fvar () "DUMMY_Timedelta" none +------------------------------------------------------------------------------- + +-- Translating a Python expression can require Boogie statements, e.g., a function call +-- We translate these by first defining temporary variables to store the results of the stmts +-- and then using those variables in the expression. +structure PyExprTranslated where + stmts : List Boogie.Statement + expr: Boogie.Expression.Expr + post_stmts : List Boogie.Statement := [] +deriving Inhabited + + +structure PythonFunctionDecl where + name : String + args : List (String × String) -- Elements are (arg_name, arg_ty) where `arg_ty` is the string representation of the type in Python + ret : String +deriving Repr, BEq, Inhabited + +structure PythonClassDecl where + name : String +deriving Repr, BEq, Inhabited + +structure TranslationContext where + expectedType : Option (Lambda.LMonoTy) + variableTypes : List (String × Lambda.LMonoTy) + func_infos : List PythonFunctionDecl + class_infos : List PythonClassDecl +deriving Inhabited ------------------------------------------------------------------------------- @@ -95,15 +123,23 @@ def handleSub (lhs rhs: Boogie.Expression.Expr) : Boogie.Expression.Expr := | (.tcons "Datetime" []), (.tcons "int" []) => .app () (.app () (.op () "Datetime_sub" none) lhs) rhs | _, _ => panic! s!"Unimplemented add op for {lhs} + {rhs}" -def handleMult (lhs rhs: Boogie.Expression.Expr) : Boogie.Expression.Expr := - let lty : Lambda.LMonoTy := mty[string] - let rty : Lambda.LMonoTy := mty[int] - match lty, rty with - | (.tcons "string" []), (.tcons "int" []) => - match lhs, rhs with - | .strConst () s, .intConst () i => .strConst () (String.join (List.replicate i.toNat s)) - | _, _ => panic! s!"We only handle str * int for constant strings and ints. Got: {lhs} and {rhs}" - | _, _ => panic! s!"Unimplemented add op for {lhs} + {rhs}" +def handleMult (translation_ctx: TranslationContext) (lhs rhs: Boogie.Expression.Expr) : Boogie.Expression.Expr := + match lhs, rhs with + | .strConst () s, .intConst () i => .strConst () (String.join (List.replicate i.toNat s)) + | .intConst () l, .intConst () r => .intConst () (l * r) + | .fvar () l _, .fvar () r _ => + let l := translation_ctx.variableTypes.find? (λ p => p.fst == l.name) + let r := translation_ctx.variableTypes.find? (λ p => p.fst == r.name) + match l, r with + | .some lty, .some rty => + match lty.snd, rty.snd with + | .tcons "int" [], .tcons "int" [] => .app () (.app () (.op () "Int.Mul" mty[int → (int → int)]) lhs) rhs + | _, _ => panic! s!"Unsupported types for fvar *. Types: {lty} and {rty}" + | _, _ => panic! s!"Missing needed type information for *. Exprs: {lhs} and {rhs}" + | _ , _ => panic! s!"Unsupported args for * . Got: {lhs} and {rhs}" + +def handleFloorDiv (_translation_ctx: TranslationContext) (lhs rhs: Boogie.Expression.Expr) : Boogie.Expression.Expr := + .app () (.app () (.op () "Int.Div" mty[int → (int → int)]) lhs) rhs def handleNot (arg: Boogie.Expression.Expr) : Boogie.Expression.Expr := let ty : Lambda.LMonoTy := (.tcons "ListStr" []) @@ -138,33 +174,6 @@ def PyListStrToBoogie (names : Array (Python.alias SourceRange)) : Boogie.Expres .app () (.app () (.op () "ListStr_cons" mty[string → (ListStr → ListStr)]) (PyAliasToBoogieExpr names[0]!)) (.op () "ListStr_nil" mty[ListStr]) --- Translating a Python expression can require Boogie statements, e.g., a function call --- We translate these by first defining temporary variables to store the results of the stmts --- and then using those variables in the expression. -structure PyExprTranslated where - stmts : List Boogie.Statement - expr: Boogie.Expression.Expr - post_stmts : List Boogie.Statement := [] -deriving Inhabited - - -structure PythonFunctionDecl where - name : String - args : List (String × String) -- Elements are (arg_name, arg_ty) where `arg_ty` is the string representation of the type in Python - ret : String -deriving Repr, BEq, Inhabited - -structure PythonClassDecl where - name : String -deriving Repr, BEq, Inhabited - -structure TranslationContext where - expectedType : Option (Lambda.LMonoTy) - variableTypes : List (String × Lambda.LMonoTy) - func_infos : List PythonFunctionDecl - class_infos : List PythonClassDecl -deriving Inhabited - def handleList (_elmts: Array (Python.expr SourceRange)) (expected_type : Lambda.LMonoTy): PyExprTranslated := match expected_type with | (.tcons "ListStr" _) => {stmts := [], expr := (.op () "ListStr_nil" expected_type)} @@ -421,7 +430,7 @@ partial def PyExprToBoogie (translation_ctx : TranslationContext) (e : Python.ex | .Sub _ => {stmts := lhs.stmts ++ rhs.stmts, expr := handleSub lhs.expr rhs.expr} | .Mult _ => - {stmts := lhs.stmts ++ rhs.stmts, expr := handleMult lhs.expr rhs.expr} + {stmts := lhs.stmts ++ rhs.stmts, expr := handleMult translation_ctx lhs.expr rhs.expr} | _ => panic! s!"Unhandled BinOp: {repr e}" | .Compare _ lhs op rhs => let lhs := PyExprToBoogie translation_ctx lhs @@ -609,6 +618,11 @@ partial def PyStmtToBoogie (jmp_targets: List String) (translation_ctx : Transla ([.ite guard (assign_tgt ++ (ArrPyStmtToBoogie translation_ctx body.val).fst) []], none) | _ => panic! s!"tgt must be single name: {repr tgt}" -- TODO: missing havoc + | .While _ test body _ => + -- Do one unrolling: + let guard := .app () (.op () "Bool.Not" none) (.eq () (.app () (.op () "dict_str_any_length" none) (PyExprToBoogie default test).expr) (.intConst () 0)) + ([.ite guard (ArrPyStmtToBoogie translation_ctx body.val).fst []], none) + -- TODO: missing havoc | .Assert _ a _ => let res := PyExprToBoogie translation_ctx a ([(.assert "py_assertion" res.expr)], none) @@ -621,6 +635,14 @@ partial def PyStmtToBoogie (jmp_targets: List String) (translation_ctx : Transla let new_lhs := (.strConst () "DUMMY_FLOAT") (rhs.stmts ++ [.set n.val new_lhs], none) | _ => panic! s!"Expected lhs to be name: {repr lhs}" + | .FloorDiv _ => + match lhs with + | .Name _ n _ => + let lhs := PyExprToBoogie translation_ctx lhs + let rhs := PyExprToBoogie translation_ctx rhs + let new_lhs := .app () (.app () (.op () "Int.Div" mty[int → (int → int)]) lhs.expr) rhs.expr + (rhs.stmts ++ [.set n.val new_lhs], none) + | _ => panic! s!"Expected lhs to be name: {repr lhs}" | _ => panic! s!"Unsupported AugAssign op: {repr op}" | _ => panic! s!"Unsupported {repr s}"