Skip to content

Commit f372bdd

Browse files
author
Andrew Kent
authored
more general linear exp stx for props
1 parent 1a042f8 commit f372bdd

File tree

4 files changed

+68
-64
lines changed

4 files changed

+68
-64
lines changed

typed-racket-doc/typed-racket/scribblings/reference/experimental.scrbl

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -72,11 +72,10 @@ on the values of terms.
7272
(linear-comp symbolic-object symbolic-object)]
7373
[linear-comp < <= = >= >]
7474
[symbolic-object exact-integer
75-
linear-term
76-
(+ linear-term linear-term ...)
77-
(- linear-term linear-term ...)]
78-
[linear-term symbolic-path
79-
(* exact-integer symbolic-path)]
75+
symbolic-path
76+
(+ symbolic-object ...)
77+
(- symbolic-object ...)
78+
(* exact-integer symbolic-object)]
8079
[symbolic-path id
8180
(path-elem symbolic-path)]
8281
[path-elem car

typed-racket-lib/typed-racket/private/parse-type.rkt

Lines changed: 28 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -401,20 +401,14 @@
401401
(define-syntax-class symbolic-object
402402
#:description "symbolic object"
403403
#:attributes (val)
404-
(pattern (:+^ . body)
405-
#:attr val (parse-linear-expression-body #'body #t))
406-
(pattern (:-^ . body)
407-
#:attr val (parse-linear-expression-body #'body #f))
408-
(pattern (:*^ ~! n:exact-integer o:symbolic-object-w/o-lexp)
409-
#:do [(define obj (attribute o.val))
410-
(define obj-ty (lookup-obj-type/lexical obj))]
411-
#:fail-when (and (check-type-invariants-while-parsing?)
412-
(not (subtype obj-ty -Int)))
413-
(format "terms in linear constraints must be integers, got ~a for ~a"
414-
obj-ty obj)
415-
#:attr val (-lexp (list (syntax->datum #'n) (attribute o.val))))
416404
(pattern n:exact-integer
417405
#:attr val (-lexp (syntax->datum #'n)))
406+
(pattern (:+^ ls:linear-expression ...)
407+
#:attr val (combine-linear-expressions (attribute ls.val) #t))
408+
(pattern (:-^ ls:linear-expression ...)
409+
#:attr val (combine-linear-expressions (attribute ls.val) #f))
410+
(pattern (:*^ ~! n:exact-integer o:linear-expression)
411+
#:attr val (-lexp (list (syntax->datum #'n) (attribute o.val))))
418412
(pattern o:symbolic-object-w/o-lexp
419413
#:attr val (attribute o.val))
420414
)
@@ -457,31 +451,17 @@
457451
obj-ty obj)
458452
#:attr val (-vec-len-of (attribute o.val))))
459453

460-
(define (parse-linear-expression-body body plus?)
461-
(syntax-parse body
462-
[(t:linear-expression-term ts:linear-expression-term ...)
463-
(cond
464-
[plus?
465-
(apply -lexp (attribute t.val) (attribute ts.val))]
466-
[else
467-
(apply -lexp
468-
(attribute t.val)
469-
(for/list ([term (in-list (attribute ts.val))])
470-
(scale-obj -1 term)))])]))
471-
472-
(define-syntax-class linear-expression-term
473-
#:description "symbolic object"
454+
(define-syntax-class linear-expression
455+
#:description "linear expression"
474456
#:attributes (val)
475-
(pattern (:*^ ~! coeff:exact-integer o:symbolic-object-w/o-lexp)
476-
#:do [(define obj (attribute o.val))
477-
(define obj-ty (lookup-obj-type/lexical obj))]
478-
#:fail-when (and (check-type-invariants-while-parsing?)
479-
(not (subtype obj-ty -Int)))
480-
(format "terms in linear expressions must be integers, got ~a for ~a"
481-
obj-ty obj)
482-
#:attr val (-lexp (list (syntax->datum #'coeff) (attribute o.val))))
483457
(pattern n:exact-integer
484458
#:attr val (-lexp (syntax-e (attribute n))))
459+
(pattern (:+^ ls:linear-expression ...)
460+
#:attr val (combine-linear-expressions (attribute ls.val) #t))
461+
(pattern (:-^ ls:linear-expression ...)
462+
#:attr val (combine-linear-expressions (attribute ls.val) #f))
463+
(pattern (:*^ ~! coeff:exact-integer l:linear-expression)
464+
#:attr val (-lexp (list (syntax->datum #'coeff) (attribute l.val))))
485465
(pattern o:symbolic-object-w/o-lexp
486466
#:do [(define obj (attribute o.val))
487467
(define obj-ty (lookup-obj-type/lexical obj))]
@@ -492,6 +472,20 @@
492472
#:attr val (attribute o.val))
493473
)
494474

475+
;; [Listof Object?] boolean? -> Object?
476+
;; create (+ linear-exps ...) or (- linear-exps ...)
477+
(define (combine-linear-expressions linear-exps plus?)
478+
(cond
479+
[(null? linear-exps) (-lexp 0)]
480+
[plus?
481+
(apply -lexp linear-exps)]
482+
[else
483+
(apply -lexp
484+
(car linear-exps)
485+
(for/list ([term (in-list (cdr linear-exps))])
486+
(scale-obj -1 term)))]))
487+
488+
495489
;; old + deprecated
496490
(define-syntax-class (legacy-prop doms)
497491
#:description "proposition"

typed-racket-lib/typed-racket/rep/object-rep.rkt

Lines changed: 32 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -242,39 +242,46 @@
242242
;; *****************************************************************************
243243
;; Operations for Linear Expressions
244244

245+
;; adds two sets of terms -- used in a few cases
246+
;; for -lexp below
247+
(define-syntax-rule (add-terms ts ts*)
248+
(for/fold ([ts ts])
249+
([(p coeff) (in-terms ts*)])
250+
(terms-set ts p (+ coeff (terms-ref ts p)))))
245251

246252
;; constructor for LExps
247253
(define/cond-contract (-lexp . raw-terms)
248254
(->* () () #:rest (listof (or/c exact-integer?
249255
name-ref/c
250256
Path?
251257
LExp?
252-
(list/c exact-integer? (or/c name-ref/c Path?))))
258+
(list/c exact-integer? (or/c name-ref/c Path? LExp?))))
253259
(or/c LExp? Path?))
254-
(define-values (const terms)
255-
(for/fold ([c 0] [ts (make-terms)])
256-
([term (in-list raw-terms)])
257-
(match term
258-
[(list (? exact-integer? coeff) (? Path? p))
259-
(values c (terms-set ts p (+ coeff (terms-ref ts p))))]
260-
[(list (? exact-integer? coeff) (? name-ref/c nm))
261-
(let ([p (-id-path nm)])
262-
(if (Empty? nm)
263-
(values c ts)
264-
(values c (terms-set ts p (+ coeff (terms-ref ts p))))))]
265-
[(? exact-integer? new-const)
266-
(values (+ new-const c) ts)]
267-
[(LExp: c* ts*)
268-
(values (+ c c*)
269-
(for/fold ([ts ts])
270-
([(p coeff) (in-terms ts*)])
271-
(terms-set ts p (+ coeff (terms-ref ts p)))))]
272-
[(? Object? p)
273-
(values c (terms-set ts p (add1 (terms-ref ts p))))]
274-
[(? name-ref/c var)
275-
(define p (-id-path var))
276-
(values c (terms-set ts p (add1 (terms-ref ts p))))])))
277-
(make-LExp* const terms))
260+
(for/fold ([c 0]
261+
[ts (make-terms)]
262+
#:result (make-LExp* c ts))
263+
([term (in-list raw-terms)])
264+
(match term
265+
[(list (? exact-integer? coeff) (? Path? p))
266+
(values c (terms-set ts p (+ coeff (terms-ref ts p))))]
267+
[(list (? exact-integer? coeff) (? name-ref/c nm))
268+
(let ([p (-id-path nm)])
269+
(if (Empty? nm)
270+
(values c ts)
271+
(values c (terms-set ts p (+ coeff (terms-ref ts p))))))]
272+
[(? exact-integer? new-const)
273+
(values (+ new-const c) ts)]
274+
[(LExp: c* ts*)
275+
(values (+ c c*) (add-terms ts ts*))]
276+
[(list (? exact-integer? l-coeff) (? LExp? l))
277+
(match (scale-obj l-coeff l)
278+
[(LExp: c* ts*)
279+
(values (+ c c*) (add-terms ts ts*))])]
280+
[(? Object? p)
281+
(values c (terms-set ts p (add1 (terms-ref ts p))))]
282+
[(? name-ref/c var)
283+
(define p (-id-path var))
284+
(values c (terms-set ts p (add1 (terms-ref ts p))))])))
278285

279286

280287
;; LExp-add1

typed-racket-test/unit-tests/parse-type-tests.rkt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -497,6 +497,10 @@
497497
[(Refine [x : Integer] (> x 42))
498498
(-refine/fresh x -Int (-leq (-lexp 43)
499499
(-lexp x)))]
500+
[(Refine [n : Integer] (<= (- (+ n n) (* 1 (+ n)))
501+
(+ 2 (- 80 (* 2 (+ 9 9 (+) (-) 2))))))
502+
(-refine/fresh x -Int (-leq (-lexp x)
503+
(-lexp 42)))]
500504
;; id shadowing
501505
[(Refine [x : Any] (: x (Refine [x : Integer] (<= x 42))))
502506
(-refine/fresh x -Int (-leq (-lexp x)

0 commit comments

Comments
 (0)