Safety point before changing the return type of SExp.eval to SExp

This commit is contained in:
Jonathan Bernard 2009-11-20 09:10:21 -06:00
parent adc5b2d250
commit f6d3658342
19 changed files with 138 additions and 6 deletions

0
.hgignore Normal file → Executable file
View File

0
build-common-versioning.xml Normal file → Executable file
View File

0
build.xml Normal file → Executable file
View File

0
project.properties Normal file → Executable file
View File

2
src/edu/utexas/cs345/jdblisp/FunctionEntry.java Normal file → Executable file
View File

@ -18,7 +18,7 @@ public class FunctionEntry {
// bind arguments to parameters
SymbolTable localScope = new SymbolTable(symbolTable);
int i = 0
int i = 0;
while (i < parameters.length) {
// too few arguments

View File

@ -1,7 +1,8 @@
package edu.utexas.cs345.jdb-lisp;
package edu.utexas.cs345.jdblisp;
/**
* InvalidArgumentQuantityException
* @author Jonathan Bernard (jdbernard@gmail.com)
* Indicates a call to a form with an incorrect number of arguments.
*/
public class InvalidArgumentQuantityException extends LispException {

4
src/edu/utexas/cs345/jdblisp/Lisp.java Normal file → Executable file
View File

@ -26,12 +26,13 @@ public class Lisp {
public Lisp(boolean interactive) {
this.interactive = interactive;
Parser parser = new Parser(new ByteArrayInputStream(new byte[]{}));
globalSymbolTable = new SymbolTable();
SpecialFormEntry.defineSpecialForms(this);
}
public static void main(String[] args) {
Lisp lisp = new Lisp();
lisp.repl(System.in, System.out);
globalSymbolTable = SpecialForms.createSymbolTable();
}
public void repl(InputStream is, OutputStream os) {
@ -68,7 +69,6 @@ public class Lisp {
}
out.println(sexp.display(" "));
out.println(sexp.eval(globalSymbolTable).car.body);
// print prompt if applicable
if (interactive) {

0
src/edu/utexas/cs345/jdblisp/LispException.java Normal file → Executable file
View File

6
src/edu/utexas/cs345/jdblisp/List.java Normal file → Executable file
View File

@ -1,6 +1,7 @@
package edu.utexas.cs345.jdblisp;
/**
* List
* @author Jonathan Bernard (jdbernard@gmail.com)
*/
public class List implements SExp {
@ -42,4 +43,9 @@ public class List implements SExp {
return sb.toString();
}
@Override
public String toString() {
return "(" + (seq == null ? "" : seq.toString()) + ")";
}
}

3
src/edu/utexas/cs345/jdblisp/Num.java Normal file → Executable file
View File

@ -36,7 +36,7 @@ public class Num implements SExp {
}
/** {@inheritdoc} */
public SymbolTable eval(SymbolTable table) {
public SExp eval(SymbolTable table) {
return new SymbolTable(
new TableEntry(
new Symbol("RETURN-VAL"),
@ -48,6 +48,7 @@ public class Num implements SExp {
return offset + "Num: " + n.toString() + "\n";
}
@Override
public String toString() {
return n.toString();
}

0
src/edu/utexas/cs345/jdblisp/Parser.jj Normal file → Executable file
View File

0
src/edu/utexas/cs345/jdblisp/SExp.java Normal file → Executable file
View File

5
src/edu/utexas/cs345/jdblisp/Seq.java Normal file → Executable file
View File

@ -46,4 +46,9 @@ public class Seq implements SExp {
return sb.toString();
}
@Override
public String toString() {
return car.toString() + (cdr == null ? "" : cdr.toString());
}
}

View File

@ -0,0 +1,101 @@
package edu.utexas.cs345.jdblisp;
import java.util.ArrayList;
/**
* SpecialFormEntry
* @author Jonathan Bernard (jdbernard@gmail.com)
*/
public abstract class SpecialFormEntry extends FunctionEntry {
protected Lisp environment;
public SpecialFormEntry(Lisp environment) { this.environment = environment; }
public abstract SExp call(SymbolTable symbolTable, Seq arguments) throws LispException;
public static void defineSpecialForms(Lisp environment) {
SpecialFormEntry DEFUN = new SpecialFormEntry(environment) {
public SExp call(SymbolTable symbolTable, Seq arguments) throws LispException {
Symbol functionName;
ArrayList<Symbol> parameters;
SExp body;
// TODO: check to see if a function for this symbol exists
// and warn if so
if (arguments.length() != 3)
new InvalidArgumentQuantityException(3, arguments.length());
// first argument: Symbol for function name
if (!(arguments.car instanceof Symbol))
throw new TypeException(arguments.car, Symbol.class);
functionName = (Symbol) arguments.car;
// second argument, parameter list
arguments = arguments.cdr;
assert (arguments != null);
if (!(arguments.car instanceof List))
// TODO: error, need parameter list
// read parameters
parameters = new ArrayList<Symbol>();
Seq paramSeq = ((List) arguments.car).seq;
while (seq != null) {
if (!(seq.car instanceof Symbol))
throw new TypeException(seq.car, Symbol.class);
parameters.add((Symbol) seq.car);
seq = seq.cdr;
}
// third argument: function body
arguments = arguments.cdr;
assert (arguments != null);
// TODO: necessary? if (!(arguments.car instanceof List))
body = arguments.car;
environment.globalSymbolTable.define(functionName,
new FunctionEntry(parameters.toArray(new Symbol[]{}), body));
return functionName;
}
};
SpecialFormEntry SETQ = new SpecialFormEntry(environment) {
public SExp call(SymbolTable symbolTable, Seq arguments) throws LispException {
Symbol variableName;
SExp variableValue;
// TODO: check for redifinition of variable (and warn)
if (arguments.length() != 2)
throw new InvalidArgumentQuantityException(2,
arguments.length());
// first argument: Symbol for variable name
if (!(arguments.car instanceof Symbol))
// TODO: error: expected symbol
variableName = (Symbol) arguments.car;
// second argument: variable value
arguments = arguments.cdr;
assert (arguments != null);
variableValue = arguments.car;
}
};
environment.globalSymbolTable.defin(new Symbol("DEFUN"), DEFUN);
environment.globalSymbolTable.defin(new Symbol("SETQ"), SETQ);
}
}

1
src/edu/utexas/cs345/jdblisp/Str.java Normal file → Executable file
View File

@ -24,6 +24,7 @@ public class Str implements SExp {
return offset + "Str: " + value + "\n";
}
@Override
public String toString() {
return value;
}

0
src/edu/utexas/cs345/jdblisp/Symbol.java Normal file → Executable file
View File

3
src/edu/utexas/cs345/jdblisp/SymbolTable.java Normal file → Executable file
View File

@ -1,5 +1,8 @@
package edu.utexas.cs345.jdblisp;
import java.util.HashMap;
import java.util.Map;
/**
* SymbolTable
* @author Jonathan Bernard (jdbernard@gmail.com)

View File

@ -0,0 +1,14 @@
package edu.utexas.cs345.jdblisp;
/**
* TypeException
* @author Jonathan Bernard (jdbernard@gmail.com)
* Represents type errors.
*/
public class TypeException extends LispException {
public TypeException(SExp sexp, Class<? extends SExp> expectedType) {
super("TYPE-ERROR: The value " + sexp.toString() + " is not of type "
+ expectedType.getSimpleName());
}
}

2
src/edu/utexas/cs345/jdblisp/VariableEntry.java Normal file → Executable file
View File

@ -10,7 +10,7 @@ public class VariableEntry {
public VariableEntry(SExp expression) { this.expression = expression; }
public SExp eval(SymbolTable symbolTable) {
public SExp eval(SymbolTable symbolTable) throws LispException {
return expression.eval(symbolTable);
}
}