diff options
Diffstat (limited to 'compiler')
-rwxr-xr-x | compiler/ast.nim | 1 | ||||
-rw-r--r-- | compiler/evalffi.nim | 8 | ||||
-rwxr-xr-x | compiler/evals.nim | 32 | ||||
-rwxr-xr-x | compiler/jsgen.nim | 18 | ||||
-rwxr-xr-x | compiler/parser.nim | 47 | ||||
-rwxr-xr-x | compiler/renderer.nim | 4 | ||||
-rwxr-xr-x | compiler/semexprs.nim | 31 | ||||
-rwxr-xr-x | compiler/semfold.nim | 15 | ||||
-rwxr-xr-x | compiler/semthreads.nim | 6 | ||||
-rwxr-xr-x | compiler/trees.nim | 2 |
10 files changed, 125 insertions, 39 deletions
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.. <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 = result = n 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 nkCurly: result = semSetConstr(c, n) of nkBracket: result = semArrayConstr(c, n) + of nkObjConstr: result = semObjConstr(c, n) of nkLambdaKinds: result = semLambda(c, n, flags) of nkDerefExpr: result = semDeref(c, n) of nkAddr: diff --git a/compiler/semfold.nim b/compiler/semfold.nim index e46bb0459..e26700e27 100755 --- a/compiler/semfold.nim +++ b/compiler/semfold.nim @@ -516,13 +516,13 @@ proc foldArrayAccess(m: PSym, n: PNode): PNode = LocalError(n.info, errIndexOutOfBounds) else: nil -proc foldFieldAccess(m: PSym, n: PNode): PNode = +proc foldFieldAccess(m: PSym, n: PNode): PNode = # a real field access; proc calls have already been transformed 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 - 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: # lookup per index: @@ -649,7 +649,14 @@ proc getConstExpr(m: PSym, n: PNode): PNode = if a == nil: return nil result.sons[i] = a incl(result.flags, nfAllConst) - of nkPar: + 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: # tuple constructor result = copyTree(n) if (sonsLen(n) > 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 .. <n.len: if not isDeepConstExpr(n.sons[i]): return false result = true |