Files
agda-spa/lean/Spa/Language/Base.lean

64 lines
1.9 KiB
Lean4
Raw Normal View History

import Mathlib.Data.Finset.Basic
2026-06-25 15:39:51 -05:00
/-!
# Base Language
2026-06-25 15:39:51 -05:00
This file defines the core object language for the program analysis and
2026-08-09 17:38:56 -05:00
transformation. It's a very basic imperative language.
Program points are identified by their node in the control flow graph rather than
by an identifier stored in the AST: a recursion over a `Stmt` threads a
`Spa.GGraph.Embed` of the subtree's CFG into the whole program's (starting from
`Spa.Program.rootEmbed`), which yields the CFG index of each basic statement
along with a proof that the node carries it.
2026-06-25 15:39:51 -05:00
-/
namespace Spa
2026-06-25 15:39:51 -05:00
/-- A value-producing expression. Currently, this cannot have side effects. -/
inductive Expr where
| add (e₁ e₂ : Expr)
| sub (e₁ e₂ : Expr)
| var (x : String)
2026-08-09 17:51:58 -05:00
| num (z : )
deriving DecidableEq
2026-06-25 15:39:51 -05:00
/-- A statement that cannot alter control flow (and thus, can be part of a basic block).
This differs from, e.g., a loop, which can cause execution to jump to its top several times. -/
inductive BasicStmt where
| assign (x : String) (e : Expr)
| noop
deriving DecidableEq
2026-06-25 15:39:51 -05:00
/-- Any statements, which may or may not change program state (variable assignments). -/
inductive Stmt where
| basic (bs : BasicStmt)
| andThen (s₁ s₂ : Stmt)
| ifElse (e : Expr) (s₁ s₂ : Stmt)
| whileLoop (e : Expr) (s : Stmt)
deriving DecidableEq
2026-06-25 15:39:51 -05:00
/-- Variables mentioned in this expression. -/
def Expr.vars : Expr Finset String
| .add l r => l.vars r.vars
| .sub l r => l.vars r.vars
| .var s => {s}
| .num _ =>
2026-06-25 15:39:51 -05:00
/-- Variables assigned or mentioned in this basic statement. -/
def BasicStmt.vars : BasicStmt Finset String
| .assign x e => {x} e.vars
| .noop =>
2026-06-25 15:39:51 -05:00
/-- Variables assigned or mentioned in this statement. -/
def Stmt.vars : Stmt Finset String
| .basic bs => bs.vars
| .andThen s₁ s₂ => s₁.vars s₂.vars
| .ifElse e s₁ s₂ => (e.vars s₁.vars) s₂.vars
| .whileLoop e s => e.vars s.vars
end Spa