[READY] Adds selector lists to SDQL (#43383)

* [SDQL2] Adds selector arrays

* SDQL2 documentation spec updated slightly

* SDQL2 selector array docs + tweaks

If a single list is the only result of a MAP statement,
meaning objs.len == 1, AND it's a list, it will unwrap
the result from its containing list and return it directly.

The selector array logic keeps track of the state of the query
when it starts the first Search. It won't change the state back
to Execute until the top-level is reached, which sets a var
to keep track.

* SDQL2 MAP change from objs.len to length(objs)

* [SDQL2] Reverts MAP list unwrap

* [SDQL] Move (expr) from expr, unary_expr to var

This should result in the same functionality but instead of expressions and unary_expressions processing sub expressions, variables do
This means that expression->value->variable is now completely recursable

* [SDQL2] Update selector list documentation
This commit is contained in:
JJRcop
2019-04-15 09:22:30 +02:00
committed by AnturK
parent a4906f2382
commit 1cf1df847c
2 changed files with 72 additions and 37 deletions
+26 -1
View File
@@ -61,6 +61,10 @@
"SELECT /mob WHERE client MAP client WHERE holder MAP holder"
You can also generate a new list on the fly using a selector array. @[] will generate a list of objects based off the selector provided.
"SELECT /mob/living IN (@[/area/crew_quarters/bar MAP contents])[1]"
What if some dumbass admin spawned a bajillion spiders and you need to kill them all?
Oh yeah you'd rather not delete all the spiders in maintenace. Only that one room the spiders were
spawned in.
@@ -879,6 +883,22 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/SDQL2_VV_all, new(null
dummy[result] = assoc
result = dummy
val += result
else if(expression[i] == "@\[")
var/list/search_tree = expression[++i]
var/already_searching = (state == SDQL2_STATE_SEARCHING) //In case we nest, don't want to break out of the searching state until we're all done.
if(!already_searching)
state = SDQL2_STATE_SEARCHING
val = Search(search_tree)
SDQL2_STAGE_SWITCH_CHECK
if(!already_searching)
state = SDQL2_STATE_EXECUTING
else
state = SDQL2_STATE_SEARCHING
else
val = world.SDQL_var(object, expression, i, object, superuser, src)
i = expression.len
@@ -968,6 +988,10 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/SDQL2_VV_all, new(null
return null
start++
long = start < expression.len
else if(expression[start] == "(" && long)
v = query.SDQL_expression(source, expression[start + 1])
start++
long = start < expression.len
else if(D != null && (!long || expression[start + 1] == ".") && (expression[start] in D.vars))
if(D.can_vv_get(expression[start]) || superuser)
v = D.vars[expression[start]]
@@ -1060,7 +1084,8 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/SDQL2_VV_all, new(null
"=" = list("", "="),
"<" = list("", "=", ">"),
">" = list("", "="),
"!" = list("", "="))
"!" = list("", "="),
"@" = list("\["))
var/word = ""
var/list/query_list = list()
+46 -36
View File
@@ -19,24 +19,28 @@
//
// from_item : 'world' | expression
//
// call_function : <function name> '(' [arguments] ')'
// arguments : expression [',' arguments]
// call_function : <function name> '(' [expression_list] ')'
//
// object_type : <type path>
//
// assignments : assignment [',' assignments]
// assignment : <variable name> '=' expression
// variable : <variable name> | <variable name> '.' variable | '[' <hex number> ']' | '[' <hex number> ']' '.' variable
// variable : <variable name> | variable '.' variable | variable '[' <list index> ']' | '{' <ref as hex number> '}' | '(' expression ')' | call_function
//
// bool_expression : expression comparitor expression [bool_operator bool_expression]
// expression : ( unary_expression | '(' expression ')' | value ) [binary_operator expression]
// unary_expression : unary_operator ( unary_expression | value | '(' expression ')' )
// expression_list : expression [',' expression_list]
// unary_expression : unary_operator ( unary_expression | value )
//
// comparitor : '=' | '==' | '!=' | '<>' | '<' | '<=' | '>' | '>='
// value : variable | string | number | 'null' | object_type
// value : variable | string | number | 'null' | object_type | array | selectors_array
// unary_operator : '!' | '-' | '~'
// binary_operator : comparitor | '+' | '-' | '/' | '*' | '&' | '|' | '^' | '%'
// bool_operator : 'AND' | '&&' | 'OR' | '||'
//
// array : '[' expression_list ']'
// selectors_array : '@[' object_selectors ']'
//
// string : ''' <some text> ''' | '"' <some text > '"'
// number : <some digits>
//
@@ -336,7 +340,7 @@
return i
//variable: <variable name> | <variable name> '.' variable | '[' <hex number> ']' | '[' <hex number> ']' '.' variable
//variable: <variable name> | variable '.' variable | variable '[' <list index> ']' | '{' <ref as hex number> '}' | '(' expression ')' | call_function
/datum/SDQL_parser/proc/variable(i, list/node)
var/list/L = list(token(i))
node[++node.len] = L
@@ -348,6 +352,16 @@
if(token(i) != "}")
parse_error("Missing } at end of pointer.")
else if(token(i) == "(") // not a proc but an expression
var/list/sub_expression = list()
i = expression(i + 1, sub_expression)
if(token(i) != ")")
parse_error("Missing ) at end of expression.")
L[++L.len] = sub_expression
if(token(i + 1) == ".")
L += "."
i = variable(i + 2, L)
@@ -424,7 +438,7 @@
return i + 1
//array: '[' expression, expression, ... ']'
//array: '[' expression_list ']'
/datum/SDQL_parser/proc/array(var/i, var/list/node)
// Arrays get turned into this: list("[", list(exp_1a = exp_1b, ...), ...), "[" is to mark the next node as an array.
if(copytext(token(i), 1, 2) != "\[")
@@ -490,6 +504,23 @@
return i + 1
//selectors_array: '@[' object_selectors ']'
/datum/SDQL_parser/proc/selectors_array(var/i, var/list/node)
if(token(i) == "@\[")
node += token(i++)
if(token(i) != "]")
var/list/select = list()
i = object_selectors(i, select)
node[++node.len] = select
if(token(i) != "]")
parse_error("Expected ']' to close selector array, but found '[token(i)]'")
else
parse_error("Selector array expected a selector, but found nothing")
else
parse_error("Expected '@\[' but found '[token(i)]'")
return i + 1
//call_function: <function name> ['(' [arguments] ')']
/datum/SDQL_parser/proc/call_function(i, list/node, list/arguments)
if(length(tokenl(i)))
@@ -520,25 +551,12 @@
return i + 1
//expression: ( unary_expression | '(' expression ')' | value ) [binary_operator expression]
//expression: ( unary_expression | value ) [binary_operator expression]
/datum/SDQL_parser/proc/expression(i, list/node)
if(token(i) in unary_operators)
i = unary_expression(i, node)
else if(token(i) == "(")
var/list/expr = list()
i = expression(i + 1, expr)
if(token(i) != ")")
parse_error("Missing ) at end of expression.")
else
i++
node[++node.len] = expr
else
i = value(i, node)
@@ -558,7 +576,7 @@
return i
//unary_expression: unary_operator ( unary_expression | value | '(' expression ')' )
//unary_expression: unary_operator ( unary_expression | value )
/datum/SDQL_parser/proc/unary_expression(i, list/node)
if(token(i) in unary_operators)
@@ -570,19 +588,6 @@
if(token(i) in unary_operators)
i = unary_expression(i, unary_exp)
else if(token(i) == "(")
var/list/expr = list()
i = expression(i + 1, expr)
if(token(i) != ")")
parse_error("Missing ) at end of expression.")
else
i++
unary_exp[++unary_exp.len] = expr
else
i = value(i, unary_exp)
@@ -607,7 +612,7 @@
return i + 1
//value: variable | string | number | 'null' | object_type
//value: variable | string | number | 'null' | object_type | array | selectors_array
/datum/SDQL_parser/proc/value(i, list/node)
if(token(i) == "null")
node += "null"
@@ -626,8 +631,13 @@
else if(copytext(token(i), 1, 2) == "\[") // Start a list.
i = array(i, node)
else if(copytext(token(i), 1, 3) == "@\[")
i = selectors_array(i, node)
else if(copytext(token(i), 1, 2) == "/")
i = object_type(i, node)
else
i = variable(i, node)