Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Comparing changes

Choose two branches to see what's changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
base fork: mwatts15/Crono
...
head fork: mwatts15/Crono
Checking mergeability… Don't worry, you can still create the pull request.
  • 9 commits
  • 10 files changed
  • 0 commit comments
  • 2 contributors
Commits on Nov 20, 2012
Troy Varney Completed CronoStruct implementation and functions. CronoStructs defi…
…nitions can

now be created with the (defstruct name (fields)) function, substructs with the
(substruct name parent (fields)) function, and instances of them by the
(struct name) function. CronoStructs currently do not support changing fields
when creating new instances, which is something to do later.
9250e34
Troy Varney Fixed issue with LambdaFunctions not taking all of their arguments. G…
…ot rid of

ArrayIndexOutOfBounds exception. LambdaFunctions now properly evaluate all of
their body statements.
91f1a85
Troy Varney Fixed issue with the Interpreter throwing an ArrayIndexOutOfBoundsExc…
…eption

when evaluating variadic functions.
5dafd27
Troy Varney Added 'list' Variadic function for creating lists. 0d41230
Troy Varney Removed interpreter returning a Cons if the first element is not a fu…
…nction.

Statements which are not valid function applications such as ('a' 10) will now
cause the interpreter to throw an exception.
151d010
Commits on Nov 26, 2012
Troy Varney Added repr() method to CronoType, added array functions, updated Arra…
…y interface

and a few other things.
5288f83
Commits on Nov 27, 2012
Troy Varney Added parser support for vectors. abcc9b0
Mark Watts 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
e228f08
Mark Watts Fixed some mis-merges so we actually compile c47bdef
View
181 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,55 @@ 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 Cons.fromList(args);
+ }
+ 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 = (CronoArray) 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";
+ }
+ }),
EQ(new Function(new TypeId[]{CronoType.TYPEID, CronoType.TYPEID},
Cons.TYPEID, 2)
{
@@ -133,7 +183,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 +214,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 +274,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 +293,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 +360,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 +377,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 +389,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 +398,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 +466,6 @@ public String toString() {
//throw new InterpreterException("EVAL: parse error\n%s",
//pe.getMessage());
//}
- //}
- //public String toString() {
- //return "eval";
- //}
//}),
;
View
127 crono/src/crono/CronoSpecial.java
@@ -1,5 +1,7 @@
package crono;
import java.util.List;
+import java.util.LinkedList;
+import java.util.ListIterator;
import crono.type.Function.EvalType;
import crono.type.*;
/* These are like functions but have evaluation
@@ -11,16 +13,41 @@
LAMBDA(new Special(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.get(0) instanceof Cons)) {
+ throw new InterpreterException(_bad_type,
+ args.get(0).typeId(),
+ args.get(1).typeId());
+ }
List<CronoType> list = ((Cons)args.remove(0)).toList();
+ for(CronoType item : list) {
+ if(!(item instanceof Symbol)) {
+ throw new InterpreterException(_bad_arg,item.typeId());
+ }
+ }
+
Symbol[] arglist = new Symbol[list.size()];
- return new LambdaFunction(list.toArray(arglist), args.remove(0),
- v.getEnv());
+
+ CronoType[] body;
+ List<CronoType> blist = new LinkedList<CronoType>();
+ ListIterator<CronoType> it = args.listIterator();
+ while (it.hasNext())
+ {
+ blist.add(it.next());
+ }
+ body = new CronoType[blist.size()];
+ body = blist.toArray(body);
+ return new LambdaFunction(list.toArray(arglist), body,
+ v.getEnv());
+ }
+ public String toString() {
+ return "\\";
}
- public String toString() {
- return "\\";
- }
});
//DEFINE(new Function(new TypeId[]{Symbol.TYPEID, CronoType.TYPEID},
//CronoType.TYPEID, 2, EvalType.NONE)
@@ -73,62 +100,64 @@ public String toString() {
//LET(new Function(new TypeId[]{Cons.TYPEID, CronoType.TYPEID},
//CronoType.TYPEID, 2, true, EvalType.NONE)
//{
- //private static final String _subst_list_type =
- //"LET: substitution list must be :cons, got %s";
- //private static final String _subst_not_cons =
- //"LET: expected :cons in substitution list, got %s";
- //private static final String _subst_not_sym =
- //"LET: argument names numst be :symbol, got %s";
+ //private static final String _subst_list_type =
+ //"LET: substitution list must be :cons, got %s";
+ //private static final String _subst_not_cons =
+ //"LET: expected :cons in substitution list, got %s";
+ //private static final String _subst_not_sym =
+ //"LET: argument names numst be :symbol, got %s";
- //public CronoType run(Visitor v, CronoType[] args) {
- //if(!(args[0] instanceof Cons)) {
- //throw new InterpreterException(_subst_list_type,
- //args[0].typeId());
- //}
+ //public CronoType run(Visitor v, List<CronoType> args) {
+ //if(!(args[0] instanceof Cons)) {
+ //throw new InterpreterException(_subst_list_type,
+ //args[0].typeId());
+ //}
- //List<Symbol> symlist = new LinkedList<Symbol>();
- //List<CronoType> arglist = new LinkedList<CronoType>();
- //for(CronoType ct : ((Cons)args[0])) {
- //if(!(ct instanceof Cons)) {
- //throw new InterpreterException(_subst_not_cons,
- //ct.typeId());
- //}
+ //List<Symbol> symlist = new LinkedList<Symbol>();
+ //List<CronoType> arglist = new LinkedList<CronoType>();
+ //for(CronoType ct : ((Cons)args[0])) {
+ //if(!(ct instanceof Cons)) {
+ //throw new InterpreterException(_subst_not_cons,
+ //ct.typeId());
+ //}
- //CronoType car = ((Cons)ct).car();
- //CronoType cdr = ((Cons)ct).cdr();
- //if(!(car instanceof Symbol)) {
- //throw new InterpreterException(_subst_not_sym,
- //car.typeId());
- //}
+ //CronoType car = ((Cons)ct).car();
+ //CronoType cdr = ((Cons)ct).cdr();
+ //if(!(car instanceof Symbol)) {
+ //throw new InterpreterException(_subst_not_sym,
+ //car.typeId());
+ //}
- //cdr = cdr.accept(v);
- //symlist.add((Symbol)car);
- //arglist.add(cdr);
- //}
+ //cdr = cdr.accept(v);
+ //symlist.add((Symbol)car);
+ //arglist.add(cdr);
+ //}
- //Symbol[] lsyms = new Symbol[symlist.size()];
- //lsyms = symlist.toArray(lsyms);
+ //Symbol[] lsyms = new Symbol[symlist.size()];
+ //lsyms = symlist.toArray(lsyms);
- //List<CronoType> bodylist = new LinkedList<CronoType>();
- //for(int i = 1; i < args.length; ++i) {
- //bodylist.add(args[i]);
- //}
- //CronoType body = Cons.fromList(bodylist);
- //CronoType[] largs = new CronoType[arglist.size()];
- //largs = arglist.toArray(largs);
+ //List<CronoType> bodylist = new LinkedList<CronoType>();
+ //for(int i = 1; i < args.length; ++i) {
+ //bodylist.add(args[i]);
+ //}
+ //CronoType[] body = new CronoType[bodylist.size()];
+ //body = bodylist.toArray(body);
- //LambdaFunction lambda = new LambdaFunction(lsyms,body,v.getEnv());
- //return lambda.run(v, largs); [>< -. - <]
- //}
- //public String toString() {
- //return "let";
- //}
+ //CronoType[] largs = new CronoType[arglist.size()];
+ //largs = arglist.toArray(largs);
+
+ //LambdaFunction lambda = new LambdaFunction(lsyms,body,v.getEnv());
+ //return lambda.run(v, largs); [>< -. - <]
+ //}
+ //public String toString() {
+ //return "let";
+ //}
//}),
//IF(new Function(new TypeId[]{CronoType.TYPEID, CronoType.TYPEID,
//CronoType.TYPEID},
//CronoType.TYPEID, 3, EvalType.NONE)
//{
- //public CronoType run(Visitor v, CronoType[] args) {
+ //public CronoType run(Visitor v, List<CronoType> args) {
//CronoType check = args[0].accept(v);
//if(check != Nil.NIL) {
//return args[1].accept(v);
View
390 crono/src/crono/Interpreter.java.noncomp
@@ -21,215 +21,221 @@ 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";
+ "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";
-
+ "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 */
+ 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());
+ 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 = lfun.body.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 */
-
- /* 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),
- Cons.fromList(body), 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 < argarray.length; ++i) {
- if(!(fun.args[i].isType(argarray[i]))) {
- String argstr = Arrays.toString(argarray);
- 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 */
- List<CronoType> list = new LinkedList<CronoType>();
- list.add(value);
- while(iter.hasNext()) {
- list.add(iter.next().accept(this));
- }
- return Cons.fromList(list);
+ 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;
+ 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;
+ return q.node;
}
- public CronoType defaultVisit(CronoType object) {return object;}
}
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
153 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) {
/* 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
149 crono/src/crono/type/CronoVector.java
@@ -2,100 +2,91 @@
import crono.InterpreterException;
+import java.util.ArrayList;
+
public class CronoVector extends CronoArray {
public static final TypeId TYPEID = new TypeId(":vector",
- CronoVector.class,
- CronoArray.TYPEID);
+ CronoVector.class,
+ CronoArray.TYPEID);
private static final String _rank_dim_mismatch =
- "Wrong number of dimensions to Array of rank %d: %d";
+ "Wrong number of dimensions to Array of rank %d: %d";
private static final String _data_size_mismatch =
- "Data size (%d) does not match Array size: %d";
+ "Data size (%d) does not match Array size: %d";
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;
+ "Array Rank must be a positive, non-zero integer";
+
+ 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 size, TypeId accept) {
+ super(accept);
+
+ this.type = new NestedTypeId(":vector", CronoVector.class,
+ new TypeId[]{accept}, TYPEID);
+
+ this.size = size;
+ this.data = new ArrayList<CronoType>(size);
+ for(int i = 0; i < size; ++i) {
+ this.data.add(i, Nil.NIL);
+ }
}
-
- public CronoVector(int rank, int[] dimensions, 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.data = new CronoType[size];
+ public CronoVector(CronoType[] data) {
+ this(data, CronoType.TYPEID);
}
-
- 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, 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");
- }
- return dimensions[n];
+
+ public CronoType get(int n) {
+ if(n >= size || n < 0) {
+ throw new InterpreterException("Array index out of bounds");
+ }
+ 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];
- }
- return pos;
+ public CronoType put(int n, CronoType item) {
+ if(n >= size || n < 0) {
+ throw new InterpreterException("Array index out of bounds");
+ }
+ data.set(n, item);
+ return item;
}
- public CronoType get(int[] n) {
- return data[offset(n)];
+ public CronoType append(CronoType item) {
+ data.add(item);
+ size++;
+ return item;
}
- public CronoType put(int[] n, CronoType item) {
- data[offset(n)] = item;
- return item;
+ public CronoType concat(CronoArray array) {
+ return Nil.NIL;
}
-
+
public TypeId typeId() {
- return type;
+ return type;
}
public String toString() {
- StringBuilder builder = new StringBuilder();
- builder.append("Not implemented =D");
- return builder.toString();
+ StringBuilder builder = new StringBuilder();
+ 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);
}

No commit comments for this range

Something went wrong with that request. Please try again.