first steps to implement object construction expressions
This commit is contained in:
parent
4f79e34a9a
commit
225d657019
12 changed files with 132 additions and 41 deletions
|
|
@ -89,6 +89,7 @@ type
|
||||||
# formal parameters, var statements, etc.
|
# formal parameters, var statements, etc.
|
||||||
nkVarTuple, # a ``var (a, b) = expr`` construct
|
nkVarTuple, # a ``var (a, b) = expr`` construct
|
||||||
nkPar, # syntactic (); may be a tuple constructor
|
nkPar, # syntactic (); may be a tuple constructor
|
||||||
|
nkObjConstr, # object constructor: T(a: 1, b: 2)
|
||||||
nkCurly, # syntactic {}
|
nkCurly, # syntactic {}
|
||||||
nkCurlyExpr, # an expression like a{i}
|
nkCurlyExpr, # an expression like a{i}
|
||||||
nkBracket, # syntactic []
|
nkBracket, # syntactic []
|
||||||
|
|
|
||||||
|
|
@ -142,10 +142,10 @@ proc getField(n: PNode; position: int): PSym =
|
||||||
else: nil
|
else: nil
|
||||||
|
|
||||||
proc packObject(x: PNode, typ: PType, res: pointer) =
|
proc packObject(x: PNode, typ: PType, res: pointer) =
|
||||||
InternalAssert x.kind == nkPar
|
InternalAssert x.kind in {nkObjConstr, nkPar}
|
||||||
# compute the field's offsets:
|
# compute the field's offsets:
|
||||||
discard typ.getSize
|
discard typ.getSize
|
||||||
for i in countup(0, sonsLen(x) - 1):
|
for i in countup(ord(x.kind == nkObjConstr), sonsLen(x) - 1):
|
||||||
var it = x.sons[i]
|
var it = x.sons[i]
|
||||||
if it.kind == nkExprColonExpr:
|
if it.kind == nkExprColonExpr:
|
||||||
internalAssert it.sons[0].kind == nkSym
|
internalAssert it.sons[0].kind == nkSym
|
||||||
|
|
@ -257,11 +257,11 @@ proc unpackObject(x: pointer, typ: PType, n: PNode): PNode =
|
||||||
unpackObjectAdd(x, typ.n, result)
|
unpackObjectAdd(x, typ.n, result)
|
||||||
else:
|
else:
|
||||||
result = n
|
result = n
|
||||||
if result.kind != nkPar:
|
if result.kind notin {nkObjConstr, nkPar}:
|
||||||
GlobalError(n.info, "cannot map value from FFI")
|
GlobalError(n.info, "cannot map value from FFI")
|
||||||
if typ.n.isNil:
|
if typ.n.isNil:
|
||||||
GlobalError(n.info, "cannot unpack unnamed tuple")
|
GlobalError(n.info, "cannot unpack unnamed tuple")
|
||||||
for i in countup(0, sonsLen(n) - 1):
|
for i in countup(ord(n.kind == nkObjConstr), sonsLen(n) - 1):
|
||||||
var it = n.sons[i]
|
var it = n.sons[i]
|
||||||
if it.kind == nkExprColonExpr:
|
if it.kind == nkExprColonExpr:
|
||||||
internalAssert it.sons[0].kind == nkSym
|
internalAssert it.sons[0].kind == nkSym
|
||||||
|
|
|
||||||
|
|
@ -274,6 +274,7 @@ proc getNullValue(typ: PType, info: TLineInfo): PNode =
|
||||||
for i in countup(0, int(lengthOrd(t)) - 1):
|
for i in countup(0, int(lengthOrd(t)) - 1):
|
||||||
addSon(result, getNullValue(elemType(t), info))
|
addSon(result, getNullValue(elemType(t), info))
|
||||||
of tyTuple:
|
of tyTuple:
|
||||||
|
# XXX nkExprColonExpr is out of fashion ...
|
||||||
result = newNodeIT(nkPar, info, t)
|
result = newNodeIT(nkPar, info, t)
|
||||||
for i in countup(0, sonsLen(t) - 1):
|
for i in countup(0, sonsLen(t) - 1):
|
||||||
var p = newNodeIT(nkExprColonExpr, info, t.sons[i])
|
var p = newNodeIT(nkExprColonExpr, info, t.sons[i])
|
||||||
|
|
@ -1385,6 +1386,23 @@ proc evalAux(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode =
|
||||||
if isSpecial(result): return
|
if isSpecial(result): return
|
||||||
a.sons[i] = result
|
a.sons[i] = result
|
||||||
result = a
|
result = a
|
||||||
|
of nkObjConstr:
|
||||||
|
let t = skipTypes(n.typ, abstractInst)
|
||||||
|
var a: PNode
|
||||||
|
if t.kind == tyRef:
|
||||||
|
result = newNodeIT(nkRefTy, n.info, t)
|
||||||
|
a = getNullValue(t.sons[0], n.info)
|
||||||
|
addSon(result, a)
|
||||||
|
else:
|
||||||
|
a = getNullValue(t, n.info)
|
||||||
|
result = a
|
||||||
|
for i in countup(1, sonsLen(n) - 1):
|
||||||
|
let it = n.sons[i]
|
||||||
|
if it.kind == nkExprColonExpr:
|
||||||
|
let value = evalAux(c, it.sons[1], flags)
|
||||||
|
if isSpecial(value): return value
|
||||||
|
a.sons[it.sons[0].sym.position] = value
|
||||||
|
else: return raiseCannotEval(c, n.info)
|
||||||
of nkWhenStmt, nkIfStmt, nkIfExpr: result = evalIf(c, n)
|
of nkWhenStmt, nkIfStmt, nkIfExpr: result = evalIf(c, n)
|
||||||
of nkWhileStmt: result = evalWhile(c, n)
|
of nkWhileStmt: result = evalWhile(c, n)
|
||||||
of nkCaseStmt: result = evalCase(c, n)
|
of nkCaseStmt: result = evalCase(c, n)
|
||||||
|
|
|
||||||
|
|
@ -758,7 +758,7 @@ proc generateHeader(p: var TProc, typ: PType): PRope =
|
||||||
|
|
||||||
const
|
const
|
||||||
nodeKindsNeedNoCopy = {nkCharLit..nkInt64Lit, nkStrLit..nkTripleStrLit,
|
nodeKindsNeedNoCopy = {nkCharLit..nkInt64Lit, nkStrLit..nkTripleStrLit,
|
||||||
nkFloatLit..nkFloat64Lit, nkCurly, nkPar, nkStringToCString,
|
nkFloatLit..nkFloat64Lit, nkCurly, nkPar, nkObjConstr, nkStringToCString,
|
||||||
nkCStringToString, nkCall, nkPrefix, nkPostfix, nkInfix,
|
nkCStringToString, nkCall, nkPrefix, nkPostfix, nkInfix,
|
||||||
nkCommand, nkHiddenCallConv, nkCallStrLit}
|
nkCommand, nkHiddenCallConv, nkCallStrLit}
|
||||||
|
|
||||||
|
|
@ -1367,6 +1367,21 @@ proc genTupleConstr(p: var TProc, n: PNode, r: var TCompRes) =
|
||||||
appf(r.res, "Field$1: $2", [i.toRope, a.res])
|
appf(r.res, "Field$1: $2", [i.toRope, a.res])
|
||||||
r.res.app("}")
|
r.res.app("}")
|
||||||
|
|
||||||
|
proc genObjConstr(p: var TProc, n: PNode, r: var TCompRes) =
|
||||||
|
# XXX inheritance?
|
||||||
|
var a: TCompRes
|
||||||
|
r.res = toRope("{")
|
||||||
|
for i in countup(0, sonsLen(n) - 1):
|
||||||
|
if i > 0: app(r.res, ", ")
|
||||||
|
var it = n.sons[i]
|
||||||
|
InternalAssert it.kind == nkExprColonExpr
|
||||||
|
gen(p, it.sons[1], a)
|
||||||
|
r.com = mergeExpr(r.com, a.com)
|
||||||
|
var f = it.sons[0].sym
|
||||||
|
if f.loc.r == nil: f.loc.r = mangleName(f)
|
||||||
|
appf(r.res, "$1: $2", [f.loc.r, a.res])
|
||||||
|
r.res.app("}")
|
||||||
|
|
||||||
proc genConv(p: var TProc, n: PNode, r: var TCompRes) =
|
proc genConv(p: var TProc, n: PNode, r: var TCompRes) =
|
||||||
var dest = skipTypes(n.typ, abstractVarRange)
|
var dest = skipTypes(n.typ, abstractVarRange)
|
||||||
var src = skipTypes(n.sons[1].typ, abstractVarRange)
|
var src = skipTypes(n.sons[1].typ, abstractVarRange)
|
||||||
|
|
@ -1566,6 +1581,7 @@ proc gen(p: var TProc, n: PNode, r: var TCompRes) =
|
||||||
of nkCurly: genSetConstr(p, n, r)
|
of nkCurly: genSetConstr(p, n, r)
|
||||||
of nkBracket: genArrayConstr(p, n, r)
|
of nkBracket: genArrayConstr(p, n, r)
|
||||||
of nkPar: genTupleConstr(p, n, r)
|
of nkPar: genTupleConstr(p, n, r)
|
||||||
|
of nkObjConstr: genObjConstr(p, n, r)
|
||||||
of nkHiddenStdConv, nkHiddenSubConv, nkConv: genConv(p, n, r)
|
of nkHiddenStdConv, nkHiddenSubConv, nkConv: genConv(p, n, r)
|
||||||
of nkAddr, nkHiddenAddr: genAddr(p, n, r)
|
of nkAddr, nkHiddenAddr: genAddr(p, n, r)
|
||||||
of nkDerefExpr, nkHiddenDeref: genDeref(p, n, r)
|
of nkDerefExpr, nkHiddenDeref: genDeref(p, n, r)
|
||||||
|
|
|
||||||
|
|
@ -254,10 +254,16 @@ proc indexExprList(p: var TParser, first: PNode, k: TNodeKind,
|
||||||
optPar(p)
|
optPar(p)
|
||||||
eat(p, endToken)
|
eat(p, endToken)
|
||||||
|
|
||||||
proc exprColonEqExpr(p: var TParser, kind: TNodeKind, tok: TTokType): PNode =
|
proc exprColonEqExpr(p: var TParser): PNode =
|
||||||
var a = parseExpr(p)
|
var a = parseExpr(p)
|
||||||
if p.tok.tokType == tok:
|
if p.tok.tokType == tkColon:
|
||||||
result = newNodeP(kind, p)
|
result = newNodeP(nkExprColonExpr, p)
|
||||||
|
getTok(p)
|
||||||
|
#optInd(p, result)
|
||||||
|
addSon(result, a)
|
||||||
|
addSon(result, parseExpr(p))
|
||||||
|
elif p.tok.tokType == tkEquals:
|
||||||
|
result = newNodeP(nkExprEqExpr, p)
|
||||||
getTok(p)
|
getTok(p)
|
||||||
#optInd(p, result)
|
#optInd(p, result)
|
||||||
addSon(result, a)
|
addSon(result, a)
|
||||||
|
|
@ -309,14 +315,13 @@ proc qualifiedIdentListAux(p: var TParser, endTok: TTokType, result: PNode) =
|
||||||
optInd(p, a)
|
optInd(p, a)
|
||||||
eat(p, endTok)
|
eat(p, endTok)
|
||||||
|
|
||||||
proc exprColonEqExprListAux(p: var TParser, elemKind: TNodeKind,
|
proc exprColonEqExprListAux(p: var TParser, endTok: TTokType, result: PNode) =
|
||||||
endTok, sepTok: TTokType, result: PNode) =
|
|
||||||
assert(endTok in {tkCurlyRi, tkCurlyDotRi, tkBracketRi, tkParRi})
|
assert(endTok in {tkCurlyRi, tkCurlyDotRi, tkBracketRi, tkParRi})
|
||||||
getTok(p)
|
getTok(p)
|
||||||
optInd(p, result)
|
optInd(p, result)
|
||||||
while (p.tok.tokType != endTok) and (p.tok.tokType != tkEof) and
|
while (p.tok.tokType != endTok) and (p.tok.tokType != tkEof) and
|
||||||
(p.tok.tokType != tkSad) and (p.tok.tokType != tkInd):
|
(p.tok.tokType != tkSad) and (p.tok.tokType != tkInd):
|
||||||
var a = exprColonEqExpr(p, elemKind, sepTok)
|
var a = exprColonEqExpr(p)
|
||||||
addSon(result, a)
|
addSon(result, a)
|
||||||
if p.tok.tokType != tkComma: break
|
if p.tok.tokType != tkComma: break
|
||||||
getTok(p)
|
getTok(p)
|
||||||
|
|
@ -324,10 +329,10 @@ proc exprColonEqExprListAux(p: var TParser, elemKind: TNodeKind,
|
||||||
optPar(p)
|
optPar(p)
|
||||||
eat(p, endTok)
|
eat(p, endTok)
|
||||||
|
|
||||||
proc exprColonEqExprList(p: var TParser, kind, elemKind: TNodeKind,
|
proc exprColonEqExprList(p: var TParser, kind: TNodeKind,
|
||||||
endTok, sepTok: TTokType): PNode =
|
endTok: TTokType): PNode =
|
||||||
result = newNodeP(kind, p)
|
result = newNodeP(kind, p)
|
||||||
exprColonEqExprListAux(p, elemKind, endTok, sepTok, result)
|
exprColonEqExprListAux(p, endTok, result)
|
||||||
|
|
||||||
proc setOrTableConstr(p: var TParser): PNode =
|
proc setOrTableConstr(p: var TParser): PNode =
|
||||||
result = newNodeP(nkCurly, p)
|
result = newNodeP(nkCurly, p)
|
||||||
|
|
@ -338,7 +343,7 @@ proc setOrTableConstr(p: var TParser): PNode =
|
||||||
result.kind = nkTableConstr
|
result.kind = nkTableConstr
|
||||||
else:
|
else:
|
||||||
while p.tok.tokType notin {tkCurlyRi, tkEof, tkSad, tkInd}:
|
while p.tok.tokType notin {tkCurlyRi, tkEof, tkSad, tkInd}:
|
||||||
var a = exprColonEqExpr(p, nkExprColonExpr, tkColon)
|
var a = exprColonEqExpr(p)
|
||||||
if a.kind == nkExprColonExpr: result.kind = nkTableConstr
|
if a.kind == nkExprColonExpr: result.kind = nkTableConstr
|
||||||
addSon(result, a)
|
addSon(result, a)
|
||||||
if p.tok.tokType != tkComma: break
|
if p.tok.tokType != tkComma: break
|
||||||
|
|
@ -473,14 +478,13 @@ proc identOrLiteral(p: var TParser): PNode =
|
||||||
getTok(p)
|
getTok(p)
|
||||||
of tkParLe:
|
of tkParLe:
|
||||||
# () constructor
|
# () constructor
|
||||||
result = exprColonEqExprList(p, nkPar, nkExprColonExpr, tkParRi, tkColon)
|
result = exprColonEqExprList(p, nkPar, tkParRi)
|
||||||
of tkCurlyLe:
|
of tkCurlyLe:
|
||||||
# {} constructor
|
# {} constructor
|
||||||
result = setOrTableConstr(p)
|
result = setOrTableConstr(p)
|
||||||
of tkBracketLe:
|
of tkBracketLe:
|
||||||
# [] constructor
|
# [] constructor
|
||||||
result = exprColonEqExprList(p, nkBracket, nkExprColonExpr, tkBracketRi,
|
result = exprColonEqExprList(p, nkBracket, tkBracketRi)
|
||||||
tkColon)
|
|
||||||
of tkCast:
|
of tkCast:
|
||||||
result = parseCast(p)
|
result = parseCast(p)
|
||||||
else:
|
else:
|
||||||
|
|
@ -496,7 +500,10 @@ proc primarySuffix(p: var TParser, r: PNode): PNode =
|
||||||
var a = result
|
var a = result
|
||||||
result = newNodeP(nkCall, p)
|
result = newNodeP(nkCall, p)
|
||||||
addSon(result, a)
|
addSon(result, a)
|
||||||
exprColonEqExprListAux(p, nkExprEqExpr, tkParRi, tkEquals, result)
|
exprColonEqExprListAux(p, tkParRi, result)
|
||||||
|
if result.len > 1 and result.sons[0].kind == nkExprColonExpr:
|
||||||
|
result.kind = nkObjConstr
|
||||||
|
else:
|
||||||
parseDoBlocks(p, result)
|
parseDoBlocks(p, result)
|
||||||
of tkDo:
|
of tkDo:
|
||||||
var a = result
|
var a = result
|
||||||
|
|
@ -564,7 +571,7 @@ proc parsePragma(p: var TParser): PNode =
|
||||||
optInd(p, result)
|
optInd(p, result)
|
||||||
while (p.tok.tokType != tkCurlyDotRi) and (p.tok.tokType != tkCurlyRi) and
|
while (p.tok.tokType != tkCurlyDotRi) and (p.tok.tokType != tkCurlyRi) and
|
||||||
(p.tok.tokType != tkEof) and (p.tok.tokType != tkSad):
|
(p.tok.tokType != tkEof) and (p.tok.tokType != tkSad):
|
||||||
var a = exprColonEqExpr(p, nkExprColonExpr, tkColon)
|
var a = exprColonEqExpr(p)
|
||||||
addSon(result, a)
|
addSon(result, a)
|
||||||
if p.tok.tokType == tkComma:
|
if p.tok.tokType == tkComma:
|
||||||
getTok(p)
|
getTok(p)
|
||||||
|
|
|
||||||
|
|
@ -367,7 +367,7 @@ proc lsub(n: PNode): int =
|
||||||
else: result = len(atom(n))
|
else: result = len(atom(n))
|
||||||
of succ(nkEmpty)..pred(nkTripleStrLit), succ(nkTripleStrLit)..nkNilLit:
|
of succ(nkEmpty)..pred(nkTripleStrLit), succ(nkTripleStrLit)..nkNilLit:
|
||||||
result = len(atom(n))
|
result = len(atom(n))
|
||||||
of nkCall, nkBracketExpr, nkCurlyExpr, nkConv, nkPattern:
|
of nkCall, nkBracketExpr, nkCurlyExpr, nkConv, nkPattern, nkObjConstr:
|
||||||
result = lsub(n.sons[0]) + lcomma(n, 1) + 2
|
result = lsub(n.sons[0]) + lcomma(n, 1) + 2
|
||||||
of nkHiddenStdConv, nkHiddenSubConv, nkHiddenCallConv: result = lsub(n[1])
|
of nkHiddenStdConv, nkHiddenSubConv, nkHiddenCallConv: result = lsub(n[1])
|
||||||
of nkCast: result = lsub(n.sons[0]) + lsub(n.sons[1]) + len("cast[]()")
|
of nkCast: result = lsub(n.sons[0]) + lsub(n.sons[1]) + len("cast[]()")
|
||||||
|
|
@ -779,7 +779,7 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
|
||||||
of nkRStrLit: put(g, tkRStrLit, atom(n))
|
of nkRStrLit: put(g, tkRStrLit, atom(n))
|
||||||
of nkCharLit: put(g, tkCharLit, atom(n))
|
of nkCharLit: put(g, tkCharLit, atom(n))
|
||||||
of nkNilLit: put(g, tkNil, atom(n)) # complex expressions
|
of nkNilLit: put(g, tkNil, atom(n)) # complex expressions
|
||||||
of nkCall, nkConv, nkDotCall, nkPattern:
|
of nkCall, nkConv, nkDotCall, nkPattern, nkObjConstr:
|
||||||
if sonsLen(n) >= 1: gsub(g, n.sons[0])
|
if sonsLen(n) >= 1: gsub(g, n.sons[0])
|
||||||
put(g, tkParLe, "(")
|
put(g, tkParLe, "(")
|
||||||
gcomma(g, n, 1)
|
gcomma(g, n, 1)
|
||||||
|
|
|
||||||
|
|
@ -1551,6 +1551,36 @@ proc semTuplePositionsConstr(c: PContext, n: PNode): PNode =
|
||||||
addSonSkipIntLit(typ, n.sons[i].typ)
|
addSonSkipIntLit(typ, n.sons[i].typ)
|
||||||
result.typ = typ
|
result.typ = typ
|
||||||
|
|
||||||
|
proc semObjConstr(c: PContext, n: PNode): PNode =
|
||||||
|
var t = semTypeNode(c, n.sons[0], nil)
|
||||||
|
result = n
|
||||||
|
result.typ = t
|
||||||
|
t = skipTypes(t, abstractInst)
|
||||||
|
if t.kind == tyRef: t = skipTypes(t.sons[0], abstractInst)
|
||||||
|
if t.kind != tyObject:
|
||||||
|
localError(n.info, errGenerated, "object constructor needs an object type")
|
||||||
|
return
|
||||||
|
var ids = initIntSet()
|
||||||
|
for i in 1.. <n.len:
|
||||||
|
let it = n.sons[i]
|
||||||
|
if it.kind != nkExprColonExpr or it.sons[0].kind notin {nkSym, nkIdent}:
|
||||||
|
localError(n.info, errNamedExprExpected)
|
||||||
|
break
|
||||||
|
var id: PIdent
|
||||||
|
if it.sons[0].kind == nkIdent: id = it.sons[0].ident
|
||||||
|
else: id = it.sons[0].sym.name
|
||||||
|
if ContainsOrIncl(ids, id.id):
|
||||||
|
localError(it.info, errFieldInitTwice, id.s)
|
||||||
|
var e = semExprWithType(c, it.sons[1])
|
||||||
|
let field = lookupInRecord(t.n, id)
|
||||||
|
if field.isNil:
|
||||||
|
localError(it.info, errUndeclaredFieldX, id.s)
|
||||||
|
else:
|
||||||
|
it.sons[0] = newSymNode(field)
|
||||||
|
e = fitNode(c, field.typ, e)
|
||||||
|
it.sons[1] = e
|
||||||
|
# XXX object field name check for 'case objects' if the kind is static?
|
||||||
|
|
||||||
proc semStmtListExpr(c: PContext, n: PNode): PNode =
|
proc semStmtListExpr(c: PContext, n: PNode): PNode =
|
||||||
result = n
|
result = n
|
||||||
checkMinSonsLen(n, 1)
|
checkMinSonsLen(n, 1)
|
||||||
|
|
@ -1801,6 +1831,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||||
of paSingle: result = semExpr(c, n.sons[0], flags)
|
of paSingle: result = semExpr(c, n.sons[0], flags)
|
||||||
of nkCurly: result = semSetConstr(c, n)
|
of nkCurly: result = semSetConstr(c, n)
|
||||||
of nkBracket: result = semArrayConstr(c, n)
|
of nkBracket: result = semArrayConstr(c, n)
|
||||||
|
of nkObjConstr: result = semObjConstr(c, n)
|
||||||
of nkLambdaKinds: result = semLambda(c, n, flags)
|
of nkLambdaKinds: result = semLambda(c, n, flags)
|
||||||
of nkDerefExpr: result = semDeref(c, n)
|
of nkDerefExpr: result = semDeref(c, n)
|
||||||
of nkAddr:
|
of nkAddr:
|
||||||
|
|
|
||||||
|
|
@ -519,10 +519,10 @@ proc foldArrayAccess(m: PSym, n: PNode): PNode =
|
||||||
proc foldFieldAccess(m: PSym, n: PNode): PNode =
|
proc foldFieldAccess(m: PSym, n: PNode): PNode =
|
||||||
# a real field access; proc calls have already been transformed
|
# a real field access; proc calls have already been transformed
|
||||||
var x = getConstExpr(m, n.sons[0])
|
var x = getConstExpr(m, n.sons[0])
|
||||||
if x == nil or x.kind != nkPar: return
|
if x == nil or x.kind notin {nkObjConstr, nkPar}: return
|
||||||
|
|
||||||
var field = n.sons[1].sym
|
var field = n.sons[1].sym
|
||||||
for i in countup(0, sonsLen(x) - 1):
|
for i in countup(ord(x.kind == nkObjConstr), sonsLen(x) - 1):
|
||||||
var it = x.sons[i]
|
var it = x.sons[i]
|
||||||
if it.kind != nkExprColonExpr:
|
if it.kind != nkExprColonExpr:
|
||||||
# lookup per index:
|
# lookup per index:
|
||||||
|
|
@ -649,6 +649,13 @@ proc getConstExpr(m: PSym, n: PNode): PNode =
|
||||||
if a == nil: return nil
|
if a == nil: return nil
|
||||||
result.sons[i] = a
|
result.sons[i] = a
|
||||||
incl(result.flags, nfAllConst)
|
incl(result.flags, nfAllConst)
|
||||||
|
of nkObjConstr:
|
||||||
|
result = copyTree(n)
|
||||||
|
for i in countup(1, sonsLen(n) - 1):
|
||||||
|
var a = getConstExpr(m, n.sons[i].sons[1])
|
||||||
|
if a == nil: return nil
|
||||||
|
result.sons[i].sons[1] = a
|
||||||
|
incl(result.flags, nfAllConst)
|
||||||
of nkPar:
|
of nkPar:
|
||||||
# tuple constructor
|
# tuple constructor
|
||||||
result = copyTree(n)
|
result = copyTree(n)
|
||||||
|
|
|
||||||
|
|
@ -311,6 +311,12 @@ proc analyse(c: PProcCtx, n: PNode): TThreadOwner =
|
||||||
# container construction:
|
# container construction:
|
||||||
result = toNil # nothing until later
|
result = toNil # nothing until later
|
||||||
for i in 0..n.len-1: aggregateOwner(result, analyse(c, n[i]))
|
for i in 0..n.len-1: aggregateOwner(result, analyse(c, n[i]))
|
||||||
|
of nkObjConstr:
|
||||||
|
if n.typ != nil and containsGarbageCollectedRef(n.typ):
|
||||||
|
result = toMine
|
||||||
|
else:
|
||||||
|
result = toNil # nothing until later
|
||||||
|
for i in 1..n.len-1: aggregateOwner(result, analyse(c, n[i]))
|
||||||
of nkAddr, nkHiddenAddr:
|
of nkAddr, nkHiddenAddr:
|
||||||
var a = lvalueSym(n)
|
var a = lvalueSym(n)
|
||||||
if a.kind == nkSym:
|
if a.kind == nkSym:
|
||||||
|
|
|
||||||
|
|
@ -115,7 +115,7 @@ proc isDeepConstExpr*(n: PNode): bool =
|
||||||
result = true
|
result = true
|
||||||
of nkExprEqExpr, nkExprColonExpr, nkHiddenStdConv, nkHiddenSubConv:
|
of nkExprEqExpr, nkExprColonExpr, nkHiddenStdConv, nkHiddenSubConv:
|
||||||
result = isDeepConstExpr(n.sons[1])
|
result = isDeepConstExpr(n.sons[1])
|
||||||
of nkCurly, nkBracket, nkPar, nkClosure:
|
of nkCurly, nkBracket, nkPar, nkObjConstr, nkClosure:
|
||||||
for i in 0 .. <n.len:
|
for i in 0 .. <n.len:
|
||||||
if not isDeepConstExpr(n.sons[i]): return false
|
if not isDeepConstExpr(n.sons[i]): return false
|
||||||
result = true
|
result = true
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,8 @@ type
|
||||||
nnkCommand, nnkCall, nnkCallStrLit, nnkInfix,
|
nnkCommand, nnkCall, nnkCallStrLit, nnkInfix,
|
||||||
nnkPrefix, nnkPostfix, nnkHiddenCallConv,
|
nnkPrefix, nnkPostfix, nnkHiddenCallConv,
|
||||||
nnkExprEqExpr,
|
nnkExprEqExpr,
|
||||||
nnkExprColonExpr, nnkIdentDefs, nnkVarTuple, nnkPar, nnkCurly, nnkCurlyExpr,
|
nnkExprColonExpr, nnkIdentDefs, nnkVarTuple,
|
||||||
|
nnkPar, nnkObjConstr, nnkCurly, nnkCurlyExpr,
|
||||||
nnkBracket, nnkBracketExpr, nnkPragmaExpr, nnkRange,
|
nnkBracket, nnkBracketExpr, nnkPragmaExpr, nnkRange,
|
||||||
nnkDotExpr, nnkCheckedFieldExpr, nnkDerefExpr, nnkIfExpr,
|
nnkDotExpr, nnkCheckedFieldExpr, nnkDerefExpr, nnkIfExpr,
|
||||||
nnkElifExpr, nnkElseExpr, nnkLambda, nnkDo, nnkAccQuoted,
|
nnkElifExpr, nnkElseExpr, nnkLambda, nnkDo, nnkAccQuoted,
|
||||||
|
|
|
||||||
6
todo.txt
6
todo.txt
|
|
@ -8,7 +8,10 @@ version 0.9.2
|
||||||
* test libffi on windows
|
* test libffi on windows
|
||||||
* test: times.format with the FFI
|
* test: times.format with the FFI
|
||||||
- acyclic vs prunable; introduce GC hints
|
- acyclic vs prunable; introduce GC hints
|
||||||
- implement constructors + full 'not nil' checking
|
- implement constructors
|
||||||
|
- more checks
|
||||||
|
- C codegen for them
|
||||||
|
- document them
|
||||||
- CGEN: ``restrict`` pragma + backend support; computed goto support
|
- CGEN: ``restrict`` pragma + backend support; computed goto support
|
||||||
- fix:
|
- fix:
|
||||||
- 'result' is not properly cleaned for NRVO
|
- 'result' is not properly cleaned for NRVO
|
||||||
|
|
@ -24,6 +27,7 @@ version 0.9.4
|
||||||
- provide tool/API to track leaks/object counts
|
- provide tool/API to track leaks/object counts
|
||||||
- hybrid GC
|
- hybrid GC
|
||||||
- use big blocks in the allocator
|
- use big blocks in the allocator
|
||||||
|
- implement full 'not nil' checking
|
||||||
- make 'bind' default for templates and introduce 'mixin';
|
- make 'bind' default for templates and introduce 'mixin';
|
||||||
special rule for ``[]=``
|
special rule for ``[]=``
|
||||||
- implicit deref for parameter matching; overloading based on 'var T'
|
- implicit deref for parameter matching; overloading based on 'var T'
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue