-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathast8.rego
96 lines (79 loc) · 2.35 KB
/
ast8.rego
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
package regal.ast
import future.keywords.contains
import future.keywords.every
import future.keywords.if
import future.keywords.in
_find_nested_vars(obj) := [var |
walk(obj, [_, value])
value.type == "var"
indexof(value.value, "$") == -1
var := value
]
# simple assignment, i.e. `x := 100` returns `x`
# always returns a single var, but wrapped in an
# array for consistency
_find_assign_vars(path, value) := var if {
value[1].type == "var"
var := [value[1]]
}
# 'destructuring' array assignment, i.e.
# [a, b, c] := [1, 2, 3]
# or
# {a: b} := {"foo": "bar"}
_find_assign_vars(path, value) := var if {
value[1].type in {"array", "object"}
var := _find_nested_vars(value[1])
}
# var declared via `some`, i.e. `some x` or `some x, y`
_find_some_decl_vars(path, value) := [v |
some v in value
v.type == "var"
]
# single var declared via `some in`, i.e. `some x in y`
_find_some_in_decl_vars(path, value) := var if {
arr := value[0].value
count(arr) == 3
var := _find_nested_vars(arr[1])
}
# two vars declared via `some in`, i.e. `some x, y in z`
_find_some_in_decl_vars(path, value) := var if {
arr := value[0].value
count(arr) == 4
var := [v |
some i in [1, 2]
some v in _find_nested_vars(arr[i])
]
}
# one or two vars declared via `every`, i.e. `every x in y {}`
# or `every`, i.e. `every x, y in y {}`
_find_every_vars(path, value) := var if {
key_var := [v | v := value.key; v.type == "var"; indexof(v.value, "$") == -1]
val_var := [v | v := value.value; v.type == "var"; indexof(v.value, "$") == -1]
var := array.concat(key_var, val_var)
}
_find_vars(path, value, last) := _find_assign_vars(path, value) if {
last == "terms"
value[0].type == "ref"
value[0].value[0].type == "var"
value[0].value[0].value == "assign"
}
_find_vars(path, value, last) := _find_some_in_decl_vars(path, value) if {
last == "symbols"
value[0].type == "call"
}
_find_vars(path, value, last) := _find_some_decl_vars(path, value) if {
last == "symbols"
value[0].type != "call"
}
_find_vars(path, value, last) := _find_every_vars(path, value) if {
last == "terms"
value.domain
}
# METADATA
# description: |
# traverses all nodes under provided path (using `walk`), and returns an array with
# all variables declared via assignment (:=), `some` or `every`
find_vars(path) := [var |
walk(path, [_path, _value])
some var in _find_vars(_path, _value, _path[count(_path) - 1])
]