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
|
// bind arguments to parameters
|
||||||
SymbolTable localScope = new SymbolTable(symbolTable);
|
SymbolTable localScope = new SymbolTable(symbolTable);
|
||||||
int i = 0
|
int i = 0;
|
||||||
while (i < parameters.length) {
|
while (i < parameters.length) {
|
||||||
|
|
||||||
// too few arguments
|
// 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
|
* InvalidArgumentQuantityException
|
||||||
|
* @author Jonathan Bernard (jdbernard@gmail.com)
|
||||||
* Indicates a call to a form with an incorrect number of arguments.
|
* Indicates a call to a form with an incorrect number of arguments.
|
||||||
*/
|
*/
|
||||||
public class InvalidArgumentQuantityException extends LispException {
|
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) {
|
public Lisp(boolean interactive) {
|
||||||
this.interactive = interactive;
|
this.interactive = interactive;
|
||||||
Parser parser = new Parser(new ByteArrayInputStream(new byte[]{}));
|
Parser parser = new Parser(new ByteArrayInputStream(new byte[]{}));
|
||||||
|
globalSymbolTable = new SymbolTable();
|
||||||
|
SpecialFormEntry.defineSpecialForms(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
Lisp lisp = new Lisp();
|
Lisp lisp = new Lisp();
|
||||||
lisp.repl(System.in, System.out);
|
lisp.repl(System.in, System.out);
|
||||||
globalSymbolTable = SpecialForms.createSymbolTable();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void repl(InputStream is, OutputStream os) {
|
public void repl(InputStream is, OutputStream os) {
|
||||||
@ -68,7 +69,6 @@ public class Lisp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
out.println(sexp.display(" "));
|
out.println(sexp.display(" "));
|
||||||
out.println(sexp.eval(globalSymbolTable).car.body);
|
|
||||||
|
|
||||||
// print prompt if applicable
|
// print prompt if applicable
|
||||||
if (interactive) {
|
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;
|
package edu.utexas.cs345.jdblisp;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* List
|
||||||
* @author Jonathan Bernard (jdbernard@gmail.com)
|
* @author Jonathan Bernard (jdbernard@gmail.com)
|
||||||
*/
|
*/
|
||||||
public class List implements SExp {
|
public class List implements SExp {
|
||||||
@ -42,4 +43,9 @@ public class List implements SExp {
|
|||||||
return sb.toString();
|
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} */
|
/** {@inheritdoc} */
|
||||||
public SymbolTable eval(SymbolTable table) {
|
public SExp eval(SymbolTable table) {
|
||||||
return new SymbolTable(
|
return new SymbolTable(
|
||||||
new TableEntry(
|
new TableEntry(
|
||||||
new Symbol("RETURN-VAL"),
|
new Symbol("RETURN-VAL"),
|
||||||
@ -48,6 +48,7 @@ public class Num implements SExp {
|
|||||||
return offset + "Num: " + n.toString() + "\n";
|
return offset + "Num: " + n.toString() + "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return n.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();
|
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";
|
return offset + "Str: " + value + "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return value;
|
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;
|
package edu.utexas.cs345.jdblisp;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SymbolTable
|
* SymbolTable
|
||||||
* @author Jonathan Bernard (jdbernard@gmail.com)
|
* @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 VariableEntry(SExp expression) { this.expression = expression; }
|
||||||
|
|
||||||
public SExp eval(SymbolTable symbolTable) {
|
public SExp eval(SymbolTable symbolTable) throws LispException {
|
||||||
return expression.eval(symbolTable);
|
return expression.eval(symbolTable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user