Skip to content

Commit e7dc99d

Browse files
authored
implements const set union (#1194)
This is required to compile `src/lib/nifreader.nim` with Nimony.
1 parent fb1db3b commit e7dc99d

File tree

2 files changed

+79
-0
lines changed

2 files changed

+79
-0
lines changed

src/nimony/expreval.nim

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,74 @@ template evalBinOp(c: var EvalContext; n: var Cursor; opr: untyped) {.dirty.} =
225225
else:
226226
evalOrdBinOp(c, n, opr)
227227

228+
proc intToToken(result: var TokenBuf; x: int; typ: Cursor) =
229+
case typ.typeKind
230+
of IT:
231+
result.addIntLit x
232+
of UT:
233+
result.addUIntLit uint x
234+
of CT:
235+
result.add charToken(char x, NoLineInfo)
236+
else:
237+
assert false, "Got unexpected type: " & toString(typ)
238+
239+
proc bitSetToTokens(result: var TokenBuf; x: seq[uint8]; elementTyp: Cursor; info: PackedLineInfo) =
240+
result.addParLe SetConstrX, info
241+
result.buildTree TagId(SetT), NoLineInfo:
242+
result.addSubtree elementTyp
243+
244+
var start = -1
245+
for i in 0 ..< x.len:
246+
for j in 0..7:
247+
let val = i * 8 + j
248+
if (x[i] and (1'u8 shl j)) == 0:
249+
if start != -1:
250+
if val - start < 5:
251+
for k in start ..< val:
252+
result.intToToken k, elementTyp
253+
else:
254+
result.addParLe RangeU
255+
result.intToToken start, elementTyp
256+
result.intToToken (val - 1), elementTyp
257+
result.addParRi
258+
start = -1
259+
else:
260+
if start == -1:
261+
start = val
262+
263+
result.addParRi
264+
265+
proc evalBitSet*(n, typ: Cursor): seq[uint8]
266+
267+
proc evalPlusSet(c: var EvalContext; n: var Cursor): Cursor =
268+
let info = n.info
269+
inc n # tag
270+
assert n.typeKind == SetT
271+
var elementTyp = n
272+
inc elementTyp
273+
skip n # skip type
274+
var a = eval(c, n)
275+
var b = eval(c, n)
276+
skipParRi n # skip last parRi
277+
assert a.exprKind == SetConstrX, "got " & toString(a)
278+
assert b.exprKind == SetConstrX, "got " & toString(b)
279+
var typeA = a
280+
inc typeA
281+
var typeB = b
282+
inc typeB
283+
assert sameTrees(typeA, typeB) # must be the same type
284+
let setA = evalBitSet(a, typeA)
285+
let setB = evalBitSet(b, typeB)
286+
assert setA.len == setB.len
287+
var setRes = newSeq[uint8](setA.len)
288+
for i in 0 ..< setA.len:
289+
setRes[i] = setA[i] or setB[i]
290+
291+
let valPos = c.values.len
292+
c.values.add createTokenBuf()
293+
c.values[valPos].bitSetToTokens(setRes, elementTyp, info)
294+
result = cursorAt(c.values[valPos], 0)
295+
228296
proc eval*(c: var EvalContext; n: var Cursor): Cursor =
229297
template propagateError(r: Cursor): Cursor =
230298
let val = r
@@ -408,6 +476,8 @@ proc eval*(c: var EvalContext; n: var Cursor): Cursor =
408476
of CallKinds:
409477
result = evalCall(c, n)
410478
skip n
479+
of PlusSetX:
480+
result = evalPlusSet(c, n)
411481
else:
412482
if n.tagId == ErrT:
413483
result = n

tests/nimony/const/tconstset.nim

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,17 @@
11
import std/assertions
22

3+
const a = {'a', 'b'}
4+
const b = {'0', '1'} + {'8', '9'}
5+
assert b == {'0', '1', '8', '9'}
6+
7+
const c = a + {'x'}
8+
assert c == {'a', 'b', 'x'}
9+
310
const d = {'a'..'c'}
411
assert d == {'a', 'b', 'c'}
512
const e = {'0'..'3', '6'..'9', '3'..'7'}
613
assert e == {'0'..'9'}
714
const f = {5'i8..8, 9'i8..10}
815
assert f == {5'i8, 6, 7, 8, 9, 10}
16+
const g = {1'i8..3} + {5'i8..8} + {10'i8..14'i8}
17+
assert g == {1'i8, 2, 3, 5, 6, 7, 8, 10, 11, 12, 13, 14}

0 commit comments

Comments
 (0)