You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

114 lines
3.8KB

  1. (module lisp (run-lisp)
  2. (import scheme)
  3. (import chicken.base)
  4. (import matchable)
  5. (import srfi-1)
  6. (import util)
  7. (define (any-or fn ln thunk)
  8. (let loop ((ln ln))
  9. (if (null? ln)
  10. (thunk)
  11. (let ((result (fn (car ln))))
  12. (if result
  13. result
  14. (loop (cdr ln)))))))
  15. (define (run-lisp body)
  16. (define (lisp body environments lisp-exit)
  17. (define (reference symbol)
  18. (cdr (any-or (curry assoc symbol) (cons lisp-builtins environments) (thunk (lisp-exit (string-append "Undefined reference: " (symbol->string symbol)))))))
  19. (define (lisp-apply function args)
  20. (cond ((procedure? function)
  21. (apply function args))
  22. ((list? function)
  23. (let ((function-arguments (car function))
  24. (function-body (cdr function)))
  25. (lisp function-body (cons (if (= (length function-arguments) (length args))
  26. (map cons function-arguments args)
  27. (lisp-exit "Wrong number of arguments to function")) environments) lisp-exit)))
  28. (else (lisp-exit "attempt to call atom"))))
  29. (define (lisp-eval body)
  30. (cond ((symbol? body) (reference body))
  31. ((atom? body) body)
  32. ((list? body) (lisp-apply (lisp-eval (car body)) (cdr body)))
  33. (else (lisp-exit "Unknown value type in evaluation."))))
  34. (define (bind name value)
  35. (set! environments (cons (let loop ((environment (car environments)))
  36. (if (null? environment)
  37. (list (cons name value))
  38. (if (eq? name (caar environment))
  39. (cons (cons name value) (cdr environment))
  40. (cons (car environment) (loop (cdr environment))))))
  41. (cdr environments))))
  42. (define lisp-builtins
  43. `((test . ,(lambda function-args
  44. (display "test function called")
  45. (newline)))
  46. (begin . ,(lambda function-args
  47. (mapn lisp-eval function-args)))
  48. (if . ,(lambda function-args
  49. (match function-args
  50. ((e x y) (if (lisp-eval e)
  51. (lisp-eval x)
  52. (lisp-eval y)))
  53. (_ (lisp-exit "malformed if expression")))))
  54. (quote . ,(lambda function-args
  55. (match function-args
  56. ((v) v)
  57. (_ (lisp-exit "malformed quote expression")))))
  58. (cons . ,(lambda function-args
  59. (match function-args
  60. ((a b) (cons (lisp-eval a) (lisp-eval b)))
  61. (_ (lisp-exit "malformed cons expression")))))
  62. (car . ,(lambda function-args
  63. (match function-args
  64. ((a) (let ((e (lisp-eval a)))
  65. (if (atom? e)
  66. (lisp-exit "tried to take car of atom")
  67. (car e))))
  68. (_ (lisp-exit "malformed car expression")))))
  69. (cdr . ,(lambda function-args
  70. (match function-args
  71. ((a) (let ((e (lisp-eval a)))
  72. (if (atom? e)
  73. (lisp-exit "tried to take cdr of atom")
  74. (cdr e))))
  75. (_ (lisp-exit "malformed cdr expression")))))
  76. (atom . ,(lambda function-args
  77. (match function-args
  78. ((a) (let ((e (lisp-eval a)))
  79. (atom? e)))
  80. (_ (lisp-exit "malformed atom expression")))))
  81. (eq . ,(lambda function-args
  82. (match function-args
  83. ((a b) (let ((ea (lisp-eval a))
  84. (eb (lisp-eval b)))
  85. (equal? ea eb)))
  86. (_ (lisp-exit "malformed eq expression")))))
  87. (set . ,(lambda function-args
  88. (match function-args
  89. ((a b) (let ((eb (eval b)))
  90. (if (symbol? a)
  91. (bind a b)
  92. (lisp-exit "tried to bind to non-symbol"))))
  93. (_ (lisp-exit "malformed set expression")))))
  94. (lambda . ,(lambda function-args
  95. (match function-args
  96. ((args exp . exps)
  97. (if (and (list? args) (every symbol? args))
  98. (append (list args exp) exps)
  99. (lisp-exit "malformed lambda expression")))
  100. (_ (lisp-exit "malformed lambda expression")))))))
  101. (lisp-eval (cons 'begin body)))
  102. (call/cc (lambda (lisp-exit)
  103. (cons #t (lisp body (list (list)) (compose lisp-exit (curry cons #f))))))))