Create symbols dynamically
This commit is contained in:
parent
ff60d0d3da
commit
99ae99a8ab
|
@ -0,0 +1,13 @@
|
||||||
|
(defmacro array (size)
|
||||||
|
`(let ,(map (lambda (x) (list (fuse 'index x))) (create-indices size))
|
||||||
|
(dlambda
|
||||||
|
(:get (i) (eval (fuse 'index i)))
|
||||||
|
(:set (i value) (set (fuse 'index i) value)))))
|
||||||
|
|
||||||
|
(defun create-indices (size)
|
||||||
|
(create-indices-tail (- size 1) ()))
|
||||||
|
|
||||||
|
(defun create-indices-tail (index accumulator)
|
||||||
|
(if (< index 0)
|
||||||
|
accumulator
|
||||||
|
(recur (- index 1) (cons index accumulator))))
|
|
@ -0,0 +1,36 @@
|
||||||
|
package function.builtin;
|
||||||
|
|
||||||
|
import function.ArgumentValidator;
|
||||||
|
import function.FunctionNames;
|
||||||
|
import function.LispFunction;
|
||||||
|
import sexpression.Atom;
|
||||||
|
import sexpression.Cons;
|
||||||
|
import sexpression.LispString;
|
||||||
|
import sexpression.SExpression;
|
||||||
|
import sexpression.Symbol;
|
||||||
|
|
||||||
|
@FunctionNames({ "FUSE" })
|
||||||
|
public class FUSE extends LispFunction {
|
||||||
|
|
||||||
|
private static final String SEPARATOR = "-";
|
||||||
|
|
||||||
|
private ArgumentValidator argumentValidator;
|
||||||
|
|
||||||
|
public FUSE(String name) {
|
||||||
|
this.argumentValidator = new ArgumentValidator(name);
|
||||||
|
this.argumentValidator.setExactNumberOfArguments(2);
|
||||||
|
this.argumentValidator.setFirstArgumentExpectedType(Symbol.class);
|
||||||
|
this.argumentValidator.setTrailingArgumentExpectedType(Atom.class);
|
||||||
|
this.argumentValidator.setTrailingArgumentExcludedType(LispString.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SExpression call(Cons argumentList) {
|
||||||
|
argumentValidator.validate(argumentList);
|
||||||
|
Symbol left = (Symbol) argumentList.getFirst();
|
||||||
|
Atom right = (Atom) ((Cons) argumentList.getRest()).getFirst();
|
||||||
|
|
||||||
|
return new Symbol(left.toString() + SEPARATOR + right.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -14,6 +14,7 @@ import function.builtin.APPLY;
|
||||||
import function.builtin.EVAL;
|
import function.builtin.EVAL;
|
||||||
import function.builtin.EXIT;
|
import function.builtin.EXIT;
|
||||||
import function.builtin.FUNCALL;
|
import function.builtin.FUNCALL;
|
||||||
|
import function.builtin.FUSE;
|
||||||
import function.builtin.GENSYM;
|
import function.builtin.GENSYM;
|
||||||
import function.builtin.LOAD;
|
import function.builtin.LOAD;
|
||||||
import function.builtin.PRINT;
|
import function.builtin.PRINT;
|
||||||
|
@ -77,6 +78,7 @@ public class FunctionTable {
|
||||||
allBuiltIns.add(EXIT.class);
|
allBuiltIns.add(EXIT.class);
|
||||||
allBuiltIns.add(FIRST.class);
|
allBuiltIns.add(FIRST.class);
|
||||||
allBuiltIns.add(FUNCALL.class);
|
allBuiltIns.add(FUNCALL.class);
|
||||||
|
allBuiltIns.add(FUSE.class);
|
||||||
allBuiltIns.add(GENSYM.class);
|
allBuiltIns.add(GENSYM.class);
|
||||||
allBuiltIns.add(GENSYM_EQUAL.class);
|
allBuiltIns.add(GENSYM_EQUAL.class);
|
||||||
allBuiltIns.add(NUMERIC_GREATER.class);
|
allBuiltIns.add(NUMERIC_GREATER.class);
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
package function.builtin.special;
|
||||||
|
|
||||||
|
import static testutil.TestUtilities.assertSExpressionsMatch;
|
||||||
|
import static testutil.TestUtilities.evaluateString;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import function.ArgumentValidator.BadArgumentTypeException;
|
||||||
|
import function.ArgumentValidator.TooFewArgumentsException;
|
||||||
|
import function.ArgumentValidator.TooManyArgumentsException;
|
||||||
|
import sexpression.Symbol;
|
||||||
|
import testutil.SymbolAndFunctionCleaner;
|
||||||
|
|
||||||
|
public class FUSETest extends SymbolAndFunctionCleaner {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void fuseSymbolAndNumber() {
|
||||||
|
assertSExpressionsMatch(new Symbol("A-1"), evaluateString("(fuse 'a 1)"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void fuseTwoSymbols_NeitherQuoted() {
|
||||||
|
evaluateString("(setq a 'aaa)");
|
||||||
|
evaluateString("(setq b 'bbb)");
|
||||||
|
assertSExpressionsMatch(new Symbol("AAA-BBB"), evaluateString("(fuse a b)"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void fuseTwoSymbols_OneQuoted() {
|
||||||
|
evaluateString("(setq b 'bbb)");
|
||||||
|
assertSExpressionsMatch(new Symbol("A-BBB"), evaluateString("(fuse 'a b)"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void fuseTwoSymbols_BothQuoted() {
|
||||||
|
assertSExpressionsMatch(new Symbol("A-B"), evaluateString("(fuse 'a 'b)"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = TooFewArgumentsException.class)
|
||||||
|
public void fuseWithTooFewArguments() {
|
||||||
|
evaluateString("(fuse 'a)");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = TooManyArgumentsException.class)
|
||||||
|
public void fuseWithTooManyArguments() {
|
||||||
|
evaluateString("(fuse 'a 'b 'c)");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = BadArgumentTypeException.class)
|
||||||
|
public void fuseWithBadFirstArgumentType() {
|
||||||
|
evaluateString("(fuse 1 'b)");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = BadArgumentTypeException.class)
|
||||||
|
public void fuseWithBadSecondArgumentType() {
|
||||||
|
evaluateString("(fuse 'a \"b\")");
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue