From 39a28bd78071aa75a24b052c9f6b6195f688c899 Mon Sep 17 00:00:00 2001 From: Sameer Rahmani Date: Wed, 1 Jan 2020 16:28:14 +0000 Subject: [PATCH] Conj function has been added --- src/main/java/serene/simple/ListNode.java | 31 ++++++++--- src/main/java/serene/simple/Main.java | 17 +++--- src/main/java/serene/simple/Reader.java | 5 +- src/main/java/serene/simple/RootScope.java | 2 + .../java/serene/simple/builtin/ConjFn.java | 53 +++++++++++++++++++ 5 files changed, 90 insertions(+), 18 deletions(-) create mode 100644 src/main/java/serene/simple/builtin/ConjFn.java diff --git a/src/main/java/serene/simple/ListNode.java b/src/main/java/serene/simple/ListNode.java index 08adc1b..c81e568 100644 --- a/src/main/java/serene/simple/ListNode.java +++ b/src/main/java/serene/simple/ListNode.java @@ -31,7 +31,7 @@ import static java.util.Arrays.asList; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -public class ListNode extends Node implements Iterable { +public class ListNode extends Node implements Iterable { public static final ListNode EMPTY = new ListNode<>(); public final T first; @@ -51,11 +51,11 @@ public class ListNode extends Node implements Iterable { } @SafeVarargs - public static ListNode list(T... objs) { + public static ListNode list(T... objs) { return list(asList(objs)); } - public static ListNode list(List objs) { + public static ListNode list(List objs) { ListNode l = (ListNode) EMPTY; for (int i = objs.size() - 1; i >= 0; i--) { l = l.cons(objs.get(i)); @@ -73,7 +73,12 @@ public class ListNode extends Node implements Iterable { List args = new ArrayList(); for (T node : this.rest()) { - args.add(node.eval(scope)); + if (node instanceof Node) { + args.add(((Node) node).eval(scope)); + } + else { + args.add(node); + } } if (firstElement.name.startsWith(".")) { @@ -102,7 +107,7 @@ public class ListNode extends Node implements Iterable { throws SereneException { String mName = firstElement.name.substring(1, firstElement.name.length()); - Object target = this.rest().first().eval(scope); + Object target = this.evalNode(scope, this.rest().first()); if (mName.startsWith("-")) { return this.evalInteropProperty( @@ -179,9 +184,10 @@ public class ListNode extends Node implements Iterable { @Override public T next() { - if (this.l == EMPTY) { + if (this.l == EMPTY || this.l.length == 0) { return null; } + T first = this.l.first; this.l = this.l.rest; return first; @@ -200,8 +206,13 @@ public class ListNode extends Node implements Iterable { } String output = "(" + this.first(); - for(Node x : this.rest()) { - output = output + " " + x.toString(); + for(T x : this.rest()) { + if (x != null) { + output = output + " " + x.toString(); + } + else { + output = output + " nil"; + } } return output + ")"; @@ -214,4 +225,8 @@ public class ListNode extends Node implements Iterable { return target.getClass(); } + + private Object evalNode(IScope s, T node) { + return node instanceof Node ? ((Node) node).eval(s) : node; + } } diff --git a/src/main/java/serene/simple/Main.java b/src/main/java/serene/simple/Main.java index ec9d388..4aa3d8c 100644 --- a/src/main/java/serene/simple/Main.java +++ b/src/main/java/serene/simple/Main.java @@ -37,6 +37,8 @@ import java.io.FileInputStream; * * Primitive functions in Serene. I implemented lots of primitive functions * in java rather than Serene itself mostly because of two reasons. Lack of * macros and namespaces. + * * Decent [functional] data structures. The only data structure I implemented + * is list. * * Quality code. The general quality of this implementation is not great, I * sacrificed quality for time. */ @@ -88,15 +90,14 @@ public class Main { result = n.eval(rootScope); } - if (result != ListNode.EMPTY) { - System.out.print(";; "); - if (result == null) { - System.out.println("nil"); - } - else { - System.out.println(result.toString()); - } + System.out.print(";; "); + if (result == null) { + System.out.println("nil"); } + else { + System.out.println(result.toString()); + } + } catch(Exception e) { System.out.println("Error: "); diff --git a/src/main/java/serene/simple/Reader.java b/src/main/java/serene/simple/Reader.java index 1bee0f2..d1bdca4 100644 --- a/src/main/java/serene/simple/Reader.java +++ b/src/main/java/serene/simple/Reader.java @@ -107,8 +107,9 @@ public class Reader { while (true) { int ch = inputStream.read(); - - if(isWhiteSpace(ch) || isClosingChar(ch) || ch == -1) { + // 65535 comes from the fact that unsigned -1 is 65535 so unreading -1 + // puts 65535 in the buffer of pushbackreader + if(isWhiteSpace(ch) || isClosingChar(ch) || ch == -1 || ch == 65535) { inputStream.unread(ch); break; }; diff --git a/src/main/java/serene/simple/RootScope.java b/src/main/java/serene/simple/RootScope.java index 5bee134..94565b3 100644 --- a/src/main/java/serene/simple/RootScope.java +++ b/src/main/java/serene/simple/RootScope.java @@ -43,6 +43,8 @@ public class RootScope extends AScope { put("and", new AndFn()); put("or", new OrFn()); put("not", new NotFn()); + put("conj", new ConjFn()); + //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 new file mode 100644 index 0000000..4742077 --- /dev/null +++ b/src/main/java/serene/simple/builtin/ConjFn.java @@ -0,0 +1,53 @@ +/** + * Serene (simple) - A PoC lisp to collect data on Serenes concepts + * Copyright (C) 2019-2020 Sameer Rahmani + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +package serene.simple.builtin; + +import java.util.List; + +import serene.simple.IScope; +import serene.simple.ListNode; +import serene.simple.SereneException; + + +public class ConjFn extends AFn { + public String fnName() { + return "conj"; + }; + + public Object eval(IScope scope) throws SereneException{ + List args = this.arguments(); + + if (args.size() == 0) { + return ListNode.EMPTY; + } + + if (args.size() == 1) { + return args.get(0); + } + + ListNode list = (ListNode) args.get(0); + + for (Object x : args.subList(1, args.size())) { + list = new ListNode(x, list); + } + + return list; + } +}