From bb2354e8920f5e555fafe4d7162f44b11fa213d9 Mon Sep 17 00:00:00 2001 From: Sameer Rahmani Date: Wed, 1 Jan 2020 17:22:11 +0000 Subject: [PATCH] Let special form has been added --- .../java/serene/simple/LetSpecialForm.java | 58 +++++++++++++++++++ src/main/java/serene/simple/RootScope.java | 1 - src/main/java/serene/simple/SpecialForm.java | 3 + src/main/java/serene/simple/SymbolNode.java | 50 ++++++++-------- 4 files changed, 86 insertions(+), 26 deletions(-) create mode 100644 src/main/java/serene/simple/LetSpecialForm.java diff --git a/src/main/java/serene/simple/LetSpecialForm.java b/src/main/java/serene/simple/LetSpecialForm.java new file mode 100644 index 0000000..56b4f7c --- /dev/null +++ b/src/main/java/serene/simple/LetSpecialForm.java @@ -0,0 +1,58 @@ +/** + * 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; + +public class LetSpecialForm extends SpecialForm { + private ListNode bindings; + private ListNode body; + + public LetSpecialForm(ListNode listNode) { + super(listNode); + + if (!(listNode.rest().first() instanceof ListNode)) { + throw new SereneException("Let bindings should be a list of pairs."); + } + + this.bindings = (ListNode) listNode.rest().first(); + this.body = listNode.rest().rest(); + } + + @Override + public Object eval(IScope scope) { + Scope letScope = new Scope(scope); + + for (Object x : this.bindings) { + if (!(x instanceof ListNode)) + throw new SereneException(String.format("Expect a pair instead of '%s'", x.toString())); + + letScope.insertSymbol( + ((ListNode) x).first().toString(), + ((ListNode) x).rest().first().eval(letScope)); + } + + Object result = ListNode.EMPTY; + + for(Node x: body) { + result = x.eval(letScope); + } + + return result; + } +} diff --git a/src/main/java/serene/simple/RootScope.java b/src/main/java/serene/simple/RootScope.java index d58cfd7..a930354 100644 --- a/src/main/java/serene/simple/RootScope.java +++ b/src/main/java/serene/simple/RootScope.java @@ -47,7 +47,6 @@ public class RootScope extends AScope { put("list", new ListFn()); put("first", new FirstFn()); put("rest", new RestFn()); - //put("let", new LetFn()); // put("cond", new CondFn()); //put("reduce", new ReduceFn()); put("System", System.class); diff --git a/src/main/java/serene/simple/SpecialForm.java b/src/main/java/serene/simple/SpecialForm.java index 75d2036..3bf3dcb 100644 --- a/src/main/java/serene/simple/SpecialForm.java +++ b/src/main/java/serene/simple/SpecialForm.java @@ -25,6 +25,7 @@ public class SpecialForm extends Node { private static final SymbolNode FN = new SymbolNode("fn"); private static final SymbolNode IF = new SymbolNode("if"); private static final SymbolNode QUOTE = new SymbolNode("quote"); + private static final SymbolNode LET = new SymbolNode("let"); public ListNode node; @@ -39,6 +40,8 @@ public class SpecialForm extends Node { return l; } else if (l.first().equals(DEF)) { return new DefSpecialForm(l); + } else if (l.first().equals(LET)){ + return new LetSpecialForm(l); } else if (l.first().equals(FN)) { return new FnSpecialForm(l); } else if (l.first().equals(IF)) { diff --git a/src/main/java/serene/simple/SymbolNode.java b/src/main/java/serene/simple/SymbolNode.java index 8854aeb..bce928f 100644 --- a/src/main/java/serene/simple/SymbolNode.java +++ b/src/main/java/serene/simple/SymbolNode.java @@ -20,33 +20,33 @@ package serene.simple; public class SymbolNode extends Node { - public String name; + public String name; - public SymbolNode(String name) { - this.name = name; + public SymbolNode(String name) { + this.name = name; + } + + @Override + public boolean equals(Node other) { + if (other instanceof SymbolNode) { + SymbolNode n = (SymbolNode) other; + + if (this.name.equals(n.name)) { + return true; + } + + return false; } + return super.equals(other); + } - @Override - public boolean equals(Node other) { - if (other instanceof SymbolNode) { - SymbolNode n = (SymbolNode) other; + @Override + public Object eval(IScope scope) { + return scope.lookupSymbol(this.name); + } - if (this.name.equals(n.name)) { - return true; - } - - return false; - } - return super.equals(other); - } - - @Override - public Object eval(IScope scope) { - return scope.lookupSymbol(this.name); - } - - @Override - public String toString() { - return this.name; - } + @Override + public String toString() { + return this.name; + } }