diff options
author | Araq <rumpf_a@web.de> | 2012-08-06 18:11:03 +0200 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2012-08-06 18:11:03 +0200 |
commit | ce23b814a0255a1a20eefff5e9b3679d52b8aa43 (patch) | |
tree | 7cf5ee8f11d53cd7aa45cebb4e8bbdbb3e6545bf | |
parent | 5cd933a44d37b46dd3a1f349777efca6eaaf11e2 (diff) | |
download | Nim-ce23b814a0255a1a20eefff5e9b3679d52b8aa43.tar.gz |
borrow works with generics
-rwxr-xr-x | compiler/procfind.nim | 70 | ||||
-rwxr-xr-x | compiler/semcall.nim | 14 | ||||
-rwxr-xr-x | compiler/types.nim | 14 | ||||
-rw-r--r-- | tests/run/tborrow.nim | 21 | ||||
-rwxr-xr-x | todo.txt | 1 | ||||
-rwxr-xr-x | web/news.txt | 1 |
6 files changed, 79 insertions, 42 deletions
diff --git a/compiler/procfind.nim b/compiler/procfind.nim index 34a3482f8..eefe734b3 100755 --- a/compiler/procfind.nim +++ b/compiler/procfind.nim @@ -13,14 +13,6 @@ import ast, astalgo, msgs, semdata, types, trees -proc SearchForProc*(c: PContext, fn: PSym, tos: int): PSym - # Searchs for the fn in the symbol table. If the parameter lists are exactly - # the same the sym in the symbol table is returned, else nil. -proc SearchForBorrowProc*(c: PContext, fn: PSym, tos: int): PSym - # Searchs for the fn in the symbol table. If the parameter lists are suitable - # for borrowing the sym in the symbol table is returned, else nil. -# implementation - proc equalGenericParams(procA, procB: PNode): bool = var a, b: PSym result = procA == procB @@ -41,7 +33,9 @@ proc equalGenericParams(procA, procB: PNode): bool = if not ExprStructuralEquivalent(a.ast, b.ast): return result = true -proc SearchForProc(c: PContext, fn: PSym, tos: int): PSym = +proc SearchForProc*(c: PContext, fn: PSym, tos: int): PSym = + # Searchs for the fn in the symbol table. If the parameter lists are exactly + # the same the sym in the symbol table is returned, else nil. var it: TIdentIter result = initIdentIter(it, c.tab.stack[tos], fn.Name) while result != nil: @@ -58,36 +52,30 @@ proc SearchForProc(c: PContext, fn: PSym, tos: int): PSym = nil result = NextIdentIter(it, c.tab.stack[tos]) -proc paramsFitBorrow(child, parent: PNode): bool = - var length = sonsLen(child) - result = false - if length == sonsLen(parent): - for i in countup(1, length - 1): - var m = child.sons[i].sym - var n = parent.sons[i].sym - assert((m.kind == skParam) and (n.kind == skParam)) - if not compareTypes(m.typ, n.typ, dcEqOrDistinctOf): return - if not compareTypes(child.sons[0].typ, parent.sons[0].typ, - dcEqOrDistinctOf): return - result = true - -proc SearchForBorrowProc(c: PContext, fn: PSym, tos: int): PSym = - # Searchs for the fn in the symbol table. If the parameter lists are suitable - # for borrowing the sym in the symbol table is returned, else nil. - var it: TIdentIter - for scope in countdown(tos, 0): - result = initIdentIter(it, c.tab.stack[scope], fn.Name) - while result != nil: - # watchout! result must not be the same as fn! - if (result.Kind == fn.kind) and (result.id != fn.id): - if equalGenericParams(result.ast.sons[genericParamsPos], - fn.ast.sons[genericParamsPos]): - if paramsFitBorrow(fn.typ.n, result.typ.n): return - result = NextIdentIter(it, c.tab.stack[scope]) +when false: + proc paramsFitBorrow(child, parent: PNode): bool = + var length = sonsLen(child) + result = false + if length == sonsLen(parent): + for i in countup(1, length - 1): + var m = child.sons[i].sym + var n = parent.sons[i].sym + assert((m.kind == skParam) and (n.kind == skParam)) + if not compareTypes(m.typ, n.typ, dcEqOrDistinctOf): return + if not compareTypes(child.sons[0].typ, parent.sons[0].typ, + dcEqOrDistinctOf): return + result = true -proc SearchForBorrowProc2(c: PContext, fn: PSym, tos: int): PSym = - # Searchs for the fn in the symbol table. If the parameter lists are suitable - # for borrowing the sym in the symbol table is returned, else nil. - # New approach: generate fn(x, y, z) where x, y, z have the proper types - # and use the overloading resolution mechanism: - nil + proc SearchForBorrowProc*(c: PContext, fn: PSym, tos: int): PSym = + # Searchs for the fn in the symbol table. If the parameter lists are suitable + # for borrowing the sym in the symbol table is returned, else nil. + var it: TIdentIter + for scope in countdown(tos, 0): + result = initIdentIter(it, c.tab.stack[scope], fn.Name) + while result != nil: + # watchout! result must not be the same as fn! + if (result.Kind == fn.kind) and (result.id != fn.id): + if equalGenericParams(result.ast.sons[genericParamsPos], + fn.ast.sons[genericParamsPos]): + if paramsFitBorrow(fn.typ.n, result.typ.n): return + result = NextIdentIter(it, c.tab.stack[scope]) diff --git a/compiler/semcall.nim b/compiler/semcall.nim index eca8d75f0..e4655c5ba 100755 --- a/compiler/semcall.nim +++ b/compiler/semcall.nim @@ -150,3 +150,17 @@ proc explicitGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode = else: result = explicitGenericInstError(n) +proc SearchForBorrowProc(c: PContext, fn: PSym, tos: int): PSym = + # Searchs for the fn in the symbol table. If the parameter lists are suitable + # for borrowing the sym in the symbol table is returned, else nil. + # New approach: generate fn(x, y, z) where x, y, z have the proper types + # and use the overloading resolution mechanism: + var call = newNode(nkCall) + call.add(newIdentNode(fn.name, fn.info)) + for i in 1.. <fn.typ.n.len: + let param = fn.typ.n.sons[i] + let t = skipTypes(param.typ, abstractVar) + call.add(newNodeIT(nkEmpty, fn.info, t.baseOfDistinct)) + var resolved = semOverloadedCall(c, call, call, {fn.kind}) + if resolved != nil: + result = resolved.sons[0].sym diff --git a/compiler/types.nim b/compiler/types.nim index ce044c2eb..c4d218f2b 100755 --- a/compiler/types.nim +++ b/compiler/types.nim @@ -1108,3 +1108,17 @@ proc containsGenericTypeIter(t: PType, closure: PObject): bool = proc containsGenericType*(t: PType): bool = result = iterOverType(t, containsGenericTypeIter, nil) + +proc baseOfDistinct*(t: PType): PType = + if t.kind == tyDistinct: + result = t.sons[0] + else: + result = copyType(t, t.owner, false) + var parent: PType = nil + var it = result + while it.kind in {tyPtr, tyRef}: + parent = it + it = it.sons[0] + if it.kind == tyDistinct: + internalAssert parent != nil + parent.sons[0] = it.sons[0] diff --git a/tests/run/tborrow.nim b/tests/run/tborrow.nim new file mode 100644 index 000000000..8e6aeba74 --- /dev/null +++ b/tests/run/tborrow.nim @@ -0,0 +1,21 @@ +discard """ + output: "4887 true" +""" + +# test the new borrow feature that works with generics: + +proc `++`*[T: int | float](a, b: T): T = + result = a + b + +type + DI = distinct int + DF = distinct float + DS = distinct string + +proc `++`(x, y: DI): DI {.borrow.} +proc `++`(x, y: DF): DF {.borrow.} + +proc `$`(x: DI): string {.borrow.} +proc `$`(x: DF): string {.borrow.} + +echo 4544.DI ++ 343.di, " ", (4.5.df ++ 0.5.df).float == 5.0 diff --git a/todo.txt b/todo.txt index 40e9f7003..3cce1721c 100755 --- a/todo.txt +++ b/todo.txt @@ -5,7 +5,6 @@ version 0.9.0 module vars - implicit deref for parameter matching -- ``borrow`` needs to take type classes into account - optimize genericAssign in the code generator - fix remaining closure bugs: - fix evals.nim with closures diff --git a/web/news.txt b/web/news.txt index b445ff8c4..74d91e601 100755 --- a/web/news.txt +++ b/web/news.txt @@ -145,6 +145,7 @@ Language Additions - A semicolon can now be used to have multiple simple statements on a single line: ``inc i; inc j``. - ``bind`` supports overloaded symbols and operators. +- A ``distinct`` type can now borrow from generic procs. 2012-02-09 Version 0.8.14 released |