i7.scm 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. #lang racket
  2. (require racket/match)
  3. (require racket/include)
  4. (require "parser.scm")
  5. ;; NOTE: lots of bugs in this: i8 fixes them
  6. ;;; data
  7. ;;
  8. (define (print s) (display s) (newline))
  9. (define builtins^
  10. `((cons . cons)
  11. ;;
  12. (print . print)))
  13. (define builtins
  14. `((cons . ,cons)
  15. (print . ,print)))
  16. (define specials '(lambda))
  17. (struct special ((id #:mutable) (metadata #:mutable)) #:transparent)
  18. ;;; resolve
  19. ;;
  20. (define (resolve-prg prg env^ spec)
  21. (if (null? prg)
  22. '()
  23. (match (car prg)
  24. (`(,(sid define meta) ,name ,source)
  25. (cons `(,(sid define meta) ,name ,(resolve-exp source env^ spec))
  26. (resolve-prg (cdr prg) env^ spec))))))
  27. (define (resolve-exp exp env^ spec)
  28. (cond ((or (number? exp) (boolean? exp) (string? exp)) exp)
  29. ((sid? exp)
  30. ;;
  31. ;; we see a variable
  32. ;; ensure that it is bound
  33. ;; and freshen it with a gensym if so
  34. ;;
  35. (cond ((assoc (sid-id exp) env^) => (lambda (i) (sid (cdr i) (sid-metadata exp))))
  36. (else (error "unbound variable" exp))))
  37. ((list? exp)
  38. (if (and (sid? (car exp)) (member (sid-id (car exp)) spec))
  39. (resolve-special exp env^ spec)
  40. (map (lambda (i) (resolve-exp i env^ spec)) exp)))
  41. (else (error "syntax error" exp))))
  42. (define (resolve-special exp env^ spec)
  43. (match exp
  44. (`(,(sid 'lambda m1) (,(sid x m2)) ,b)
  45. (let ((x^ (gensym x)))
  46. `(,(special 'lambda m1)
  47. (,x^)
  48. ,(resolve-exp b (cons (cons x x^) env^)
  49. (remove x spec)))))
  50. (else (error "invalid syntax" exp))))
  51. ;;; interpret
  52. ;;
  53. (define (interpret-prg prg env)
  54. (if (null? prg)
  55. #t
  56. (match (car prg)
  57. (`(,(sid define meta) ,name ,exp)
  58. (let ((value (interpret-exp exp env)))
  59. (interpret-prg (cdr prg)
  60. (cons (cons name value) env)))))))
  61. (define (interpret-exp exp env)
  62. (cond ((or (number? exp) (boolean? exp) (string? exp)) exp)
  63. ((sid? exp) (cdr (assoc (sid-id exp) env)))
  64. ((list? exp)
  65. (if (special? (car exp))
  66. (interpret-special exp env)
  67. (apply (interpret-exp (car exp) env)
  68. (map (lambda (i) (interpret-exp i env)) (cdr exp)))))
  69. (else (error "?" exp))))
  70. (define (interpret-special exp env)
  71. (match exp
  72. (`(,(special 'lambda meta) (,x) ,b)
  73. (lambda (x^)
  74. (interpret-exp b (cons x x^) env)))
  75. ))
  76. ;;; main
  77. ;;
  78. (define (check filename)
  79. (resolve-prg (parse-file filename) builtins^ specials))
  80. (define (go filename)
  81. (interpret-prg
  82. (resolve-prg (parse-file filename) builtins^ specials)
  83. builtins))