diff --git a/lib/std/system.nim b/lib/std/system.nim index bdab856d..179c0518 100644 --- a/lib/std/system.nim +++ b/lib/std/system.nim @@ -273,6 +273,8 @@ proc `==`*(x, y: char): bool {.magic: "EqCh", noSideEffect.} ## Checks for equality between two `char` variables. proc `==`*(x, y: bool): bool {.magic: "EqB", noSideEffect.} ## Checks for equality between two `bool` variables. +proc `==`*[T](x, y: set[T]): bool {.magic: "EqSet", noSideEffect.} + ## Checks for equality between two variables of type `set`. proc `==`*[T](x, y: ref T): bool {.magic: "EqRef", noSideEffect.} ## Checks that two `ref` variables refer to the same item. @@ -288,6 +290,12 @@ proc `<=`*(x, y: char): bool {.magic: "LeCh", noSideEffect.} ## Compares two chars and returns true if `x` is lexicographically ## before `y` (uppercase letters come before lowercase letters). +proc `<=`*[T](x, y: set[T]): bool {.magic: "LeSet", noSideEffect.} + ## Returns true if `x` is a subset of `y`. + ## + ## A subset `x` has all of its members in `y` and `y` doesn't necessarily + ## have more members than `x`. That is, `x` can be equal to `y`. + proc `<=`*(x, y: bool): bool {.magic: "LeB", noSideEffect.} proc `<=`*[T](x, y: ref T): bool {.magic: "LePtr", noSideEffect.} proc `<=`*(x, y: pointer): bool {.magic: "LePtr", noSideEffect.} @@ -301,6 +309,12 @@ proc `<`*(x, y: char): bool {.magic: "LtCh", noSideEffect.} ## Compares two chars and returns true if `x` is lexicographically ## before `y` (uppercase letters come before lowercase letters). +proc `<`*[T](x, y: set[T]): bool {.magic: "LtSet", noSideEffect.} + ## Returns true if `x` is a strict or proper subset of `y`. + ## + ## A strict or proper subset `x` has all of its members in `y` but `y` has + ## more elements than `y`. + proc `==`*(x, y: int8): bool {.magic: "EqI", noSideEffect.} proc `==`*(x, y: int16): bool {.magic: "EqI", noSideEffect.} proc `==`*(x, y: int32): bool {.magic: "EqI", noSideEffect.} diff --git a/src/hexer/desugar.nim b/src/hexer/desugar.nim new file mode 100644 index 00000000..1c2961be --- /dev/null +++ b/src/hexer/desugar.nim @@ -0,0 +1,449 @@ +# removes abstractions like set ops and ref object constructors + +import std / [assertions] +include nifprelude +import ".." / nimony / [nimony_model, decls, programs, typenav, sizeof, expreval, xints] +import basics + +type + Context = object + counter: int + typeCache: TypeCache + thisModuleSuffix: string + tempUseBufStack: seq[TokenBuf] + +proc declareTemp(c: var Context; dest: var TokenBuf; typ: Cursor; info: PackedLineInfo): SymId = + let s = "`desugar." & $c.counter & "." & c.thisModuleSuffix + inc c.counter + result = pool.syms.getOrIncl(s) + copyIntoKind dest, VarS, info: + dest.addSymDef result, info + dest.addDotToken() # export, pragmas + dest.addDotToken() + copyTree dest, typ # type + dest.addDotToken() # value + +proc needsTemp(n: Cursor): bool = + case n.kind + of Symbol, IntLit, UIntLit, FloatLit, CharLit, StringLit: + result = false + of ParLe: + var n = n + case n.exprKind + of NilX, FalseX, TrueX, InfX, NegInfX, NanX, SizeofX: + result = false + of ExprX: + inc n + let first = n + skip n + if n.kind == ParRi: + # single element expr + result = needsTemp(first) + else: + result = true + of SufX: + inc n + result = needsTemp(n) + of DconvX: + inc n + skip n + result = needsTemp(n) + of AtX, PatX, ArrAtX, TupAtX, DotX, DerefDotX, ParX, AddrX, HaddrX: + inc n + while n.kind != ParRi: + if needsTemp(n): + return true + skip n + result = false + else: + result = true + else: + result = true + +proc skipParRi(n: var Cursor) = + if n.kind == ParRi: + inc n + else: + error "expected ')', but got: ", n + +proc tr(c: var Context; dest: var TokenBuf; n: var Cursor) + +proc trSons(c: var Context; dest: var TokenBuf; n: var Cursor) = + copyInto dest, n: + while n.kind != ParRi: + tr(c, dest, n) + +proc trLocal(c: var Context; dest: var TokenBuf; n: var Cursor) = + copyInto dest, n: + let name = n.symId + takeTree dest, n # name + takeTree dest, n # export marker + takeTree dest, n # pragmas + c.typeCache.registerLocal(name, n) + takeTree dest, n # type + tr(c, dest, n) + +proc trProc(c: var Context; dest: var TokenBuf; n: var Cursor) = + c.typeCache.openScope() + copyInto dest, n: + let sym = n.symId + for i in 0.. result.hi: result.hi = x @@ -311,6 +313,7 @@ proc evalBitSet*(n, typ: Cursor): seq[uint8] = return @[] result = newSeq[uint8](s) var n = n + inc n # skip set tag while n.kind != ParRi: if n.exprKind == RangeX: inc n diff --git a/tests/nimony/sysbasics/tforloops1.nif b/tests/nimony/sysbasics/tforloops1.nif index cce3a772..e85754d4 100644 --- a/tests/nimony/sysbasics/tforloops1.nif +++ b/tests/nimony/sysbasics/tforloops1.nif @@ -76,7 +76,7 @@ (hconv 11,~16 (cstring) "countup start\3A %ld\0A") 25 m.1) ,2 (if 3 - (elif 11,758,lib/std/system.nim + (elif 11,786,lib/std/system.nim (expr 2,1 (lt (i -1) 9,26,tests/nimony/sysbasics/tforloops1.nim +5 5,26,tests/nimony/sysbasics/tforloops1.nim x.0)) ~1,1 diff --git a/tests/nimony/sysbasics/tsets.nim b/tests/nimony/sysbasics/tsets.nim new file mode 100644 index 00000000..a746e4d9 --- /dev/null +++ b/tests/nimony/sysbasics/tsets.nim @@ -0,0 +1,13 @@ +type Foo = enum + A, B, C, D, E, F + +var s, s1: set[Foo] +s = {A..D} +s1 = {A..C} +discard s1 < s +let y = s1 * s +let z: set[Foo] = y +discard y == {A..C} +discard z == {A..C} +discard s - s1 == {D} +discard s1 <= s