#lang scheme

(require "Gramatica-Lpo.rkt")
(require "Pattern-matching-Lpo.rkt")

(define renombrar-variables
  (lambda (sexpr)
    (letrec ((frame-sust '())
             (renombrar-variable
              (lambda (var)
                (if (variable? var)
                    (let* ((num (random 100))
                           (str (symbol->string var))
                           (str-num (number->string num))
                           (new-var (string-append str str-num))
                           )
                      (string->symbol new-var))
                    var)
                ))
             (aux-renombrar-variables
              (lambda (expr)
                (cond
                  ((null? expr) '())
                  ((variable? expr)
                   (let ((sust (assoc expr frame-sust)) )
                     (if sust
                         (cdr sust)
                         (let ((new-var (renombrar-variable expr)))
                           (set! frame-sust
                                 (cons
                                  (cons expr new-var)
                                  frame-sust))
                           new-var))) )
                  ((list? expr)
                   (cons
                    (aux-renombrar-variables (first expr))
                    (aux-renombrar-variables (rest expr))) )
                  (else expr) ) ))
             )
      (aux-renombrar-variables sexpr)
      ) ))

(define aplica-regla
  (lambda (sexpr regla)
    ;(printf "La regla es: ~a ~n" regla)
    (letrec ((rule (renombrar-variables regla))
             (consecuente (second rule))
             (antecedente (third rule))
             (sustituciones (pattern-matching sexpr consecuente))
             (aplica-sust-antecedente
              (lambda (s-expr lista-sust)
                (cond
                  ((pair? s-expr)
                   (cons
                    (aplica-sust-antecedente (first s-expr) lista-sust)
                    (aplica-sust-antecedente (rest s-expr) lista-sust)))
                  ((variable? s-expr)
                   (let ((hay-una? (assoc s-expr lista-sust)))
                     (if hay-una?
                         (cdr hay-una?)
                         s-expr)))
                  (else
                   s-expr))))
             )
      ;(printf "~a ~n" rule)
      ;(printf "~a ~n" sustituciones)
      (aplica-sust-antecedente antecedente sustituciones)
      ) ))

(provide renombrar-variables aplica-regla)