return result;
}
catch (IOException e) {
throw new LException("[file not found] - " + path + " can't be resolved", e);
}
}
});
// (resource name)
root.put(LSymbol.get("resource"), new LOperation("resource") {
@Override
public LObject evaluate(Environment environment, LObject tokens) {
String rs = ((LList) tokens).get(0).toString();
String content = new Util().read(getClass(), rs);
String commands = parser.format(content.toString());
List<LObject> objects = parser.parseAll(commands);
LObject result = LNull.NULL;
for(LObject object: objects) {
result = execute(object, environment);
}
return result;
}
});
// (instance? object class)
root.put(LSymbol.get("instance?"), new LOperation("instance?") {
@Override
public LObject evaluate(Environment environment, LObject tokens) {
LList list = (LList) tokens;
LObject first = list.get(0).run(environment, tokens);
LJClass second = (LJClass) list.get(1).run(environment, tokens);
return LBoolean.get(((Class<?>) second.getJObject()).isInstance(first));
}
});
// (try (expression) (exception (expression)))
root.put(LSymbol.get("try"), new LOperation("try") {
@Override
public LObject evaluate(Environment environment, LObject tokens) {
LList list = (LList) tokens;
LObject first = list.get(0);
LObject second = list.get(1);
try {
return first.run(environment, first);
}
catch(Exception e) {
logger.info("Caught exception", e);
LList tmp = (LList) second;
LObject name = tmp.getFirst();
LObject expression = tmp.getRest();
environment.put(LSymbol.get(name), new LJObject(e));
return expression.run(environment, expression);
}
}
});
// (begin (expression1) (expression2) ...)
root.put(LSymbol.get("begin"), new LOperation("begin") {
@Override
public LObject evaluate(Environment environment, LObject tokens) {
LObject result = LNull.NULL;
LList list = (LList) tokens;
for (LObject object: list) {
result = object.run(environment, tokens);
}
return result;
}
});
// (let (parameters) body)
root.put(LSymbol.get("let"), new LOperation("let") {
@Override
public LObject evaluate(Environment environment, LObject tokens) {
LList parameters = (LList) ((LList) tokens).getFirst();
LObject body = ((LList) tokens).getRest();
Environment innerEnvironment = new Environment(environment);
for (LObject tmp: parameters) {
LList parameter = (LList) tmp;
LSymbol symbol = LSymbol.get(parameter.get(0));
LObject object = parameter.get(1).run(innerEnvironment, tokens);
innerEnvironment.put(symbol, object);
}
return body.run(innerEnvironment, tokens);
}
});
// (+ token..)
root.put(LSymbol.get("+"), new LOperation("+") {
@Override
public LObject evaluate(Environment environment, LObject tokens) {
LObject n = null;
for (LObject token : (LList) tokens) {
if (n == null) {
n = token.run(environment, token);
}
else {
n = n.sum(token.run(environment, token));
}
}
return n;
}
});
// (- token..)
root.put(LSymbol.get("-"), new LOperation("-") {
@Override
public LObject evaluate(Environment environment, LObject tokens) {
LObject n = null;
for (LObject token : (LList) tokens) {
if (n == null) {
n = token.run(environment, token);
}
else {
n = n.subtract(token.run(environment, token));
}
}
return n;
}
});
// (* token..)
root.put(LSymbol.get("*"), new LOperation("*") {
@Override
public LObject evaluate(Environment environment, LObject tokens) {
LObject n = null;
for (LObject token : (LList) tokens) {
if (n == null) {
n = token.run(environment, token);
}
else {
n = n.multiply(token.run(environment, token));
}
}
return n;
}
});
// (/ token..)
root.put(LSymbol.get("/"), new LOperation("/") {
@Override
public LObject evaluate(Environment environment, LObject tokens) {
LObject n = null;
for (LObject token : (LList) tokens) {
if (n == null) {
n = token.run(environment, token);
}
else {
n = n.divide(token.run(environment, token));
}
}
return n;
}
});
// (define name expression)
root.put(LSymbol.get("define"), new LOperation("define") {
@Override
public LObject evaluate(Environment environment, LObject tokens) {
LObject name = ((LList) tokens).get(0);
LObject expression = LNull.NULL;
// We have the second version of define, if name is a list.
// e.g.: (define (dec2 (n)) (- n 1))
//
// If so, we create a common define-lambda list. So we have just implemented a
// short-cut and the actual definition of a lambda still resists in a single function.
if (name instanceof List) {
LList list = (LList) name;
name = list.get(0);
if(name instanceof LOperation) {
name = ((LOperation) name).getName();
}
LList parameters;
// enables two ways of specifing the parameters:
// (1) (define (dec2 (n)) (- n 1))
// (2) (define (dec2 n) (- n 1))
if (list.get(1) instanceof LList) {
parameters = (LList) list.get(1);
}
else {
parameters = new LList();
parameters.addAll(list.subList(1, list.size()));
}
LList body = (LList) ((LList) tokens).getRest();
LList lambdaList = new LList();
lambdaList.add(LSymbol.get("lambda"));
lambdaList.add(parameters);
for (int i = 0; i < body.size(); i++) {
lambdaList.add(body.get(i));
}
expression = lambdaList.run(environment, lambdaList);
}
else {
LObject second = ((LList) tokens).get(1);
if(second instanceof LOperation)
expression = second; //.run(environment, tokens);
else
expression = second.run(environment, tokens);
}
// if we have a lambda (not an other variable) we can name it
if (expression instanceof LLambda)
((LLambda) expression).setName(name.toString());
environment.put(LSymbol.get(name), expression);
callEnvironmentListeners();
return expression;
}
});
// (set! value)
root.put(LSymbol.get("set!"), new LOperation("set!") {
@Override
public LObject evaluate(Environment environment, LObject tokens) {
LObject name = ((LList) tokens).get(0);
if (name instanceof List) {
name = ((LList) name).get(0);
}
if (!environment.contains(LSymbol.get(name)))
throw new LException(name + " is undefined");
LObject second = ((LList) tokens).get(1);
second = second.run(environment, tokens);