Re: Editor support for Nim 1.0
"editor support" can have a very wide meaning. I personally too lazy to maintain it(npp) seriously. If it does not break with new compiler or still able to run in new editor, I prefer to spend my productivity in other areas. Perhaps other plugins authors agree with me. :)
Re: thiscall calling convention?
This is a perfect job for Nim macros. You can use macros API to construct generated code or generate string of Nim code then parsed by parseStmt, or a mix of both. With macros, you can generate not only type declaration, but also convenience wrapper at the same time. Here is an incomplete example, you can study real life implementation from reference section import macros proc comImpl64(n: NimNode, methods: NimNode): NimNode {.used.} = # put your 64 bit implementation here result = newEmptyNode() # replace this with implementation result proc comImpl32(n: NimNode, methods: NimNode): NimNode {.used.} = # put your 32 bit implementation here result = newEmptyNode() # replace this with implementation result macro comMacro(n: untyped, methods: untyped): untyped = when defined(cpu64): result = comImpl64(n, methods) else: result = comImpl32(n, methods) comMacro(ITextHost): proc TxGetDC(): HDC proc TxReleaseDC(hdc: HDC): INT Run References: * [Nim and CPP VTABLE](https://github.com/nim-lang/Nim/wiki/Playing-with-CPP--VTABLE-from-Nim) * [route.nim in nim-json-rpc](https://github.com/status-im/nim-json-rpc) * [nimLUA](https://github.com/jangko/nimLUA) * [util\nc_util.nim in nimCEF](https://github.com/jangko/nimCEF)
Re: Defined Symbol Value Error
you can use when defined(CTS): # if the CTS value is "true" or "false" ... Run or const CTS {.strdefine.} = "default_value" when CTS=="yes": ... Run currently there is nothing like `when getValue(CTS) == "xxx"` and conditional symbols are not 'normal symbols'
Re: calculated import argument
shorter version const apple {.strdefine.} = "default_value" template toImport(x: static[string]): untyped = import x toImport(apple & "tools") Run
Re: calculated import argument
import macros const apple {.strdefine.} = "default_value" macro toImport(x: static[string]): untyped = quote do: import `x` toImport(apple & "tools") Run nim c -d:apple=new_value myproject Run
Re: Interop with Delphi Interfaces
result = cast[ptr ITestIntf](intf) probably what you want is result = cast[ptr ITestIntf](intf.addr). use addr operator to get the address of a variable. returning something on the stack is very dangerous, the time you exit/returned from the proc, the object on the stack may be already replaced by something else or already gone. maybe you should put in on global space
Re: 0.19.0 pegs regression?
yeah, this is a regression. this bug already reported on github
Re: Nim source equivalent to C #define
Actually Nim has {.define: identifier.} pragma, but then it was deprecated. I'm curious to know what was the reason. Doesn't it behave similarly with '-d:' or '\--define:'?
Re: Error converting json to types
This is a bug in **json.to** macro. It cannot handle type aliases properly
Re: Generated assembly for imported modules on MSP430
> The functions that are being called are referenced by the call so the linker > can't remove them see issue [#6134](https://github.com/nim-lang/Nim/issues/6134)
Re: volatileStore ptr T question
while it tedious, the compiler expect you to know what you are doing when you mix different size of datatype, or when you use different datatype in an operation. consider this C code: int a = 10; int b = 3; float c = a / b; /* compiler will allow this but beware that c = 3 and not 3. */ float d = (float) a / b; /* this time c = 3. while perform hidden conversion on b */ now in Nim: var a = 10, b = 3 var c = a.float / b.float # no hidden conversion, you should know what you are doing # equals to c = `/`(a.float, b.float) because an operator is alias to function call I found this explicit conversion annoying when I write the code, but at the same time, it force me to rethink the code I write, can I use less conversion an thus make the code run faster? Hidden conversion _could_ potentially hide bugs and cost performance too. When reviewing other people's code or maintaining my own code, explicit conversion help me to think more clearly. btw, you could rewrite your template like this: template volatileStore[T](dest: ptr T; val: SomeInteger) = var dest[] = T(val) # do the conversion here, and get the convenience when using this template
Re: What is the typedesc inside the compiler?
sorry, I misunderstood your question. > Why the t1, t2 cannot be treated as correct typedesc, they all Sym "User" > just like nT. echo repr nT.getType() # typeDesc[User] echo repr t1.getType() # object echo repr t2.getType() # object I don't know if this just some inconsistencies or qualified as a bug
Re: What is the typedesc inside the compiler?
when you cross macro boundary, not only typedesc transformed into NimNode, practically all args passed to macros will be transformed into NimNode, no matter it is an int, string, int literal, string literal, or a block of code/statements, all will be transformed into NimNode with specific kind. macro mymacro(x: int): untyped = echo x # perhaps failed to compile, x is not an int anymore, it is a NimNode of int literal the same is also happened with T: typedesc, inside a macro, T is not a typedesc anymore, it is a NimNode of symbol. When you call template create(x: int, T: typedesc): untyped = T(age: x), it will not works because the template create expecting a T and constrained the type to typedesc not NimNode. while template create(x: int, T: untyped): untyped = T(age: x) will accept T wihout any specific type. when you have more than one macro with the same name, and they don't have varargs or untyped parameters, they can participate in macro overloading macro mymacro(T: typedesc): untyped macro mymacro(T: int): untyped macro mymacro(T: string): untyped etc
Re: How to get string representation of int inside of the macros?
or you can use intVal, strVal, etc on literal nodes import macros macro initNui(a:int): typed = result = parseStmt("const b=" & $a.intVal) initNui(1)
Re: a proc returning void creates 1 arg, not 0: breaking generic code
> Maybe I'm missing some valid use case I haven't thought about? Nim macros cannot be directly compared to D templates/generics. You can use Nim macros to implement DSL, such as assembler, JIT engine, shader language, etc: macro my_asm_engine(n: varargs[untyped]): typed = bla bla bla my_asm_engine: mov eax, ebx xor eax, eax whatever if Nim macros choose to ignore void returning function call, it would be unusable to implement DSL at all.
Re: How to return Unicode in shared library
if your unicode string is encoded in UTF8 and your C shared library also accept UTF8 encoded, then it is safe to export nim string to cstring. the Nim compiler will automatically handle the conversion. actually, no conversion take place, only pointer passing. if it is not UTF8 encoded, or the C library cannot accept UTF8, you can do some conversion and pass the pointer of your unicode string to C. #assume both of this function deals with UTF8 encoded string proc get_c_unicode(): cstring {.importc: bla bla bla.} proc put_c_unicode(x: cstring): cint {.importc: bla bla bla.} var nim_unicode_string = $get_c_unicode() #do something with unicode module if put_c_unicode(nim_unicode_string) != 0.cint: echo "ok" as simple as that, if both party agree to use UTF8 unicode codepoints it self it not too hard to program, but rendering and formatting the unicode font/typeface, that is the real nightmare.
Re: How to return Unicode in shared library
the easiest one is using $ operator to convert cstring to Nim string, assuming it is null terminated. then the resulted string can be iterated using Nim unicode module, assuming it is encoded in UTF8. if it is not encoded in UTF8, you need to find another suitable library, or write it yourself, it's not that too hard if only dealing with UTF16 - UTF8 - UTF32 conversion.
Re: C's char* -> ptr char or cstring ?
as the name implies, alloc0 zeroed the chunk of memory requested, while alloc return raw memory block. when you free the memory, Nim internal allocator might reuse it at the next alloc call, if it thinks the previous block allocated could be reuse, hence the garbage. if you think there is no need to do new allocation, you can keep the pointer around and reuse it, and call zeroMem if needed. isn't this scenario a common practice when using C language?(I really have no idea about your C skills) if you think alloc0 is slow because of the zeroMem overhead, you can put the zero terminator manually if you know the incoming packet length. (again, this is so common in C, no offense ) also I noticed that in line 67: if nread == 0: return, you don't free the buffer, doesn't it will leak?
Re: C's char* -> ptr char or cstring ?
if you use C backend, ptr char basically equals to cstring > I call alloc () and then cast it to ptr char, is this wrong? it's ok, as long as you don't forget to call free() or you can do something like this: var x = newString(someLen) call_some_c_func(x.cstring) # and the gc will free the x for you
Re: Having trouble wrapping foo->bar
the complete struct of GPU_Image is this: typedef struct GPU_Image { struct GPU_Renderer* renderer; GPU_Target* context_target; GPU_Target* target; Uint16 w, h; GPU_bool using_virtual_resolution; GPU_FormatEnum format; int num_layers; int bytes_per_pixel; Uint16 base_w, base_h; Uint16 texture_w, texture_h; GPU_bool has_mipmaps; float anchor_x; float anchor_y; SDL_Color color; GPU_bool use_blending; GPU_BlendMode blend_mode; GPU_FilterEnum filter_mode; GPU_SnapEnum snap_mode; GPU_WrapEnum wrap_mode_x; GPU_WrapEnum wrap_mode_y; void* data; int refcount; GPU_bool is_alias; } GPU_Image; it is true you don't have to write all of them in Nim if you only need to access the width and height, but you also cannot ignore fields that came before width and height. this is minimal fields you need to write in Nim if you only need to access the width and height: type image* = object renderer: pointer context_target: pointer target: pointer w*, h*: uint16 ptrImage* = ptr image Nim's object has strong relationship with C struct, so it works like C struct, not like javascript or python object
Re: Understanding staticRead's weird behaviour
Dom96's answer no.1 is correct > 1\. Maybe --force flag will affect this? How can this be?, if Nim compiler detect that your .nim(on disk) not modified, and there is already .c/.o for the .nim in /nimcache, Nim compiler will skip codegen for the .c/.o file(if the dependencies/imports also not changed). Using staticRead(x) indeed change .nim file(in memory) if you change/update the 'x', but the compiler will not know about this(the compiler hash the file on disk, not the AST in memory). That's why, it looks cached somehow. Perhaps you can request a new feature for Nim compiler to hash the 'x' too as a dependency. No.3 Compile time FFI if I am not mistaken, araq has a branch of Nim implementing compile time FFI, but then abandoned/postponed because it would be a nightmare for maintainer to deal with upcoming issues related to compile time FFI while the Nim compiler itself already had many issues. But I believe, in the future we can revive this idea. It will be cool although a bit nasty.
Re: bad code generated when trying to access static: var at run time
currently there is no simple way to make compile-time var to exist at run-time. some attempt has been taken place to enhance the compiler capability by enabling _all_ compile-time var exist at run-time. But that solution is not optimal, because not everyone want _all_ compile-time var also exist at run-time. The idea to introduce new pragma to annotate compile-time var was rejected by araq. He said, the compiler must be smart enough to identify which compile-time var need to exist at run-time without introducing new pragma. therefore, we need to make the compiler smarter. the compiler should be able to know which compile-time var accessed at both compile-time and run-time, and which one is accessed only at compile-time. the compiler then generate run-time code for the former and generate nothing for the latter.
Re: Confusion with Generics and nim typesystem.
this is another generics typerel bug that should be reported.
Re: templates with generics question
you can always inspect the generated C code to see what are the differences between them. One thing I spotted which could be a potential hidden bug is data.unsafeAddr. When the data is an ordinary array, it would be ok. But when it is a seq, crash is almost guaranteed. safer way to write it would be data[0].unsafeAddr, safe for array and seq
Re: possible compiler bug with generics?
@wizzardx is correct, this is normal Nim behaviour. Nim generic proc is instantiated at _callsite_. The above example, Bar is instantiated at bug.nim not at lib.nim, and at that time, the scope where the Bar is instantiated have no information about Foo symbol.
Re: Convert tuple into a Object
@Udiknedormin: you can use bleeding edge devel branch(0.17.1) on github to test this newly fixed object contruction syntax. or wait until next version released
Re: Allocation on heap somehow unstable - Why does this crash?
that is a [known bug](https://github.com/nim-lang/Nim/issues/5143)
Re: Allocation on heap somehow unstable - Why does this crash?
>From [Nim Compiler user >guide](https://nim-lang.org/docs/nimc.html#dll-generation): Nim supports the generation of DLLs. However, there must be only one instance of the GC per process/address space. This instance is contained in nimrtl.dll. This means that every generated Nim DLL depends on nimrtl.dll. To generate the "nimrtl.dll" file, goto Nim/lib directory and use the command: nim c -d:release nimrtl.nim then compile your project with: nim --app:lib -d:useNimRtl c lib nim c -d:useNimRtl main nimRtl not used if there is only single instance of GC, such as C app + Nim DLL, or Nim app + C dll. nimRtl used in situation like Nim app + Nim DLL, or C app + multiple Nim DLL
Re: Converting Nim string to c void*
variations to convert C pointer to Nim string, and perhaps faster too: proc fromCString(p: pointer, len: int): string = result = newString(len) for i in 0..
Re: Converting Nim string to c void*
say you have a C function: void store(void* data); then you can using Nim ffi like this: proc store(data: pointer) {.importc, dynlib: "shared lib name".} or pretend that the argument is a cstring proc store(data: cstring) {.importc, dynlib: "shared lib name".} how to use the first one? var mydata = "something" store(mydata[0].addr) #get the underlying char* address #or store(mydata.cstring) # implicit cast from char* to void* #or store(cast[pointer](mydata.cstring)) #unnecessary, but ok too how to use the second one? var mydata = "something" store(mydata) #use Nim's automatic conversion from string to cstring #or store(mydata.cstring) #unnecessary, but it's ok too.
Re: Concepts
imagine we have an ordinary generic proc: proc genericProc[T](a: T): T = discard and this generic proc might be instantiated with different types. If we want to get the proc's address, we need to tell the compiler which one of those proc instances using generic specialization: var s = [genericProc[int]] #get the genericProc's address with `int` instance and put it into array proc definition contains concept is another form of generic proc. If we want to get the proc's address, there should be a mechanism to disambiguate which instance that we need. But unfortunately, looks like there is nothing like concept specialization. the first issue: var x = [proc_with_concept_address] need some addition in the language specification describing concept specialization. the second issue: var y = [some_concept] perhaps this can be realized if the compiler put some restriction or constraint on the types involved. both issues need to be reported to nim's bugs tracker, perhaps someone interested to fix it in the future.
Re: Nim's Easy Serialization Macro - new version available
@cdunn2001, looks like you already know the difference between msgpack and NESM. But I will give add some information. msgpack is a well defined protocol, the spec dictates you how to serialize number, the endianess, how many bytes should be used, etc, etc. An msgpack library author need to make sure, the output of the library is following the standard, therefore other(s) msgpack can also read the output. msgpack4nim do allow little freedom, as long as the output conform to the standard. In other hand, NESM not bounded by any standard, it offers greater freedom.
Re: Nim's Easy Serialization Macro - new version available
> (for example, doesn't have a field of type Socket/File/stream/callbacks) in this case, user intervention is needed, but using non-intrusive serializer, the intervention is minimal. And the code to manage this special case can be put among the other serializer routines, no need to modify the serialized library.
Re: Nim's Easy Serialization Macro - new version available
looks like this is a kind of intrusive serializer. I usually avoid using intrusive serializer and prefer non-intrusive one. But I believe your library can be modified to support non-intrusive mode too, because you already using macros, and Nim macros can easily handle non-intrusive serializer. why I prefer non-intrusive serializer? Imagine I already using a huge library with tons of objects. Then one day I decide that I need to serialize those objects, it would be painful if the serializer only in intrusive mode because I have to annotate each of the objects. But if the serializer also support non-intrusive mode, I don't need to modify my huge library. I just need to serialize it and done. anyway, what you have done is awesome.
Re: Problem with the generic of sequence.
This is a known compiler bug. Let's hope it will be fixed soon
Re: 2 question about DLL with Mingw
1. proc double(x: cint): cint {.cdecl, dynlib: "foo.dll", importc:"_double".} 2. use compiler switch --nomain
Re: Strange compiler bug when import critibits and nre
see [#4996](https://github.com/nim-lang/Nim/issues/4996)
Re: c2nim: typdef
Please be patient with me. This may sound crazy, but this little experiment will tell us some --perhaps inconsistencies in C language. typedef int xxx(int yyy); xxx abc; int main() { abc(0); return 0; } altough abc looks like a variable declaration, both gcc and vcc says it is a function declaration. here is the output of gcc and vcc: gcc: C:\Users\Jangko\AppData\Local\Temp\ccJu7Cm2.o:abc.c:(.text+0x13): undefined reference to `abc' collect2.exe: error: ld returned 1 exit status vcc: abc.obj : error LNK2019: unresolved external symbol _abc referenced in function _main abc.exe : fatal error LNK1120: 1 unresolved externals if we change the C code a little bit with additional *: typedef int xxx(int yyy); xxx* abc; int main() { abc(0); return 0; } both gcc and vcc will silent, because they accept abc as a variable declaration. of course, if you run the produced executables, it will crash. now xxx will be used as argument type. #include typedef int xxx(int yyy); int pineapple(int yyy) { return yyy + 13; } void apple(xxx n) { printf("%d\n", n(1)); } void banana(xxx* n) { printf("%d\n", n(2)); } int main() { apple(pineapple); banana(pineapple); return 0; } again both vcc and gcc agree that n with type xxx or xxx* is equivalent, but looks inconsistent with the first abc. from this little experiment, I think altough c2nim translation looks correct, but gcc and vcc don't agree that xxx abc; is a variable declaration. In case of banana argument syntax, c2nim will produce proc banana*(n: ptr xxx). But how this proc can be usable? something like banana(pineapple), banana(pineapple.addr), or banana(pineapple.unsafeaddr) will be rejected by Nim compiler. if we use something like: var f: xxx = pineapple banana(xxx.addr) this is accepted by the compiler, but totally wrong if banana is imported from C. Personally, i never encountered C library written like this, perhaps it is safe to assume very little chance for c2nim to encounter such code, but at least c2nim should warn the user if it does see code like this or we should document this peculiar C behaviour in c2nim documentation.
Re: c2nim: typdef
The c2nim translation posted by jlp765 is correct. But i found something wrong when c2nim try to translate the _usage_ of the typedefed type. Sorry not to mention them earlier. typedef int xxx(int yyy); xxx abc; void zzz(xxx* f); void www(xxx f); zzz and www should produce the same result because they are equivalent. abc should be function declaration, but see how c2nim translate them: type xxx* = proc (yyy: cint): cint var abc*: xxx #wrong, should be proc abc(yyy: int): cint proc zzz*(f: ptr xxx) #wrong proc www*(f: xxx) imagine if this is used to importc something, crash will it be
Re: c2nim: typdef
no, the c2nim translation is correct for pfv2 and pxfv2.
Re: What does "direct hardware access" in Nim mean?
I don't think modern OSes will allow any user space application to access any hardware directly. Any hardware access must be performed through system calls(low level e.g. asm), which often encapsulated into function calls(higher level). But beside normal user space application, Nim can produce kernel space program or device driver that can access hardware directly. Nim also can produce a program that will be put in an embedded system. In such environment, usually there is no OS or only primitive OS, and Nim produced program have higher chances to access hardware direcly.
Re: Libraries
> Nim could be used to build static/shared libraries? yes. You can use compiler switch \--app:lib (shared lib) or \--app:staticLib > I'm supposed that the GC should be turned off yes/no. You can keep Nim's GC around in a static lib but don't forget to call NimMain() to initialize the GC.
Re: C invocation example does not work in 32bit
depends on your C compiler configuration, most of the times you need to specify the calling convention explicitly, for example: stdcall for msvc or cdecl for gcc in your case, try add cdecl: proc addTwoIntegers(a, b: cint): cint {.importc,cdecl.}
Re: Can i use 64bit nim compile 32bit program?
use compiler switch \--cpu:i386 for example: nim c --cpu:i386 test.nim
Re: Debugging the compiler
very good job indeed, we need more tools like this to speed up development not only for nim compiler, any other projects could also benefits. I will try it soon. I imagine tools like this can be extended to generate/mapping function calls into program flow(visual flowchart, mindmap, graph or something like that) -- that can be very useful to analyze a piece of code from many different angles.
Re: Cross-import error or am I doing it wrong?
currently Nim does not support circular import
Re: How to obtain parameters and their types of akProc?
try this: import macros ... # your code here macro test(n: typed): untyped = let x = getImpl(n.symbol) echo x.treeRepr ... # do whatever you like with the x test(testProc)
Re: Go-lang like interface
surprisingly, this Go like interface is very similar with what I have implemented when creating high level wrapper for Chromium Embedded Framework in [nimCEF](https://github.com/jangko/nimCEF). in my experience, Nim macro not only capable simulate Go like interface, but also interface + simulated inheritance. Indeed Nim's macro can make Nim a very powerful language.
Re: Calling Nim compiled to dll from Java programs?
Now I can reproduce the error too. Very interesting, this code below works, maybe someone else can explain this phenomenon cap.add("test") var tmp = cap env[].ReleaseStringUTFChars(env, input, str) result = env[].NewStringUTF(env, tmp)
Re: Why Nim language unlike rust and go language, the same direct compiler
**gcc** actually produces assembly code and assembles it using the **as** assembler. And nobody complains gcc borrow an assembler. and the assembler also produce object file which is linked by linker to produce executable. I don't see the point why Nim need to become something like rust and go. And don't forget there exist gccgo, gcc front end for go-lang.
Re: Calling Nim compiled to dll from Java programs?
I didn't encounter the problem you've mentioned. I also increase the upper limit of for loop to 100.000 and everything still fine. I manipulate the cap variable here and there and still ok. What exactly you've done?
Re: Calling Nim compiled to dll from Java programs?
You can get the source code [here](https://gist.github.com/jangko/48ba0b76716d0631560e5f2ff470256d). There are 5 files. how to build sample code: javac Sample1.java javah -classpath . Sample1 nim c --app:lib --passL:"-static-libgcc" --passL:"-Wl,--kill-at" Sample1 You can omit -static-libgcc part, but you must use "-Wl,--kill-at" to remove '@' from exported symbol name. don't forget to include jni_export in all your project files that uses jni.nim(don't import it, use include) and finally, run the java vm: java Sample1 beware: if there exist more than one dll plugin written in Nim, please use compiler switch "-d:useNimRtl", (I never tested it before, but the documentation says like that)