`isInstanceOf` problem with multiple `impl`
Hello! I'm glad you added this feature, but currently this work only for this case:
import oolib
protocol Launchable:
proc prepareForLaunch()
proc launch()
proc stop()
protocol HotCompilable:
proc configureReloading()
class ServerLaunchable impl (Launchable):
proc prepareForLaunch = discard
proc launch = discard
proc stop = discard
proc configureReloading = discard
let serverLaunchable = ServerLaunchable.new()
echo serverLaunchable.isInstanceOf(Launchable) #true
echo serverLaunchable.isInstanceOf(HotCompilable) #false
and not for this:
import oolib
protocol Launchable:
proc prepareForLaunch()
proc launch()
proc stop()
protocol HotCompilable:
proc configureReloading()
class ServerLaunchable impl (Launchable, HotCompilable):
proc prepareForLaunch = discard
proc launch = discard
proc stop = discard
proc configureReloading = discard
let serverLaunchable = ServerLaunchable.new()
echo serverLaunchable.isInstanceOf(Launchable) #false
echo serverLaunchable.isInstanceOf(HotCompilable) #false
Tryed rewrite code for checking like this:
macro isInstanceOf*(value: typed, protocol: typed): bool =
let protocolDefinition = if ProtocolTable.hasKey(protocol.strVal):
protocol
else:
newEmptyNode()
if protocolDefinition.kind == nnkEmpty: return newLit(false)
let protocolImpl = getImpl(protocol)
for protocolFieldIndex, protocolFieldNode in protocolImpl[2]:
let protocolParameterName = if protocolFieldNode.kind == nnkIdent: protocolFieldNode[0].strVal else: repr(protocolFieldNode[0])
let protocolParameterType = protocolFieldNode[1]
let destinationImpl = if value.kind == nnkObjConstr: getImpl(value[0]) else: getImpl(getImpl(value)[2][1])
var isValid = false
for destinationFieldIndex, destinationFieldNode in destinationImpl[2][0][2]:
let parameterName = if destinationFieldNode.kind == nnkIdent: destinationFieldNode[0].strVal else: repr(destinationFieldNode[0])
let parameterType = destinationFieldNode[1]
isValid = isValid or (protocolParameterName == parameterName) and (protocolParameterType == parameterType)
result = newLit(isValid)
but seem's like procedures not stored like destination proc fields, and then from your side need make CacheTable like [Destination, seq[proc]], where destination - generated type for protocol impl, and seq[proc] is implemented procedures
For example, my idea works with that code:
macro isInstanceOf*(value: typed, protocol: typed): bool =
let protocolDefinition = if ProtocolTable.hasKey(protocol.strVal):
protocol
else:
newEmptyNode()
if protocolDefinition.kind == nnkEmpty: return newLit(false)
let protocolImpl = getImpl(protocol)
var isValidDestination = false
for protocolFieldIndex, protocolFieldNode in protocolImpl[2]:
let protocolParameterName = if protocolFieldNode.kind == nnkIdent: protocolFieldNode[0].strVal else: repr(protocolFieldNode[0])
let protocolParameterType = protocolFieldNode[1]
let destinationImpl = if value.kind == nnkObjConstr: getImpl(value[0]) else: getImpl(getImpl(value)[2][1])
for destinationFieldIndex, destinationFieldNode in destinationImpl[2][0][2]:
let parameterName = if destinationFieldNode.kind == nnkIdent: destinationFieldNode[0].strVal else: repr(destinationFieldNode[0])
let parameterType = destinationFieldNode[1]
isValidDestination = isValidDestination or (protocolParameterName == parameterName) and (protocolParameterType == parameterType)
if result.kind == nnkEmpty:
result = newLit(isValidDestination)
elif result.kind == nnkSym:
let storedValue = result.boolVal
if storedValue and not isValidDestination:
return newLit(false)
and then testing code:
import oolib
protocol Launchable:
proc prepareForLaunch()
proc launch()
proc stop()
protocol HotCompilable:
proc configureReloading()
protocol Understable:
proc idk()
class ServerLaunchable impl (Launchable, HotCompilable):
proc prepareForLaunch = discard
proc launch = discard
proc stop = discard
proc configureReloading = discard
type IDK = ref object
configureReloading: proc()
idk: proc()
let serverLaunchable = ServerLaunchable.new()
echo IDK().isInstanceOf(HotCompilable) #true
echo IDK().isInstanceOf(Understable) #true
echo IDK().isInstanceOf(Launchable) #false
echo serverLaunchable.isInstanceOf(Launchable) #false
echo serverLaunchable.isInstanceOf(HotCompilable) #false
echo serverLaunchable.isInstanceOf(Understable) #false
echo serverLaunchable.isInstanceOf(string) #false
Thank you for letting me know this issue, I've completely forgotten about multiple implementation.
I was unsure of how to proceed, but I now realize making protocols with custom pragma can be an easier solution. This will allow isInstanceOf to read their names to check whether an instance matches a type.
protocol P:
...
protocol P2:
class C impl (P, P2):
...
# will be converted to below
type P = tuple
...
type C {.derive: ["P", "P2"].} = ref object
...
What's the status about this?
My apologies for my late response. I had been struggling with my own problems. Would you check if isInstanceOf() works properly?