Merge pull request #7846 from Citadel-Station-13/sdql2

SDQL2 upgrades!
This commit is contained in:
deathride58
2019-01-03 08:00:15 -05:00
committed by GitHub
7 changed files with 1261 additions and 508 deletions
+4 -1
View File
@@ -7,4 +7,7 @@
#define TICK_USAGE_REAL world.tick_usage //to be used where the result isn't checked
#define TICK_CHECK ( TICK_USAGE > Master.current_ticklimit )
#define CHECK_TICK if TICK_CHECK stoplag()
#define CHECK_TICK ( TICK_CHECK ? stoplag() : 0 )
#define TICK_CHECK_HIGH_PRIORITY ( TICK_USAGE > 95 )
#define CHECK_TICK_HIGH_PRIORITY ( TICK_CHECK_HIGH_PRIORITY? stoplag() : 0 )
+5
View File
@@ -4,6 +4,11 @@
#define ALL (~0) //For convenience.
#define NONE 0
//for convenience
#define ENABLE_BITFIELD(variable, flag) (variable |= (flag))
#define DISABLE_BITFIELD(variable, flag) (variable &= ~(flag))
#define CHECK_BITFIELD(variable, flag) (variable & flag)
GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768))
// for /datum/var/datum_flags
+24 -91
View File
@@ -63,96 +63,29 @@ GLOBAL_VAR_INIT(rollovercheck_last_timeofday, 0)
//Takes a value of time in deciseconds.
//Returns a text value of that number in hours, minutes, or seconds.
/proc/DisplayTimeText(time_value, truncate = FALSE)
var/second = (time_value)*0.1
var/second_adjusted = null
var/second_rounded = FALSE
var/minute = null
var/hour = null
var/day = null
/proc/DisplayTimeText(time_value, round_seconds_to = 0.1)
var/second = FLOOR(time_value * 0.1, round_seconds_to)
if(!second)
return "0 seconds"
if(second >= 60)
minute = FLOOR(second/60, 1)
second = round(second - (minute*60), 0.1)
second_rounded = TRUE
if(second) //check if we still have seconds remaining to format, or if everything went into minute.
second_adjusted = round(second) //used to prevent '1 seconds' being shown
if(day || hour || minute)
if(second_adjusted == 1 && second >= 1)
second = " and 1 second"
else if(second > 1)
second = " and [second_adjusted] seconds"
else //shows a fraction if seconds is < 1
if(second_rounded) //no sense rounding again if it's already done
second = " and [second] seconds"
else
second = " and [round(second, 0.1)] seconds"
else
if(second_adjusted == 1 && second >= 1)
second = "[truncate ? "second" : "1 second"]"
else if(second > 1)
second = "[second_adjusted] seconds"
else
if(second_rounded)
second = "[second] seconds"
else
second = "[round(second, 0.1)] seconds"
else
second = null
if(!minute)
return "[second]"
if(minute >= 60)
hour = FLOOR(minute/60, 1)
minute = (minute - (hour*60))
if(minute) //alot simpler from here since you don't have to worry about fractions
if(minute != 1)
if((day || hour) && second)
minute = ", [minute] minutes"
else if((day || hour) && !second)
minute = " and [minute] minutes"
else
minute = "[minute] minutes"
else
if((day || hour) && second)
minute = ", 1 minute"
else if((day || hour) && !second)
minute = " and 1 minute"
else
minute = "[truncate ? "minute" : "1 minute"]"
else
minute = null
if(!hour)
return "[minute][second]"
if(hour >= 24)
day = FLOOR(hour/24, 1)
hour = (hour - (day*24))
return "right now"
if(second < 60)
return "[second] second[(second != 1)? "s":""]"
var/minute = FLOOR(second / 60, 1)
second = FLOOR(MODULUS(second, 60), round_seconds_to)
var/secondT
if(second)
secondT = " and [second] second[(second != 1)? "s":""]"
if(minute < 60)
return "[minute] minute[(minute != 1)? "s":""][secondT]"
var/hour = FLOOR(minute / 60, 1)
minute = MODULUS(minute, 60)
var/minuteT
if(minute)
minuteT = " and [minute] minute[(minute != 1)? "s":""]"
if(hour < 24)
return "[hour] hour[(hour != 1)? "s":""][minuteT][secondT]"
var/day = FLOOR(hour / 24, 1)
hour = MODULUS(hour, 24)
var/hourT
if(hour)
if(hour != 1)
if(day && (minute || second))
hour = ", [hour] hours"
else if(day && (!minute || !second))
hour = " and [hour] hours"
else
hour = "[hour] hours"
else
if(day && (minute || second))
hour = ", 1 hour"
else if(day && (!minute || !second))
hour = " and 1 hour"
else
hour = "[truncate ? "hour" : "1 hour"]"
else
hour = null
if(!day)
return "[hour][minute][second]"
if(day > 1)
day = "[day] days"
else
day = "[truncate ? "day" : "1 day"]"
return "[day][hour][minute][second]"
hourT = " and [hour] hour[(hour != 1)? "s":""]"
return "[day] day[(day != 1)? "s":""][hourT][minuteT][secondT]"
File diff suppressed because it is too large Load Diff
+297 -107
View File
@@ -7,36 +7,34 @@
//
// query : select_query | delete_query | update_query | call_query | explain
// explain : 'EXPLAIN' query
// select_query : 'SELECT' object_selectors
// delete_query : 'DELETE' object_selectors
// update_query : 'UPDATE' object_selectors 'SET' assignments
// call_query : 'CALL' variable 'ON' object_selectors // Note here: 'variable' does function calls. This simplifies parsing.
//
// select_query : 'SELECT' select_list [('FROM' | 'IN') from_list] ['WHERE' bool_expression]
// delete_query : 'DELETE' select_list [('FROM' | 'IN') from_list] ['WHERE' bool_expression]
// update_query : 'UPDATE' select_list [('FROM' | 'IN') from_list] 'SET' assignments ['WHERE' bool_expression]
// call_query : 'CALL' call_function ['ON' select_list [('FROM' | 'IN') from_list] ['WHERE' bool_expression]]
// select_item : '*' | object_type
//
// select_list : select_item [',' select_list]
// select_item : '*' | select_function | object_type
// select_function : count_function
// count_function : 'COUNT' '(' '*' ')' | 'COUNT' '(' object_types ')'
// object_selectors : select_item [('FROM' | 'IN') from_item] [modifier_list]
// modifier_list : ('WHERE' bool_expression | 'MAP' expression) [modifier_list]
//
// from_list : from_item [',' from_list]
// from_item : 'world' | object_type
// from_item : 'world' | expression
//
// call_function : <function name> ['(' [arguments] ')']
// call_function : <function name> '(' [arguments] ')'
// arguments : expression [',' arguments]
//
// object_type : <type path> | string
// object_type : <type path>
//
// assignments : assignment, [',' assignments]
// assignments : assignment [',' assignments]
// assignment : <variable name> '=' expression
// variable : <variable name> | <variable name> '.' variable
// variable : <variable name> | <variable name> '.' variable | '[' <hex number> ']' | '[' <hex number> ']' '.' variable
//
// 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 ')' )
// comparitor : '=' | '==' | '!=' | '<>' | '<' | '<=' | '>' | '>='
// value : variable | string | number | 'null'
// value : variable | string | number | 'null' | object_type
// unary_operator : '!' | '-' | '~'
// binary_operator : comparitor | '+' | '-' | '/' | '*' | '&' | '|' | '^'
// binary_operator : comparitor | '+' | '-' | '/' | '*' | '&' | '|' | '^' | '%'
// bool_operator : 'AND' | '&&' | 'OR' | '||'
//
// string : ''' <some text> ''' | '"' <some text > '"'
@@ -51,10 +49,9 @@
var/list/query
var/list/tree
var/list/select_functions = list("count")
var/list/boolean_operators = list("and", "or", "&&", "||")
var/list/unary_operators = list("!", "-", "~")
var/list/binary_operators = list("+", "-", "/", "*", "&", "|", "^")
var/list/binary_operators = list("+", "-", "/", "*", "&", "|", "^", "%")
var/list/comparitors = list("=", "==", "!=", "<>", "<", "<=", ">", ">=")
/datum/SDQL_parser/New(query_list)
@@ -62,12 +59,12 @@
/datum/SDQL_parser/proc/parse_error(error_message)
error = 1
to_chat(usr, "<span class='danger'>SQDL2 Parsing Error: [error_message]</span>")
to_chat(usr, "<span class='warning'>SQDL2 Parsing Error: [error_message]</span>")
return query.len + 1
/datum/SDQL_parser/proc/parse()
tree = list()
query(1, tree)
query_options(1, tree)
if(error)
return list()
@@ -91,354 +88,547 @@
/datum/SDQL_parser/proc/tokenl(i)
return lowertext(token(i))
/datum/SDQL_parser/proc/query_options(i, list/node)
var/list/options = list()
if(tokenl(i) == "using")
i = option_assignments(i + 1, node, options)
query(i, node)
if(length(options))
node["options"] = options
//option_assignment: query_option '=' define
/datum/SDQL_parser/proc/option_assignment(i, list/node, list/assignment_list = list())
var/type = tokenl(i)
if(!(type in SDQL2_VALID_OPTION_TYPES))
parse_error("Invalid option type: [type]")
if(!(token(i + 1) == "="))
parse_error("Invalid option assignment symbol: [token(i + 1)]")
var/val = tokenl(i + 2)
if(!(val in SDQL2_VALID_OPTION_VALUES))
parse_error("Invalid optoin value: [val]")
assignment_list[type] = val
return (i + 3)
//option_assignments: option_assignment, [',' option_assignments]
/datum/SDQL_parser/proc/option_assignments(i, list/node, list/store)
i = option_assignment(i, node, store)
if(token(i) == ",")
i = option_assignments(i + 1, node, store)
return i
//query: select_query | delete_query | update_query
/datum/SDQL_parser/proc/query(i, list/node)
query_type = tokenl(i)
switch(query_type)
if("select")
select_query(i, node)
if("delete")
delete_query(i, node)
if("update")
update_query(i, node)
if("call")
call_query(i, node)
if("explain")
node += "explain"
node["explain"] = list()
query(i + 1, node["explain"])
// select_query: 'SELECT' select_list [('FROM' | 'IN') from_list] ['WHERE' bool_expression]
// select_query: 'SELECT' object_selectors
/datum/SDQL_parser/proc/select_query(i, list/node)
var/list/select = list()
i = select_list(i + 1, select)
node += "select"
i = object_selectors(i + 1, select)
node["select"] = select
selectors(i, node)
return i
//delete_query: 'DELETE' select_list [('FROM' | 'IN') from_list] ['WHERE' bool_expression]
//delete_query: 'DELETE' object_selectors
/datum/SDQL_parser/proc/delete_query(i, list/node)
var/list/select = list()
i = select_list(i + 1, select)
node += "delete"
i = object_selectors(i + 1, select)
node["delete"] = select
selectors(i, node)
return i
//update_query: 'UPDATE' select_list [('FROM' | 'IN') from_list] 'SET' assignments ['WHERE' bool_expression]
//update_query: 'UPDATE' object_selectors 'SET' assignments
/datum/SDQL_parser/proc/update_query(i, list/node)
var/list/select = list()
i = select_list(i + 1, select)
node += "update"
i = object_selectors(i + 1, select)
node["update"] = select
if(tokenl(i) != "set")
i = parse_error("UPDATE has misplaced SET")
var/list/set_assignments = list()
i = assignments(i + 1, set_assignments)
node += "set"
node["set"] = set_assignments
selectors(i, node)
return i
//call_query: 'CALL' call_function ['ON' select_list [('FROM' | 'IN') from_list] ['WHERE' bool_expression]]
//call_query: 'CALL' call_function ['ON' object_selectors]
/datum/SDQL_parser/proc/call_query(i, list/node)
var/list/func = list()
i = variable(i + 1, func) // Yes technically does anything variable() matches but I don't care, if admins fuck up this badly then they shouldn't be allowed near SDQL.
node += "call"
node["call"] = func
if(tokenl(i) != "on")
return i
return parse_error("You need to specify what to call ON.")
var/list/select = list()
i = select_list(i + 1, select)
node += "on"
i = object_selectors(i + 1, select)
node["on"] = select
selectors(i, node)
return i
//select_list: select_item [',' select_list]
// object_selectors: select_item [('FROM' | 'IN') from_item] [modifier_list]
/datum/SDQL_parser/proc/object_selectors(i, list/node)
i = select_item(i, node)
if (tokenl(i) == "from" || tokenl(i) == "in")
i++
var/list/from = list()
i = from_item(i, from)
node[++node.len] = from
else
node[++node.len] = list("world")
i = modifier_list(i, node)
return i
// modifier_list: ('WHERE' bool_expression | 'MAP' expression) [modifier_list]
/datum/SDQL_parser/proc/modifier_list(i, list/node)
while (TRUE)
if (tokenl(i) == "where")
i++
node += "where"
var/list/expr = list()
i = bool_expression(i, expr)
node[++node.len] = expr
else if (tokenl(i) == "map")
i++
node += "map"
var/list/expr = list()
i = expression(i, expr)
node[++node.len] = expr
else
return i
//select_list:select_item [',' select_list]
/datum/SDQL_parser/proc/select_list(i, list/node)
i = select_item(i, node)
if(token(i) == ",")
i = select_list(i + 1, node)
return i
//assignments: assignment, [',' assignments]
/datum/SDQL_parser/proc/assignments(i, list/node)
i = assignment(i, node)
if(token(i) == ",")
i = assignments(i + 1, node)
return i
//select_item: '*' | select_function | object_type
/datum/SDQL_parser/proc/select_item(i, list/node)
if(token(i) == "*")
if (token(i) == "*")
node += "*"
i++
else if(tokenl(i) in select_functions)
i = select_function(i, node)
else
else if (copytext(token(i), 1, 2) == "/")
i = object_type(i, node)
else
i = parse_error("Expected '*' or type path for select item")
return i
// Standardized method for handling the IN/FROM and WHERE options.
/datum/SDQL_parser/proc/selectors(i, list/node)
while (token(i))
var/tok = tokenl(i)
if(tok in list("from", "in"))
if (tok in list("from", "in"))
var/list/from = list()
i = from_item(i + 1, from)
node["from"] = from
continue
if(tok == "where")
if (tok == "where")
var/list/where = list()
i = bool_expression(i + 1, where)
node["where"] = where
continue
parse_error("Expected either FROM, IN or WHERE token, found [token(i)] instead.")
return i + 1
if(!node.Find("from"))
if (!node.Find("from"))
node["from"] = list("world")
return i
//from_item: 'world' | object_type
//from_item: 'world' | expression
/datum/SDQL_parser/proc/from_item(i, list/node)
if(token(i) == "world")
node += "world"
i++
else
i = expression(i, node)
return i
//bool_expression: expression [bool_operator bool_expression]
/datum/SDQL_parser/proc/bool_expression(i, list/node)
var/list/bool = list()
i = expression(i, bool)
node[++node.len] = bool
if(tokenl(i) in boolean_operators)
i = bool_operator(i, node)
i = bool_expression(i, node)
return i
//assignment: <variable name> '=' expression
/datum/SDQL_parser/proc/assignment(var/i, var/list/node, var/list/assignment_list = list())
assignment_list += token(i)
if(token(i + 1) == ".")
i = assignment(i + 2, node, assignment_list)
else if(token(i + 1) == "=")
var/exp_list = list()
node[assignment_list] = exp_list
i = expression(i + 2, exp_list)
else
parse_error("Assignment expected, but no = found")
return i
//variable: <variable name> | <variable name> '.' variable
//variable: <variable name> | <variable name> '.' variable | '[' <hex number> ']' | '[' <hex number> ']' '.' variable
/datum/SDQL_parser/proc/variable(i, list/node)
var/list/L = list(token(i))
node[++node.len] = L
if(token(i) == "{")
L += token(i+1)
L += token(i + 1)
i += 2
if(token(i) != "}")
parse_error("Missing } at end of pointer.")
if(token(i + 1) == ".")
L += "."
i = variable(i + 2, L)
else if(token(i + 1) == "(") // OH BOY PROC
else if (token(i + 1) == "(") // OH BOY PROC
var/list/arguments = list()
i = call_function(i, null, arguments)
L += ":"
L[++L.len] = arguments
else if(token(i + 1) == "\[")
else if (token(i + 1) == "\[")
var/list/expression = list()
i = expression(i + 2, expression)
if (token(i) != "]")
parse_error("Missing ] at the end of list access.")
L += "\["
L[++L.len] = expression
i++
else
i++
return i
//object_type: <type path>
/datum/SDQL_parser/proc/object_type(i, list/node)
if (copytext(token(i), 1, 2) != "/")
return parse_error("Expected type, but it didn't begin with /")
var/path = text2path(token(i))
if (path == null)
return parse_error("Nonexistant type path: [token(i)]")
node += path
return i + 1
//comparitor: '=' | '==' | '!=' | '<>' | '<' | '<=' | '>' | '>='
/datum/SDQL_parser/proc/comparitor(i, list/node)
if(token(i) in list("=", "==", "!=", "<>", "<", "<=", ">", ">="))
node += token(i)
else
parse_error("Unknown comparitor [token(i)]")
return i + 1
//bool_operator: 'AND' | '&&' | 'OR' | '||'
/datum/SDQL_parser/proc/bool_operator(i, list/node)
if(tokenl(i) in list("and", "or", "&&", "||"))
node += token(i)
else
parse_error("Unknown comparitor [token(i)]")
return i + 1
//string: ''' <some text> ''' | '"' <some text > '"'
/datum/SDQL_parser/proc/string(i, list/node)
if(copytext(token(i), 1, 2) in list("'", "\""))
node += token(i)
else
parse_error("Expected string but found '[token(i)]'")
return i + 1
//array: '[' expression, expression, ... ']'
/datum/SDQL_parser/proc/array(i, list/node)
/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) != "\[")
parse_error("Expected an array but found '[token(i)]'")
return i + 1
node += token(i)
node += token(i) // Add the "["
var/list/expression_list = list()
i++
if(token(i) != "]")
var/list/temp_expression_list = list()
var/tok
do
tok = token(i)
if(tok == "," || tok == ":")
if(temp_expression_list == null)
if (tok == "," || tok == ":")
if (temp_expression_list == null)
parse_error("Found ',' or ':' without expression in an array.")
return i + 1
expression_list[++expression_list.len] = temp_expression_list
temp_expression_list = null
if(tok == ":")
if (tok == ":")
temp_expression_list = list()
i = expression(i + 1, temp_expression_list)
expression_list[expression_list[expression_list.len]] = temp_expression_list
temp_expression_list = null
tok = token(i)
if(tok != ",")
if(tok == "]")
if (tok != ",")
if (tok == "]")
break
parse_error("Expected ',' or ']' after array assoc value, but found '[token(i)]'")
return i
i++
continue
temp_expression_list = list()
i = expression(i, temp_expression_list)
// Ok, what the fuck BYOND?
// Not having these lines here causes the parser to die
// on an error saying that list/token() doesn't exist as a proc.
// These lines prevent that.
// I assume the compiler/VM is shitting itself and swapping out some variables internally?
// While throwing in debug logging it disappeared
// And these 3 lines prevent it from happening while being quiet.
// So.. it works.
// Don't touch it.
var/whatthefuck = i
whatthefuck = src.type
whatthefuck = whatthefuck
while(token(i) && token(i) != "]")
if(temp_expression_list)
if (temp_expression_list)
expression_list[++expression_list.len] = temp_expression_list
node[++node.len] = expression_list
return i + 1
//object_type: <type path> | string
/datum/SDQL_parser/proc/object_type(i, list/node)
if(copytext(token(i), 1, 2) == "/")
node += token(i)
else
i = string(i, node)
return i + 1
//comparitor: '=' | '==' | '!=' | '<>' | '<' | '<=' | '>' | '>='
/datum/SDQL_parser/proc/comparitor(i, list/node)
if(token(i) in list("=", "==", "!=", "<>", "<", "<=", ">", ">="))
node += token(i)
else
parse_error("Unknown comparitor [token(i)]")
return i + 1
//bool_operator: 'AND' | '&&' | 'OR' | '||'
/datum/SDQL_parser/proc/bool_operator(i, list/node)
if(tokenl(i) in list("and", "or", "&&", "||"))
node += token(i)
else
parse_error("Unknown comparitor [token(i)]")
return i + 1
//string: ''' <some text> ''' | '"' <some text > '"'
/datum/SDQL_parser/proc/string(i, list/node)
if(copytext(token(i), 1, 2) in list("'", "\""))
node += token(i)
else
parse_error("Expected string 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)))
var/procname = ""
if(token(i) == "global" && token(i+1) == ".")
if(tokenl(i) == "global" && token(i + 1) == ".") // Global proc.
i += 2
procname = "global."
node += procname + token(i++)
if(token(i) != "(")
parse_error("Expected ( but found '[token(i)]'")
else if(token(i + 1) != ")")
var/list/expression_list_temp = list()
var/list/temp_expression_list = list()
do
i = expression(i + 1, expression_list_temp)
i = expression(i + 1, temp_expression_list)
if(token(i) == ",")
arguments[++arguments.len] = expression_list_temp
expression_list_temp = list()
arguments[++arguments.len] = temp_expression_list
temp_expression_list = list()
continue
while(token(i) && token(i) != ")")
arguments[++arguments.len] = expression_list_temp
arguments[++arguments.len] = temp_expression_list // The code this is copy pasted from won't be executed when it's the last param, this fixes that.
else
i++
else
parse_error("Expected a function but found nothing")
return i + 1
//select_function: count_function
/datum/SDQL_parser/proc/select_function(i, list/node)
parse_error("Sorry, function calls aren't available yet")
return i
//expression: ( unary_expression | '(' 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)
if(token(i) in binary_operators)
i = binary_operator(i, node)
i = expression(i, node)
else if(token(i) in comparitors)
i = binary_operator(i, node)
var/list/rhs = list()
i = expression(i, rhs)
node[++node.len] = rhs
return i
//unary_expression: unary_operator ( unary_expression | value | '(' expression ')' )
/datum/SDQL_parser/proc/unary_expression(i, list/node)
if(token(i) in unary_operators)
var/list/unary_exp = list()
unary_exp += token(i)
i++
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)
node[++node.len] = unary_exp
else
parse_error("Expected unary operator but found '[token(i)]'")
return i
//binary_operator: comparitor | '+' | '-' | '/' | '*' | '&' | '|' | '^'
//binary_operator: comparitor | '+' | '-' | '/' | '*' | '&' | '|' | '^' | '%'
/datum/SDQL_parser/proc/binary_operator(i, list/node)
if(token(i) in (binary_operators + comparitors))
node += token(i)
else
parse_error("Unknown binary operator [token(i)]")
return i + 1
//value: variable | string | number | 'null'
//value: variable | string | number | 'null' | object_type
/datum/SDQL_parser/proc/value(i, list/node)
if(token(i) == "null")
node += "null"
i++
else if(lowertext(copytext(token(i),1,3)) == "0x" && isnum(hex2num(copytext(token(i),3))))
node += hex2num(copytext(token(i),3))
else if(lowertext(copytext(token(i), 1, 3)) == "0x" && isnum(hex2num(copytext(token(i), 3))))
node += hex2num(copytext(token(i), 3))
i++
else if(isnum(text2num(token(i))))
node += text2num(token(i))
i++
else if(copytext(token(i), 1, 2) in list("'", "\""))
i = string(i, node)
else if(copytext(token(i), 1, 2) == "\[") // Start a list.
i = array(i, node)
else if(copytext(token(i), 1, 2) == "/")
i = object_type(i, node)
else
i = variable(i, node)
return i
/*EXPLAIN SELECT * WHERE 42 = 6 * 9 OR val = - 5 == 7*/
return i
@@ -48,6 +48,12 @@
/proc/_image(icon, loc, icon_state, layer, dir)
return image(icon, loc, icon_state, layer, dir)
/proc/_istype(object, type)
return istype(object, type)
/proc/_ispath(path, type)
return ispath(path, type)
/proc/_length(E)
return length(E)
@@ -208,4 +214,3 @@
/proc/_step_away(ref, trg, max)
step_away(ref, trg, max)
+6 -1
View File
@@ -564,7 +564,12 @@
GLOB.cameranet.stat_entry()
if(statpanel("Tickets"))
GLOB.ahelp_tickets.stat_entry()
if(length(GLOB.sdql2_queries))
if(statpanel("SDQL2"))
stat("Access Global SDQL2 List", GLOB.sdql2_vv_statobj)
for(var/i in GLOB.sdql2_queries)
var/datum/SDQL2_query/Q = i
Q.generate_stat()
if(listed_turf && client)
if(!TurfAdjacent(listed_turf))
listed_turf = null