Re: Wrong copy of sequences?
Yes, I know it works with **var**. I have once written a statement let b = a in a program, **a** being a sequence, with a comment # No copy. Reading this some months later, I was not sure that there is actually no copy (and I thought that, in fact, a copy is needed). So I done some checks and found these strange behaviors.
Re: Wrong copy of sequences?
Interestingly, this seems to work correctly: proc p() = var a = @[0, 1, 2, 3] discard a.pop var b = a # note the change from `let` to `var` a.add(5) echo a # @[0, 1, 2, 5] echo b # @[0, 1, 2] p() Looks like an optimization gone wrong. Perhaps the intent was for the sharing to happen between two `let` s. [EDIT] Looks like Iscrd beat me to it.
Re: Wrong copy of sequences?
I use 0.18.0, so the results may differ, of course. When running in the browser, I get the same results as with version 0.18.0. Maybe the compiler does some optimization but it cannot consider that _a_ and _b_ are not used in another place: they are used by _echo_. Assigning with **var** works, of course, so, it 's clearly an optimization when assigning to a read-only object. I suppose, this has been done for performance reason. I have tried with version 0.17.2. Indeed, I get a strange result in the first case, i.e. @[0, 1, 2, 3] @[54014246935360, 1] So it seems that some bug has been fixed in version 0.18.0. For the other tests, the results are indeed the same.
Re: Wrong copy of sequences?
I ran your code, using 0.17.2, it gave wrong seq in example 1, other than that it's same with your result. Is that because the compiler infer that variable a and b didn't used at other place so it's safe to be shared? Just a guess tho
Wrong copy of sequences?
I would like to discuss a problem I have encountered and for which I have submitted a report on the bug tracker with a different version using _newSeqOfCap_. Here is a simple program: proc p() = var a = @[0, 1, 2] let b = a a.add(3) echo a # @[0, 1, 2, 3] echo b # @[0, 1, 2] p() The result is logical: _a_ and _b_ are different sequences and modifying _a_ doesn 't change _b_. Now, a somewhat different program. proc p() = var a = @[0, 1, 2, 3] discard a.pop let b = a a.add(5) echo a # @[0, 1, 2, 5] echo b # @[0, 1, 2, 5] p() It seems that now _a_ and _b_ are sharing some memory. Looking at the generated C code, it appears that in the first case, when adding an element, there is a reallocation. This is not the case in the second program as there is enough room to receive the new value but it is not clear for me why the length of _b_ is modified. But, what if we don't change the length at all? proc p() = var a = @[0, 1, 2, 3] let b = a a[^1] = 4 echo a # @[0, 1, 2, 4] echo b # @[0, 1, 2, 4] p() This seems clearly wrong to me. Now if we replace the sequence by an array. proc p() = var a = [0, 1, 2, 3] let b = a a[^1] = 4 echo a # [0, 1, 2, 4] echo b # [0, 1, 2, 3] p() And looking at the C code, there is clearly a copy, which was expected. We can also get some odd behavior with parameters. var a = @[0, 1, 2, 3] proc p(s: seq[int]) = echo s # @[0, 1, 2, 3] a[^1] = 4 echo s # @[0, 1, 2, 4] p(a) I think this problem is not likely to happen frequently, but it may cause some troubles. What do you think of it? And how could this been solved?
Re: Compiler won't scale (still)
OK, I set `MaxLoopIterations* = 1_000_000_000` (1 Billion) in `~/nim-0.18.0/compiler/vmdef.nim` and rebuilt doing `./koch boot -d:release` and was able to compile P17. I think this value is way more reasonable, because as stated previously, on modern machines (or really any system with gigahertz clock speeds) we're only talking second for even a billion iterations. I really hope you will up the value. Until so, I'll patch my own systems. Thanks for instructing how to do this. `Again, I strongly urge you to PROMINENTLY DOCUMENT this capability too.`
Re: Nim syntax Quiz
Ok, correct answer to the quiz is: 8 You'll find the corrected code below. As any decent quiz should, one trick question was included: although " _inheritance only works with non-final objects_ " is reported as syntax error, there's no syntax error at that line; _MyObject_ just should have been declared as " _of RootObj_ ". type MyTuple = tuple[a: int, b: int] var myTuple: MyTuple = (a: 10, b: 10) type MyObject = ref object of RootObj a: int var myObject: MyObject = MyObject(a: 5) type MySpecialObject = ref object of MyObject var seqOfStrings: seq[int] = @[] proc silentProc*() = discard proc inc(a: var int) = a += 1 Btw1. This discussion is also relevant: [https://forum.nim-lang.org/t/3647](https://forum.nim-lang.org/t/3647) It's a fact that when the parser gets carried away, it may state some irrelevant line as the source of your error. (Due to what StasB stated above). Again, use the error message line number as a hint, not as a fact. Btw2. Below is an example of a program that produces - while being a pedantically correct error message - quite scary output for a newcomer. A friendlier (and admittedly unrealistic to achieve) alternative would be something like: _The & operator concatenates two strings, but the procedure debug does not return a string. Did you mean: debug("foo" & "bar")_ import logging debug("foo") & "bar" The lesson to be learned: Just take nim error messages with a grain of salt (at least until Nim 1.x). After all, nim is more programmer-friendly language than it's error messages might first suggest.
Re: db_mysql & threads
Doesn't this mean that you have to use multiple connections? Which seems easy enough to do.
Re: Resolve: Error: parallel 'fields' iterator does not work for 'case' objects
In the other tests you have posted you are not comparing case objects. E.g `boolValueAV.boolValue == boolValue` is fine because you are comparing bools, but `anyseqValueAV.anyseqValue == anyseqValue` will use the `==` proc for seqs, which internally will use the generic `==` proc for objects to compare the `AnyValue` objects in the seq. Since that proc doesn't support case objects, and `AnyValue` is a case object, it fails. The same thing happens with `boolValueAV == boolValueAV`, since in that case you are also comparing case objects.
Re: Case type and float: compiler seems to confuse float and float64
`system.nim` has this comment: `'float64' is now an alias to 'float'; this solves many problems`. I don't know what the actual motivation for the behavior is, but it's definitely intended.
Re: Resolve: Error: parallel 'fields' iterator does not work for 'case' objects
This happens because the built in `==` operator for objects simply doesn't work for case objects. You can get the same behavior by doing `boolValueAV == boolValueAV`. It should be possible to fix it by defining your own `==` operator for `AnyValue`.
Re: Resolve: Error: parallel 'fields' iterator does not work for 'case' objects
In my "full modules", I have something like 22 types supported now. avAnySeq is the _last_ one to be checked, and the only one to fail (except for the float /float64 case). If I understand your reply properly, it's just "luck" that it only fails for avAnySeq? Maybe I shouldn't use "42" everywhere as test value...
Re: Case type and float: compiler seems to confuse float and float64
So, it's a "feature" and not a bug? Is there any known rational, to act differently with float, than with int and uint?
Re: Case type and float: compiler seems to confuse float and float64
`float` and `float64` are equivalent, even on 32bit architectures. `int` and `int64` on the other hand are distinct types which may or may not have the same underlying type. So you only need `avFloat64`, not `avFloat`. You can observe this by naming the two converters the same - the compiler will complain that they have the same signature. Perhaps the compiler should complain when there are multiple converters with the same arguments/return type in the scope, since it's not clear which one will be called.
Resolve: Error: parallel 'fields' iterator does not work for 'case' objects
As I said in the previous post, I'm trying to create a "Any Value" case type. Another problem I have is supporting "seq[AnyValue]". Seq of anything else seems to work. Maybe it's a type recursion problem? Is there a work-around? Here's the example: type AnyValueType* = enum avBool, # ... avBoolSeq, # ... avAnySeq AnyValue* = object case kind*: AnyValueType of avBool: boolValue*: bool # ... of avBoolSeq: boolSeqValue*: seq[bool] # ... of avAnySeq: anyseqValue*: seq[AnyValue] converter toBoolAnyValue*(v: bool): AnyValue {.inline, noSideEffect.} = result.kind = avBool result.boolValue = v converter toBoolSeqAnyValue*(v: seq[bool]): AnyValue {.inline, noSideEffect.} = result.kind = avBoolSeq result.boolSeqValue = v converter toSeqAnyValueAnyValue*(v: seq[AnyValue]): AnyValue {.inline, noSideEffect.} = result.kind = avAnySeq result.anyseqValue = v when isMainModule: let boolValue: bool = true let boolValueAV: AnyValue = boolValue let boolSeqValue: seq[bool] = @[boolValue] let boolSeqValueAV: AnyValue = boolSeqValue let anyseqValue: seq[AnyValue] = @[boolValueAV] let anyseqValueAV: AnyValue = anyseqValue assert(boolValueAV.boolValue == boolValue) assert(boolSeqValueAV.boolSeqValue == boolSeqValue) assert(anyseqValueAV.anyseqValue == anyseqValue) # Compiler bug :(
Case type and float: compiler seems to confuse float and float64
I'm trying to write a "Any Value" type, so I can create a type-safe string-to-any-value table. First I noticed the compiler seems to "confuse" byte and uint8, but I think it's normal, since I've read byte is just an alias for uint8. Unfortunately, it also has problems with float vs float64 (on 64bit architecture), which is strange, because it has no problem with int vs int64 and uint vs uint64. Therefore, I think it's a bug. Here's the code that compiles but fails to run: type AnyValueType* = enum avBool, # ... avFloat, avFloat64 AnyValue* = object case kind*: AnyValueType of avBool: boolValue*: bool # ... of avFloat: floatValue*: float of avFloat64: float64Value*: float64 converter toBoolAnyValue*(v: bool): AnyValue {.inline, noSideEffect.} = result.kind = avBool result.boolValue = v converter toFloatAnyValue*(v: float): AnyValue {.inline, noSideEffect.} = result.kind = avFloat result.floatValue = v converter toFloat64AnyValue*(v: float64): AnyValue {.inline, noSideEffect.} = result.kind = avFloat64 result.float64Value = v when isMainModule: let boolValue: bool = true let floatValue: float = 42.0 let float64Value: float64 = 42.0'f64 let boolValueAV: AnyValue = boolValue let floatValueAV: AnyValue = floatValue let float64ValueAV: AnyValue = float64Value assert(boolValueAV.boolValue == boolValue) assert(floatValueAV.floatValue == floatValue) assert(float64ValueAV.float64Value == float64Value) # Compiler bug :( And returns: float64value.nim(38) float64value system.nim(2839) sysFatal Error: unhandled exception: float64Value is not accessible [FieldError] Error: execution of an external program failed: 'bin/float64value ' The terminal process terminated with exit code: 1
Re: Stein's (binary) GCD algorithm (iterative version)
Here's a gist of the code. [https://gist.github.com/jzakiya/b096b92c181ed343dab8c130c88f1d39](https://gist.github.com/jzakiya/b096b92c181ed343dab8c130c88f1d39)
Re: Stein's (binary) GCD algorithm (iterative version)
Back in the day I had that book, when I wore a younger man's clothes, and also **Applied Cryptography**. I wonder what happened to them [https://www.goodreads.com/book/show/351301.Applied_Cryptography](https://www.goodreads.com/book/show/351301.Applied_Cryptography)
Re: How to turn thread spawn call into an async call
I agree that would be fine. The two are very similar. To avoid the polling, threadpool should be able to transfer the result of its work to the async dispatch list of the calling thread when its done. expanding my example you could do: import os, asyncdispatch, threadpool type Noise = distinct bool proc doWork(param: int): Noise = # staff use sql echo "starting with ", param, " ..." sleep(5000) # complete the future var echo "... ok" proc doOtherWork(p1:int, p2: int): Noise = echo "other starting with ", p1, " and ", p2, " ..." sleep(4000) # complete the future var echo "... other ok" proc doRealWork(p1, p2, p3: int): int = echo "real starting with ", p1, " and ", p2, " and ", p3, " ..." sleep(3000) result = p1 + p2 + p3 echo "... done real work" proc asyncWaitFor (work: FlowVar[Noise], sleepTime: int = 500) {.async.} = ## waits asynchron for a FlowVar to finish while not work.isReady : await sleepAsync(sleepTime) proc asyncWaitFor[T: not Noise] (work: FlowVar[T], sleepTime: int = 500):Future[T] {.async.} = ## waits asynchron for a FlowVar to finish while not work.isReady : await sleepAsync(sleepTime) return ^work proc callWorkAsync() {.async.} = let work = spawn doWork(1) let other = spawn doOtherWork(2, 3) let real = spawn doRealWork(4, 5, 6) let res = await asyncWaitFor(real) echo "real work returned: ", res await asyncWaitFor(work) await asyncWaitFor(other) let call = callWorkAsync() echo "do so more" waitFor call echo "done"
Re: Stein's (binary) GCD algorithm (iterative version)
Relevant [Handbook of Applied Cryptography](http://cacr.uwaterloo.ca/hac/about/chap14.pdf) on page 17 of the this chapter 14 PDF (page 606 - chapter 14.4 of the whole book) It has the binary GCD, extended binary GCD and Lehmer's GCD algorithm.
Re: db_mysql & threads
> can of worms ? Yes, according to this : [MySql Reference](https://dev.mysql.com/doc/refman/5.7/en/c-api-threaded-clients.html) "Multiple threads cannot send a query to the MySQL server at the same time on the same connection" So you'll have to serialize your queries anyway, what's the point then?
Re: Compiler won't scale (still)
Such a limit would probably be around a few seconds, rather than a fixed number of iterations, because that's where most people start to suspect that their computation is either too long or stuck in an infinite loop.
Re: Compiler won't scale (still)
Then the limit would depend on the used CPU. Bad idea IMO.
Re: Compiler won't scale (still)
> Why not add a flag to set/disable the iteration limit like he wants? I'm sure > that as the user base grows, more people are going to hit the limit and get > annoyed. Because I am curious whether it can be supported out of the box by a "reasonable" limit first.
Re: What can we learn from the SO 2018 Dev Survey?
> It means that you're used to The Python Way of doing things, and don't want > to deviate from it without good reason Developing/testing stuff out interactively is part of the Python Way of doing things for many people, at least in my experience.
Re: Compile-time type reflection API?
@Araq: > An object does not only consist of fields, it can have case and when etc. Which is part of the reason why doing something as simple as getting the fields robustly gets difficult when dealing directly with the AST; there isn't just one canonical representation. I thought the compiler might have such a canonical representation internally which can be queried, but I guess not. @chrisheller: > Keep in mind that you can write some of your own compile time methods I did write my own (partial) solution. It just doesn't work for every valid tree configuration as of yet. If the plan is to write an API on top of the AST one anyway, then I guess I'll just keep building up on mine and release it eventually as a library when it becomes robust. Then someone could integrate into Nim core if it comes out any good.
Re: Compiler won't scale (still)
Why not add a flag to set/disable the iteration limit like he wants? I'm sure that as the user base grows, more people are going to hit the limit and get annoyed.
db_mysql & threads
Is it possible to have a thread that update contents on the table A, and another thread that queries table A on the same connexion, or I need 2 DbConn objects ? I guess it doesn't make much sense to share anyway since nim supposedly separates all memory, though I could copy the conn object on a channel ? can of worms ?
Re: What can we learn from the SO 2018 Dev Survey?
> To really appeal to Python programmers, Nim would have to support dynamic > compilation and a REPL. Not necessarily. Being a Python programmer doesn't mean you can't do anything other than Python. It means that you're used to _The Python Way_ of doing things, and don 't want to deviate from it without good reason. Python programmers routinely optimize in C/C++ (and now Go), and Nim should offer a better alternative. Some aspects of Nim seem very Python-like, but some do not. > > Since vscode doesn't work on all platforms > > Wait, what? > > [https://code.visualstudio.com/Download](https://code.visualstudio.com/Download) > \- you can have it on Windows, Linux, and Mac. Yes, which is what most people use, and that's why I said vscode was the right choice as the default recommended code editor for Nim. (There's [some progress with FreeBSD](https://github.com/prash-wghats/Electron-VSCode-Atom-For-FreeBSD), but still not stable.) But it doesn't run in restricted environments, Android / Termux, OpenBSD, HaikuOS, etc. Which is why, if vscode is the primary focus, I think vim should be second. > If Nim can get REPL, that would be huge!! Another random thought: [Anaconda now ships with vscode](https://www.anaconda.com/blog/company-blog/vs-code-in-anaconda-distribution-5-1/). I wonder if Nim would be a fitting component for that bundle...
Stein's (binary) GCD algorithm (iterative version)
On the Ruby issue tracker replacing Euclid's gcd algorithm with Steins (binary) algorithm came up. [https://bugs.ruby-lang.org/issues/13503](https://bugs.ruby-lang.org/issues/13503) Here's the wikipedia article on it. [https://en.wikipedia.org/wiki/Binary_GCD_algorithm](https://en.wikipedia.org/wiki/Binary_GCD_algorithm) Here's a Nim implementation of the iterative version. proc gcd(a, b: int): int = var (a, b) = (a, b) if a == 0: return b if b == 0: return a var k = 0 while ((a or b) and 1) == 0: a = a shr 1 b = b shr 1 k += 1 while (a and 1) == 0: a = a shr 1 while b != 0: while (b and 1) == 0: b = b shr 1 if a > b: swap a,b b -= a result = a shl k Here's a Ruby implementation of it. def gcd(a, b) return b if a.zero? return a if b.zero? k = 0 while (a | b).even? a >>= 1; b >>= 1; k += 1 end a >>= 1 while a.even? until b.zero? b >>= 1 while b.even? a, b = b, a if a > b b -= a end a << k end
Re: Compiler won't scale (still)
> Do I need to recompile|rebuild Nim to make the change? Yup. `koch boot -d:release` creates the modified compiler if you have an installation where `koch boot` works (pick the "installation from source" route: [https://github.com/nim-lang/Nim#compiling](https://github.com/nim-lang/Nim#compiling) > Why does this line cause this compiler iteration problem? Because that line triggered the 1_500_000th iteration limit. This line is nothing special, any line could trigger this limit.
Re: How to turn thread spawn call into an async call
I think what I really need is a new spawn which return a Future[T] rather than FlowVar[T].
Re: Compiler won't scale (still)
Compiling again for P17, with 0.18.0 and 0.17.2, the error messages point to `gcd` function in both cases: # 0.18.0 error message generating parameters for P17 stack trace: (most recent call last) twinprimes_ssozp17par5d3.nim(87) twinprimes_ssozp17par5d3.nim(65) genPGparameters lib/pure/math.nim(452) gcd lib/pure/math.nim(452, 15) Error: interpretation requires too many iteratio # 0.17.2 error message generating parameters for P17 stack trace: (most recent call last) twinprimes_ssozp17par5d3.nim(87) twinprimes_ssozp17par5d3.nim(65) genPGparameters lib/pure/math.nim(439) gcd lib/pure/math.nim(439, 15) Error: interpretation requires too many iterations In both cases it points to the same line in `lib/pure/math.nim` (line 452 in 0.18.0 or 439 in 0.17.2): proc gcd*[T](x, y: T): T = ## Computes the greatest common divisor of ``x`` and ``y``. ## Note that for floats, the result cannot always be interpreted as ## "greatest decimal `z` such that ``z*N == x and z*M == y`` ## where N and M are positive integers." var (x,y) = (x,y)# < this line is pointed to in both cases while y != 0: x = x mod y swap x, y abs x Changing `var (x,y) = (x,y)` to `var x = x; var y = y` or changing variable names, in both cases, creates same results. **Why does this line cause this compiler iteration problem?**
Re: How to turn thread spawn call into an async call
Now there is another problem. I hope I can write the code like this: proc ff1(p1: int): Result = # my db acess code here .. proc ff2(p1, p2: int): Result = # my db acess code here .. proc main() {.async.} = # async call ff1 with parameter let r1 = await callAsync(ff1(1)) # async call ff2 with parameter let r2 = await callAsync(ff2(1, 2)) .. Because we pass the parameter 'ff1(1)' to callAsync, so callAsync must be a macro like this: macro callAsync*(p: untyped): untyped {.async.} = quote do: proc callme(evt: AsyncEvent): Result = let s = `p` evt.trigger() s let evt = newAsyncEvent() let fut = waitEvent(evt) let val = spawn callme(evt) await fut return ^val But a macro cannot be {.async.}, so I cannot do this. A limited way to resolve this problem is use an procval, here is the code: type Result* = ref object of RootObj body*: string Action = proc(): Result proc waitEvent(evt: AsyncEvent): Future[void] = let fut = newFuture[void]("callAsync") addEvent(evt, (fd: AsyncFD) => (fut.complete(); true)) return fut proc callp(evt: AsyncEvent, p: Action): Result = let v = p() evt.trigger() v proc callAsync*(p: Action): Future[Result] {.async.} = let evt = newAsyncEvent() let fut = waitEvent(evt) let val = spawn callp(evt, p) await fut return ^val proc ff(): Result = echo "work" sleep(1000) Result(body: "hello") block: let val = waitFor callAsync(ff) echo "future return ", val.body The limitation is I can only call Action type proc, and I cannot pass the paramter freely. Any way to solve the problem? Thanks.
Re: How to turn thread spawn call into an async call
@adrianv Thank you
Re: Compiler won't scale (still)
One (last?) trick to reduce the number of iterations. I changed this: var residues: seq[int] = @[] var pc = 1 while pc < modpg: (pc += 2; if gcd(modpg, pc) == 1: residues.add(pc)) let rescnt = residues.len to this: var residues: seq[int] = @[] var pc = 1 var inc = 4 while pc < modpg: (pc += inc; inc = inc xor 0b110; if gcd(modpg, pc) == 1: residues.add(pc)) let rescnt = residues.len This reduces the number of times `gcd` is called from half the numbers (all the odds) upto modpg (modpg/2) to a third (modpg/3). This change produces the P3 PG residue sequence: `pcs = 6m +|- 1` pc = 1, 5, 7, 11, 13, 17, 19... +4 +2 +4 +2 +4 +2 So while it shaves off some iterations of `gcd` it's still not enough to get P17 to compile. `A REQUEST:` It would be really, really nice to use the boolean operators like: `x ^= y; x &= y`; etc.
Re: Compiler won't scale (still)
OK, **I finally got it to compile with the original iteration count** , but man, did I have to jump through hoops to do it. To reduce the number of loops, instead of doing `brute force trial-and-error` to test each residue against the others to find its inverse, I found the code here `https://rosettacode.org/wiki/Modular_inverse#Nim` on Rosetta Code, that had a Nim version already done. [Notice: the code there doesn't compile without changing `proc mulInv(a0, b0): int =` to `proc mulInv(a0, b0: int): int =`. In fact, quite a few of those old Rosetta code Nim examples don't compile, but I digress.] proc mulInv(a0, b0: int): int = var (a, b, x0) = (a0, b0, 0) result = 1 if b == 1: return while a > 1: let q = a div b a = a mod b swap a, b result = result - q * x0 swap x0, result if result < 0: result += b0 Then I was able to eliminate the loop-in-a-loop construct, and just do this: var inverses: seq[int] = @[] for res in residues: inverses.add(mulInv(res,modpg)) I was trying to avoid using another function just to do this, since I don't use it at runtime, but you do what you gotta do. Does Nim already have this function in its library? If not, can you please add it (math lib, etc). Below is final code that compiles with original compiler iteration value, with some added diagnostic checks. # Compute modular inverse of a to base b, e.g. a*a_invese mod m = 1 proc mulInv(a0, b0: int): int = var (a, b, x0) = (a0, b0, 0) result = 1 if b == 1: return while a > 1: let q = a div b a = a mod b swap a, b result = result - q * x0 swap x0, result if result < 0: result += b0 # Create constant parameters for chosen PG at compile time proc genPGparameters(prime: int): (int, int, int, seq[int], seq[int], seq[int]) = echo("generating parameters for P", prime) let primes = [2, 3, 5, 7, 11, 13, 17, 19, 23] var modpg = 1 for prm in primes: (modpg *= prm; if prm == prime: break) var pc = 1 var residues: seq[int] = @[] while pc < modpg: (pc += 2; if gcd(modpg, pc) == 1: residues.add(pc)) let rescnt = residues.len var restwins: seq[int] = @[] var j = 0 while j < rescnt-1: if residues[j]+2 == residues[j+1]: restwins.add residues[j]; restwins.add residues[j+1]; j += 1 j += 1 let rescntp = restwins.len inverses: seq[int] = @[] for res in residues: inverses.add(mulInv(res,modpg)) echo("residues size = ", residues.len) echo("inverses size = ", inverses.len) for j in 0..residues.len-1: (if residues[j]*inverses[j] mod modpg != 1: echo("error at index ",j)) result = (modpg, rescnt, rescntp, residues, restwins, inverses) # Generate at compile time the parameters for P13 const parameters = genPGparameters(13) This must be is under the `Magical Limit` using P13. So what will it do with P17? And the answer is...Nope! It bombs (again) when trying to compute the 92,160 values for the `residues` array, as it never gets to the inverse array computation. I ultimately tried changing the iteration variable upto 1 trillion again before giving up. I think I will need to rebuild Nim with a new value in that file to make it take. That's for tomorrow (maybe), unless someone can instruct me how to do it without rebuilding Nim. So, at least partial success, and I have learned something new and useful. **But Please, FIX THIS!, and DOCUMENT IT!**
Re: Compiler won't scale (still)
I started changing the `MaxLoopIterations* = 1500_000 # max iterations of all loops` line in `compiler/vmdef.nim` in increments of 1 million, until it was 20M, recompiling after each change, and still got error. Then I went up in 100M increments until 1 trillion, and still got error. Do I need to recompile|rebuild Nim to make the change? Is merely changing the file sufficient? I doesn't seem so.
Re: Why is my destructor not called?
Oh, seems the **\--newruntime** compiler flag is needed for destructors to work.