public static LispObject evaluate(String name, Environment environment, List<LispObject> args) { for (Class c : getSubroutineContainers()) { for (Method m : c.getMethods()) { Subroutine annotation = m.getAnnotation(Subroutine.class); if (annotation == null || !annotation.value().equals(name)) continue; if (!Arrays.asList(mySpecialForms).contains(c)) { if (!environment.areArgumentsEvaluated()) { for (int i = 0, dataSize = args.size(); i < dataSize; i++) { args.set(i, args.get(i).evaluate(environment)); } } else { environment.setArgumentsEvaluated(false); } } ArgumentsList arguments = parseArguments(m, environment, args); checkArguments(name, arguments, args); try { return (LispObject) m.invoke(null, arguments.getValues()); } catch (IllegalAccessException | InvocationTargetException e) { if (e.getCause().getMessage() == null) e.getCause().printStackTrace(); else System.err.println(e.getCause().getMessage()); Throwable cause = getCause(e); if (cause instanceof LispThrow) throw (LispThrow) cause; if (cause instanceof VoidVariableException && TestMode.TEST && c == Key.class) { System.err.println("Skip keymap errors in test mode"); return LispSymbol.ourNil; } if (cause instanceof LispException) throw (LispException) cause; cause.printStackTrace(); throw new LispException(e.getCause().getMessage()); } } } throw new InternalException(JelispBundle.message("unknown.subroutine", name)); }
@Subroutine(value = "string-match") public static LispObject stringMatch( Environment environment, LispString regexp, LispString string, @Optional LispInteger start) { int from = 0; if (start != null) { from = start.getData(); if (from < 0 || from >= string.size()) throw new ArgumentOutOfRange(string.toString(), start.toString()); } LispSymbol s = environment.find("case-fold-search"); int r = string.match( environment, regexp, from, (s != null && !s.getValue().equals(LispSymbol.ourNil))); if (r == -1) return LispSymbol.ourNil; return new LispInteger(r); }