Skip to content

Commit 1914963

Browse files
committed
more micro lean operators
1 parent b3f3bb1 commit 1914963

File tree

5 files changed

+52
-18
lines changed

5 files changed

+52
-18
lines changed

src/kdrag/contrib/fast/__init__.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,15 +36,15 @@
3636
sys.path.insert(1, tmpdir)
3737
os.chdir(dir0)
3838

39-
from _fast.lib import * # noqa: E402, F403
39+
from _fast.lib import * # noqa: E402, F403 # type: ignore
4040

4141

4242
def ctxptr(ctx: z3.Context):
43-
return ffibuilder.cast("void *", ctx.ctx.value)
43+
return ffibuilder.cast("void *", ctx.ctx.value) # type: ignore
4444

4545

4646
def astptr(ast: z3.AstRef):
47-
return ffibuilder.cast("void *", ast.as_ast().value)
47+
return ffibuilder.cast("void *", ast.as_ast().value) # type: ignore
4848

4949

5050
def intify(ptr):

src/kdrag/contrib/fast/fast.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ Z3_ast_vector KDRAG_get_consts(Z3_context ctx, Z3_ast t) {
3535
Z3_ast_vector_inc_ref(ctx, res);
3636
Z3_ast_vector todo = Z3_mk_ast_vector(ctx);
3737
Z3_ast_vector_inc_ref(ctx, todo);
38+
// todo: seen set
3839
// Z3_ast_map seen = Z3_mk_ast_map(ctx);
3940
// Z3_ast_map_inc_ref(ctx, seen);
4041

src/kdrag/contrib/pcode/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ def set_register(self, offset: int, value: smt.BitVecRef):
145145
return dataclasses.replace(
146146
self,
147147
mem=self.mem._replace( # type: ignore
148-
register=bv.StoreConcat(
148+
register=bv.StoreConcat( # type: ignore
149149
self.mem.register, # type: ignore
150150
smt.BitVecVal(offset, self.bits),
151151
value,

src/kdrag/parsers/microlean.py

Lines changed: 44 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,54 @@
1+
"""
2+
A parser for a simple logical expression language using Lark. The syntax is inspired by Lean's
3+
4+
Unicode symbols are not required, but if you like them, adding the Unicode LaTeX extension for VSCode
5+
https://marketplace.visualstudio.com/items?itemName=oijaz.unicode-latex
6+
Goto the `File > Preferences > Settings` of the plugin and add `python` to the enabled extensions.
7+
Reloading your window will enable access via backslash autocomplete commands.
8+
For example \\alpha will tab autocomplete to α.
9+
"""
10+
111
import lark
212
import kdrag.smt as smt
313
from lark import Tree
414

515
grammar = r"""
616
start: expr
717
8-
?expr: quantifier
18+
?expr: ite
19+
?ite: quantifier | "if" expr "then" expr "else" expr -> if
920
?quantifier: implication | ("forall" | "∀") binders "," expr -> forall_ | \
10-
("exists" | "∃") binders "," expr -> exists_ | ("fun" | "λ") binders "=>" expr -> fun_
21+
("exists" | "∃") binders "," expr -> exists_ | ("fun" | "λ") binders ("=>" | "↦") expr -> fun_ | set
1122
?implication: disjunction | disjunction ("->" | "→") implication -> implies
12-
?disjunction: conjunction | disjunction ("\\/" | "∨" | "||") conjunction -> or_
13-
?conjunction: comparison | conjunction ("/\\" | "∧" | "&&") comparison -> and_
23+
?disjunction: conjunction | disjunction ("\\/" | "∨" | "||" | "∪" ) conjunction -> or_
24+
?conjunction: comparison | conjunction ("/\\" | "∧" | "&&" | "∩") comparison -> and_
1425
?comparison: additive
1526
| comparison ("=" | "==") additive -> eq
1627
| comparison "!=" additive -> neq
17-
| comparison "<" additive -> lt
18-
| comparison ">" additive -> gt
19-
| comparison "<=" additive -> le
20-
| comparison ">=" additive -> ge
28+
| comparison ("<" | "⊂") additive -> lt
29+
| comparison (">" | "⊃") additive -> gt
30+
| comparison ("<=" | "≤" | "⊆") additive -> le
31+
| comparison (">=" | "≥" | "⊇") additive -> ge
2132
?additive: multiplicative
2233
| additive "+" multiplicative -> add | additive "-" multiplicative -> sub
2334
?multiplicative: application
2435
| multiplicative "*" application -> mul | multiplicative "/" application -> div
2536
?application: atom atom* -> app
2637
?atom: const | num | bool_ | "(" expr ")" | seq
2738
28-
binders: binder+
39+
binders: binder+ | NAME ":" sort -> sing_binder
2940
?binder: "(" NAME+ ":" sort ")" -> annot_binder | NAME -> infer_binder
3041
?sort: arrow
3142
?arrow: sortatom | sortatom "->" arrow -> array
3243
?sortatom : NAME -> sortlit | "BitVec" NUMBER -> bitvecsort | "(" sort ")" | "'" NAME -> typevar
3344
34-
const: NAME
45+
const: NAME ("." NAME)*
3546
num: NUMBER
3647
bool_: "true" -> true | "false" -> false
3748
seq : "[" expr ("," expr)* "]"
3849
50+
set : "{" binders "|" expr "}"
51+
3952
NAME: /[a-zA-Z_][a-zA-Z0-9_']*/
4053
NUMBER: /-?\d+/
4154
%import common.WS
@@ -79,6 +92,13 @@ def parse(s: str, globals=None) -> smt.ExprRef:
7992
True
8093
>>> parse("[true, false]")
8194
Concat(Unit(True), Unit(False))
95+
>>> q = smt.Const("x", smt.TupleSort("pair", [smt.IntSort(), smt.BoolSort()])[0])
96+
>>> parse("q.project1", {"q": q})
97+
project1(x)
98+
>>> parse("{x : Int | x > 0}")
99+
Lambda(x, x > 0)
100+
>>> parse("if true && false then 1 + 1 else 0")
101+
If(And(True, False), 2, 0)
82102
"""
83103
env = {}
84104

@@ -139,10 +159,14 @@ def binders(tree) -> list[smt.ExprRef]:
139159
match tree:
140160
case Tree("binders", bs):
141161
return [v for b in bs for v in binder(b)]
162+
case Tree("sing_binder", [name, sort_tree]):
163+
s = sort(sort_tree)
164+
return [smt.Const(str(name), s)]
142165
case _:
143166
raise ValueError("Unknown binders tree", tree)
144167

145168
def quant(vs, body_tree, q) -> smt.QuantifierRef:
169+
# TODO: doofy. Should make a env stack
146170
nonlocal env
147171
old_env = env.copy()
148172
vs = binders(vs)
@@ -157,8 +181,10 @@ def expr(tree) -> smt.ExprRef:
157181
# TODO: obviously this is not well typed.
158182
case Tree("num", [n]):
159183
return int(n) # type: ignore
160-
case Tree("const", [name]):
184+
case Tree("const", [name, *attrs]):
161185
res = lookup(name) # type: ignore
186+
for attr in attrs:
187+
res = getattr(res, str(attr)) # type: ignore
162188
return res # type: ignore
163189
case Tree("true", []):
164190
return smt.BoolVal(True)
@@ -213,6 +239,13 @@ def expr(tree) -> smt.ExprRef:
213239
return quant(vs, body, smt.Exists)
214240
case Tree("fun_", [vs, body]):
215241
return quant(vs, body, smt.Lambda)
242+
case Tree("set", [vs, body]):
243+
t = quant(vs, body, smt.Lambda)
244+
if t.sort().range() != smt.BoolSort():
245+
raise ValueError("Set comprehension must return Bool", t)
246+
return t
247+
case Tree("if", [cond, then_, else_]):
248+
return smt.If(expr(cond), expr(then_), expr(else_))
216249
case Tree("implies", [left, right]):
217250
return smt.Implies(expr(left), expr(right))
218251
case _:

src/kdrag/theories/logic/zf.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
Class = ZFSet >> smt.BoolSort()
2525
P, Q = smt.Consts("P Q", Class)
2626

27-
elem = smt.Function("elem", ZFSet, ZFSet, smt.BoolSort())
27+
elem = smt.Function("", ZFSet, ZFSet, smt.BoolSort())
2828
elts = kd.define("elts", [A], smt.Lambda([x], elem(x, A)))
2929

3030
zf_db = []
@@ -57,7 +57,7 @@ def slemma(thm, by=[], **kwargs):
5757

5858
le = kd.notation.le.define([A, B], kd.QForAll([x], elem(x, A), elem(x, B)))
5959

60-
emp = smt.Const("emp", ZFSet)
60+
emp = smt.Const("", ZFSet)
6161
elem_emp = kd.axiom(smt.ForAll([x], elem(x, emp) == smt.BoolVal(False)))
6262

6363

@@ -237,7 +237,7 @@ def sep_upair(l):
237237

238238
# bigunion
239239

240-
bigunion = smt.Function("bigunion", ZFSet, ZFSet)
240+
bigunion = smt.Function("bigunion", ZFSet, ZFSet) # ⋃
241241
bigunion_ax = kd.axiom(
242242
kd.QForAll(
243243
[A, x], smt.Eq(elem(x, bigunion(A)), kd.QExists([B], elem(B, A), elem(x, B)))

0 commit comments

Comments
 (0)