Skip to content

Commit

Permalink
Merge pull request #7 from Patitotective/devel
Browse files Browse the repository at this point in the history
v1.2.4
  • Loading branch information
Patitotective authored Oct 25, 2023
2 parents 1cf932e + 0725fc8 commit 2183130
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 19 deletions.
2 changes: 1 addition & 1 deletion kdl.nimble
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Package

version = "1.2.3"
version = "1.2.4"
author = "Patitotective"
description = "KDL document language Nim implementation"
license = "MIT"
Expand Down
7 changes: 5 additions & 2 deletions src/kdl/nodes.nim
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ proc getInt*(val: KdlVal): int64 =
check val.isInt()
val.num

proc get*[T: SomeNumber or string or bool](val: KdlVal, x: typedesc[T]): T =
proc get*[T: Value](val: KdlVal, x: typedesc[T]): T =
## Tries to get and convert val to T, raises an error when it cannot.
runnableExamples:
let val = initKFloat(3.14)
Expand All @@ -88,6 +88,7 @@ proc get*[T: SomeNumber or string or bool](val: KdlVal, x: typedesc[T]): T =
assert val.get(uint) == 3u
assert val.get(float) == 3.14
assert val.get(float32) == 3.14f
assert val.get(range[0f..4f]) == 3.14f

when T is string:
result =
Expand All @@ -104,7 +105,7 @@ proc get*[T: SomeNumber or string or bool](val: KdlVal, x: typedesc[T]): T =
$val.getInt()
of KEmpty:
"empty"
elif T is SomeNumber:
elif T is SomeNumber or T is range:
check val.isFloat or val.isInt

result =
Expand All @@ -116,6 +117,8 @@ proc get*[T: SomeNumber or string or bool](val: KdlVal, x: typedesc[T]): T =
check val.isBool

result = val.getBool
else:
{.error: "get is not implemented for " & $typeof(T).}

# ----- Setters -----

Expand Down
40 changes: 25 additions & 15 deletions src/kdl/utils.nim
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ type

Object* = ((object or tuple) and not KdlSome)
List* = (array or seq)
Value* = (SomeNumber or string or bool)
Value* = (SomeNumber or string or bool or range)
KdlSome* = (KdlDoc or KdlNode or KdlVal)
SomeTable*[K, V] = (Table[K, V] or OrderedTable[K, V])

template fail*(msg: string) =
template fail*(msg: string) =
raise newException(KdlError, msg)

template check*(cond: untyped, msg = "") =
template check*(cond: untyped, msg = "") =
if not cond:
let txt = msg
fail astToStr(cond) & " failed" & (if txt.len > 0: ": " & txt else: "")
Expand Down Expand Up @@ -50,12 +50,12 @@ proc eqIdent*(v, a: openarray[char], ignoreChars = {'_', '-'}): bool = cmpIgnore

# ----- Streams -----

proc peekRune*(s: Stream): Rune =
proc peekRune*(s: Stream): Rune =
let str = s.peekStr(4)
if str.len > 0:
result = str.runeAt(0)

proc peekLineFromStart*(s: Stream): string =
proc peekLineFromStart*(s: Stream): string =
let before = s.getPosition()
while s.getPosition() > 0:
s.setPosition(s.getPosition() - 1)
Expand All @@ -69,7 +69,7 @@ proc peekLineFromStart*(s: Stream): string =
result = s.peekLine()
s.setPosition before

proc peekLineFromStart*(s: string, at: int): string =
proc peekLineFromStart*(s: string, at: int): string =
if at >= s.len:
return

Expand Down Expand Up @@ -112,7 +112,7 @@ proc getCoord*(s: string, at: int): Coord =

inc result.idx

proc errorAt*(s: Stream, coord: Coord): string =
proc errorAt*(s: Stream, coord: Coord): string =
let before = s.getPosition()
s.setPosition coord.idx
let line = s.peekLineFromStart()
Expand All @@ -122,7 +122,7 @@ proc errorAt*(s: Stream, coord: Coord): string =
result.add(&"{lineNum}{line}\n")
result.add(&"{repeat(' ', lineNum.len + coord.col)}^")

proc errorAt*(s: string, coord: Coord): string =
proc errorAt*(s: string, coord: Coord): string =
let line = s.peekLineFromStart(coord.idx)

let lineNum = &"{coord.line + 1} | "
Expand All @@ -131,16 +131,19 @@ proc errorAt*(s: string, coord: Coord): string =

# ----- Object variants -----

macro isObjVariant*(a: typedesc): bool =
macro isObjVariant*(a: typedesc): bool =
var a = a.getTypeImpl
doAssert a.kind == nnkBracketExpr
if a.kind != nnkBracketExpr:
return ident("false")

let sym = a[1]
let t = sym.getTypeImpl
if t.kind != nnkObjectTy:
return ident("false")

let t2 = t[2]
doAssert t2.kind == nnkRecList
if t2.kind != nnkRecList:
return ident("false")

result = ident("false")

Expand All @@ -155,24 +158,30 @@ macro getDiscriminants*(a: typedesc): seq[string] =
## return the discriminant keys
# candidate for std/typetraits
var a = a.getTypeImpl
doAssert a.kind == nnkBracketExpr
if a.kind != nnkBracketExpr:
return quote do:
newSeq[string]()

let sym = a[1]
let t = sym.getTypeImpl
if t.kind != nnkObjectTy:
return quote do:
newSeq[string]()

let t2 = t[2]
doAssert t2.kind == nnkRecList
if t2.kind != nnkRecList:
return quote do:
newSeq[string]()

result = newTree(nnkBracket)

for ti in t2:
if ti.kind == nnkRecCase:
let key = ti[0][0]
let typ = ti[0][1]
result.add newLit key.strVal
result =

result =
if result.len > 0:
quote do:
@`result`
Expand Down Expand Up @@ -214,3 +223,4 @@ macro initCaseObject*(T: typedesc, discriminatorSetter): untyped =
result.add newTree(nnkExprColonExpr, key, val)

template typeofdesc*[T](b: typedesc[T]): untyped = T

3 changes: 2 additions & 1 deletion tests/test_serializer.nim
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ type
MyObj2 = object
id*: int
name*: string
subrange*: range[0f..1f]

MyObj3 = object
id*: int
Expand Down Expand Up @@ -368,7 +369,7 @@ suite "Decoder":

test "newHook":
check parseKdl("").decode(DateTime) == dateTime(2000, mMar, 30)
check parseKdl("name \"otoboke\"").decode(MyObj2) == MyObj2(id: 5, name: "otoboke")
check parseKdl("name \"otoboke\"; subrange 0.6").decode(MyObj2) == MyObj2(id: 5, subrange: 0.6, name: "otoboke")

test "postHook":
check parseKdl("id 4").decode(MyObj3) == MyObj3(id: 5)
Expand Down

0 comments on commit 2183130

Please sign in to comment.