Skip to content
Browse files

Merge remote-tracking branch 'origin' into master-interp2

Conflicts:
	crono/src/crono/Crono.java
	crono/src/crono/CronoFunction.java
	crono/src/crono/Interpreter.java
	crono/src/crono/type/CronoStruct.java
	crono/src/crono/type/LambdaFunction.java
  • Loading branch information...
2 parents ccb8c3c + abcc9b0 commit e228f0860b04a8b4c3cb6a5e3e2ea815d797a685 Mark Watts committed Nov 27, 2012
View
218 crono/src/crono/CronoFunction.java
@@ -6,6 +6,7 @@
import java.io.StringReader;
import java.util.LinkedList;
import java.util.List;
+import java.util.Map;
import crono.type.*;
@@ -56,6 +57,92 @@ public String toString()
return "cdr";
}
}),
+ LIST(new Function(new TypeId[]{CronoType.TYPEID}, Cons.TYPEID, 1, true)
+ {
+ public CronoType run(Visitor v, List<CronoType> args) {
+ return c.fromList();
+ }
+ public String toString() {
+ return "list";
+ }
+ }),
+ GET(new Function(new TypeId[]{CronoArray.TYPEID, CronoInteger.TYPEID},
+ CronoType.TYPEID, 2)
+ {
+ public CronoType run(Visitor v, List<CronoType> args) {
+ CronoArray a = args.remove(0);
+ int index = (int)((CronoInteger)args.remove(0)).value;
+ return a.get(index);
+ }
+ public String toString() {
+ return "get";
+ }
+ }),
+ PUT(new Function(new TypeId[]{CronoArray.TYPEID, CronoInteger.TYPEID,
+ CronoType.TYPEID},
+ CronoType.TYPEID, 3)
+ {
+ public CronoType run(Visitor v, List<CronoType> args) {
+ CronoArray a = (CronoArray) args.remove(0);
+ int index = (int)((CronoInteger)args.remove(0)).value;
+ CronoType new_val = args.remove(0);
+ /* Maybe return nil instead? */
+ a.put(index, new_val);
+ return a;
+ }
+ public String toString() {
+ return "put";
+ }
+ }),
+ APPEND(new Function(new TypeId[]{CronoArray.TYPEID, CronoType.TYPEID},
+ CronoType.TYPEID, 2)
+ {
+ public CronoType run(Visitor v, List<CronoType> args) {
+ CronoArray a = (CronoArray) args.remove(0);
+ a.append(args.remove(0));
+ return a;
+ }
+ public String toString() {
+ return "append";
+ }
+ }),
+ LAMBDA(new Function(new TypeId[]{Cons.TYPEID, CronoType.TYPEID},
+ Function.TYPEID, 2, true, EvalType.NONE)
+ {
+ private static final String _bad_type =
+ "\\: expected :cons :any, got %s, %s";
+ private static final String _bad_arg =
+ "\\: arguments must be :symbol, got %s";
+
+ public CronoType run(Visitor v, List<CronoType> args) {
+ if(!(args[0] instanceof Cons)) {
+ throw new InterpreterException(_bad_type,
+ args[0].typeId(),
+ args[1].typeId());
+ }
+
+ List<CronoType> list = ((Cons)args[0]).toList();
+ for(CronoType item : list) {
+ if(!(item instanceof Symbol)) {
+ throw new InterpreterException(_bad_arg,item.typeId());
+ }
+ }
+
+ Symbol[] arglist = new Symbol[list.size()];
+ CronoType[] body;
+ List<CronoType> blist = new LinkedList<CronoType>();
+ for(int i = 1; i < args.length; ++i) {
+ blist.add(args[i]);
+ }
+ body = new CronoType[blist.size()];
+ body = blist.toArray(body);
+ return new LambdaFunction(list.toArray(arglist), body,
+ v.getEnv());
+ }
+ public String toString() {
+ return "\\";
+ }
+ }),
EQ(new Function(new TypeId[]{CronoType.TYPEID, CronoType.TYPEID},
Cons.TYPEID, 2)
{
@@ -133,7 +220,6 @@ public String toString() {
MUL(new Function(new TypeId[]{CronoNumber.TYPEID, CronoNumber.TYPEID},
CronoNumber.TYPEID, 2)
{
-
public CronoType run(Visitor v, List<CronoType> args)
{
CronoNumber lhs = (CronoNumber) args.remove(0);
@@ -165,12 +251,47 @@ public String toString() {
return "*";
}
}),
+ DIV(new Function(new TypeId[]{CronoNumber.TYPEID, CronoNumber.TYPEID},
+ CronoNumber.TYPEID, 2)
+ {
+ public CronoType run(Visitor v, List<CronoType> args) {
+ CronoNumber lhs = (CronoNumber) args.remove(0);
+ CronoNumber rhs = (CronoNumber) args.remove(0);
+
+ if(lhs instanceof CronoFloat) {
+ double val1, val2;
+ val1 = ((CronoFloat)lhs).value;
+ if(rhs instanceof CronoFloat) {
+ val2 = ((CronoFloat)rhs).value;
+ }else {
+ val2 = (double)(((CronoInteger)rhs).value);
+ }
+ return new CronoFloat(val1 / val2);
+ }else {
+ if(rhs instanceof CronoFloat) {
+ double val1, val2;
+ val1 = (double)(((CronoInteger)lhs).value);
+ val2 = ((CronoFloat)rhs).value;
+ return new CronoFloat(val1 / val2);
+ }else {
+ long val1, val2;
+ val1 = ((CronoInteger)lhs).value;
+ val2 = ((CronoInteger)rhs).value;
+ return new CronoInteger(val1 / val2);
+ }
+ }
+ }
+
+ public String toString() {
+ return "/";
+ }
+ }),
//INT(new Function(new TypeId[]{CronoPrimitive.TYPEID},CronoInteger.TYPEID,1)
//{
//public static final String _bad_type =
//"INT: Excepted one of :char, :float, or :int; got %s";
- //public CronoType run(Visitor v, CronoType[] args) {
+ //public CronoType run(Visitor v, List<CronoType> args) {
//if(args[0] instanceof CronoCharacter) {
//return new CronoInteger(((long)((CronoCharacter)args[0]).ch));
//}else if(args[0] instanceof CronoFloat) {
@@ -190,7 +311,7 @@ public String toString() {
//private static final String _bad_type =
//"CHAR: expected one of :int, or :char; got %s";
- //public CronoType run(Visitor v, CronoType[] args) {
+ //public CronoType run(Visitor v, List<CronoType> args) {
//if(args[0] instanceof CronoInteger) {
//return new CronoCharacter((char)((CronoInteger)args[0]).value);
//}else if(args[0] instanceof CronoFloat) {
@@ -209,7 +330,7 @@ public String toString() {
//private static final String _bad_type =
//"FLOAT: expected one of :int, or :float; got %s";
- //public CronoType run(Visitor v, CronoType[] args) {
+ //public CronoType run(Visitor v, List<CronoType> args) {
//if(args[0] instanceof CronoInteger) {
//return new CronoFloat((double)((CronoInteger)args[0]).value);
//}else if(args[0] instanceof CronoCharacter) {
@@ -276,11 +397,11 @@ public String toString() {
//return TruthValue.T;
//}
- //public CronoType run(Visitor v, CronoType[] args) {
+ //public CronoType run(Visitor v, List<CronoType> args) {
//if(!(args[0] instanceof CronoString)) {
//throw new InterpreterException(_bad_type, args[0].typeId());
//}
- //String fname = ((CronoString)args[0]).image();
+ //String fname = ((CronoString)args[0]).toString();
//String lname = fname.toLowerCase();
//if(lname.endsWith(".lisp") || lname.endsWith(".crono")) {
//return loadLisp(v, fname);
@@ -293,15 +414,9 @@ public String toString() {
//}),
//PRINT(new Function(new TypeId[]{CronoType.TYPEID}, Nil.TYPEID, 1, true)
//{
- //public CronoType run(Visitor v, CronoType[] args) {
+ //public CronoType run(Visitor v, List<CronoType> args) {
//for(int i = 0; i < args.length; ++i) {
- //if(args[i] instanceof CronoString) {
- //System.out.print(((CronoString)args[i]).image());
- //}else if(args[i] instanceof CronoCharacter) {
- //System.out.print(((CronoCharacter)args[i]).ch);
- //}else {
- //System.out.print(args[i]);
- //}
+ //System.out.print(args[i].toString());
//}
//return Nil.NIL;
//}
@@ -311,7 +426,7 @@ public String toString() {
//}),
//PRINTLN(new Function(new TypeId[]{CronoType.TYPEID}, Nil.TYPEID, 1, true)
//{
- //public CronoType run(Visitor v, CronoType[] args) {
+ //public CronoType run(Visitor v, List<CronoType> args) {
//PRINT.function.run(v, args);
//System.out.println();
//return Nil.NIL;
@@ -320,48 +435,65 @@ public String toString() {
//return "println";
//}
//}),
- //[>
- //STRUCT(new Function() {
- //public int arity() {
- //return 1;
- //}
- //public CronoType run(Visitor v, CronoType[] args) {
+ //STRUCT(new Function(new TypeId[]{Symbol.TYPEID}, CronoStruct.TYPEID, 1,
+ //false, EvalType.NONE)
+ //{
+ //private static final String _name = "struct";
+ //private static final String _no_struct_in_scope =
+ //"struct: No structure definition for %s in scope";
+ //public CronoType run(Visitor v, List<CronoType> args) {
+ //CronoStruct struct = v.getEnv().getStruct((Symbol)args[0]);
+ //if(struct == null) {
+ //throw new InterpreterException(_no_struct_in_scope, args[0]);
+ //}
+ //return struct.copy();
//}
//public String toString() {
+ //return _name;
//}
//}),
- //SUBSTRUCT(new Function() {
- //public int arity() {
- //}
- //public CronoType run(Visitor v, CronoType[] args) {
+ //SUBSTRUCT(new Function(new TypeId[]{Symbol.TYPEID, Symbol.TYPEID,
+ //Cons.TYPEID},
+ //Nil.TYPEID, 3, false, EvalType.NONE)
+ //{
+ //private static final String _name = "substruct";
+ //private static final String _no_struct_in_scope =
+ //"substruct: no structure definition for %s in scope";
+
+ //public CronoType run(Visitor v, List<CronoType> args) {
+ //CronoStruct par = v.getEnv().getStruct((Symbol)args[1]);
+ //if(par == null) {
+ //throw new InterpreterException(_no_struct_in_scope, args[1]);
+ //}
+ //Map<String, CronoStruct.Field> fields;
+ //fields = CronoStruct.BuildFieldMap(_name, (Cons)args[2]);
+ //v.getEnv().put(new CronoStruct(args[0].toString(), fields, par));
+ //return Nil.NIL;
//}
//public String toString() {
+ //return _name;
//}
//}),
- //NEWSTRUCT(new Function() {
- //public static final String _bad_type =
- //"NEWSTRUCT: expected types :symbol :cons, got %s %s";
- //public int arity() {
- //return 2;
- //}
- //public CronoType run(Visitor v, CronoType[] args) {
- //if(!(args[0] instanceof Symbol && args[1] instanceof Cons)) {
- //throw new InterpreterException(_bad_type, args[0].typeId(),
- //args[1].typeId());
- //}
-
-
+ //DEFSTRUCT(new Function(new TypeId[]{Symbol.TYPEID, Cons.TYPEID},
+ //Nil.TYPEID, 2, false, EvalType.NONE)
+ //{
+ //private static final String _name = "defstruct";
+ //public CronoType run(Visitor v, List<CronoType> args) {
+ //Map<String, CronoStruct.Field> fields;
+ //fields = CronoStruct.BuildFieldMap(_name, (Cons)args[1]);
+ //v.getEnv().put(new CronoStruct(args[0].toString(), fields));
+ //return Nil.NIL;
//}
//public String toString() {
+ //return _name;
//}
//}),
- //*/
//EVAL(new Function(new TypeId[]{CronoString.TYPEID}, Cons.TYPEID, 1)
//{
- //public CronoType run(Visitor v, CronoType[] args) {
+ //public CronoType run(Visitor v, List<CronoType> args) {
//StringReader reader;
- //reader = new StringReader(((CronoString)args[0]).image());
+ //reader = new StringReader(((CronoString)args[0]).toString());
//Parser p = new Parser(reader);
@@ -371,10 +503,6 @@ public String toString() {
//throw new InterpreterException("EVAL: parse error\n%s",
//pe.getMessage());
//}
- //}
- //public String toString() {
- //return "eval";
- //}
//}),
;
View
241 crono/src/crono/Interpreter.java
@@ -0,0 +1,241 @@
+package crono;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Stack;
+
+import crono.type.Atom;
+import crono.type.Cons;
+import crono.type.CronoType;
+import crono.type.Function;
+import crono.type.LambdaFunction;
+import crono.type.Nil;
+import crono.type.Quote;
+import crono.type.Symbol;
+import crono.type.CronoTypeId;
+import crono.type.TypeId;
+
+public class Interpreter extends Visitor {
+ private static final String _scope_err = "No object %s in scope";
+ private static final String _too_many_args =
+ "Too many arguments to %s: %d/%d recieved";
+ private static final String _type_scope_err = "No type %s in scope";
+ private static final String _type_mismatch =
+ "Function '%s' expected arguments %s; got %s";
+
+ public boolean show_env;
+ public boolean show_closure;
+ public boolean dprint_enable;
+ public boolean dprint_ident;
+ public boolean dynamic;
+
+ protected int indent_level;
+ protected Function.EvalType eval;
+
+ public Interpreter() {
+ show_env = false;
+ show_closure = false;
+ dprint_enable = false;
+ dprint_ident = true;
+ dynamic = false;
+
+ indent_level = 0;
+ eval = Function.EvalType.FULL;
+
+ env_stack = new Stack<Environment>();
+ reset(); /*< Set up initial environment and types */
+ }
+ public void reset() {
+ env_stack.clear();
+ pushEnv(new Environment());
+ }
+
+ public CronoType visit(Cons c) {
+ if(eval == Function.EvalType.NONE) {
+ return c;
+ }
+
+ Iterator<CronoType> iter = c.iterator();
+ if(!(iter.hasNext())) {
+ return c; /*< C is an empty list (may be Nil or T) */
+ }
+
+ CronoType value = iter.next().accept(this);
+ if(value instanceof Function) {
+ Function fun = ((Function)value);
+
+ Function.EvalType reserve = eval;
+ /* Set the eval type to the current function's type; this keeps
+ * type errors in builtins from happening, ex:
+ * (+ arg1 arg2) under partial evaluation would fail since +
+ * expects two numbers.
+ */
+ eval = fun.eval;
+ if(eval.level > reserve.level) {
+ eval = reserve;
+ }
+ List<CronoType> args = new ArrayList<CronoType>();
+ while(iter.hasNext()) {
+ args.add(iter.next().accept(this));
+ }
+ eval = reserve;
+
+ int arglen = args.size();
+ int nargs = fun.arity;
+ if(arglen < nargs) {
+ if(arglen == 0) {
+ /* Special case -- we don't have to do anything to the
+ * function to return it properly. */
+ return fun;
+ }
+
+ /* Curry it */
+ if(fun instanceof LambdaFunction) {
+ LambdaFunction lfun = ((LambdaFunction)fun);
+ Environment env = getEnv();
+ if(!dynamic) {
+ /* Use the lambda's stored environment */
+ env = lfun.environment;
+ }
+ /* We want to preserve the current environment */
+ env = new Environment(env);
+
+ /* Put known values into the new environment */
+ for(int i = 0; i < arglen; ++i) {
+ env.put(lfun.arglist[i], args.get(i));
+ }
+ /* Create new argument list and remove remaining args from
+ * the new environment */
+ List<Symbol> largs = new ArrayList<Symbol>();
+ for(int i = arglen; i < lfun.arglist.length; ++i) {
+ largs.add(lfun.arglist[i]);
+ env.remove(lfun.arglist[i]);
+ }
+
+ /* Evaluate the body as much as possible */
+ reserve = eval;
+ eval = Function.EvalType.PARTIAL;
+ pushEnv(env);
+ CronoType[] lbody = new CronoType[lfun.body.length];
+ for(int i = 0; i < lfun.body.length; ++i) {
+ lbody[i] = lfun.body[i].accept(this);
+ }
+ popEnv();
+ eval = reserve;
+
+ /* Return the new, partially evaluated lambda */
+ Symbol[] arglist = new Symbol[largs.size()];
+ return new LambdaFunction(largs.toArray(arglist),
+ lbody, lfun.environment);
+ }
+ /* Builtin partial evaluation */
+
+ List<CronoType> body = new LinkedList<CronoType>();
+ body.add(fun);
+
+ body.addAll(args); /*< Dump args in order into the new cons */
+ CronoType[] barr = new CronoType[body.size()];
+ barr = body.toArray(barr);
+
+ /* Add symbols for missing args */
+ List<Symbol> arglist = new ArrayList<Symbol>();
+ Symbol sym;
+ for(int i = arglen, n = 0; i < nargs; ++i, ++n) {
+ sym = new Symbol(String.format("_i?%d!_", n));
+ body.add(sym);
+ arglist.add(sym);
+ }
+
+ /* Create a new lambda */
+ Symbol[] narglist = new Symbol[arglist.size()];
+ return new LambdaFunction(arglist.toArray(narglist), barr,
+ getEnv());
+ }
+ if(arglen > nargs && !fun.variadic) {
+ throw new RuntimeException(String.format(_too_many_args, fun,
+ arglen, nargs));
+ }
+
+ /* Full evaluation */
+ if(fun instanceof LambdaFunction && dynamic) {
+ /* We have to trick the lambda function if we want dynamic
+ * scoping. I hate making so many objects left and right, but
+ * this is the easiest way to do what I want here. */
+ LambdaFunction lfun = ((LambdaFunction)fun);
+ lfun = new LambdaFunction(lfun.arglist, lfun.body, getEnv());
+
+ CronoType[] argarray = new CronoType[args.size()];
+ return lfun.run(this, args.toArray(argarray));
+ }
+ if(eval == Function.EvalType.FULL) {
+ CronoType[] argarray = new CronoType[args.size()];
+ argarray = args.toArray(argarray);
+ TypeId[] types = new TypeId[args.size()];
+ for(int i = 0; i < types.length; ++i) {
+ types[i] = argarray[i].typeId();
+ }
+ for(int i = 0; i < fun.args.length; ++i) {
+ if(!(fun.args[i].isType(argarray[i]))) {
+ String argstr = Arrays.toString(types);
+ String expected = Arrays.toString(fun.args);
+ throw new InterpreterException(_type_mismatch, fun,
+ expected, argstr);
+ }
+ }
+ return ((Function)value).run(this, args.toArray(argarray));
+ }else {
+ args.add(0, value);
+ return Cons.fromList(args);
+ }
+ }
+
+ /* The initial value is not a function */
+ throw new InterpreterException("Invalid Function Application: %s is not a function in %s", value, c);
+ /*
+ List<CronoType> list = new LinkedList<CronoType>();
+ list.add(value);
+ while(iter.hasNext()) {
+ list.add(iter.next().accept(this));
+ }
+ return Cons.fromList(list);
+ */
+ }
+
+ public CronoType visit(Atom a) {
+ if(eval == Function.EvalType.NONE) {
+ return a;
+ }
+
+ CronoType t = a;
+ if(t instanceof Symbol) {
+ t = getEnv().get((Symbol)a);
+ if(t == null) {
+ if(eval == Function.EvalType.FULL) {
+ throw new RuntimeException(String.format(_scope_err,
+ a.toString()));
+ }
+ t = a;
+ }
+ }
+ /* Not else-if, so that we perform a double-resolution on a symbol that
+ * represents a TypeId */
+ if(t instanceof CronoTypeId) {
+ CronoType res = t; /*< Save symbol resolution in new CronoType */
+ t = getEnv().getType((CronoTypeId)t);
+ if(t == null) {
+ if(eval == Function.EvalType.FULL) {
+ throw new InterpreterException(_type_scope_err, a);
+ }
+ t = res; /*< Revert to symbol resolution */
+ }
+ }
+ return t;
+ }
+
+ public CronoType visit(Quote q) {
+ return q.node;
+ }
+}
View
19 crono/src/crono/Parser.jj
@@ -19,6 +19,7 @@ import crono.type.CronoInteger;
import crono.type.CronoString;
import crono.type.CronoType;
import crono.type.CronoTypeId;
+import crono.type.CronoVector;
import crono.type.Nil;
import crono.type.Quote;
import crono.type.Symbol;
@@ -52,12 +53,14 @@ TOKEN:
{
< LPAR : "(" >
| < RPAR : ")" >
+ | < RBRACKET : "]" >
+ | < LBRACKET : "[" >
| < INTEGER : ("-")? (["0"-"9"])+ >
| < FLOAT : ("-")? (["0"-"9"])* "." (["0"-"9"])+ ("f")? >
| < CHAR : "'" ([" "-"~"] | ("\\" ~["\n", "\r", "\t"])) "'" >
| < STRING : "\"" ("\\" ~["\n"] | ~["\"", "\n"])* "\"" >
| < TYPEID : ":" (["a"-"z","A"-"Z"] (["a"-"z","A"-"Z","-"])?)+ >
- | < SYMBOL : ["!"-"&", "*"-"/", ";"-"~"] (["!"-"'", "*"-"~"])* >
+ | < SYMBOL : ["!"-"&", "*"-"/", ";"-"Z", "\\", "^"-"~"] (["!"-"'", "*"-"/", ";"-"Z", "\\", "^"-"~"])* >
| < QUOTE : "'" >
}
@@ -70,6 +73,8 @@ Atom atom():
{
Token n;
Atom a;
+ CronoType node;
+ ArrayList<CronoType> types = new ArrayList<CronoType>();
}
{
n = <INTEGER> {
@@ -90,6 +95,18 @@ Atom atom():
}
return new CronoCharacter(n.image);
}
+ | <LBRACKET>
+ (
+ node = node() {
+ types.add(node);
+ }
+ )* <RBRACKET> {
+ if(types.size() > 0) {
+ return new CronoVector(types.toArray(new CronoType[types.size()]));
+ }else {
+ return new CronoVector(1);
+ }
+ }
| n = <TYPEID> {
if(debug) {
System.out.println("Parser: Saw <TYPEID>");
View
9 crono/src/crono/type/CronoArray.java
@@ -9,10 +9,11 @@ public CronoArray(TypeId accept) {
this.accept = accept;
}
- public abstract int rank();
- public abstract int dim(int n);
- public abstract CronoType get(int[] n);
- public abstract CronoType put(int[] n, CronoType item);
+ public abstract int size();
+ public abstract CronoType get(int n);
+ public abstract CronoType put(int n, CronoType item);
+ public abstract CronoType append(CronoType item);
+ public abstract CronoType concat(CronoArray array);
public TypeId accept() {
return accept;
View
47 crono/src/crono/type/CronoString.java
@@ -49,45 +49,34 @@ public CronoString(int size) {
this.size = size;
}
- public int rank() {
- return 1;
+ public int size() {
+ return data.length();
}
- public int dim(int n) {
- if(n != 1) {
- throw new InterpreterException(_rank_mismatch, n, 1);
- }
- return size;
- }
-
- private int offset(int[] n) {
- if(n.length > 1) {
- throw new InterpreterException(_rank_mismatch, n.length, 1);
- }
- if(n[0] >= size) {
- throw new InterpreterException(_index_oob, n[0], size);
- }
- return n[0];
+ public CronoType get(int n) {
+ return new CronoCharacter(data.charAt(n));
}
- public CronoType get(int[] n) {
- return new CronoCharacter(data.charAt(offset(n)));
+ public CronoType put(int n, CronoType item) {
+ data.setCharAt(n, ((CronoCharacter)item).ch);
+ return item;
}
- public CronoType put(int[] n, CronoType item) {
- data.setCharAt(offset(n), ((CronoCharacter)item).ch);
+ public CronoType append(CronoType item) {
+ if(!(item instanceof CronoCharacter)) {
+ throw new InterpreterException("Bad type: string expects char");
+ }
+ data.append(((CronoCharacter)item).ch);
return item;
}
-
- public String image() {
- return data.toString();
+ public CronoType concat(CronoArray array) {
+ return Nil.NIL;
}
public TypeId typeId() {
return CronoString.TYPEID;
}
public String toString() {
- StringBuilder builder = new StringBuilder();
- builder.append("\"");
- builder.append(data);
- builder.append("\"");
- return builder.toString();
+ return data.toString();
+ }
+ public String repr() {
+ return "\"" + data.toString() + "\"";
}
}
View
155 crono/src/crono/type/CronoStruct.java
@@ -1,6 +1,8 @@
package crono.type;
import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
import java.util.Map;
import java.util.List;
@@ -25,85 +27,154 @@
"Field %s expects %s, got %s";
private static final TypeId[] _args = {Symbol.TYPEID, CronoType.TYPEID};
- public class Field {
- public final Symbol sym;
- public final TypeId type;
- private CronoType data;
+ public static class Field {
+ public final Symbol sym;
+ public final TypeId type;
+ private CronoType data;
- public Field(Symbol sym, TypeId type, CronoType data) {
- this.sym = sym;
- this.type = type;
- this.data = data;
- }
- public CronoType put(CronoType data) {
- if(!(type.isType(data))) {
- throw new InterpreterException(_field_type_mismatch, sym,
- type, data.typeId());
+ public Field(Symbol sym, TypeId type, CronoType data) {
+ this.sym = sym;
+ this.type = type;
+ this.data = data;
+ }
+ public CronoType put(CronoType data) {
+ if(!(type.isType(data))) {
+ throw new InterpreterException(_field_type_mismatch, sym,
+ type, data.typeId());
+ }
+ this.data = data;
+ return data;
+ }
+ public CronoType get() {
+ return data;
}
- this.data = data;
- return data;
}
- public CronoType get() {
- return data;
+
+ private static final String _malformed_field =
+ "%s: malformed field default %s; expected (:symbol <:type> <:any>)";
+ public static Map<String, Field> BuildFieldMap(String name, Cons list) {
+ Map<String, Field> fields = new HashMap<String, Field>();
+ Iterator<CronoType> iter;
+ String str;
+ Symbol sym;
+ CronoType element, data;
+ TypeId accept;
+ boolean el2isType;
+ for(CronoType ct: list) {
+ if(!(ct instanceof Cons)) {
+ throw new InterpreterException(_malformed_field, name, ct);
+ }
+
+ accept = CronoType.TYPEID;
+ data = Nil.NIL;
+ iter = ((Cons)ct).iterator();
+ str = null;
+ sym = null;
+ el2isType = false;
+ if(iter.hasNext()) {
+ element = iter.next();
+ if(!(element instanceof Symbol)) {
+ throw new InterpreterException(_malformed_field, name, ct);
+ }
+ sym = (Symbol)element;
+ str = sym.toString();
+ }
+ if(iter.hasNext()) {
+ element = iter.next();
+ if(element instanceof CronoTypeId) {
+ accept = ((CronoTypeId)element).type;
+ el2isType = true;
+ }else {
+ data = element;
+ }
+ }
+ if(iter.hasNext()) {
+ element = iter.next();
+ if(element instanceof CronoTypeId) {
+ if(el2isType) {
+ throw new InterpreterException(_malformed_field, name,
+ ct);
+ }
+ accept = ((CronoTypeId)element).type;
+ }else if(!el2isType) {
+ throw new InterpreterException(_malformed_field, name, ct);
+ }else {
+ data = element;
+ }
+ }
+ if(iter.hasNext()) {
+ throw new InterpreterException(_malformed_field, name, ct);
+ }
+ fields.put(str, new CronoStruct.Field(sym, accept, data));
}
+ return fields;
}
- public final String name;
+ public final String name;
public final CronoStruct parent;
- private Map<Symbol, Field> fields;
+ private Map<String, Field> fields;
private TypeId type;
- public CronoStruct(String name, Map<Symbol, Field> fields) {
- this(name, fields, null);
- }
- public CronoStruct(String name, Map<Symbol, Field> fields,
- CronoStruct parent)
+ public CronoStruct(String name, Map<String, Field> fields) {
+ this(name, fields, null);
+ }
+ public CronoStruct(String name, Map<String, Field> fields, CronoStruct p)
{
super(_args, CronoType.TYPEID, 1, true, Function.EvalType.NONE);
this.name = name;
- this.parent = parent;
- this.fields = new HashMap<Symbol, Field>();
- TypeId parid = TYPEID;
- if(parent != null) {
- /* Since all structs do this we only need to add the parent's
- * fields */
+ this.parent = p;
+ this.fields = new HashMap<String, Field>();
+ TypeId id = TYPEID;
+ if(p != null) {
fields.putAll(parent.fields);
- parid = parent.typeId();
+ id = p.type;
}
- fields.putAll(fields);
-
- this.type = new TypeId(":struct-"+name, CronoStruct.class, parid);
+ this.fields.putAll(fields);
+ this.type = new TypeId(":struct-"+name, CronoStruct.class, id);
+ }
+ protected CronoStruct(CronoStruct cs) {
+ super(_args, CronoType.TYPEID, 1, true, Function.EvalType.NONE);
+ this.name = cs.name;
+ this.parent = cs.parent;
+ this.fields = new HashMap<String, Field>();
+ this.fields.putAll(cs.fields);
+ this.type = cs.type;
}
- public CronoType run(Visitor v, List<CronoType> args) {
+ public CronoType run(Visitor v, CronoType[] args) {
/* CronoStruct doesn't contain an AST, so we can ignore the visitor */
+ Field field;
switch(args.size()) {
case 1:
/* Being used as a get */
- CronoType val = fields.get((Symbol)args.get(0)).get();
- if(val == null) {
+ field = fields.get(args.get(0).toString());
+ if(field == null) {
throw new InterpreterException(_inv_field_name, name,
args.get(0).toString());
}
- return val;
+ return field.get();
case 2:
/* Being used as a set */
- Field field = fields.get((Symbol)args.get(0));
+ field = fields.get(args.get(0).toString());
if(field == null) {
throw new InterpreterException(_inv_field_name, name,
args.get(0).toString());
}
- return field.put(args.get(1));
+ return field.put(args.get(1).accept(v));
default:
throw new InterpreterException("Too many arguments to struct");
}
}
- public TypeId typeId() {
- return type;
+ public CronoStruct copy() {
+ return new CronoStruct(this);
}
+ public TypeId typeId() {
+ return type;
+ }
+
public String toString() {
return name;
}
View
3 crono/src/crono/type/CronoType.java
@@ -7,6 +7,9 @@
public abstract TypeId typeId();
public abstract String toString();
+ public String repr() {
+ return toString();
+ }
public abstract CronoType accept(Visitor v);
}
View
103 crono/src/crono/type/CronoVector.java
@@ -2,6 +2,8 @@
import crono.InterpreterException;
+import java.util.ArrayList;
+
public class CronoVector extends CronoArray {
public static final TypeId TYPEID = new TypeId(":vector",
CronoVector.class,
@@ -13,89 +15,78 @@
private static final String _inv_rank =
"Array Rank must be a positive, non-zero integer";
- protected CronoType[] data;
- protected int[] dimensions;
- protected int rank, size;
+ protected ArrayList<CronoType> data;
+ protected int size;
protected TypeId type;
- public CronoVector(int rank, int[] dimensions) {
- this(rank, dimensions, CronoType.TYPEID);
+ public CronoVector(int size) {
+ this(size, CronoType.TYPEID);
}
- public CronoVector(int rank, int[] dimensions, TypeId accept) {
+ public CronoVector(int size, TypeId accept) {
super(accept);
- if(rank <= 0) {
- throw new InterpreterException(_inv_rank);
- }
- this.rank = rank;
this.type = new NestedTypeId(":vector", CronoVector.class,
new TypeId[]{accept}, TYPEID);
- if(dimensions.length != rank) {
- throw new InterpreterException(_rank_dim_mismatch,
- dimensions.length, rank);
- }
-
- this.dimensions = dimensions;
- size = 1;
- for(int i = 0; i < dimensions.length; ++i) {
- size *= dimensions[i];
+ this.size = size;
+ this.data = new ArrayList<CronoType>(size);
+ for(int i = 0; i < size; ++i) {
+ this.data.add(i, Nil.NIL);
}
-
- this.data = new CronoType[size];
}
-
- public CronoVector(int rank, int[] dimensions, TypeId accept,
- CronoType[] data)
- {
- this(rank, dimensions, accept);
-
- if(data.length != size) {
- throw new InterpreterException(_data_size_mismatch, data.length,
- size);
- }
-
- for(int i = 0; i < size; ++i) {
- this.data[i] = data[i];
+ public CronoVector(CronoType[] data) {
+ this(data, CronoType.TYPEID);
+ }
+ public CronoVector(CronoType[] data, TypeId accept) {
+ super(accept);
+ this.type = new NestedTypeId(":vector", CronoVector.class,
+ new TypeId[]{accept}, TYPEID);
+ this.data = new ArrayList<CronoType>();
+ for(int i = 0; i < data.length; ++i) {
+ this.data.add(data[i]);
}
+ this.size = data.length;
}
- public int rank() {
- return rank;
+ public int size() {
+ return size;
}
- public int dim(int n) {
- if(n > dimensions.length) {
- throw new InterpreterException("rank mismatch");
+
+ public CronoType get(int n) {
+ if(n >= size || n < 0) {
+ throw new InterpreterException("Array index out of bounds");
}
- return dimensions[n];
+ return data.get(n);
}
- private int offset(int[] n) {
- int pos = n[n.length - 1];
- int step = dimensions[n.length - 1];
- for(int i = n.length - 2; i >= 0; --i) {
- if(n[i] >= dimensions[i]) {
- throw new InterpreterException("Vector index out of bounds");
- }
- pos += step * n[i];
- step *= dimensions[i];
+ public CronoType put(int n, CronoType item) {
+ if(n >= size || n < 0) {
+ throw new InterpreterException("Array index out of bounds");
}
- return pos;
- }
- public CronoType get(int[] n) {
- return data[offset(n)];
+ data.set(n, item);
+ return item;
}
- public CronoType put(int[] n, CronoType item) {
- data[offset(n)] = item;
+ public CronoType append(CronoType item) {
+ data.add(item);
+ size++;
return item;
}
+ public CronoType concat(CronoArray array) {
+ return Nil.NIL;
+ }
public TypeId typeId() {
return type;
}
public String toString() {
StringBuilder builder = new StringBuilder();
- builder.append("Not implemented =D");
+ builder.append("[");
+ for(int i = 0; i < size - 1; ++i) {
+ builder.append(data.get(i).repr());
+ builder.append(", ");
+ }
+ builder.append(data.get(size - 1).repr());
+ builder.append("]");
return builder.toString();
}
}
View
15 crono/src/crono/type/LambdaFunction.java
@@ -1,5 +1,6 @@
package crono.type;
+import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
@@ -8,11 +9,12 @@
public class LambdaFunction extends Function {
public final Symbol[] arglist;
- public final CronoType body; /*< AST head node */
+ public final CronoType[] body; /*< AST head node */
public final Environment environment; /*< for scoping */
- public LambdaFunction(Symbol[] args, CronoType body, Environment env) {
- /* We might want this to specify argument type later
+ public LambdaFunction(Symbol[] args, CronoType[] body, Environment env) {
+ /*
+ * We might want this to specify argument type later
*/
super(new TypeId[args.length], CronoType.TYPEID, args.length);
@@ -48,7 +50,10 @@ public CronoType run(Visitor v, List<CronoType> args) {
}
v.pushEnv(env);
- CronoType ret = body.accept(v);
+ CronoType ret = null;
+ for(int i = 0; i < body.length; ++i) {
+ ret = body[i].accept(v);
+ }
v.popEnv();
return ret;
@@ -65,6 +70,8 @@ public String toString() {
builder.append(arglist[arglist.length - 1]);
}
builder.append(")");
+ String bodystr =
+ (body.length > 1) ? Arrays.toString(body) : body[0].toString();
return String.format("(Lambda %s %s)", builder.toString(), body);
}

0 comments on commit e228f08

Please sign in to comment.
Something went wrong with that request. Please try again.