TLDR: The [[
and ]]
after the query
keyword are not parsed as a string literal[1]. When parsed, they are delimiters for query clauses, like how ()
delimits the parameters for a function. Those query clauses start with the familiar keywords, from
, limit
, where
, etc. and are followed by an expression. The {}
hack I provided before meant the expression was being parsed as a table literal. Using ()
in that case is better because index.tag
is a function. Iām not sure why it is not parsed correctly otherwise.
Limit does not need any special treatment. It can event collide with the keyword (not recommended):
test.objectAndLimit = function (object, limit)
return query[[from t = index.tag(object) limit limit]]
end
-- outside the code block
${test.objectAndLimit('tag', 3)}
Dynamically changing a condition for where
is trickier because you need to have a reference to each object in the possible results. You can do that with a function:
test.attrIsString = function (obj, attr, s)
return obj[attr] == s
end
test.dynamicWhere = function (object, limit, where_fun, ...)
return query[[from t = index.tag(object) where where_fun(t, unpack(..., 1)) limit limit]]
end
-- outside the space-lua block
${test.dynamicWhere('tag', 3, test.attrIsString, 'name', 'git')}
[1] Some notes from code that I used to try to explain what was going on.
From lua.grammar
in source:
Query {
kw<"query"> "[[" QueryClause* "]]"
}
QueryClause {
FromClause |
WhereClause |
OrderByClause |
SelectClause |
LimitClause
}
FromClause { ckw<"from"> (Name "=")? exp }
WhereClause { ckw<"where"> exp }
LimitClause { ckw<"limit"> exp ("," exp)? }
OrderByClause { ckw<"order"> ckw<"by"> list<OrderBy> }
OrderBy { exp ckw<"desc">? }
SelectClause { ckw<"select"> exp }
So the keyword āqueryā is followed by zero or more QueryClause
s surrounded by [[...]]
. I think kw<>
is how to specify keywords. I donāt know what ckw<>
does, but I assume it is similar to providing a keyword. Note how they are all followed by exp
, to some extent. Here is the definition for exp
:
exp {
kw<"nil"> | kw<"true"> | kw<"false"> | "..." |
Number |
LiteralString |
prefixexp |
BinaryExpression |
UnaryExpression |
TableConstructor |
FunctionDef { kw<"function"> FuncBody } |
Query
}
So I think my hack to wrap the argument in {..}
before was a way to get the parser to interpret it as a TableConstructor
argument to index.tag
. Using (..)
for index.tag
makes it properly interpreted as a function call through prefixexp
:
prefixexp {
var |
Parens { "(" exp ")" ~parens } |
FunctionCall ~fcall
}