Re: Reason for -fno-strict-aliasing?

2017-08-25 Thread cblake
I did a little searching and compiling and I'd have to say Jehan is right here 
about "absence of evidence". See, [this stackoverflow 
thread](https://stackoverflow.com/questions/21214875/gcc-accuracy-of-strict-aliasing-warnings)
 for a very simple example to people that is (still in 2017) too complex for 
(at least gcc's) Wstrict-aliasing heuristics. It sure seems like 
strict-aliasing is a real morass.

@cdome - perhaps a better solution would be some kind of `emit` and/or `macro` 
machinery that turns on `-fstrict-aliasing` just for the procs you need to 
recover performance. gcc has had this `#pragma` or `__attribute__` way to do 
that for quite a few years now (2011, I think). See 
[here](https://gcc.gnu.org/wiki/FunctionSpecificOpt).


Re: Reason for -fno-strict-aliasing?

2017-08-25 Thread Jehan
> Also, in my opinion, violating the strict aliasing rule is a code smell, and 
> so I think we should avoid accommodating bad code with the 
> "-fno-strict-aliasing" flag.

All the major OS kernels (Linux, FreeBSD, and OpenBSD) have strict aliasing 
disabled, and for good reasons. So do a plethora of other C applications and 
libraries.

One, it is insanely easy to accidentally violate the strict aliasing rule when 
manually writing normal C code and there is no way to safely statically 
safeguard against such occurrences. It's an easy source of Heisenbugs with 
basically no performance-related payoff outside of rare circumstances (where 
aliasing can create a performance impact, the pointers usually point to 
entities of the same type).

This also goes for manually written C code that's being included in Nim 
directly, such as static inline functions from header files for external 
functions.

Two, even for generated code (such as code emitted by the Nim compiler), it is 
difficult to avoid undefined behavior in low-level code unless the code 
generator was designed from the ground up for this. There are a number of 
reasons for that:

  1. The gcc developers have held for the longest time that casting through a 
union is _not_ sufficient to work around the pointer aliasing rule and did in 
fact defend that claim fairly agressively (see [this 
thread](http://www.mail-archive.com/gcc@gcc.gnu.org/msg48627.html), for 
example). I _think_ they've finally gone back on that, because programmers 
expressed a need for that use case, but there are probably still gcc versions 
out there for which this isn't safe; or at least casting through a union 
silences warnings that you'd otherwise get. And I'm not actually 100% sure that 
we're safe now.
  2. For each cast, the union through which to cast would have to be the 
transitive closure of all non-char types that the pointer may ever have pointed 
to, for example:




proc main =
  var a: int64 = 1
  var p: ptr float = cast[ptr float](addr a)
  var q: ptr int32 = cast[ptr int32](addr a)
  p[] = 1.0
  q[] = 2'i32
  echo a

main()


This example would require a union of int64, int32, and float. Which may be 
impossible to construct if the code is spread over several functions.

> I've even changed -fno-strict-aliasing to "-fstrict-aliasing 
> -Wstrict-aliasing" in build.sh (in csources), and nim compiler compiled 
> without any issues!

"Absence of evidence does not mean evidence of absence", as they say. The 
compiler may just not have triggered the relevant optimizations in this case, 
or you may not have executed the relevant code. You also have no guarantee that 
future versions of gcc/clang won't introduce breakage.


Re: Reason for -fno-strict-aliasing?

2017-08-25 Thread cblake
@Tiberium, in the `csources/build.sh` context you should only need to remove 
the `-w` and change the `-fno-strict-aliasing` in `COMP_FLAGS` since it's just 
a shell script with a zillion gcc invocations. Compiling other nim code, I only 
had to change my nim.cfg's `gcc.options.always = "-Wall 2>>/tmp/gcc.log"` or 
something similar to catch the warning outputs. Still yet to see any warnings 
related to aliasing.


Re: Reason for -fno-strict-aliasing?

2017-08-25 Thread cblake
One other gotcha in this "test" to see how close we already are is that it 
seems nim catches the `stderr` output of the gcc invocations. In that sense the 
nim `gcc` is as if it were `gcc -w` anyway. If you capture the commands from 
`--verbosity:2` and re-execute them from a `/bin/sh` script, you do see any gcc 
warnings, though. I still don't see any warnings related to aliasing.


Re: Reason for -fno-strict-aliasing?

2017-08-25 Thread Tiberium
I've even changed -fno-strict-aliasing to "-fstrict-aliasing -Wstrict-aliasing" 
in build.sh (in csources), and nim compiler compiled without any issues!


Re: Reason for -fno-strict-aliasing?

2017-08-25 Thread Tiberium
@cblake it doesn't show any problems for me


Re: Reason for -fno-strict-aliasing?

2017-08-25 Thread cblake
This may be obvious, but has anyone else tried changing `-fno-strict-aliasing` 
to `-fstrict-aliasing -Wstrict-aliasing` in their `nim.cfg` and seeing if any 
gcc warnings arise? When I try this on Linux with gcc-6.3 and gcc-7.2 and devel 
nim I don't see any warnings at all. You may also need to turn off the `-w` 
general gcc warning suppression, too (maybe in the system level nim.cfg as well 
as $HOME one) and double check with `nim c --verbosity:2` that the compiler is 
getting invoked as you think it should. I tried a few different garbage 
collector impls and a variety of small Nim programs. It's hardly exhaustive and 
I'm not sure that this particular gcc warning has a 0% false-negative rate 
(does someone know?). We may be so close to this to be almost already there.


Simple Python-like class macro and some python-like procedures (print, input, range, others)

2017-08-25 Thread Tiberium
I've implemented some simplest Python functions and very simple "class" macro 
(which doesn't and wouldn't support inheritance). 
[https://github.com/Yardanico/nimpylib](https://github.com/Yardanico/nimpylib) 
\- check example2.nim for classes.

Yeah, code isn't the best - this is mainly due to the nature of Python 
(dynamic-typing), for example:

"range(5)" \- here 5 is a position where range stops

"range(1, 5)" \- 1 here is a position where range starts

Simplest example of class macro usage: 


import pylib

type HelloWorld = ref object
  name: string

class HelloWorld(object):
  def init(self, name):
self.name = name
  
  def greet(self):
print("Hello,", self.name, sep = "\n")

let c = newHelloWorld("Daniil")
c.greet()



Re: Reason for -fno-strict-aliasing?

2017-08-25 Thread pwernersbach
Also, in my opinion, violating the strict aliasing rule is a code smell, and so 
I think we should avoid accommodating bad code with the "-fno-strict-aliasing" 
flag.


Re: Reason for -fno-strict-aliasing?

2017-08-25 Thread pwernersbach
I read a bit about the strict aliasing rule, and it seems that the only code 
that would be broken by "-fno-strict-aliasing" is code that declares two 
pointers to the same block of memory, and simultaneously uses both pointers to 
access the memory. I'd say that most programs, especially Nim programs, do not 
do this.

I see two potential problem areas:

The first potential problem area would be the garbage collector. If the garbage 
collector does this, then it must be converted to casting through unions, as 
Araq suggests.

The second potential problem area would be how the Nim garbage collector 
generates code for ref's and inheritance. If a ref is only used as one type, 
then there is no problem. If a ref is used as a parent type and a child type, 
then there is a potential problem there, depending on how the Nim compiler 
generates the cast for the ref.

After these two potential problems areas are evaluated and fixed, then 
"-fno-strict-aliasing" can be removed, as "safe" Nim code would not be able to 
violate the strict aliasing rule. Nim code that uses "cast" and ptr's in 
certain ways would still be able to violate the rule, but I would argue that it 
would be the programmer's responsibility to pass "-fno-strict-aliasing" to the 
compiler in this case.


Re: parsecsv problem

2017-08-25 Thread nucky9
That works perfectly, thanks!


Re: parsecsv problem

2017-08-25 Thread stisa
With [existsFile](https://nim-lang.org/docs/os.html#existsFile,string) you 
could do something like 


import os
let filename = "my.png"
if not existsFile(filename):
  raise newException(IOError, (filename & " not found"))



Re: parsecsv problem

2017-08-25 Thread nucky9
Yeah, that is it. I was pretty sure it was a problem closing the file, but 
thought that the file didn't remain open since I didn't assign it to a 
variable, which is quite foolish actually - thanks Stefan!

However, if I do as Parashurama suggested:


try:
  p.open(fileName)
except:
  raise newException(IOError, (fileName & " not found"))


I get the generic parsecsv error instead of my custom exception, if the file 
isn't found. This isn't _too_ bad, since I can find the errant name based on 
the line numbers in the stack trace, but it would be nice to keep the exception 
I have. Is there a way to close the system.open(), or maybe to test for the 
file without using open()? 


Re: parsecsv problem

2017-08-25 Thread Stefan_Salewski
Well, I had the impression that he does a system.open() call first -- to check 
if file exist, followed by p.open()...

And for system.open() there is no corresponding close, so maybe OS refuses 
opening the the file again? 


Re: parsecsv problem

2017-08-25 Thread Parashurama
You are forgetting to pass `p` CsvParser arg


var p: CsvParser
  try:
#discard open(fileName) # missing arg
p.open(fileName) # this works
  except:
raise newException(IOError, (fileName & " not found"))



Re: parsecsv problem

2017-08-25 Thread nucky9
Oh, I should mention this is with nim 0.16.0.


parsecsv problem

2017-08-25 Thread nucky9
I'm having a problem with the parsecsv that I can't figure out.

Basically, in order to generate map tiles, I am opening five .csv files, and 
reading from them. The map tiles are generated in pairs of twos. I can generate 
25 pairs without any trouble, but the program always crashes when the 26th pair 
is generated, after the set of five .csv files are opened for the 51st time. 
This is the error thrown: 


main.nim(38) main
main.nim(32) main
mainScreen.nim(627)  mainScreen
mainScreen.nim(415)  processInput
endTurnFunctions.nim(33) endTurn
tileGenerator.nim(1141)  createMapTiles
tileGenerator.nim(34)generateTile
miscFunctions.nim(27)readCSV
parsecsv.nim(110)open
parsecsv.nim(79) error
parsecsv.nim(75) raiseEInvalidCsv
SIGSEGV: Illegal storage access. (Attempt to read from nil?)


Line 27 of miscFunctions refers to line 7 of readCSV(): 


p.open(fileName)


I believe the means that the .csv file can't be found, but it is found without 
problem the first 50 times, and no exception is raised when 


try:
  discard open(fileName)
except:
  raise newException(IOError, (fileName & " not found"))


is run. This, and the fact that it always happens after the same number of 
files are opened, makes me think it is some sort of memory error, but I am 
closing the file every time, so I am not sure why that would be. The full proc 
is given below. If anyone has any idea of what the problem could be, I would 
greatly appreciate the insight.


proc readCSV*(fileName: string, minRow: int, numRows: int = 1):  auto =
  var p: CsvParser
  try:
discard open(fileName)
  except:
raise newException(IOError, (fileName & " not found"))
  echo fileName
  p.open(fileName)
  
  let rowsToRead = numRows - minRow
  var tableEntries = newSeq[CSVRow](numRows) # will be appended as 
tableEntries[y][x]
  var convertedTable: seq[seq[string]] = @[]
  
  for i in 0 .. (minRow + numRows - 1):
try:
  discard p.readRow
  if i  >= minRow:
tableEntries[i - minRow]  =  p.row # i - minRow to begin indexing 
at 0
except:
  raise newException(IOError, "row not found")
  
  # need to convert from tableEntries[y][x] to tableEntries[x][y]
  for x in 0..