(StarlarkThread.Frame fr, Comprehension comp)
| 875 | } |
| 876 | |
| 877 | private static Object evalComprehension(StarlarkThread.Frame fr, Comprehension comp) |
| 878 | throws EvalException, InterruptedException { |
| 879 | final Dict<Object, Object> dict = comp.isDict() ? Dict.of(fr.thread.mutability()) : null; |
| 880 | final StarlarkList<Object> list = |
| 881 | comp.isDict() ? null : StarlarkList.newList(fr.thread.mutability()); |
| 882 | |
| 883 | // The Lambda class serves as a recursive lambda closure. |
| 884 | class Lambda { |
| 885 | // execClauses(index) recursively executes the clauses starting at index, |
| 886 | // and finally evaluates the body and adds its value to the result. |
| 887 | void execClauses(int index) throws EvalException, InterruptedException { |
| 888 | fr.thread.checkInterrupt(); |
| 889 | |
| 890 | // recursive case: one or more clauses |
| 891 | if (index < comp.getClauses().size()) { |
| 892 | Comprehension.Clause clause = comp.getClauses().get(index); |
| 893 | if (clause instanceof Comprehension.For forClause) { |
| 894 | |
| 895 | Iterable<?> seq = evalAsIterable(fr, forClause.getIterable()); |
| 896 | EvalUtils.addIterator(seq); |
| 897 | try { |
| 898 | for (Object elem : seq) { |
| 899 | assign(fr, forClause.getVars(), elem); |
| 900 | execClauses(index + 1); |
| 901 | } |
| 902 | } catch (EvalException ex) { |
| 903 | fr.setErrorLocation(forClause.getStartLocation()); |
| 904 | throw ex; |
| 905 | } finally { |
| 906 | EvalUtils.removeIterator(seq); |
| 907 | } |
| 908 | |
| 909 | } else { |
| 910 | Comprehension.If ifClause = (Comprehension.If) clause; |
| 911 | if (Starlark.truth(eval(fr, ifClause.getCondition()))) { |
| 912 | execClauses(index + 1); |
| 913 | } |
| 914 | } |
| 915 | return; |
| 916 | } |
| 917 | |
| 918 | // base case: evaluate body and add to result. |
| 919 | if (dict != null) { |
| 920 | DictExpression.Entry body = (DictExpression.Entry) comp.getBody(); |
| 921 | Object k = eval(fr, body.getKey()); |
| 922 | try { |
| 923 | Starlark.checkHashable(k); |
| 924 | Object v = eval(fr, body.getValue()); |
| 925 | dict.putEntry(k, v); |
| 926 | } catch (EvalException ex) { |
| 927 | fr.setErrorLocation(body.getColonLocation()); |
| 928 | throw ex; |
| 929 | } |
| 930 | } else { |
| 931 | list.addElement(eval(fr, ((Expression) comp.getBody()))); |
| 932 | } |
| 933 | } |
| 934 | } |
no test coverage detected