Advertisement
Guest User

Untitled

a guest
Feb 27th, 2019
78
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Racket 15.32 KB | None | 0 0
  1. #lang eopl
  2.  
  3. ;******************************************************************************************
  4. ;;;;; Interpretador para lenguaje con condicionales, ligadura local, procedimientos,
  5. ;;;;; procedimientos recursivos, ejecución secuencial y asignación de variables
  6.  
  7. ;; La definición BNF para las expresiones del lenguaje:
  8. ;;
  9. ;;  <program>       ::= <expression>
  10. ;;                      <a-program (exp)>
  11. ;;  <expression>    ::= <number>
  12. ;;                      <lit-exp (datum)>
  13. ;;                  ::= <identifier>
  14. ;;                      <var-exp (id)>
  15. ;;                  ::= <primitive> ({<expression>}*(,))
  16. ;;                      <primapp-exp (prim rands)>
  17. ;;                  ::= if <expresion> then <expresion> else <expression>
  18. ;;                      <if-exp (exp1 exp2 exp23)>
  19. ;;                  ::= let {<identifier> = <expression>}* in <expression>
  20. ;;                      <let-exp (ids rands body)>
  21. ;;                  ::= proc({<identificador>}*) <expression>
  22. ;;                      <proc-exp (ids body)>
  23. ;;                  ::= (<expression> {<expression>}*)
  24. ;;                      <app-exp proc rands>
  25. ;;                  ::= letrec  {identifier ({identifier}*(,)) = <expression>}* in <expression>
  26. ;;                     <letrec-exp(proc-names idss bodies bodyletrec)>
  27. ;;                  ::= begin <expression> {; <expression>}* end
  28. ;;                     <begin-exp (exp exps)>
  29. ;;                  ::= set <identifier> = <expression>
  30. ;;                     <set-exp (id rhsexp)>
  31. ;;  <primitive>     ::= + | - | * | add1 | sub1
  32.  
  33. ;******************************************************************************************
  34.  
  35. ;******************************************************************************************
  36. ;Especificación Léxica
  37.  
  38. (define scanner-spec-simple-interpreter
  39. '((white-sp
  40.    (whitespace) skip)
  41.   (comment
  42.    ("%" (arbno (not #\newline))) skip)
  43.   (identifier
  44.    (letter (arbno (or letter digit "?"))) symbol)
  45.   (number
  46.    (digit (arbno digit)) number)
  47.   (number
  48.    ("-" digit (arbno digit)) number)))
  49.  
  50. ;Especificación Sintáctica (gramática)
  51.  
  52. (define grammar-simple-interpreter
  53.   '((program (expression) a-program)
  54.     (expression (number) lit-exp)
  55.     (expression (identifier) var-exp)
  56.     (expression
  57.      (primitive "(" (separated-list expression ",")")")
  58.      primapp-exp)
  59.     (expression ("if" expression "then" expression "else" expression)
  60.                 if-exp)
  61.     (expression ("let" (arbno identifier "=" expression) "in" expression)
  62.                 let-exp)
  63.     (expression ("proc" "(" (arbno identifier) ")" expression)
  64.                 proc-exp)
  65.     (expression ( "(" expression (arbno expression) ")")
  66.                 app-exp)
  67.     (expression ("letrec" (arbno identifier "(" (separated-list identifier ",") ")" "=" expression)  "in" expression)
  68.                 letrec-exp)
  69.    
  70.     ; características adicionales
  71.     (expression ("begin" expression (arbno ";" expression) "end")
  72.                 begin-exp)
  73.     (expression ("set" identifier "=" expression)
  74.                 set-exp)
  75.     ;;;;;;
  76.  
  77.     (primitive ("+") add-prim)
  78.     (primitive ("-") substract-prim)
  79.     (primitive ("*") mult-prim)
  80.     (primitive ("add1") incr-prim)
  81.     (primitive ("sub1") decr-prim)))
  82.  
  83.  
  84. ;Tipos de datos para la sintaxis abstracta de la gramática
  85.  
  86. ;Construidos manualmente:
  87.  
  88. ;(define-datatype program program?
  89. ;  (a-program
  90. ;   (exp expression?)))
  91. ;
  92. ;(define-datatype expression expression?
  93. ;  (lit-exp
  94. ;   (datum number?))
  95. ;  (var-exp
  96. ;   (id symbol?))
  97. ;  (primapp-exp
  98. ;   (prim primitive?)
  99. ;   (rands (list-of expression?)))
  100. ;  (if-exp
  101. ;   (test-exp expression?)
  102. ;   (true-exp expression?)
  103. ;   (false-exp expression?))
  104. ;  (let-exp
  105. ;   (ids (list-of symbol?))
  106. ;   (rans (list-of expression?))
  107. ;   (body expression?))
  108. ;  (proc-exp
  109. ;   (ids (list-of symbol?))
  110. ;   (body expression?))
  111. ;  (app-exp
  112. ;   (proc expression?)
  113. ;   (args (list-of expression?)))
  114. ;  (letrec-exp
  115. ;   (proc-names (list-of symbol?))
  116. ;   (idss (list-of (list-of symbol?)))
  117. ;   (bodies (list-of expression?))
  118. ;   (body-letrec expression?))
  119. ;  (begin-exp
  120. ;   (exp expression?)
  121. ;   (exps (list-of expression?)))
  122. ;  (set-exp
  123. ;   (id symbol?)
  124. ;   (rhs expression?)))
  125. ;
  126. ;(define-datatype primitive primitive?
  127. ;  (add-prim)
  128. ;  (substract-prim)
  129. ;  (mult-prim)
  130. ;  (incr-prim)
  131. ;  (decr-prim))
  132.  
  133. ;Construidos automáticamente:
  134.  
  135. (sllgen:make-define-datatypes scanner-spec-simple-interpreter grammar-simple-interpreter)
  136.  
  137. (define show-the-datatypes
  138.   (lambda () (sllgen:list-define-datatypes scanner-spec-simple-interpreter grammar-simple-interpreter)))
  139.  
  140. ;*******************************************************************************************
  141. ;Parser, Scanner, Interfaz
  142.  
  143. ;El FrontEnd (Análisis léxico (scanner) y sintáctico (parser) integrados)
  144.  
  145. (define scan&parse
  146.   (sllgen:make-string-parser scanner-spec-simple-interpreter grammar-simple-interpreter))
  147.  
  148. ;El Analizador Léxico (Scanner)
  149.  
  150. (define just-scan
  151.   (sllgen:make-string-scanner scanner-spec-simple-interpreter grammar-simple-interpreter))
  152.  
  153. ;El Interpretador (FrontEnd + Evaluación + señal para lectura )
  154.  
  155. (define interpretador
  156.   (sllgen:make-rep-loop  "--> "
  157.     (lambda (pgm) (eval-program  pgm))
  158.     (sllgen:make-stream-parser
  159.       scanner-spec-simple-interpreter
  160.       grammar-simple-interpreter)))
  161.  
  162. ;*******************************************************************************************
  163. ;El Interprete
  164.  
  165. ;eval-program: <programa> -> numero
  166. ; función que evalúa un programa teniendo en cuenta un ambiente dado (se inicializa dentro del programa)
  167.  
  168. (define eval-program
  169.   (lambda (pgm)
  170.     (cases program pgm
  171.       (a-program (body)
  172.                  (eval-expression body (init-env))))))
  173.  
  174. ; Ambiente inicial
  175. ;(define init-env
  176. ;  (lambda ()
  177. ;    (extend-env
  178. ;     '(x y z)
  179. ;     '(4 2 5)
  180. ;     (empty-env))))
  181.  
  182. (define init-env
  183.   (lambda ()
  184.     (extend-env
  185.      '(i v x)
  186.      '(1 5 10)
  187.      (empty-env))))
  188.  
  189. ;(define init-env
  190. ;  (lambda ()
  191. ;    (extend-env
  192. ;     '(x y z f)
  193. ;     (list 4 2 5 (closure '(y) (primapp-exp (mult-prim) (cons (var-exp 'y) (cons (primapp-exp (decr-prim) (cons (var-exp 'y) ())) ())))
  194. ;                      (empty-env)))
  195. ;     (empty-env))))
  196.  
  197. ;eval-expression: <expression> <enviroment> -> numero
  198. ; evalua la expresión en el ambiente de entrada
  199. (define eval-expression
  200.   (lambda (exp env)
  201.     (cases expression exp
  202.       (lit-exp (datum) datum)
  203.       (var-exp (id) (apply-env env id))
  204.       (primapp-exp (prim rands)
  205.                    (let ((args (eval-rands rands env)))
  206.                      (apply-primitive prim args)))
  207.       (if-exp (test-exp true-exp false-exp)
  208.               (if (true-value? (eval-expression test-exp env))
  209.                   (eval-expression true-exp env)
  210.                   (eval-expression false-exp env)))
  211.       (let-exp (ids rands body)
  212.                (let ((args (eval-rands rands env)))
  213.                  (eval-expression body
  214.                                   (extend-env ids args env))))
  215.       (proc-exp (ids body)
  216.                 (closure ids body env))
  217.       (app-exp (rator rands)
  218.                (let ((proc (eval-expression rator env))
  219.                      (args (eval-rands rands env)))
  220.                  (if (procval? proc)
  221.                      (apply-procedure proc args)
  222.                      (eopl:error 'eval-expression
  223.                                  "Attempt to apply non-procedure ~s" proc))))
  224.       (letrec-exp (proc-names idss bodies letrec-body)
  225.                   (eval-expression letrec-body
  226.                                    (extend-env-recursively proc-names idss bodies env)))
  227.       (set-exp (id rhs-exp)
  228.                (begin
  229.                  (setref!
  230.                   (apply-env-ref env id)
  231.                   (eval-expression rhs-exp env))
  232.                  1))
  233.       (begin-exp (exp exps)
  234.                  (let loop ((acc (eval-expression exp env))
  235.                              (exps exps))
  236.                     (if (null? exps)
  237.                         acc
  238.                         (loop (eval-expression (car exps)
  239.                                                env)
  240.                               (cdr exps))))))))
  241.  
  242. ; funciones auxiliares para aplicar eval-expression a cada elemento de una
  243. ; lista de operandos (expresiones)
  244. (define eval-rands
  245.   (lambda (rands env)
  246.     (map (lambda (x) (eval-rand x env)) rands)))
  247.  
  248. (define eval-rand
  249.   (lambda (rand env)
  250.     (eval-expression rand env)))
  251.  
  252. ;apply-primitive: <primitiva> <list-of-expression> -> numero
  253. (define apply-primitive
  254.   (lambda (prim args)
  255.     (cases primitive prim
  256.       (add-prim () (+ (car args) (cadr args)))
  257.       (substract-prim () (- (car args) (cadr args)))
  258.       (mult-prim () (* (car args) (cadr args)))
  259.       (incr-prim () (+ (car args) 1))
  260.       (decr-prim () (- (car args) 1)))))
  261.  
  262. ;true-value?: determina si un valor dado corresponde a un valor booleano falso o verdadero
  263. (define true-value?
  264.   (lambda (x)
  265.     (not (zero? x))))
  266.  
  267. ;*******************************************************************************************
  268. ;Procedimientos
  269. (define-datatype procval procval?
  270.   (closure
  271.    (ids (list-of symbol?))
  272.    (body expression?)
  273.    (env environment?)))
  274.  
  275. ;apply-procedure: evalua el cuerpo de un procedimientos en el ambiente extendido correspondiente
  276. (define apply-procedure
  277.   (lambda (proc args)
  278.     (cases procval proc
  279.       (closure (ids body env)
  280.                (eval-expression body (extend-env ids args env))))))
  281.  
  282. ;*******************************************************************************************
  283. ;Ambientes
  284.  
  285. ;definición del tipo de dato ambiente
  286. (define-datatype environment environment?
  287.   (empty-env-record)
  288.   (extended-env-record
  289.    (syms (list-of symbol?))
  290.    (vec vector?)
  291.    (env environment?)))
  292.  
  293. (define scheme-value? (lambda (v) #t))
  294.  
  295. ;empty-env:      -> enviroment
  296. ;función que crea un ambiente vacío
  297. (define empty-env  
  298.   (lambda ()
  299.     (empty-env-record)))       ;llamado al constructor de ambiente vacío
  300.  
  301.  
  302. ;extend-env: <list-of symbols> <list-of numbers> enviroment -> enviroment
  303. ;función que crea un ambiente extendido
  304. (define extend-env
  305.   (lambda (syms vals env)
  306.     (extended-env-record syms (list->vector vals) env)))
  307.  
  308. ;extend-env-recursively: <list-of symbols> <list-of <list-of symbols>> <list-of expressions> environment -> environment
  309. ;función que crea un ambiente extendido para procedimientos recursivos
  310. (define extend-env-recursively
  311.   (lambda (proc-names idss bodies old-env)
  312.     (let ((len (length proc-names)))
  313.       (let ((vec (make-vector len)))
  314.         (let ((env (extended-env-record proc-names vec old-env)))
  315.           (for-each
  316.             (lambda (pos ids body)
  317.               (vector-set! vec pos (closure ids body env)))
  318.             (iota len) idss bodies)
  319.           env)))))
  320.  
  321. ;iota: number -> list
  322. ;función que retorna una lista de los números desde 0 hasta end
  323. (define iota
  324.   (lambda (end)
  325.     (let loop ((next 0))
  326.       (if (>= next end) '()
  327.         (cons next (loop (+ 1 next)))))))
  328.  
  329. ;(define iota
  330. ;  (lambda (end)
  331. ;    (iota-aux 0 end)))
  332. ;
  333. ;(define iota-aux
  334. ;  (lambda (ini fin)
  335. ;    (if (>= ini fin)
  336. ;        ()
  337. ;        (cons ini (iota-aux (+ 1 ini) fin)))))
  338.  
  339. ;función que busca un símbolo en un ambiente
  340. (define apply-env
  341.   (lambda (env sym)
  342.     (deref (apply-env-ref env sym))))
  343.  
  344. (define apply-env-ref
  345.   (lambda (env sym)
  346.     (cases environment env
  347.       (empty-env-record ()
  348.                         (eopl:error 'apply-env-ref "No binding for ~s" sym))
  349.       (extended-env-record (syms vals env)
  350.                            (let ((pos (rib-find-position sym syms)))
  351.                              (if (number? pos)
  352.                                  (a-ref pos vals)
  353.                                  (apply-env-ref env sym)))))))
  354.  
  355.  
  356. ;*******************************************************************************************
  357. ;Referencias
  358.  
  359. (define-datatype reference reference?
  360.   (a-ref (position integer?)
  361.          (vec vector?)))
  362.  
  363. (define deref
  364.   (lambda (ref)
  365.     (primitive-deref ref)))
  366.  
  367. (define primitive-deref
  368.   (lambda (ref)
  369.     (cases reference ref
  370.       (a-ref (pos vec)
  371.              (vector-ref vec pos)))))
  372.  
  373. (define setref!
  374.   (lambda (ref val)
  375.     (primitive-setref! ref val)))
  376.  
  377. (define primitive-setref!
  378.   (lambda (ref val)
  379.     (cases reference ref
  380.       (a-ref (pos vec)
  381.              (vector-set! vec pos val)))))
  382.  
  383.  
  384. ;****************************************************************************************
  385. ;Funciones Auxiliares
  386.  
  387. ; funciones auxiliares para encontrar la posición de un símbolo
  388. ; en la lista de símbolos de un ambiente
  389.  
  390. (define rib-find-position
  391.   (lambda (sym los)
  392.     (list-find-position sym los)))
  393.  
  394. (define list-find-position
  395.   (lambda (sym los)
  396.     (list-index (lambda (sym1) (eqv? sym1 sym)) los)))
  397.  
  398. (define list-index
  399.   (lambda (pred ls)
  400.     (cond
  401.       ((null? ls) #f)
  402.       ((pred (car ls)) 0)
  403.       (else (let ((list-index-r (list-index pred (cdr ls))))
  404.               (if (number? list-index-r)
  405.                 (+ list-index-r 1)
  406.                 #f))))))
  407.  
  408. ;******************************************************************************************
  409. ;Pruebas
  410.  
  411. (show-the-datatypes)
  412. just-scan
  413. scan&parse
  414. (just-scan "add1(x)")
  415. (just-scan "add1(   x   )%cccc")
  416. (just-scan "add1(  +(5, x)   )%cccc")
  417. (just-scan "add1(  +(5, %ccccc x) ")
  418. (scan&parse "add1(x)") ;#(struct:a-program #(struct:primapp-exp #(struct:incr-prim) (#(struct:var-exp x))))
  419. (scan&parse "add1(   x   )%cccc")
  420. (scan&parse "add1(  +(5, x)   )%cccc") ;#(struct:a-program #(struct:primapp-exp #(struct:incr-prim) (#(struct:primapp-exp #(struct:add-prim) (#(struct:lit-exp 5) #(struct:var-exp x))))))
  421. (scan&parse "add1(  +(5, %cccc
  422. x)) ")
  423. (scan&parse "if -(x,4) then +(y,11) else *(y,10)") ;#(struct:a-program #(struct:if-exp #(struct:primapp-exp #(struct:substract-prim) (#(struct:var-exp x) #(struct:lit-exp 4)))
  424.                                                                                      ;#(struct:primapp-exp #(struct:add-prim) (#(struct:var-exp y) #(struct:lit-exp 11)))
  425.                                                                                      ;#(struct:primapp-exp #(struct:mult-prim) (#(struct:var-exp y) #(struct:lit-exp 10)))))
  426. (scan&parse "let
  427. x = -(y,1)
  428. in
  429. let
  430. x = +(x,2)
  431. in
  432. add1(x)") ;#(struct:a-program #(struct:let-exp (x) (#(struct:primapp-exp #(struct:substract-prim) (#(struct:var-exp y) #(struct:lit-exp 1))))
  433.                                               ;#(struct:let-exp (x) (#(struct:primapp-exp #(struct:add-prim) (#(struct:var-exp x) #(struct:lit-exp 2))))
  434.                                               ;#(struct:primapp-exp #(struct:incr-prim) (#(struct:var-exp x))))))
  435.  
  436. (define caso1 (primapp-exp (incr-prim) (list (lit-exp 5))))
  437. (define exp-numero (lit-exp 8))
  438. (define exp-ident (var-exp 'c))
  439. (define exp-app (primapp-exp (add-prim) (list exp-numero exp-ident)))
  440. (define programa (a-program exp-app))
  441. (define una-expresion-dificil (primapp-exp (mult-prim)
  442.                                            (list (primapp-exp (incr-prim)
  443.                                                               (list (var-exp 'v)
  444.                                                                     (var-exp 'y)))
  445.                                                  (var-exp 'x)
  446.                                                  (lit-exp 200))))
  447. (define un-programa-dificil
  448.     (a-program una-expresion-dificil))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement