compiler bug about generic type, dot operators
The following code runs on windows only, and requires
when nim compiles the code
import sugar
import winim/clr
var
mscor* = load("mscorlib")
NPOIOOXML* = clr.load("NPOI.OOXML.dll")
var
File* = mscor.GetType("System.IO.File")
WorkbookFactory* = NPOIOOXML.GetType("NPOI.SS.UserModel.WorkbookFactory")
# proc fn(fnExcel: string, sthSheet: int|string): int = # error too
proc fn(fnExcel: string, sthSheet: int|string=0): int = # error
var stream= @File.OpenRead(fnExcel)
var workbook = @WorkbookFactory.Create(stream);
return workbook.NumberOfSheets
var fnExcel = "testR.xlsx"
dump fn(fnExcel, 0)
#~ dump fn(fnExcel, "Sheet1")
it says
........................................................................................................................
D:\tmp\compareexcel\b.nim(19, 6) template/generic instantiation of `dump` from here
E:\msys64\home\USER\_nim\nim\lib\pure\sugar.nim(171, 12) template/generic instantiation of `fn` from here
D:\tmp\compareexcel\b.nim(14, 36) Error: type mismatch: got <CLRType, CLRVariant>
but expected one of:
proc Create(self: ptr IPropertySetStorage; rfmtid: REFFMTID; pclsid: ptr CLSID;
grfFlags: DWORD; grfMode: DWORD; ppprstg: ptr ptr IPropertyStorage): HRESULT
first type mismatch at position: 1
required type for self: ptr IPropertySetStorage
but expression '@WorkbookFactory' is of type: CLRType
proc Create(self: ptr IShellImageStore; dwMode: DWORD; pdwLock: ptr DWORD): HRESULT
first type mismatch at position: 1
required type for self: ptr IShellImageStore
but expression '@WorkbookFactory' is of type: CLRType
expression: Create(@WorkbookFactory, stream)
however, the following 2 codes can be compiled and run without problem
# good code 1
import sugar
import winim/clr
var
mscor* = load("mscorlib")
NPOIOOXML* = clr.load("NPOI.OOXML.dll")
var
File* = mscor.GetType("System.IO.File")
WorkbookFactory* = NPOIOOXML.GetType("NPOI.SS.UserModel.WorkbookFactory")
proc fn(fnExcel: string, intSheet: int=0): int =
var stream= @File.OpenRead(fnExcel)
var workbook = @WorkbookFactory.Create(stream);
return workbook.NumberOfSheets
var fnExcel = "testR.xlsx"
dump fn(fnExcel, 0)
and
# good code 2
import sugar
import winim/clr
var
mscor* = load("mscorlib")
NPOIOOXML* = clr.load("NPOI.OOXML.dll")
var
File* = mscor.GetType("System.IO.File")
WorkbookFactory* = NPOIOOXML.GetType("NPOI.SS.UserModel.WorkbookFactory")
proc fn(fnExcel: string, strSheet: string="Sheet1"): int =
var stream= @File.OpenRead(fnExcel)
var workbook = @WorkbookFactory.Create(stream);
return workbook.NumberOfSheets
var fnExcel = "testR.xlsx"
dump fn(fnExcel, "Sheet1")
Since it is a simplified version, the parameter strSheet/intSheet/sthSheet is not used here, however in my real code, it is need and can not be omitted.
Minimized:
{.experimental: "dotOperators".}
type Foo = object
x: int
proc bar(a, b: int): int = a + b
template `.`(a: Foo, b): untyped = a.x
proc generic[T]() =
echo Foo(x: 3).bar
generic[void]()
So dot operators don't work with overloaded symbols inside generic procs. int | string in your fn proc makes it generic. The workaround is
proc fn(fnExcel: string, sthSheet: int|string=0): int =
var stream= @File.OpenRead(fnExcel)
var workbook = `.`(@WorkbookFactory, Create, stream)
return workbook.NumberOfSheets
Fwiw dot operators are known to not work well with generics. Which is why they were declared "experimental". But finding a design for them that actually works would be nice.