From fa198f5be1a2867a0a2fd6972e0465cf9f8a66ff Mon Sep 17 00:00:00 2001 From: Dominik Picheta Date: Sun, 2 Dec 2012 13:21:21 +0000 Subject: [PATCH 1/8] Fixes SSL httpclient and problems with hidden path splitting in OS. Added babel's libs dir to Nimrod's path. --- config/nimrod.cfg | 2 +- lib/pure/httpclient.nim | 31 ++++++++++++++++++++----------- lib/pure/os.nim | 3 ++- 3 files changed, 23 insertions(+), 13 deletions(-) diff --git a/config/nimrod.cfg b/config/nimrod.cfg index 564a0d4a6..3ae38133d 100755 --- a/config/nimrod.cfg +++ b/config/nimrod.cfg @@ -36,7 +36,7 @@ path="$lib/windows" path="$lib/posix" path="$lib/ecmas" path="$lib/pure/unidecode" -#recursivePath:"$home/.babel/lib" +path="$home/.babel/libs/" @if release or quick: obj_checks:off diff --git a/lib/pure/httpclient.nim b/lib/pure/httpclient.nim index 184bca867..462db91b1 100755 --- a/lib/pure/httpclient.nim +++ b/lib/pure/httpclient.nim @@ -238,8 +238,15 @@ type httpCONNECT ## Converts the request connection to a transparent ## TCP/IP tunnel, usually used for proxies. +when not defined(ssl): + type PSSLContext = ref object + let defaultSSLContext = nil +else: + let defaultSSLContext = newContext(verifyMode = CVerifyNone) + proc request*(url: string, httpMethod = httpGET, extraHeaders = "", - body = ""): TResponse = + body = "", + sslContext: PSSLContext = defaultSSLContext): TResponse = ## | Requests ``url`` with the specified ``httpMethod``. ## | Extra headers can be specified and must be seperated by ``\c\L`` var r = parseUrl(url) @@ -257,7 +264,7 @@ proc request*(url: string, httpMethod = httpGET, extraHeaders = "", var port = TPort(80) if r.scheme == "https": when defined(ssl): - s.wrapSocket(verifyMode = CVerifyNone) + sslContext.wrapSocket(s) else: raise newException(EHttpRequestErr, "SSL support was not compiled in. Cannot connect over SSL.") port = TPort(443) @@ -277,7 +284,7 @@ proc redirection(status: string): bool = if status.startsWith(i): return True -proc get*(url: string, maxRedirects = 5): TResponse = +proc get*(url: string, maxRedirects = 5, sslContext: PSSLContext = defaultSSLContext): TResponse = ## | GET's the ``url`` and returns a ``TResponse`` object ## | This proc also handles redirection result = request(url) @@ -285,24 +292,24 @@ proc get*(url: string, maxRedirects = 5): TResponse = if result.status.redirection(): var locationHeader = result.headers["Location"] if locationHeader == "": httpError("location header expected") - result = request(locationHeader) + result = request(locationHeader, sslContext = sslContext) -proc getContent*(url: string): string = +proc getContent*(url: string, sslContext: PSSLContext = defaultSSLContext): string = ## | GET's the body and returns it as a string. ## | Raises exceptions for the status codes ``4xx`` and ``5xx`` - var r = get(url) + var r = get(url, sslContext = sslContext) if r.status[0] in {'4','5'}: raise newException(EHTTPRequestErr, r.status) else: return r.body proc post*(url: string, extraHeaders = "", body = "", - maxRedirects = 5): TResponse = + maxRedirects = 5, sslContext: PSSLContext = defaultSSLContext): TResponse = ## | POST's ``body`` to the ``url`` and returns a ``TResponse`` object. ## | This proc adds the necessary Content-Length header. ## | This proc also handles redirection. var xh = extraHeaders & "Content-Length: " & $len(body) & "\c\L" - result = request(url, httpPOST, xh, body) + result = request(url, httpPOST, xh, body, sslContext) for i in 1..maxRedirects: if result.status.redirection(): var locationHeader = result.headers["Location"] @@ -310,7 +317,8 @@ proc post*(url: string, extraHeaders = "", body = "", var meth = if result.status != "307": httpGet else: httpPost result = request(locationHeader, meth, xh, body) -proc postContent*(url: string, extraHeaders = "", body = ""): string = +proc postContent*(url: string, extraHeaders = "", body = "", + sslContext: PSSLContext = defaultSSLContext): string = ## | POST's ``body`` to ``url`` and returns the response's body as a string ## | Raises exceptions for the status codes ``4xx`` and ``5xx`` var r = post(url, extraHeaders, body) @@ -319,11 +327,12 @@ proc postContent*(url: string, extraHeaders = "", body = ""): string = else: return r.body -proc downloadFile*(url: string, outputFilename: string) = +proc downloadFile*(url: string, outputFilename: string, + sslContext: PSSLContext = defaultSSLContext) = ## Downloads ``url`` and saves it to ``outputFilename`` var f: TFile if open(f, outputFilename, fmWrite): - f.write(getContent(url)) + f.write(getContent(url, sslContext)) f.close() else: fileError("Unable to open file") diff --git a/lib/pure/os.nim b/lib/pure/os.nim index a220c1da4..9513dbffb 100755 --- a/lib/pure/os.nim +++ b/lib/pure/os.nim @@ -554,7 +554,8 @@ proc splitFile*(path: string): tuple[dir, name, ext: string] {. var dotPos = path.len for i in countdown(len(path)-1, 0): if path[i] == ExtSep: - if dotPos == path.len and i > 0: dotPos = i + if dotPos == path.len and i > 0 and + path[i-1] notin {dirsep, altsep}: dotPos = i elif path[i] in {dirsep, altsep}: sepPos = i break From 0916137287b1d1468810f0ad4cf638eed5436f5e Mon Sep 17 00:00:00 2001 From: Dominik Picheta Date: Sun, 2 Dec 2012 13:45:28 +0000 Subject: [PATCH 2/8] Fixes error in httpclient. --- lib/pure/httpclient.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pure/httpclient.nim b/lib/pure/httpclient.nim index 462db91b1..20b448123 100755 --- a/lib/pure/httpclient.nim +++ b/lib/pure/httpclient.nim @@ -240,7 +240,7 @@ type when not defined(ssl): type PSSLContext = ref object - let defaultSSLContext = nil + let defaultSSLContext: PSSLContext = nil else: let defaultSSLContext = newContext(verifyMode = CVerifyNone) From 8948a97151fc000414aee7cd4064881ef646a26c Mon Sep 17 00:00:00 2001 From: Araq Date: Sun, 2 Dec 2012 20:02:42 +0100 Subject: [PATCH 3/8] bugfix: 'not nil' and 'shared' types --- compiler/semtypes.nim | 9 ++++++++- lib/pure/sockets.nim | 2 ++ lib/wrappers/openssl.nim | 2 ++ tests/reject/tnotnil.nim | 12 ++++++++++-- todo.txt | 3 +-- 5 files changed, 23 insertions(+), 5 deletions(-) diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index 9efeba5b7..6478c1ec6 100755 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -787,6 +787,12 @@ proc semTypeExpr(c: PContext, n: PNode): PType = else: LocalError(n.info, errTypeExpected, n.renderTree) +proc freshType(res, prev: PType): PType {.inline.} = + if prev.isNil: + result = copyType(result, result.owner, keepId=false) + else: + result = res + proc semTypeNode(c: PContext, n: PNode, prev: PType): PType = result = nil if gCmd == cmdIdeTools: suggestExpr(c, n) @@ -825,7 +831,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType = checkSonsLen(n, 3) result = semTypeNode(c, n.sons[1], prev) if result.kind in NilableTypes and n.sons[2].kind == nkNilLit: - # XXX this is wrong for tyString at least + result = freshType(result, prev) result.flags.incl(tfNotNil) else: LocalError(n.info, errGenerated, "invalid type") @@ -920,6 +926,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType = of nkSharedTy: checkSonsLen(n, 1) result = semTypeNode(c, n.sons[0], prev) + result = freshType(result, prev) result.flags.incl(tfShared) else: LocalError(n.info, errTypeExpected) diff --git a/lib/pure/sockets.nim b/lib/pure/sockets.nim index 371641b06..6a3c644bd 100755 --- a/lib/pure/sockets.nim +++ b/lib/pure/sockets.nim @@ -14,6 +14,8 @@ ## For OpenSSL support compile with ``-d:ssl``. When using SSL be aware that ## most functions will then raise ``ESSL`` on SSL errors. +{.deadCodeElim: on.} + when hostos == "solaris": {.passl: "-lsocket -lnsl".} diff --git a/lib/wrappers/openssl.nim b/lib/wrappers/openssl.nim index 1063f401d..752e594d1 100755 --- a/lib/wrappers/openssl.nim +++ b/lib/wrappers/openssl.nim @@ -39,6 +39,8 @@ ## OpenSSL support +{.deadCodeElim: on.} + when defined(WINDOWS): const DLLSSLName = "(ssleay32|libssl32).dll" diff --git a/tests/reject/tnotnil.nim b/tests/reject/tnotnil.nim index 8676aedf8..b02e33713 100644 --- a/tests/reject/tnotnil.nim +++ b/tests/reject/tnotnil.nim @@ -1,5 +1,5 @@ discard """ - line: 11 + line: 22 errormgs: "type mismatch" """ @@ -7,9 +7,17 @@ type PObj = ref TObj not nil TObj = object x: int + + MyString = string not nil -var x: PObj = nil +#var x: PObj = nil proc p(x: string not nil): int = result = 45 +proc q(x: MyString) = nil +proc q2(x: string) = nil + +q2(nil) +q(nil) + diff --git a/todo.txt b/todo.txt index ca2def6aa..f736ce8dd 100755 --- a/todo.txt +++ b/todo.txt @@ -1,7 +1,6 @@ version 0.9.2 ============= -- fix tfShared and tfNotNil - test&finish first class iterators: * nested iterators * test generic iterators @@ -20,7 +19,7 @@ version 0.9.X ============= - implement the missing features wrt inheritance -- implement generic methods +- implement generic methods and generic converters - improve the compiler as a service - ``=`` should be overloadable; requires specialization for ``=`` - implement constructors + full 'not nil' checking From 08342240709690f81286aea207a037348e46f635 Mon Sep 17 00:00:00 2001 From: Araq Date: Mon, 3 Dec 2012 21:48:12 +0100 Subject: [PATCH 4/8] disable SSLv2_method for ubuntu --- compiler/sigmatch.nim | 6 +++--- lib/pure/sockets.nim | 5 ++++- todo.txt | 11 ++++++----- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index 799622355..8913b6d5d 100755 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -837,10 +837,10 @@ proc matchesAux*(c: PContext, n, nOrig: PNode, m.baseTypeMatch = false var arg = ParamTypesMatch(c, m, formal.typ, n.sons[a].typ, n.sons[a], nOrig.sons[a]) - if arg == nil: + if arg == nil: m.state = csNoMatch - return - if m.baseTypeMatch: + return + if m.baseTypeMatch: assert(container == nil) container = newNodeI(nkBracket, n.sons[a].info) addSon(container, arg) diff --git a/lib/pure/sockets.nim b/lib/pure/sockets.nim index 6a3c644bd..01b97197e 100755 --- a/lib/pure/sockets.nim +++ b/lib/pure/sockets.nim @@ -258,7 +258,10 @@ when defined(ssl): of protSSLv23: newCTX = SSL_CTX_new(SSLv23_method()) # SSlv2,3 and TLS1 support. of protSSLv2: - newCTX = SSL_CTX_new(SSLv2_method()) + when not defined(linux): + newCTX = SSL_CTX_new(SSLv2_method()) + else: + SSLError() of protSSLv3: newCTX = SSL_CTX_new(SSLv3_method()) of protTLSv1: diff --git a/todo.txt b/todo.txt index f736ce8dd..b7147c235 100755 --- a/todo.txt +++ b/todo.txt @@ -1,11 +1,6 @@ version 0.9.2 ============= -- test&finish first class iterators: - * nested iterators - * test generic iterators - -- fix closure bug finally - overloading based on ASTs: 'constraint' should not be in PType but for the parameter *symbol* @@ -14,6 +9,12 @@ version 0.9.2 - ``hoist`` pragma for loop hoisting: can be easily done with AST overloading + global +- test&finish first class iterators: + * nested iterators + * test generic iterators +- fix closure bug finally +- fix marshal bug + version 0.9.X ============= From 7171ae62cb94bf5e7ed426ec0679e4247c993121 Mon Sep 17 00:00:00 2001 From: Araq Date: Wed, 5 Dec 2012 01:39:49 +0100 Subject: [PATCH 5/8] constraint now part of the parameter symbol and not of the type --- compiler/ast.nim | 2 +- compiler/parampatterns.nim | 4 ++-- compiler/patterns.nim | 4 ++-- compiler/rodread.nim | 6 +++--- compiler/rodwrite.nim | 6 +++--- compiler/semtypes.nim | 18 +++++++++++------- todo.txt | 6 +++--- 7 files changed, 25 insertions(+), 21 deletions(-) diff --git a/compiler/ast.nim b/compiler/ast.nim index f4ba1ef70..82a20c312 100755 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -624,6 +624,7 @@ type loc*: TLoc annex*: PLib # additional fields (seldom used, so we use a # reference to another object to safe space) + constraint*: PNode # additional constraints like 'lit|result' TTypeSeq* = seq[PType] TType* = object of TIdObj # types are identical iff they have the @@ -650,7 +651,6 @@ type align*: int # the type's alignment requirements containerID*: int # used for type checking of generics loc*: TLoc - constraint*: PNode # additional constraints like 'lit|result' TPair*{.final.} = object key*, val*: PObject diff --git a/compiler/parampatterns.nim b/compiler/parampatterns.nim index ee1f69818..21c7faf19 100644 --- a/compiler/parampatterns.nim +++ b/compiler/parampatterns.nim @@ -48,8 +48,8 @@ proc add(code: var TPatternCode, op: TOpcode) {.inline.} = add(code, chr(ord(op))) proc whichAlias*(p: PSym): TAliasRequest = - if p.typ.constraint != nil: - result = TAliasRequest(p.typ.constraint.strVal[0].ord) + if p.constraint != nil: + result = TAliasRequest(p.constraint.strVal[0].ord) proc compileConstraints(p: PNode, result: var TPatternCode) = case p.kind diff --git a/compiler/patterns.nim b/compiler/patterns.nim index af259c916..b7792100f 100644 --- a/compiler/patterns.nim +++ b/compiler/patterns.nim @@ -71,8 +71,8 @@ proc inSymChoice(sc, x: PNode): bool = proc checkTypes(c: PPatternContext, p: PSym, n: PNode): bool = # check param constraints first here as this is quite optimized: - if p.typ.constraint != nil: - result = matchNodeKinds(p.typ.constraint, n) + if p.constraint != nil: + result = matchNodeKinds(p.constraint, n) if not result: return if isNil(n.typ): result = p.typ.kind in {tyEmpty, tyStmt} diff --git a/compiler/rodread.nim b/compiler/rodread.nim index 4461641db..722887299 100755 --- a/compiler/rodread.nim +++ b/compiler/rodread.nim @@ -330,9 +330,6 @@ proc decodeType(r: PRodReader, info: TLineInfo): PType = if r.s[r.pos] == '@': inc(r.pos) result.containerID = decodeVInt(r.s, r.pos) - if r.s[r.pos] == '`': - inc(r.pos) - result.constraint = decodeNode(r, UnknownLineInfo()) decodeLoc(r, result.loc, info) while r.s[r.pos] == '^': inc(r.pos) @@ -423,6 +420,9 @@ proc decodeSym(r: PRodReader, info: TLineInfo): PSym = result.offset = - 1 decodeLoc(r, result.loc, result.info) result.annex = decodeLib(r, info) + if r.s[r.pos] == '#': + inc(r.pos) + result.constraint = decodeNode(r, UnknownLineInfo()) if r.s[r.pos] == '(': if result.kind in routineKinds: result.ast = decodeNodeLazyBody(r, result.info, result) diff --git a/compiler/rodwrite.nim b/compiler/rodwrite.nim index 5be9a2439..0a361d4dd 100755 --- a/compiler/rodwrite.nim +++ b/compiler/rodwrite.nim @@ -233,9 +233,6 @@ proc encodeType(w: PRodWriter, t: PType, result: var string) = if t.containerID != 0: add(result, '@') encodeVInt(t.containerID, result) - if t.constraint != nil: - add(result, '`') - encodeNode(w, UnknownLineInfo(), t.constraint, result) encodeLoc(w, t.loc, result) for i in countup(0, sonsLen(t) - 1): if t.sons[i] == nil: @@ -295,6 +292,9 @@ proc encodeSym(w: PRodWriter, s: PSym, result: var string) = encodeVInt(s.offset, result) encodeLoc(w, s.loc, result) if s.annex != nil: encodeLib(w, s.annex, s.info, result) + if s.constraint != nil: + add(result, '#') + encodeNode(w, UnknownLineInfo(), s.constraint, result) # lazy loading will soon reload the ast lazily, so the ast needs to be # the last entry of a symbol: if s.ast != nil: diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index 6478c1ec6..3da2a95b7 100755 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -635,6 +635,13 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode, genericParams.addSon(newSymNode(s)) result = typeClass +proc semParamType(c: PContext, n: PNode, constraint: var PNode): PType = + if n.kind == nkCurlyExpr: + result = semTypeNode(c, n.sons[0], nil) + constraint = semNodeKindConstraints(n) + else: + result = semTypeNode(c, n, nil) + proc semProcTypeNode(c: PContext, n, genericParams: PNode, prev: PType, kind: TSymKind): PType = var @@ -660,13 +667,14 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode, checkMinSonsLen(a, 3) var typ: PType = nil - def: PNode = nil + def: PNode = nil + constraint: PNode = nil length = sonsLen(a) hasType = a.sons[length-2].kind != nkEmpty hasDefault = a.sons[length-1].kind != nkEmpty if hasType: - typ = semTypeNode(c, a.sons[length-2], nil) + typ = semParamType(c, a.sons[length-2], constraint) if hasDefault: def = semExprWithType(c, a.sons[length-1]) @@ -689,6 +697,7 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode, arg.name.s, arg.info).skipIntLit arg.typ = finalType arg.position = counter + arg.constraint = constraint inc(counter) if def != nil and def.kind != nkEmpty: arg.ast = copyTree(def) if ContainsOrIncl(check, arg.name.id): @@ -839,11 +848,6 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType = result = semTypeExpr(c, n) else: result = semTypeExpr(c, n) - of nkCurlyExpr: - result = semTypeNode(c, n.sons[0], nil) - if result != nil: - result = copyType(result, getCurrOwner(), true) - result.constraint = semNodeKindConstraints(n) of nkWhenStmt: var whenResult = semWhen(c, n, false) if whenResult.kind == nkStmtList: whenResult.kind = nkStmtListType diff --git a/todo.txt b/todo.txt index b7147c235..3d3ba8346 100755 --- a/todo.txt +++ b/todo.txt @@ -1,8 +1,8 @@ version 0.9.2 ============= -- overloading based on ASTs: 'constraint' should not be in PType but for the - parameter *symbol* +- overloading based on ASTs +- implement generic converters - implement ``partial`` pragma for partial evaluation: easily done with AST overloading @@ -20,7 +20,7 @@ version 0.9.X ============= - implement the missing features wrt inheritance -- implement generic methods and generic converters +- implement generic methods - improve the compiler as a service - ``=`` should be overloadable; requires specialization for ``=`` - implement constructors + full 'not nil' checking From 38ab30d153f7ae3b1b2b74329092ffb7ca781ead Mon Sep 17 00:00:00 2001 From: Araq Date: Wed, 5 Dec 2012 22:03:36 +0100 Subject: [PATCH 6/8] implemented generic converters --- compiler/semcall.nim | 12 +++++++++++ compiler/semstmts.nim | 4 ++-- compiler/sigmatch.nim | 19 +++++++++++++--- tests/compile/tsecondarrayproperty.nim | 28 ++++++++++++++++++++++++ tests/run/tgenericconverter.nim | 30 ++++++++++++++++++++++++++ todo.txt | 2 -- web/news.txt | 1 + 7 files changed, 89 insertions(+), 7 deletions(-) create mode 100644 tests/compile/tsecondarrayproperty.nim create mode 100644 tests/run/tgenericconverter.nim diff --git a/compiler/semcall.nim b/compiler/semcall.nim index a5107bf64..962e4d3cc 100755 --- a/compiler/semcall.nim +++ b/compiler/semcall.nim @@ -84,6 +84,16 @@ proc resolveOverloads(c: PContext, n, orig: PNode, getProcHeader(best.calleeSym), getProcHeader(alt.calleeSym), args]) +proc instantiateGenericConverters(c: PContext, n: PNode, x: TCandidate) {. + noinline.}= + for i in 1 .. Date: Wed, 5 Dec 2012 22:58:52 +0100 Subject: [PATCH 7/8] fixes #266 --- compiler/semstmts.nim | 2 -- lib/pure/fsmonitor.nim | 4 +--- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index c5b226004..8b55058bb 100755 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -869,8 +869,6 @@ proc semMethod(c: PContext, n: PNode): PNode = proc semConverterDef(c: PContext, n: PNode): PNode = if not isTopLevel(c): LocalError(n.info, errXOnlyAtModuleScope, "converter") checkSonsLen(n, bodyPos + 1) - #if n.sons[genericParamsPos].kind != nkEmpty: - # LocalError(n.info, errNoGenericParamsAllowedForX, "converter") result = semProcAux(c, n, skConverter, converterPragmas) var s = result.sons[namePos].sym var t = s.typ diff --git a/lib/pure/fsmonitor.nim b/lib/pure/fsmonitor.nim index 92a80425a..a554cf963 100644 --- a/lib/pure/fsmonitor.nim +++ b/lib/pure/fsmonitor.nim @@ -17,9 +17,7 @@ ## module will therefore not work with any Linux kernel prior to that, unless ## it has been patched to support inotify. -when defined(windows): - {.error: "Windows is not yet supported by this module.".} -elif defined(linux): +when defined(linux) or defined(nimdoc): from posix import read else: {.error: "Your platform is not supported.".} From 6431e602160a5f2e1323a057e9c0166431e5a002 Mon Sep 17 00:00:00 2001 From: Araq Date: Wed, 5 Dec 2012 23:28:35 +0100 Subject: [PATCH 8/8] fixes #269 --- compiler/docgen.nim | 3 +++ compiler/semstmts.nim | 2 ++ 2 files changed, 5 insertions(+) diff --git a/compiler/docgen.nim b/compiler/docgen.nim index e06277f91..aff77cc1f 100755 --- a/compiler/docgen.nim +++ b/compiler/docgen.nim @@ -145,6 +145,9 @@ proc isVisible(n: PNode): bool = var v = n.sons[0].ident result = v.id == ord(wStar) or v.id == ord(wMinus) elif n.kind == nkSym: + # we cannot generate code for forwarded symbols here as we have no + # exception tracking information here. Instead we copy over the comment + # from the proc header. result = {sfExported, sfFromGeneric, sfForward}*n.sym.flags == {sfExported} elif n.kind == nkPragmaExpr: result = isVisible(n.sons[0]) diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 8b55058bb..68d485f48 100755 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -780,6 +780,8 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind, n.sons[pragmasPos] = proto.ast.sons[pragmasPos] if n.sons[namePos].kind != nkSym: InternalError(n.info, "semProcAux") n.sons[namePos].sym = proto + if gCmd == cmdDoc and not isNil(proto.ast.comment): + n.comment = proto.ast.comment proto.ast = n # needed for code generation popOwner() pushOwner(s)