Safety point before changing the return type of SExp.eval to SExp
This commit is contained in:
parent
adc5b2d250
commit
f6d3658342
0
build-common-versioning.xml
Normal file → Executable file
0
build-common-versioning.xml
Normal file → Executable file
0
project.properties
Normal file → Executable file
0
project.properties
Normal file → Executable file
2
src/edu/utexas/cs345/jdblisp/FunctionEntry.java
Normal file → Executable file
2
src/edu/utexas/cs345/jdblisp/FunctionEntry.java
Normal file → Executable 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
|
||||
|
3
src/edu/utexas/cs345/jdblisp/InvalidArgumentQuantityException.java
Normal file → Executable file
3
src/edu/utexas/cs345/jdblisp/InvalidArgumentQuantityException.java
Normal file → Executable 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
4
src/edu/utexas/cs345/jdblisp/Lisp.java
Normal file → Executable 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
0
src/edu/utexas/cs345/jdblisp/LispException.java
Normal file → Executable file
6
src/edu/utexas/cs345/jdblisp/List.java
Normal file → Executable file
6
src/edu/utexas/cs345/jdblisp/List.java
Normal file → Executable 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
3
src/edu/utexas/cs345/jdblisp/Num.java
Normal file → Executable 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
0
src/edu/utexas/cs345/jdblisp/Parser.jj
Normal file → Executable file
0
src/edu/utexas/cs345/jdblisp/SExp.java
Normal file → Executable file
0
src/edu/utexas/cs345/jdblisp/SExp.java
Normal file → Executable file
5
src/edu/utexas/cs345/jdblisp/Seq.java
Normal file → Executable file
5
src/edu/utexas/cs345/jdblisp/Seq.java
Normal file → Executable file
@ -46,4 +46,9 @@ public class Seq implements SExp {
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return car.toString() + (cdr == null ? "" : cdr.toString());
|
||||
}
|
||||
}
|
||||
|
101
src/edu/utexas/cs345/jdblisp/SpecialFormEntry.java
Executable file
101
src/edu/utexas/cs345/jdblisp/SpecialFormEntry.java
Executable 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
1
src/edu/utexas/cs345/jdblisp/Str.java
Normal file → Executable 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
0
src/edu/utexas/cs345/jdblisp/Symbol.java
Normal file → Executable file
3
src/edu/utexas/cs345/jdblisp/SymbolTable.java
Normal file → Executable file
3
src/edu/utexas/cs345/jdblisp/SymbolTable.java
Normal file → Executable 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)
|
||||
|
14
src/edu/utexas/cs345/jdblisp/TypeException.java
Normal file
14
src/edu/utexas/cs345/jdblisp/TypeException.java
Normal 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
2
src/edu/utexas/cs345/jdblisp/VariableEntry.java
Normal file → Executable 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);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user