-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
6ea13df
commit 5a67758
Showing
3 changed files
with
218 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
let foo1* = [1,2] ## c1 | ||
var foo2* = "asdf" ## c2 | ||
const foo3* = 'a' ## c3 | ||
|
||
proc `@@@`*(a: int) = discard | ||
proc `@@@`*(a: float) = discard | ||
proc `@@@`*[T: Ordinal](a: T) = discard | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
import std/macros | ||
|
||
macro overloadExistsImpl(x: typed): bool = | ||
newLit(x != nil) | ||
|
||
template overloadExists*(a: untyped): bool = | ||
overloadExistsImpl(resolveSymbol(a)) | ||
|
||
type InstantiationInfo = type(instantiationInfo()) | ||
|
||
proc toStr(info: InstantiationInfo | LineInfo): string = | ||
const offset = 1 | ||
result = info.filename & ":" & $info.line & ":" & $(info.column + offset) | ||
|
||
proc inspectImpl*(s: var string, a: NimNode, resolveLet: bool) = | ||
var a = a | ||
if resolveLet: | ||
a = a.getImpl | ||
a = a[2] | ||
case a.kind | ||
of nnkClosedSymChoice: | ||
s.add "closedSymChoice:" | ||
for ai in a: | ||
s.add "\n " | ||
inspectImpl(s, ai, false) | ||
of nnkSym: | ||
var a2 = a.getImpl | ||
const callables = {nnkProcDef, nnkMethodDef, nnkConverterDef, nnkMacroDef, nnkTemplateDef, nnkIteratorDef} | ||
if a2.kind in callables: | ||
let a20=a2 | ||
a2 = newTree(a20.kind) | ||
for i, ai in a20: | ||
a2.add if i notin [6]: ai else: newEmptyNode() | ||
s.add a2.lineInfoObj.toStr & " " & a2.repr | ||
else: error($a.kind, a) | ||
|
||
macro inspect*(a: typed, resolveLet: static bool = false): untyped = | ||
var a = a | ||
if a.kind == nnkTupleConstr: | ||
a = a[0] | ||
var s: string | ||
s.add a.lineInfoObj.toStr & ": " | ||
s.add a.repr & " = " | ||
inspectImpl(s, a, resolveLet) | ||
echo s |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,165 @@ | ||
#[ | ||
D20190825T173945 | ||
]# | ||
|
||
import ./mresolves | ||
|
||
template bail() = static: doAssert false | ||
|
||
proc funDecl1(a: int) {.importc.} | ||
proc funDecl2(a: int) | ||
|
||
proc fun(a: int) = discard | ||
|
||
template fun2(a = 0) = bail() | ||
template fun3() = bail() | ||
|
||
proc fun4(a: float) = discard | ||
|
||
proc fun4[T](a: T) = | ||
static: echo "in fun4" | ||
bail() | ||
|
||
macro fun5(a: typed): untyped = discard | ||
macro fun6(a: untyped): untyped = discard | ||
iterator fun7(a: int): auto = yield 1 | ||
|
||
proc fun8(a: int): auto = (a, "int") | ||
proc fun8(a: float): tuple = (a,"float") | ||
template fun8(a: string) = discard | ||
template fun8(a: char = 'x') = discard | ||
template fun8() = discard | ||
macro fun8(b = 1'u8): untyped = discard | ||
macro fun8(c: static bool): untyped = discard | ||
|
||
proc fun8(d: var int) = d.inc | ||
|
||
proc main()= | ||
static: | ||
doAssert overloadExists(fun4(1)) | ||
doAssert not compiles(fun4(1)) | ||
doAssert overloadExists(fun4(1)) | ||
doAssert overloadExists(fun4(1.2)) | ||
doAssert not overloadExists(fun4()) | ||
# doAssert not overloadExists(nonexistant(1)) # should we error with `Error: undeclared identifier: 'nonexistant'` ? A: probly should just return false, eg: imagine for: ` 1 @ 2` | ||
|
||
doAssert overloadExists(funDecl1(1)) | ||
doAssert not overloadExists(funDecl1(1.0)) | ||
doAssert overloadExists(funDecl2(1)) | ||
|
||
doAssert overloadExists(fun(1)) | ||
doAssert overloadExists(1+1) | ||
doAssert not overloadExists('a'+1.2) | ||
|
||
doAssert not overloadExists(fun(1.1)) | ||
doAssert not overloadExists(fun(1, 2)) | ||
doAssert overloadExists(fun2()) | ||
doAssert overloadExists(fun2(1)) | ||
doAssert overloadExists(fun3()) | ||
doAssert not overloadExists(fun3(1)) | ||
|
||
# subtlety: if arguments for a `typed` formal param are not well typed, | ||
# we error instead of return false | ||
doAssert not compiles overloadExists(fun5(1 + 'a')) | ||
|
||
doAssert overloadExists(fun5(1 + 1)) | ||
doAssert not overloadExists(fun5(1 + 1, 2)) | ||
doAssert overloadExists(fun6(1 + 'a')) | ||
doAssert not overloadExists(fun6(1 + 'a', 2)) | ||
doAssert overloadExists(fun7(1)) | ||
doAssert not overloadExists(fun7()) | ||
|
||
doAssert resolveSymbol(fun8(1))(3) == fun8(3) | ||
inspect resolveSymbol(fun8) | ||
|
||
inspect resolveSymbol(fun7) | ||
inspect resolveSymbol(fun8(1)) | ||
inspect resolveSymbol(fun8(1.2)) | ||
inspect resolveSymbol(fun8("asdf")) | ||
inspect resolveSymbol(fun8('a')) | ||
doAssert compiles(resolveSymbol(fun8('a'))) | ||
doAssert not compiles(resolveSymbol(fun8())) # correctly would give ambiguous error | ||
inspect resolveSymbol(fun8(b = 1)) | ||
inspect resolveSymbol(fun8(c = false)) | ||
inspect resolveSymbol(1.1 / 2.0) | ||
|
||
block: | ||
var c1 = false | ||
doAssert not overloadExists(fun8(c = c1)) | ||
const c2 = false | ||
doAssert overloadExists(fun8(c = c2)) | ||
var c3 = 10 | ||
doAssert overloadExists(fun8(d = c3)) | ||
doAssert c3 == 10 | ||
resolveSymbol(fun8(d = c3))(d = c3) | ||
doAssert c3 == 11 | ||
let t = resolveSymbol(fun8(d = c3)) | ||
doAssert type(t) is proc | ||
t(d = c3) | ||
doAssert c3 == 12 | ||
|
||
block: | ||
var z = 10 | ||
proc fun9(z0: int) = z+=z0 | ||
proc fun9(z0: float) = doAssert false | ||
let t = resolveSymbol(fun9(12)) | ||
# can't work with `const t = fun9`: invalid type for const | ||
doAssert type(t) is proc | ||
t(3) | ||
doAssert z == 10+3 | ||
inspect resolveSymbol(fun9(12)) | ||
inspect(resolveSymbol(t), resolveLet=true) | ||
|
||
import std/strutils | ||
import std/macros | ||
import std/macros as macrosAlias | ||
import ./mresolve_overloads | ||
|
||
proc main2()= | ||
block: | ||
inspect resolveSymbol(`@@@`) | ||
|
||
let t = resolveSymbol toUpper("asdf") | ||
inspect resolveSymbol(t), resolveLet=true | ||
doAssert t("asdf") == "ASDF" | ||
let t2 = resolveSymbol strutils.toUpper("asdf") | ||
inspect resolveSymbol(t2), resolveLet=true | ||
doAssert t2("asdf") == "ASDF" | ||
|
||
inspect resolveSymbol(strutils.toUpper) | ||
inspect resolveSymbol(strutils.`toUpper`) | ||
inspect resolveSymbol(`toUpper`) | ||
# overloaded | ||
inspect resolveSymbol(`$`) | ||
inspect resolveSymbol(system.`$`) | ||
|
||
doAssert compiles resolveSymbol(system.compiles) | ||
inspect resolveSymbol(system.compiles) | ||
doAssert not compiles resolveSymbol(system.nonexistant) | ||
doAssert not compiles resolveSymbol(nonexistant) | ||
|
||
block: | ||
template bar1(): untyped = 12 | ||
inspect resolveSymbol(bar1) | ||
inspect resolveSymbol(currentSourcePath) | ||
inspect resolveSymbol(system.currentSourcePath) | ||
doAssert resolveSymbol(system.currentSourcePath)() == currentSourcePath() | ||
inspect resolveSymbol(system.uint16) | ||
inspect resolveSymbol(system.cint) | ||
inspect resolveSymbol(cint) | ||
inspect resolveSymbol(system.off) | ||
inspect resolveSymbol(newLit(true)) | ||
inspect resolveSymbol(foo1) | ||
inspect resolveSymbol(foo2) | ||
inspect resolveSymbol(foo3) | ||
inspect resolveSymbol(mresolve_overloads.foo3) | ||
inspect resolveSymbol(macros.nnkCallKinds) | ||
|
||
## module | ||
inspect resolveSymbol(macros) | ||
inspect resolveSymbol(macrosAlias) | ||
|
||
proc funDecl2(a: int) = discard | ||
|
||
main() | ||
main2() |