A fast implementation of the Nix expression language
Révision | 4127f061908401ed22b880862dfb62ba6be22fd7 (tree) |
---|---|
l'heure | 2024-05-25 11:28:14 |
Auteur | Corbin <cds@corb...> |
Commiter | Corbin |
regiux: Implement Booleans and if-expressions.
@@ -22,18 +22,21 @@ class HeapObject(object): | ||
22 | 22 | def getAttr(self, name): |
23 | 23 | raise WrongType("Heap object type %s doesn't have attributes" % |
24 | 24 | self.__class__.__name__) |
25 | + def unwrapBool(self): | |
26 | + raise WrongType("Heap object type %s isn't a Boolean" % | |
27 | + self.__class__.__name__) | |
25 | 28 | |
26 | -class MutableObject(HeapObject): | |
27 | - loop = False | |
28 | - cache = None | |
29 | - def evaluate(self): | |
30 | - if not self.cache: | |
31 | - if self.loop: raise InfiniteLoop() | |
32 | - try: | |
33 | - self.loop = True | |
34 | - self.cache = self.resolve() | |
35 | - finally: self.loop = False | |
36 | - return self.cache | |
29 | +class HeapTrue(HeapObject): | |
30 | + _immutable_ = True | |
31 | + def asStr(self): return "true" | |
32 | + def unwrapBool(self): return True | |
33 | +true = HeapTrue() | |
34 | + | |
35 | +class HeapFalse(HeapObject): | |
36 | + _immutable_ = True | |
37 | + def asStr(self): return "false" | |
38 | + def unwrapBool(self): return False | |
39 | +false = HeapFalse() | |
37 | 40 | |
38 | 41 | class HeapInt(HeapObject): |
39 | 42 | _immutable_ = True |
@@ -49,11 +52,34 @@ class HeapStr(HeapObject): | ||
49 | 52 | |
50 | 53 | class InfiniteLoop(Exception): pass |
51 | 54 | |
55 | +class MutableObject(HeapObject): | |
56 | + loop = False | |
57 | + cache = None | |
58 | + def evaluate(self): | |
59 | + if not self.cache: | |
60 | + if self.loop: raise InfiniteLoop() | |
61 | + try: | |
62 | + self.loop = True | |
63 | + self.cache = self.resolve() | |
64 | + finally: self.loop = False | |
65 | + return self.cache | |
66 | + | |
52 | 67 | # XXX currently unused, but ready to go |
53 | 68 | # class HeapThunk(MutableObject): |
54 | 69 | # def __init__(self, obj): self.obj = obj |
55 | 70 | # def resolve(self): return self.obj |
56 | 71 | |
72 | +class HeapCond(MutableObject): | |
73 | + def __init__(self, b, cons, alt): | |
74 | + self.b = b | |
75 | + self.cons = cons | |
76 | + self.alt = alt | |
77 | + def asStr(self): | |
78 | + return "if %s then %s else %s" % (self.b.asStr(), self.cons.asStr(), self.alt.asStr()) | |
79 | + def resolve(self): | |
80 | + rv = self.cons if self.b.unwrapBool() else self.alt | |
81 | + return rv.evaluate() | |
82 | + | |
57 | 83 | class HeapAttrSet(MutableObject): |
58 | 84 | def __init__(self, attrs): self.attrs = attrs |
59 | 85 | def asStr(self): |
@@ -106,4 +132,5 @@ builtins = HeapAttrSet({ | ||
106 | 132 | |
107 | 133 | defaultScope = { |
108 | 134 | "builtins": builtins, |
135 | + "false": false, "true": true, | |
109 | 136 | } |
@@ -90,6 +90,18 @@ class StrBox(EBox): | ||
90 | 90 | def pretty(self): return '"%s"' % self.value |
91 | 91 | def compile(self, scope): return heap.HeapStr(self.value) |
92 | 92 | |
93 | +class IfBox(EBox): | |
94 | + def __init__(self, cond, seq, alt): | |
95 | + self.cond = cond | |
96 | + self.seq = seq | |
97 | + self.alt = alt | |
98 | + def pretty(self): | |
99 | + return "if %s then %s else %s" % ( | |
100 | + self.cond.pretty(), self.seq.pretty(), self.alt.pretty()) | |
101 | + def compile(self, scope): | |
102 | + return heap.HeapCond(self.cond.compile(scope), self.seq.compile(scope), | |
103 | + self.alt.compile(scope)) | |
104 | + | |
93 | 105 | class BindsBox(EBox): |
94 | 106 | def __init__(self, binds): self.binds = binds |
95 | 107 | def pretty(self): |
@@ -249,15 +261,6 @@ class LambdaBox(BaseBox): | ||
249 | 261 | elif self.params: return "%s: %s" % (self.params.pretty(), body) |
250 | 262 | else: return "_: " + body |
251 | 263 | |
252 | -class IfBox(BaseBox): | |
253 | - def __init__(self, cond, seq, alt): | |
254 | - self.cond = cond | |
255 | - self.seq = seq | |
256 | - self.alt = alt | |
257 | - def pretty(self): | |
258 | - return "if %s then %s else %s" % ( | |
259 | - self.cond.pretty(), self.seq.pretty(), self.alt.pretty()) | |
260 | - | |
261 | 264 | pg = rply.ParserGenerator(KEYWORDS + [ |
262 | 265 | "ID", "INT", "SPATH", "URI", |
263 | 266 | "AND", "IMPL", "OR_OP", |