123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132 |
- #lang racket
- (require racket/block)
- (provide replace
- invoke
- exec)
- (define (lambda-symbol? symbol)
- (equal? symbol
- 'lambda))
- (define (lambda-fun? expr)
- (and (pair? expr)
- (lambda-symbol? (first expr))
- (list? (second expr))))
- ; [List of Symbol] [List of Expression] -> Lambda-fun
- (define (make-lf args body)
- (append (list 'lambda
- args)
- body))
- (define (lf-formal-params lambda-fun)
- (second lambda-fun))
- (define (lf-body lambda-fun)
- (rest (rest lambda-fun)))
- (define (call-fun expr)
- (first expr))
- (define (call-args expr)
- (rest expr))
- (define (call? expr)
- (and (pair? expr)
- (not (lambda-fun? expr))
- (or (symbol? (call-fun expr))
- (lambda-fun? (call-fun expr))
- (call? (call-fun expr)))))
- (define (contains? lst obj)
- (cond [(empty? lst)
- #f]
- [(equal? (first lst)
- obj)
- #t]
- [else
- (contains? (rest lst)
- obj)]))
- (define (replace expr from to)
- (define (replace-help expr) ; Определим вспомогательную функцию
- (replace expr from to)) ; Она должна принимать только одно выражение.
- ; Эта функция локальная, при каждом вызове replace она будет использовать
- ; Новые from и to, те, которые были передан в replace в этот раз.
- (cond [(symbol? expr)
- (if (equal? expr from) ; Если expr - это переменная, которую надо заменить
- to ; Мы её заменяем, вернув новое значение
- expr)] ; В противном случае, ничего с ней не делаем.
- [(lambda-fun? expr)
- (if (contains? (lf-formal-params expr)
- from); По нашим правилам, если у функции есть такой-же параметр
- expr ; Мы ничего не торгаем.
- (make-lf (lf-formal-params expr) ; В противном случае
- (map replace-help ; Заменяем все вхождения данной переменной
- (lf-body expr))))] ; В тело лямбда-фукции.
- [(call? expr) ; если наше выражение - это вызов функции
- (map replace-help ; мы просто заменяем переменную на её значение
- expr)] ; во всех выражениях, входящих в вызов.
- [else
- expr]))
- (define (invoke fun args)
- (define formal-params (lf-formal-params fun))
- (define body (lf-body fun))
- (cond [(not (lambda-fun? fun))
- (error 'not-a-function "~A - это не функция." fun)]
- [(and (empty? args)
- (empty? formal-params))
- (evaluate (cons 'begin body))]
- [(and (not (empty? args))
- (empty? formal-params))
- (error 'more-arguments "Аргументов слишком много: ~A~%~%~A" fun args)]
- [(and (empty? args)
- (not (empty? formal-params)))
- fun]
- [(and (not (empty? args))
- (not (empty? formal-params)))
- (block
- (define var (first formal-params))
- (define arg (first args))
- (define (replace-var-to-arg expr)
- (replace expr var arg))
- (invoke (cons 'lambda
- (cons (rest formal-params)
- (map replace-var-to-arg
- body)))
- (rest args)))]
- [else
- (error "Кашмар! что-то вообще не то с invoke")]))
- (define (evaluate expr)
- (cond [(lambda-fun? expr)
- expr]
- [(call? expr)
- (block
- (define operator (evaluate (call-fun expr)))
- (define args (call-args expr))
- (match operator
- ['begin
- (if (empty? (rest args))
- (evaluate (first args))
- (begin
- (evaluate (first args))
- (evaluate (cons 'begin
- (rest args)))))]
- [lambda-fun?
- (invoke operator
- args)]
- [_ (error 'bad-operator "Плохой оператор ~A" operator)]))]
- [else
- expr]))
|