diff --git a/Makefile b/Makefile index b5787f9..692ff49 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,8 @@ repl: gradle compileJava && rlwrap java -cp build/classes/java/main/ serene.simple.Main + +run: + gradle compileJava && java -cp build/classes/java/main/ serene.simple.Main ${PWD}/test.srns + docs: npx docco src/**/*.java diff --git a/src/main/java/serene/simple/AScope.java b/src/main/java/serene/simple/AScope.java index a9392eb..1f23916 100644 --- a/src/main/java/serene/simple/AScope.java +++ b/src/main/java/serene/simple/AScope.java @@ -1,3 +1,4 @@ + /** * Serene (simple) - A PoC lisp to collect data on Serenes concepts * Copyright (C) 2019-2020 Sameer Rahmani @@ -47,7 +48,7 @@ public abstract class AScope implements IScope { public Object lookupSymbol(String symbolName) { Object value = this.getLocalSymbol(symbolName); - if (value != null) { + if (!(value instanceof Null)) { return value; } else if (this.parent() != null) { @@ -68,6 +69,8 @@ public abstract class AScope implements IScope { return this.symbols().get(symbolName); } - return null; + return new Null(); } + + private class Null {} } diff --git a/src/main/java/serene/simple/CondSpecialForm.java b/src/main/java/serene/simple/CondSpecialForm.java index 38bf319..ad77411 100644 --- a/src/main/java/serene/simple/CondSpecialForm.java +++ b/src/main/java/serene/simple/CondSpecialForm.java @@ -30,7 +30,7 @@ public class CondSpecialForm extends SpecialForm { throw new SereneException("Let bindings should be a list of pairs."); } - this.conditions = (ListNode) listNode.rest().first(); + this.conditions = (ListNode) listNode.rest(); } @Override diff --git a/src/main/java/serene/simple/FnSpecialForm.java b/src/main/java/serene/simple/FnSpecialForm.java index 7cc3a17..8a681e3 100644 --- a/src/main/java/serene/simple/FnSpecialForm.java +++ b/src/main/java/serene/simple/FnSpecialForm.java @@ -38,9 +38,11 @@ public class FnSpecialForm extends SpecialForm { Scope scope = new Scope(parentScope); if (args.length != formalParams.length) { - throw new RuntimeException(String.format("Wrong number of arguments. Expected: %s, Got: %s.", - formalParams.length, - args.length)); + throw new RuntimeException( + String.format("Wrong number of arguments. Expected: %s, Got: %s. ARGS: %s", + formalParams.length, + args.length, + args.toString())); } // Map parameter values to formal parameter names int i = 0; diff --git a/src/main/java/serene/simple/Main.java b/src/main/java/serene/simple/Main.java index 4aa3d8c..814256b 100644 --- a/src/main/java/serene/simple/Main.java +++ b/src/main/java/serene/simple/Main.java @@ -109,8 +109,8 @@ public class Main { private static void runSerene(String filePath) throws IOException { IScope rootScope = new RootScope(); - - ListNode nodes = Reader.read(new FileInputStream(filePath)); + FileInputStream input = new FileInputStream(filePath); + ListNode nodes = Reader.read(input); for (Node n : nodes) { n.eval(rootScope); diff --git a/src/main/java/serene/simple/Reader.java b/src/main/java/serene/simple/Reader.java index d1bdca4..bbe8979 100644 --- a/src/main/java/serene/simple/Reader.java +++ b/src/main/java/serene/simple/Reader.java @@ -67,7 +67,15 @@ public class Reader { char c = (char) inputStream.read(); while ((byte) c != -1) { if (c == ';') { - break; + while(true) { + char commentChar = (char) inputStream.read(); + + if (commentChar == '\n') { + break; + } + } + c = (char) inputStream.read(); + continue; } inputStream.unread(c); diff --git a/src/main/java/serene/simple/RootScope.java b/src/main/java/serene/simple/RootScope.java index a930354..cd48352 100644 --- a/src/main/java/serene/simple/RootScope.java +++ b/src/main/java/serene/simple/RootScope.java @@ -44,11 +44,14 @@ public class RootScope extends AScope { put("or", new OrFn()); put("not", new NotFn()); put("conj", new ConjFn()); + put("cons", new ConjFn()); + // put("size", new SizeFn()); + // put("reverse", new SizeFn()); put("list", new ListFn()); put("first", new FirstFn()); put("rest", new RestFn()); - // put("cond", new CondFn()); - //put("reduce", new ReduceFn()); + // put("doc", new DocFn()); + // put("reduce", new ReduceFn()); put("System", System.class); put("Boolean", Boolean.class); put("String", String.class); diff --git a/src/main/java/serene/simple/builtin/ConjFn.java b/src/main/java/serene/simple/builtin/ConjFn.java index 4742077..bc19c24 100644 --- a/src/main/java/serene/simple/builtin/ConjFn.java +++ b/src/main/java/serene/simple/builtin/ConjFn.java @@ -45,7 +45,7 @@ public class ConjFn extends AFn { ListNode list = (ListNode) args.get(0); for (Object x : args.subList(1, args.size())) { - list = new ListNode(x, list); + list = list.cons(x); } return list; diff --git a/src/main/java/serene/simple/builtin/PrintlnFn.java b/src/main/java/serene/simple/builtin/PrintlnFn.java index a1cdcf8..a6239ee 100644 --- a/src/main/java/serene/simple/builtin/PrintlnFn.java +++ b/src/main/java/serene/simple/builtin/PrintlnFn.java @@ -19,6 +19,8 @@ */ package serene.simple.builtin; +import java.util.List; + import serene.simple.IScope; @@ -28,12 +30,17 @@ public class PrintlnFn extends AFn { }; public Object eval(IScope scope) { - String output = ""; + List args = this.arguments(); - for(Object x: this.arguments()) { - output = String.format( - "%s %s", output, - (String) x.toString()); + if (args.size() == 0) { + System.out.println(""); + return null; + } + + String output = args.get(0).toString(); + + for(Object x: args.subList(1, args.size())) { + output = output + " " + x.toString(); } System.out.println(output);