From 225d6570192e75371a1a7d6246ae56be784ea140 Mon Sep 17 00:00:00 2001 From: Araq Date: Thu, 7 Mar 2013 01:52:17 +0100 Subject: first steps to implement object construction expressions --- compiler/ast.nim | 1 + compiler/evalffi.nim | 8 ++++---- compiler/evals.nim | 32 +++++++++++++++++++++++++------- compiler/jsgen.nim | 18 +++++++++++++++++- compiler/parser.nim | 47 +++++++++++++++++++++++++++-------------------- compiler/renderer.nim | 4 ++-- compiler/semexprs.nim | 31 +++++++++++++++++++++++++++++++ compiler/semfold.nim | 15 +++++++++++---- compiler/semthreads.nim | 6 ++++++ compiler/trees.nim | 2 +- 10 files changed, 125 insertions(+), 39 deletions(-) (limited to 'compiler') diff --git a/compiler/ast.nim b/compiler/ast.nim index 4fa3617d7..5d420c6d2 100755 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -89,6 +89,7 @@ type # formal parameters, var statements, etc. nkVarTuple, # a ``var (a, b) = expr`` construct nkPar, # syntactic (); may be a tuple constructor + nkObjConstr, # object constructor: T(a: 1, b: 2) nkCurly, # syntactic {} nkCurlyExpr, # an expression like a{i} nkBracket, # syntactic [] diff --git a/compiler/evalffi.nim b/compiler/evalffi.nim index ba6e7ee8f..21a131996 100644 --- a/compiler/evalffi.nim +++ b/compiler/evalffi.nim @@ -142,10 +142,10 @@ proc getField(n: PNode; position: int): PSym = else: nil proc packObject(x: PNode, typ: PType, res: pointer) = - InternalAssert x.kind == nkPar + InternalAssert x.kind in {nkObjConstr, nkPar} # compute the field's offsets: 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] if it.kind == nkExprColonExpr: internalAssert it.sons[0].kind == nkSym @@ -257,11 +257,11 @@ proc unpackObject(x: pointer, typ: PType, n: PNode): PNode = unpackObjectAdd(x, typ.n, result) else: result = n - if result.kind != nkPar: + if result.kind notin {nkObjConstr, nkPar}: GlobalError(n.info, "cannot map value from FFI") if typ.n.isNil: 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] if it.kind == nkExprColonExpr: internalAssert it.sons[0].kind == nkSym diff --git a/compiler/evals.nim b/compiler/evals.nim index 3825bbb6c..a05f96829 100755 --- a/compiler/evals.nim +++ b/compiler/evals.nim @@ -273,9 +273,10 @@ proc getNullValue(typ: PType, info: TLineInfo): PNode = result = newNodeIT(nkBracket, info, t) for i in countup(0, int(lengthOrd(t)) - 1): addSon(result, getNullValue(elemType(t), info)) - of tyTuple: + of tyTuple: + # XXX nkExprColonExpr is out of fashion ... 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 field = if t.n != nil: t.n.sons[i].sym else: newSym( skField, getIdent(":tmp" & $i), t.owner, info) @@ -999,10 +1000,10 @@ proc evalExpandToAst(c: PEvalContext, original: PNode): PNode = case expandedSym.kind of skTemplate: - let genSymOwner = if c.tos != nil and c.tos.prc != nil: - c.tos.prc - else: - c.module + let genSymOwner = if c.tos != nil and c.tos.prc != nil: + c.tos.prc + else: + c.module result = evalTemplate(macroCall, expandedSym, genSymOwner) of skMacro: # At this point macroCall.sons[0] is nkSym node. @@ -1342,7 +1343,7 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode = cc = result if isEmpty(a) or isEmpty(b) or isEmpty(cc): result = emptyNode else: result = evalOp(m, n, a, b, cc) - + proc evalAux(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode = result = emptyNode dec(gNestedEvals) @@ -1385,6 +1386,23 @@ proc evalAux(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode = if isSpecial(result): return a.sons[i] = result 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 nkWhileStmt: result = evalWhile(c, n) of nkCaseStmt: result = evalCase(c, n) diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim index 94b662b48..64175dc93 100755 --- a/compiler/jsgen.nim +++ b/compiler/jsgen.nim @@ -758,7 +758,7 @@ proc generateHeader(p: var TProc, typ: PType): PRope = const nodeKindsNeedNoCopy = {nkCharLit..nkInt64Lit, nkStrLit..nkTripleStrLit, - nkFloatLit..nkFloat64Lit, nkCurly, nkPar, nkStringToCString, + nkFloatLit..nkFloat64Lit, nkCurly, nkPar, nkObjConstr, nkStringToCString, nkCStringToString, nkCall, nkPrefix, nkPostfix, nkInfix, 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]) 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) = var dest = skipTypes(n.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 nkBracket: genArrayConstr(p, n, r) of nkPar: genTupleConstr(p, n, r) + of nkObjConstr: genObjConstr(p, n, r) of nkHiddenStdConv, nkHiddenSubConv, nkConv: genConv(p, n, r) of nkAddr, nkHiddenAddr: genAddr(p, n, r) of nkDerefExpr, nkHiddenDeref: genDeref(p, n, r) diff --git a/compiler/parser.nim b/compiler/parser.nim index a2c7f71d2..f820c38db 100755 --- a/compiler/parser.nim +++ b/compiler/parser.nim @@ -254,15 +254,21 @@ proc indexExprList(p: var TParser, first: PNode, k: TNodeKind, optPar(p) eat(p, endToken) -proc exprColonEqExpr(p: var TParser, kind: TNodeKind, tok: TTokType): PNode = +proc exprColonEqExpr(p: var TParser): PNode = var a = parseExpr(p) - if p.tok.tokType == tok: - result = newNodeP(kind, p) + if p.tok.tokType == tkColon: + result = newNodeP(nkExprColonExpr, p) getTok(p) #optInd(p, result) addSon(result, a) addSon(result, parseExpr(p)) - else: + elif p.tok.tokType == tkEquals: + result = newNodeP(nkExprEqExpr, p) + getTok(p) + #optInd(p, result) + addSon(result, a) + addSon(result, parseExpr(p)) + else: result = a proc exprList(p: var TParser, endTok: TTokType, result: PNode) = @@ -309,14 +315,13 @@ proc qualifiedIdentListAux(p: var TParser, endTok: TTokType, result: PNode) = optInd(p, a) eat(p, endTok) -proc exprColonEqExprListAux(p: var TParser, elemKind: TNodeKind, - endTok, sepTok: TTokType, result: PNode) = +proc exprColonEqExprListAux(p: var TParser, endTok: TTokType, result: PNode) = assert(endTok in {tkCurlyRi, tkCurlyDotRi, tkBracketRi, tkParRi}) getTok(p) optInd(p, result) while (p.tok.tokType != endTok) and (p.tok.tokType != tkEof) and (p.tok.tokType != tkSad) and (p.tok.tokType != tkInd): - var a = exprColonEqExpr(p, elemKind, sepTok) + var a = exprColonEqExpr(p) addSon(result, a) if p.tok.tokType != tkComma: break getTok(p) @@ -324,10 +329,10 @@ proc exprColonEqExprListAux(p: var TParser, elemKind: TNodeKind, optPar(p) eat(p, endTok) -proc exprColonEqExprList(p: var TParser, kind, elemKind: TNodeKind, - endTok, sepTok: TTokType): PNode = +proc exprColonEqExprList(p: var TParser, kind: TNodeKind, + endTok: TTokType): PNode = result = newNodeP(kind, p) - exprColonEqExprListAux(p, elemKind, endTok, sepTok, result) + exprColonEqExprListAux(p, endTok, result) proc setOrTableConstr(p: var TParser): PNode = result = newNodeP(nkCurly, p) @@ -338,7 +343,7 @@ proc setOrTableConstr(p: var TParser): PNode = result.kind = nkTableConstr else: 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 addSon(result, a) if p.tok.tokType != tkComma: break @@ -471,16 +476,15 @@ proc identOrLiteral(p: var TParser): PNode = of tkNil: result = newNodeP(nkNilLit, p) getTok(p) - of tkParLe: + of tkParLe: # () constructor - result = exprColonEqExprList(p, nkPar, nkExprColonExpr, tkParRi, tkColon) - of tkCurlyLe: + result = exprColonEqExprList(p, nkPar, tkParRi) + of tkCurlyLe: # {} constructor result = setOrTableConstr(p) - of tkBracketLe: + of tkBracketLe: # [] constructor - result = exprColonEqExprList(p, nkBracket, nkExprColonExpr, tkBracketRi, - tkColon) + result = exprColonEqExprList(p, nkBracket, tkBracketRi) of tkCast: result = parseCast(p) else: @@ -496,8 +500,11 @@ proc primarySuffix(p: var TParser, r: PNode): PNode = var a = result result = newNodeP(nkCall, p) addSon(result, a) - exprColonEqExprListAux(p, nkExprEqExpr, tkParRi, tkEquals, result) - parseDoBlocks(p, result) + exprColonEqExprListAux(p, tkParRi, result) + if result.len > 1 and result.sons[0].kind == nkExprColonExpr: + result.kind = nkObjConstr + else: + parseDoBlocks(p, result) of tkDo: var a = result result = newNodeP(nkCall, p) @@ -564,7 +571,7 @@ proc parsePragma(p: var TParser): PNode = optInd(p, result) while (p.tok.tokType != tkCurlyDotRi) and (p.tok.tokType != tkCurlyRi) and (p.tok.tokType != tkEof) and (p.tok.tokType != tkSad): - var a = exprColonEqExpr(p, nkExprColonExpr, tkColon) + var a = exprColonEqExpr(p) addSon(result, a) if p.tok.tokType == tkComma: getTok(p) diff --git a/compiler/renderer.nim b/compiler/renderer.nim index 48a190ec1..b4ef52100 100755 --- a/compiler/renderer.nim +++ b/compiler/renderer.nim @@ -367,7 +367,7 @@ proc lsub(n: PNode): int = else: result = len(atom(n)) of succ(nkEmpty)..pred(nkTripleStrLit), succ(nkTripleStrLit)..nkNilLit: 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 of nkHiddenStdConv, nkHiddenSubConv, nkHiddenCallConv: result = lsub(n[1]) 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 nkCharLit: put(g, tkCharLit, atom(n)) 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]) put(g, tkParLe, "(") gcomma(g, n, 1) diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 3539424d1..1c95a7452 100755 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -1551,6 +1551,36 @@ proc semTuplePositionsConstr(c: PContext, n: PNode): PNode = addSonSkipIntLit(typ, n.sons[i].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.. 0) and (n.sons[0].kind == nkExprColonExpr): diff --git a/compiler/semthreads.nim b/compiler/semthreads.nim index 9fc6a54d9..6f24e1f6d 100755 --- a/compiler/semthreads.nim +++ b/compiler/semthreads.nim @@ -311,6 +311,12 @@ proc analyse(c: PProcCtx, n: PNode): TThreadOwner = # container construction: result = toNil # nothing until later 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: var a = lvalueSym(n) if a.kind == nkSym: diff --git a/compiler/trees.nim b/compiler/trees.nim index 08b89a76e..f371cb021 100755 --- a/compiler/trees.nim +++ b/compiler/trees.nim @@ -115,7 +115,7 @@ proc isDeepConstExpr*(n: PNode): bool = result = true of nkExprEqExpr, nkExprColonExpr, nkHiddenStdConv, nkHiddenSubConv: result = isDeepConstExpr(n.sons[1]) - of nkCurly, nkBracket, nkPar, nkClosure: + of nkCurly, nkBracket, nkPar, nkObjConstr, nkClosure: for i in 0 ..