Added unit tests and refactored defun
This commit is contained in:
		
							parent
							
								
									5fd22b310f
								
							
						
					
					
						commit
						79648cd96f
					
				@ -1,7 +1,9 @@
 | 
				
			|||||||
package function.builtin.special;
 | 
					package function.builtin.special;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.text.MessageFormat;
 | 
				
			||||||
import java.util.HashMap;
 | 
					import java.util.HashMap;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import environment.Environment;
 | 
				
			||||||
import function.*;
 | 
					import function.*;
 | 
				
			||||||
import function.builtin.EVAL;
 | 
					import function.builtin.EVAL;
 | 
				
			||||||
import function.builtin.cons.LIST;
 | 
					import function.builtin.cons.LIST;
 | 
				
			||||||
@ -12,6 +14,7 @@ public class DEFUN extends LispFunction {
 | 
				
			|||||||
    private ArgumentValidator argumentValidator;
 | 
					    private ArgumentValidator argumentValidator;
 | 
				
			||||||
    private ArgumentValidator lambdaListIsListValidator;
 | 
					    private ArgumentValidator lambdaListIsListValidator;
 | 
				
			||||||
    private ArgumentValidator lambdaListValidator;
 | 
					    private ArgumentValidator lambdaListValidator;
 | 
				
			||||||
 | 
					    private Environment environment;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public DEFUN() {
 | 
					    public DEFUN() {
 | 
				
			||||||
        this.argumentValidator = new ArgumentValidator("DEFUN");
 | 
					        this.argumentValidator = new ArgumentValidator("DEFUN");
 | 
				
			||||||
@ -23,6 +26,8 @@ public class DEFUN extends LispFunction {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        this.lambdaListValidator = new ArgumentValidator("DEFUN|lambda_list|");
 | 
					        this.lambdaListValidator = new ArgumentValidator("DEFUN|lambda_list|");
 | 
				
			||||||
        this.lambdaListValidator.setEveryArgumentExpectedType(Symbol.class);
 | 
					        this.lambdaListValidator.setEveryArgumentExpectedType(Symbol.class);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.environment = Environment.getInstance();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public SExpression call(Cons argumentList) {
 | 
					    public SExpression call(Cons argumentList) {
 | 
				
			||||||
@ -37,16 +42,26 @@ public class DEFUN extends LispFunction {
 | 
				
			|||||||
        lambdaListValidator.validate(lambdaList);
 | 
					        lambdaListValidator.validate(lambdaList);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Cons functionBody = (Cons) remainingArguments.getCdr();
 | 
					        Cons functionBody = (Cons) remainingArguments.getCdr();
 | 
				
			||||||
 | 
					        UserDefinedFunction function = new UserDefinedFunction(functionName.toString(), lambdaList, functionBody);
 | 
				
			||||||
        HashMap<String, LispFunction> functionTable = EVAL.getFunctionTable();
 | 
					        HashMap<String, LispFunction> functionTable = EVAL.getFunctionTable();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (functionTable.containsKey(functionName.toString()))
 | 
					        if (isAlreadyDefined(functionName, functionTable))
 | 
				
			||||||
            System.out.println("WARNING: redefining function " + functionName.toString());
 | 
					            printWarning(functionName);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        functionTable.put(functionName.toString(), new UserDefinedFunction(functionName.toString(), lambdaList, functionBody));
 | 
					        functionTable.put(functionName.toString(), function);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return functionName;
 | 
					        return functionName;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private boolean isAlreadyDefined(SExpression functionName, HashMap<String, LispFunction> functionTable) {
 | 
				
			||||||
 | 
					        return functionTable.containsKey(functionName.toString());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void printWarning(SExpression functionName) {
 | 
				
			||||||
 | 
					        String message = MessageFormat.format("WARNING: redefining function {0}", functionName.toString());
 | 
				
			||||||
 | 
					        environment.getOutput().println(message);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public boolean evaluateArguments() {
 | 
					    public boolean evaluateArguments() {
 | 
				
			||||||
        return false;
 | 
					        return false;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -1,13 +1,29 @@
 | 
				
			|||||||
package function.builtin.special;
 | 
					package function.builtin.special;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import static org.junit.Assert.assertEquals;
 | 
				
			||||||
import static testutil.TestUtilities.*;
 | 
					import static testutil.TestUtilities.*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import org.junit.Test;
 | 
					import java.io.*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.junit.*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import environment.Environment;
 | 
				
			||||||
import function.ArgumentValidator.*;
 | 
					import function.ArgumentValidator.*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public class DEFUNTester {
 | 
					public class DEFUNTester {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private ByteArrayOutputStream outputStream;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void assertPrinted(String expected) {
 | 
				
			||||||
 | 
					        assertEquals(expected, outputStream.toString());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Before
 | 
				
			||||||
 | 
					    public void setUp() {
 | 
				
			||||||
 | 
					        this.outputStream = new ByteArrayOutputStream();
 | 
				
			||||||
 | 
					        Environment.getInstance().setOutput(new PrintStream(outputStream));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Test
 | 
					    @Test
 | 
				
			||||||
    public void testDefun() {
 | 
					    public void testDefun() {
 | 
				
			||||||
        String input = "(defun f () nil)";
 | 
					        String input = "(defun f () nil)";
 | 
				
			||||||
@ -16,6 +32,24 @@ public class DEFUNTester {
 | 
				
			|||||||
        assertSExpressionsMatch(parseString("()"), evaluateString("(f)"));
 | 
					        assertSExpressionsMatch(parseString("()"), evaluateString("(f)"));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    public void redefineFunction_DisplaysWarning() {
 | 
				
			||||||
 | 
					        String input = "(defun myFunction () nil)";
 | 
				
			||||||
 | 
					        evaluateString(input);
 | 
				
			||||||
 | 
					        evaluateString(input);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        assertPrinted("WARNING: redefining function MYFUNCTION\n");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    public void redefineFunction_ActuallyRedefinesFunction() {
 | 
				
			||||||
 | 
					        evaluateString("(defun myFunction2 () nil)");
 | 
				
			||||||
 | 
					        evaluateString("(defun myFunction2 () T)");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        assertPrinted("WARNING: redefining function MYFUNCTION2\n");
 | 
				
			||||||
 | 
					        assertSExpressionsMatch(parseString("t"), evaluateString("(myFunction2)"));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Test(expected = DottedArgumentListException.class)
 | 
					    @Test(expected = DottedArgumentListException.class)
 | 
				
			||||||
    public void testDefunWithDottedLambdaList() {
 | 
					    public void testDefunWithDottedLambdaList() {
 | 
				
			||||||
        String input = "(funcall 'defun 'x (cons 'a 'b) ())";
 | 
					        String input = "(funcall 'defun 'x (cons 'a 'b) ())";
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user