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:
|
of tyArrayConstr, tyArray, tySequence:
|
||||||
if tfHasAsgn in t.flags:
|
if tfHasAsgn in t.flags:
|
||||||
if t.kind == tySequence:
|
if t.kind == tySequence:
|
||||||
|
# XXX add 'nil' handling here
|
||||||
body.add newSeqCall(c.c, x, y)
|
body.add newSeqCall(c.c, x, y)
|
||||||
let i = declareCounter(c, body, firstOrd(t))
|
let i = declareCounter(c, body, firstOrd(t))
|
||||||
let whileLoop = genWhileLoop(c, i, x)
|
let whileLoop = genWhileLoop(c, i, x)
|
||||||
|
|
|
||||||
|
|
@ -1233,8 +1233,6 @@ proc asgnToResultVar(c: PContext, n, le, ri: PNode) {.inline.} =
|
||||||
template resultTypeIsInferrable(typ: PType): expr =
|
template resultTypeIsInferrable(typ: PType): expr =
|
||||||
typ.isMetaType and typ.kind != tyTypeDesc
|
typ.isMetaType and typ.kind != tyTypeDesc
|
||||||
|
|
||||||
include semasgn
|
|
||||||
|
|
||||||
proc semAsgn(c: PContext, n: PNode): PNode =
|
proc semAsgn(c: PContext, n: PNode): PNode =
|
||||||
checkSonsLen(n, 2)
|
checkSonsLen(n, 2)
|
||||||
var a = n.sons[0]
|
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:
|
elif tfNotNil in v.typ.flags and tfNotNil notin v.ast.typ.flags:
|
||||||
message(v.info, warnProveInit, v.name.s)
|
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 =
|
proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
|
||||||
var b: PNode
|
var b: PNode
|
||||||
result = copyNode(n)
|
result = copyNode(n)
|
||||||
|
|
@ -396,7 +429,7 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
|
||||||
newSons(b, length)
|
newSons(b, length)
|
||||||
b.sons[length-2] = a.sons[length-2] # keep type desc for doc generator
|
b.sons[length-2] = a.sons[length-2] # keep type desc for doc generator
|
||||||
b.sons[length-1] = def
|
b.sons[length-1] = def
|
||||||
addSon(result, b)
|
addToVarSection(c, result, n, b)
|
||||||
elif tup.kind == tyTuple and def.kind == nkPar and
|
elif tup.kind == tyTuple and def.kind == nkPar and
|
||||||
a.kind == nkIdentDefs and a.len > 3:
|
a.kind == nkIdentDefs and a.len > 3:
|
||||||
message(a.info, warnEachIdentIsTuple)
|
message(a.info, warnEachIdentIsTuple)
|
||||||
|
|
@ -429,7 +462,7 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
|
||||||
addSon(b, newSymNode(v))
|
addSon(b, newSymNode(v))
|
||||||
addSon(b, a.sons[length-2]) # keep type desc for doc generator
|
addSon(b, a.sons[length-2]) # keep type desc for doc generator
|
||||||
addSon(b, copyTree(def))
|
addSon(b, copyTree(def))
|
||||||
addSon(result, b)
|
addToVarSection(c, result, n, b)
|
||||||
else:
|
else:
|
||||||
if def.kind == nkPar: v.ast = def[j]
|
if def.kind == nkPar: v.ast = def[j]
|
||||||
v.typ = tup.sons[j]
|
v.typ = tup.sons[j]
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ operator `=`
|
||||||
------------
|
------------
|
||||||
|
|
||||||
This operator is the assignment operator. Note that in the contexts
|
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
|
parameter passing no assignment is performed. For a type ``T`` that has an
|
||||||
overloaded assignment operator ``var v = T()`` is rewritten
|
overloaded assignment operator ``var v = T()`` is rewritten
|
||||||
to ``var v: T; v = T()``; in other words ``var`` and ``let`` contexts do count
|
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'
|
- make 'nil' work for 'add' and 'len'
|
||||||
- overloading of '='
|
|
||||||
- introduce typed/untyped types
|
- introduce typed/untyped types
|
||||||
|
|
||||||
|
|
||||||
version 1.0
|
version 1.0
|
||||||
===========
|
===========
|
||||||
|
|
||||||
|
- macro support for '='; bind '=' to a memory region
|
||||||
- remove echo $foo gotcha
|
- remove echo $foo gotcha
|
||||||
- add "all threads are blocked" detection to 'spawn'
|
- add "all threads are blocked" detection to 'spawn'
|
||||||
- figure out why C++ bootstrapping is so much slower
|
- 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
|
- Array and seq indexing can now use the builtin ``^`` operator to access
|
||||||
things from backwards: ``a[^1]`` is like Python's ``a[-1]``.
|
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
|
Library additions
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue