Advertisement
Guest User

Untitled

a guest
Apr 16th, 2019
148
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Racket 23.96 KB | None | 0 0
  1. #lang racket
  2. (require eopl)
  3. (require racket/string); string-trim
  4. #|--------------------INTEGRANTES---------------------------
  5.  Diana Sofía Navas   1629571
  6.  Luis David Restrepo 1427086
  7.  Walter Santacruz    1630645
  8.  Víctor Vargas       1842274
  9.  ----------------------------------------------------------|#
  10.  
  11.  
  12. (define lexical-spec
  13. '((white-sp (whitespace) skip)
  14.   (comment ("#" (arbno (not #\newline))) skip)
  15.   (identifier ((arbno "@") letter (arbno (or letter digit "_" "?" "=" ))) symbol)
  16.   (number (digit (arbno digit)) number)
  17.   (number ("-" digit (arbno digit)) number)
  18.   (text ("\"" (or letter whitespace)
  19.               (arbno (or letter digit whitespace ":" "?" "=" "'")) "\"") string)
  20.   )
  21. )
  22.  
  23. (define grammar-spec
  24.   '( ;;Representa un programa de ruby    
  25.      (ruby-program ("ruby" exp-batch "end") a-program)
  26.      ;; Parte 2: Ruby con objetos
  27.      ;; cambiar a: (ruby-program ("ruby" (arbno class-decl) exp-batch "end") a-program)
  28.      
  29.      ;;Exp-batch: Representa una cerradura de expresiones
  30.      (exp-batch (expression (arbno expression)) a-batch)
  31.  
  32.      ;;Expresión:
  33.      (expression (simple-exp) a-simple-exp)
  34.      ;Declare-exp: al menos uno o más identificadores (deben inicializarse en 'nil)
  35.      (expression ("declare" identifier (arbno "," identifier) ";") declare-exp)
  36.      ;Puts-exp: al menos un valor compuesto para imprimir
  37.      (expression ("puts" (separated-list comp-value ",") ";") puts-exp)
  38.  
  39.      (expression ("if" comp-value (arbno "then") exp-batch
  40.                        (arbno "elsif" comp-value (arbno "then") exp-batch)
  41.                        (arbno "else" exp-batch) "end") if-exp)
  42.      
  43.      (expression ("unless" comp-value (arbno "then")
  44.                            exp-batch
  45.                            (arbno "else" exp-batch) "end") unless-exp)
  46.  
  47.      (expression ("while" comp-value (arbno "do") exp-batch "end") while-exp)
  48.      (expression ("until" comp-value (arbno "do") exp-batch "end") until-exp)
  49.  
  50.      (expression ("for" identifier "in" comp-value (arbno "do") exp-batch "end") for-exp)
  51.  
  52.      (expression ("def" identifier "(" (separated-list identifier ",") ")"
  53.                   exp-batch                  
  54.                   "end") function-exp)
  55.      (expression ("return" comp-value ";") return-exp)
  56.  
  57.      ;;Expresión simple
  58.      (simple-exp (simple-value complement ";") val-exp)
  59.      
  60.      ;;Complemento
  61.      (complement ("=" comp-value calls) assign)
  62.      (complement (assign-op comp-value calls) assign-and)
  63.      (complement (calls) comp-calls)
  64.  
  65.      ;;Calls
  66.      ;; 0 o muchas llamadas
  67.      (calls ((arbno call)) some-calls)
  68.  
  69.      ;;Call
  70.      (call (arguments) arguments-call)
  71.      ;; (call ("." identifier arguments) a-method-call) ;; Parte 2: Ruby con Objetos
  72.  
  73.      ;;Argumentos
  74.      ;; llamar una función puede tener 0 argumentos o muchos
  75.      (arguments ("(" (separated-list comp-value ",") ")") some-arguments)
  76.      ;; almenos 1 argumento para llamar acceder a un elemento en un arreglo
  77.      ;; máximo 2, ejemplo: a=[1,2,3]; a[1] #output 2; a[1,2] #output [2,3];
  78.      ;;                    a[1,2,3] #output Error
  79.      (arguments ("[" comp-value (arbno "," comp-value) "]") arr-arguments)
  80.  
  81.      ;;Valores compuestos
  82.      (comp-value (value) a-value)
  83.      (comp-value (un-op comp-value) unop-value)
  84.      
  85.      (value (simple-value) a-s-val)
  86.      (value ("(" comp-value val-compl ")") compl-val)
  87.  
  88.      ;;Complemento para valores
  89.      ;; llamadas a un valor:
  90.      ;; Ejemplo: sirve para ("hola"+(mundo())) donde mundo() retorna "mundo"
  91.      (val-compl (calls) val-call)
  92.      ;; operacion inorden con otro valor
  93.      (val-compl (bin-op comp-value) binop-val)
  94.  
  95.      ;; Valores simples
  96.      (simple-value (identifier) id-val)
  97.      (simple-value (number) int-val)
  98.      (simple-value (text) str-val) ;; recordar hacer string-trim cuando se evalue
  99.      (simple-value ("true") true-val)
  100.      (simple-value ("false") false-val)
  101.      (simple-value ("nil") nil-val)
  102.      ;; arreglo con 0 o muchos valores
  103.      (simple-value ("["(separated-list comp-value ",")"]") arr-val)
  104.      
  105.      ;;Operacion Inorden
  106.      (bin-op ("+") add)
  107.      (bin-op ("-") diff)
  108.      (bin-op ("*") mult)
  109.      (bin-op ("/") div)
  110.      (bin-op ("%") mod)
  111.      (bin-op ("**") pow)
  112.      (bin-op (">") great)
  113.      (bin-op (">=") great-eq)
  114.      (bin-op ("<") less)
  115.      (bin-op ("<=") less-eq)
  116.      (bin-op ("==") equal)
  117.      (bin-op ("!=") not-equal)
  118.      (bin-op ("and") and-op)
  119.      (bin-op ("&&") and-op)
  120.      (bin-op ("or") or-op)
  121.      (bin-op ("||") or-op)
  122.      ;;Rangos:
  123.      ;; Solo admite 2 argumentos, no se puede operar más de 1 vez
  124.      ;;Inclusivo: va hasta el limite superior
  125.      (bin-op ("..") in-range)
  126.      ;;Exclusivo: va hasta un step antes del limite superior
  127.      (bin-op ("...") ex-range)
  128.      ;; Ejemplo: (1..5) => (1 2 3 4 5)
  129.      ;; Ejemplo: (1...5) => (1 2 3 4)
  130.      ;; Ejemplo: ((1..5) .. 6) => Error
  131.      (bin-op ("step") st-range)
  132.      ;; Ejemplo: ((1..5) step 2) => (1 3 5)
  133.      ;; Ejemplo: ((1..5) step -1) => Error
  134.      ;; Ejemplo: ((-1..-5) step -2) => (-1 -3 -5)
  135.      ;; Ejemplo: ((1..-5) step 2) => Error
  136.      
  137.      ;;Operación asignación
  138.      (assign-op ("+=") add-eq)
  139.      (assign-op ("-=") diff-eq)
  140.      (assign-op ("*=") mult-eq)
  141.      (assign-op ("/=") div-eq)
  142.      (assign-op ("**=") pow-eq)
  143.  
  144.      ;;Operación unitaria
  145.      (un-op ("not") not-op)
  146.      (un-op ("!") not-op)
  147.  
  148.      ;;##############################################
  149.      ;; Parte 2: Ruby con objetos
  150.      ;(class-decl ("class" identifier
  151.      ;                     (arbno "<" identifier)
  152.      ;                     "attr" (separated-list ":" identifier ",") ";"
  153.      ;                     (arbno method-decl) "end") a-class-decl)
  154.  
  155.      ;(method-decl ("def" identifier "(" (separated-list identifier ",") ")"
  156.      ;             exp-batch                  
  157.      ;             "end") a-method-decl)
  158.  
  159.   )
  160. )
  161.  
  162. ;Construidos automáticamente:
  163. (sllgen:make-define-datatypes lexical-spec grammar-spec)
  164.  
  165. (define show-the-datatypes
  166.   (lambda () (sllgen:list-define-datatypes lexical-spec grammar-spec)))
  167.  
  168. ;*******************************************************************************************
  169. ;Parser, Scanner, Interfaz
  170.  
  171. ;El FrontEnd (Análisis léxico (scanner) y sintáctico (parser) integrados)
  172.  
  173. (define scan&parse
  174.   (sllgen:make-string-parser lexical-spec grammar-spec))
  175.  
  176. ;El Analizador Léxico (Scanner)
  177.  
  178. (define scan
  179.   (sllgen:make-string-scanner lexical-spec grammar-spec))
  180.  
  181. ;El Interpretador (FrontEnd + Evaluación + señal para lectura )
  182.  
  183. (define interpretador
  184.   (sllgen:make-rep-loop  "--> "
  185.     (lambda (pgm) (eval-program pgm))
  186.     (sllgen:make-stream-parser
  187.       lexical-spec
  188.       grammar-spec)))
  189.  
  190. ;*******************************************************************************************
  191. ;*******************************************************************************************
  192. ;Procedimientos
  193. (define-datatype procval procval?
  194.   (closure
  195.    (ids (list-of symbol?))
  196.    (body exp-batch?)
  197.    (env environment?)
  198.    ))
  199.  
  200. ;apply-procedure: evalua el cuerpo de un procedimientos en el ambiente extendido correspondiente
  201. (define apply-procedure
  202.   (lambda (proc args env)
  203.     (cases procval proc
  204.       (closure (ids body env)
  205.                ; |Evaluar el cuerpo de una función
  206. ;;quitar '
  207.                '(eval-exp-batch body (extend-env ids args env))
  208.                )
  209.       )
  210.     )
  211.   )
  212. ;*******************************************************************************************
  213.  
  214. (define (eval-program pgm)
  215.   (cases ruby-program pgm
  216.     (a-program (a-batch) (eval-exp-batch a-batch (empty-env)))
  217.     )
  218.   )
  219.  
  220. (define (eval-exp-batch batch env)
  221.   (cases exp-batch batch
  222.     (a-batch (exp exps) (eval-expressions exp exps env))
  223.     )
  224.   )
  225.  
  226. (define (eval-expressions exp exps env)
  227.   (let loop ((acc (eval-expression exp env))
  228.                              (exps exps))
  229.                     (if (null? exps)
  230.                         (if (void? acc) (begin (display "=> ") 'nil) acc)
  231.                         (loop (eval-expression (car exps)
  232.                                                env)
  233.                               (cdr exps)))))
  234.  
  235. (define (eval-expression exp exps env)
  236.   (cases expression exp
  237.     (a-simple-exp (simple-exp) (eval-simple-exp simple-exp env))
  238.     (declare-exp (id ids) (extend-env (cons id ids) (map (lambda (x) 'nil) (cons id ids)) env))
  239.     (puts-exp (vals)
  240.               (for-each (lambda (arg)
  241.                           (pretty-display arg))
  242.                         (map (lambda(x) (eval-comp-value x env)) vals)))        
  243.     ;---->Creo que empezaría así
  244.     ;(declare-exp (identifier identifiers) exps)
  245.     ;if-exp
  246.     ;unless-exp
  247.     ;while-exp
  248.     ;until-exp
  249.     ;for-exp
  250.     ;function-exp
  251.     ;return-exp
  252.     (else "TO DO")))
  253.    
  254.  
  255.  
  256. #|Función que me sirve para sacar una id de una estructura simple|#
  257. (define (regresar ids)
  258.   (cases simple-value ids
  259.     (id-val (identifier) (list identifier))
  260.     (else "TO DO")))
  261.  
  262. (define (asignar exps ids args env)
  263.   (if (equal? exps '())'() (eval-expressions (car exps) (cdr exps) (extend-env ids args env))))
  264.  
  265. (define (eval-simple-exp s-exp env)
  266.   (cases simple-exp s-exp
  267.     (val-exp (simple-value complement) (apply-complement simple-value complement env))))
  268.  
  269. (define eval-complement-ass
  270.   (lambda (comp-value calls env)
  271.     (cond
  272.       ((is-comp-calls-empty calls env) (eval-comp-value comp-value env))
  273.       (else "TODO-handle proc calls"))))
  274.  
  275. (define (is-comp-calls-empty cls env)
  276.   (cases calls cls
  277.     (some-calls (cls) (empty? cls))
  278.     (else "")))
  279.  
  280.  
  281. (define (apply-complement s-val compl env)
  282.   (cases complement compl
  283.     (assign (comp-value calls)
  284.             (let ((id (apply-env-ref env s-val)) (val (eval-complement-ass comp-value calls)))
  285.               (begin
  286.                 (setref! id val)
  287.                 val)))                  
  288.    
  289. ;-----------------------------------------------------------------------------------------------------------------
  290. #|Lo que hacemos aquí es:
  291.   1) args = lista(lo-que-vale-mi-id  lo-que-vale-mi-comp-value)
  292.   2) ids  = lista(id)
  293.   3) evaluar el resto de expresiones con base en un nuevo ambiente extendido que contiene ids args y el env-0|#
  294.     (assign-and (assign-op comp-value calls)
  295.                 (let((args(list(apply-assign assign-op(append (list(eval-simple-value s-val env))
  296.                                                               (list(eval-comp-value comp-value env))))))
  297.                      (ids (regresar s-val)))
  298.                   (asignar ids args env)))
  299. ;-----------------------------------------------------------------------------------------------------------------
  300.     (comp-calls (calls)
  301. #|Lo que hacemos aquí es que la estructura de tipo comp-calls devuelva s-val (que es la id) evaluada
  302.   en el ambiente extendido (recordemos que es extendido gracias al assign). Al retornar la id evaluada en el ambiente,
  303. la convierto en lista y la concateno con la llamada de eval-expressions pero esta vez con el resto del cuerpo o
  304. expresiones que tengo, no sin antes, estar seguros a través de un if, que mi variable exps no esté vacía.|#
  305.                 (append
  306.                    (list(eval-simple-value s-val env))
  307.                   (if (equal? 'exps '())'()(eval-expressions (car '(exps)) (cdr '(exps)) env))))));--->No sé para qué es calls
  308. ;----------------------------------------------------------------------------------------------------------------------
  309.  
  310. (define (eval-comp-value c-value env)
  311.   (cases comp-value c-value
  312.     (a-value (value) (eval-value value env))
  313.     (unop-value (un-op comp-value) (eval-un-op (eval-comp-value comp-value env)))))
  314.  
  315. (define eval-un-op
  316.   (lambda (val)
  317.     (cond
  318.       ((eqv? val "true") "false")
  319.       ((eqv? val "false") "true")
  320.       (else (eopl:error 'eval-un-op "Not a bool")))))      
  321.  
  322. ; eval-value a-value env => (cases value a-value (simple-val ...) (compl-val ...))
  323. ;   evalúa un valor, tiene 2 casos:
  324. ;     1) un valor simple que se evaluaría con eval-simple-value
  325. ;     2) un valor con complemento, se llama eval-val-compl con c-val evaluado y
  326. ;        a-val-compl (c-val es un comp-value, a-val-compl es un val-compl)
  327. (define (eval-value a-value env)
  328.   (cases value a-value
  329.     (a-s-val (simple-value)(eval-simple-value simple-value env))
  330.     (compl-val (comp-value val-compl) (eval-val-compl (eval-comp-value comp-value env) val-compl env))))
  331.  
  332. ; eval-val-compl a-val a-val-compl env => (cases val-compl a-val-compl (val-call ...) (binop-val ...))
  333. ;  evalúa un complemento sobre un c-val, tiene 2 casos:
  334. ;    1) val-call(some-calls) entonces se tienen que aplicar los argumentos
  335. ;    2) binop-val(binop c-val) entonces se aplica una bin-op entre a-val y la evaluacion
  336. ;       de c-val (c-val es un comp-value)
  337.  
  338. (define (eval-val-compl a-val a-val-compl env)
  339.   (cases val-compl a-val-compl
  340.     (val-call (calls) a-val-compl) ;---->No sé qué hacer aquí
  341.     (binop-val (bin-op comp-value) (apply-op bin-op (reverse(list (eval-comp-value comp-value env) a-val))))))
  342.  
  343. ; eval-simple-value s-val env (cases simple-value s-val (id-val ...) (num-val ...) (true-val ...))
  344. ;   evalúa un valor simple, comprende los casos desde id-val hasta arr-val
  345. ;   para el caso de id-val se debe hacer apply-env
  346.  
  347. (define (eval-simple-value s-val env)
  348.   (cases simple-value s-val
  349.     (id-val  (identifier)(apply-env env identifier))
  350.     (int-val (number) number)
  351.     (str-val (text) text)
  352.     (true-val  () "true")
  353.     (false-val () "false")
  354.     (nil-val   () "nil")
  355.     (arr-val   (comp-value) (map (lambda (x) (eval-comp-value x env)) comp-value))))
  356.  
  357. (define (apply-op op args)
  358.   (cases bin-op op
  359.      (add ()  (operacion args 'suma))
  360.      (diff () (- (car args) (cadr args)))
  361.      (mult () (operacion args 'mult))
  362.      (div () (/ (car args) (cadr args)))
  363.      (mod () (mod (car args) (cadr args)))
  364.      (pow ()(potencia (car args) (cadr args)))
  365.      (great () (> (car args) (cadr args)))
  366.      (great-eq () (>= (car args) (cadr args)))
  367.      (less () (< (car args) (cadr args)))
  368.      (less-eq () (<= (car args) (cadr args)))
  369.      (equal () (equal? (car args) (cadr args)))
  370.      (not-equal () (not(equal? (car args) (cadr args))))
  371.      (and-op () (and (car args) (cadr args)))
  372.      (or-op () (or (car args) (cadr args)))
  373.      (in-range () (rango (car args) (cadr args) 'in))
  374.      (ex-range () (rango (car args) (cadr args) 'ex))
  375.      (st-range () "#<void>")));---->No sé qué debería retornar esto
  376.  
  377. (define (apply-assign op args)
  378.   (cases assign-op op
  379.     (add-eq   ()   (+(car args) (cadr args)))
  380.      (diff-eq ()   (-(car args) (cadr args)))
  381.      (mult-eq ()   (*(car args) (cadr args)))
  382.      (div-eq  ()   (/(car args) (cadr args)))
  383.      (pow-eq  ()   (potencia(car args) (cadr args)))))
  384.  
  385.  
  386.  
  387.  
  388. #|FUNCION AUXILIAR PARA EX-RANGE Y ST-RANGE|#
  389. (define (rango origen destino sym)
  390.   (cond
  391.     [(not(or(number? origen) (number? destino))) "Error"]
  392.     [(equal? sym 'in) (inclu origen destino 0)]
  393.     [(equal? sym 'ex) (exclu origen destino 0)]))
  394.  
  395. #|La función inclu crea una lista desde origen hasta destino que va de uno en uno|#
  396. (define (inclu origen destino acc)
  397.   (cond
  398.    [(or (not (number? origen)) (not (number? destino))) "Error"]
  399.    [(= acc destino) empty]
  400.    [(= destino 1) (list origen)]
  401.    [else (append (list origen) (inclu (+ origen 1) destino (+ acc 1)))]))
  402.  
  403. #|La función inclu crea una lista desde origen hasta destino menos uno, que va de uno en uno|#
  404. (define (exclu origen destino acc)
  405.   (cond
  406.    [(or (not (number? origen)) (not (number? destino))) "Error"]
  407.    [(= acc (- destino 1)) empty]
  408.    [(= destino 1) (list origen)]
  409.    [else (append (list origen) (exclu (+ origen 1) destino (+ acc 1)))]))
  410.  
  411. #|La función potencia elevan una base a la n potencia|#
  412. (define (potencia base n)
  413.   (cond
  414.     [(= n 1) base]
  415.     [(= n 0) 1]
  416.     [else (* base (potencia base (- n 1)))]))
  417.  
  418. #|Función que opera seguún el tipo de dato que contenga la lista|#
  419. (define (operacion lista sys)
  420.   (cond
  421.     [(equal? lista '()) "Error"]
  422.     #|Si mi lista de args son puras cadenas entonces sé que su suma equivale a concatenar ambos|#
  423.     [(and (string? (car lista)) (string? (cadr lista)) (eq? sys 'suma))
  424.  
  425.      ;---AQUÍ LO QUE HAGO ES LIMPIAR MI CADENA DE ESTO: #\"
  426.      (list->string(eliminar(string->list
  427.      (string-append (car lista) (cadr lista)))))]
  428.     ;---------------------------------------------------
  429. #|Si el simbolo es 'mult tengo que verificar que almenos uno de los elemenos sea un número para saber
  430. cuantas veces repetir mi cadena|#
  431.     [(or
  432.       (and (string? (car lista)) (number? (cadr lista)) (eq? sys 'mult))
  433.       (and (number? (car lista)) (string? (cadr lista)) (eq? sys 'mult)))
  434.  
  435.      ;---AQUÍ LO QUE HAGO ES LIMPIAR MI CADENA DE ESTO: #\"
  436.       (list->string(eliminar(string->list(mul (cadr lista) (car lista)))))]
  437.     ;---------------------------------------------------
  438.    
  439.     #|Si no se cumple que almenos uno sea cadena entonces hay que verificar si ambos son números. Así,
  440. ya se trate de una suma o una multiplicación, los puedo operar de manera común y corriente|#
  441.     [(and (number? (car lista)) (number? (cadr lista)))
  442.              (if (eq? sys 'suma) (+ (car lista) (cadr lista))
  443.                                  (* (car lista) (cadr lista)))]
  444.     #|Si no cumple ninguna, entonces se trata de un arreglo y debo usar funciones auxiliares|#
  445.     [else (if (eq? sys 'suma)(operar (car lista) (cadr lista))
  446.              (duplicar (car lista) (cadr lista)))
  447.      ]))
  448.  
  449. #|Duplica el contenido de una lista n veces|#
  450. (define (duplicar lista n)
  451.   (cond
  452.     [(eq? '() lista) '()]
  453.     [(= n 0)'()]
  454.     [else (append lista (duplicar lista (- n 1)))]))
  455.  
  456. #|Suma dos arreglos teniendo en cuenta la manera en que son recibidos|#
  457. (define (operar lista1 lista2)
  458.   (cond
  459.     [(and (equal? lista1 '()) (equal? lista2 '())) '()]
  460.     [(append (list (+ (car lista1)
  461.                       (car lista2)))
  462.              (operar (cdr lista1)
  463.                      (cdr lista2)))]))
  464.  
  465. #|MULTIPLICAR CADENAS|#
  466. #|Esta función crea una sola cadena que realmente es una cadena repetida n veces|#
  467. (define (mul cadena n)
  468.   (cond
  469.     [(= n 0) ""]
  470.     [(string-append cadena (mul cadena (- n 1)))]))
  471.  
  472. #|ELIMINAR DIAGONALES DEL TEXTO|#
  473. #|dado a que las cadenas son acompañadas por un #\" entonces hago esta función para eliminarlas y devolver una
  474. cadena más limpia|#
  475. (define (eliminar lista)
  476.   (cond
  477.     [(eq? '() lista)'()]
  478.     [(eq? (car lista) #\")(append (eliminar (cdr lista)))]
  479.    [else (append (list(car lista)) (eliminar (cdr lista)))]))
  480. ;*******************************************************************************************
  481. ;Referencias
  482. (define-datatype reference reference?
  483.  (a-ref (position integer?)
  484.         (vec vector?)))
  485.  
  486. (define deref
  487.  (lambda (ref)
  488.    (primitive-deref ref)))
  489.  
  490. (define primitive-deref
  491.  (lambda (ref)
  492.    (cases reference ref
  493.      (a-ref (pos vec)
  494.             (vector-ref vec pos)))))
  495.  
  496. (define setref!
  497.  (lambda (ref val)
  498.    (primitive-setref! ref val)))
  499.  
  500. (define primitive-setref!
  501.  (lambda (ref val)
  502.    (cases reference ref
  503.      (a-ref (pos vec)
  504.             (vector-set! vec pos val)))))
  505.  
  506. ;*******************************************************************************************
  507. ;*******************************************************************************************
  508. ;Ambientes
  509.  
  510. ;definición del tipo de dato ambiente
  511. (define-datatype environment environment?
  512.  (empty-env-record)
  513.  (extended-env-record
  514.   (syms (list-of symbol?))
  515.   (vec  vector?)
  516.   (env environment?)))
  517.  
  518. (define scheme-value? (lambda (v) #t))
  519.  
  520. ;empty-env:      -> enviroment
  521. ;función que crea un ambiente vacío
  522. (define empty-env  
  523.  (lambda ()
  524.    (empty-env-record)))       ;llamado al constructor de ambiente vacío
  525.  
  526.  
  527. ;extend-env: <list-of symbols> <list-of numbers> enviroment -> enviroment
  528. ;función que crea un ambiente extendido
  529. (define extend-env
  530.  (lambda (syms vals env)
  531.    (extended-env-record syms (list->vector vals) env)))
  532.  
  533. ;extend-env-recursively: <list-of symbols> <list-of <list-of symbols>> <list-of expressions> environment -> environment
  534. ;función que crea un ambiente extendido para procedimientos recursivos
  535. (define extend-env-recursively
  536.  (lambda (proc-names idss bodies old-env)
  537.    (let ((len (length proc-names)))
  538.      (let ((vec (make-vector len)))
  539.        (let ((env (extended-env-record proc-names vec old-env)))
  540.          (for-each
  541.            (lambda (pos ids body)
  542.              (vector-set! vec pos (closure ids body env)))
  543.            (iota len) idss bodies)
  544.          env)))))
  545.  
  546. ; |Ambiente recursivo para un solo procedimiento
  547.  
  548. (define (a-recursive-env a-proc-name ids body env)
  549.  (let ((vec (make-vector 1)))
  550.    (let ((env (extended-env-record (list a-proc-name) vec env)))
  551.          (vector-set! vec 0 (closure ids body env))
  552.          env)
  553.    )
  554.  )
  555.  
  556. ;iota: number -> list
  557. ;función que retorna una lista de los números desde 0 hasta end
  558. (define iota
  559.  (lambda (end)
  560.    (let loop ((next 0))
  561.      (if (>= next end) '()
  562.        (cons next (loop (+ 1 next)))))))
  563.  
  564. ;función que busca un símbolo en un ambiente
  565. (define apply-env
  566.  (lambda (env sym)
  567.    (deref (apply-env-ref env sym))))
  568.  
  569. (define apply-env-ref
  570.  (lambda (env sym)
  571.    (cases environment env
  572.      (empty-env-record ()
  573.                        (eopl:error 'empty-env "No binding for ~s" sym))
  574.      (extended-env-record (syms vals env)
  575.                           (let ((pos (rib-find-position sym syms)))
  576.                             (if (number? pos)
  577.                                 (a-ref pos vals)
  578.                                 (apply-env-ref env sym)))))))
  579.  
  580. ;*******************************************************************************************
  581. ;*******************************************************************************************
  582. ;Ambiente inicial
  583.  
  584. (define (init-env) (empty-env))
  585. ;*******************************************************************************************
  586. ;*******************************************************************************************
  587. ;Funciones Auxiliares
  588.  
  589. ; funciones auxiliares para encontrar la posición de un símbolo
  590. ; en la lista de símbolos de un ambiente
  591.  
  592. (define rib-find-position
  593.  (lambda (sym los)
  594.    (list-find-position sym los)))
  595.  
  596. (define list-find-position
  597.  (lambda (sym los)
  598.    (list-index (lambda (sym1) (eqv? sym1 sym)) los)))
  599.  
  600. (define list-index
  601.  (lambda (pred ls)
  602.    (cond
  603.      ((null? ls) #f)
  604.      ((pred (car ls)) 0)
  605.      (else (let ((list-index-r (list-index pred (cdr ls))))
  606.              (if (number? list-index-r)
  607.                (+ list-index-r 1)
  608.                #f))))))
  609.  
  610. ;*******************************************************************************************
  611. ;*******************************************************************************************
  612. ;;;Rangos
  613. (define-datatype range range?
  614.  (inclusive (start number?) (end number?) (step number?))
  615.  (exclusive (start number?) (end number?) (step number?))
  616.  )
  617.  
  618. (define (eval-range a-range)
  619.  (cases range a-range
  620.    (inclusive (start end step) (iota-range start end step))
  621.    (exclusive (start end step) (iota-range start (- end 1) step))
  622.    )
  623.  )
  624.  
  625. ;;Función que retorna una lista dado un inicio, un final, y un incremento
  626. (define iota-range
  627.  (lambda (start end step)
  628.    (cond [(or
  629.            (and (< start end) (> 0 step))
  630.            (and (> start end) (< 0 step)))
  631.           (eopl:error 'Step "bad step")]
  632.          [else
  633.           (let loop ((next start))
  634.             (if (= 0 (abs (- next end)))
  635.                 (list next)
  636.                 (cons next (loop (+ next step)))))]
  637.          )
  638.    ))
  639.  
  640. ; #Ejemplos:
  641. ; > (eval-range (inclusive 1 10 1))
  642. ; (1 2 3 4 5 6 7 8 9 10)
  643. ; > (eval-range (exclusive 1 10 1))
  644. ; (1 2 3 4 5 6 7 8 9)
  645. ; > (eval-range (inclusive 1 -10 1))
  646. ; . . Step: bad step
  647. ; > (eval-range (inclusive -1 10 -1))
  648. ; . . Step: bad step
  649.  
  650.  
  651. ;*******************************************************************************************
  652. ;*******************************************************************************************
  653. (interpretador)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement