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.

112 lines
3.7KB

  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. (if . ,(lambda function-args
  47. (match function-args
  48. ((e x y) (if (lisp-eval e)
  49. (lisp-eval x)
  50. (lisp-eval y)))
  51. (_ (lisp-exit "malformed if expression")))))
  52. (quote . ,(lambda function-args
  53. (match function-args
  54. ((v) v)
  55. (_ (lisp-exit "malformed quote expression")))))
  56. (cons . ,(lambda function-args
  57. (match function-args
  58. ((a b) (cons (lisp-eval a) (lisp-eval b)))
  59. (_ (lisp-exit "malformed cons expression")))))
  60. (car . ,(lambda function-args
  61. (match function-args
  62. ((a) (let ((e (lisp-eval a)))
  63. (if (atom? e)
  64. (lisp-exit "tried to take car of atom")
  65. (car e))))
  66. (_ (lisp-exit "malformed car expression")))))
  67. (cdr . ,(lambda function-args
  68. (match function-args
  69. ((a) (let ((e (lisp-eval a)))
  70. (if (atom? e)
  71. (lisp-exit "tried to take cdr of atom")
  72. (cdr e))))
  73. (_ (lisp-exit "malformed cdr expression")))))
  74. (atom . ,(lambda function-args
  75. (match function-args
  76. ((a) (let ((e (lisp-eval a)))
  77. (atom? e)))
  78. (_ (lisp-exit "malformed atom expression")))))
  79. (eq . ,(lambda function-args
  80. (match function-args
  81. ((a b) (let ((ea (eval a))
  82. (eb (eval b)))
  83. (equal? ea eb)))
  84. (_ (lisp-exit "malformed eq expression")))))
  85. (set . ,(lambda function-args
  86. (match function-args
  87. ((a b) (let ((eb (eval b)))
  88. (if (symbol? a)
  89. (bind a b)
  90. (lisp-exit "tried to bind to non-symbol"))))
  91. (_ (lisp-exit "malformed set expression")))))
  92. (lambda . ,(lambda function-args
  93. (match function-args
  94. ((args exp . exps)
  95. (if (and (list? args) (every symbol? args))
  96. (append (list args exp) exps)
  97. (lisp-exit "malformed lambda expression")))
  98. (_ (lisp-exit "malformed lambda expression")))))))
  99. (lisp-eval body))
  100. (call/cc (lambda (lisp-exit)
  101. (cons #t (lisp body (list (list)) (compose lisp-exit (curry cons #f))))))))