Re: Getting fields of an object type at compile time?
You might want something like this: import macros type Foo = object a: int b: string macro getFields(x: typed): untyped = let impl = getImpl(x) let objFields = impl[2][2] # 2 is nnkObjectTy, 2 2 is nnkRecList expectKind objFields, nnkRecList result = nnkBracket.newTree() for f in objFields: expectKind f, nnkIdentDefs result.add nnkPar.newTree(newLit f[0].strVal, newLit f[1].strVal) for (fieldName, typeName) in getFields(Foo): echo "Field: ", fieldName, " with type name ", typeName Run It returns a bracket of (field name, type name) tuples. Both as strings, since you can't mix strings with types in a tuple. For more complicated objects you'd have to recurse on the fields with complex types of course.
Re: Getting fields of an object type at compile time?
https://nim-lang.github.io/Nim/iterators.html#fieldPairs.i%2CT
Re: Getting fields of an object type at compile time?
@SolitudeSF \-- My understanding is `fieldPairs` only works on instances of a type, not on the`` typedesc`` itself. `fieldPairs(Foo)` yields a type mismatch.
Re: Getting memory address of object into string
Thanks a lot! This worked beautifully: fmt"{cast[int](addr(OBJ)):#x}" Run
Re: Getting memory address of object into string
Note that it's fine to use them for logging or debugging but otherwise the GC can and will move those ref addresses in memory for cycle detection purposes if you have a cyclic type (unless you compile with pure refcounting with no cycle detection or you tag your cyclic type acyclic).
Re: Getting memory address of object into string
I sometimes use $cast[int](addr(x)). If you like it hex just transform the integer into a hex string...
Re: Getting memory address of object into string
I still have issues... I have some ref objects and trying to get the hex address of the objects using repr(addr(x)) but when trying to echo the value the output is ... whitespace(!). Is it possible that it has sth to do with my configuration and/or compilation options? I cannot explain it otherwise...
Re: Getting memory address of object into string
echo obj.addr.repr Or repr(obj.addr) Or repr(addr(obj)) Or similar
Re: Getting Unix-Style file permissions
go does the translation too, [https://golang.org/src/os/types.go?s=2790:2823#L55](https://golang.org/src/os/types.go?s=2790:2823#L55) 65 func (m FileMode) String() string { 66 const str = "dalTLDpSugct?" 67 var buf [32]byte // Mode is uint32. 68 w := 0 69 for i, c := range str { 70 if m&(1<
Re: Getting Unix-Style file permissions
Ok, I'm getting the idea that there is no way to retrieve the permissions string as it is seen in "ls -l" without doing some processing on it. I recently wrote a program in Go and I was able to get it via file.Mode() from the os module, so I thought it would be the same in Nim. I'll try the ideas above. Thank you all for your help.
Re: Getting Unix-Style file permissions
It may also depend on how "standard" the desired string is whether @jasper's solution is enough for @cnuzzi. Usually, the setuid, setgid, sticky bits have some `'s'` or `'t'` substitutions for the `'x'`, and capitialized `[ST]` if one of those bits is set but the corresponding execute permission is missing. I think Unix standardization efforts were disintegrating by the time they were getting around to this level of the userspace utilities. So, @jasper may need to use something like this (from [https://github.com/c-blake/lc/blob/master/lc.nim](https://github.com/c-blake/lc/blob/master/lc.nim) search for `proc fmtPerm`): import posix proc fmtPerm*(m: Mode, s=""): string = ## Call with ``.st_mode`` of some ``Stat`` to get rwxr-x..; ``s`` is optional ## separator string such as a space or a comma to enhance readabilty. let m = m.uint and 4095 const rwx = ["---", "--x", "-w-", "-wx", "r--", "r-x", "rw-", "rwx" ] result = rwx[(m shr 6) and 7] & s & rwx[(m shr 3) and 7] & s & rwx[m and 7] let o = s.len if (m and 0o4000) != 0 and (m and 0o100) != 0: result[2] = 's' #setuid,+x if (m and 0o4000) != 0 and (m and 0o100) == 0: result[2] = 'S' #setuid,noX if (m and 0o2000) != 0 and (m and 0o010) != 0: result[5+o] = 's' #setgid,+x if (m and 0o2000) != 0 and (m and 0o010) == 0: result[5+o] = 'S' #setgid,noX if (m and 0o1000) != 0 and (m and 0o001) != 0: result[8+o] = 't' #sticky,+x if (m and 0o1000) != 0 and (m and 0o001) == 0: result[8+o] = 'T' #sticky,noX Run I didn't see any direct code to do this formatting in `posix`, but you surely would `import posix` to get `Mode`. That code just uses the raw low 12 bits, but those are actually pretty standard.
Re: Getting Unix-Style file permissions
Or use the posix.nim module for this.
Re: Getting Unix-Style file permissions
Just check that set for each permission and add the corresponding character, it should map 1-1. proc posixRepr(file: string): string = let info = getFileInfo(file, followSymlink = false) result.add([pcFile: '-', 'l', pcDir: 'd', 'l'][info.kind]) for i, fp in [fpUserRead, fpUserWrite, fpUserExec, fpGroupRead, fpGroupWrite, fpGroupExec, fpOthersRead, fpOthersWrite, fpOthersExec]: result.add(if fp in info.permissions: "rwx"[i mod 3] else: '-') Run
Re: Getting a strange error with file streams
Also watch out, you use `test` and `result` inconsistently. (There is no need for `test`.)
Re: Getting a strange error with file streams
Ah, I'm an idiot. Thank you.
Re: Getting a strange error with file streams
Compiler message is very clear. There is only proc setPosition(s: Stream; pos: int) which takes an non optional int as second parameter. So call file.setPosition() is invalid. I have no idea what you wants to do exactly, maybe you assume that there is a default parameter to setPosition()? There is none in this case, so maybe use file.setPosition(0). See [https://nim-lang.org/docs/lib.html](https://nim-lang.org/docs/lib.html)
Re: Getting OrderedTable key/value pair by insertion order
We're still waiting for your B-Trees implementation to have SortedTable in the standard lib ;)
Re: Getting OrderedTable key/value pair by insertion order
> So indeed iterating over the keys and stopping after first one makes sense, I > think there is no function to retrieve the first added element. And I think I > can remember someone asking how to get the n-th. added element, conclusion > was to use a loop similar as you do. Thanks, Stefan. I'd though I was just being silly and missing something obvious. Good to know this is a reasonable solution. > use > > > iterator pairs[A, B](t: OrderedTable[A, B]): (A, B) > > > Run > > and break-out after first (does "... in insertion order." kind of implies > FIFO?) element. Hi, lucian. That's what I did in the code sample I provided, but I used the `keys` iterator instead of `pairs`.
Re: Getting OrderedTable key/value pair by insertion order
Ok, yeah, we have no api for that.
Re: Getting OrderedTable key/value pair by insertion order
use iterator pairs[A, B](t: OrderedTable[A, B]): (A, B) Run and break-out after first (does "... in insertion order." kind of implies FIFO?) element.
Re: Getting OrderedTable key/value pair by insertion order
I'm not trying to get sorted items, just the first item added (hence why I used an OrderedTable).
Re: Getting OrderedTable key/value pair by insertion order
>From your last code sample, I think I understand that you want to retrieve the >table entry, that was added first to table. So indeed iterating over the keys >and stopping after first one makes sense, I think there is no function to >retrieve the first added element. And I think I can remember someone asking >how to get the n-th. added element, conclusion was to use a loop similar as >you do.
Re: Getting OrderedTable key/value pair by insertion order
I don't understand the question: An OrderedTable keeps the insertion order, it's not a "SortedTable" (which the stdlib still lacks)
Re: Getting rid of{.locks: .}
When assigning functions to a variable I strongly suggest you to force the nimcall or closure convention like this: var fn0 = proc (x: int): void {.nimcall.} = echo(x) Run Similar to [https://github.com/nim-lang/Nim/issues/2614](https://github.com/nim-lang/Nim/issues/2614) I agree, that's a big weakness of Nim higher order functions.
Re: Getting rid of{.locks: .}
Sorry, I can't because I restructured my code yesterday. I tried to create an example today based on my memory but it passed the compiler. I'm pretty sure that I used the exact same parameter list for all cases. When I run into a new sample I will try to post it here.
Re: Getting rid of{.locks: .}
You can ignore `{.locks.}` pragma. It's only important when you use the `locks` module and/or the [guard system](https://nim-lang.github.io/Nim/manual_experimental.html#guards-and-locks). It's one of the most misleading thing in the error message, where it bears zero significance. Same as with the `{.closure.}` pragma, a lot of times it's not the problem, but the differences in proc signature (param list) is. Can you provide a reproducible sample of your erroring code?
Re: Getting rid of{.locks: .}
And now the closure thing: ... gn.nim(93, 20) Error: type mismatch: got ... but expected one of: ... proc (...){.closure.} Run The parameter looks like this: p: ProcType where ProcType is: type ProcType = proc(a: int, ...): void Run This doesn't make any sense.
Re: Getting CommentStmt from TypeDef AST
Wonder game play this online [http://gta5moneyonline.net](http://gta5moneyonline.net)
Re: Getting printable variable identifier
The delayed answers may indicate that it is hard to see what you really intent. Of course there is no special id field present for all data types in Nim -- for a plain int with bytesize 4 or 8 that field would double storage consumption and decrease computing performance. For real objects we may have used an id field, but why should one. And for your custom objects you can add whatever field you desire. Note that in computers nearly all instances of data types have addresses in memory, so you may use them for your is: proc main = var a: int var b: ref int = new int echo cast[int](a.addr) echo cast[int](b.addr) main() Run
Re: Getting the original type of an 'upcasted' object
Thanks for pointing me to that thread, that explains some of the details I did not yet grasp. For now I'm good with a bit of redesign: I store a ref to object with some proc pointers for that specific type in each node. If this is solvable with a macro I can save a pointer per object though, which would be nice.
Re: Getting the original type of an 'upcasted' object
That is indeed too difficult for me to answer. Mr Felsing once suggested to use a proc in combination with methods to solve a similar issue, see [https://forum.nim-lang.org/t/3128](https://forum.nim-lang.org/t/3128) I hope some of the smart devs can answer your question -- maybe after the holidays.
Re: Getting the original type of an 'upcasted' object
Here's an extract of my code. My issue is with the `proc `$`(s: SNodeAny): string =` function. Basically, it is just a long list of `if` statements (could be a `case` as well, doesn't matter) to check if the object is of some type, and then apply the `$` operator on the casted type. I feel this could be replaced by a two line macro or template, but for this I need to be able to deduce the original type of the passed SNode before I can cast and apply the `$` operator. My real code now includes 4 of these kind of functions where I need to check for every possible node kind, cast it, and apply some kind of generic function to it. import strutils type IPv4Address = distinct string IPv6Address = distinct string MacAddress = distinct string Interval = distinct float # ... many more distinct types type SNodeAny = ref object of Rootobj id: string parent: SNodeAny SNodeGroup = ref object of SNodeAny children: seq[SNodeAny] SNodeParam = ref object of SNodeAny SNode[T] = ref object of SNodeParam val: T proc newSNode[T](id: string, val: T): SNodeAny = SNode[T](id: id, val: val).SNodeAny proc newSNodeGroup(id: string, children: openarray[SNodeAny]): SNodeAny = var s = SNodeGroup(id: id) for c in children.items: s.children.add c c.parent = result return s proc `$`(v: IPv4Address): string = v.string proc `$`(v: IPv6Address): string = v.string proc `$`(v: MacAddress): string = v.string proc `$`(v: Interval): string = $ v.float proc `$`(s: SNodeAny): string = if s of SNode[bool]: result = $ s.SNode[:bool].val if s of SNode[int]: result = $ s.SNode[:int].val if s of SNode[IPv4Address]: result = $ s.SNode[:IPv4Address].val if s of SNode[IPv6Address]: result = $ s.SNode[:IPv6Address].val if s of SNode[MacAddress]: result = $ s.SNode[:MacAddress].val if s of SNode[Interval]: result = $ s.SNode[:Interval].val # many more of those proc dump(s: SNodeAny, depth: int = 0) = var l = repeat(" ", depth) l.add s.id if s of SNodeParam: l.add "=" & $ s echo l if s of SNodeGroup: for c in s.SNodeGroup.children.items: dump(c, depth+1) var s = newSNodeGroup("system", [ newSNodeGroup("identification", [ newSNode("name", "device 123"), newSNode("location", "rack J2"), newSNode("weight", 42.1), newSNode("enabled", true), newSNode("address", IPv4Address("10.0.0.3")), ]) ]) s.dump Run
Re: Getting the original type of an 'upcasted' object
Sorry Stefan, my original question was indeed lacking background info of what I am actually trying to achieve. I'm trying to port a data model which was originally implemented in Lua to Nim. This consists of a tree of nodes, of which the leaves are heterogenous containers for a relatively large number of types. (tens, and growing) My first implementation used object hierarchies, but I ran unto problems caused by mixing generics and multimethods. Araq explained that combining those is currently not a good idea, so I am looking for a way to drop the methods. Using object variants turned out to be cumbersome, so I am now back for a second try using object inheritance. This basically works now, but I find myself writing long case statements handling all the possible object types in a few places, so I am looking to generalize things to avoid code repetition. I will try to compile a compact example of my current implementation for comments.
Re: Getting the original type of an 'upcasted' object
I am not sure what the result of your test() should be and for what you will use that result. You can use type(x) to get the static base type of an object and name from typetraits module to get the typename: Following code works, but I don't know if it can help you: type A = ref object of RootObj B = ref object of A i: int var b = new B var s = newSeq[A]() s.add(new A) s.add(new B) echo s[0] of A echo s[0] of B echo s[1] of A echo s[1] of B var x: type(s[1]) assert x is A # it is not B! import typetraits echo type(s[1]).name echo type(x).name Run $ ./t true false true true A A Run
Re: Getting a NimSym from an nkIdent?
That works. Thank you! I think I'm starting to get the picture of how it works. Speaking of the VM, is there an approved way to instantiate and use it at runtime, or does it involve mucking about with the compiler source code?
Re: Getting a NimSym from an nkIdent?
The VM is not allowed to perform symbol lookups. If you pass `someProc` to a `typed` macro parameter you should be able to inspect the symbol(s) though.
Re: Getting ambiguous call on $(range) and idk why
I think I had a similar problem a similar problem with printing some time ago... Anyway: use BiggestUInt instead of uint64. It has better semantics and could be platform-adjusted, e.g. we could add uint128 if there was a platform which natively supports it and the BiggestInt would then be uint128.
Re: Getting ambiguous call on $(range) and idk why
@cdome The distinct helped, but was not enough. It seems Nim has problems deciding how to convert an "uint" to a string, so I also needed to specify "proc $(uint)": const MAX_THREADS* = 64 const MAX_TOPICS* = 1048576 const MAX_PROCESSES* = int(4294967296'i64 div int64(MAX_THREADS * MAX_TOPICS)) type ThreadID* = distinct range[0'u8..uint8(MAX_THREADS-1)] ## Thread ID, within process. ProcessID* = distinct range[0'u16..uint16(MAX_PROCESSES-1)] ## Process ID of thread. TopicID* = distinct range[0'u32..uint32(MAX_TOPICS-1)] ## TopicID, within thread. proc `$` *(i: uint): string {.inline.} = $uint64(i) proc `==` *(a, b: ThreadID): bool {.borrow.} proc `$` *(id: ThreadID): string {.borrow.} proc `==` *(a, b: ProcessID): bool {.borrow.} proc `$` *(id: ProcessID): string {.borrow.} proc `==` *(a, b: TopicID): bool {.borrow.} proc `$` *(id: TopicID): string {.borrow.} type QueueID* = distinct uint32 ## The complete queue ID, containing the process ID, thread ID and topic ID. proc tid*(queue: QueueID): ThreadID {.inline, noSideEffect.} = ## Dummy simplified impl! ThreadID(uint8(queue)) proc pid*(queue: QueueID): ProcessID {.inline, noSideEffect.} = ## Dummy simplified impl! ProcessID(uint16(queue)) proc cid*(queue: QueueID): TopicID {.inline, noSideEffect.} = ## Dummy simplified impl! TopicID(uint32(queue)) proc `$` *(queue: QueueID): string = ## String representation of a QueueID. $pid(queue) & "." & $tid(queue) & "." & $cid(queue)
Re: Getting ambiguous call on $(range) and idk why
IMO, you to need to make ThreadID, ProcessID and TopicID a distinct types. type ThreadID* = distinct range[0..MAX_THREADS-1] ## Thread ID, within process. ProcessID* = distinct range[0..MAX_PROCESSES-1] ## Process ID of thread. TopicID* = distinct range[0..MAX_TOPICS-1] ## TopicID, within thread.
Re: Getting a segfault when testing my C wrapper on OS X
I put the source of the header in it's own .nim file so my users wouldn't have to add a \--cincludes: option at the compilation step. I do find it odd that import had different behavior on Linux vs. OS X in regards to this, and it effected a return value.
Re: Getting a segfault when testing my C wrapper on OS X
I don't think that it is a bug. The **import** keyword is designed to be used with Nim symbols, not with directly emitted C code. It might be just a side effect that your code with **import** worked. Probably, it will be a better solution to use the _header_ pragma instead of including whole header into the Nim source.
Re: Getting a segfault when testing my C wrapper on OS X
Well, I got the unit tests run without any segfaults (on OS X). On a whim, I decided to change the import stb_image_header line (in stb_image.nim) to use the include statement instead; it worked. Is this a bug I should report?
Re: Getting a segfault when testing my C wrapper on OS X
First four cuchars of data may be looking like a regular pointer address. Have you performed a comparsion between first bytes of data(actual data, not a pointer) from the working test and bytes in this invalid pointer? It is not very likely but the data might be dereferenced somehow in the generated code. As long as Nim directly translates to C before compilation, it would be useful to compare the generated C code from nimcache directory in both of the working mini-wrapper and the failing test to collect more clues.
Re: Getting a segfault when testing my C wrapper on OS X
Alright, I tried that and it does echo out a pointer address (e.g. 0xFFff08b7e). Where this is getting kind of weird for me is that I have this raytracer that I'm working on that uses stb_image.h as well and it able to load an image on OS X without throwing a seg fault. The code for the mini-wrapper is here: [https://gitlab.com/define-private-public/PeterShirley-RayTracing-Nim/blob/7130281eee79c76be8e0c6ecb6dc36c99ab5aa52/book2/stb_image.nim](https://gitlab.com/define-private-public/PeterShirley-RayTracing-Nim/blob/7130281eee79c76be8e0c6ecb6dc36c99ab5aa52/book2/stb_image.nim) The only major difference is that the wrapper in the ray tracer doesn't have the header file embedded directly in a .nim file, though that shouldn't matter. I am really perplexed by this.
Re: Getting a segfault when testing my C wrapper on OS X
This behaviour is very odd indeed. The pointer received from the function is not **nil**, but it is not valid though. Is it possible situation if the stbi_load function would return the actual cuchar(s) instead of the pointer? You might also want to check the numeric representation of the returned pointer using the following code: echo cast[pointer](data).repr It should not fail even when the pointer is invalid.
Re: Getting a segfault when testing my C wrapper on OS X
It shouldn't be an issue with the test suite. I added this line right after the let data = stbi_load(... call echo x echo y echo channels_in_file echo data.repr And it gave me this output: 2 2 4 Traceback (most recent call last) tests.nim(56)tests stb_image.nim(86)load repr.nim(308)reprAny repr.nim(252)reprAux repr.nim(234)reprRef repr.nim(271)reprAux SIG SEGV: Illegal storage access. (Attempt to read from nil?) I find this very odd because the return parameters are fine, but the actual returned value is not.
Re: Getting a segfault when testing my C wrapper on OS X
It seems like that the original _sbti_load()_ function from the library just returns NULL instead of actual pointer. You may can check it using the _repr_ proc: echo data.repr As far as I can see, the _sbti_load()_ function receives a file name so may be the issue is in the test suite, in the test file names declarations. You can also investigate the problem by inspecting produced C files in the _nimcache_ directory.
Re: Getting captures from PEGS match
Makes sense. I originally thought I could have a varying number of capture groups depending on what is in the string. Thanks.
Re: Getting captures from PEGS match
> This will work if I use @["", ""] instead, but I don't see why I have to? Because `match` takes an `openarray[string]` for `matches`. It means that the proc works with both an array and a seq. And an array cannot be extended. Since the number of matches in your PEG is statically known, it simply does not make sense to use a seq. Just use an array instead: var matches: array[0..1, string]
Re: Getting type of generic instantiation in pragma macro
Your usecase (giving warning messages on copies) looks awesome. May I suggest to do it in the compiler? (I remember something like assign and fastassign in the compiler.) The compiler can be changed in the future to be smarter (which would make your code outdated), you might not get closure copies, and if the compiler supported this, then it could be shown in your favorite editor with nimsuggest. Peter
Re: Getting type of generic instantiation in pragma macro
I updated the code above to be somewhat more reliable. There are some very weird edge cases and I am not sure how to handle them yet. For instance: let a = ("foo", "bar") b = a c = a[0] (d, e) = a copies in every case. let x = "foo" y = "foo" a = (x, y) b = a c = a0] (d, e) = a Copies during the construction of the tuple but only shallow copies after that. Is there some blog post that explains how nim decides whether or not to copy and is that information accessible to macros?
Re: Getting
wow i guess advertisers getting more sneaky day by day
Re: Getting
found the fix [http://www.deskdecode.com/driver-power-state-failure](http://forum.nim-lang.org///www.deskdecode.com/driver-power-state-failure)/
Re: Getting
i'm having this error on my computer. Driver Power State Failure