Skip to content

Commit b044249

Browse files
authored
qwen3 coder support (in filter, keys method) (#78)
1 parent 8cd0d6d commit b044249

File tree

3 files changed

+25
-7
lines changed

3 files changed

+25
-7
lines changed

include/minja/minja.hpp

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1291,6 +1291,12 @@ class UnaryOpExpr : public Expression {
12911291
}
12921292
};
12931293

1294+
static bool in(const Value & value, const Value & container) {
1295+
return (((container.is_array() || container.is_object()) && container.contains(value)) ||
1296+
(value.is_string() && container.is_string() &&
1297+
container.to_str().find(value.to_str()) != std::string::npos));
1298+
};
1299+
12941300
class BinaryOpExpr : public Expression {
12951301
public:
12961302
enum class Op { StrConcat, Add, Sub, Mul, MulMul, Div, DivDiv, Mod, Eq, Ne, Lt, Gt, Le, Ge, And, Or, In, NotIn, Is, IsNot };
@@ -1355,13 +1361,8 @@ class BinaryOpExpr : public Expression {
13551361
case Op::Gt: return l > r;
13561362
case Op::Le: return l <= r;
13571363
case Op::Ge: return l >= r;
1358-
case Op::In: return (((r.is_array() || r.is_object()) && r.contains(l)) ||
1359-
(l.is_string() && r.is_string() &&
1360-
r.to_str().find(l.to_str()) != std::string::npos));
1361-
case Op::NotIn:
1362-
return !(((r.is_array() || r.is_object()) && r.contains(l)) ||
1363-
(l.is_string() && r.is_string() &&
1364-
r.to_str().find(l.to_str()) != std::string::npos));
1364+
case Op::In: return in(l, r);
1365+
case Op::NotIn: return !in(l, r);
13651366
default: break;
13661367
}
13671368
throw std::runtime_error("Unknown binary operator");
@@ -1500,6 +1501,13 @@ class MethodCallExpr : public Expression {
15001501
} else if (method->get_name() == "pop") {
15011502
vargs.expectArgs("pop method", {1, 1}, {0, 0});
15021503
return obj.pop(vargs.args[0]);
1504+
} else if (method->get_name() == "keys") {
1505+
vargs.expectArgs("keys method", {0, 0}, {0, 0});
1506+
auto result = Value::array();
1507+
for (const auto& key : obj.keys()) {
1508+
result.push_back(Value(key));
1509+
}
1510+
return result;
15031511
} else if (method->get_name() == "get") {
15041512
vargs.expectArgs("get method", {1, 2}, {0, 0});
15051513
auto key = vargs.args[0];
@@ -2792,6 +2800,9 @@ inline std::shared_ptr<Context> Context::builtins() {
27922800
if (!items.is_array()) throw std::runtime_error("object is not iterable");
27932801
return items;
27942802
}));
2803+
globals.set("in", simple_function("in", { "item", "items" }, [](const std::shared_ptr<Context> &, Value & args) -> Value {
2804+
return in(args.at("item"), args.at("items"));
2805+
}));
27952806
globals.set("unique", simple_function("unique", { "items" }, [](const std::shared_ptr<Context> &, Value & args) -> Value {
27962807
auto & items = args.at("items");
27972808
if (!items.is_array()) throw std::runtime_error("object is not iterable");

tests/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,9 @@ set(MODEL_IDS
320320
xwen-team/Xwen-72B-Chat
321321
xwen-team/Xwen-7B-Chat
322322
Qwen/Qwen3-4B
323+
Qwen/Qwen3-235B-A22B-Instruct-2507
324+
Qwen/Qwen3-235B-A22B-Thinking-2507
325+
Qwen/Qwen3-Coder-30B-A3B-Instruct
323326

324327
# Broken, TODO:
325328
# Qwen/QwQ-32B

tests/test-syntax.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,10 @@ TEST(SyntaxTest, SimpleCases) {
217217
render(R"({{ 'a' in 'abc' }},{{ 'd' in 'abc' }})", {}, {}));
218218
EXPECT_EQ("False,True",
219219
render(R"({{ 'a' not in 'abc' }},{{ 'd' not in 'abc' }})", {}, {}));
220+
EXPECT_EQ("['a', 'a']",
221+
render(R"({{ ['a', 'b', 'c', 'a'] | select('in', ['a']) | list }})", {}, {}));
222+
EXPECT_EQ("['a', 'b'],[]",
223+
render(R"({{ {'a': 1, 'b': 2}.keys() | list }},{{ {}.keys() | list }})", {}, {}));
220224
EXPECT_EQ(
221225
R"([{'a': 1}])",
222226
render(R"({{ [{"a": 1}, {"a": 2}, {}] | selectattr("a", "equalto", 1) | list }})", {}, {}));

0 commit comments

Comments
 (0)