Skip to content

Commit e679859

Browse files
committed
Updates
1 parent de152c5 commit e679859

2 files changed

Lines changed: 44 additions & 59 deletions

File tree

NEWS.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ This file contains a summary of important user-visible changes.
33
ethos 0.1.2 prerelease
44
======================
55

6+
- Drops support for `:var` and `:implicit` as *term* attributes. The recommended way of introducing function symbols with named arguments is via the command `declare-parameterized-const`, which now permits the parameter annotations `:requires`, `:implicit`, and `:opaque`. The parameters of a parameterized constants are no longer assumed to be implicit, and are explicit by default. The `:implicit` attribute can be used on all parameters to recover the previous behavior.
67
- Change the execution semantics when a program takes an unevalated term as an argument. In particular, we do not call user provided programs and oracles when at least argument could not be evaluated. This change was made to make errors more intuitive. Note this changes the semantics of programs that previously relied on being called on unevaluated terms.
78
- User programs, user oracles, and builtin operators that are unapplied are now considered unevaluated. This makes the type checker more strict and disallows passing them as arguments to other programs, which previously led to undefined behavior.
8-
- Changes the interface of `declare-parameterized-const`. In particular, the parameters of a parameterized constants are no longer assumed to be implicit, and are explicit by default. The `:implicit` attribute can be used on all parameters to recover the previous behavior. Other attributes such as `:opaque` and `:requires` can be used on parameters to this command.
99
- Remove support for the explicit parameter annotation `eo::_`, which was used to provide annotations for implicit arguments to parameterized constants.
1010
- Changed the semantics of pairwise and chainable operators for a single argument, which now reduces to the neutral element of the combining operator instead of a parse error.
1111
- The operator `eo::typeof` now fails to evaluate if the type of the given term is not ground.
@@ -16,7 +16,7 @@ ethos 0.1.2 prerelease
1616

1717
- Added the option `--stats-all` to track the number of times side conditions are invoked.
1818
- The option `--print-let` has been renamed to `--print-dag` and is now enabled by default. The printer is changed to use `eo::define` instead of `let`.
19-
- Ethos now explicitly forbids `:var`, `:implicit`, and `:opaque` on return types.
19+
- Ethos now explicitly forbids the `:opaque` annotation on return types.
2020
- The option `--binder-fresh`, which specified for fresh variables to be constructed when parsing binders, has been removed.
2121

2222
ethos 0.1.1

user_manual.md

Lines changed: 42 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -216,57 +216,63 @@ In particular:
216216

217217
This indicates the checker to compare the type it computed for the term `(not true)`, with the specified type `Bool`. An error will be thrown if the two types are not identical.
218218

219-
### The :var and :implicit annotations
219+
### Declaring Parameterized Constants
220220

221-
The Eunoia language uses the SMT-LIB version 3.0 attributes `:var <symbol>` and `:implicit` in term annotations, for naming arguments of functions and specifying that they are implicit.
221+
The Eunoia language uses the command `declare-parameterized-const`, for declaring constants that have (possibly) dependent types.
222+
In particular, this command allows naming arguments of functions and specifying that they are implicit.
223+
The syntax of this command is the following:
224+
225+
```smt
226+
(declare-parameterized-const <symbol> (<typed-param>*) <type> > <attr>*)
227+
```
228+
229+
Consider the following example:
222230

223231
```smt
224232
(declare-type Int ())
225-
(declare-const eq (-> (! Type :var T) T T Bool))
233+
(declare-parameterized-const eq ((T Type)) (-> T T Bool))
226234
(define P ((x Int) (y Int)) (eq Int x y))
227235
```
228236

229237
The above example declares a predicate symbol `eq` whose first argument is a type, that is given name `T`. It then expects two terms of type `T` and returns a `Bool`. In the definition of `P`, `eq` is applied to two variables, with type `Int` explicitly provided.
230238

231-
In contrast, the example below declares a predicate `=` where the type of the arguments is implicit (this corresponds to the SMT-LIB standard definition of `=`). In the definition of `P`, the type `Int` of the arguments is not provided.
239+
In contrast, the example below declares a predicate `=` where the type of the arguments is implicit (this corresponds to the SMT-LIB standard definition of `=`). An implicit argument for a parameterized constant can be given by the annotation `:implicit`. In the definition of `P`, the type `Int` of the arguments is not provided.
232240

233241
```smt
234242
(declare-type Int ())
235-
(declare-const = (-> (! Type :var T :implicit) T T Bool))
243+
(declare-parameterized-const = ((T Type :implicit)) (-> T T Bool))
236244
(define P ((x Int) (y Int)) (= x y))
237245
```
238246

239247
In general, an argument can be made implicit if its value can be inferred from the type of later arguments.
240248

241-
Return types cannot be marked `:implicit` or `:var` or a type error will be immediately reported.
242-
243249
We call `T` in the above definitions a _parameter_. The free parameters of the return type of an expression should be contained in at least one non-implicit argument. In particular, the following declaration is malformed, since the return type of `f` cannot be inferred from its arguments:
244250

245251
```smt
246252
(declare-type Int ())
247-
(declare-const f (-> (! Type :var T :implicit) Int T))
253+
(declare-const f ((T Type :implicit)) (-> Int T))
248254
```
249255

250-
> __Note:__ Internally, `(! T :var t)` is syntax sugar for the type `(Quote t)` where `t` is a parameter of type `T` and `Quote` is a distinguished type of kind `(-> (! Type :var U) U Type)`. When type checking applications of functions of type `(-> (Quote t) S)`, the parameter `t` is bound to the argument the function is applied to.
256+
> __Note:__ Internally, parameters `(t T)` in the command `declare-parameterized-const` are handled specially in the type system. In particular `(declare-parameterized-const foo ((T Type)) T)` defines `foo` to be of "quote arrow" type, `(~> T T)`, where the argument to `foo` is bound to `T`, e.g. `(foo Int)` binds `T` to `Int` and thus has type `Int`. Technical details of the type system can be found at the end of this manual.
251257
252-
> __Note:__ Internally, `(! T :implicit)` drops `T` from the list of arguments of the function type we are defining.
258+
> __Note:__ Internally, `(t T :implicit)` drops `t` from the list of arguments of the function type we are defining.
253259
254260
### The :requires annotation
255261

256262
Arguments to functions can also be annotated with the attribute `:requires (<term> <term>)` to denote a equality condition that is required for applications of the term to type check.
257263

258264
```smt
259265
(declare-type Int ())
260-
(declare-const BitVec (-> (! Int :var w :requires ((eo::is_neg w) false)) Type))
266+
(declare-parameterized-const BitVec ((w Int :requires ((eo::is_neg w) false))) Type)
261267
```
262268
The above declares the integer type `Int` and a bitvector type constructor `BitVec` that expects a _non-negative integer_ `w`.
263269
In detail, the first argument of `BitVec` is supposed to be an `Int` value and is named `w` via the `:var` attribute.
264270
The second annotation indicates that the term `(eo::is_neg w)` must evaluate to `false` at type checking type.
265271
Symbol `eo::is_neg` denotes a builtin function that returns `true` if its argument is a negative numeral, and returns false otherwise (for details, see [computation](#computation)).
266272
<!-- This needs discussion, what is the input type of `eo::is_neg`? How can `eo::is_neg` accept a value of a user-defined type `Int` given that it is builtin? -->
267273

268-
> __Note:__ Internally, `(! T :requires (t s))` is syntax sugar for the type term `(eo::requires t s T)` where `eo::requires` is an operator that evaluates to its third argument if and only if its first two arguments are _computationally_ equivalent (details on this operator are given in [computation](#computation)).
269-
Furthermore, the function type `(-> (eo::requires t s T) S)` is treated as `(-> T (eo::requires t s S))`. Ethos rewrites all types of the former form to the latter.
274+
> __Note:__ Internally, a parameter `(t T :requires (s r))` is syntax sugar for the type term `(eo::requires s r T)` where `eo::requires` is an operator that evaluates to its third argument if and only if its first two arguments are _computationally_ equivalent (details on this operator are given in [computation](#computation)).
275+
Furthermore, the function type `(-> (eo::requires s r T) S)` is treated as `(-> T (eo::requires s r S))`. Ethos rewrites all types of the former form to the latter.
270276
271277
<a name="opaque"></a>
272278

@@ -278,8 +284,8 @@ An example of this annotation is the following:
278284

279285
```smt
280286
(declare-type Array (Type Type))
281-
(declare-const @array_diff
282-
(-> (! Type :var T :implicit) (! Type :var U :implicit)
287+
(declare-parameterized-const @array_diff ((T Type :implicit) (U Type :implicit))
288+
(->
283289
(! (Array T U) :opaque)
284290
(! (Array T U) :opaque)
285291
T))
@@ -430,20 +436,7 @@ that references the free constant `re.all`.
430436

431437
However, when using `declare-const`, the nil terminator of an associative operator cannot depend on the parameters of the type of that function.
432438
For example, say we wish to declare bitvector or (`bvor` in SMT-LIB), where its nil terminator is the bitvector zero.
433-
A possible declaration is the following:
434-
435-
```smt
436-
(declare-const bvor
437-
(-> (! Int :var m :implicit) (BitVec m) (BitVec m) (BitVec m))
438-
:right-assoc-nil #b0000
439-
)
440-
```
441-
442-
Above, note that `m` was not in scope when defining the nil terminator of this operator,
443-
and thus we have hardcoded the nil terminator to be a bitvector of width `4`.
444-
This definition is clearly limited, as applications of this operator will fail to type check if `m` is not `4`.
445-
However,
446-
the command `declare-parameterized-const` can be used to define a version of `bvor` whose nil terminator depends on `m`,
439+
The command `declare-parameterized-const` can be used to define a version of `bvor` whose nil terminator depends on `m`,
447440
which we will describe later in [param-constants](#param-constants).
448441

449442
#### List
@@ -524,7 +517,7 @@ For example, `(>= x)` is equivalent to `true`.
524517
```smt
525518
(declare-type Int ())
526519
(declare-const and (-> Bool Bool Bool) :right-assoc)
527-
(declare-const distinct (-> (! Type :var T :implicit) T T Bool) :pairwise and)
520+
(declare-parameterized-const distinct ((T Type :implicit)) (-> T T Bool) :pairwise and)
528521
(define P ((x Int) (y Int) (z Int)) (distinct x y z))
529522
```
530523

@@ -546,7 +539,7 @@ For example, `(distinct x)` is equivalent to `true`.
546539
(declare-type Int ())
547540
(declare-type @List ())
548541
(declare-const @nil @List)
549-
(declare-const @cons (-> (! Type :var T :implicit) T @List @List)
542+
(declare-parameterized-const @cons ((T Type :implicit)) (-> T @List @List)
550543
:right-assoc-nil @nil)
551544
(declare-const forall (-> @List Bool Bool) :binder @cons)
552545
(declare-const P (-> Int Bool))
@@ -943,9 +936,8 @@ for the term `or` applied to arguments `a,b`.
943936
(declare-consts <numeral> Int)
944937
(declare-type BitVec (Int))
945938
946-
(declare-const concat (->
947-
(! Int :var n :implicit)
948-
(! Int :var m :implicit)
939+
(declare-parameterized-const concat ((n Int :implicit) (m Int :implicit))
940+
(->
949941
(BitVec n)
950942
(BitVec m)
951943
(BitVec (eo::add n m))))
@@ -995,15 +987,10 @@ This means that when type checking the binary constant `#b0000`, its type prior
995987

996988
<a name="param-constants"></a>
997989

998-
## Parameterized constants
990+
## Parameterized constants with Attributes
999991

1000992
Recall that in [assoc-nil](#assoc-nil), when using `declare-const` to define associative operators with nil terminators, it is not possible to have the nil terminator for that operator depend on its type parameters.
1001-
In this section, we introduce a new command `declare-parameterized-const` which overcomes this limitation.
1002-
Its syntax is:
1003-
1004-
```smt
1005-
(declare-parameterized-const <symbol> (<typed-param>*) <type> > <attr>*)
1006-
```
993+
In this section, we note that `declare-parameterized-const` which overcomes this limitation.
1007994

1008995
In the following example,
1009996
we declare bitvector-or (`bvor` in SMT-LIB) where its nil terminator is bitvector zero for the given bitwidth.
@@ -1160,7 +1147,7 @@ In detail, for the purposes of representing the return value of these operators,
11601147
```smt
11611148
(declare-type eo::List ())
11621149
(declare-const eo::List::nil eo::List)
1163-
(declare-const eo::List::cons (-> (! Type :var T :implicit) T eo::List eo::List)
1150+
(declare-const eo::List::cons ((T Type :implicit)) (-> T eo::List eo::List)
11641151
:right-assoc-nil eo::List::nil)
11651152
```
11661153

@@ -1194,7 +1181,7 @@ We assume the declaration of a generic `is` predicate (often called a "tester" p
11941181
```smt
11951182
11961183
; The constraint (is c x) is true iff x is an application of constructor c
1197-
(declare-const is (-> (! Type :var C :implicit) (! Type :var D :implicit) C D Bool))
1184+
(declare-parameterized-const is ((C Type :implicit) (D Type :implicit)) (-> C D Bool))
11981185
11991186
(declare-const or (-> Bool Bool Bool) :right-assoc-nil false)
12001187
@@ -1322,7 +1309,7 @@ A proof rule is only well defined if the free parameters of the requirements and
13221309
### Example rule: Reflexivity of equality
13231310

13241311
```smt
1325-
(declare-const = (-> (! Type :var T :implicit) T T Bool))
1312+
(declare-parameterized-const = ((T Type :implicit)) (-> T T Bool))
13261313
(declare-rule refl ((T Type) (t T))
13271314
:premises ()
13281315
:args (t)
@@ -1338,7 +1325,7 @@ Notice that the type `T` is a part of the parameter list and not explicitly prov
13381325
### Example rule: Symmetry of Equality
13391326

13401327
```smt
1341-
(declare-const = (-> (! Type :var T :implicit) T T Bool))
1328+
(declare-parameterized-const = ((T Type :implicit)) (-> T T Bool))
13421329
(declare-rule symm ((T Type) (t T) (s T))
13431330
:premises ((= t s))
13441331
:conclusion (= s t)
@@ -1400,7 +1387,7 @@ where
14001387
### Example proof: symmetry of equality
14011388

14021389
```smt
1403-
(declare-const = (-> (! Type :var T :implicit) T T Bool))
1390+
(declare-parameterized-const = ((T Type :implicit)) (-> T T Bool))
14041391
(declare-rule symm ((T Type) (t T) (s T))
14051392
:premises ((= t s))
14061393
:conclusion (= s t)
@@ -1612,7 +1599,7 @@ Calling it with arguments `A`, `B`, and `(@array_diff A B)` would return `(@arra
16121599
```smt
16131600
(declare-type Int ())
16141601
(declare-consts <numeral> Int)
1615-
(declare-const = (-> (! Type :var T :implicit) T T Bool))
1602+
(declare-parameterized-const = ((T Type :implicit)) (-> T T Bool))
16161603
(declare-const + (-> Int Int Int))
16171604
(declare-const - (-> Int Int Int))
16181605
(declare-const < (-> Int Int Bool))
@@ -1648,9 +1635,8 @@ The above example recursively evaluates arithmetic terms and predicates accordin
16481635
((arith.typeunion Real Real) Real)
16491636
)
16501637
)
1651-
(declare-const + (-> (! Type :var T :implicit)
1652-
(! Type :var U :implicit)
1653-
T U (arith.typeunion T U)))
1638+
(declare-parameterized-const + ((T Type :implicit) (U Type :implicit))
1639+
(-> T U (arith.typeunion T U)))
16541640
```
16551641

16561642
In the above example, a side condition is being used to define the type rule for the function `+`.
@@ -1752,7 +1738,7 @@ Also, similar to programs, the free parameters of `ri` that occur in the paramet
17521738

17531739
```smt
17541740
(declare-type Int ())
1755-
(declare-const = (-> (! Type :var T :implicit) T T Bool))
1741+
(declare-parameterized-const = ((T Type :implicit)) (-> T T Bool))
17561742
(declare-const not (-> Bool Bool))
17571743
(declare-rule symm ((F Bool))
17581744
:premises (F)
@@ -1773,7 +1759,7 @@ Internally, the semantics of `eo::match` can be seen as an (inlined) program app
17731759

17741760
```smt
17751761
(declare-type Int ())
1776-
(declare-const = (-> (! Type :var T :implicit) T T Bool))
1762+
(declare-parameterized-const = ((T Type :implicit)) (-> T T Bool))
17771763
(declare-const not (-> Bool Bool))
17781764
(program matchF ((t1 Int) (t2 Int))
17791765
(Bool) Bool
@@ -1796,7 +1782,7 @@ In more general cases, if the body of the match term contains free variables, th
17961782

17971783
```smt
17981784
(declare-type Int ())
1799-
(declare-const = (-> (! Type :var T :implicit) T T Bool))
1785+
(declare-parameterized-const = ((T Type :implicit)) (-> T T Bool))
18001786
(declare-const and (-> Bool Bool Bool) :left-assoc)
18011787
18021788
(program mk_trans ((t1 Int) (t2 Int) (t3 Int) (t4 Int) (tail Bool :list))
@@ -1894,7 +1880,7 @@ Ground applications of oracle functions are eagerly evaluated by invoking the bi
18941880
```smt
18951881
(declare-type Int ())
18961882
(declare-consts <numeral> Int)
1897-
(declare-const = (-> (! Type :var T :implicit) T T Bool))
1883+
(declare-parameterized-const = ((T Type :implicit)) (-> T T Bool))
18981884
(declare-const >= (-> Int Int Bool))
18991885
19001886
(declare-oracle-fun runIsPrime (Int) Bool ./isPrime)
@@ -2120,9 +2106,8 @@ The command:
21202106
can be seen as syntax sugar for:
21212107

21222108
```smt
2123-
(declare-const s
2124-
(-> (! T1 :var v1 :implicit) ... (! Ti :var vi :implicit)
2125-
(Proof p1) ... (Proof pn)
2109+
(declare-parameterized-const s ((v1 T1 :implicit) ... (vi Ti :implicit))
2110+
(-> (Proof p1) ... (Proof pn)
21262111
(Quote t1) ... (Quote tm)
21272112
(eo::requires r1 s1 ... (eo::requires rk sk
21282113
(Proof t)))))

0 commit comments

Comments
 (0)