Cleaned up code and tests
This commit is contained in:
parent
503b19a5e1
commit
311a3b4036
|
@ -3,5 +3,6 @@ Test
|
||||||
---
|
---
|
||||||
Unit tests for the dlambda special function.
|
Unit tests for the dlambda special function.
|
||||||
|
|
||||||
| script | lisp interpreter fixture |
|
| script | lisp interpreter fixture |
|
||||||
| show | evaluate | (load "lisp/dlambda-test.lisp") |
|
| check | evaluate | (load "lisp/dlambda-test.lisp") | T |
|
||||||
|
| check | evaluate | (test-dlambda) | =~/T$/ |
|
||||||
|
|
|
@ -3,7 +3,7 @@ Test
|
||||||
---
|
---
|
||||||
A simple lexical closure.
|
A simple lexical closure.
|
||||||
|
|
||||||
| script | lisp interpreter fixture |
|
| script | lisp interpreter fixture |
|
||||||
| show | evaluate | (defun adderx (x) (lambda (y) (+ x y))) |
|
| show | evaluate | (defun adder-x (x) (lambda (y) (+ x y))) |
|
||||||
| show | evaluate | (setf adder20 (adderx 20)) |
|
| show | evaluate | (setf adder-20 (adder-x 20)) |
|
||||||
| check | evaluate | (funcall adder20 2) | 22 |
|
| check | evaluate | (funcall adder-20 2) | 22 |
|
||||||
|
|
|
@ -3,7 +3,7 @@ Test
|
||||||
---
|
---
|
||||||
An object with multiple methods.
|
An object with multiple methods.
|
||||||
|
|
||||||
| script | lisp interpreter fixture |
|
| script | lisp interpreter fixture |
|
||||||
| show | evaluate |!-
|
| show | evaluate |!-
|
||||||
|
|
||||||
(defun counter-class ()
|
(defun counter-class ()
|
||||||
|
@ -15,11 +15,11 @@ An object with multiple methods.
|
||||||
((:dec)
|
((:dec)
|
||||||
(setq counter (- counter 1)))))))
|
(setq counter (- counter 1)))))))
|
||||||
|
|
||||||
-!|
|
-!|
|
||||||
| show | evaluate | (setq my-counter (counter-class)) |
|
| show | evaluate | (setq my-counter (counter-class)) |
|
||||||
| check | evaluate | (funcall my-counter :inc) | 1 |
|
| check | evaluate | (funcall my-counter :inc) | 1 |
|
||||||
| check | evaluate | (funcall my-counter :inc) | 2 |
|
| check | evaluate | (funcall my-counter :inc) | 2 |
|
||||||
| check | evaluate | (funcall my-counter :inc) | 3 |
|
| check | evaluate | (funcall my-counter :inc) | 3 |
|
||||||
| check | evaluate | (funcall my-counter :dec) | 2 |
|
| check | evaluate | (funcall my-counter :dec) | 2 |
|
||||||
| check | evaluate | (funcall my-counter :dec) | 1 |
|
| check | evaluate | (funcall my-counter :dec) | 1 |
|
||||||
| check | evaluate | (funcall my-counter :dec) | 0 |
|
| check | evaluate | (funcall my-counter :dec) | 0 |
|
||||||
|
|
|
@ -3,11 +3,11 @@ Test
|
||||||
---
|
---
|
||||||
Shows object composition, a default method, and two different ways of referencing objects.
|
Shows object composition, a default method, and two different ways of referencing objects.
|
||||||
|
|
||||||
| script | lisp interpreter fixture |
|
| script | lisp interpreter fixture |
|
||||||
| show | evaluate | (load "lisp/fruit-counter.lisp") |
|
| check | evaluate | (load "lisp/fruit-counter.lisp") | T |
|
||||||
| check | evaluate | (my-counter :inc-apples) | 1 |
|
| check | evaluate | (my-fruits :inc-apples) | 1 |
|
||||||
| check | evaluate | (my-counter :inc-apples) | 2 |
|
| check | evaluate | (my-fruits :inc-apples) | 2 |
|
||||||
| check | evaluate | (funcall my-counter2 :dec-bananas) | 9999 |
|
| check | evaluate | (funcall my-fruits2 :dec-bananas) | 9999 |
|
||||||
| check | evaluate | (my-counter :set-coconuts 12) | 12 |
|
| check | evaluate | (my-fruits :set-coconuts 12) | 12 |
|
||||||
| check | evaluate | (my-counter) |(APPLES 2 BANANAS 0 COCONUTS 12) |
|
| check | evaluate | (my-fruits) | ((APPLES 2) (BANANAS 0) (COCONUTS 12)) |
|
||||||
| check | evaluate | (funcall my-counter2) |(APPLES 10000 BANANAS 9999 COCONUTS 10000) |
|
| check | evaluate | (funcall my-fruits2) | ((APPLES 10000) (BANANAS 9999) (COCONUTS 10000)) |
|
|
@ -1,9 +1,10 @@
|
||||||
|LispInterpreter.ExternalFunctionUnitTests||12:36:10 Fri, Mar 03, 2017|
|
|LispInterpreter.ExternalFunctionUnitTests||14:30:55 Fri, Mar 03, 2017|
|
||||||
|LispInterpreter.ObjectComposition||12:36:01 Fri, Mar 03, 2017|
|
|LispInterpreter.MultipleMethodObject||14:19:50 Fri, Mar 03, 2017|
|
||||||
|
|LispInterpreter.LexicalClosures||14:18:39 Fri, Mar 03, 2017|
|
||||||
|
|LispInterpreter.ObjectComposition||14:17:58 Fri, Mar 03, 2017|
|
||||||
|LispInterpreter.DlambdaUnitTests||10:16:42 Fri, Mar 03, 2017|
|
|LispInterpreter.DlambdaUnitTests||10:16:42 Fri, Mar 03, 2017|
|
||||||
|LispInterpreter.dlambda||10:12:59 Fri, Mar 03, 2017|
|
|LispInterpreter.dlambda||10:12:59 Fri, Mar 03, 2017|
|
||||||
|LispInterpreter||09:04:51 Fri, Mar 03, 2017|
|
|LispInterpreter||09:04:51 Fri, Mar 03, 2017|
|
||||||
|LispInterpreter.LexicalClosures||16:31:40 Thu, Mar 02, 2017|
|
|
||||||
|LispInterpreter.LexicalClosure||16:26:49 Thu, Mar 02, 2017|
|
|LispInterpreter.LexicalClosure||16:26:49 Thu, Mar 02, 2017|
|
||||||
|LispInterpreter.FruitCounter||16:13:51 Thu, Mar 02, 2017|
|
|LispInterpreter.FruitCounter||16:13:51 Thu, Mar 02, 2017|
|
||||||
|LispInterpreter.SimpleClosure||16:12:31 Thu, Mar 02, 2017|
|
|LispInterpreter.SimpleClosure||16:12:31 Thu, Mar 02, 2017|
|
||||||
|
|
|
@ -10,9 +10,11 @@
|
||||||
(defun compound-interest (principal rate years)
|
(defun compound-interest (principal rate years)
|
||||||
(if (= years 0)
|
(if (= years 0)
|
||||||
principal
|
principal
|
||||||
(compound-interest (+ principal (percent principal rate))
|
(compound-interest
|
||||||
rate
|
(+ principal (percent principal rate))
|
||||||
(decrement years)
|
rate
|
||||||
|
(decrement years)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -1,111 +1,115 @@
|
||||||
(load "unit-test.lisp")
|
(load "unit-test.lisp")
|
||||||
(load "dlambda.lisp")
|
(load "dlambda.lisp")
|
||||||
|
|
||||||
(unit
|
(defun test-dlambda ()
|
||||||
(list
|
|
||||||
|
|
||||||
(defun empty-dlambda ()
|
(unit
|
||||||
(assert-equal
|
(list
|
||||||
'(lambda (&rest arguments) (case (first arguments)))
|
|
||||||
(dlambda)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
(defun dlambda-default-method-only ()
|
(defun empty-dlambda ()
|
||||||
(assert-equal
|
(assert-equal
|
||||||
'(lambda (&rest arguments)
|
'(lambda (&rest arguments) (case (first arguments)))
|
||||||
(case (first arguments)
|
(dlambda)
|
||||||
(t (apply (lambda () (print "nothing")) arguments))
|
|
||||||
)
|
|
||||||
)
|
|
||||||
(dlambda
|
|
||||||
(t () (print "nothing"))
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
|
||||||
|
|
||||||
(defun dlambda-named-method-only ()
|
(defun dlambda-default-method-only ()
|
||||||
(assert-equal
|
(assert-equal
|
||||||
'(lambda (&rest arguments)
|
'(lambda (&rest arguments)
|
||||||
(case (first arguments)
|
(case (first arguments)
|
||||||
(:write (apply (lambda () (print "something")) (rest arguments)))
|
(t (apply (lambda () (print "nothing")) arguments))
|
||||||
)
|
|
||||||
)
|
|
||||||
(dlambda
|
|
||||||
(:write () (print "something"))
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
(defun dlambda-named-and-default-method ()
|
|
||||||
(assert-equal
|
|
||||||
'(lambda (&rest arguments)
|
|
||||||
(case (first arguments)
|
|
||||||
(:write (apply (lambda () (print "something")) (rest arguments)))
|
|
||||||
(t (apply (lambda () (print "nothing")) arguments))
|
|
||||||
)
|
|
||||||
)
|
|
||||||
(dlambda
|
|
||||||
(:write () (print "something"))
|
|
||||||
(t () (print "nothing"))
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
(defun dlambda-methods-with-arguments ()
|
|
||||||
(assert-equal
|
|
||||||
'(lambda (&rest arguments)
|
|
||||||
(case (first arguments)
|
|
||||||
(:write (apply (lambda (message) (print message)) (rest arguments)))
|
|
||||||
(t (apply (lambda (&rest messages) (print messages)) arguments))
|
|
||||||
)
|
|
||||||
)
|
|
||||||
(dlambda
|
|
||||||
(:write (message) (print message))
|
|
||||||
(t (&rest messages) (print messages))
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
(defun dlambda-methods-with-multiple-arguments ()
|
|
||||||
(assert-equal
|
|
||||||
'(lambda (&rest arguments)
|
|
||||||
(case (first arguments)
|
|
||||||
(:write
|
|
||||||
(apply
|
|
||||||
(lambda (message &rest other-stuff)
|
|
||||||
(print message)
|
|
||||||
(print other-stuff)
|
|
||||||
)
|
|
||||||
(rest arguments)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
(t
|
)
|
||||||
(apply
|
(dlambda
|
||||||
(lambda (message1 message2 &rest other-stuff)
|
(t () (print "nothing"))
|
||||||
(print message1)
|
)
|
||||||
(print message2)
|
)
|
||||||
(print other-stuff)
|
)
|
||||||
|
|
||||||
|
(defun dlambda-named-method-only ()
|
||||||
|
(assert-equal
|
||||||
|
'(lambda (&rest arguments)
|
||||||
|
(case (first arguments)
|
||||||
|
(:write (apply (lambda () (print "something")) (rest arguments)))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(dlambda
|
||||||
|
(:write () (print "something"))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
(defun dlambda-named-and-default-method ()
|
||||||
|
(assert-equal
|
||||||
|
'(lambda (&rest arguments)
|
||||||
|
(case (first arguments)
|
||||||
|
(:write (apply (lambda () (print "something")) (rest arguments)))
|
||||||
|
(t (apply (lambda () (print "nothing")) arguments))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(dlambda
|
||||||
|
(:write () (print "something"))
|
||||||
|
(t () (print "nothing"))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
(defun dlambda-methods-with-arguments ()
|
||||||
|
(assert-equal
|
||||||
|
'(lambda (&rest arguments)
|
||||||
|
(case (first arguments)
|
||||||
|
(:write (apply (lambda (message) (print message)) (rest arguments)))
|
||||||
|
(t (apply (lambda (&rest messages) (print messages)) arguments))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(dlambda
|
||||||
|
(:write (message) (print message))
|
||||||
|
(t (&rest messages) (print messages))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
(defun dlambda-methods-with-multiple-arguments ()
|
||||||
|
(assert-equal
|
||||||
|
'(lambda (&rest arguments)
|
||||||
|
(case (first arguments)
|
||||||
|
(:write
|
||||||
|
(apply
|
||||||
|
(lambda (message &rest other-stuff)
|
||||||
|
(print message)
|
||||||
|
(print other-stuff)
|
||||||
|
)
|
||||||
|
(rest arguments)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(t
|
||||||
|
(apply
|
||||||
|
(lambda (message1 message2 &rest other-stuff)
|
||||||
|
(print message1)
|
||||||
|
(print message2)
|
||||||
|
(print other-stuff)
|
||||||
|
)
|
||||||
|
arguments
|
||||||
)
|
)
|
||||||
arguments
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
(dlambda
|
||||||
(dlambda
|
(:write (message &rest other-stuff)
|
||||||
(:write (message &rest other-stuff)
|
(print message)
|
||||||
(print message)
|
(print other-stuff)
|
||||||
(print other-stuff)
|
)
|
||||||
)
|
(t (message1 message2 &rest other-stuff)
|
||||||
(t (message1 message2 &rest other-stuff)
|
(print message1)
|
||||||
(print message1)
|
(print message2)
|
||||||
(print message2)
|
(print other-stuff)
|
||||||
(print other-stuff)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
|
||||||
|
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -3,3 +3,4 @@
|
||||||
(* x (fact (- x 1)))
|
(* x (fact (- x 1)))
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -87,9 +87,9 @@
|
||||||
|
|
||||||
(t (&rest arguments)
|
(t (&rest arguments)
|
||||||
(list
|
(list
|
||||||
'apples (funcall apple-counter :get)
|
(list 'apples (funcall apple-counter :get))
|
||||||
'bananas (funcall banana-counter :get)
|
(list 'bananas (funcall banana-counter :get))
|
||||||
'coconuts (funcall coconut-counter :get)
|
(list 'coconuts (funcall coconut-counter :get))
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -102,18 +102,18 @@
|
||||||
; Create an instance
|
; Create an instance
|
||||||
;
|
;
|
||||||
; usage:
|
; usage:
|
||||||
; ~ (my-counter :set-apples 23)
|
; ~ (my-fruits :set-apples 23)
|
||||||
; 23
|
; 23
|
||||||
;
|
;
|
||||||
(let ((instance (fruit-counter 0)))
|
(let ((instance (fruit-counter 0)))
|
||||||
(defun my-counter (&rest args) (apply instance args))
|
(defun my-fruits (&rest args) (apply instance args))
|
||||||
)
|
)
|
||||||
|
|
||||||
; Another way
|
; Another way
|
||||||
;
|
;
|
||||||
; usage:
|
; usage:
|
||||||
; ~ (funcall my-counter2 :set-apples 23)
|
; ~ (funcall my-fruits2 :set-apples 23)
|
||||||
; 23
|
; 23
|
||||||
;
|
;
|
||||||
(setf my-counter2 (fruit-counter 10000))
|
(setf my-fruits2 (fruit-counter 10000))
|
||||||
|
|
||||||
|
|
|
@ -3,9 +3,19 @@
|
||||||
(days-in-year 365)
|
(days-in-year 365)
|
||||||
(two-weeks 14))
|
(two-weeks 14))
|
||||||
|
|
||||||
(+ 1
|
(+
|
||||||
(/ (- (+ days-in-year
|
(/
|
||||||
leap-year)
|
(-
|
||||||
first-payday-day)
|
(+
|
||||||
two-weeks))
|
days-in-year
|
||||||
|
leap-year
|
||||||
|
)
|
||||||
|
first-payday-day
|
||||||
|
)
|
||||||
|
two-weeks
|
||||||
|
)
|
||||||
|
1
|
||||||
|
)
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -1,23 +1,23 @@
|
||||||
(defun reverse (the-list)
|
(defun reverse (the-list)
|
||||||
(cond
|
(if the-list
|
||||||
(the-list (append (reverse (rest the-list))
|
(append
|
||||||
(list (first the-list))
|
(reverse (rest the-list))
|
||||||
)
|
(list (first the-list))
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
(defun deep-reverse (the-list)
|
(defun deep-reverse (the-list)
|
||||||
(cond
|
(if the-list
|
||||||
(the-list (append (deep-reverse (rest the-list))
|
(append
|
||||||
(list (cond
|
(deep-reverse (rest the-list))
|
||||||
((listp (first the-list))
|
(list
|
||||||
(deep-reverse (first the-list))
|
(if (listp (first the-list))
|
||||||
)
|
(deep-reverse (first the-list))
|
||||||
(t (first the-list))
|
(first the-list)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
;; A list containing the values of single-letter Roman numerals.
|
||||||
|
(setf roman-number-list
|
||||||
|
'((I 1) (V 5) (X 10) (L 50) (C 100) (D 500) (M 1000))
|
||||||
|
)
|
||||||
|
|
||||||
|
;; Converts a single Roman numeral letter into its equivalent decimal value.
|
||||||
|
(defun letter-to-decimal (letter)
|
||||||
|
(car
|
||||||
|
(cdr
|
||||||
|
(
|
||||||
|
(lambda (lst f)
|
||||||
|
(cond
|
||||||
|
((null lst) ())
|
||||||
|
((eq (car (car lst)) letter) (car lst))
|
||||||
|
(t (funcall f (cdr lst) f))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
roman-number-list
|
||||||
|
(lambda (lst f)
|
||||||
|
(cond
|
||||||
|
((null lst) ())
|
||||||
|
((eq (car (car lst)) letter) (car lst))
|
||||||
|
(t (funcall f (cdr lst) f))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
|
@ -1,15 +0,0 @@
|
||||||
;; A list containing the values of single-letter Roman numerals.
|
|
||||||
(setf *roman-number-list*
|
|
||||||
'((I 1) (V 5) (X 10) (L 50) (C 100) (D 500) (M 1000)))
|
|
||||||
|
|
||||||
;; Converts a single Roman numeral letter into its equivalent decimal value.
|
|
||||||
(defun letter-to-decimal (letter)
|
|
||||||
(car (cdr ((lambda (lst f)
|
|
||||||
(cond ((null lst) ())
|
|
||||||
((eq (car (car lst)) letter) (car lst))
|
|
||||||
(t (funcall f (cdr lst) f))))
|
|
||||||
*roman-number-list*
|
|
||||||
(lambda (lst f)
|
|
||||||
(cond ((null lst) ())
|
|
||||||
((eq (car (car lst)) letter) (car lst))
|
|
||||||
(t (funcall f (cdr lst) f))))))))
|
|
|
@ -2,10 +2,10 @@
|
||||||
|
|
||||||
(defun counter (initial-count)
|
(defun counter (initial-count)
|
||||||
(let ((count initial-count)
|
(let ((count initial-count)
|
||||||
(print-prefix nil)
|
(name nil)
|
||||||
(this nil))
|
(this nil))
|
||||||
|
|
||||||
(setf print-prefix "Counter")
|
(setf name "Counter")
|
||||||
|
|
||||||
(setf this
|
(setf this
|
||||||
(eval
|
(eval
|
||||||
|
@ -40,7 +40,7 @@
|
||||||
)
|
)
|
||||||
|
|
||||||
(t ()
|
(t ()
|
||||||
(cons print-prefix count)
|
(cons name count)
|
||||||
)
|
)
|
||||||
|
|
||||||
)
|
)
|
||||||
|
@ -50,21 +50,8 @@
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
; Create an instance
|
|
||||||
;
|
|
||||||
; usage:
|
|
||||||
; ~ (my-counter :inc-3)
|
|
||||||
; 3
|
|
||||||
;
|
|
||||||
(let ((instance (counter 0)))
|
(let ((instance (counter 0)))
|
||||||
(defun my-counter (&rest args) (apply instance args))
|
(defun my-counter (&rest args) (apply instance args))
|
||||||
)
|
)
|
||||||
|
|
||||||
; Another way
|
|
||||||
;
|
|
||||||
; usage:
|
|
||||||
; ~ (funcall my-counter2 :dec-3)
|
|
||||||
; 997
|
|
||||||
;
|
|
||||||
(setf my-counter2 (counter 10000))
|
(setf my-counter2 (counter 10000))
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
t
|
t
|
||||||
)
|
)
|
||||||
(progn
|
(progn
|
||||||
(print (cons 'F unit-test))
|
(print (cons 'f unit-test))
|
||||||
nil
|
nil
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
package function.builtin;
|
package function.builtin;
|
||||||
|
|
||||||
|
import static function.builtin.EVAL.lookupFunctionOrLambda;
|
||||||
|
import static table.FunctionTable.lookupFunction;
|
||||||
|
|
||||||
import function.*;
|
import function.*;
|
||||||
import sexpression.*;
|
import sexpression.*;
|
||||||
|
|
||||||
|
@ -9,7 +12,7 @@ public class APPLY extends LispFunction {
|
||||||
private ArgumentValidator argumentValidator;
|
private ArgumentValidator argumentValidator;
|
||||||
|
|
||||||
public static SExpression apply(Cons argumentList) {
|
public static SExpression apply(Cons argumentList) {
|
||||||
return new APPLY().call(argumentList);
|
return lookupFunction("APPLY").call(argumentList);
|
||||||
}
|
}
|
||||||
|
|
||||||
public APPLY() {
|
public APPLY() {
|
||||||
|
@ -22,11 +25,11 @@ public class APPLY extends LispFunction {
|
||||||
argumentValidator.validate(argumentList);
|
argumentValidator.validate(argumentList);
|
||||||
|
|
||||||
Cons rest = (Cons) argumentList.getRest();
|
Cons rest = (Cons) argumentList.getRest();
|
||||||
|
Cons functionArguments = (Cons) rest.getFirst();
|
||||||
SExpression functionName = argumentList.getFirst();
|
SExpression functionName = argumentList.getFirst();
|
||||||
SExpression functionArguments = rest.getFirst();
|
LispFunction function = lookupFunctionOrLambda(functionName);
|
||||||
LispFunction function = EVAL.lookupFunctionOrLambda(functionName);
|
|
||||||
|
|
||||||
return function.call((Cons) functionArguments);
|
return function.call(functionArguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package function.builtin;
|
||||||
|
|
||||||
import static sexpression.Nil.NIL;
|
import static sexpression.Nil.NIL;
|
||||||
import static sexpression.Symbol.T;
|
import static sexpression.Symbol.T;
|
||||||
|
import static table.FunctionTable.lookupFunction;
|
||||||
|
|
||||||
import java.text.MessageFormat;
|
import java.text.MessageFormat;
|
||||||
|
|
||||||
|
@ -10,13 +11,13 @@ import function.*;
|
||||||
import function.builtin.cons.LIST;
|
import function.builtin.cons.LIST;
|
||||||
import function.builtin.special.LAMBDA;
|
import function.builtin.special.LAMBDA;
|
||||||
import sexpression.*;
|
import sexpression.*;
|
||||||
import table.*;
|
import table.ExecutionContext;
|
||||||
|
|
||||||
@FunctionNames({ "EVAL" })
|
@FunctionNames({ "EVAL" })
|
||||||
public class EVAL extends LispFunction {
|
public class EVAL extends LispFunction {
|
||||||
|
|
||||||
public static LispFunction lookupFunctionOrLambda(SExpression functionExpression) {
|
public static LispFunction lookupFunctionOrLambda(SExpression functionExpression) {
|
||||||
LispFunction function = FunctionTable.lookupFunction(functionExpression.toString());
|
LispFunction function = lookupFunction(functionExpression.toString());
|
||||||
|
|
||||||
if (function == null)
|
if (function == null)
|
||||||
function = createLambdaFunction(functionExpression);
|
function = createLambdaFunction(functionExpression);
|
||||||
|
@ -46,9 +47,8 @@ public class EVAL extends LispFunction {
|
||||||
|
|
||||||
public static SExpression eval(SExpression sExpression) {
|
public static SExpression eval(SExpression sExpression) {
|
||||||
Cons argumentList = LIST.makeList(sExpression);
|
Cons argumentList = LIST.makeList(sExpression);
|
||||||
EVAL eval = new EVAL();
|
|
||||||
|
|
||||||
return eval.call(argumentList);
|
return lookupFunction("EVAL").call(argumentList);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ArgumentValidator argumentValidator;
|
private ArgumentValidator argumentValidator;
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package function.builtin;
|
package function.builtin;
|
||||||
|
|
||||||
|
import static table.FunctionTable.lookupFunction;
|
||||||
|
|
||||||
import function.*;
|
import function.*;
|
||||||
import sexpression.*;
|
import sexpression.*;
|
||||||
import table.*;
|
import table.*;
|
||||||
|
@ -8,7 +10,7 @@ import table.*;
|
||||||
public class SET extends LispFunction {
|
public class SET extends LispFunction {
|
||||||
|
|
||||||
public static SExpression set(Cons argumentList) {
|
public static SExpression set(Cons argumentList) {
|
||||||
return new SET().call(argumentList);
|
return lookupFunction("SET").call(argumentList);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ArgumentValidator argumentValidator;
|
private ArgumentValidator argumentValidator;
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
package function.builtin;
|
package function.builtin;
|
||||||
|
|
||||||
|
import static table.FunctionTable.lookupFunction;
|
||||||
|
|
||||||
import java.text.MessageFormat;
|
import java.text.MessageFormat;
|
||||||
|
|
||||||
import error.LispException;
|
import error.LispException;
|
||||||
import function.*;
|
import function.*;
|
||||||
import sexpression.*;
|
import sexpression.*;
|
||||||
import table.FunctionTable;
|
|
||||||
|
|
||||||
@FunctionNames({ "SYMBOL-FUNCTION" })
|
@FunctionNames({ "SYMBOL-FUNCTION" })
|
||||||
public class SYMBOL_FUNCTION extends LispFunction {
|
public class SYMBOL_FUNCTION extends LispFunction {
|
||||||
|
@ -22,7 +23,7 @@ public class SYMBOL_FUNCTION extends LispFunction {
|
||||||
argumentValidator.validate(argumentList);
|
argumentValidator.validate(argumentList);
|
||||||
|
|
||||||
SExpression symbol = argumentList.getFirst();
|
SExpression symbol = argumentList.getFirst();
|
||||||
LispFunction function = FunctionTable.lookupFunction(symbol.toString());
|
LispFunction function = lookupFunction(symbol.toString());
|
||||||
|
|
||||||
if (function != null)
|
if (function != null)
|
||||||
return createRepresentation(symbol, function);
|
return createRepresentation(symbol, function);
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package function.builtin.cons;
|
package function.builtin.cons;
|
||||||
|
|
||||||
|
import static function.builtin.cons.LIST.makeList;
|
||||||
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
|
||||||
import function.*;
|
import function.*;
|
||||||
|
@ -10,7 +12,7 @@ public class LENGTH extends LispFunction {
|
||||||
|
|
||||||
public static BigInteger getLength(Cons list) {
|
public static BigInteger getLength(Cons list) {
|
||||||
LENGTH lengthFunction = new LENGTH();
|
LENGTH lengthFunction = new LENGTH();
|
||||||
LispNumber length = lengthFunction.callWithoutArgumentValidation(LIST.makeList(list));
|
LispNumber length = lengthFunction.callWithoutArgumentValidation(makeList(list));
|
||||||
|
|
||||||
return length.getValue();
|
return length.getValue();
|
||||||
}
|
}
|
||||||
|
@ -35,7 +37,7 @@ public class LENGTH extends LispFunction {
|
||||||
|
|
||||||
private LispNumber callTailRecursive(BigInteger accumulatedLength, Cons argumentList) {
|
private LispNumber callTailRecursive(BigInteger accumulatedLength, Cons argumentList) {
|
||||||
Cons list = (Cons) argumentList.getFirst();
|
Cons list = (Cons) argumentList.getFirst();
|
||||||
Cons restOfList = LIST.makeList(list.getRest());
|
Cons restOfList = makeList(list.getRest());
|
||||||
|
|
||||||
if (list.isNull())
|
if (list.isNull())
|
||||||
return new LispNumber(accumulatedLength);
|
return new LispNumber(accumulatedLength);
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
package function.builtin.special;
|
package function.builtin.special;
|
||||||
|
|
||||||
|
import static function.builtin.cons.LIST.makeList;
|
||||||
|
import static table.FunctionTable.*;
|
||||||
|
|
||||||
import java.text.MessageFormat;
|
import java.text.MessageFormat;
|
||||||
|
|
||||||
import environment.RuntimeEnvironment;
|
import environment.RuntimeEnvironment;
|
||||||
import error.*;
|
import error.*;
|
||||||
import function.*;
|
import function.*;
|
||||||
import function.builtin.cons.LIST;
|
|
||||||
import sexpression.*;
|
import sexpression.*;
|
||||||
import table.FunctionTable;
|
|
||||||
|
|
||||||
public abstract class Define extends LispSpecialFunction {
|
public abstract class Define extends LispSpecialFunction {
|
||||||
|
|
||||||
|
@ -36,7 +37,7 @@ public abstract class Define extends LispSpecialFunction {
|
||||||
Cons remainingArguments = (Cons) argumentList.getRest();
|
Cons remainingArguments = (Cons) argumentList.getRest();
|
||||||
SExpression functionName = argumentList.getFirst();
|
SExpression functionName = argumentList.getFirst();
|
||||||
SExpression secondArgument = remainingArguments.getFirst();
|
SExpression secondArgument = remainingArguments.getFirst();
|
||||||
lambdaListIsListValidator.validate(LIST.makeList(secondArgument));
|
lambdaListIsListValidator.validate(makeList(secondArgument));
|
||||||
|
|
||||||
Cons lambdaList = (Cons) secondArgument;
|
Cons lambdaList = (Cons) secondArgument;
|
||||||
lambdaListValidator.validate(lambdaList);
|
lambdaListValidator.validate(lambdaList);
|
||||||
|
@ -44,10 +45,10 @@ public abstract class Define extends LispSpecialFunction {
|
||||||
Cons functionBody = (Cons) remainingArguments.getRest();
|
Cons functionBody = (Cons) remainingArguments.getRest();
|
||||||
UserDefinedFunction function = createFunction(functionName, lambdaList, functionBody);
|
UserDefinedFunction function = createFunction(functionName, lambdaList, functionBody);
|
||||||
|
|
||||||
if (FunctionTable.isAlreadyDefined(functionName.toString()))
|
if (isAlreadyDefined(functionName.toString()))
|
||||||
errorManager.handle(new RedefiningFunctionWarning(functionName.toString()));
|
errorManager.handle(new RedefiningFunctionWarning(functionName.toString()));
|
||||||
|
|
||||||
FunctionTable.defineFunction(functionName.toString(), function);
|
defineFunction(functionName.toString(), function);
|
||||||
|
|
||||||
return functionName;
|
return functionName;
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,11 +67,11 @@ public class FunctionTable {
|
||||||
getTable().put(functionName, function);
|
getTable().put(functionName, function);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void reset() {
|
public static void resetFunctionTable() {
|
||||||
getUniqueInstance().initializeFunctionTable(allBuiltIns);
|
getUniqueInstance().initializeFunctionTable(allBuiltIns);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void reset(Set<Class<? extends LispFunction>> builtIns) {
|
static void resetFunctionTable(Set<Class<? extends LispFunction>> builtIns) {
|
||||||
getUniqueInstance().initializeFunctionTable(builtIns);
|
getUniqueInstance().initializeFunctionTable(builtIns);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
package acceptance.fixture;
|
package acceptance.fixture;
|
||||||
|
|
||||||
|
import static table.FunctionTable.resetFunctionTable;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
|
||||||
import interpreter.*;
|
import interpreter.*;
|
||||||
import table.*;
|
import table.ExecutionContext;
|
||||||
|
|
||||||
public class LispInterpreterFixture {
|
public class LispInterpreterFixture {
|
||||||
|
|
||||||
|
@ -22,7 +24,7 @@ public class LispInterpreterFixture {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void reset() {
|
public void reset() {
|
||||||
FunctionTable.reset();
|
resetFunctionTable();
|
||||||
ExecutionContext.getInstance().clearContext();
|
ExecutionContext.getInstance().clearContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,22 +1,22 @@
|
||||||
package function.builtin;
|
package function.builtin;
|
||||||
|
|
||||||
|
import static table.FunctionTable.resetFunctionTable;
|
||||||
import static testutil.TestUtilities.*;
|
import static testutil.TestUtilities.*;
|
||||||
|
|
||||||
import org.junit.*;
|
import org.junit.*;
|
||||||
|
|
||||||
import function.ArgumentValidator.TooFewArgumentsException;
|
import function.ArgumentValidator.TooFewArgumentsException;
|
||||||
import table.FunctionTable;
|
|
||||||
|
|
||||||
public class FUNCALLTester {
|
public class FUNCALLTester {
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
FunctionTable.reset();
|
resetFunctionTable();
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
public void tearDown() {
|
public void tearDown() {
|
||||||
FunctionTable.reset();
|
resetFunctionTable();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -3,24 +3,24 @@ package function.builtin;
|
||||||
import static error.ErrorManager.Severity.ERROR;
|
import static error.ErrorManager.Severity.ERROR;
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
import static sexpression.Nil.NIL;
|
import static sexpression.Nil.NIL;
|
||||||
|
import static table.FunctionTable.resetFunctionTable;
|
||||||
import static testutil.TestUtilities.evaluateString;
|
import static testutil.TestUtilities.evaluateString;
|
||||||
|
|
||||||
import org.junit.*;
|
import org.junit.*;
|
||||||
|
|
||||||
import function.ArgumentValidator.*;
|
import function.ArgumentValidator.*;
|
||||||
import function.builtin.SYMBOL_FUNCTION.UndefinedSymbolFunctionException;
|
import function.builtin.SYMBOL_FUNCTION.UndefinedSymbolFunctionException;
|
||||||
import table.FunctionTable;
|
|
||||||
|
|
||||||
public class SYMBOL_FUNCTIONTester {
|
public class SYMBOL_FUNCTIONTester {
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
FunctionTable.reset();
|
resetFunctionTable();
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
public void tearDown() {
|
public void tearDown() {
|
||||||
FunctionTable.reset();
|
resetFunctionTable();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package function.builtin.special;
|
package function.builtin.special;
|
||||||
|
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static table.FunctionTable.resetFunctionTable;
|
||||||
import static testutil.TestUtilities.*;
|
import static testutil.TestUtilities.*;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
@ -11,7 +12,6 @@ import environment.RuntimeEnvironment;
|
||||||
import error.ErrorManager;
|
import error.ErrorManager;
|
||||||
import function.ArgumentValidator.*;
|
import function.ArgumentValidator.*;
|
||||||
import function.UserDefinedFunction.IllegalKeywordRestPositionException;
|
import function.UserDefinedFunction.IllegalKeywordRestPositionException;
|
||||||
import table.FunctionTable;
|
|
||||||
|
|
||||||
public class DEFINE_MACROTester {
|
public class DEFINE_MACROTester {
|
||||||
|
|
||||||
|
@ -34,12 +34,12 @@ public class DEFINE_MACROTester {
|
||||||
environment.setErrorManager(new ErrorManager());
|
environment.setErrorManager(new ErrorManager());
|
||||||
environment.setWarningOutputDecorator(s -> s);
|
environment.setWarningOutputDecorator(s -> s);
|
||||||
|
|
||||||
FunctionTable.reset();
|
resetFunctionTable();
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
public void tearDown() {
|
public void tearDown() {
|
||||||
FunctionTable.reset();
|
resetFunctionTable();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package function.builtin.special;
|
package function.builtin.special;
|
||||||
|
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static table.FunctionTable.resetFunctionTable;
|
||||||
import static testutil.TestUtilities.*;
|
import static testutil.TestUtilities.*;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
@ -11,7 +12,6 @@ import environment.RuntimeEnvironment;
|
||||||
import error.ErrorManager;
|
import error.ErrorManager;
|
||||||
import function.ArgumentValidator.*;
|
import function.ArgumentValidator.*;
|
||||||
import function.UserDefinedFunction.IllegalKeywordRestPositionException;
|
import function.UserDefinedFunction.IllegalKeywordRestPositionException;
|
||||||
import table.FunctionTable;
|
|
||||||
|
|
||||||
public class DEFUNTester {
|
public class DEFUNTester {
|
||||||
|
|
||||||
|
@ -34,12 +34,12 @@ public class DEFUNTester {
|
||||||
environment.setErrorManager(new ErrorManager());
|
environment.setErrorManager(new ErrorManager());
|
||||||
environment.setWarningOutputDecorator(s -> s);
|
environment.setWarningOutputDecorator(s -> s);
|
||||||
|
|
||||||
FunctionTable.reset();
|
resetFunctionTable();
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
public void tearDown() {
|
public void tearDown() {
|
||||||
FunctionTable.reset();
|
resetFunctionTable();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -3,6 +3,7 @@ package table;
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
import static sexpression.Nil.NIL;
|
import static sexpression.Nil.NIL;
|
||||||
import static sexpression.Symbol.T;
|
import static sexpression.Symbol.T;
|
||||||
|
import static table.FunctionTable.*;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
@ -57,58 +58,58 @@ public class FunctionTableTester {
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
FunctionTable.reset();
|
resetFunctionTable();
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
public void tearDown() {
|
public void tearDown() {
|
||||||
FunctionTable.reset();
|
resetFunctionTable();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void builtInFunctionIsDefined() {
|
public void builtInFunctionIsDefined() {
|
||||||
assertTrue(FunctionTable.isAlreadyDefined("CONS"));
|
assertTrue(isAlreadyDefined("CONS"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void undefinedFunctionIsNotDefined() {
|
public void undefinedFunctionIsNotDefined() {
|
||||||
assertFalse(FunctionTable.isAlreadyDefined("undefined"));
|
assertFalse(isAlreadyDefined("undefined"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void lookupBuiltInFunction_ReturnsFunction() {
|
public void lookupBuiltInFunction_ReturnsFunction() {
|
||||||
assertNotNull(FunctionTable.lookupFunction("CONS"));
|
assertNotNull(lookupFunction("CONS"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void lookupUndefinedFunction_ReturnsNull() {
|
public void lookupUndefinedFunction_ReturnsNull() {
|
||||||
assertNull(FunctionTable.lookupFunction("undefined"));
|
assertNull(lookupFunction("undefined"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void defineFunction() {
|
public void defineFunctionWorks() {
|
||||||
String functionName = "testFunction";
|
String functionName = "testFunction";
|
||||||
LispFunction testFunction = createLispFunction();
|
LispFunction testFunction = createLispFunction();
|
||||||
|
|
||||||
assertNull(FunctionTable.lookupFunction(functionName));
|
assertNull(lookupFunction(functionName));
|
||||||
assertFalse(FunctionTable.isAlreadyDefined(functionName));
|
assertFalse(isAlreadyDefined(functionName));
|
||||||
|
|
||||||
FunctionTable.defineFunction(functionName, testFunction);
|
defineFunction(functionName, testFunction);
|
||||||
|
|
||||||
assertTrue(FunctionTable.isAlreadyDefined(functionName));
|
assertTrue(isAlreadyDefined(functionName));
|
||||||
assertEquals(testFunction, FunctionTable.lookupFunction(functionName));
|
assertEquals(testFunction, lookupFunction(functionName));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void resetFunctionTable() {
|
public void resetFunctionTableWorks() {
|
||||||
String functionName = "testFunction";
|
String functionName = "testFunction";
|
||||||
LispFunction testFunction = createLispFunction();
|
LispFunction testFunction = createLispFunction();
|
||||||
FunctionTable.defineFunction(functionName, testFunction);
|
defineFunction(functionName, testFunction);
|
||||||
|
|
||||||
FunctionTable.reset();
|
resetFunctionTable();
|
||||||
|
|
||||||
assertFalse(FunctionTable.isAlreadyDefined(functionName));
|
assertFalse(isAlreadyDefined(functionName));
|
||||||
assertNull(FunctionTable.lookupFunction(functionName));
|
assertNull(lookupFunction(functionName));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -116,10 +117,10 @@ public class FunctionTableTester {
|
||||||
Set<Class<? extends LispFunction>> goodBuiltIns = new HashSet<>();
|
Set<Class<? extends LispFunction>> goodBuiltIns = new HashSet<>();
|
||||||
goodBuiltIns.add(GoodFunction.class);
|
goodBuiltIns.add(GoodFunction.class);
|
||||||
|
|
||||||
FunctionTable.reset(goodBuiltIns);
|
resetFunctionTable(goodBuiltIns);
|
||||||
|
|
||||||
assertTrue(FunctionTable.isAlreadyDefined("GOOD"));
|
assertTrue(isAlreadyDefined("GOOD"));
|
||||||
assertNotNull(FunctionTable.lookupFunction("GOOD"));
|
assertNotNull(lookupFunction("GOOD"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = LispFunctionInstantiationException.class)
|
@Test(expected = LispFunctionInstantiationException.class)
|
||||||
|
@ -127,7 +128,7 @@ public class FunctionTableTester {
|
||||||
Set<Class<? extends LispFunction>> badBuiltIns = new HashSet<>();
|
Set<Class<? extends LispFunction>> badBuiltIns = new HashSet<>();
|
||||||
badBuiltIns.add(BadFunction.class);
|
badBuiltIns.add(BadFunction.class);
|
||||||
|
|
||||||
FunctionTable.reset(badBuiltIns);
|
resetFunctionTable(badBuiltIns);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -144,10 +145,10 @@ public class FunctionTableTester {
|
||||||
Set<Class<? extends LispFunction>> namelessBuiltins = new HashSet<>();
|
Set<Class<? extends LispFunction>> namelessBuiltins = new HashSet<>();
|
||||||
namelessBuiltins.add(UglyFunction.class);
|
namelessBuiltins.add(UglyFunction.class);
|
||||||
|
|
||||||
FunctionTable.reset(namelessBuiltins);
|
resetFunctionTable(namelessBuiltins);
|
||||||
|
|
||||||
assertFalse(FunctionTable.isAlreadyDefined("UGLY"));
|
assertFalse(isAlreadyDefined("UGLY"));
|
||||||
assertNull(FunctionTable.lookupFunction("UGLY"));
|
assertNull(lookupFunction("UGLY"));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue