overloading of '=' works
This commit is contained in:
parent
78f371c03a
commit
05e39cf6ad
9 changed files with 147 additions and 6 deletions
|
|
@ -190,6 +190,7 @@ proc liftBodyAux(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
|||
of tyArrayConstr, tyArray, tySequence:
|
||||
if tfHasAsgn in t.flags:
|
||||
if t.kind == tySequence:
|
||||
# XXX add 'nil' handling here
|
||||
body.add newSeqCall(c.c, x, y)
|
||||
let i = declareCounter(c, body, firstOrd(t))
|
||||
let whileLoop = genWhileLoop(c, i, x)
|
||||
|
|
|
|||
|
|
@ -1233,8 +1233,6 @@ proc asgnToResultVar(c: PContext, n, le, ri: PNode) {.inline.} =
|
|||
template resultTypeIsInferrable(typ: PType): expr =
|
||||
typ.isMetaType and typ.kind != tyTypeDesc
|
||||
|
||||
include semasgn
|
||||
|
||||
proc semAsgn(c: PContext, n: PNode): PNode =
|
||||
checkSonsLen(n, 2)
|
||||
var a = n.sons[0]
|
||||
|
|
|
|||
|
|
@ -340,6 +340,39 @@ proc checkNilable(v: PSym) =
|
|||
elif tfNotNil in v.typ.flags and tfNotNil notin v.ast.typ.flags:
|
||||
message(v.info, warnProveInit, v.name.s)
|
||||
|
||||
include semasgn
|
||||
|
||||
proc addToVarSection(c: PContext; result: var PNode; orig, identDefs: PNode) =
|
||||
# consider this:
|
||||
# var
|
||||
# x = 0
|
||||
# withOverloadedAssignment = foo()
|
||||
# y = use(withOverloadedAssignment)
|
||||
# We need to split this into a statement list with multiple 'var' sections
|
||||
# in order for this transformation to be correct.
|
||||
let L = identDefs.len
|
||||
let value = identDefs[L-1]
|
||||
if value.typ != nil and tfHasAsgn in value.typ.flags:
|
||||
# the spec says we need to rewrite 'var x = T()' to 'var x: T; x = T()':
|
||||
identDefs.sons[L-1] = emptyNode
|
||||
if result.kind != nkStmtList:
|
||||
let oldResult = result
|
||||
oldResult.add identDefs
|
||||
result = newNodeI(nkStmtList, result.info)
|
||||
result.add oldResult
|
||||
else:
|
||||
let o = copyNode(orig)
|
||||
o.add identDefs
|
||||
result.add o
|
||||
for i in 0 .. L-3:
|
||||
result.add overloadedAsgn(c, identDefs[i], value)
|
||||
elif result.kind == nkStmtList:
|
||||
let o = copyNode(orig)
|
||||
o.add identDefs
|
||||
result.add o
|
||||
else:
|
||||
result.add identDefs
|
||||
|
||||
proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
|
||||
var b: PNode
|
||||
result = copyNode(n)
|
||||
|
|
@ -396,7 +429,7 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
|
|||
newSons(b, length)
|
||||
b.sons[length-2] = a.sons[length-2] # keep type desc for doc generator
|
||||
b.sons[length-1] = def
|
||||
addSon(result, b)
|
||||
addToVarSection(c, result, n, b)
|
||||
elif tup.kind == tyTuple and def.kind == nkPar and
|
||||
a.kind == nkIdentDefs and a.len > 3:
|
||||
message(a.info, warnEachIdentIsTuple)
|
||||
|
|
@ -429,7 +462,7 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
|
|||
addSon(b, newSymNode(v))
|
||||
addSon(b, a.sons[length-2]) # keep type desc for doc generator
|
||||
addSon(b, copyTree(def))
|
||||
addSon(result, b)
|
||||
addToVarSection(c, result, n, b)
|
||||
else:
|
||||
if def.kind == nkPar: v.ast = def[j]
|
||||
v.typ = tup.sons[j]
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ operator `=`
|
|||
------------
|
||||
|
||||
This operator is the assignment operator. Note that in the contexts
|
||||
like ``result = expr``, ``parameter = defaultValue`` or for
|
||||
``result = expr``, ``parameter = defaultValue`` or for
|
||||
parameter passing no assignment is performed. For a type ``T`` that has an
|
||||
overloaded assignment operator ``var v = T()`` is rewritten
|
||||
to ``var v: T; v = T()``; in other words ``var`` and ``let`` contexts do count
|
||||
|
|
|
|||
10
tests/assign/moverload_asgn2.nim
Normal file
10
tests/assign/moverload_asgn2.nim
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
type
|
||||
Concrete* = object
|
||||
a*, b*: string
|
||||
rc*: int # refcount
|
||||
|
||||
proc `=`(d: var Concrete; src: Concrete) =
|
||||
shallowCopy(d.a, src.a)
|
||||
shallowCopy(d.b, src.b)
|
||||
dec d.rc
|
||||
d.rc = src.rc + 1
|
||||
75
tests/assign/toverload_asgn1.nim
Normal file
75
tests/assign/toverload_asgn1.nim
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
discard """
|
||||
output: '''Concrete '='
|
||||
Concrete '='
|
||||
Concrete '='
|
||||
Concrete '='
|
||||
Concrete '='
|
||||
GenericT[T] '=' int
|
||||
GenericT[T] '=' float
|
||||
GenericT[T] '=' float
|
||||
GenericT[T] '=' float
|
||||
GenericT[T] '=' string
|
||||
GenericT[T] '=' int8
|
||||
GenericT[T] '=' bool
|
||||
GenericT[T] '=' bool
|
||||
GenericT[T] '=' bool
|
||||
GenericT[T] '=' bool'''
|
||||
"""
|
||||
|
||||
import typetraits
|
||||
|
||||
type
|
||||
Concrete = object
|
||||
a, b: string
|
||||
|
||||
proc `=`(d: var Concrete; src: Concrete) =
|
||||
shallowCopy(d.a, src.a)
|
||||
shallowCopy(d.b, src.b)
|
||||
echo "Concrete '='"
|
||||
|
||||
var x, y: array[0..2, Concrete]
|
||||
var cA, cB: Concrete
|
||||
|
||||
var cATup, cBTup: tuple[x: int, ha: Concrete]
|
||||
|
||||
x = y
|
||||
cA = cB
|
||||
cATup = cBTup
|
||||
|
||||
type
|
||||
GenericT[T] = object
|
||||
a, b: T
|
||||
|
||||
proc `=`[T](d: var GenericT[T]; src: GenericT[T]) =
|
||||
shallowCopy(d.a, src.a)
|
||||
shallowCopy(d.b, src.b)
|
||||
echo "GenericT[T] '=' ", type(T).name
|
||||
|
||||
var ag: GenericT[int]
|
||||
var bg: GenericT[int]
|
||||
|
||||
ag = bg
|
||||
|
||||
var xg, yg: array[0..2, GenericT[float]]
|
||||
var cAg, cBg: GenericT[string]
|
||||
|
||||
var cATupg, cBTupg: tuple[x: int, ha: GenericT[int8]]
|
||||
|
||||
xg = yg
|
||||
cAg = cBg
|
||||
cATupg = cBTupg
|
||||
|
||||
var caSeqg, cbSeqg: seq[GenericT[bool]]
|
||||
newSeq(cbSeqg, 4)
|
||||
caSeqg = cbSeqg
|
||||
|
||||
when false:
|
||||
type
|
||||
Foo = object
|
||||
case b: bool
|
||||
of false: xx: GenericT[int]
|
||||
of true: yy: bool
|
||||
|
||||
var
|
||||
a, b: Foo
|
||||
a = b
|
||||
22
tests/assign/toverload_asgn2.nim
Normal file
22
tests/assign/toverload_asgn2.nim
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
discard """
|
||||
output: '''i value 88
|
||||
2aa'''
|
||||
"""
|
||||
|
||||
import moverload_asgn2
|
||||
|
||||
proc passAround(i: int): Concrete =
|
||||
echo "i value ", i
|
||||
result = Concrete(a: "aa", b: "bb", rc: 0)
|
||||
|
||||
proc main =
|
||||
let
|
||||
i = 88
|
||||
v = passAround(i)
|
||||
z = v.a
|
||||
var
|
||||
x: Concrete
|
||||
x = v
|
||||
echo x.rc, z # 2aa
|
||||
|
||||
main()
|
||||
2
todo.txt
2
todo.txt
|
|
@ -2,13 +2,13 @@ version 0.10.4
|
|||
==============
|
||||
|
||||
- make 'nil' work for 'add' and 'len'
|
||||
- overloading of '='
|
||||
- introduce typed/untyped types
|
||||
|
||||
|
||||
version 1.0
|
||||
===========
|
||||
|
||||
- macro support for '='; bind '=' to a memory region
|
||||
- remove echo $foo gotcha
|
||||
- add "all threads are blocked" detection to 'spawn'
|
||||
- figure out why C++ bootstrapping is so much slower
|
||||
|
|
|
|||
|
|
@ -113,6 +113,8 @@ News
|
|||
|
||||
- Array and seq indexing can now use the builtin ``^`` operator to access
|
||||
things from backwards: ``a[^1]`` is like Python's ``a[-1]``.
|
||||
- A first version of the specification and implementation of the overloading
|
||||
of the assignment operator has arrived!
|
||||
|
||||
|
||||
Library additions
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue