aboutsummaryrefslogtreecommitdiff
path: root/rego-proofs/compiler/passes/compile-definition.scm
blob: b9f7ce8e740579d9f2787bb113b4dc2ca2ebceb2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
;;; Copyright © 2023 Jakob L. Kreuze <zerodaysfordays@sdf.org>
;;;
;;; This program is free software; you can redistribute it and/or
;;; modify it under the terms of the GNU General Public License as
;;; published by the Free Software Foundation; either version 3 of the
;;; License, or (at your option) any later version.
;;;
;;; This program is distributed in the hope that it will be useful,
;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
;;; General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with this program. If not, see
;;; <http://www.gnu.org/licenses/>.

(define-module (compiler passes compile-definition)
  #:use-module ((rnrs base) #:select (assert))
  #:use-module (compiler lean)
  #:use-module (compiler types)
  #:use-module (compiler utilities)
  #:use-module (ice-9 match)
  #:use-module (ice-9 pretty-print)
  #:use-module (oop goops)
  #:use-module (srfi srfi-1)
  #:use-module (srfi srfi-11)
  #:export (compile-definition))

(define (find-default rules)
  (find default-rule? rules))

(define (all-but-default rules)
  (let ((result (filter (negate default-rule?) rules)))
    (unless (member (- (length rules) (length result)) '(0 1) )
      (error "expected at most 1 default rule, found"
             (- (length rules) (length result))))
    result))

(define (process-rule-group rule-group)
  (define subject-ref (make <variable-ref> #:name "rulesubject"))
  (define (collapse-rule rule)
    (match rule
      (($ <rule> default head ($ <body> clauses) else-arm)
       (make <lean-conjunction>
         #:clauses `(,@clauses
                     ,(make <lean-compare>
                        #:left subject-ref
                        #:right (right head)
                        #:kind 'eq))))))
  (match rule-group
    ((left rules ...)
     (list
      (make <definition>
        #:left left
        #:kind (kind (head (first rules))) ;; TODO: When do we rewrite as `plain'?
        #:right #f
        #:default (let ((default (find-default rules)))
                    (if default
                        (collapse-rule default)
                        default))
        #:rules (map collapse-rule (all-but-default rules)))
      (variable-ref->local subject-ref)))))

;; Convert grouped rules into a `<definition>'
(define (compile-definition policy)
  (define new-scope (scope policy))
  (define new-rules
    (map (lambda (rule-group)
           (match (process-rule-group rule-group)
             ((definition subject-ref)
              (add-to-scope new-scope `(,(left definition)) subject-ref) 
              definition)))
         (rules policy)))
  (with-modified-slot (with-modified-slot policy 'rules new-rules) 'scope new-scope))

© 2015 - 2026 Jakob L. Kreuze