interpreter.rkt 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. #lang racket
  2. (require racket/block)
  3. (provide replace
  4. invoke
  5. exec)
  6. (define (lambda-symbol? symbol)
  7. (equal? symbol
  8. 'lambda))
  9. (define (lambda-fun? expr)
  10. (and (pair? expr)
  11. (lambda-symbol? (first expr))
  12. (list? (second expr))))
  13. ; [List of Symbol] [List of Expression] -> Lambda-fun
  14. (define (make-lf args body)
  15. (append (list 'lambda
  16. args)
  17. body))
  18. (define (lf-formal-params lambda-fun)
  19. (second lambda-fun))
  20. (define (lf-body lambda-fun)
  21. (rest (rest lambda-fun)))
  22. (define (call-fun expr)
  23. (first expr))
  24. (define (call-args expr)
  25. (rest expr))
  26. (define (call? expr)
  27. (and (pair? expr)
  28. (not (lambda-fun? expr))
  29. (or (symbol? (call-fun expr))
  30. (lambda-fun? (call-fun expr))
  31. (call? (call-fun expr)))))
  32. (define (contains? lst obj)
  33. (cond [(empty? lst)
  34. #f]
  35. [(equal? (first lst)
  36. obj)
  37. #t]
  38. [else
  39. (contains? (rest lst)
  40. obj)]))
  41. (define (replace expr from to)
  42. (define (replace-help expr) ; Определим вспомогательную функцию
  43. (replace expr from to)) ; Она должна принимать только одно выражение.
  44. ; Эта функция локальная, при каждом вызове replace она будет использовать
  45. ; Новые from и to, те, которые были передан в replace в этот раз.
  46. (cond [(symbol? expr)
  47. (if (equal? expr from) ; Если expr - это переменная, которую надо заменить
  48. to ; Мы её заменяем, вернув новое значение
  49. expr)] ; В противном случае, ничего с ней не делаем.
  50. [(lambda-fun? expr)
  51. (if (contains? (lf-formal-params expr)
  52. from); По нашим правилам, если у функции есть такой-же параметр
  53. expr ; Мы ничего не торгаем.
  54. (make-lf (lf-formal-params expr) ; В противном случае
  55. (map replace-help ; Заменяем все вхождения данной переменной
  56. (lf-body expr))))] ; В тело лямбда-фукции.
  57. [(call? expr) ; если наше выражение - это вызов функции
  58. (map replace-help ; мы просто заменяем переменную на её значение
  59. expr)] ; во всех выражениях, входящих в вызов.
  60. [else
  61. expr]))
  62. (define (invoke fun args)
  63. (define formal-params (lf-formal-params fun))
  64. (define body (lf-body fun))
  65. (cond [(not (lambda-fun? fun))
  66. (error 'not-a-function "~A - это не функция." fun)]
  67. [(and (empty? args)
  68. (empty? formal-params))
  69. (evaluate (cons 'begin body))]
  70. [(and (not (empty? args))
  71. (empty? formal-params))
  72. (error 'more-arguments "Аргументов слишком много: ~A~%~%~A" fun args)]
  73. [(and (empty? args)
  74. (not (empty? formal-params)))
  75. fun]
  76. [(and (not (empty? args))
  77. (not (empty? formal-params)))
  78. (block
  79. (define var (first formal-params))
  80. (define arg (first args))
  81. (define (replace-var-to-arg expr)
  82. (replace expr var arg))
  83. (invoke (cons 'lambda
  84. (cons (rest formal-params)
  85. (map replace-var-to-arg
  86. body)))
  87. (rest args)))]
  88. [else
  89. (error "Кашмар! что-то вообще не то с invoke")]))
  90. (define (evaluate expr)
  91. (cond [(lambda-fun? expr)
  92. expr]
  93. [(call? expr)
  94. (block
  95. (define operator (evaluate (call-fun expr)))
  96. (define args (call-args expr))
  97. (match operator
  98. ['begin
  99. (if (empty? (rest args))
  100. (evaluate (first args))
  101. (begin
  102. (evaluate (first args))
  103. (evaluate (cons 'begin
  104. (rest args)))))]
  105. [lambda-fun?
  106. (invoke operator
  107. args)]
  108. [_ (error 'bad-operator "Плохой оператор ~A" operator)]))]
  109. [else
  110. expr]))