rule.bend

bend-osdev-apparmor@0.1.0.0 · 151 lines · 18 definitions

1# bend-osdev-apparmor: what the rule kinds share when they read their terms:
2# patterns from words, strings and conditions, and checked name lists.
3import Base
4import bend-osdev-apparmor@0.1.0.0/text.bend as X
5import bend-osdev-apparmor@0.1.0.0/glob.bend as G
6import bend-osdev-apparmor@0.1.0.0/token.bend as T
7import bend-osdev-apparmor@0.1.0.0/error.bend as E
8import bend-osdev-apparmor@0.1.0.0/perm.bend as P
9
10def AaRule.of_maybe(m: Maybe<&2, G.AaGlob>, e: E.AaError) -> Result<&2, &2, E.AaError, G.AaGlob>:
11  match m:
12    case None{}:
13      Fail{e}
14    case Some{g}:
15      Done{g}
16
17# the pattern written as xs
18def AaRule.glob_text(xs: List<&2, U32>, src: E.AaSrc) -> Result<&2, &2, E.AaError, G.AaGlob>:
19  AaRule.of_maybe(G.AaGlob.parse(xs), E.AaSrc.glob(src))
20
21def AaRule.glob.go(m: Maybe<&2, List<&2, U32>>, +src: E.AaSrc) -> Result<&2, &2, E.AaError, G.AaGlob>:
22  match m:
23    case None{}:
24      Fail{E.AaSrc.syntax(src)}
25    case Some{xs}:
26      AaRule.glob_text(xs, src)
27
28# the pattern a word or quoted string writes
29def AaRule.glob(t: T.AaTerm, src: E.AaSrc) -> Result<&2, &2, E.AaError, G.AaGlob>:
30  AaRule.glob.go(T.AaTerm.text(t), src)
31
32def AaRule.one.go(xs: List<&2, T.AaTerm>, +src: E.AaSrc) -> Result<&2, &2, E.AaError, G.AaGlob>:
33  match xs:
34    case Nil{}:
35      Fail{E.AaSrc.syntax(src)}
36    case Con{x, rest}:
37      match rest:
38        case Nil{}:
39          AaRule.glob(x, src)
40        case Con{y, more}:
41          Fail{E.AaSrc.syntax(src)}
42
43# the pattern of a condition's value: a word, a quoted string, or one of
44# them in parentheses
45def AaRule.value_glob(v: T.AaTerm, +src: E.AaSrc) -> Result<&2, &2, E.AaError, G.AaGlob>:
46  match v:
47    case T.AaTmWord{w}:
48      AaRule.glob_text(w, src)
49    case T.AaTmQuoted{q}:
50      AaRule.glob_text(q, src)
51    case T.AaTmList{xs}:
52      AaRule.one.go(xs, src)
53    case T.AaTmCond{k, x}:
54      Fail{E.AaSrc.syntax(src)}
55    case T.AaTmArrow{}:
56      Fail{E.AaSrc.syntax(src)}
57
58# the patterns of a value: one, or a parenthesised list
59def AaRule.value_globs.go(xs: List<&2, List<&2, U32>>, +src: E.AaSrc) -> Result<&2, &2, E.AaError, List<&2, G.AaGlob>>:
60  match xs:
61    case Nil{}:
62      Done{Nil{}}
63    case Con{x, rest}:
64      do Result<&2, &2, E.AaError, List<&2, G.AaGlob>>:
65        g : G.AaGlob <- AaRule.glob_text(x, src)
66        gs : List<&2, G.AaGlob> <- AaRule.value_globs.go(rest, src)
67        return Con{g, gs}
68
69def AaRule.texts(m: Maybe<&2, List<&2, List<&2, U32>>>, src: E.AaSrc) -> Result<&2, &2, E.AaError, List<&2, List<&2, U32>>>:
70  match m:
71    case None{}:
72      Fail{E.AaSrc.syntax(src)}
73    case Some{xs}:
74      Done{xs}
75
76def AaRule.value_globs(v: T.AaTerm, +src: E.AaSrc) -> Result<&2, &2, E.AaError, List<&2, G.AaGlob>>:
77  do Result<&2, &2, E.AaError, List<&2, G.AaGlob>>:
78    xs : List<&2, List<&2, U32>> <- AaRule.texts(T.AaTerm.texts(v), src)
79    AaRule.value_globs.go(xs, src)
80
81# the names of a value, each one of the allowed names
82def AaRule.check_names.go(hit: Bool, x: List<&2, U32>, r: Result<&2, &2, E.AaError, List<&2, List<&2, U32>>>, src: E.AaSrc) -> Result<&2, &2, E.AaError, List<&2, List<&2, U32>>>:
83  match hit:
84    case False{}:
85      Fail{E.AaSrc.name(src)}
86    case True{}:
87      match r:
88        case Fail{e}:
89          Fail{e}
90        case Done{xs}:
91          Done{Con{x, xs}}
92
93def AaRule.check_names(xs: List<&2, List<&2, U32>>, +ok: List<&2, String>, +src: E.AaSrc) -> Result<&2, &2, E.AaError, List<&2, List<&2, U32>>>:
94  match xs:
95    case Nil{}:
96      Done{Nil{}}
97    case Con{+x, rest}:
98      AaRule.check_names.go(X.AaText.one_of(ok, x), x, AaRule.check_names(rest, ok, src), src)
99
100def AaRule.names(v: T.AaTerm, +ok: List<&2, String>, +src: E.AaSrc) -> Result<&2, &2, E.AaError, List<&2, List<&2, U32>>>:
101  do Result<&2, &2, E.AaError, List<&2, List<&2, U32>>>:
102    xs : List<&2, List<&2, U32>> <- AaRule.texts(T.AaTerm.texts(v), src)
103    AaRule.check_names(xs, ok, src)
104
105# Matching helpers
106
107def AaRule.opt_match(m: Maybe<&2, G.AaGlob>, +s: List<&2, U32>) -> Bool:
108  match m:
109    case None{}:
110      True{}
111    case Some{g}:
112      G.AaGlob.matches(g, s)
113
114# some pattern of the list matches s
115def AaRule.any_match(gs: List<&2, G.AaGlob>, +s: List<&2, U32>) -> Bool:
116  match gs:
117    case Nil{}:
118      False{}
119    case Con{g, t}:
120      Bool.or(G.AaGlob.matches(g, s), AaRule.any_match(t, s))
121
122def AaRule.opt_any(m: Maybe<&2, List<&2, G.AaGlob>>, +s: List<&2, U32>) -> Bool:
123  match m:
124    case None{}:
125      True{}
126    case Some{gs}:
127      AaRule.any_match(gs, s)
128
129def AaRule.glob_append(xs: List<&2, G.AaGlob>, ys: List<&2, G.AaGlob>) -> List<&2, G.AaGlob>:
130  match xs:
131    case Nil{}:
132      ys
133    case Con{h, t}:
134      Con{h, AaRule.glob_append(t, ys)}
135
136def AaRule.add_globs(m: Maybe<&2, List<&2, G.AaGlob>>, gs: List<&2, G.AaGlob>) -> Maybe<&2, List<&2, G.AaGlob>>:
137  match m:
138    case None{}:
139      Some{gs}
140    case Some{hs}:
141      Some{AaRule.glob_append(hs, gs)}
142
143# the qualifiers of a rule kind that does not take owner
144def AaRule.no_owner(q: P.AaQual, src: E.AaSrc) -> Result<&2, &2, E.AaError, P.AaQual>:
145  match q:
146    case P.AaQual{a, d, o}:
147      match o:
148        case True{}:
149          Fail{E.AaSrc.syntax(src)}
150        case False{}:
151          Done{P.AaQual{a, d, False{}}}