fixes #2022
This commit is contained in:
parent
8f587e2eab
commit
43e5e3ac22
3 changed files with 101 additions and 2 deletions
|
|
@ -215,6 +215,7 @@ proc asgnComplexity(n: PNode): int =
|
||||||
else: discard
|
else: discard
|
||||||
|
|
||||||
proc optAsgnLoc(a: TLoc, t: PType, field: PRope): TLoc =
|
proc optAsgnLoc(a: TLoc, t: PType, field: PRope): TLoc =
|
||||||
|
assert field != nil
|
||||||
result.k = locField
|
result.k = locField
|
||||||
result.s = a.s
|
result.s = a.s
|
||||||
result.t = t
|
result.t = t
|
||||||
|
|
@ -229,7 +230,7 @@ proc genOptAsgnTuple(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
|
||||||
flags - {needToCopy}
|
flags - {needToCopy}
|
||||||
else:
|
else:
|
||||||
flags
|
flags
|
||||||
let t = skipTypes(dest.t, abstractInst)
|
let t = skipTypes(dest.t, abstractInst).getUniqueType()
|
||||||
for i in 0 .. <t.len:
|
for i in 0 .. <t.len:
|
||||||
let t = t.sons[i]
|
let t = t.sons[i]
|
||||||
let field = ropef("Field$1", i.toRope)
|
let field = ropef("Field$1", i.toRope)
|
||||||
|
|
@ -336,6 +337,7 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
|
||||||
elif needsComplexAssignment(ty):
|
elif needsComplexAssignment(ty):
|
||||||
if ty.sons[0].isNil and asgnComplexity(ty.n) <= 4:
|
if ty.sons[0].isNil and asgnComplexity(ty.n) <= 4:
|
||||||
discard getTypeDesc(p.module, ty)
|
discard getTypeDesc(p.module, ty)
|
||||||
|
ty = getUniqueType(ty)
|
||||||
internalAssert ty.n != nil
|
internalAssert ty.n != nil
|
||||||
genOptAsgnObject(p, dest, src, flags, ty.n)
|
genOptAsgnObject(p, dest, src, flags, ty.n)
|
||||||
else:
|
else:
|
||||||
|
|
@ -1131,7 +1133,7 @@ proc genObjConstr(p: BProc, e: PNode, d: var TLoc) =
|
||||||
var tmp2: TLoc
|
var tmp2: TLoc
|
||||||
tmp2.r = r
|
tmp2.r = r
|
||||||
var field: PSym = nil
|
var field: PSym = nil
|
||||||
var ty = t
|
var ty = getUniqueType(t)
|
||||||
while ty != nil:
|
while ty != nil:
|
||||||
field = lookupInRecord(ty.n, it.sons[0].sym.name)
|
field = lookupInRecord(ty.n, it.sons[0].sym.name)
|
||||||
if field != nil: break
|
if field != nil: break
|
||||||
|
|
|
||||||
37
tests/generics/tgeneric_closure.nim
Normal file
37
tests/generics/tgeneric_closure.nim
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
# Test to ensure TEventHandler is '.closure'
|
||||||
|
|
||||||
|
# bug #1187
|
||||||
|
|
||||||
|
type
|
||||||
|
TEventArgs* = object
|
||||||
|
skip*: bool
|
||||||
|
TEventHandler[T] = proc (e: var TEventArgs, data: T) {.closure.}
|
||||||
|
TEvent*[T] = object
|
||||||
|
#handlers: seq[TEventHandler[T]] # Does not work
|
||||||
|
handlers: seq[proc (e: var TEventArgs, data: T) {.closure.}] # works
|
||||||
|
|
||||||
|
TData = object
|
||||||
|
x: int
|
||||||
|
|
||||||
|
TSomething = object
|
||||||
|
s: TEvent[TData]
|
||||||
|
|
||||||
|
proc init*[T](e: var TEvent[T]) =
|
||||||
|
e.handlers.newSeq(0)
|
||||||
|
|
||||||
|
#proc add*[T](e: var TEvent[T], h: proc (e: var TEventArgs, data: T) {.closure.}) =
|
||||||
|
# this line works
|
||||||
|
proc add*[T](e: var TEvent[T], h: TEventHandler[T]) =
|
||||||
|
# this line does not work
|
||||||
|
e.handlers.add(h)
|
||||||
|
|
||||||
|
proc main () =
|
||||||
|
var something: TSomething
|
||||||
|
something.s.init()
|
||||||
|
var fromOutside = 4711
|
||||||
|
|
||||||
|
something.s.add() do (e: var TEventArgs, data: TData):
|
||||||
|
var x = data.x
|
||||||
|
x = fromOutside
|
||||||
|
|
||||||
|
main()
|
||||||
60
tests/generics/tunique_type.nim
Normal file
60
tests/generics/tunique_type.nim
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
# Bug #2022
|
||||||
|
|
||||||
|
## The goal of this snippet is to provide and test a construct for general-
|
||||||
|
## purpose, random-access mapping. I use an AST-manipulation-based approach
|
||||||
|
## because it's more efficient than using procedure pointers and less
|
||||||
|
## verbose than defining a new callable type for every invocation of `map`.
|
||||||
|
|
||||||
|
import future
|
||||||
|
import macros
|
||||||
|
import strutils
|
||||||
|
|
||||||
|
#===============================================================================
|
||||||
|
# Define a system for storing copies of ASTs as static strings.
|
||||||
|
# This serves the same purpose as D's `alias` parameters for types, used heavily
|
||||||
|
# in its popular `ranges` and `algorithm` modules.
|
||||||
|
|
||||||
|
var exprNodes {.compileTime.} = newSeq[PNimrodNode]()
|
||||||
|
|
||||||
|
proc refExpr(exprNode: PNimrodNode): string {.compileTime.} =
|
||||||
|
exprNodes.add exprNode.copy
|
||||||
|
"expr" & $(exprNodes.len - 1)
|
||||||
|
|
||||||
|
proc derefExpr(exprRef: string): PNimrodNode {.compileTime.} =
|
||||||
|
exprNodes[parseInt(exprRef[4 .. -1])]
|
||||||
|
|
||||||
|
#===============================================================================
|
||||||
|
# Define a type that allows a callable expression to be mapped onto elements
|
||||||
|
# of an indexable collection.
|
||||||
|
|
||||||
|
type Mapped[Input; predicate: static[string]] = object
|
||||||
|
input: Input
|
||||||
|
|
||||||
|
macro map(input, predicate: expr): expr =
|
||||||
|
newNimNode(nnkObjConstr).add(
|
||||||
|
newNimNode(nnkBracketExpr).add(
|
||||||
|
ident"Mapped",
|
||||||
|
newNimNode(nnkTypeOfExpr).add(input),
|
||||||
|
newLit(refExpr(predicate))),
|
||||||
|
newNimNode(nnkExprColonExpr).add(
|
||||||
|
ident"input", input))
|
||||||
|
|
||||||
|
proc `[]`(m: Mapped, i: int): auto =
|
||||||
|
macro buildResult: expr =
|
||||||
|
newCall(
|
||||||
|
derefExpr(m.predicate),
|
||||||
|
newNimNode(nnkBracketExpr).add(
|
||||||
|
newDotExpr(ident"m", ident"input"),
|
||||||
|
ident"i"))
|
||||||
|
buildResult()
|
||||||
|
|
||||||
|
#===============================================================================
|
||||||
|
# Test out our generic mapping construct.
|
||||||
|
|
||||||
|
let a = "a-string".map(ord)
|
||||||
|
let b = @["a", "seq"].map((e: string) => e == "a")
|
||||||
|
let c = "another-string".map((e: char) => e == 'o')
|
||||||
|
|
||||||
|
echo(@[a[0], a[1]]) # @[97, 45]
|
||||||
|
echo(@[b[0], b[1]]) # @[true, false]
|
||||||
|
echo(@[c[0], c[1]]) # @[false, false]
|
||||||
Loading…
Add table
Add a link
Reference in a new issue