From 3ce400bb00363a4b207ba966937d26c746d25e1b Mon Sep 17 00:00:00 2001 From: Zahary Karadjov Date: Sun, 3 Jun 2012 18:00:45 +0300 Subject: [PATCH 01/15] bugfix: finally blocks were not executed when the except block is exited by raise or return --- compiler/ccgstmts.nim | 29 ++++++++++------- compiler/cgendata.nim | 5 +-- tests/run/texceptions.nim | 66 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 87 insertions(+), 13 deletions(-) create mode 100644 tests/run/texceptions.nim diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim index 46e4f75dff..d21093845b 100755 --- a/compiler/ccgstmts.nim +++ b/compiler/ccgstmts.nim @@ -205,15 +205,19 @@ proc blockLeaveActions(p: BProc, howMany: int) = stack[i-1] = p.nestedTryStmts[L-i] setLen(p.nestedTryStmts, L-howMany) + var alreadyPoppedCnt = p.inExceptBlock for tryStmt in items(stack): - appcg(p, cpsStmts, "#popSafePoint();$n", []) + if alreadyPoppedCnt > 0: + dec alreadyPoppedCnt + else: + appcg(p, cpsStmts, "#popSafePoint();$n", []) var finallyStmt = lastSon(tryStmt) if finallyStmt.kind == nkFinally: genStmts(p, finallyStmt.sons[0]) # push old elements again: for i in countdown(howMany-1, 0): p.nestedTryStmts.add(stack[i]) - for i in countdown(p.popCurrExc-1, 0): + for i in countdown(p.inExceptBlock-1, 0): appcg(p, cpsStmts, "#popCurrentException();$n", []) proc genReturnStmt(p: BProc, t: PNode) = @@ -310,7 +314,13 @@ proc getRaiseFrmt(p: BProc): string = #else: result = "#raiseException((#E_Base*)$1, $2);$n" -proc genRaiseStmt(p: BProc, t: PNode) = +proc genRaiseStmt(p: BProc, t: PNode) = + if p.inExceptBlock > 0: + # if the current try stmt have a finally block, + # we must execute it before reraising + var finallyBlock = p.nestedTryStmts[p.nestedTryStmts.len - 1].lastSon + if finallyBlock.kind == nkFinally: + genStmts(p, finallyBlock.sons[0]) if t.sons[0].kind != nkEmpty: var a: TLoc InitLocExpr(p, t.sons[0], a) @@ -628,7 +638,7 @@ proc genTryStmt(p: BProc, t: PNode) = add(p.nestedTryStmts, t) genStmts(p, t.sons[0]) endBlock(p, ropecg(p.module, "#popSafePoint();$n } else {$n#popSafePoint();$n")) - discard pop(p.nestedTryStmts) + inc p.inExceptBlock var i = 1 while (i < length) and (t.sons[i].kind == nkExceptBranch): var blen = sonsLen(t.sons[i]) @@ -637,13 +647,10 @@ proc genTryStmt(p: BProc, t: PNode) = if i > 1: appf(p.s(cpsStmts), "else") startBlock(p) appcg(p, cpsStmts, "$1.status = 0;$n", [safePoint]) - inc p.popCurrExc genStmts(p, t.sons[i].sons[0]) - dec p.popCurrExc appcg(p, cpsStmts, "#popCurrentException();$n", []) endBlock(p) else: - inc p.popCurrExc var orExpr: PRope = nil for j in countup(0, blen - 2): assert(t.sons[i].sons[j].kind == nkType) @@ -655,9 +662,10 @@ proc genTryStmt(p: BProc, t: PNode) = startBlock(p, "if ($1) {$n", [orExpr]) appcg(p, cpsStmts, "$1.status = 0;$n", [safePoint]) genStmts(p, t.sons[i].sons[blen-1]) - dec p.popCurrExc endBlock(p, ropecg(p.module, "#popCurrentException();}$n")) inc(i) + dec p.inExceptBlock + discard pop(p.nestedTryStmts) appf(p.s(cpsStmts), "}$n") # end of else block if i < length and t.sons[i].kind == nkFinally: genSimpleBlock(p, t.sons[i].sons[0]) @@ -820,9 +828,8 @@ proc genStmts(p: BProc, t: PNode) = initLocExpr(p, t.sons[0], a) of nkAsmStmt: genAsmStmt(p, t) of nkTryStmt: - #if gCmd == cmdCompileToCpp: genTryStmtCpp(p, t) - #else: - genTryStmt(p, t) + if gCmd == cmdCompileToCpp: genTryStmtCpp(p, t) + else: genTryStmt(p, t) of nkRaiseStmt: genRaiseStmt(p, t) of nkTypeSection: # we have to emit the type information for object types here to support diff --git a/compiler/cgendata.nim b/compiler/cgendata.nim index a22c13f3aa..bcdf53afd2 100644 --- a/compiler/cgendata.nim +++ b/compiler/cgendata.nim @@ -62,8 +62,9 @@ type ThreadVarAccessed*: bool # true if the proc already accessed some threadvar nestedTryStmts*: seq[PNode] # in how many nested try statements we are # (the vars must be volatile then) - popCurrExc*: Natural # how often to emit 'popCurrentException()' - # before 'break'|'return' + inExceptBlock*: int # are we currently inside an except block? + # leaving such scopes by raise or by return must + # execute any applicable finally blocks labels*: Natural # for generating unique labels in the C proc blocks*: seq[TBlock] # nested blocks breakIdx*: int # the block that will be exited diff --git a/tests/run/texceptions.nim b/tests/run/texceptions.nim new file mode 100644 index 0000000000..2e6101c2a1 --- /dev/null +++ b/tests/run/texceptions.nim @@ -0,0 +1,66 @@ +discard """ + output: ''' +BEFORE +FINALLY + +BEFORE +EXCEPT +FINALLY +RECOVER + +BEFORE +EXCEPT +FINALLY +''' +""" + +echo "" + +proc no_expcetion = + try: + echo "BEFORE" + + except: + echo "EXCEPT" + raise + + finally: + echo "FINALLY" + +try: no_expcetion() +except: echo "RECOVER" + +echo "" + +proc reraise_in_except = + try: + echo "BEFORE" + raise newException(EIO, "") + + except: + echo "EXCEPT" + raise + + finally: + echo "FINALLY" + +try: reraise_in_except() +except: echo "RECOVER" + +echo "" + +proc return_in_except = + try: + echo "BEFORE" + raise newException(EIO, "") + + except: + echo "EXCEPT" + return + + finally: + echo "FINALLY" + +try: return_in_except() +except: echo "RECOVER" + From bb850aafec622401d26e052cbd8cd6a7fef36156 Mon Sep 17 00:00:00 2001 From: Zahary Karadjov Date: Sun, 3 Jun 2012 20:37:56 +0300 Subject: [PATCH 02/15] codegen for C++ exceptions --- compiler/ccgstmts.nim | 136 ++++++++++++++++++++------------------ lib/nimbase.h | 7 ++ tests/run/texceptions.nim | 2 +- 3 files changed, 80 insertions(+), 65 deletions(-) diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim index d21093845b..0e85f2c2cd 100755 --- a/compiler/ccgstmts.nim +++ b/compiler/ccgstmts.nim @@ -207,18 +207,20 @@ proc blockLeaveActions(p: BProc, howMany: int) = var alreadyPoppedCnt = p.inExceptBlock for tryStmt in items(stack): - if alreadyPoppedCnt > 0: - dec alreadyPoppedCnt - else: - appcg(p, cpsStmts, "#popSafePoint();$n", []) + if gCmd != cmdCompileToCpp: + if alreadyPoppedCnt > 0: + dec alreadyPoppedCnt + else: + appcg(p, cpsStmts, "#popSafePoint();$n", []) var finallyStmt = lastSon(tryStmt) if finallyStmt.kind == nkFinally: genStmts(p, finallyStmt.sons[0]) # push old elements again: for i in countdown(howMany-1, 0): p.nestedTryStmts.add(stack[i]) - for i in countdown(p.inExceptBlock-1, 0): - appcg(p, cpsStmts, "#popCurrentException();$n", []) + if gCmd != cmdCompileToCpp: + for i in countdown(p.inExceptBlock-1, 0): + appcg(p, cpsStmts, "#popCurrentException();$n", []) proc genReturnStmt(p: BProc, t: PNode) = p.beforeRetNeeded = true @@ -309,10 +311,10 @@ proc genBreakStmt(p: BProc, t: PNode) = appf(p.s(cpsStmts), "goto $1;$n", [label]) proc getRaiseFrmt(p: BProc): string = - #if gCmd == cmdCompileToCpp: - # result = "throw #nimException($1, $2);$n" - #else: - result = "#raiseException((#E_Base*)$1, $2);$n" + if gCmd == cmdCompileToCpp: + result = "throw NimException($1, $2);$n" + else: + result = "#raiseException((#E_Base*)$1, $2);$n" proc genRaiseStmt(p: BProc, t: PNode) = if p.inExceptBlock > 0: @@ -320,7 +322,7 @@ proc genRaiseStmt(p: BProc, t: PNode) = # we must execute it before reraising var finallyBlock = p.nestedTryStmts[p.nestedTryStmts.len - 1].lastSon if finallyBlock.kind == nkFinally: - genStmts(p, finallyBlock.sons[0]) + genSimpleBlock(p, finallyBlock.sons[0]) if t.sons[0].kind != nkEmpty: var a: TLoc InitLocExpr(p, t.sons[0], a) @@ -331,10 +333,10 @@ proc genRaiseStmt(p: BProc, t: PNode) = else: genLineDir(p, t) # reraise the last exception: - #if gCmd == cmdCompileToCpp: - # appcg(p, cpsStmts, "throw;$n") - #else: - appcg(p, cpsStmts, "#reraiseException();$n") + if gCmd == cmdCompileToCpp: + appcg(p, cpsStmts, "throw;$n") + else: + appcg(p, cpsStmts, "#reraiseException();$n") proc genCaseGenericBranch(p: BProc, b: PNode, e: TLoc, rangeFormat, eqFormat: TFormatStr, labl: TLabel) = @@ -528,80 +530,86 @@ proc hasGeneralExceptSection(t: PNode): bool = inc(i) result = false -proc genTryStmtCpp(p: BProc, t: PNode) = +proc genTryStmtCpp(p: BProc, t: PNode) = # code to generate: # - # bool tmpRethrow = false; + # XXX: There should be a standard dispatch algorithm + # that's used both here and with multi-methods + # # try # { # myDiv(4, 9); - # } catch (NimException& tmp) { - # tmpRethrow = true; - # switch (tmp.exc) - # { - # case DIVIDE_BY_ZERO: - # tmpRethrow = false; - # printf("Division by Zero\n"); - # break; - # default: // used for general except! - # generalExceptPart(); - # tmpRethrow = false; + # } catch (NimException& exp) { + # if (isObj(exp, EIO) { + # ... + # } else if (isObj(exp, ESystem) { + # ... + # finallyPart() + # raise; + # } else { + # // general handler # } # } - # excHandler = excHandler->prev; // we handled the exception # finallyPart(); - # if (tmpRethrow) throw; - # - # XXX: push blocks - var - rethrowFlag: PRope + var exc: PRope i, length, blen: int genLineDir(p, t) - rethrowFlag = nil exc = getTempName() - if not hasGeneralExceptSection(t): - rethrowFlag = getTempName() - appf(p.s(cpsLocals), "volatile NIM_BOOL $1 = NIM_FALSE;$n", [rethrowFlag]) - if optStackTrace in p.Options: + if optStackTrace in p.Options: appcg(p, cpsStmts, "#setFrame((TFrame*)&F);$n") - appf(p.s(cpsStmts), "try {$n") add(p.nestedTryStmts, t) + startBlock(p, "try {$n") genStmts(p, t.sons[0]) length = sonsLen(t) - if t.sons[1].kind == nkExceptBranch: - appf(p.s(cpsStmts), "} catch (NimException& $1) {$n", [exc]) - if rethrowFlag != nil: - appf(p.s(cpsStmts), "$1 = NIM_TRUE;$n", [rethrowFlag]) - appf(p.s(cpsStmts), "if ($1.sp.exc) {$n", [exc]) + endBlock(p, ropecg(p.module, "} catch (NimException& $1) {$n", [exc])) + inc p.inExceptBlock i = 1 - while (i < length) and (t.sons[i].kind == nkExceptBranch): + var catchAllPresent = false + while (i < length) and (t.sons[i].kind == nkExceptBranch): blen = sonsLen(t.sons[i]) - if blen == 1: + if i > 1: appf(p.s(cpsStmts), "else ") + if blen == 1: # general except section: - appf(p.s(cpsStmts), "default:$n") - genStmts(p, t.sons[i].sons[0]) - else: - for j in countup(0, blen - 2): + catchAllPresent = true + genSimpleBlock(p, t.sons[i].sons[0]) + else: + var orExpr: PRope = nil + for j in countup(0, blen - 2): assert(t.sons[i].sons[j].kind == nkType) - appf(p.s(cpsStmts), "case $1:$n", [toRope(t.sons[i].sons[j].typ.id)]) - genStmts(p, t.sons[i].sons[blen - 1]) - if rethrowFlag != nil: - appf(p.s(cpsStmts), "$1 = NIM_FALSE; ", [rethrowFlag]) - appf(p.s(cpsStmts), "break;$n") + if orExpr != nil: app(orExpr, "||") + appcg(p.module, orExpr, + "#isObj($1.exp->m_type, $2)", + [exc, genTypeInfo(p.module, t.sons[i].sons[j].typ)]) + if i > 1: app(p.s(cpsStmts), "else ") + appf(p.s(cpsStmts), "if ($1) ", [orExpr]) + genSimpleBlock(p, t.sons[i].sons[blen-1]) inc(i) - if t.sons[1].kind == nkExceptBranch: - appf(p.s(cpsStmts), "}}$n") # end of catch-switch statement - appcg(p, cpsStmts, "#popSafePoint();") + + # reraise the exception if there was no catch all + # and none of the handlers matched + if not catchAllPresent: + if i > 1: appf(p.s(cpsStmts), "else ") + startBlock(p) + var finallyBlock = t.lastSon + if finallyBlock.kind == nkFinally: + genStmts(p, finallyBlock.sons[0]) + appcg(p, cpsStmts, "throw;$n") + endBlock(p) + + appf(p.s(cpsStmts), "}$n") # end of catch block + dec p.inExceptBlock + discard pop(p.nestedTryStmts) - if (i < length) and (t.sons[i].kind == nkFinally): - genStmts(p, t.sons[i].sons[0]) - if rethrowFlag != nil: - appf(p.s(cpsStmts), "if ($1) { throw; }$n", [rethrowFlag]) - + if (i < length) and (t.sons[i].kind == nkFinally): + genSimpleBlock(p, t.sons[i].sons[0]) + proc genTryStmt(p: BProc, t: PNode) = # code to generate: # + # XXX: There should be a standard dispatch algorithm + # that's used both here and with multi-methods + # # TSafePoint sp; # pushSafePoint(&sp); # sp.status = setjmp(sp.context); diff --git a/lib/nimbase.h b/lib/nimbase.h index a114430abb..61e7da75e1 100755 --- a/lib/nimbase.h +++ b/lib/nimbase.h @@ -281,6 +281,13 @@ static unsigned long nimInf[2]={0xffffffff, 0x7fffffff}; # endif # define NIM_BOOL bool # define NIM_NIL 0 +struct NimException +{ + NimException(struct E_Base* exp, const char* msg): exp(exp), msg(msg) {} + + struct E_Base* exp; + const char* msg; +}; #else # ifdef bool # define NIM_BOOL bool diff --git a/tests/run/texceptions.nim b/tests/run/texceptions.nim index 2e6101c2a1..69b2d0f6a4 100644 --- a/tests/run/texceptions.nim +++ b/tests/run/texceptions.nim @@ -37,7 +37,7 @@ proc reraise_in_except = echo "BEFORE" raise newException(EIO, "") - except: + except EIO: echo "EXCEPT" raise From 3294cb10a944e9c80ccb87173bbd0896597447c9 Mon Sep 17 00:00:00 2001 From: Dominik Picheta Date: Sun, 3 Jun 2012 19:09:42 +0100 Subject: [PATCH 03/15] Sockets are now buffered and have ssl support through openssl. --- lib/impure/ssl.nim | 2 + lib/pure/httpclient.nim | 20 +- lib/pure/smtp.nim | 55 ++--- lib/pure/sockets.nim | 452 +++++++++++++++++++++++++++++++++------ lib/wrappers/openssl.nim | 62 ++++-- web/news.txt | 8 +- 6 files changed, 478 insertions(+), 121 deletions(-) diff --git a/lib/impure/ssl.nim b/lib/impure/ssl.nim index 5fe986b14f..4a101ca92e 100755 --- a/lib/impure/ssl.nim +++ b/lib/impure/ssl.nim @@ -10,6 +10,8 @@ ## This module provides an easy to use sockets-style ## nimrod interface to the OpenSSL library. +{.deprecate.} + import openssl, strutils, os type diff --git a/lib/pure/httpclient.nim b/lib/pure/httpclient.nim index 3af08f040b..c4dbd85091 100755 --- a/lib/pure/httpclient.nim +++ b/lib/pure/httpclient.nim @@ -42,6 +42,14 @@ ## body.add("--xyz--") ## ## echo(postContent("http://validator.w3.org/check", headers, body)) +## +## SSL/TLS support +## =============== +## This requires the OpenSSL library, fortunately it's widely used and installed +## on many operating systems. httpclient will use SSL automatically if you give +## any of the functions a url with the ``https`` schema, for example: +## ``https://github.com/``, you also have to compile with ``ssl`` defined like so: +## ``nimrod c -d:ssl ...``. import sockets, strutils, parseurl, parseutils, strtabs @@ -152,7 +160,7 @@ proc parseBody(d: var string, start: int, s: TSocket, result.add(moreData) proc parseResponse(s: TSocket): TResponse = - var d = s.recv.string + var d = s.recv.string # Warning: without a Connection: Close header this will not work. var i = 0 # Parse the version @@ -241,11 +249,19 @@ proc request*(url: string, httpMethod = httpGET, extraHeaders = "", headers.add(" HTTP/1.1\c\L") add(headers, "Host: " & r.hostname & "\c\L") + add(headers, "Connection: Close\c\L") add(headers, extraHeaders) add(headers, "\c\L") var s = socket() - s.connect(r.hostname, TPort(80)) + var port = TPort(80) + if r.scheme == "https": + when defined(ssl): + s.wrapSocket(verifyMode = CVerifyNone) + port = TPort(443) + if r.port != "": + port = TPort(r.port.parseInt) + s.connect(r.hostname, port) s.send(headers) if body != "": s.send(body) diff --git a/lib/pure/smtp.nim b/lib/pure/smtp.nim index 7eeb026d3f..58c1d4b586 100755 --- a/lib/pure/smtp.nim +++ b/lib/pure/smtp.nim @@ -25,20 +25,17 @@ ## smtp.sendmail("username@gmail.com", @["foo@gmail.com"], $msg) ## ## -## For SSL support this module relies on the SSL module. If you want to -## disable SSL, compile with ``-d:NoSSL``. +## For SSL support this module relies on OpenSSL. If you want to +## enable SSL, compile with ``-d:ssl``. + +when not defined(ssl): + {.error: "The SMTP module should be compiled with SSL support. Compile with -d:ssl."} import sockets, strutils, strtabs, base64, os -when not defined(noSSL): - import ssl - type TSMTP* {.final.} = object sock: TSocket - when not defined(noSSL): - sslSock: TSecureSocket - ssl: Bool debug: Bool TMessage* {.final.} = object @@ -53,20 +50,13 @@ type proc debugSend(smtp: TSMTP, cmd: string) = if smtp.debug: echo("C:" & cmd) - if not smtp.ssl: - smtp.sock.send(cmd) - else: - when not defined(noSSL): - smtp.sslSock.send(cmd) + smtp.sock.send(cmd) -proc debugRecv(smtp: TSMTP): TaintedString = +proc debugRecv(smtp: var TSMTP): TaintedString = var line = TaintedString"" var ret = False - if not smtp.ssl: - ret = smtp.sock.recvLine(line) - else: - when not defined(noSSL): - ret = smtp.sslSock.recvLine(line) + ret = smtp.sock.recvLine(line) + if ret: if smtp.debug: echo("S:" & line.string) @@ -79,7 +69,7 @@ proc quitExcpt(smtp: TSMTP, msg: string) = smtp.debugSend("QUIT") raise newException(EInvalidReply, msg) -proc checkReply(smtp: TSMTP, reply: string) = +proc checkReply(smtp: var TSMTP, reply: string) = var line = smtp.debugRecv() if not line.string.startswith(reply): quitExcpt(smtp, "Expected " & reply & " reply, got: " & line.string) @@ -88,25 +78,21 @@ proc connect*(address: string, port = 25, ssl = false, debug = false): TSMTP = ## Establishes a connection with a SMTP server. ## May fail with EInvalidReply or with a socket error. - - if not ssl: - result.sock = socket() - result.sock.connect(address, TPort(port)) - else: - when not defined(noSSL): - result.ssl = True - discard result.sslSock.connect(address, port) + result.sock = socket() + if ssl: + when defined(ssl): + result.sock.wrapSocket(verifyMode = CVerifyNone) else: - raise newException(EInvalidReply, + raise newException(ESystem, "SMTP module compiled without SSL support") - + result.sock.connect(address, TPort(port)) result.debug = debug result.checkReply("220") result.debugSend("HELO " & address & "\c\L") result.checkReply("250") -proc auth*(smtp: TSMTP, username, password: string) = +proc auth*(smtp: var TSMTP, username, password: string) = ## Sends an AUTH command to the server to login as the `username` ## using `password`. ## May fail with EInvalidReply. @@ -120,7 +106,7 @@ proc auth*(smtp: TSMTP, username, password: string) = smtp.debugSend(encode(password) & "\c\L") smtp.checkReply("235") # Check whether the authentification was successful. -proc sendmail*(smtp: TSMTP, fromaddr: string, +proc sendmail*(smtp: var TSMTP, fromaddr: string, toaddrs: seq[string], msg: string) = ## Sends `msg` from `fromaddr` to `toaddr`. ## Messages may be formed using ``createMessage`` by converting the @@ -142,10 +128,7 @@ proc sendmail*(smtp: TSMTP, fromaddr: string, proc close*(smtp: TSMTP) = ## Disconnects from the SMTP server and closes the socket. smtp.debugSend("QUIT\c\L") - if not smtp.ssl: - smtp.sock.close() - else: - smtp.sslSock.close() + smtp.sock.close() proc createMessage*(mSubject, mBody: string, mTo, mCc: seq[string], otherHeaders: openarray[tuple[name, value: string]]): TMessage = diff --git a/lib/pure/sockets.nim b/lib/pure/sockets.nim index eeec628434..5179527812 100755 --- a/lib/pure/sockets.nim +++ b/lib/pure/sockets.nim @@ -10,11 +10,16 @@ ## This module implements a simple portable type-safe sockets layer. ## ## Most procedures raise EOS on error. - +## +## For OpenSSL support compile with ``-d:ssl``. When using SSL be aware that +## most functions will then raise ``ESSL`` on SSL errors. import os, parseutils from times import epochTime +when defined(ssl): + import openssl + when defined(Windows): import winlean else: @@ -22,8 +27,40 @@ else: # Note: The enumerations are mapped to Window's constants. +when defined(ssl): + type + ESSL* = object of ESynch + + TSSLCVerifyMode* = enum + CVerifyNone, CVerifyPeer + + TSSLProtVersion* = enum + protSSLv2, protSSLv3, protTLSv1, protSSLv23 + + TSSLOptions* = object + verifyMode*: TSSLCVerifyMode + certFile*, keyFile*: string + protVer*: TSSLprotVersion + type - TSocket* = distinct cint ## socket type + TSocketImpl = object ## socket type + fd: cint + case isBuffered: bool # determines whether this socket is buffered. + of true: + buffer: array[0..4000, char] + currPos: int # current index in buffer + bufLen: int # current length of buffer + of false: nil + when defined(ssl): + case isSsl: bool + of true: + sslHandle: PSSL + sslContext: PSSLCTX + wrapOptions: TSSLOptions + of false: nil + + TSocket* = ref TSocketImpl + TPort* = distinct int16 ## port type TDomain* = enum ## domain, which specifies the protocol family of the @@ -65,11 +102,15 @@ type ETimeout* = object of ESynch -const - InvalidSocket* = TSocket(-1'i32) ## invalid socket number +proc newTSocket(fd: int32, isBuff: bool): TSocket = + new(result) + result.fd = fd + result.isBuffered = isBuff + if isBuff: + result.currPos = 0 -proc `==`*(a, b: TSocket): bool {.borrow.} - ## ``==`` for sockets. +let + InvalidSocket*: TSocket = nil ## invalid socket proc `==`*(a, b: TPort): bool {.borrow.} ## ``==`` for ports. @@ -144,18 +185,111 @@ else: result = cint(ord(p)) proc socket*(domain: TDomain = AF_INET, typ: TType = SOCK_STREAM, - protocol: TProtocol = IPPROTO_TCP): TSocket = + protocol: TProtocol = IPPROTO_TCP, buffered = true): TSocket = ## creates a new socket; returns `InvalidSocket` if an error occurs. when defined(Windows): - result = TSocket(winlean.socket(ord(domain), ord(typ), ord(protocol))) + result = newTSocket(winlean.socket(ord(domain), ord(typ), ord(protocol)), buffered) else: - result = TSocket(posix.socket(ToInt(domain), ToInt(typ), ToInt(protocol))) + result = newTSocket(posix.socket(ToInt(domain), ToInt(typ), ToInt(protocol)), buffered) + +when defined(ssl): + CRYPTO_malloc_init() + SslLibraryInit() + SslLoadErrorStrings() + ErrLoadBioStrings() + OpenSSL_add_all_algorithms() + + proc SSLError(s = "") = + if s != "": + raise newException(ESSL, s) + let err = ErrGetError() + if err == 0: + raise newException(ESSL, "An EOF was observed that violates the protocol.") + if err == -1: + OSError() + var errStr = ErrErrorString(err, nil) + raise newException(ESSL, $errStr) + + # http://simplestcodings.blogspot.co.uk/2010/08/secure-server-client-using-openssl-in-c.html + proc loadCertificates(socket: var TSocket, certFile, keyFile: string) = + if certFile != "": + if SSLCTXUseCertificateFile(socket.sslContext, certFile, + SSL_FILETYPE_PEM) != 1: + SSLError() + if keyFile != "": + if SSL_CTX_use_PrivateKey_file(socket.sslContext, keyFile, + SSL_FILETYPE_PEM) != 1: + SSLError() + + if SSL_CTX_check_private_key(socket.sslContext) != 1: + SSLError("Verification of private key file failed.") + + proc wrapSocket*(socket: var TSocket, protVersion = ProtSSLv23, + verifyMode = CVerifyPeer, + certFile = "", keyFile = "") = + ## Creates a SSL context for ``socket`` and wraps the socket in it. + ## + ## Protocol version specifies the protocol to use. SSLv2, SSLv3, TLSv1 are + ## are available with the addition of ``ProtSSLv23`` which allows for + ## compatibility with all of them. + ## + ## There are currently only two options for verify mode; one is ``CVerifyNone`` + ## and with it certificates will not be verified the other is ``CVerifyPeer`` + ## and certificates will be verified for it, ``CVerifyPeer`` is the safest choice. + ## + ## The last two parameters specify the certificate file path and the key file + ## path, a server socket will most likely not work without these. + ## Certificates can be generated using the following command: + ## ``openssl req -x509 -nodes -days 365 -newkey rsa:1024 -keyout mycert.pem -out mycert.pem``. + ## + ## **Warning:** Because SSL is meant to be secure I feel the need to warn you + ## that this "wrapper" has not been thorougly tested and is therefore + ## most likely very prone to security vulnerabilities. + + socket.isSSL = true + socket.wrapOptions.verifyMode = verifyMode + socket.wrapOptions.certFile = certFile + socket.wrapOptions.keyFile = keyFile + socket.wrapOptions.protVer = protVersion + + case protVersion + of protSSLv23: + socket.sslContext = SSL_CTX_new(SSLv23_method()) # SSlv2,3 and TLS1 support. + of protSSLv2: + socket.sslContext = SSL_CTX_new(SSLv2_method()) + of protSSLv3: + socket.sslContext = SSL_CTX_new(SSLv3_method()) + of protTLSv1: + socket.sslContext = SSL_CTX_new(TLSv1_method()) + + if socket.sslContext.SSLCTXSetCipherList("ALL") != 1: + SSLError() + case verifyMode + of CVerifyPeer: + socket.sslContext.SSLCTXSetVerify(SSLVerifyPeer, nil) + of CVerifyNone: + socket.sslContext.SSLCTXSetVerify(SSLVerifyNone, nil) + if socket.sslContext == nil: + SSLError() + + socket.loadCertificates(certFile, keyFile) + + socket.sslHandle = SSLNew(socket.sslContext) + if socket.sslHandle == nil: + SSLError() + + if SSLSetFd(socket.sslHandle, socket.fd) != 1: + SSLError() + + proc wrapSocket*(socket: var TSocket, wo: TSSLOptions) = + ## A variant of the above with a options object. + wrapSocket(socket, wo.protVer, wo.verifyMode, wo.certFile, wo.keyFile) proc listen*(socket: TSocket, backlog = SOMAXCONN) = ## Marks ``socket`` as accepting connections. ## ``Backlog`` specifies the maximum length of the ## queue of pending connections. - if listen(cint(socket), cint(backlog)) < 0'i32: OSError() + if listen(socket.fd, cint(backlog)) < 0'i32: OSError() proc invalidIp4(s: string) {.noreturn, noinline.} = raise newException(EInvalidValue, "invalid ip4 address: " & s) @@ -208,7 +342,7 @@ proc bindAddr*(socket: TSocket, port = TPort(0), address = "") = name.sin_family = posix.AF_INET name.sin_port = sockets.htons(int16(port)) name.sin_addr.s_addr = sockets.htonl(INADDR_ANY) - if bindSocket(cint(socket), cast[ptr TSockAddr](addr(name)), + if bindSocket(socket.fd, cast[ptr TSockAddr](addr(name)), sizeof(name)) < 0'i32: OSError() else: @@ -218,7 +352,7 @@ proc bindAddr*(socket: TSocket, port = TPort(0), address = "") = hints.ai_socktype = toInt(SOCK_STREAM) hints.ai_protocol = toInt(IPPROTO_TCP) gaiNim(address, port, hints, aiList) - if bindSocket(cint(socket), aiList.ai_addr, aiList.ai_addrLen) < 0'i32: + if bindSocket(socket.fd, aiList.ai_addr, aiList.ai_addrLen) < 0'i32: OSError() when false: @@ -245,47 +379,88 @@ proc getSockName*(socket: TSocket): TPort = #name.sin_port = htons(cint16(port)) #name.sin_addr.s_addr = htonl(INADDR_ANY) var namelen: cint = sizeof(name) - if getsockname(cint(socket), cast[ptr TSockAddr](addr(name)), + if getsockname(socket.fd, cast[ptr TSockAddr](addr(name)), addr(namelen)) == -1'i32: OSError() result = TPort(sockets.ntohs(name.sin_port)) -proc acceptAddr*(server: TSocket): tuple[sock: TSocket, address: string] = +proc selectWrite*(writefds: var seq[TSocket], timeout = 500): int + +proc acceptAddr*(server: TSocket): tuple[client: TSocket, address: string] = ## Blocks until a connection is being made from a client. When a connection - ## is made returns the client socket and address of the connecting client. + ## is made sets ``client`` to the client socket and ``address`` to the address + ## of the connecting client. ## If ``server`` is non-blocking then this function returns immediately, and ## if there are no connections queued the returned socket will be ## ``InvalidSocket``. ## This function will raise EOS if an error occurs. - var address: Tsockaddr_in - var addrLen: cint = sizeof(address) - var sock = accept(cint(server), cast[ptr TSockAddr](addr(address)), + ## + ## **Warning:** This function might block even if socket is non-blocking + ## when using SSL. + var sockAddress: Tsockaddr_in + var addrLen: cint = sizeof(sockAddress) + var sock = accept(server.fd, cast[ptr TSockAddr](addr(sockAddress)), addr(addrLen)) + if sock < 0: # TODO: Test on Windows. when defined(windows): var err = WSAGetLastError() if err == WSAEINPROGRESS: - return (InvalidSocket, "") + client = InvalidSocket else: OSError() else: if errno == EAGAIN or errno == EWOULDBLOCK: return (InvalidSocket, "") else: OSError() - else: return (TSocket(sock), $inet_ntoa(address.sin_addr)) + else: + when defined(ssl): + if server.isSSL: + # We must wrap the client sock in a ssl context. + var client = newTSocket(sock, server.isBuffered) + let wo = server.wrapOptions + wrapSocket(client, wo.protVer, wo.verifyMode, + wo.certFile, wo.keyFile) + let ret = SSLAccept(client.sslHandle) + while ret <= 0: + let err = SSLGetError(client.sslHandle, ret) + if err != SSL_ERROR_WANT_ACCEPT: + case err + of SSL_ERROR_ZERO_RETURN: + SSLError("TLS/SSL connection failed to initiate, socket closed prematurely.") + of SSL_ERROR_WANT_READ, SSL_ERROR_WANT_WRITE, SSL_ERROR_WANT_CONNECT: + SSLError("The operation did not complete. Perhaps you should use connectAsync?") + of SSL_ERROR_WANT_ACCEPT: + var sss: seq[TSocket] = @[client] + discard selectWrite(sss, 1500) + continue + of SSL_ERROR_WANT_X509_LOOKUP: + SSLError("Function for x509 lookup has been called.") + of SSL_ERROR_SYSCALL, SSL_ERROR_SSL: + SSLError() + else: + SSLError("Unknown error") + return (client, $inet_ntoa(sockAddress.sin_addr)) + return (newTSocket(sock, server.isBuffered), $inet_ntoa(sockAddress.sin_addr)) proc accept*(server: TSocket): TSocket = ## Equivalent to ``acceptAddr`` but doesn't return the address, only the ## socket. - var (client, a) = acceptAddr(server) + let (client, a) = acceptAddr(server) return client proc close*(socket: TSocket) = ## closes a socket. when defined(windows): - discard winlean.closeSocket(cint(socket)) + discard winlean.closeSocket(socket.fd) else: - discard posix.close(cint(socket)) + discard posix.close(socket.fd) + + when defined(ssl): + if socket.isSSL: + discard SSLShutdown(socket.sslHandle) + + SSLCTXFree(socket.sslContext) proc getServByName*(name, proto: string): TServent = ## well-known getservbyname proc. @@ -365,7 +540,7 @@ proc getSockOptInt*(socket: TSocket, level, optname: int): int = ## getsockopt for integer options. var res: cint var size: cint = sizeof(res) - if getsockopt(cint(socket), cint(level), cint(optname), + if getsockopt(socket.fd, cint(level), cint(optname), addr(res), addr(size)) < 0'i32: OSError() result = int(res) @@ -373,7 +548,7 @@ proc getSockOptInt*(socket: TSocket, level, optname: int): int = proc setSockOptInt*(socket: TSocket, level, optname, optval: int) = ## setsockopt for integer options. var value = cint(optval) - if setsockopt(cint(socket), cint(level), cint(optname), addr(value), + if setsockopt(socket.fd, cint(level), cint(optname), addr(value), sizeof(value)) < 0'i32: OSError() @@ -395,7 +570,7 @@ proc connect*(socket: TSocket, name: string, port = TPort(0), var success = false var it = aiList while it != nil: - if connect(cint(socket), it.ai_addr, it.ai_addrlen) == 0'i32: + if connect(socket.fd, it.ai_addr, it.ai_addrlen) == 0'i32: success = true break it = it.ai_next @@ -403,6 +578,24 @@ proc connect*(socket: TSocket, name: string, port = TPort(0), freeaddrinfo(aiList) if not success: OSError() + when defined(ssl): + if socket.isSSL: + let ret = SSLConnect(socket.sslHandle) + if ret <= 0: + let err = SSLGetError(socket.sslHandle, ret) + case err + of SSL_ERROR_ZERO_RETURN: + SSLError("TLS/SSL connection failed to initiate, socket closed prematurely.") + of SSL_ERROR_WANT_READ, SSL_ERROR_WANT_WRITE, SSL_ERROR_WANT_CONNECT, + SSL_ERROR_WANT_ACCEPT: + SSLError("The operation did not complete. Perhaps you should use connectAsync?") + of SSL_ERROR_WANT_X509_LOOKUP: + SSLError("Function for x509 lookup has been called.") + of SSL_ERROR_SYSCALL, SSL_ERROR_SSL: + SSLError() + else: + SSLError("Unknown error") + when false: var s: TSockAddrIn s.sin_addr.s_addr = inet_addr(name) @@ -415,7 +608,7 @@ proc connect*(socket: TSocket, name: string, port = TPort(0), of AF_INET: s.sin_family = posix.AF_INET of AF_INET6: s.sin_family = posix.AF_INET6 else: nil - if connect(cint(socket), cast[ptr TSockAddr](addr(s)), sizeof(s)) < 0'i32: + if connect(socket.fd, cast[ptr TSockAddr](addr(s)), sizeof(s)) < 0'i32: OSError() proc connectAsync*(socket: TSocket, name: string, port = TPort(0), @@ -431,7 +624,7 @@ proc connectAsync*(socket: TSocket, name: string, port = TPort(0), var success = false var it = aiList while it != nil: - var ret = connect(cint(socket), it.ai_addr, it.ai_addrlen) + var ret = connect(socket.fd, it.ai_addr, it.ai_addrlen) if ret == 0'i32: success = true break @@ -453,6 +646,26 @@ proc connectAsync*(socket: TSocket, name: string, port = TPort(0), freeaddrinfo(aiList) if not success: OSError() + when defined(ssl): + if socket.isSSL: + var ret = SSLConnect(socket.sslHandle) + if ret <= 0: + var errret = SSLGetError(socket.sslHandle, ret) + case errret + of SSL_ERROR_ZERO_RETURN: + SSLError("TLS/SSL connection failed to initiate, socket closed prematurely.") + of SSL_ERROR_WANT_READ, SSL_ERROR_WANT_WRITE, + SSL_ERROR_WANT_ACCEPT: + SSLError("Unexpected error occured.") # This should just not happen. + of SSL_ERROR_WANT_CONNECT: + return + of SSL_ERROR_WANT_X509_LOOKUP: + SSLError("Function for x509 lookup has been called.") + of SSL_ERROR_SYSCALL, SSL_ERROR_SSL: + SSLError() + else: + SSLError("Unknown Error") + proc timeValFromMilliseconds(timeout = 500): TTimeVal = if timeout != -1: var seconds = timeout div 1000 @@ -467,14 +680,14 @@ proc timeValFromMilliseconds(timeout = 500): TTimeVal = proc createFdSet(fd: var TFdSet, s: seq[TSocket], m: var int) = FD_ZERO(fd) for i in items(s): - m = max(m, int(i)) - FD_SET(cint(i), fd) + m = max(m, int(i.fd)) + FD_SET(i.fd, fd) proc pruneSocketSet(s: var seq[TSocket], fd: var TFdSet) = var i = 0 var L = s.len while i < L: - if FD_ISSET(cint(s[i]), fd) != 0'i32: + if FD_ISSET(s[i].fd, fd) != 0'i32: s[i] = s[L-1] dec(L) else: @@ -552,19 +765,64 @@ proc select*(readfds: var seq[TSocket], timeout = 500): int = result = int(select(cint(m+1), addr(rd), nil, nil, nil)) pruneSocketSet(readfds, (rd)) - + +proc readIntoBuf(socket: TSocket, flags: int32): int = + result = 0 + when defined(ssl): + if socket.isSSL: + result = SSLRead(socket.sslHandle, addr(socket.buffer), int(socket.buffer.high)) + else: + result = recv(socket.fd, addr(socket.buffer), int(socket.buffer.high), flags) + else: + result = recv(socket.fd, addr(socket.buffer), int(socket.buffer.high), flags) + if result <= 0: return + socket.bufLen = result + socket.currPos = 0 + +template retRead(flags, read: int) = + let res = socket.readIntoBuf(flags) + if res <= 0: + if read > 0: + return read + else: + return res + proc recv*(socket: TSocket, data: pointer, size: int): int = ## receives data from a socket - result = recv(cint(socket), data, size, 0'i32) + if socket.isBuffered: + if socket.bufLen == 0: + retRead(0'i32, 0) + + var read = 0 + while read < size: + if socket.currPos >= socket.bufLen: + retRead(0'i32, read) + + let chunk = min(socket.bufLen, size-read) + var d = cast[cstring](data) + copyMem(addr(d[read]), addr(socket.buffer[socket.currPos]), chunk) + read.inc(chunk) + socket.currPos.inc(chunk) + + result = read + else: + when defined(ssl): + if socket.isSSL: + result = SSLRead(socket.sslHandle, data, size) + else: + result = recv(socket.fd, data, size, 0'i32) + else: + result = recv(socket.fd, data, size, 0'i32) -template waitFor(): stmt = - if timeout - int(waited * 1000.0) < 1: - raise newException(ETimeout, "Call to recv() timed out.") - var s = @[socket] - var startTime = epochTime() - if select(s, timeout - int(waited * 1000.0)) != 1: - raise newException(ETimeout, "Call to recv() timed out.") - waited += (epochTime() - startTime) +proc waitFor(socket: TSocket, waited: var float, timeout: int) = + if socket.bufLen == 0: + if timeout - int(waited * 1000.0) < 1: + raise newException(ETimeout, "Call to recv() timed out.") + var s = @[socket] + var startTime = epochTime() + if select(s, timeout - int(waited * 1000.0)) != 1: + raise newException(ETimeout, "Call to recv() timed out.") + waited += (epochTime() - startTime) proc recv*(socket: TSocket, data: var string, size: int, timeout: int): int = ## overload with a ``timeout`` parameter in miliseconds. @@ -572,14 +830,30 @@ proc recv*(socket: TSocket, data: var string, size: int, timeout: int): int = var read = 0 while read < size: - waitFor() - result = recv(cint(socket), addr(data[read]), 1, 0'i32) + waitFor(socket, waited, timeout) + result = recv(socket, addr(data[read]), 1) if result < 0: return inc(read) result = read +proc peekChar(socket: TSocket, c: var char): int = + if socket.isBuffered: + result = 1 + if socket.bufLen == 0 or socket.currPos > socket.bufLen-1: + var res = socket.readIntoBuf(0'i32) + if res <= 0: + result = res + + c = socket.buffer[socket.currPos] + else: + when defined(ssl): + if socket.isSSL: + raise newException(ESSL, "Sorry, you cannot use recvLine on an unbuffered SSL socket.") + + result = recv(socket.fd, addr(c), 1, MSG_PEEK) + proc recvLine*(socket: TSocket, line: var TaintedString): bool = ## retrieves a line from ``socket``. If a full line is received ``\r\L`` is not ## added to ``line``, however if solely ``\r\L`` is received then ``data`` @@ -590,6 +864,9 @@ proc recvLine*(socket: TSocket, line: var TaintedString): bool = ## ## If the socket is disconnected, ``line`` will be set to ``""`` and ``True`` ## will be returned. + ## + ## **Warning:** Using this function on a unbuffered ssl socket will result + ## in an error. template addNLIfEmpty(): stmt = if line.len == 0: line.add("\c\L") @@ -597,13 +874,13 @@ proc recvLine*(socket: TSocket, line: var TaintedString): bool = setLen(line.string, 0) while true: var c: char - var n = recv(cint(socket), addr(c), 1, 0'i32) + var n = recv(socket, addr(c), 1) if n < 0: return elif n == 0: return true if c == '\r': - n = recv(cint(socket), addr(c), 1, MSG_PEEK) + n = peekChar(socket, c) if n > 0 and c == '\L': - discard recv(cint(socket), addr(c), 1, 0'i32) + discard recv(socket, addr(c), 1) elif n <= 0: return false addNlIfEmpty() return true @@ -624,15 +901,15 @@ proc recvLine*(socket: TSocket, line: var TaintedString, timeout: int): bool = setLen(line.string, 0) while true: var c: char - waitFor() - var n = recv(cint(socket), addr(c), 1, 0'i32) + waitFor(socket, waited, timeout) + var n = recv(socket, addr(c), 1) if n < 0: return elif n == 0: return true if c == '\r': - waitFor() - n = recv(cint(socket), addr(c), 1, MSG_PEEK) + waitFor(socket, waited, timeout) + n = peekChar(socket, c) if n > 0 and c == '\L': - discard recv(cint(socket), addr(c), 1, 0'i32) + discard recv(socket, addr(c), 1) elif n <= 0: return false addNlIfEmpty() return true @@ -651,15 +928,15 @@ proc recvLineAsync*(socket: TSocket, line: var TaintedString): TRecvLineResult = setLen(line.string, 0) while true: var c: char - var n = recv(cint(socket), addr(c), 1, 0'i32) + var n = recv(socket, addr(c), 1) if n < 0: return (if line.len == 0: RecvFail else: RecvPartialLine) elif n == 0: return (if line.len == 0: RecvDisconnected else: RecvPartialLine) if c == '\r': - n = recv(cint(socket), addr(c), 1, MSG_PEEK) + n = peekChar(socket, c) if n > 0 and c == '\L': - discard recv(cint(socket), addr(c), 1, 0'i32) + discard recv(socket, addr(c), 1) elif n <= 0: return (if line.len == 0: RecvFail else: RecvPartialLine) return RecvFullLine @@ -671,7 +948,7 @@ proc recv*(socket: TSocket): TaintedString = ## Socket errors will result in an ``EOS`` error. ## If socket is not a connectionless socket and socket is not connected ## ``""`` will be returned. - const bufSize = 1000 + const bufSize = 4000 result = newStringOfCap(bufSize).TaintedString var pos = 0 while true: @@ -699,9 +976,10 @@ proc recvTimeout*(socket: TSocket, timeout: int): TaintedString = ## overloaded variant to support a ``timeout`` parameter, the ``timeout`` ## parameter specifies the amount of miliseconds to wait for data on the ## socket. - var s = @[socket] - if s.select(timeout) != 1: - raise newException(ETimeout, "Call to recv() timed out.") + if socket.bufLen == 0: + var s = @[socket] + if s.select(timeout) != 1: + raise newException(ETimeout, "Call to recv() timed out.") return socket.recv @@ -718,7 +996,24 @@ proc recvAsync*(socket: TSocket, s: var TaintedString): bool = var pos = 0 while true: var bytesRead = recv(socket, addr(string(s)[pos]), bufSize-1) - if bytesRead == -1: + when defined(ssl): + if socket.isSSL: + if bytesRead <= 0: + var ret = SSLGetError(socket.sslHandle, bytesRead) + case ret + of SSL_ERROR_ZERO_RETURN: + SSLError("TLS/SSL connection failed to initiate, socket closed prematurely.") + of SSL_ERROR_WANT_CONNECT, SSL_ERROR_WANT_ACCEPT: + SSLError("Unexpected error occured.") # This should just not happen. + of SSL_ERROR_WANT_WRITE, SSL_ERROR_WANT_READ: + return false + of SSL_ERROR_WANT_X509_LOOKUP: + SSLError("Function for x509 lookup has been called.") + of SSL_ERROR_SYSCALL, SSL_ERROR_SSL: + SSLError() + else: SSLError("Unknown Error") + + if bytesRead == -1 and not (when defined(ssl): socket.isSSL else: false): when defined(windows): # TODO: Test on Windows var err = WSAGetLastError() @@ -746,19 +1041,46 @@ proc skip*(socket: TSocket) = proc send*(socket: TSocket, data: pointer, size: int): int = ## sends data to a socket. + when defined(ssl): + if socket.isSSL: + return SSLWrite(socket.sslHandle, cast[cstring](data), size) + when defined(windows) or defined(macosx): - result = send(cint(socket), data, size, 0'i32) + result = send(socket.fd, data, size, 0'i32) else: - result = send(cint(socket), data, size, int32(MSG_NOSIGNAL)) + result = send(socket.fd, data, size, int32(MSG_NOSIGNAL)) proc send*(socket: TSocket, data: string) = ## sends data to a socket. - if send(socket, cstring(data), data.len) != data.len: OSError() + if send(socket, cstring(data), data.len) != data.len: + when defined(ssl): + if socket.isSSL: + SSLError() + + OSError() proc sendAsync*(socket: TSocket, data: string): bool = ## sends data to a non-blocking socket. Returns whether ``data`` was sent. result = true var bytesSent = send(socket, cstring(data), data.len) + when defined(ssl): + if socket.isSSL: + if bytesSent <= 0: + let ret = SSLGetError(socket.sslHandle, bytesSent) + case ret + of SSL_ERROR_ZERO_RETURN: + SSLError("TLS/SSL connection failed to initiate, socket closed prematurely.") + of SSL_ERROR_WANT_CONNECT, SSL_ERROR_WANT_ACCEPT: + SSLError("Unexpected error occured.") # This should just not happen. + of SSL_ERROR_WANT_WRITE, SSL_ERROR_WANT_READ: + return false + of SSL_ERROR_WANT_X509_LOOKUP: + SSLError("Function for x509 lookup has been called.") + of SSL_ERROR_SYSCALL, SSL_ERROR_SSL: + SSLError() + else: SSLError("Unknown Error") + else: + return if bytesSent == -1: when defined(windows): var err = WSAGetLastError() @@ -792,15 +1114,15 @@ proc setBlocking*(s: TSocket, blocking: bool) = ## sets blocking mode on socket when defined(Windows): var mode = clong(ord(not blocking)) # 1 for non-blocking, 0 for blocking - if SOCKET_ERROR == ioctlsocket(TWinSocket(s), FIONBIO, addr(mode)): + if SOCKET_ERROR == ioctlsocket(TWinSocket(s.fd), FIONBIO, addr(mode)): OSError() else: # BSD sockets - var x: int = fcntl(cint(s), F_GETFL, 0) + var x: int = fcntl(s.fd, F_GETFL, 0) if x == -1: OSError() else: var mode = if blocking: x and not O_NONBLOCK else: x or O_NONBLOCK - if fcntl(cint(s), F_SETFL, mode) == -1: + if fcntl(s.fd, F_SETFL, mode) == -1: OSError() proc connect*(socket: TSocket, timeout: int, name: string, port = TPort(0), diff --git a/lib/wrappers/openssl.nim b/lib/wrappers/openssl.nim index 5fc6ddd020..b5eed38f3f 100755 --- a/lib/wrappers/openssl.nim +++ b/lib/wrappers/openssl.nim @@ -192,19 +192,44 @@ const BIO_C_DO_STATE_MACHINE = 101 BIO_C_GET_SSL = 110 -proc SSL_library_init*(): cInt{.cdecl, dynlib: DLLSSLName, importc.} +proc SSL_library_init*(): cInt{.cdecl, dynlib: DLLSSLName, importc, discardable.} proc SSL_load_error_strings*(){.cdecl, dynlib: DLLSSLName, importc.} proc ERR_load_BIO_strings*(){.cdecl, dynlib: DLLSSLName, importc.} proc SSLv23_client_method*(): PSSL_METHOD{.cdecl, dynlib: DLLSSLName, importc.} +proc SSLv23_method*(): PSSL_METHOD{.cdecl, dynlib: DLLSSLName, importc.} +proc SSLv2_method*(): PSSL_METHOD{.cdecl, dynlib: DLLSSLName, importc.} +proc SSLv3_method*(): PSSL_METHOD{.cdecl, dynlib: DLLSSLName, importc.} +proc TLSv1_method*(): PSSL_METHOD{.cdecl, dynlib: DLLSSLName, importc.} +proc SSL_new*(context: PSSL_CTX): PSSL{.cdecl, dynlib: DLLSSLName, importc.} +proc SSL_free*(ssl: PSSL){.cdecl, dynlib: DLLSSLName, importc.} proc SSL_CTX_new*(meth: PSSL_METHOD): PSSL_CTX{.cdecl, dynlib: DLLSSLName, importc.} proc SSL_CTX_load_verify_locations*(ctx: PSSL_CTX, CAfile: cstring, CApath: cstring): cInt{.cdecl, dynlib: DLLSSLName, importc.} +proc SSL_CTX_free*(arg0: PSSL_CTX){.cdecl, dynlib: DLLSSLName, importc.} +proc SSL_CTX_set_verify*(s: PSSL_CTX, mode: int, cb: proc (a: int, b: pointer): int){.cdecl, dynlib: DLLSSLName, importc.} proc SSL_get_verify_result*(ssl: PSSL): int{.cdecl, dynlib: DLLSSLName, importc.} +proc SSL_CTX_set_cipher_list*(s: PSSLCTX, ciphers: cstring): cint{.cdecl, dynlib: DLLSSLName, importc.} +proc SSL_CTX_use_certificate_file*(ctx: PSSL_CTX, filename: cstring, typ: cInt): cInt{. + cdecl, dynlib: DLLSSLName, importc.} +proc SSL_CTX_use_PrivateKey_file*(ctx: PSSL_CTX, + filename: cstring, typ: cInt): cInt{.cdecl, dynlib: DLLSSLName, importc.} +proc SSL_CTX_check_private_key*(ctx: PSSL_CTX): cInt{.cdecl, dynlib: DLLSSLName, + importc.} + +proc SSL_set_fd*(ssl: PSSL, fd: cint): cint{.cdecl, dynlib: DLLSSLName, importc.} + +proc SSL_shutdown*(ssl: PSSL): cInt{.cdecl, dynlib: DLLSSLName, importc.} +proc SSL_connect*(ssl: PSSL): cint{.cdecl, dynlib: DLLSSLName, importc.} +proc SSL_read*(ssl: PSSL, buf: pointer, num: int): cint{.cdecl, dynlib: DLLSSLName, importc.} +proc SSL_write*(ssl: PSSL, buf: cstring, num: int): cint{.cdecl, dynlib: DLLSSLName, importc.} +proc SSL_get_error*(s: PSSL, ret_code: cInt): cInt{.cdecl, dynlib: DLLSSLName, importc.} +proc SSL_accept*(ssl: PSSL): cInt{.cdecl, dynlib: DLLSSLName, importc.} + proc BIO_new_ssl_connect*(ctx: PSSL_CTX): PBIO{.cdecl, dynlib: DLLSSLName, importc.} proc BIO_ctrl*(bio: PBIO, cmd: cint, larg: int, arg: cstring): int{.cdecl, @@ -227,16 +252,27 @@ proc BIO_free*(b: PBIO): cInt{.cdecl, dynlib: DLLUtilName, importc.} proc ERR_print_errors_fp*(fp: TFile){.cdecl, dynlib: DLLSSLName, importc.} +proc ERR_error_string*(e: cInt, buf: cstring): cstring{.cdecl, + dynlib: DLLUtilName, importc.} +proc ERR_get_error*(): cInt{.cdecl, dynlib: DLLUtilName, importc.} + +proc OpenSSL_add_all_algorithms*(){.cdecl, dynlib: DLLSSLName, importc: "OPENSSL_add_all_algorithms_conf".} + +proc OPENSSL_config*(configName: cstring){.cdecl, dynlib: DLLSSLName, importc.} + +proc CRYPTO_set_mem_functions(a,b,c: pointer){.cdecl, dynlib: DLLSSLName, importc.} + +proc CRYPTO_malloc_init*() = + CRYPTO_set_mem_functions(alloc, realloc, dealloc) + when True: nil else: - proc SslGetError*(s: PSSL, ret_code: cInt): cInt{.cdecl, dynlib: DLLSSLName, - importc.} proc SslCtxSetCipherList*(arg0: PSSL_CTX, str: cstring): cInt{.cdecl, dynlib: DLLSSLName, importc.} proc SslCtxNew*(meth: PSSL_METHOD): PSSL_CTX{.cdecl, dynlib: DLLSSLName, importc.} - proc SslCtxFree*(arg0: PSSL_CTX){.cdecl, dynlib: DLLSSLName, importc.} + proc SslSetFd*(s: PSSL, fd: cInt): cInt{.cdecl, dynlib: DLLSSLName, importc.} proc SslCtrl*(ssl: PSSL, cmd: cInt, larg: int, parg: Pointer): int{.cdecl, dynlib: DLLSSLName, importc.} @@ -255,19 +291,15 @@ else: dynlib: DLLSSLName, importc.} proc SslCtxUsePrivateKeyASN1*(pk: cInt, ctx: PSSL_CTX, d: cstring, length: int): cInt{.cdecl, dynlib: DLLSSLName, importc.} - proc SslCtxUsePrivateKeyFile*(ctx: PSSL_CTX, - filename: cstring, typ: cInt): cInt{.cdecl, dynlib: DLLSSLName, importc.} + proc SslCtxUseCertificate*(ctx: PSSL_CTX, x: SslPtr): cInt{.cdecl, dynlib: DLLSSLName, importc.} proc SslCtxUseCertificateASN1*(ctx: PSSL_CTX, length: int, d: cstring): cInt{. cdecl, dynlib: DLLSSLName, importc.} - proc SslCtxUseCertificateFile*(ctx: PSSL_CTX, filename: cstring, typ: cInt): cInt{. - cdecl, dynlib: DLLSSLName, importc.} + # function SslCtxUseCertificateChainFile(ctx: PSSL_CTX; const filename: PChar):cInt; proc SslCtxUseCertificateChainFile*(ctx: PSSL_CTX, filename: cstring): cInt{. cdecl, dynlib: DLLSSLName, importc.} - proc SslCtxCheckPrivateKeyFile*(ctx: PSSL_CTX): cInt{.cdecl, dynlib: DLLSSLName, - importc.} proc SslCtxSetDefaultPasswdCb*(ctx: PSSL_CTX, cb: PPasswdCb){.cdecl, dynlib: DLLSSLName, importc.} proc SslCtxSetDefaultPasswdCbUserdata*(ctx: PSSL_CTX, u: SslPtr){.cdecl, @@ -276,10 +308,10 @@ else: proc SslCtxLoadVerifyLocations*(ctx: PSSL_CTX, CAfile: cstring, CApath: cstring): cInt{. cdecl, dynlib: DLLSSLName, importc.} proc SslNew*(ctx: PSSL_CTX): PSSL{.cdecl, dynlib: DLLSSLName, importc.} - proc SslFree*(ssl: PSSL){.cdecl, dynlib: DLLSSLName, importc.} - proc SslAccept*(ssl: PSSL): cInt{.cdecl, dynlib: DLLSSLName, importc.} + + proc SslConnect*(ssl: PSSL): cInt{.cdecl, dynlib: DLLSSLName, importc.} - proc SslShutdown*(ssl: PSSL): cInt{.cdecl, dynlib: DLLSSLName, importc.} + proc SslRead*(ssl: PSSL, buf: SslPtr, num: cInt): cInt{.cdecl, dynlib: DLLSSLName, importc.} proc SslPeek*(ssl: PSSL, buf: SslPtr, num: cInt): cInt{.cdecl, @@ -339,9 +371,7 @@ else: proc EVPcleanup*(){.cdecl, dynlib: DLLUtilName, importc.} # function ErrErrorString(e: cInt; buf: PChar): PChar; proc SSLeayversion*(t: cInt): cstring{.cdecl, dynlib: DLLUtilName, importc.} - proc ErrErrorString*(e: cInt, buf: cstring, length: cInt){.cdecl, - dynlib: DLLUtilName, importc.} - proc ErrGetError*(): cInt{.cdecl, dynlib: DLLUtilName, importc.} + proc ErrClearError*(){.cdecl, dynlib: DLLUtilName, importc.} proc ErrFreeStrings*(){.cdecl, dynlib: DLLUtilName, importc.} proc ErrRemoveState*(pid: cInt){.cdecl, dynlib: DLLUtilName, importc.} diff --git a/web/news.txt b/web/news.txt index 847c36561b..eeff4bf8a7 100755 --- a/web/news.txt +++ b/web/news.txt @@ -51,7 +51,11 @@ Library Additions - Added ``system.||`` for parallel for loop support. - The GC supports (soft) realtime systems via ``GC_setMaxPause`` and ``GC_step`` procs. - +- The sockets module now supports ssl through the OpenSSL library, ``recvLine`` + is now much more efficient thanks to the newly implemented sockets buffering. +- The httpclient module now supports ssl/tls. +- Added ``times.format`` as well as many other utility functions + for managing time. Changes affecting backwards compatibility ----------------------------------------- @@ -77,7 +81,7 @@ Changes affecting backwards compatibility - RTTI and thus the ``marshall`` module don't contain the proper field names of tuples anymore. This had to be changed as the old behaviour never produced consistent results. - +- Deprecated the ``ssl`` module. Compiler Additions ------------------ From 4105a91c4841f836949ce0c4f1d3090b8b83ac2e Mon Sep 17 00:00:00 2001 From: Zahary Karadjov Date: Mon, 4 Jun 2012 01:56:10 +0300 Subject: [PATCH 04/15] fix compilation errors when bootstrapping with C++ --- compiler/ccgexprs.nim | 15 ++++++++++++--- compiler/ccgstmts.nim | 10 +++++----- config/nimrod.cfg | 22 +++++++++++----------- lib/pure/os.nim | 10 +++++++--- lib/pure/osproc.nim | 5 +++-- lib/system.nim | 4 +++- 6 files changed, 41 insertions(+), 25 deletions(-) diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index 7a0face5e5..5b04111b36 100755 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -881,10 +881,15 @@ proc genSeqElemAppend(p: BProc, e: PNode, d: var TLoc) = # seq &= x --> # seq = (typeof seq) incrSeq(&seq->Sup, sizeof(x)); # seq->data[seq->len-1] = x; + let seqAppendPattern = if gCmd != cmdCompileToCpp: + "$1 = ($2) #incrSeq(&($1)->Sup, sizeof($3));$n" + else: + "$1 = ($2) #incrSeq($1, sizeof($3));$n" + var a, b, dest: TLoc InitLocExpr(p, e.sons[1], a) InitLocExpr(p, e.sons[2], b) - appcg(p, cpsStmts, "$1 = ($2) #incrSeq(&($1)->Sup, sizeof($3));$n", [ + appcg(p, cpsStmts, seqAppendPattern, [ rdLoc(a), getTypeDesc(p.module, skipTypes(e.sons[1].typ, abstractVar)), getTypeDesc(p.module, skipTypes(e.sons[2].Typ, abstractVar))]) @@ -1114,8 +1119,12 @@ proc genSetLengthSeq(p: BProc, e: PNode, d: var TLoc) = InitLocExpr(p, e.sons[1], a) InitLocExpr(p, e.sons[2], b) var t = skipTypes(e.sons[1].typ, abstractVar) - appcg(p, cpsStmts, - "$1 = ($3) #setLengthSeq(&($1)->Sup, sizeof($4), $2);$n", [ + let setLenPattern = if gCmd != cmdCompileToCpp: + "$1 = ($3) #setLengthSeq(&($1)->Sup, sizeof($4), $2);$n" + else: + "$1 = ($3) #setLengthSeq($1, sizeof($4), $2);$n" + + appcg(p, cpsStmts, setLenPattern, [ rdLoc(a), rdLoc(b), getTypeDesc(p.module, t), getTypeDesc(p.module, t.sons[0])]) keepAlive(p, a) diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim index 0e85f2c2cd..eb4fd7a345 100755 --- a/compiler/ccgstmts.nim +++ b/compiler/ccgstmts.nim @@ -556,13 +556,14 @@ proc genTryStmtCpp(p: BProc, t: PNode) = i, length, blen: int genLineDir(p, t) exc = getTempName() - if optStackTrace in p.Options: - appcg(p, cpsStmts, "#setFrame((TFrame*)&F);$n") + discard cgsym(p.module, "E_Base") add(p.nestedTryStmts, t) startBlock(p, "try {$n") genStmts(p, t.sons[0]) length = sonsLen(t) endBlock(p, ropecg(p.module, "} catch (NimException& $1) {$n", [exc])) + if optStackTrace in p.Options: + appcg(p, cpsStmts, "#setFrame((TFrame*)&F);$n") inc p.inExceptBlock i = 1 var catchAllPresent = false @@ -581,7 +582,6 @@ proc genTryStmtCpp(p: BProc, t: PNode) = appcg(p.module, orExpr, "#isObj($1.exp->m_type, $2)", [exc, genTypeInfo(p.module, t.sons[i].sons[j].typ)]) - if i > 1: app(p.s(cpsStmts), "else ") appf(p.s(cpsStmts), "if ($1) ", [orExpr]) genSimpleBlock(p, t.sons[i].sons[blen-1]) inc(i) @@ -639,13 +639,13 @@ proc genTryStmt(p: BProc, t: PNode) = appcg(p, cpsLocals, "#TSafePoint $1;$n", [safePoint]) appcg(p, cpsStmts, "#pushSafePoint(&$1);$n" & "$1.status = setjmp($1.context);$n", [safePoint]) - if optStackTrace in p.Options: - appcg(p, cpsStmts, "#setFrame((TFrame*)&F);$n") startBlock(p, "if ($1.status == 0) {$n", [safePoint]) var length = sonsLen(t) add(p.nestedTryStmts, t) genStmts(p, t.sons[0]) endBlock(p, ropecg(p.module, "#popSafePoint();$n } else {$n#popSafePoint();$n")) + if optStackTrace in p.Options: + appcg(p, cpsStmts, "#setFrame((TFrame*)&F);$n") inc p.inExceptBlock var i = 1 while (i < length) and (t.sons[i].kind == nkExceptBranch): diff --git a/config/nimrod.cfg b/config/nimrod.cfg index c98f30f021..fdab40c6c2 100755 --- a/config/nimrod.cfg +++ b/config/nimrod.cfg @@ -62,6 +62,7 @@ hint[LineTooLong]=off @if not bsd: # -fopenmp gcc.options.linker = "-ldl" + gpp.options.linker = "-ldl" clang.options.linker = "-ldl" tcc.options.linker = "-ldl" @else: @@ -83,24 +84,23 @@ icc.options.linker = "-cxxlib" tlsEmulation:on @end @end -gcc.options.debug = "-g3 -O0" @if macosx: tlsEmulation:on - @if not release: - gcc.options.always = "-w -fasm-blocks -O1" - @else: - gcc.options.always = "-w -fasm-blocks" - @end + gcc.options.always = "-w -fasm-blocks" + gpp.options.always = "-w -fasm-blocks" @else: - @if not release: - gcc.options.always = "-w" - @else: - gcc.options.always = "-w" - @end + gcc.options.always = "-w" + gpp.options.always = "-w" @end + gcc.options.speed = "-O3 -fno-strict-aliasing" gcc.options.size = "-Os" +gcc.options.debug = "-g3 -O0" + +gpp.options.speed = "-O3 -fno-strict-aliasing" +gpp.options.size = "-Os" +gpp.options.debug = "-g3 -O0" #passl = "-pg" # Configuration for the LLVM GCC compiler: diff --git a/lib/pure/os.nim b/lib/pure/os.nim index 570bf3e8a4..19a2fc7116 100755 --- a/lib/pure/os.nim +++ b/lib/pure/os.nim @@ -1346,11 +1346,15 @@ when defined(linux) or defined(solaris) or defined(bsd) or defined(aix): setlen(result, len) when defined(macosx): + type + cuint32* {.importc: "unsigned int", nodecl.} = int + ## This is the same as the type ``uint32_t`` in *C*. + # a really hacky solution: since we like to include 2 headers we have to # define two procs which in reality are the same - proc getExecPath1(c: cstring, size: var int32) {. + proc getExecPath1(c: cstring, size: var cuint32) {. importc: "_NSGetExecutablePath", header: "".} - proc getExecPath2(c: cstring, size: var int32): bool {. + proc getExecPath2(c: cstring, size: var cuint32): bool {. importc: "_NSGetExecutablePath", header: "".} proc getAppFilename*(): string {.rtl, extern: "nos$1".} = @@ -1379,7 +1383,7 @@ proc getAppFilename*(): string {.rtl, extern: "nos$1".} = elif defined(bsd): result = getApplAux("/proc/" & $getpid() & "/file") elif defined(macosx): - var size: int32 + var size: cuint32 getExecPath1(nil, size) result = newString(int(size)) if getExecPath2(result, size): diff --git a/lib/pure/osproc.nim b/lib/pure/osproc.nim index 2807743fe9..808c0735e9 100755 --- a/lib/pure/osproc.nim +++ b/lib/pure/osproc.nim @@ -123,7 +123,7 @@ when defined(macosx) or defined(bsd): HW_AVAILCPU = 25 HW_NCPU = 3 proc sysctl(x: ptr array[0..3, cint], y: cint, z: pointer, - a: var int, b: pointer, c: int): cint {. + a: var csize, b: pointer, c: int): cint {. importc: "sysctl", header: "".} proc countProcessors*(): int {.rtl, extern: "nosp$1".} = @@ -135,7 +135,8 @@ proc countProcessors*(): int {.rtl, extern: "nosp$1".} = elif defined(macosx) or defined(bsd): var mib: array[0..3, cint] - len, numCPU: int + numCPU: int + len: csize mib[0] = CTL_HW mib[1] = HW_AVAILCPU len = sizeof(numCPU) diff --git a/lib/system.nim b/lib/system.nim index c8166bc10b..5d01c5a44d 100755 --- a/lib/system.nim +++ b/lib/system.nim @@ -935,6 +935,8 @@ type # these work for most platforms: ## This is the same as the type ``short`` in *C*. cint* {.importc: "int", nodecl.} = int32 ## This is the same as the type ``int`` in *C*. + csize* {.importc: "size_t", nodecl.} = int + ## This is the same as the type ``size_t`` in *C*. clong* {.importc: "long", nodecl.} = int ## This is the same as the type ``long`` in *C*. clonglong* {.importc: "long long", nodecl.} = int64 @@ -951,7 +953,7 @@ type # these work for most platforms: ## This is binary compatible to the type ``char**`` in *C*. The array's ## high value is large enough to disable bounds checking in practice. ## Use `cstringArrayToSeq` to convert it into a ``seq[string]``. - + PFloat32* = ptr Float32 ## an alias for ``ptr float32`` PFloat64* = ptr Float64 ## an alias for ``ptr float64`` PInt64* = ptr Int64 ## an alias for ``ptr int64`` From 41a9a941ab627acb413f067a38406d7908dbd364 Mon Sep 17 00:00:00 2001 From: Dominik Picheta Date: Mon, 4 Jun 2012 19:24:13 +0100 Subject: [PATCH 05/15] Fixed math.round, added math.ceil and fixed times.format. --- lib/nimbase.h | 2 +- lib/pure/math.nim | 2 ++ lib/pure/times.nim | 4 ++-- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/nimbase.h b/lib/nimbase.h index 61e7da75e1..a73933a408 100755 --- a/lib/nimbase.h +++ b/lib/nimbase.h @@ -192,7 +192,7 @@ __clang__ ** long int lrint (double x); */ -#if defined(__LCC__) || (defined(__GNUC__) && defined(WIN32)) +#if defined(__LCC__) || (defined(__GNUC__)) /* Linux' GCC does not seem to have these. Why? */ # define HAVE_LRINT # define HAVE_LRINTF diff --git a/lib/pure/math.nim b/lib/pure/math.nim index 6a1fc00634..6f3135d133 100755 --- a/lib/pure/math.nim +++ b/lib/pure/math.nim @@ -186,10 +186,12 @@ when not defined(ECMAScript): proc trunc*(x: float): float {.importc: "trunc", nodecl.} proc floor*(x: float): float {.importc: "floor", nodecl.} + proc ceil*(x: float): float {.importc: "ceil", nodecl.} else: proc mathrandom(): float {.importc: "Math.random", nodecl.} proc floor*(x: float): float {.importc: "Math.floor", nodecl.} + proc ceil*(x: float): float {.importc: "Math.ceil", nodecl.} proc random*(max: int): int = return int(floor(mathrandom() * float(max))) proc randomize*() = nil diff --git a/lib/pure/times.nim b/lib/pure/times.nim index 4cb873b1ca..eded16d21d 100755 --- a/lib/pure/times.nim +++ b/lib/pure/times.nim @@ -557,9 +557,9 @@ proc format*(info: TTimeInfo, f: string): string = result.add("0") result.add($info.monthday) of "ddd": - result.add(($info.monthday)[0 .. 2]) + result.add(($info.weekday)[0 .. 2]) of "dddd": - result.add($info.monthday) + result.add($info.weekday) of "h": result.add($(info.hour - 12)) of "hh": From d10b524c9a52c1d13ca175ac9781c85fad22b0f7 Mon Sep 17 00:00:00 2001 From: Zahary Karadjov Date: Wed, 6 Jun 2012 18:34:35 +0300 Subject: [PATCH 06/15] generate default destructors --- compiler/semdata.nim | 6 ++- compiler/semstmts.nim | 106 ++++++++++++++++++++++++++++++++++++++---- compiler/types.nim | 7 --- lib/system/assign.nim | 4 ++ 4 files changed, 107 insertions(+), 16 deletions(-) diff --git a/compiler/semdata.nim b/compiler/semdata.nim index 81e45f71c9..c28c8c7a17 100755 --- a/compiler/semdata.nim +++ b/compiler/semdata.nim @@ -212,7 +212,11 @@ proc markUsed*(n: PNode, s: PSym) = if {sfDeprecated, sfError} * s.flags != {}: if sfDeprecated in s.flags: Message(n.info, warnDeprecated, s.name.s) if sfError in s.flags: LocalError(n.info, errWrongSymbolX, s.name.s) - + +proc useSym*(sym: PSym): PNode = + result = newSymNode(sym) + markUsed(result, sym) + proc illFormedAst*(n: PNode) = GlobalError(n.info, errIllFormedAstX, renderTree(n, {renderNoComments})) diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 82f43e7875..3d00d495d0 100755 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -681,7 +681,9 @@ proc semLambda(c: PContext, n: PNode): PNode = closeScope(c.tab) # close scope for parameters popOwner() result.typ = s.typ - + +proc instantiateDestructor*(c: PContext, typ: PType): bool + proc semProcAux(c: PContext, n: PNode, kind: TSymKind, validPragmas: TSpecialWords): PNode = result = n @@ -743,6 +745,19 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind, popOwner() pushOwner(s) s.options = gOptions + if result.sons[namePos].sym.name.id == ord(wDestroy) and s.typ.sons.len == 2: + let t = s.typ.sons[1].skipTypes({tyVar}) + t.destructor = s + # automatically insert calls to base classes' destructors + if n.sons[bodyPos].kind != nkEmpty: + for i in countup(0, t.sonsLen - 1): + # when inheriting directly from object + # there will be a single nil son + if t.sons[i] == nil: continue + if instantiateDestructor(c, t.sons[i]): + n.sons[bodyPos].addSon(newNode(nkCall, t.sym.info, @[ + useSym(t.sons[i].destructor), + n.sons[paramsPos][1][0]])) if n.sons[bodyPos].kind != nkEmpty: # for DLL generation it is annoying to check for sfImportc! if sfBorrow in s.flags: @@ -772,10 +787,6 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind, incl(s.flags, sfForward) elif sfBorrow in s.flags: semBorrow(c, n, s) sideEffectsCheck(c, s) - if result.sons[namePos].sym.name.id == ord(wDestroy): - if s.typ.sons.len == 2: - let typ = s.typ.sons[1].skipTypes({tyVar}) - typ.destructor = s if s.typ.callConv == ccClosure and s.owner.kind == skModule: localError(s.info, errXCannotBeClosure, s.name.s) closeScope(c.tab) # close scope for parameters @@ -864,6 +875,85 @@ proc semStaticStmt(c: PContext, n: PNode): PNode = if result.isNil: LocalError(n.info, errCannotInterpretNodeX, renderTree(n)) +# special marker that indicates that we've already tried +# to generate a destructor for some type, but it turned out +# to be trivial +var DestructorIsTrivial: PSym +new(DestructorIsTrivial) + +var + destructorParam = getIdent"this_" + rangeDestructorProc: PSym + +proc generateDestructor(c: PContext, t: PType): PNode = + ## generate a destructor for a user-defined object ot tuple type + ## returns nil if the destructor turns out to be trivial + + template addLine(e: expr): stmt = + if result == nil: result = newNode(nkStmtList) + result.addSon(e) + + internalAssert t.n.kind == nkRecList + # call the destructods of all fields + for s in countup(0, t.n.sons.len - 1): + internalAssert t.n.sons[s].kind == nkSym + let field = t.n.sons[s].sym + if instantiateDestructor(c, field.typ): + addLine(newNode(nkCall, field.info, @[ + useSym(field.typ.destructor), + newNode(nkDotExpr, field.info, @[ + newIdentNode(destructorParam, t.sym.info), + useSym(field) + ]) + ])) + # base classes' destructors will be automatically called by + # semProcAux for both auto-generated and user-defined destructors + +proc instantiateDestructor*(c: PContext, typ: PType): bool = + # returns true if the type already had a user-defined + # destructor or if the compiler generated a default + # member-wise one + var t = skipTypes(typ, {tyConst, tyMutable}) + + if t.destructor != nil: + return t.destructor != DestructorIsTrivial + + case t.kind + of tySequence, tyArray, tyArrayConstr, tyOpenArray: + if instantiateDestructor(c, t.sons[0]): + if rangeDestructorProc == nil: + rangeDestructorProc = SymtabGet(c.tab, getIdent"nimDestroyRange") + t.destructor = rangeDestructorProc + return true + else: + return false + of tyTuple, tyObject: + let generated = generateDestructor(c, t) + if generated != nil: + internalAssert t.sym != nil + var i = t.sym.info + let fullDef = newNode(nkProcDef, i, @[ + newIdentNode(getIdent"destroy", i), + emptyNode, + newNode(nkFormalParams, i, @[ + emptyNode, + newNode(nkIdentDefs, i, @[ + newIdentNode(destructorParam, i), + useSym(t.sym), + emptyNode]), + ]), + emptyNode, + generated + ]) + discard semProc(c, fullDef) + internalAssert t.destructor != nil + return true + else: + t.destructor = DestructorIsTrivial + return false + else: + return false + proc insertDestructors(c: PContext, varSection: PNode): tuple[outer: PNode, inner: PNode] = # Accepts a var or let section. @@ -889,7 +979,7 @@ proc insertDestructors(c: PContext, varSection: PNode): varTyp = varId.sym.typ info = varId.info - if varTyp != nil and instantiateDestructor(varTyp): + if varTyp != nil and instantiateDestructor(c, varTyp): var tryStmt = newNodeI(nkTryStmt, info) if j < totalVars - 1: @@ -910,8 +1000,8 @@ proc insertDestructors(c: PContext, varSection: PNode): tryStmt.addSon( newNode(nkFinally, info, @[ semStmt(c, newNode(nkCall, info, @[ - semSym(c, varId, varTyp.destructor, {}), - semSym(c, varId, varId.sym, {})]))])) + useSym(varTyp.destructor), + useSym(varId.sym)]))])) result.outer = newNodeI(nkStmtList, info) varSection.sons.setLen(j+1) diff --git a/compiler/types.nim b/compiler/types.nim index 2f201b9de6..ecc250a5ac 100755 --- a/compiler/types.nim +++ b/compiler/types.nim @@ -1062,10 +1062,3 @@ proc getSize(typ: PType): biggestInt = result = computeSize(typ) if result < 0: InternalError("getSize(" & $typ.kind & ')') -proc instantiateDestructor*(typ: PType): bool = - # return true if the type already had a user-defined - # destructor or if the compiler generated a default - # member-wise one - if typ.destructor != nil: return true - return false - diff --git a/lib/system/assign.nim b/lib/system/assign.nim index 59c44a6cce..f29dc547c7 100755 --- a/lib/system/assign.nim +++ b/lib/system/assign.nim @@ -139,6 +139,10 @@ proc objectInit(dest: Pointer, typ: PNimType) = # ---------------------- assign zero ----------------------------------------- +proc nimDestroyRange*[T](r: T) = + # internal proc used for destroying sequences and arrays + for i in countup(0, r.len - 1): destroy(r[i]) + proc genericReset(dest: Pointer, mt: PNimType) {.compilerProc.} proc genericResetAux(dest: Pointer, n: ptr TNimNode) = var d = cast[TAddress](dest) From db8dbab766e4b6b0afb69951f821e461b5424c6c Mon Sep 17 00:00:00 2001 From: Zahary Karadjov Date: Wed, 6 Jun 2012 20:38:57 +0300 Subject: [PATCH 07/15] fix bootstrapping on POSIX platforms --- compiler/semstmts.nim | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 3d00d495d0..531f3ac5dc 100755 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -893,7 +893,11 @@ proc generateDestructor(c: PContext, t: PType): PNode = if result == nil: result = newNode(nkStmtList) result.addSon(e) + # XXX: This may be true for some C-imported types such as + # Tposix_spawnattr + if t.n == nil or t.n.sons == nil: return internalAssert t.n.kind == nkRecList + # call the destructods of all fields for s in countup(0, t.n.sons.len - 1): internalAssert t.n.sons[s].kind == nkSym From 985113ee2a642f66e97e3f189bd2bf9eaecfe12f Mon Sep 17 00:00:00 2001 From: Zahary Karadjov Date: Wed, 6 Jun 2012 21:12:14 +0300 Subject: [PATCH 08/15] fix AST debug printing when line directives are enabled --- compiler/astalgo.nim | 60 ++++++++++++++++++++++---------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/compiler/astalgo.nim b/compiler/astalgo.nim index 8616425942..ebcab436e4 100755 --- a/compiler/astalgo.nim +++ b/compiler/astalgo.nim @@ -274,10 +274,10 @@ proc strTableToYaml(n: TStrTable, marker: var TIntSet, indent: int, for i in countup(0, high(n.data)): if n.data[i] != nil: if mycount > 0: app(result, ",") - appf(result, "$n$1$2", + appf(result, "$N$1$2", [istr, symToYamlAux(n.data[i], marker, indent + 2, maxRecDepth - 1)]) inc(mycount) - if mycount > 0: appf(result, "$n$1", [spaces(indent)]) + if mycount > 0: appf(result, "$N$1", [spaces(indent)]) app(result, "]") assert(mycount == n.counter) @@ -288,9 +288,9 @@ proc ropeConstr(indent: int, c: openarray[PRope]): PRope = var i = 0 while i <= high(c): if i > 0: app(result, ",") - appf(result, "$n$1\"$2\": $3", [istr, c[i], c[i + 1]]) + appf(result, "$N$1\"$2\": $3", [istr, c[i], c[i + 1]]) inc(i, 2) - appf(result, "$n$1}", [spaces(indent)]) + appf(result, "$N$1}", [spaces(indent)]) proc symToYamlAux(n: PSym, marker: var TIntSet, indent: int, maxRecDepth: int): PRope = @@ -325,9 +325,9 @@ proc typeToYamlAux(n: PType, marker: var TIntSet, indent: int, result = toRope("[") for i in countup(0, sonsLen(n) - 1): if i > 0: app(result, ",") - appf(result, "$n$1$2", [spaces(indent + 4), typeToYamlAux(n.sons[i], + appf(result, "$N$1$2", [spaces(indent + 4), typeToYamlAux(n.sons[i], marker, indent + 4, maxRecDepth - 1)]) - appf(result, "$n$1]", [spaces(indent + 2)]) + appf(result, "$N$1]", [spaces(indent + 2)]) else: result = toRope("null") result = ropeConstr(indent, [toRope("kind"), @@ -347,36 +347,36 @@ proc treeToYamlAux(n: PNode, marker: var TIntSet, indent: int, result = toRope("null") else: var istr = spaces(indent + 2) - result = ropef("{$n$1\"kind\": $2", [istr, makeYamlString($n.kind)]) + result = ropef("{$N$1\"kind\": $2", [istr, makeYamlString($n.kind)]) if maxRecDepth != 0: - appf(result, ",$n$1\"info\": $2", [istr, lineInfoToStr(n.info)]) + appf(result, ",$N$1\"info\": $2", [istr, lineInfoToStr(n.info)]) case n.kind of nkCharLit..nkInt64Lit: - appf(result, ",$n$1\"intVal\": $2", [istr, toRope(n.intVal)]) + appf(result, ",$N$1\"intVal\": $2", [istr, toRope(n.intVal)]) of nkFloatLit, nkFloat32Lit, nkFloat64Lit: - appf(result, ",$n$1\"floatVal\": $2", + appf(result, ",$N$1\"floatVal\": $2", [istr, toRope(n.floatVal.ToStrMaxPrecision)]) of nkStrLit..nkTripleStrLit: - appf(result, ",$n$1\"strVal\": $2", [istr, makeYamlString(n.strVal)]) + appf(result, ",$N$1\"strVal\": $2", [istr, makeYamlString(n.strVal)]) of nkSym: - appf(result, ",$n$1\"sym\": $2", + appf(result, ",$N$1\"sym\": $2", [istr, symToYamlAux(n.sym, marker, indent + 2, maxRecDepth)]) of nkIdent: if n.ident != nil: - appf(result, ",$n$1\"ident\": $2", [istr, makeYamlString(n.ident.s)]) + appf(result, ",$N$1\"ident\": $2", [istr, makeYamlString(n.ident.s)]) else: - appf(result, ",$n$1\"ident\": null", [istr]) + appf(result, ",$N$1\"ident\": null", [istr]) else: if sonsLen(n) > 0: - appf(result, ",$n$1\"sons\": [", [istr]) + appf(result, ",$N$1\"sons\": [", [istr]) for i in countup(0, sonsLen(n) - 1): if i > 0: app(result, ",") - appf(result, "$n$1$2", [spaces(indent + 4), treeToYamlAux(n.sons[i], + appf(result, "$N$1$2", [spaces(indent + 4), treeToYamlAux(n.sons[i], marker, indent + 4, maxRecDepth - 1)]) - appf(result, "$n$1]", [istr]) - appf(result, ",$n$1\"typ\": $2", + appf(result, "$N$1]", [istr]) + appf(result, ",$N$1\"typ\": $2", [istr, typeToYamlAux(n.typ, marker, indent + 2, maxRecDepth)]) - appf(result, "$n$1}", [spaces(indent)]) + appf(result, "$N$1}", [spaces(indent)]) proc treeToYaml(n: PNode, indent: int = 0, maxRecDepth: int = - 1): PRope = var marker = InitIntSet() @@ -413,34 +413,34 @@ proc debugTree(n: PNode, indent: int, maxRecDepth: int): PRope = result = toRope("null") else: var istr = spaces(indent + 2) - result = ropef("{$n$1\"kind\": $2", + result = ropef("{$N$1\"kind\": $2", [istr, makeYamlString($n.kind)]) if maxRecDepth != 0: case n.kind of nkCharLit..nkInt64Lit: - appf(result, ",$n$1\"intVal\": $2", [istr, toRope(n.intVal)]) + appf(result, ",$N$1\"intVal\": $2", [istr, toRope(n.intVal)]) of nkFloatLit, nkFloat32Lit, nkFloat64Lit: - appf(result, ",$n$1\"floatVal\": $2", + appf(result, ",$N$1\"floatVal\": $2", [istr, toRope(n.floatVal.ToStrMaxPrecision)]) of nkStrLit..nkTripleStrLit: - appf(result, ",$n$1\"strVal\": $2", [istr, makeYamlString(n.strVal)]) + appf(result, ",$N$1\"strVal\": $2", [istr, makeYamlString(n.strVal)]) of nkSym: - appf(result, ",$n$1\"sym\": $2_$3", + appf(result, ",$N$1\"sym\": $2_$3", [istr, toRope(n.sym.name.s), toRope(n.sym.id)]) of nkIdent: if n.ident != nil: - appf(result, ",$n$1\"ident\": $2", [istr, makeYamlString(n.ident.s)]) + appf(result, ",$N$1\"ident\": $2", [istr, makeYamlString(n.ident.s)]) else: - appf(result, ",$n$1\"ident\": null", [istr]) + appf(result, ",$N$1\"ident\": null", [istr]) else: if sonsLen(n) > 0: - appf(result, ",$n$1\"sons\": [", [istr]) + appf(result, ",$N$1\"sons\": [", [istr]) for i in countup(0, sonsLen(n) - 1): if i > 0: app(result, ",") - appf(result, "$n$1$2", [spaces(indent + 4), debugTree(n.sons[i], + appf(result, "$N$1$2", [spaces(indent + 4), debugTree(n.sons[i], indent + 4, maxRecDepth - 1)]) - appf(result, "$n$1]", [istr]) - appf(result, "$n$1}", [spaces(indent)]) + appf(result, "$N$1]", [istr]) + appf(result, "$N$1}", [spaces(indent)]) proc debug(n: PSym) = #writeln(stdout, ropeToStr(symToYaml(n, 0, 1))) From 65970efd97483a11a6f63f426ec833098339999f Mon Sep 17 00:00:00 2001 From: Zahary Karadjov Date: Wed, 6 Jun 2012 23:00:33 +0300 Subject: [PATCH 09/15] destructors for case values --- compiler/ast.nim | 1 + compiler/semstmts.nim | 77 ++++++++++++++++++++++++++++++++++--------- compiler/semtypes.nim | 4 ++- 3 files changed, 65 insertions(+), 17 deletions(-) diff --git a/compiler/ast.nim b/compiler/ast.nim index d9ec704501..2f94581696 100755 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -885,6 +885,7 @@ proc assignType(dest, src: PType) = dest.size = src.size dest.align = src.align dest.containerID = src.containerID + dest.destructor = src.destructor # this fixes 'type TLock = TSysLock': if src.sym != nil: if dest.sym != nil: diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 531f3ac5dc..ddfc2391f2 100755 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -875,16 +875,58 @@ proc semStaticStmt(c: PContext, n: PNode): PNode = if result.isNil: LocalError(n.info, errCannotInterpretNodeX, renderTree(n)) -# special marker that indicates that we've already tried -# to generate a destructor for some type, but it turned out -# to be trivial -var DestructorIsTrivial: PSym +# special marker values that indicates that we are +# 1) AnalyzingDestructor: currenlty analyzing the type for destructor +# generation (needed for recursive types) +# 2) DestructorIsTrivial: completed the anlysis before and determined +# that the type has a trivial destructor +var AnalyzingDestructor, DestructorIsTrivial: PSym +new(AnalyzingDestructor) new(DestructorIsTrivial) var destructorParam = getIdent"this_" rangeDestructorProc: PSym +proc destroyField(c: PContext, field: PSym, holder: PNode): PNode = + if instantiateDestructor(c, field.typ): + result = newNode(nkCall, field.info, @[ + useSym(field.typ.destructor), + newNode(nkDotExpr, field.info, @[holder, useSym(field)])]) + +proc destroyCase(c: PContext, n: PNode, holder: PNode): PNode = + var nonTrivialFields = 0 + result = newNode(nkCaseStmt, n.info, @[]) + # case x.kind + result.addSon(newNode(nkDotExpr, n.info, @[holder, n.sons[0]])) + for i in countup(1, n.len - 1): + # of A, B: + var caseBranch = newNode(n[i].kind, n[i].info, n[i].sons[0 .. -2]) + let recList = n[i].lastSon + var destroyRecList = newNode(nkStmtList, n[i].info, @[]) + template addField(f: expr): stmt = + let stmt = destroyField(c, f, holder) + if stmt != nil: + destroyRecList.addSon(stmt) + inc nonTrivialFields + + case recList.kind + of nkSym: + addField(recList.sym) + of nkRecList: + for j in countup(0, recList.len - 1): + addField(recList[j].sym) + else: + internalAssert false + + caseBranch.addSon(destroyRecList) + result.addSon(caseBranch) + # maybe no fields were destroyed? + if nonTrivialFields == 0: + result = nil + else: + debug result + proc generateDestructor(c: PContext, t: PType): PNode = ## generate a destructor for a user-defined object ot tuple type ## returns nil if the destructor turns out to be trivial @@ -897,19 +939,19 @@ proc generateDestructor(c: PContext, t: PType): PNode = # Tposix_spawnattr if t.n == nil or t.n.sons == nil: return internalAssert t.n.kind == nkRecList - + let destructedObj = newIdentNode(destructorParam, UnknownLineInfo()) # call the destructods of all fields for s in countup(0, t.n.sons.len - 1): - internalAssert t.n.sons[s].kind == nkSym - let field = t.n.sons[s].sym - if instantiateDestructor(c, field.typ): - addLine(newNode(nkCall, field.info, @[ - useSym(field.typ.destructor), - newNode(nkDotExpr, field.info, @[ - newIdentNode(destructorParam, t.sym.info), - useSym(field) - ]) - ])) + case t.n.sons[s].kind + of nkRecCase: + let stmt = destroyCase(c, t.n.sons[s], destructedObj) + if stmt != nil: addLine(stmt) + of nkSym: + let stmt = destroyField(c, t.n.sons[s].sym, destructedObj) + if stmt != nil: addLine(stmt) + else: + internalAssert false + # base classes' destructors will be automatically called by # semProcAux for both auto-generated and user-defined destructors @@ -920,7 +962,9 @@ proc instantiateDestructor*(c: PContext, typ: PType): bool = var t = skipTypes(typ, {tyConst, tyMutable}) if t.destructor != nil: - return t.destructor != DestructorIsTrivial + # XXX: This is not entirely correct for recursive types, but we need + # it temporarily to hide the "destroy is alrady defined" problem + return t.destructor notin [AnalyzingDestructor, DestructorIsTrivial] case t.kind of tySequence, tyArray, tyArrayConstr, tyOpenArray: @@ -932,6 +976,7 @@ proc instantiateDestructor*(c: PContext, typ: PType): bool = else: return false of tyTuple, tyObject: + t.destructor = AnalyzingDestructor let generated = generateDestructor(c, t) if generated != nil: internalAssert t.sym != nil diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index f9420d4108..19f37f4050 100755 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -306,7 +306,9 @@ proc semCaseBranch(c: PContext, t, branch: PNode, branchIndex: int, covered: var biggestInt) = for i in countup(0, sonsLen(branch) - 2): var b = branch.sons[i] - if isRange(b): + if b.kind == nkRange: + branch.sons[i] = b + elif isRange(b): branch.sons[i] = semCaseBranchRange(c, t, b, covered) else: var r = semConstExpr(c, b) From ce933c90a48ddf0331016edbc684ba6937412e22 Mon Sep 17 00:00:00 2001 From: Zahary Karadjov Date: Thu, 7 Jun 2012 03:32:40 +0300 Subject: [PATCH 10/15] destructor pragma --- compiler/ast.nim | 1 + compiler/pragmas.nim | 7 ++++++- compiler/semstmts.nim | 12 ++++++------ compiler/wordrecg.nim | 4 ++-- 4 files changed, 15 insertions(+), 9 deletions(-) diff --git a/compiler/ast.nim b/compiler/ast.nim index 2f94581696..0c25b24a17 100755 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -237,6 +237,7 @@ type sfNamedParamCall, # symbol needs named parameter call syntax in target # language; for interfacing with Objective C sfDiscardable # returned value may be discarded implicitely + sfDestructor # proc is destructor TSymFlags* = set[TSymFlag] diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim index fe8bff34b5..96ae9d701f 100755 --- a/compiler/pragmas.nim +++ b/compiler/pragmas.nim @@ -23,7 +23,7 @@ const wMagic, wNosideEffect, wSideEffect, wNoreturn, wDynLib, wHeader, wCompilerProc, wProcVar, wDeprecated, wVarargs, wCompileTime, wMerge, wBorrow, wExtern, wImportCompilerProc, wThread, wImportCpp, wImportObjC, - wNoStackFrame, wError, wDiscardable, wNoInit} + wNoStackFrame, wError, wDiscardable, wNoInit, wDestructor} converterPragmas* = procPragmas methodPragmas* = procPragmas templatePragmas* = {wImmediate, wDeprecated, wError} @@ -508,6 +508,11 @@ proc pragma(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords) = incl(sym.loc.Flags, lfNoDecl) # implies nodecl, because otherwise header would not make sense if sym.loc.r == nil: sym.loc.r = toRope(sym.name.s) + of wDestructor: + if sym.typ.sons.len == 2: + sym.flags.incl sfDestructor + else: + invalidPragma(it) of wNosideeffect: noVal(it) incl(sym.flags, sfNoSideEffect) diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index ddfc2391f2..27d7d405ba 100755 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -745,7 +745,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind, popOwner() pushOwner(s) s.options = gOptions - if result.sons[namePos].sym.name.id == ord(wDestroy) and s.typ.sons.len == 2: + if sfDestructor in s.flags: let t = s.typ.sons[1].skipTypes({tyVar}) t.destructor = s # automatically insert calls to base classes' destructors @@ -885,7 +885,9 @@ new(AnalyzingDestructor) new(DestructorIsTrivial) var + destructorName = getIdent"destroy_" destructorParam = getIdent"this_" + destructorPragma = newIdentNode(getIdent"destructor", UnknownLineInfo()) rangeDestructorProc: PSym proc destroyField(c: PContext, field: PSym, holder: PNode): PNode = @@ -924,9 +926,7 @@ proc destroyCase(c: PContext, n: PNode, holder: PNode): PNode = # maybe no fields were destroyed? if nonTrivialFields == 0: result = nil - else: - debug result - + proc generateDestructor(c: PContext, t: PType): PNode = ## generate a destructor for a user-defined object ot tuple type ## returns nil if the destructor turns out to be trivial @@ -982,7 +982,7 @@ proc instantiateDestructor*(c: PContext, typ: PType): bool = internalAssert t.sym != nil var i = t.sym.info let fullDef = newNode(nkProcDef, i, @[ - newIdentNode(getIdent"destroy", i), + newIdentNode(destructorName, i), emptyNode, newNode(nkFormalParams, i, @[ emptyNode, @@ -991,7 +991,7 @@ proc instantiateDestructor*(c: PContext, typ: PType): bool = useSym(t.sym), emptyNode]), ]), - emptyNode, + newNode(nkPragma, i, @[destructorPragma]), generated ]) discard semProc(c, fullDef) diff --git a/compiler/wordrecg.nim b/compiler/wordrecg.nim index af482966bf..cec76c9988 100755 --- a/compiler/wordrecg.nim +++ b/compiler/wordrecg.nim @@ -39,7 +39,7 @@ type wDestroy, - wImmediate, wImportCpp, wImportObjC, + wImmediate, wDestructor, wImportCpp, wImportObjC, wImportCompilerProc, wImportc, wExportc, wIncompleteStruct, wAlign, wNodecl, wPure, wSideeffect, wHeader, @@ -117,7 +117,7 @@ const "destroy", - "immediate", "importcpp", "importobjc", + "immediate", "destructor", "importcpp", "importobjc", "importcompilerproc", "importc", "exportc", "incompletestruct", "align", "nodecl", "pure", "sideeffect", "header", "nosideeffect", "noreturn", "merge", "lib", "dynlib", From 7364d725482cf27794fd42b13751348cec5d1a1e Mon Sep 17 00:00:00 2001 From: Dominik Picheta Date: Sat, 9 Jun 2012 14:24:41 +0100 Subject: [PATCH 11/15] Fixed httpclient bugs, fixed socket bugs and fixed sockets for windows. --- lib/pure/httpclient.nim | 140 ++++++++++++++++++++-------------------- lib/pure/sockets.nim | 70 +++++++++++++------- 2 files changed, 117 insertions(+), 93 deletions(-) diff --git a/lib/pure/httpclient.nim b/lib/pure/httpclient.nim index c4dbd85091..184bca867b 100755 --- a/lib/pure/httpclient.nim +++ b/lib/pure/httpclient.nim @@ -87,10 +87,11 @@ proc charAt(d: var string, i: var int, s: TSocket): char {.inline.} = i = 0 result = d[i] -proc parseChunks(d: var string, start: int, s: TSocket): string = +proc parseChunks(s: TSocket): string = # get chunks: - var i = start + var i = 0 result = "" + var d = s.recv().string while true: var chunkSize = 0 var digitFound = false @@ -136,88 +137,87 @@ proc parseChunks(d: var string, start: int, s: TSocket): string = # skip trailing CR-LF: while charAt(d, i, s) in {'\C', '\L'}: inc(i) -proc parseBody(d: var string, start: int, s: TSocket, +proc parseBody(s: TSocket, headers: PStringTable): string = + result = "" if headers["Transfer-Encoding"] == "chunked": - result = parseChunks(d, start, s) + result = parseChunks(s) else: - result = substr(d, start) # -REGION- Content-Length # (http://tools.ietf.org/html/rfc2616#section-4.4) NR.3 var contentLengthHeader = headers["Content-Length"] if contentLengthHeader != "": var length = contentLengthHeader.parseint() - while result.len() < length: result.add(s.recv.string) + result = newString(length) + var received = 0 + while true: + if received >= length: break + let r = s.recv(addr(result[received]), length-received) + if r == 0: break + received += r + if received != length: + httpError("Got invalid content length. Expected: " & $length & + " got: " & $received) else: # (http://tools.ietf.org/html/rfc2616#section-4.4) NR.4 TODO # -REGION- Connection: Close # (http://tools.ietf.org/html/rfc2616#section-4.4) NR.5 if headers["Connection"] == "close": + var buf = "" while True: - var moreData = recv(s).string - if moreData.len == 0: break - result.add(moreData) + buf = newString(4000) + let r = s.recv(addr(buf[0]), 4000) + if r == 0: break + buf.setLen(r) + result.add(buf) -proc parseResponse(s: TSocket): TResponse = - var d = s.recv.string # Warning: without a Connection: Close header this will not work. - var i = 0 - - # Parse the version - # Parses the first line of the headers - # ``HTTP/1.1`` 200 OK - var L = skipIgnoreCase(d, "HTTP/1.1", i) - if L > 0: - result.version = "1.1" - inc(i, L) - else: - L = skipIgnoreCase(d, "HTTP/1.0", i) - if L > 0: - result.version = "1.0" - inc(i, L) - else: - httpError("invalid HTTP header") - L = skipWhiteSpace(d, i) - if L <= 0: httpError("invalid HTTP header") - inc(i, L) - - result.status = "" - while d[i] notin {'\C', '\L', '\0'}: - result.status.add(d[i]) - inc(i) - if d[i] == '\C': inc(i) - if d[i] == '\L': inc(i) - else: httpError("invalid HTTP header, CR-LF expected") - - # Parse the headers - # Everything after the first line leading up to the body - # htype: hvalue +proc parseResponse(s: TSocket, getBody: bool): TResponse = + var parsedStatus = false + var linei = 0 + var fullyRead = false + var line = "" result.headers = newStringTable(modeCaseInsensitive) - while true: - var key = "" - while d[i] != ':': - if d[i] == '\0': httpError("invalid HTTP header, ':' expected") - key.add(d[i]) - inc(i) - inc(i) # skip ':' - if d[i] == ' ': inc(i) # skip if the character is a space - var val = "" - while d[i] notin {'\C', '\L', '\0'}: - val.add(d[i]) - inc(i) - - result.headers[key] = val - - if d[i] == '\C': inc(i) - if d[i] == '\L': inc(i) - else: httpError("invalid HTTP header, CR-LF expected") - - if d[i] == '\C': inc(i) - if d[i] == '\L': - inc(i) - break - - result.body = parseBody(d, i, s, result.headers) + while True: + line = "" + linei = 0 + if s.recvLine(line): + if line == "": break # We've been disconnected. + if line == "\c\L": + fullyRead = true + break + if not parsedStatus: + # Parse HTTP version info and status code. + var le = skipIgnoreCase(line, "HTTP/", linei) + if le <= 0: httpError("invalid http version") + inc(linei, le) + le = skipIgnoreCase(line, "1.1", linei) + if le > 0: result.version = "1.1" + else: + le = skipIgnoreCase(line, "1.0", linei) + if le <= 0: httpError("unsupported http version") + result.version = "1.0" + inc(linei, le) + # Status code + linei.inc skipWhitespace(line, linei) + result.status = line[linei .. -1] + parsedStatus = true + else: + # Parse headers + var name = "" + var le = parseUntil(line, name, ':', linei) + if le <= 0: httpError("invalid headers") + inc(linei, le) + if line[linei] != ':': httpError("invalid headers") + inc(linei) # Skip : + linei += skipWhitespace(line, linei) + + result.headers[name] = line[linei.. -1] + if not fullyRead: httpError("Connection was closed before full request has been made") + if getBody: + result.body = parseBody(s, result.headers) + else: + result.body = "" type THttpMethod* = enum ## the requested HttpMethod @@ -246,10 +246,10 @@ proc request*(url: string, httpMethod = httpGET, extraHeaders = "", var headers = substr($httpMethod, len("http")) headers.add(" /" & r.path & r.query) + headers.add(" HTTP/1.1\c\L") add(headers, "Host: " & r.hostname & "\c\L") - add(headers, "Connection: Close\c\L") add(headers, extraHeaders) add(headers, "\c\L") @@ -258,6 +258,8 @@ proc request*(url: string, httpMethod = httpGET, extraHeaders = "", if r.scheme == "https": when defined(ssl): s.wrapSocket(verifyMode = CVerifyNone) + else: + raise newException(EHttpRequestErr, "SSL support was not compiled in. Cannot connect over SSL.") port = TPort(443) if r.port != "": port = TPort(r.port.parseInt) @@ -266,7 +268,7 @@ proc request*(url: string, httpMethod = httpGET, extraHeaders = "", if body != "": s.send(body) - result = parseResponse(s) + result = parseResponse(s, httpMethod != httpHEAD) s.close() proc redirection(status: string): bool = diff --git a/lib/pure/sockets.nim b/lib/pure/sockets.nim index 5179527812..8c15c6adb9 100755 --- a/lib/pure/sockets.nim +++ b/lib/pure/sockets.nim @@ -407,7 +407,7 @@ proc acceptAddr*(server: TSocket): tuple[client: TSocket, address: string] = when defined(windows): var err = WSAGetLastError() if err == WSAEINPROGRESS: - client = InvalidSocket + return (InvalidSocket, "") else: OSError() else: if errno == EAGAIN or errno == EWOULDBLOCK: @@ -775,15 +775,18 @@ proc readIntoBuf(socket: TSocket, flags: int32): int = result = recv(socket.fd, addr(socket.buffer), int(socket.buffer.high), flags) else: result = recv(socket.fd, addr(socket.buffer), int(socket.buffer.high), flags) - if result <= 0: return + if result <= 0: + socket.buflen = 0 + socket.currPos = 0 + return result socket.bufLen = result socket.currPos = 0 -template retRead(flags, read: int) = +template retRead(flags, readBytes: int) = let res = socket.readIntoBuf(flags) if res <= 0: - if read > 0: - return read + if readBytes > 0: + return readBytes else: return res @@ -793,16 +796,27 @@ proc recv*(socket: TSocket, data: pointer, size: int): int = if socket.bufLen == 0: retRead(0'i32, 0) - var read = 0 - while read < size: - if socket.currPos >= socket.bufLen: - retRead(0'i32, read) - - let chunk = min(socket.bufLen, size-read) - var d = cast[cstring](data) - copyMem(addr(d[read]), addr(socket.buffer[socket.currPos]), chunk) - read.inc(chunk) - socket.currPos.inc(chunk) + when true: + var read = 0 + while read < size: + if socket.currPos >= socket.bufLen: + retRead(0'i32, read) + + let chunk = min(socket.bufLen-socket.currPos, size-read) + var d = cast[cstring](data) + copyMem(addr(d[read]), addr(socket.buffer[socket.currPos]), chunk) + read.inc(chunk) + socket.currPos.inc(chunk) + else: + var read = 0 + while read < size: + if socket.currPos >= socket.bufLen: + retRead(0'i32, read) + + var d = cast[cstring](data) + d[read] = socket.buffer[socket.currPos] + read.inc(1) + socket.currPos.inc(1) result = read else: @@ -814,8 +828,14 @@ proc recv*(socket: TSocket, data: pointer, size: int): int = else: result = recv(socket.fd, data, size, 0'i32) -proc waitFor(socket: TSocket, waited: var float, timeout: int) = - if socket.bufLen == 0: +proc waitFor(socket: TSocket, waited: var float, timeout: int): int = + ## returns the number of characters available to be read. In unbuffered + ## sockets this is always 1, otherwise this may as big as the buffer, currently + ## 4000. + result = 1 + if socket.isBuffered and socket.bufLen != 0 and socket.bufLen != socket.currPos: + result = socket.bufLen - socket.currPos + else: if timeout - int(waited * 1000.0) < 1: raise newException(ETimeout, "Call to recv() timed out.") var s = @[socket] @@ -824,17 +844,19 @@ proc waitFor(socket: TSocket, waited: var float, timeout: int) = raise newException(ETimeout, "Call to recv() timed out.") waited += (epochTime() - startTime) -proc recv*(socket: TSocket, data: var string, size: int, timeout: int): int = +proc recv*(socket: TSocket, data: pointer, size: int, timeout: int): int = ## overload with a ``timeout`` parameter in miliseconds. var waited = 0.0 # number of seconds already waited var read = 0 while read < size: - waitFor(socket, waited, timeout) - result = recv(socket, addr(data[read]), 1) + let avail = waitFor(socket, waited, timeout) + var d = cast[cstring](data) + result = recv(socket, addr(d[read]), avail) + if result == 0: break if result < 0: - return - inc(read) + return result + inc(read, result) result = read @@ -901,12 +923,12 @@ proc recvLine*(socket: TSocket, line: var TaintedString, timeout: int): bool = setLen(line.string, 0) while true: var c: char - waitFor(socket, waited, timeout) + discard waitFor(socket, waited, timeout) var n = recv(socket, addr(c), 1) if n < 0: return elif n == 0: return true if c == '\r': - waitFor(socket, waited, timeout) + discard waitFor(socket, waited, timeout) n = peekChar(socket, c) if n > 0 and c == '\L': discard recv(socket, addr(c), 1) From e2d38a57ecdc3aa7b5cd81a9f2f588eb0dc5586f Mon Sep 17 00:00:00 2001 From: Zahary Karadjov Date: Sun, 10 Jun 2012 23:33:05 +0300 Subject: [PATCH 12/15] better support for unsigned integers. --- build.bat | 10 +- build64.bat | 10 +- compiler/ast.nim | 40 +- compiler/ccgexprs.nim | 12 +- compiler/ccgtypes.nim | 12 +- compiler/ccgutils.nim | 4 +- compiler/cgendata.nim | 8 +- compiler/docgen.nim | 4 +- compiler/evals.nim | 2 + compiler/extccomp.nim | 2 +- compiler/lexer.nim | 41 +- compiler/magicsys.nim | 6 + compiler/parser.nim | 24 ++ compiler/renderer.nim | 6 + compiler/semexprs.nim | 36 +- compiler/semfold.nim | 12 +- compiler/semtypes.nim | 6 + compiler/sigmatch.nim | 8 + compiler/types.nim | 22 +- install.sh | 845 ++++++++++++++++++------------------------ lib/core/macros.nim | 5 +- lib/system.nim | 114 ++++-- 22 files changed, 643 insertions(+), 586 deletions(-) diff --git a/build.bat b/build.bat index ed2a177eaa..6d28dd4c92 100755 --- a/build.bat +++ b/build.bat @@ -2,7 +2,7 @@ REM Generated by niminst SET CC=gcc SET LINKER=gcc -SET COMP_FLAGS=-w -O3 -fno-strict-aliasing +SET COMP_FLAGS=-w -g3 -O0 -O3 -fno-strict-aliasing SET LINK_FLAGS= REM call the compiler: @@ -143,8 +143,12 @@ ECHO %CC% %COMP_FLAGS% -Ibuild -c build\1_1\aliases.c -o build\1_1\aliases.o %CC% %COMP_FLAGS% -Ibuild -c build\1_1\aliases.c -o build\1_1\aliases.o ECHO %CC% %COMP_FLAGS% -Ibuild -c build\1_1\docgen.c -o build\1_1\docgen.o %CC% %COMP_FLAGS% -Ibuild -c build\1_1\docgen.c -o build\1_1\docgen.o +ECHO %CC% %COMP_FLAGS% -Ibuild -c build\1_1\rstast.c -o build\1_1\rstast.o +%CC% %COMP_FLAGS% -Ibuild -c build\1_1\rstast.c -o build\1_1\rstast.o ECHO %CC% %COMP_FLAGS% -Ibuild -c build\1_1\rst.c -o build\1_1\rst.o %CC% %COMP_FLAGS% -Ibuild -c build\1_1\rst.c -o build\1_1\rst.o +ECHO %CC% %COMP_FLAGS% -Ibuild -c build\1_1\rstgen.c -o build\1_1\rstgen.o +%CC% %COMP_FLAGS% -Ibuild -c build\1_1\rstgen.c -o build\1_1\rstgen.o ECHO %CC% %COMP_FLAGS% -Ibuild -c build\1_1\highlite.c -o build\1_1\highlite.o %CC% %COMP_FLAGS% -Ibuild -c build\1_1\highlite.c -o build\1_1\highlite.o ECHO %CC% %COMP_FLAGS% -Ibuild -c build\1_1\cgen.c -o build\1_1\cgen.o @@ -164,8 +168,8 @@ ECHO %CC% %COMP_FLAGS% -Ibuild -c build\1_1\depends.c -o build\1_1\depends.o ECHO %CC% %COMP_FLAGS% -Ibuild -c build\1_1\parseopt.c -o build\1_1\parseopt.o %CC% %COMP_FLAGS% -Ibuild -c build\1_1\parseopt.c -o build\1_1\parseopt.o -ECHO %LINKER% %LINK_FLAGS% -o bin\nimrod.exe build\1_1\nim__dat.o build\1_1\system.o build\1_1\nimrod.o build\1_1\times.o build\1_1\strutils.o build\1_1\parseutils.o build\1_1\winlean.o build\1_1\commands.o build\1_1\os.o build\1_1\msgs.o build\1_1\options.o build\1_1\lists.o build\1_1\strtabs.o build\1_1\hashes.o build\1_1\tables.o build\1_1\math.o build\1_1\nversion.o build\1_1\condsyms.o build\1_1\ast.o build\1_1\crc.o build\1_1\ropes.o build\1_1\platform.o build\1_1\idents.o build\1_1\intsets.o build\1_1\idgen.o build\1_1\astalgo.o build\1_1\rodutils.o build\1_1\extccomp.o build\1_1\osproc.o build\1_1\streams.o build\1_1\wordrecg.o build\1_1\lexer.o build\1_1\lexbase.o build\1_1\llstream.o build\1_1\nimconf.o build\1_1\main.o build\1_1\syntaxes.o build\1_1\parser.o build\1_1\pbraces.o build\1_1\filters.o build\1_1\renderer.o build\1_1\filter_tmpl.o build\1_1\rodread.o build\1_1\memfiles.o build\1_1\rodwrite.o build\1_1\passes.o build\1_1\types.o build\1_1\trees.o build\1_1\magicsys.o build\1_1\nimsets.o build\1_1\bitsets.o build\1_1\semthreads.o build\1_1\importer.o build\1_1\lookups.o build\1_1\semdata.o build\1_1\treetab.o build\1_1\evals.o build\1_1\semfold.o build\1_1\transf.o build\1_1\cgmeth.o build\1_1\sem.o build\1_1\procfind.o build\1_1\pragmas.o build\1_1\semtypinst.o build\1_1\sigmatch.o build\1_1\suggest.o build\1_1\aliases.o build\1_1\docgen.o build\1_1\rst.o build\1_1\highlite.o build\1_1\cgen.o build\1_1\ccgutils.o build\1_1\cgendata.o build\1_1\ccgmerge.o build\1_1\ecmasgen.o build\1_1\passaux.o build\1_1\depends.o build\1_1\parseopt.o -%LINKER% %LINK_FLAGS% -o bin\nimrod.exe build\1_1\nim__dat.o build\1_1\system.o build\1_1\nimrod.o build\1_1\times.o build\1_1\strutils.o build\1_1\parseutils.o build\1_1\winlean.o build\1_1\commands.o build\1_1\os.o build\1_1\msgs.o build\1_1\options.o build\1_1\lists.o build\1_1\strtabs.o build\1_1\hashes.o build\1_1\tables.o build\1_1\math.o build\1_1\nversion.o build\1_1\condsyms.o build\1_1\ast.o build\1_1\crc.o build\1_1\ropes.o build\1_1\platform.o build\1_1\idents.o build\1_1\intsets.o build\1_1\idgen.o build\1_1\astalgo.o build\1_1\rodutils.o build\1_1\extccomp.o build\1_1\osproc.o build\1_1\streams.o build\1_1\wordrecg.o build\1_1\lexer.o build\1_1\lexbase.o build\1_1\llstream.o build\1_1\nimconf.o build\1_1\main.o build\1_1\syntaxes.o build\1_1\parser.o build\1_1\pbraces.o build\1_1\filters.o build\1_1\renderer.o build\1_1\filter_tmpl.o build\1_1\rodread.o build\1_1\memfiles.o build\1_1\rodwrite.o build\1_1\passes.o build\1_1\types.o build\1_1\trees.o build\1_1\magicsys.o build\1_1\nimsets.o build\1_1\bitsets.o build\1_1\semthreads.o build\1_1\importer.o build\1_1\lookups.o build\1_1\semdata.o build\1_1\treetab.o build\1_1\evals.o build\1_1\semfold.o build\1_1\transf.o build\1_1\cgmeth.o build\1_1\sem.o build\1_1\procfind.o build\1_1\pragmas.o build\1_1\semtypinst.o build\1_1\sigmatch.o build\1_1\suggest.o build\1_1\aliases.o build\1_1\docgen.o build\1_1\rst.o build\1_1\highlite.o build\1_1\cgen.o build\1_1\ccgutils.o build\1_1\cgendata.o build\1_1\ccgmerge.o build\1_1\ecmasgen.o build\1_1\passaux.o build\1_1\depends.o build\1_1\parseopt.o +ECHO %LINKER% %LINK_FLAGS% -o bin\nimrod.exe build\1_1\nim__dat.o build\1_1\system.o build\1_1\nimrod.o build\1_1\times.o build\1_1\strutils.o build\1_1\parseutils.o build\1_1\winlean.o build\1_1\commands.o build\1_1\os.o build\1_1\msgs.o build\1_1\options.o build\1_1\lists.o build\1_1\strtabs.o build\1_1\hashes.o build\1_1\tables.o build\1_1\math.o build\1_1\nversion.o build\1_1\condsyms.o build\1_1\ast.o build\1_1\crc.o build\1_1\ropes.o build\1_1\platform.o build\1_1\idents.o build\1_1\intsets.o build\1_1\idgen.o build\1_1\astalgo.o build\1_1\rodutils.o build\1_1\extccomp.o build\1_1\osproc.o build\1_1\streams.o build\1_1\wordrecg.o build\1_1\lexer.o build\1_1\lexbase.o build\1_1\llstream.o build\1_1\nimconf.o build\1_1\main.o build\1_1\syntaxes.o build\1_1\parser.o build\1_1\pbraces.o build\1_1\filters.o build\1_1\renderer.o build\1_1\filter_tmpl.o build\1_1\rodread.o build\1_1\memfiles.o build\1_1\rodwrite.o build\1_1\passes.o build\1_1\types.o build\1_1\trees.o build\1_1\magicsys.o build\1_1\nimsets.o build\1_1\bitsets.o build\1_1\semthreads.o build\1_1\importer.o build\1_1\lookups.o build\1_1\semdata.o build\1_1\treetab.o build\1_1\evals.o build\1_1\semfold.o build\1_1\transf.o build\1_1\cgmeth.o build\1_1\sem.o build\1_1\procfind.o build\1_1\pragmas.o build\1_1\semtypinst.o build\1_1\sigmatch.o build\1_1\suggest.o build\1_1\aliases.o build\1_1\docgen.o build\1_1\rstast.o build\1_1\rst.o build\1_1\rstgen.o build\1_1\highlite.o build\1_1\cgen.o build\1_1\ccgutils.o build\1_1\cgendata.o build\1_1\ccgmerge.o build\1_1\ecmasgen.o build\1_1\passaux.o build\1_1\depends.o build\1_1\parseopt.o +%LINKER% %LINK_FLAGS% -o bin\nimrod.exe build\1_1\nim__dat.o build\1_1\system.o build\1_1\nimrod.o build\1_1\times.o build\1_1\strutils.o build\1_1\parseutils.o build\1_1\winlean.o build\1_1\commands.o build\1_1\os.o build\1_1\msgs.o build\1_1\options.o build\1_1\lists.o build\1_1\strtabs.o build\1_1\hashes.o build\1_1\tables.o build\1_1\math.o build\1_1\nversion.o build\1_1\condsyms.o build\1_1\ast.o build\1_1\crc.o build\1_1\ropes.o build\1_1\platform.o build\1_1\idents.o build\1_1\intsets.o build\1_1\idgen.o build\1_1\astalgo.o build\1_1\rodutils.o build\1_1\extccomp.o build\1_1\osproc.o build\1_1\streams.o build\1_1\wordrecg.o build\1_1\lexer.o build\1_1\lexbase.o build\1_1\llstream.o build\1_1\nimconf.o build\1_1\main.o build\1_1\syntaxes.o build\1_1\parser.o build\1_1\pbraces.o build\1_1\filters.o build\1_1\renderer.o build\1_1\filter_tmpl.o build\1_1\rodread.o build\1_1\memfiles.o build\1_1\rodwrite.o build\1_1\passes.o build\1_1\types.o build\1_1\trees.o build\1_1\magicsys.o build\1_1\nimsets.o build\1_1\bitsets.o build\1_1\semthreads.o build\1_1\importer.o build\1_1\lookups.o build\1_1\semdata.o build\1_1\treetab.o build\1_1\evals.o build\1_1\semfold.o build\1_1\transf.o build\1_1\cgmeth.o build\1_1\sem.o build\1_1\procfind.o build\1_1\pragmas.o build\1_1\semtypinst.o build\1_1\sigmatch.o build\1_1\suggest.o build\1_1\aliases.o build\1_1\docgen.o build\1_1\rstast.o build\1_1\rst.o build\1_1\rstgen.o build\1_1\highlite.o build\1_1\cgen.o build\1_1\ccgutils.o build\1_1\cgendata.o build\1_1\ccgmerge.o build\1_1\ecmasgen.o build\1_1\passaux.o build\1_1\depends.o build\1_1\parseopt.o ECHO SUCCESS diff --git a/build64.bat b/build64.bat index aa981feb9a..cc29480560 100644 --- a/build64.bat +++ b/build64.bat @@ -2,7 +2,7 @@ REM Generated by niminst SET CC=gcc SET LINKER=gcc -SET COMP_FLAGS=-w -O3 -fno-strict-aliasing +SET COMP_FLAGS=-w -g3 -O0 -O3 -fno-strict-aliasing SET LINK_FLAGS= REM call the compiler: @@ -143,8 +143,12 @@ ECHO %CC% %COMP_FLAGS% -Ibuild -c build\1_2\aliases.c -o build\1_2\aliases.o %CC% %COMP_FLAGS% -Ibuild -c build\1_2\aliases.c -o build\1_2\aliases.o ECHO %CC% %COMP_FLAGS% -Ibuild -c build\1_2\docgen.c -o build\1_2\docgen.o %CC% %COMP_FLAGS% -Ibuild -c build\1_2\docgen.c -o build\1_2\docgen.o +ECHO %CC% %COMP_FLAGS% -Ibuild -c build\1_2\rstast.c -o build\1_2\rstast.o +%CC% %COMP_FLAGS% -Ibuild -c build\1_2\rstast.c -o build\1_2\rstast.o ECHO %CC% %COMP_FLAGS% -Ibuild -c build\1_2\rst.c -o build\1_2\rst.o %CC% %COMP_FLAGS% -Ibuild -c build\1_2\rst.c -o build\1_2\rst.o +ECHO %CC% %COMP_FLAGS% -Ibuild -c build\1_2\rstgen.c -o build\1_2\rstgen.o +%CC% %COMP_FLAGS% -Ibuild -c build\1_2\rstgen.c -o build\1_2\rstgen.o ECHO %CC% %COMP_FLAGS% -Ibuild -c build\1_2\highlite.c -o build\1_2\highlite.o %CC% %COMP_FLAGS% -Ibuild -c build\1_2\highlite.c -o build\1_2\highlite.o ECHO %CC% %COMP_FLAGS% -Ibuild -c build\1_2\cgen.c -o build\1_2\cgen.o @@ -164,8 +168,8 @@ ECHO %CC% %COMP_FLAGS% -Ibuild -c build\1_2\depends.c -o build\1_2\depends.o ECHO %CC% %COMP_FLAGS% -Ibuild -c build\1_2\parseopt.c -o build\1_2\parseopt.o %CC% %COMP_FLAGS% -Ibuild -c build\1_2\parseopt.c -o build\1_2\parseopt.o -ECHO %LINKER% %LINK_FLAGS% -o bin\nimrod.exe build\1_2\nim__dat.o build\1_2\system.o build\1_2\nimrod.o build\1_2\times.o build\1_2\strutils.o build\1_2\parseutils.o build\1_2\winlean.o build\1_2\commands.o build\1_2\os.o build\1_2\msgs.o build\1_2\options.o build\1_2\lists.o build\1_2\strtabs.o build\1_2\hashes.o build\1_2\tables.o build\1_2\math.o build\1_2\nversion.o build\1_2\condsyms.o build\1_2\ast.o build\1_2\crc.o build\1_2\ropes.o build\1_2\platform.o build\1_2\idents.o build\1_2\intsets.o build\1_2\idgen.o build\1_2\astalgo.o build\1_2\rodutils.o build\1_2\extccomp.o build\1_2\osproc.o build\1_2\streams.o build\1_2\wordrecg.o build\1_2\lexer.o build\1_2\lexbase.o build\1_2\llstream.o build\1_2\nimconf.o build\1_2\main.o build\1_2\syntaxes.o build\1_2\parser.o build\1_2\pbraces.o build\1_2\filters.o build\1_2\renderer.o build\1_2\filter_tmpl.o build\1_2\rodread.o build\1_2\memfiles.o build\1_2\rodwrite.o build\1_2\passes.o build\1_2\types.o build\1_2\trees.o build\1_2\magicsys.o build\1_2\nimsets.o build\1_2\bitsets.o build\1_2\semthreads.o build\1_2\importer.o build\1_2\lookups.o build\1_2\semdata.o build\1_2\treetab.o build\1_2\evals.o build\1_2\semfold.o build\1_2\transf.o build\1_2\cgmeth.o build\1_2\sem.o build\1_2\procfind.o build\1_2\pragmas.o build\1_2\semtypinst.o build\1_2\sigmatch.o build\1_2\suggest.o build\1_2\aliases.o build\1_2\docgen.o build\1_2\rst.o build\1_2\highlite.o build\1_2\cgen.o build\1_2\ccgutils.o build\1_2\cgendata.o build\1_2\ccgmerge.o build\1_2\ecmasgen.o build\1_2\passaux.o build\1_2\depends.o build\1_2\parseopt.o -%LINKER% %LINK_FLAGS% -o bin\nimrod.exe build\1_2\nim__dat.o build\1_2\system.o build\1_2\nimrod.o build\1_2\times.o build\1_2\strutils.o build\1_2\parseutils.o build\1_2\winlean.o build\1_2\commands.o build\1_2\os.o build\1_2\msgs.o build\1_2\options.o build\1_2\lists.o build\1_2\strtabs.o build\1_2\hashes.o build\1_2\tables.o build\1_2\math.o build\1_2\nversion.o build\1_2\condsyms.o build\1_2\ast.o build\1_2\crc.o build\1_2\ropes.o build\1_2\platform.o build\1_2\idents.o build\1_2\intsets.o build\1_2\idgen.o build\1_2\astalgo.o build\1_2\rodutils.o build\1_2\extccomp.o build\1_2\osproc.o build\1_2\streams.o build\1_2\wordrecg.o build\1_2\lexer.o build\1_2\lexbase.o build\1_2\llstream.o build\1_2\nimconf.o build\1_2\main.o build\1_2\syntaxes.o build\1_2\parser.o build\1_2\pbraces.o build\1_2\filters.o build\1_2\renderer.o build\1_2\filter_tmpl.o build\1_2\rodread.o build\1_2\memfiles.o build\1_2\rodwrite.o build\1_2\passes.o build\1_2\types.o build\1_2\trees.o build\1_2\magicsys.o build\1_2\nimsets.o build\1_2\bitsets.o build\1_2\semthreads.o build\1_2\importer.o build\1_2\lookups.o build\1_2\semdata.o build\1_2\treetab.o build\1_2\evals.o build\1_2\semfold.o build\1_2\transf.o build\1_2\cgmeth.o build\1_2\sem.o build\1_2\procfind.o build\1_2\pragmas.o build\1_2\semtypinst.o build\1_2\sigmatch.o build\1_2\suggest.o build\1_2\aliases.o build\1_2\docgen.o build\1_2\rst.o build\1_2\highlite.o build\1_2\cgen.o build\1_2\ccgutils.o build\1_2\cgendata.o build\1_2\ccgmerge.o build\1_2\ecmasgen.o build\1_2\passaux.o build\1_2\depends.o build\1_2\parseopt.o +ECHO %LINKER% %LINK_FLAGS% -o bin\nimrod.exe build\1_2\nim__dat.o build\1_2\system.o build\1_2\nimrod.o build\1_2\times.o build\1_2\strutils.o build\1_2\parseutils.o build\1_2\winlean.o build\1_2\commands.o build\1_2\os.o build\1_2\msgs.o build\1_2\options.o build\1_2\lists.o build\1_2\strtabs.o build\1_2\hashes.o build\1_2\tables.o build\1_2\math.o build\1_2\nversion.o build\1_2\condsyms.o build\1_2\ast.o build\1_2\crc.o build\1_2\ropes.o build\1_2\platform.o build\1_2\idents.o build\1_2\intsets.o build\1_2\idgen.o build\1_2\astalgo.o build\1_2\rodutils.o build\1_2\extccomp.o build\1_2\osproc.o build\1_2\streams.o build\1_2\wordrecg.o build\1_2\lexer.o build\1_2\lexbase.o build\1_2\llstream.o build\1_2\nimconf.o build\1_2\main.o build\1_2\syntaxes.o build\1_2\parser.o build\1_2\pbraces.o build\1_2\filters.o build\1_2\renderer.o build\1_2\filter_tmpl.o build\1_2\rodread.o build\1_2\memfiles.o build\1_2\rodwrite.o build\1_2\passes.o build\1_2\types.o build\1_2\trees.o build\1_2\magicsys.o build\1_2\nimsets.o build\1_2\bitsets.o build\1_2\semthreads.o build\1_2\importer.o build\1_2\lookups.o build\1_2\semdata.o build\1_2\treetab.o build\1_2\evals.o build\1_2\semfold.o build\1_2\transf.o build\1_2\cgmeth.o build\1_2\sem.o build\1_2\procfind.o build\1_2\pragmas.o build\1_2\semtypinst.o build\1_2\sigmatch.o build\1_2\suggest.o build\1_2\aliases.o build\1_2\docgen.o build\1_2\rstast.o build\1_2\rst.o build\1_2\rstgen.o build\1_2\highlite.o build\1_2\cgen.o build\1_2\ccgutils.o build\1_2\cgendata.o build\1_2\ccgmerge.o build\1_2\ecmasgen.o build\1_2\passaux.o build\1_2\depends.o build\1_2\parseopt.o +%LINKER% %LINK_FLAGS% -o bin\nimrod.exe build\1_2\nim__dat.o build\1_2\system.o build\1_2\nimrod.o build\1_2\times.o build\1_2\strutils.o build\1_2\parseutils.o build\1_2\winlean.o build\1_2\commands.o build\1_2\os.o build\1_2\msgs.o build\1_2\options.o build\1_2\lists.o build\1_2\strtabs.o build\1_2\hashes.o build\1_2\tables.o build\1_2\math.o build\1_2\nversion.o build\1_2\condsyms.o build\1_2\ast.o build\1_2\crc.o build\1_2\ropes.o build\1_2\platform.o build\1_2\idents.o build\1_2\intsets.o build\1_2\idgen.o build\1_2\astalgo.o build\1_2\rodutils.o build\1_2\extccomp.o build\1_2\osproc.o build\1_2\streams.o build\1_2\wordrecg.o build\1_2\lexer.o build\1_2\lexbase.o build\1_2\llstream.o build\1_2\nimconf.o build\1_2\main.o build\1_2\syntaxes.o build\1_2\parser.o build\1_2\pbraces.o build\1_2\filters.o build\1_2\renderer.o build\1_2\filter_tmpl.o build\1_2\rodread.o build\1_2\memfiles.o build\1_2\rodwrite.o build\1_2\passes.o build\1_2\types.o build\1_2\trees.o build\1_2\magicsys.o build\1_2\nimsets.o build\1_2\bitsets.o build\1_2\semthreads.o build\1_2\importer.o build\1_2\lookups.o build\1_2\semdata.o build\1_2\treetab.o build\1_2\evals.o build\1_2\semfold.o build\1_2\transf.o build\1_2\cgmeth.o build\1_2\sem.o build\1_2\procfind.o build\1_2\pragmas.o build\1_2\semtypinst.o build\1_2\sigmatch.o build\1_2\suggest.o build\1_2\aliases.o build\1_2\docgen.o build\1_2\rstast.o build\1_2\rst.o build\1_2\rstgen.o build\1_2\highlite.o build\1_2\cgen.o build\1_2\ccgutils.o build\1_2\cgendata.o build\1_2\ccgmerge.o build\1_2\ecmasgen.o build\1_2\passaux.o build\1_2\depends.o build\1_2\parseopt.o ECHO SUCCESS diff --git a/compiler/ast.nim b/compiler/ast.nim index 0c25b24a17..eb258e383f 100755 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -52,9 +52,15 @@ type nkInt16Lit, nkInt32Lit, nkInt64Lit, + nkUIntLit, # an unsigned integer literal + nkUInt8Lit, + nkUInt16Lit, + nkUInt32Lit, + nkUInt64Lit, nkFloatLit, # a floating point literal nkFloat32Lit, nkFloat64Lit, + nkFloat128Lit, nkStrLit, # a string literal "" nkRStrLit, # a raw string literal r"" nkTripleStrLit, # a triple string literal """ @@ -323,6 +329,7 @@ type tfEnumHasHoles, # enum cannot be mapped into a range tfShallow, # type can be shallow copied on assignment tfThread, # proc type is marked as ``thread`` + tfLiteral # type represents literal value tfFromGeneric # type is an instantiation of a generic; this is needed # because for instantiations of objects, structural # type equality has to be used @@ -406,8 +413,11 @@ type mNewString, mNewStringOfCap, mReset, mArray, mOpenArray, mRange, mSet, mSeq, - mOrdinal, mInt, mInt8, mInt16, mInt32, - mInt64, mFloat, mFloat32, mFloat64, mBool, mChar, mString, mCstring, + mOrdinal, + mInt, mInt8, mInt16, mInt32, mInt64, + mUInt, mUInt8, mUInt16, mUInt32, mUInt64, + mFloat, mFloat32, mFloat64, mFloat128, + mBool, mChar, mString, mCstring, mPointer, mEmptySet, mIntSetBaseType, mNil, mExpr, mStmt, mTypeDesc, mVoidType, mPNimrodNode, mIsMainModule, mCompileDate, mCompileTime, mNimrodVersion, mNimrodMajor, @@ -462,11 +472,11 @@ type info*: TLineInfo flags*: TNodeFlags case Kind*: TNodeKind - of nkCharLit..nkInt64Lit: + of nkCharLit..nkUInt64Lit: intVal*: biggestInt - of nkFloatLit..nkFloat64Lit: + of nkFloatLit..nkFloat128Lit: floatVal*: biggestFloat - of nkStrLit..nkTripleStrLit: + of nkStrLit..nkTripleStrLit: strVal*: string of nkSym: sym*: PSym @@ -763,8 +773,8 @@ const # for all kind of hash tables: proc ValueToString*(a: PNode): string = case a.kind - of nkCharLit..nkInt64Lit: result = $(a.intVal) - of nkFloatLit, nkFloat32Lit, nkFloat64Lit: result = $(a.floatVal) + of nkCharLit..nkUInt64Lit: result = $(a.intVal) + of nkFloatLit..nkFloat128Lit: result = $(a.floatVal) of nkStrLit..nkTripleStrLit: result = a.strVal else: InternalError(a.info, "valueToString") @@ -1019,8 +1029,8 @@ proc copyNode(src: PNode): PNode = result.typ = src.typ result.flags = src.flags * PersistentNodeFlags case src.Kind - of nkCharLit..nkInt64Lit: result.intVal = src.intVal - of nkFloatLit, nkFloat32Lit, nkFloat64Lit: result.floatVal = src.floatVal + of nkCharLit..nkUInt64Lit: result.intVal = src.intVal + of nkFloatLit..nkFloat128Lit: result.floatVal = src.floatVal of nkSym: result.sym = src.sym of nkIdent: result.ident = src.ident of nkStrLit..nkTripleStrLit: result.strVal = src.strVal @@ -1034,8 +1044,8 @@ proc shallowCopy*(src: PNode): PNode = result.typ = src.typ result.flags = src.flags * PersistentNodeFlags case src.Kind - of nkCharLit..nkInt64Lit: result.intVal = src.intVal - of nkFloatLit, nkFloat32Lit, nkFloat64Lit: result.floatVal = src.floatVal + of nkCharLit..nkUInt64Lit: result.intVal = src.intVal + of nkFloatLit..nkFloat128Lit: result.floatVal = src.floatVal of nkSym: result.sym = src.sym of nkIdent: result.ident = src.ident of nkStrLit..nkTripleStrLit: result.strVal = src.strVal @@ -1050,8 +1060,8 @@ proc copyTree(src: PNode): PNode = result.typ = src.typ result.flags = src.flags * PersistentNodeFlags case src.Kind - of nkCharLit..nkInt64Lit: result.intVal = src.intVal - of nkFloatLit, nkFloat32Lit, nkFloat64Lit: result.floatVal = src.floatVal + of nkCharLit..nkUInt64Lit: result.intVal = src.intVal + of nkFloatLit..nkFloat128Lit: result.floatVal = src.floatVal of nkSym: result.sym = src.sym of nkIdent: result.ident = src.ident of nkStrLit..nkTripleStrLit: result.strVal = src.strVal @@ -1101,14 +1111,14 @@ proc sonsNotNil(n: PNode): bool = proc getInt*(a: PNode): biggestInt = case a.kind - of nkIntLit..nkInt64Lit: result = a.intVal + of nkIntLit..nkUInt64Lit: result = a.intVal else: internalError(a.info, "getInt") result = 0 proc getFloat*(a: PNode): biggestFloat = case a.kind - of nkFloatLit..nkFloat64Lit: result = a.floatVal + of nkFloatLit..nkFloat128Lit: result = a.floatVal else: internalError(a.info, "getFloat") result = 0.0 diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index 5b04111b36..a929b5af04 100755 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -34,7 +34,7 @@ proc int32Literal(i: Int): PRope = proc genHexLiteral(v: PNode): PRope = # hex literals are unsigned in C # so we don't generate hex literals any longer. - if not (v.kind in {nkIntLit..nkInt64Lit}): + if not (v.kind in {nkIntLit..nkUInt64Lit}): internalError(v.info, "genHexLiteral") result = intLiteral(v.intVal) @@ -47,7 +47,7 @@ proc getStrLit(m: BModule, s: string): PRope = proc genLiteral(p: BProc, v: PNode, ty: PType): PRope = if ty == nil: internalError(v.info, "genLiteral: ty is nil") case v.kind - of nkCharLit..nkInt64Lit: + of nkCharLit..nkUInt64Lit: case skipTypes(ty, abstractVarRange).kind of tyChar, tyInt64, tyNil: result = intLiteral(v.intVal) @@ -277,7 +277,7 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) = else: appcg(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)]) of tyPtr, tyPointer, tyChar, tyBool, tyEnum, tyCString, - tyInt..tyFloat128, tyRange: + tyInt..tyUInt64, tyRange: appcg(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)]) else: InternalError("genAssignment(" & $ty.kind & ')') @@ -582,7 +582,7 @@ proc genTupleElem(p: BProc, e: PNode, d: var TLoc) = var ty = a.t var r = rdLoc(a) case e.sons[1].kind - of nkIntLit..nkInt64Lit: i = int(e.sons[1].intVal) + of nkIntLit..nkUInt64Lit: i = int(e.sons[1].intVal) else: internalError(e.info, "genTupleElem") when false: if ty.n != nil: @@ -1684,8 +1684,8 @@ proc expr(p: BProc, e: PNode, d: var TLoc) = InternalError(e.info, "expr: param not init " & sym.name.s) putLocIntoDest(p, d, sym.loc) else: InternalError(e.info, "expr(" & $sym.kind & "); unknown symbol") - of nkStrLit..nkTripleStrLit, nkIntLit..nkInt64Lit, nkFloatLit..nkFloat64Lit, - nkNilLit, nkCharLit: + of nkStrLit..nkTripleStrLit, nkIntLit..nkUInt64Lit, + nkFloatLit..nkFloat128Lit, nkNilLit, nkCharLit: putIntoDest(p, d, e.typ, genLiteral(p, e)) of nkCall, nkHiddenCallConv, nkInfix, nkPrefix, nkPostfix, nkCommand, nkCallStrLit: diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim index 4492c2fea2..e456a1eaa8 100755 --- a/compiler/ccgtypes.nim +++ b/compiler/ccgtypes.nim @@ -174,7 +174,7 @@ proc mapType(typ: PType): TCTypeKind = of tyProc: result = if typ.callConv != ccClosure: ctProc else: ctStruct of tyString: result = ctNimStr of tyCString: result = ctCString - of tyInt..tyFloat128: + of tyInt..tyUInt64: result = TCTypeKind(ord(typ.kind) - ord(tyInt) + ord(ctInt)) else: InternalError("mapType") @@ -313,8 +313,10 @@ proc typeNameOrLiteral(t: PType, literal: string): PRope = proc getSimpleTypeDesc(m: BModule, typ: PType): PRope = const - NumericalTypeToStr: array[tyInt..tyFloat128, string] = ["NI", "NI8", - "NI16", "NI32", "NI64", "NF", "NF32", "NF64", "NF128"] + NumericalTypeToStr: array[tyInt..tyUInt64, string] = [ + "NI", "NI8", "NI16", "NI32", "NI64", + "NF", "NF32", "NF64", "NF128", + "NU", "NU8", "NU16", "NU32", "NU64",] case typ.Kind of tyPointer: result = typeNameOrLiteral(typ, "void*") @@ -337,7 +339,7 @@ proc getSimpleTypeDesc(m: BModule, typ: PType): PRope = of tyBool: result = typeNameOrLiteral(typ, "NIM_BOOL") of tyChar: result = typeNameOrLiteral(typ, "NIM_CHAR") of tyNil: result = typeNameOrLiteral(typ, "0") - of tyInt..tyFloat128, tyUInt..tyUInt64: + of tyInt..tyUInt64: result = typeNameOrLiteral(typ, NumericalTypeToStr[typ.Kind]) of tyRange: result = getSimpleTypeDesc(m, typ.sons[0]) else: result = nil @@ -871,7 +873,7 @@ proc genTypeInfo(m: BModule, typ: PType): PRope = if dataGenerated: return case t.kind of tyEmpty: result = toRope"0" - of tyPointer, tyBool, tyChar, tyCString, tyString, tyInt..tyFloat128, tyVar: + of tyPointer, tyBool, tyChar, tyCString, tyString, tyInt..tyUInt64, tyVar: genTypeInfoAuxBase(gNimDat, t, result, toRope"0") of tyProc: if t.callConv != ccClosure: diff --git a/compiler/ccgutils.nim b/compiler/ccgutils.nim index 5ba5230702..de49897c51 100755 --- a/compiler/ccgutils.nim +++ b/compiler/ccgutils.nim @@ -70,9 +70,7 @@ proc GetUniqueType*(key: PType): PType = var k = key.kind case k of tyBool, tyChar, - tyInt, tyInt8, tyInt16, tyInt32, tyInt64, - tyFloat, tyFloat32, tyFloat64, tyFloat128, - tyUInt, tyUInt8, tyUInt16, tyUInt32, tyUInt64: + tyInt..tyUInt64: # no canonicalization for integral types, so that e.g. ``pid_t`` is # produced instead of ``NI``. result = key diff --git a/compiler/cgendata.nim b/compiler/cgendata.nim index bcdf53afd2..72c7ceae50 100644 --- a/compiler/cgendata.nim +++ b/compiler/cgendata.nim @@ -37,9 +37,11 @@ type cfsDynLibDeinit # section for deinitialization of dynamic # libraries TCTypeKind* = enum # describes the type kind of a C type - ctVoid, ctChar, ctBool, ctUInt, ctUInt8, ctUInt16, ctUInt32, ctUInt64, - ctInt, ctInt8, ctInt16, ctInt32, ctInt64, ctFloat, ctFloat32, ctFloat64, - ctFloat128, ctArray, ctStruct, ctPtr, ctNimStr, ctNimSeq, ctProc, ctCString + ctVoid, ctChar, ctBool, + ctInt, ctInt8, ctInt16, ctInt32, ctInt64, + ctFloat, ctFloat32, ctFloat64, ctFloat128, + ctUInt, ctUInt8, ctUInt16, ctUInt32, ctUInt64, + ctArray, ctStruct, ctPtr, ctNimStr, ctNimSeq, ctProc, ctCString TCFileSections* = array[TCFileSection, PRope] # represents a generated C file TCProcSection* = enum # the sections a generated C proc consists of cpsLocals, # section of local variables for C proc diff --git a/compiler/docgen.nim b/compiler/docgen.nim index 6e249b888b..ae654fda45 100755 --- a/compiler/docgen.nim +++ b/compiler/docgen.nim @@ -206,10 +206,10 @@ proc genItem(d: PDoc, n, nameNode: PNode, k: TSymKind) = of tkCharLit: dispA(result, "$1", "\\spanCharLit{$1}", [toRope(esc(d.target, literal))]) - of tkIntLit..tkInt64Lit: + of tkIntLit..tkUInt64Lit: dispA(result, "$1", "\\spanDecNumber{$1}", [toRope(esc(d.target, literal))]) - of tkFloatLit..tkFloat64Lit: + of tkFloatLit..tkFloat128Lit: dispA(result, "$1", "\\spanFloatNumber{$1}", [toRope(esc(d.target, literal))]) of tkSymbol: diff --git a/compiler/evals.nim b/compiler/evals.nim index 5c77a4d940..62649cb08d 100755 --- a/compiler/evals.nim +++ b/compiler/evals.nim @@ -235,6 +235,8 @@ proc getNullValue(typ: PType, info: TLineInfo): PNode = case t.kind of tyBool, tyEnum, tyChar, tyInt..tyInt64: result = newNodeIT(nkIntLit, info, t) + of tyUInt..tyUInt64: + result = newNodeIT(nkUIntLit, info, t) of tyFloat..tyFloat128: result = newNodeIt(nkFloatLit, info, t) of tyVar, tyPointer, tyPtr, tyRef, tyCString, tySequence, tyString, tyExpr, diff --git a/compiler/extccomp.nim b/compiler/extccomp.nim index fb2e5f3f52..2872f28a77 100755 --- a/compiler/extccomp.nim +++ b/compiler/extccomp.nim @@ -597,7 +597,7 @@ proc CallCCompiler*(projectfile: string) = proc genMappingFiles(list: TLinkedList): PRope = var it = PStrEntry(list.head) while it != nil: - appf(result, "--file:r\"$1\"$n", [toRope(AddFileExt(it.data, cExt))]) + appf(result, "--file:r\"$1\"$N", [toRope(AddFileExt(it.data, cExt))]) it = PStrEntry(it.next) proc writeMapping*(gSymbolMapping: PRope) = diff --git a/compiler/lexer.nim b/compiler/lexer.nim index a17871e3a7..73a818e321 100755 --- a/compiler/lexer.nim +++ b/compiler/lexer.nim @@ -45,8 +45,10 @@ type tkTemplate, tkTry, tkTuple, tkType, tkVar, tkWhen, tkWhile, tkWith, tkWithout, tkXor, tkYield, # end of keywords - tkIntLit, tkInt8Lit, tkInt16Lit, tkInt32Lit, tkInt64Lit, tkFloatLit, - tkFloat32Lit, tkFloat64Lit, tkStrLit, tkRStrLit, tkTripleStrLit, + tkIntLit, tkInt8Lit, tkInt16Lit, tkInt32Lit, tkInt64Lit, + tkUIntLit, tkUInt8Lit, tkUInt16Lit, tkUInt32Lit, tkUInt64Lit, + tkFloatLit, tkFloat32Lit, tkFloat64Lit, tkFloat128Lit, + tkStrLit, tkRStrLit, tkTripleStrLit, tkGStrLit, tkGTripleStrLit, tkCharLit, tkParLe, tkParRi, tkBracketLe, tkBracketRi, tkCurlyLe, tkCurlyRi, tkBracketDotLe, tkBracketDotRi, # [. and .] @@ -77,8 +79,10 @@ const "template", "try", "tuple", "type", "var", "when", "while", "with", "without", "xor", "yield", - "tkIntLit", "tkInt8Lit", "tkInt16Lit", "tkInt32Lit", "tkInt64Lit", - "tkFloatLit", "tkFloat32Lit", "tkFloat64Lit", "tkStrLit", "tkRStrLit", + "tkIntLit", "tkInt8Lit", "tkInt16Lit", "tkInt32Lit", "tkInt64Lit", + "tkUIntLit", "tkUInt8Lit", "tkUInt16Lit", "tkUInt32Lit", "tkUInt64Lit", + "tkFloatLit", "tkFloat32Lit", "tkFloat64Lit", "tkFloat128Lit", + "tkStrLit", "tkRStrLit", "tkTripleStrLit", "tkGStrLit", "tkGTripleStrLit", "tkCharLit", "(", ")", "[", "]", "{", "}", "[.", ".]", "{.", ".}", "(.", ".)", ",", ";", @@ -283,12 +287,17 @@ proc GetNumber(L: var TLexer): TToken = case L.buf[endpos] of 'f', 'F': inc(endpos) - if (L.buf[endpos] == '6') and (L.buf[endpos + 1] == '4'): - result.tokType = tkFloat64Lit - inc(endpos, 2) - elif (L.buf[endpos] == '3') and (L.buf[endpos + 1] == '2'): + if (L.buf[endpos] == '3') and (L.buf[endpos + 1] == '2'): result.tokType = tkFloat32Lit inc(endpos, 2) + elif (L.buf[endpos] == '6') and (L.buf[endpos + 1] == '4'): + result.tokType = tkFloat64Lit + inc(endpos, 2) + elif (L.buf[endpos] == '1') and + (L.buf[endpos + 1] == '2') and + (L.buf[endpos + 2] == '8'): + result.tokType = tkFloat128Lit + inc(endpos, 3) else: lexMessage(L, errInvalidNumber, result.literal & "'f" & L.buf[endpos]) of 'i', 'I': @@ -307,6 +316,22 @@ proc GetNumber(L: var TLexer): TToken = inc(endpos) else: lexMessage(L, errInvalidNumber, result.literal & "'i" & L.buf[endpos]) + of 'u', 'U': + inc(endpos) + if (L.buf[endpos] == '6') and (L.buf[endpos + 1] == '4'): + result.tokType = tkUInt64Lit + inc(endpos, 2) + elif (L.buf[endpos] == '3') and (L.buf[endpos + 1] == '2'): + result.tokType = tkUInt32Lit + inc(endpos, 2) + elif (L.buf[endpos] == '1') and (L.buf[endpos + 1] == '6'): + result.tokType = tkUInt16Lit + inc(endpos, 2) + elif (L.buf[endpos] == '8'): + result.tokType = tkUInt8Lit + inc(endpos) + else: + result.tokType = tkUIntLit else: lexMessage(L, errInvalidNumber, result.literal & "'" & L.buf[endpos]) else: L.bufpos = pos # restore position diff --git a/compiler/magicsys.nim b/compiler/magicsys.nim index 5b9987efaf..a69b40fbfb 100755 --- a/compiler/magicsys.nim +++ b/compiler/magicsys.nim @@ -53,9 +53,15 @@ proc getSysType(kind: TTypeKind): PType = of tyInt16: result = sysTypeFromName("int16") of tyInt32: result = sysTypeFromName("int32") of tyInt64: result = sysTypeFromName("int64") + of tyUInt: result = sysTypeFromName("uint") + of tyUInt8: result = sysTypeFromName("uint8") + of tyUInt16: result = sysTypeFromName("uint16") + of tyUInt32: result = sysTypeFromName("uint32") + of tyUInt64: result = sysTypeFromName("uint64") of tyFloat: result = sysTypeFromName("float") of tyFloat32: result = sysTypeFromName("float32") of tyFloat64: result = sysTypeFromName("float64") + of tyFloat128: result = sysTypeFromName("float128") of tyBool: result = sysTypeFromName("bool") of tyChar: result = sysTypeFromName("char") of tyString: result = sysTypeFromName("string") diff --git a/compiler/parser.nim b/compiler/parser.nim index 4baee5b434..d1042b04d4 100755 --- a/compiler/parser.nim +++ b/compiler/parser.nim @@ -416,6 +416,26 @@ proc identOrLiteral(p: var TParser): PNode = result = newIntNodeP(nkInt64Lit, p.tok.iNumber, p) setBaseFlags(result, p.tok.base) getTok(p) + of tkUIntLit: + result = newIntNodeP(nkUIntLit, p.tok.iNumber, p) + setBaseFlags(result, p.tok.base) + getTok(p) + of tkUInt8Lit: + result = newIntNodeP(nkUInt8Lit, p.tok.iNumber, p) + setBaseFlags(result, p.tok.base) + getTok(p) + of tkUInt16Lit: + result = newIntNodeP(nkUInt16Lit, p.tok.iNumber, p) + setBaseFlags(result, p.tok.base) + getTok(p) + of tkUInt32Lit: + result = newIntNodeP(nkUInt32Lit, p.tok.iNumber, p) + setBaseFlags(result, p.tok.base) + getTok(p) + of tkUInt64Lit: + result = newIntNodeP(nkUInt64Lit, p.tok.iNumber, p) + setBaseFlags(result, p.tok.base) + getTok(p) of tkFloatLit: result = newFloatNodeP(nkFloatLit, p.tok.fNumber, p) setBaseFlags(result, p.tok.base) @@ -428,6 +448,10 @@ proc identOrLiteral(p: var TParser): PNode = result = newFloatNodeP(nkFloat64Lit, p.tok.fNumber, p) setBaseFlags(result, p.tok.base) getTok(p) + of tkFloat128Lit: + result = newFloatNodeP(nkFloat128Lit, p.tok.fNumber, p) + setBaseFlags(result, p.tok.base) + getTok(p) of tkStrLit: result = newStrNodeP(nkStrLit, p.tok.literal, p) getTok(p) diff --git a/compiler/renderer.nim b/compiler/renderer.nim index a5e79762c3..21b0f2287d 100755 --- a/compiler/renderer.nim +++ b/compiler/renderer.nim @@ -705,9 +705,15 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) = of nkInt16Lit: put(g, tkInt16Lit, atom(n)) of nkInt32Lit: put(g, tkInt32Lit, atom(n)) of nkInt64Lit: put(g, tkInt64Lit, atom(n)) + of nkUIntLit: put(g, tkUIntLit, atom(n)) + of nkUInt8Lit: put(g, tkUInt8Lit, atom(n)) + of nkUInt16Lit: put(g, tkUInt16Lit, atom(n)) + of nkUInt32Lit: put(g, tkUInt32Lit, atom(n)) + of nkUInt64Lit: put(g, tkUInt64Lit, atom(n)) of nkFloatLit: put(g, tkFloatLit, atom(n)) of nkFloat32Lit: put(g, tkFloat32Lit, atom(n)) of nkFloat64Lit: put(g, tkFloat64Lit, atom(n)) + of nkFloat128Lit: put(g, tkFloat128Lit, atom(n)) of nkStrLit: put(g, tkStrLit, atom(n)) of nkRStrLit: put(g, tkRStrLit, atom(n)) of nkCharLit: put(g, tkCharLit, atom(n)) diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index ac9075d4f9..8910e54c26 100755 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -132,10 +132,10 @@ proc checkConversionBetweenObjects(info: TLineInfo, castDest, src: PType) = proc checkConvertible(info: TLineInfo, castDest, src: PType) = const - IntegralTypes = {tyBool, tyEnum, tyChar, tyInt..tyFloat128} + IntegralTypes = {tyBool, tyEnum, tyChar, tyInt..tyUInt64} if sameType(castDest, src) and castDest.sym == src.sym: # don't annoy conversions that may be needed on another processor: - if not (castDest.kind in {tyInt..tyFloat128, tyNil}): + if not (castDest.kind in {tyInt..tyUInt64, tyNil}): Message(info, hintConvFromXtoItselfNotNeeded, typeToString(castDest)) return var d = skipTypes(castDest, abstractVar) @@ -143,7 +143,7 @@ proc checkConvertible(info: TLineInfo, castDest, src: PType) = while (d != nil) and (d.Kind in {tyPtr, tyRef}) and (d.Kind == s.Kind): d = base(d) s = base(s) - if d == nil: + if d == nil: GlobalError(info, errGenerated, msgKindToString(errIllegalConvFromXtoY) % [ src.typeToString, castDest.typeToString]) elif d.Kind == tyObject and s.Kind == tyObject: @@ -1283,6 +1283,20 @@ proc semMacroStmt(c: PContext, n: PNode, semCheck = true): PNode = GlobalError(n.info, errInvalidExpressionX, renderTree(a, {renderNoComments})) +proc litIntType(kind: TTypeKind): PType = + result = getSysType(kind).copyType(getCurrOwner(), true) + result.flags.incl(tfLiteral) + +template memoize(e: expr): expr = + var `*guard` {.global.} = false + var `*memo` {.global.} : type(e) + + if not `*guard`: + `*memo` = e + `*guard` = true + + `*memo` + proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode = result = n if gCmd == cmdIdeTools: suggestExpr(c, n) @@ -1303,9 +1317,9 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode = if result.typ == nil: let i = result.intVal if i >= low(int32) and i <= high(int32): - result.typ = getSysType(tyInt) + result.typ = litIntType(tyInt).memoize else: - result.typ = getSysType(tyInt64) + result.typ = litIntType(tyInt64).memoize of nkInt8Lit: if result.typ == nil: result.typ = getSysType(tyInt8) of nkInt16Lit: @@ -1314,12 +1328,24 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode = if result.typ == nil: result.typ = getSysType(tyInt32) of nkInt64Lit: if result.typ == nil: result.typ = getSysType(tyInt64) + of nkUIntLit: + if result.typ == nil: result.typ = getSysType(tyUInt) + of nkUInt8Lit: + if result.typ == nil: result.typ = getSysType(tyUInt8) + of nkUInt16Lit: + if result.typ == nil: result.typ = getSysType(tyUInt16) + of nkUInt32Lit: + if result.typ == nil: result.typ = getSysType(tyUInt32) + of nkUInt64Lit: + if result.typ == nil: result.typ = getSysType(tyUInt64) of nkFloatLit: if result.typ == nil: result.typ = getSysType(tyFloat) of nkFloat32Lit: if result.typ == nil: result.typ = getSysType(tyFloat32) of nkFloat64Lit: if result.typ == nil: result.typ = getSysType(tyFloat64) + of nkFloat128Lit: + if result.typ == nil: result.typ = getSysType(tyFloat128) of nkStrLit..nkTripleStrLit: if result.typ == nil: result.typ = getSysType(tyString) of nkCharLit: diff --git a/compiler/semfold.nim b/compiler/semfold.nim index 565155791b..f67e58e2f3 100755 --- a/compiler/semfold.nim +++ b/compiler/semfold.nim @@ -258,15 +258,15 @@ proc partialOrExpr(c: PSym, n: PNode): PNode = proc leValueConv(a, b: PNode): bool = result = false case a.kind - of nkCharLit..nkInt64Lit: + of nkCharLit..nkUInt64Lit: case b.kind - of nkCharLit..nkInt64Lit: result = a.intVal <= b.intVal - of nkFloatLit..nkFloat64Lit: result = a.intVal <= round(b.floatVal) + of nkCharLit..nkUInt64Lit: result = a.intVal <= b.intVal + of nkFloatLit..nkFloat128Lit: result = a.intVal <= round(b.floatVal) else: InternalError(a.info, "leValueConv") - of nkFloatLit..nkFloat64Lit: + of nkFloatLit..nkFloat128Lit: case b.kind - of nkFloatLit..nkFloat64Lit: result = a.floatVal <= b.floatVal - of nkCharLit..nkInt64Lit: result = a.floatVal <= toFloat(int(b.intVal)) + of nkFloatLit..nkFloat128Lit: result = a.floatVal <= b.floatVal + of nkCharLit..nkUInt64Lit: result = a.floatVal <= toFloat(int(b.intVal)) else: InternalError(a.info, "leValueConv") else: InternalError(a.info, "leValueConv") diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index 19f37f4050..e68ea007ee 100755 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -822,9 +822,15 @@ proc processMagicType(c: PContext, m: PSym) = of mInt16: setMagicType(m, tyInt16, 2) of mInt32: setMagicType(m, tyInt32, 4) of mInt64: setMagicType(m, tyInt64, 8) + of mUInt: setMagicType(m, tyUInt, intSize) + of mUInt8: setMagicType(m, tyUInt8, 1) + of mUInt16: setMagicType(m, tyUInt16, 2) + of mUInt32: setMagicType(m, tyUInt32, 4) + of mUInt64: setMagicType(m, tyUInt64, 8) of mFloat: setMagicType(m, tyFloat, floatSize) of mFloat32: setMagicType(m, tyFloat32, 4) of mFloat64: setMagicType(m, tyFloat64, 8) + of mFloat128: setMagicType(m, tyFloat128, 16) of mBool: setMagicType(m, tyBool, 1) of mChar: setMagicType(m, tyChar, 1) of mString: diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index 9881e84a30..168936ed4c 100755 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -163,6 +163,9 @@ proc handleRange(f, a: PType, min, max: TTypeKind): TTypeRelation = var k = skipTypes(a, {tyRange}).kind if k == f.kind: result = isSubtype elif f.kind == tyInt and k in {tyInt..tyInt32}: result = isIntConv + elif f.kind == tyUInt and k in {tyUInt..tyUInt32}: result = isIntConv + elif f.kind in {tyUInt..tyUInt64} and k == tyInt and tfLiteral in a.flags: + result = isIntConv elif k >= min and k <= max: result = isConvertible else: result = isNone @@ -306,6 +309,11 @@ proc typeRel(mapping: var TIdTable, f, a: PType): TTypeRelation = of tyInt16: result = handleRange(f, a, tyInt8, tyInt16) of tyInt32: result = handleRange(f, a, tyInt, tyInt32) of tyInt64: result = handleRange(f, a, tyInt, tyInt64) + of tyUInt: result = handleRange(f, a, tyUInt8, tyUInt32) + of tyUInt8: result = handleRange(f, a, tyUInt8, tyUInt8) + of tyUInt16: result = handleRange(f, a, tyUInt8, tyUInt16) + of tyUInt32: result = handleRange(f, a, tyUInt, tyUInt32) + of tyUInt64: result = handleRange(f, a, tyUInt, tyUInt64) of tyFloat: result = handleFloatRange(f, a) of tyFloat32: result = handleFloatRange(f, a) of tyFloat64: result = handleFloatRange(f, a) diff --git a/compiler/types.nim b/compiler/types.nim index ecc250a5ac..fb0e9a123f 100755 --- a/compiler/types.nim +++ b/compiler/types.nim @@ -141,7 +141,7 @@ proc skipTypes(t: PType, kinds: TTypeKinds): PType = proc isOrdinalType(t: PType): bool = assert(t != nil) - result = (t.Kind in {tyChar, tyInt..tyInt64, tyBool, tyEnum}) or + result = (t.Kind in {tyChar, tyInt..tyInt64, tyUInt..tyUInt64, tyBool, tyEnum}) or (t.Kind in {tyRange, tyOrdinal, tyConst, tyMutable, tyGenericInst}) and isOrdinalType(t.sons[0]) @@ -386,10 +386,11 @@ proc TypeToString(typ: PType, prefer: TPreferedDesc = preferName): string = "GenericInvokation", "GenericBody", "GenericInst", "GenericParam", "distinct $1", "enum", "ordinal[$1]", "array[$1, $2]", "object", "tuple", "set[$1]", "range[$1]", "ptr ", "ref ", "var ", "seq[$1]", "proc", - "pointer", "OpenArray[$1]", "string", "CString", "Forward", "int", "int8", - "int16", "int32", "int64", "float", "float32", "float64", "float128", - - "uint", "uint8", "uint16", "uint32", "uint64", "bignum", "const ", + "pointer", "OpenArray[$1]", "string", "CString", "Forward", + "int", "int8", "int16", "int32", "int64", + "float", "float32", "float64", "float128", + "uint", "uint8", "uint16", "uint32", "uint64", + "bignum", "const ", "!", "varargs[$1]", "iter[$1]", "proxy[$1]", "TypeClass" ] var t = typ result = "" @@ -494,6 +495,7 @@ proc firstOrd(t: PType): biggestInt = of tyInt16: result = - 32768 of tyInt32: result = - 2147483646 - 2 of tyInt64: result = 0x8000000000000000'i64 + of tyUInt..tyUInt64: result = 0 of tyEnum: # if basetype <> nil then return firstOrd of basetype if (sonsLen(t) > 0) and (t.sons[0] != nil): @@ -524,6 +526,13 @@ proc lastOrd(t: PType): biggestInt = of tyInt16: result = 0x00007FFF of tyInt32: result = 0x7FFFFFFF of tyInt64: result = 0x7FFFFFFFFFFFFFFF'i64 + of tyUInt: + if platform.intSize == 4: result = 0xFFFFFFFF + else: result = 0x7FFFFFFFFFFFFFFF'i64 + of tyUInt8: result = 0x7F # XXX: Fix these + of tyUInt16: result = 0x7FFF + of tyUInt32: result = 0x7FFFFFFF + of tyUInt64: result = 0x7FFFFFFFFFFFFFFF'i64 of tyEnum: assert(t.n.sons[sonsLen(t.n) - 1].kind == nkSym) result = t.n.sons[sonsLen(t.n) - 1].sym.position @@ -980,6 +989,9 @@ proc computeSizeAux(typ: PType, a: var biggestInt): biggestInt = of tyInt64, tyUInt64, tyFloat64: result = 8 a = result + of tyFloat128: + result = 16 + a = result of tyFloat: result = floatSize a = result diff --git a/install.sh b/install.sh index fde6c82a24..4feabbb77a 100755 --- a/install.sh +++ b/install.sh @@ -1,6 +1,8 @@ #! /bin/sh # Generated by niminst +set -e + if [ $# -eq 1 ] ; then if test -f bin/nimrod then @@ -43,692 +45,573 @@ if [ $# -eq 1 ] ; then docdir="$1/nimrod/doc" datadir="$1/nimrod/data" - mkdir -p $1/nimrod || exit 1 - mkdir -p $bindir || exit 1 - mkdir -p $configdir || exit 1 + mkdir -p $1/nimrod + mkdir -p $bindir + mkdir -p $configdir ;; esac - mkdir -p $libdir || exit 1 - mkdir -p $docdir || exit 1 + mkdir -p $libdir + mkdir -p $docdir echo "copying files..." - mkdir -p $libdir/system || exit 1 - mkdir -p $libdir/core || exit 1 - mkdir -p $libdir/pure || exit 1 - mkdir -p $libdir/pure/collections || exit 1 - mkdir -p $libdir/impure || exit 1 - mkdir -p $libdir/wrappers || exit 1 - mkdir -p $libdir/wrappers/cairo || exit 1 - mkdir -p $libdir/wrappers/gtk || exit 1 - mkdir -p $libdir/wrappers/lua || exit 1 - mkdir -p $libdir/wrappers/opengl || exit 1 - mkdir -p $libdir/wrappers/sdl || exit 1 - mkdir -p $libdir/wrappers/x11 || exit 1 - mkdir -p $libdir/wrappers/zip || exit 1 - mkdir -p $libdir/windows || exit 1 - mkdir -p $libdir/posix || exit 1 - mkdir -p $libdir/ecmas || exit 1 + mkdir -p $libdir/system + mkdir -p $libdir/core + mkdir -p $libdir/pure + mkdir -p $libdir/pure/collections + mkdir -p $libdir/impure + mkdir -p $libdir/wrappers + mkdir -p $libdir/wrappers/cairo + mkdir -p $libdir/wrappers/gtk + mkdir -p $libdir/wrappers/lua + mkdir -p $libdir/wrappers/opengl + mkdir -p $libdir/wrappers/readline + mkdir -p $libdir/wrappers/sdl + mkdir -p $libdir/wrappers/x11 + mkdir -p $libdir/wrappers/zip + mkdir -p $libdir/windows + mkdir -p $libdir/posix + mkdir -p $libdir/ecmas - cp bin/nimrod $bindir/nimrod || exit 1 + cp bin/nimrod $bindir/nimrod chmod 755 $bindir/nimrod - cp config/nimrod.cfg $configdir/nimrod.cfg || exit 1 + cp config/nimrod.cfg $configdir/nimrod.cfg chmod 644 $configdir/nimrod.cfg - cp config/nimdoc.cfg $configdir/nimdoc.cfg || exit 1 + cp config/nimdoc.cfg $configdir/nimdoc.cfg chmod 644 $configdir/nimdoc.cfg - cp config/nimdoc.tex.cfg $configdir/nimdoc.tex.cfg || exit 1 + cp config/nimdoc.tex.cfg $configdir/nimdoc.tex.cfg chmod 644 $configdir/nimdoc.tex.cfg - cp doc/abstypes.txt $docdir/abstypes.txt || exit 1 - chmod 644 $docdir/abstypes.txt - cp doc/advopt.txt $docdir/advopt.txt || exit 1 - chmod 644 $docdir/advopt.txt - cp doc/apis.txt $docdir/apis.txt || exit 1 - chmod 644 $docdir/apis.txt - cp doc/astspec.txt $docdir/astspec.txt || exit 1 - chmod 644 $docdir/astspec.txt - cp doc/basicopt.txt $docdir/basicopt.txt || exit 1 - chmod 644 $docdir/basicopt.txt - cp doc/c2nim.txt $docdir/c2nim.txt || exit 1 - chmod 644 $docdir/c2nim.txt - cp doc/docs.txt $docdir/docs.txt || exit 1 - chmod 644 $docdir/docs.txt - cp doc/effects.txt $docdir/effects.txt || exit 1 - chmod 644 $docdir/effects.txt - cp doc/endb.txt $docdir/endb.txt || exit 1 - chmod 644 $docdir/endb.txt - cp doc/filelist.txt $docdir/filelist.txt || exit 1 - chmod 644 $docdir/filelist.txt - cp doc/filters.txt $docdir/filters.txt || exit 1 - chmod 644 $docdir/filters.txt - cp doc/grammar.txt $docdir/grammar.txt || exit 1 - chmod 644 $docdir/grammar.txt - cp doc/intern.txt $docdir/intern.txt || exit 1 - chmod 644 $docdir/intern.txt - cp doc/keywords.txt $docdir/keywords.txt || exit 1 - chmod 644 $docdir/keywords.txt - cp doc/lib.txt $docdir/lib.txt || exit 1 - chmod 644 $docdir/lib.txt - cp doc/manual.txt $docdir/manual.txt || exit 1 - chmod 644 $docdir/manual.txt - cp doc/niminst.txt $docdir/niminst.txt || exit 1 - chmod 644 $docdir/niminst.txt - cp doc/nimrodc.txt $docdir/nimrodc.txt || exit 1 - chmod 644 $docdir/nimrodc.txt - cp doc/overview.txt $docdir/overview.txt || exit 1 - chmod 644 $docdir/overview.txt - cp doc/pegdocs.txt $docdir/pegdocs.txt || exit 1 - chmod 644 $docdir/pegdocs.txt - cp doc/readme.txt $docdir/readme.txt || exit 1 - chmod 644 $docdir/readme.txt - cp doc/regexprs.txt $docdir/regexprs.txt || exit 1 - chmod 644 $docdir/regexprs.txt - cp doc/rst.txt $docdir/rst.txt || exit 1 - chmod 644 $docdir/rst.txt - cp doc/subexes.txt $docdir/subexes.txt || exit 1 - chmod 644 $docdir/subexes.txt - cp doc/targets.txt $docdir/targets.txt || exit 1 - chmod 644 $docdir/targets.txt - cp doc/theindex.txt $docdir/theindex.txt || exit 1 - chmod 644 $docdir/theindex.txt - cp doc/tools.txt $docdir/tools.txt || exit 1 - chmod 644 $docdir/tools.txt - cp doc/tut1.txt $docdir/tut1.txt || exit 1 - chmod 644 $docdir/tut1.txt - cp doc/tut2.txt $docdir/tut2.txt || exit 1 - chmod 644 $docdir/tut2.txt - cp doc/actors.html $docdir/actors.html || exit 1 - chmod 644 $docdir/actors.html - cp doc/algorithm.html $docdir/algorithm.html || exit 1 - chmod 644 $docdir/algorithm.html - cp doc/apis.html $docdir/apis.html || exit 1 - chmod 644 $docdir/apis.html - cp doc/asyncio.html $docdir/asyncio.html || exit 1 - chmod 644 $docdir/asyncio.html - cp doc/base64.html $docdir/base64.html || exit 1 - chmod 644 $docdir/base64.html - cp doc/browsers.html $docdir/browsers.html || exit 1 - chmod 644 $docdir/browsers.html - cp doc/c2nim.html $docdir/c2nim.html || exit 1 - chmod 644 $docdir/c2nim.html - cp doc/cgi.html $docdir/cgi.html || exit 1 - chmod 644 $docdir/cgi.html - cp doc/channels.html $docdir/channels.html || exit 1 - chmod 644 $docdir/channels.html - cp doc/colors.html $docdir/colors.html || exit 1 - chmod 644 $docdir/colors.html - cp doc/complex.html $docdir/complex.html || exit 1 - chmod 644 $docdir/complex.html - cp doc/critbits.html $docdir/critbits.html || exit 1 - chmod 644 $docdir/critbits.html - cp doc/db_mysql.html $docdir/db_mysql.html || exit 1 - chmod 644 $docdir/db_mysql.html - cp doc/db_postgres.html $docdir/db_postgres.html || exit 1 - chmod 644 $docdir/db_postgres.html - cp doc/db_sqlite.html $docdir/db_sqlite.html || exit 1 - chmod 644 $docdir/db_sqlite.html - cp doc/dom.html $docdir/dom.html || exit 1 - chmod 644 $docdir/dom.html - cp doc/dynlib.html $docdir/dynlib.html || exit 1 - chmod 644 $docdir/dynlib.html - cp doc/encodings.html $docdir/encodings.html || exit 1 - chmod 644 $docdir/encodings.html - cp doc/endb.html $docdir/endb.html || exit 1 - chmod 644 $docdir/endb.html - cp doc/events.html $docdir/events.html || exit 1 - chmod 644 $docdir/events.html - cp doc/filters.html $docdir/filters.html || exit 1 - chmod 644 $docdir/filters.html - cp doc/ftpclient.html $docdir/ftpclient.html || exit 1 - chmod 644 $docdir/ftpclient.html - cp doc/graphics.html $docdir/graphics.html || exit 1 - chmod 644 $docdir/graphics.html - cp doc/hashes.html $docdir/hashes.html || exit 1 - chmod 644 $docdir/hashes.html - cp doc/htmlgen.html $docdir/htmlgen.html || exit 1 - chmod 644 $docdir/htmlgen.html - cp doc/htmlparser.html $docdir/htmlparser.html || exit 1 - chmod 644 $docdir/htmlparser.html - cp doc/httpclient.html $docdir/httpclient.html || exit 1 - chmod 644 $docdir/httpclient.html - cp doc/httpserver.html $docdir/httpserver.html || exit 1 - chmod 644 $docdir/httpserver.html - cp doc/intern.html $docdir/intern.html || exit 1 - chmod 644 $docdir/intern.html - cp doc/intsets.html $docdir/intsets.html || exit 1 - chmod 644 $docdir/intsets.html - cp doc/irc.html $docdir/irc.html || exit 1 - chmod 644 $docdir/irc.html - cp doc/json.html $docdir/json.html || exit 1 - chmod 644 $docdir/json.html - cp doc/lexbase.html $docdir/lexbase.html || exit 1 - chmod 644 $docdir/lexbase.html - cp doc/lib.html $docdir/lib.html || exit 1 - chmod 644 $docdir/lib.html - cp doc/lists.html $docdir/lists.html || exit 1 - chmod 644 $docdir/lists.html - cp doc/locks.html $docdir/locks.html || exit 1 - chmod 644 $docdir/locks.html - cp doc/macros.html $docdir/macros.html || exit 1 - chmod 644 $docdir/macros.html - cp doc/manual.html $docdir/manual.html || exit 1 - chmod 644 $docdir/manual.html - cp doc/marshal.html $docdir/marshal.html || exit 1 - chmod 644 $docdir/marshal.html - cp doc/matchers.html $docdir/matchers.html || exit 1 - chmod 644 $docdir/matchers.html - cp doc/math.html $docdir/math.html || exit 1 - chmod 644 $docdir/math.html - cp doc/memfiles.html $docdir/memfiles.html || exit 1 - chmod 644 $docdir/memfiles.html - cp doc/niminst.html $docdir/niminst.html || exit 1 - chmod 644 $docdir/niminst.html - cp doc/nimrodc.html $docdir/nimrodc.html || exit 1 - chmod 644 $docdir/nimrodc.html - cp doc/os.html $docdir/os.html || exit 1 - chmod 644 $docdir/os.html - cp doc/osproc.html $docdir/osproc.html || exit 1 - chmod 644 $docdir/osproc.html - cp doc/overview.html $docdir/overview.html || exit 1 - chmod 644 $docdir/overview.html - cp doc/parsecfg.html $docdir/parsecfg.html || exit 1 - chmod 644 $docdir/parsecfg.html - cp doc/parsecsv.html $docdir/parsecsv.html || exit 1 - chmod 644 $docdir/parsecsv.html - cp doc/parseopt.html $docdir/parseopt.html || exit 1 - chmod 644 $docdir/parseopt.html - cp doc/parsesql.html $docdir/parsesql.html || exit 1 - chmod 644 $docdir/parsesql.html - cp doc/parseutils.html $docdir/parseutils.html || exit 1 - chmod 644 $docdir/parseutils.html - cp doc/parsexml.html $docdir/parsexml.html || exit 1 - chmod 644 $docdir/parsexml.html - cp doc/pegs.html $docdir/pegs.html || exit 1 - chmod 644 $docdir/pegs.html - cp doc/queues.html $docdir/queues.html || exit 1 - chmod 644 $docdir/queues.html - cp doc/rdstdin.html $docdir/rdstdin.html || exit 1 - chmod 644 $docdir/rdstdin.html - cp doc/re.html $docdir/re.html || exit 1 - chmod 644 $docdir/re.html - cp doc/redis.html $docdir/redis.html || exit 1 - chmod 644 $docdir/redis.html - cp doc/ropes.html $docdir/ropes.html || exit 1 - chmod 644 $docdir/ropes.html - cp doc/scgi.html $docdir/scgi.html || exit 1 - chmod 644 $docdir/scgi.html - cp doc/sequtils.html $docdir/sequtils.html || exit 1 - chmod 644 $docdir/sequtils.html - cp doc/sets.html $docdir/sets.html || exit 1 - chmod 644 $docdir/sets.html - cp doc/smtp.html $docdir/smtp.html || exit 1 - chmod 644 $docdir/smtp.html - cp doc/sockets.html $docdir/sockets.html || exit 1 - chmod 644 $docdir/sockets.html - cp doc/sphinx.html $docdir/sphinx.html || exit 1 - chmod 644 $docdir/sphinx.html - cp doc/ssl.html $docdir/ssl.html || exit 1 - chmod 644 $docdir/ssl.html - cp doc/streams.html $docdir/streams.html || exit 1 - chmod 644 $docdir/streams.html - cp doc/strtabs.html $docdir/strtabs.html || exit 1 - chmod 644 $docdir/strtabs.html - cp doc/strutils.html $docdir/strutils.html || exit 1 - chmod 644 $docdir/strutils.html - cp doc/subexes.html $docdir/subexes.html || exit 1 - chmod 644 $docdir/subexes.html - cp doc/system.html $docdir/system.html || exit 1 - chmod 644 $docdir/system.html - cp doc/tables.html $docdir/tables.html || exit 1 - chmod 644 $docdir/tables.html - cp doc/terminal.html $docdir/terminal.html || exit 1 - chmod 644 $docdir/terminal.html - cp doc/theindex.html $docdir/theindex.html || exit 1 - chmod 644 $docdir/theindex.html - cp doc/threads.html $docdir/threads.html || exit 1 - chmod 644 $docdir/threads.html - cp doc/times.html $docdir/times.html || exit 1 - chmod 644 $docdir/times.html - cp doc/tools.html $docdir/tools.html || exit 1 - chmod 644 $docdir/tools.html - cp doc/tut1.html $docdir/tut1.html || exit 1 - chmod 644 $docdir/tut1.html - cp doc/tut2.html $docdir/tut2.html || exit 1 - chmod 644 $docdir/tut2.html - cp doc/typeinfo.html $docdir/typeinfo.html || exit 1 - chmod 644 $docdir/typeinfo.html - cp doc/unicode.html $docdir/unicode.html || exit 1 - chmod 644 $docdir/unicode.html - cp doc/unidecode.html $docdir/unidecode.html || exit 1 - chmod 644 $docdir/unidecode.html - cp doc/web.html $docdir/web.html || exit 1 - chmod 644 $docdir/web.html - cp doc/xmldom.html $docdir/xmldom.html || exit 1 - chmod 644 $docdir/xmldom.html - cp doc/xmldomparser.html $docdir/xmldomparser.html || exit 1 - chmod 644 $docdir/xmldomparser.html - cp doc/xmlparser.html $docdir/xmlparser.html || exit 1 - chmod 644 $docdir/xmlparser.html - cp doc/xmltree.html $docdir/xmltree.html || exit 1 - chmod 644 $docdir/xmltree.html - cp doc/zipfiles.html $docdir/zipfiles.html || exit 1 - chmod 644 $docdir/zipfiles.html - cp doc/zmq.html $docdir/zmq.html || exit 1 - chmod 644 $docdir/zmq.html - cp doc/mytest.cfg $docdir/mytest.cfg || exit 1 - chmod 644 $docdir/mytest.cfg - cp doc/c2nim.pdf $docdir/c2nim.pdf || exit 1 - chmod 644 $docdir/c2nim.pdf - cp doc/lib.pdf $docdir/lib.pdf || exit 1 - chmod 644 $docdir/lib.pdf - cp doc/manual.pdf $docdir/manual.pdf || exit 1 - chmod 644 $docdir/manual.pdf - cp doc/niminst.pdf $docdir/niminst.pdf || exit 1 - chmod 644 $docdir/niminst.pdf - cp doc/nimrodc.pdf $docdir/nimrodc.pdf || exit 1 - chmod 644 $docdir/nimrodc.pdf - cp doc/tut1.pdf $docdir/tut1.pdf || exit 1 - chmod 644 $docdir/tut1.pdf - cp doc/tut2.pdf $docdir/tut2.pdf || exit 1 - chmod 644 $docdir/tut2.pdf - cp doc/nimrod.ini $docdir/nimrod.ini || exit 1 - chmod 644 $docdir/nimrod.ini - cp lib/nimbase.h $libdir/nimbase.h || exit 1 + if [ -f doc/abstypes.txt ]; then + cp doc/abstypes.txt $docdir/abstypes.txt + chmod 644 $docdir/abstypes.txt + fi + if [ -f doc/advopt.txt ]; then + cp doc/advopt.txt $docdir/advopt.txt + chmod 644 $docdir/advopt.txt + fi + if [ -f doc/apis.txt ]; then + cp doc/apis.txt $docdir/apis.txt + chmod 644 $docdir/apis.txt + fi + if [ -f doc/astspec.txt ]; then + cp doc/astspec.txt $docdir/astspec.txt + chmod 644 $docdir/astspec.txt + fi + if [ -f doc/basicopt.txt ]; then + cp doc/basicopt.txt $docdir/basicopt.txt + chmod 644 $docdir/basicopt.txt + fi + if [ -f doc/c2nim.txt ]; then + cp doc/c2nim.txt $docdir/c2nim.txt + chmod 644 $docdir/c2nim.txt + fi + if [ -f doc/docs.txt ]; then + cp doc/docs.txt $docdir/docs.txt + chmod 644 $docdir/docs.txt + fi + if [ -f doc/effects.txt ]; then + cp doc/effects.txt $docdir/effects.txt + chmod 644 $docdir/effects.txt + fi + if [ -f doc/endb.txt ]; then + cp doc/endb.txt $docdir/endb.txt + chmod 644 $docdir/endb.txt + fi + if [ -f doc/filelist.txt ]; then + cp doc/filelist.txt $docdir/filelist.txt + chmod 644 $docdir/filelist.txt + fi + if [ -f doc/filters.txt ]; then + cp doc/filters.txt $docdir/filters.txt + chmod 644 $docdir/filters.txt + fi + if [ -f doc/gc.txt ]; then + cp doc/gc.txt $docdir/gc.txt + chmod 644 $docdir/gc.txt + fi + if [ -f doc/grammar.txt ]; then + cp doc/grammar.txt $docdir/grammar.txt + chmod 644 $docdir/grammar.txt + fi + if [ -f doc/intern.txt ]; then + cp doc/intern.txt $docdir/intern.txt + chmod 644 $docdir/intern.txt + fi + if [ -f doc/keywords.txt ]; then + cp doc/keywords.txt $docdir/keywords.txt + chmod 644 $docdir/keywords.txt + fi + if [ -f doc/lib.txt ]; then + cp doc/lib.txt $docdir/lib.txt + chmod 644 $docdir/lib.txt + fi + if [ -f doc/manual.txt ]; then + cp doc/manual.txt $docdir/manual.txt + chmod 644 $docdir/manual.txt + fi + if [ -f doc/nimgrep.txt ]; then + cp doc/nimgrep.txt $docdir/nimgrep.txt + chmod 644 $docdir/nimgrep.txt + fi + if [ -f doc/niminst.txt ]; then + cp doc/niminst.txt $docdir/niminst.txt + chmod 644 $docdir/niminst.txt + fi + if [ -f doc/nimrodc.txt ]; then + cp doc/nimrodc.txt $docdir/nimrodc.txt + chmod 644 $docdir/nimrodc.txt + fi + if [ -f doc/overview.txt ]; then + cp doc/overview.txt $docdir/overview.txt + chmod 644 $docdir/overview.txt + fi + if [ -f doc/pegdocs.txt ]; then + cp doc/pegdocs.txt $docdir/pegdocs.txt + chmod 644 $docdir/pegdocs.txt + fi + if [ -f doc/readme.txt ]; then + cp doc/readme.txt $docdir/readme.txt + chmod 644 $docdir/readme.txt + fi + if [ -f doc/regexprs.txt ]; then + cp doc/regexprs.txt $docdir/regexprs.txt + chmod 644 $docdir/regexprs.txt + fi + if [ -f doc/rst.txt ]; then + cp doc/rst.txt $docdir/rst.txt + chmod 644 $docdir/rst.txt + fi + if [ -f doc/subexes.txt ]; then + cp doc/subexes.txt $docdir/subexes.txt + chmod 644 $docdir/subexes.txt + fi + if [ -f doc/tools.txt ]; then + cp doc/tools.txt $docdir/tools.txt + chmod 644 $docdir/tools.txt + fi + if [ -f doc/tut1.txt ]; then + cp doc/tut1.txt $docdir/tut1.txt + chmod 644 $docdir/tut1.txt + fi + if [ -f doc/tut2.txt ]; then + cp doc/tut2.txt $docdir/tut2.txt + chmod 644 $docdir/tut2.txt + fi + if [ -f doc/mytest.cfg ]; then + cp doc/mytest.cfg $docdir/mytest.cfg + chmod 644 $docdir/mytest.cfg + fi + cp lib/nimbase.h $libdir/nimbase.h chmod 644 $libdir/nimbase.h - cp lib/cycle.h $libdir/cycle.h || exit 1 + cp lib/cycle.h $libdir/cycle.h chmod 644 $libdir/cycle.h - cp lib/nimrtl.nim $libdir/nimrtl.nim || exit 1 + cp lib/nimrtl.nim $libdir/nimrtl.nim chmod 644 $libdir/nimrtl.nim - cp lib/prelude.nim $libdir/prelude.nim || exit 1 + cp lib/prelude.nim $libdir/prelude.nim chmod 644 $libdir/prelude.nim - cp lib/system.nim $libdir/system.nim || exit 1 + cp lib/system.nim $libdir/system.nim chmod 644 $libdir/system.nim - cp lib/nimrtl.nimrod.cfg $libdir/nimrtl.nimrod.cfg || exit 1 + cp lib/nimrtl.nimrod.cfg $libdir/nimrtl.nimrod.cfg chmod 644 $libdir/nimrtl.nimrod.cfg - cp lib/system/alloc.nim $libdir/system/alloc.nim || exit 1 + cp lib/system/alloc.nim $libdir/system/alloc.nim chmod 644 $libdir/system/alloc.nim - cp lib/system/ansi_c.nim $libdir/system/ansi_c.nim || exit 1 + cp lib/system/ansi_c.nim $libdir/system/ansi_c.nim chmod 644 $libdir/system/ansi_c.nim - cp lib/system/arithm.nim $libdir/system/arithm.nim || exit 1 + cp lib/system/arithm.nim $libdir/system/arithm.nim chmod 644 $libdir/system/arithm.nim - cp lib/system/assign.nim $libdir/system/assign.nim || exit 1 + cp lib/system/assign.nim $libdir/system/assign.nim chmod 644 $libdir/system/assign.nim - cp lib/system/atomics.nim $libdir/system/atomics.nim || exit 1 + cp lib/system/atomics.nim $libdir/system/atomics.nim chmod 644 $libdir/system/atomics.nim - cp lib/system/avltree.nim $libdir/system/avltree.nim || exit 1 + cp lib/system/avltree.nim $libdir/system/avltree.nim chmod 644 $libdir/system/avltree.nim - cp lib/system/cellsets.nim $libdir/system/cellsets.nim || exit 1 + cp lib/system/cellsets.nim $libdir/system/cellsets.nim chmod 644 $libdir/system/cellsets.nim - cp lib/system/cgprocs.nim $libdir/system/cgprocs.nim || exit 1 + cp lib/system/cgprocs.nim $libdir/system/cgprocs.nim chmod 644 $libdir/system/cgprocs.nim - cp lib/system/channels.nim $libdir/system/channels.nim || exit 1 + cp lib/system/channels.nim $libdir/system/channels.nim chmod 644 $libdir/system/channels.nim - cp lib/system/debugger.nim $libdir/system/debugger.nim || exit 1 + cp lib/system/debugger.nim $libdir/system/debugger.nim chmod 644 $libdir/system/debugger.nim - cp lib/system/dyncalls.nim $libdir/system/dyncalls.nim || exit 1 + cp lib/system/dyncalls.nim $libdir/system/dyncalls.nim chmod 644 $libdir/system/dyncalls.nim - cp lib/system/ecmasys.nim $libdir/system/ecmasys.nim || exit 1 + cp lib/system/ecmasys.nim $libdir/system/ecmasys.nim chmod 644 $libdir/system/ecmasys.nim - cp lib/system/embedded.nim $libdir/system/embedded.nim || exit 1 + cp lib/system/embedded.nim $libdir/system/embedded.nim chmod 644 $libdir/system/embedded.nim - cp lib/system/excpt.nim $libdir/system/excpt.nim || exit 1 + cp lib/system/excpt.nim $libdir/system/excpt.nim chmod 644 $libdir/system/excpt.nim - cp lib/system/gc.nim $libdir/system/gc.nim || exit 1 + cp lib/system/gc.nim $libdir/system/gc.nim chmod 644 $libdir/system/gc.nim - cp lib/system/hti.nim $libdir/system/hti.nim || exit 1 + cp lib/system/hti.nim $libdir/system/hti.nim chmod 644 $libdir/system/hti.nim - cp lib/system/inclrtl.nim $libdir/system/inclrtl.nim || exit 1 + cp lib/system/inclrtl.nim $libdir/system/inclrtl.nim chmod 644 $libdir/system/inclrtl.nim - cp lib/system/mmdisp.nim $libdir/system/mmdisp.nim || exit 1 + cp lib/system/mmdisp.nim $libdir/system/mmdisp.nim chmod 644 $libdir/system/mmdisp.nim - cp lib/system/profiler.nim $libdir/system/profiler.nim || exit 1 + cp lib/system/profiler.nim $libdir/system/profiler.nim chmod 644 $libdir/system/profiler.nim - cp lib/system/repr.nim $libdir/system/repr.nim || exit 1 + cp lib/system/repr.nim $libdir/system/repr.nim chmod 644 $libdir/system/repr.nim - cp lib/system/reprjs.nim $libdir/system/reprjs.nim || exit 1 + cp lib/system/reprjs.nim $libdir/system/reprjs.nim chmod 644 $libdir/system/reprjs.nim - cp lib/system/sets.nim $libdir/system/sets.nim || exit 1 + cp lib/system/sets.nim $libdir/system/sets.nim chmod 644 $libdir/system/sets.nim - cp lib/system/sysio.nim $libdir/system/sysio.nim || exit 1 + cp lib/system/sysio.nim $libdir/system/sysio.nim chmod 644 $libdir/system/sysio.nim - cp lib/system/syslocks.nim $libdir/system/syslocks.nim || exit 1 + cp lib/system/syslocks.nim $libdir/system/syslocks.nim chmod 644 $libdir/system/syslocks.nim - cp lib/system/sysstr.nim $libdir/system/sysstr.nim || exit 1 + cp lib/system/sysstr.nim $libdir/system/sysstr.nim chmod 644 $libdir/system/sysstr.nim - cp lib/system/threads.nim $libdir/system/threads.nim || exit 1 + cp lib/system/threads.nim $libdir/system/threads.nim chmod 644 $libdir/system/threads.nim - cp lib/system/widestrs.nim $libdir/system/widestrs.nim || exit 1 + cp lib/system/timers.nim $libdir/system/timers.nim + chmod 644 $libdir/system/timers.nim + cp lib/system/widestrs.nim $libdir/system/widestrs.nim chmod 644 $libdir/system/widestrs.nim - cp lib/core/locks.nim $libdir/core/locks.nim || exit 1 + cp lib/core/locks.nim $libdir/core/locks.nim chmod 644 $libdir/core/locks.nim - cp lib/core/macros.nim $libdir/core/macros.nim || exit 1 + cp lib/core/macros.nim $libdir/core/macros.nim chmod 644 $libdir/core/macros.nim - cp lib/core/typeinfo.nim $libdir/core/typeinfo.nim || exit 1 + cp lib/core/typeinfo.nim $libdir/core/typeinfo.nim chmod 644 $libdir/core/typeinfo.nim - cp lib/pure/actors.nim $libdir/pure/actors.nim || exit 1 + cp lib/pure/actors.nim $libdir/pure/actors.nim chmod 644 $libdir/pure/actors.nim - cp lib/pure/algorithm.nim $libdir/pure/algorithm.nim || exit 1 + cp lib/pure/algorithm.nim $libdir/pure/algorithm.nim chmod 644 $libdir/pure/algorithm.nim - cp lib/pure/asyncio.nim $libdir/pure/asyncio.nim || exit 1 + cp lib/pure/asyncio.nim $libdir/pure/asyncio.nim chmod 644 $libdir/pure/asyncio.nim - cp lib/pure/base64.nim $libdir/pure/base64.nim || exit 1 + cp lib/pure/base64.nim $libdir/pure/base64.nim chmod 644 $libdir/pure/base64.nim - cp lib/pure/browsers.nim $libdir/pure/browsers.nim || exit 1 + cp lib/pure/browsers.nim $libdir/pure/browsers.nim chmod 644 $libdir/pure/browsers.nim - cp lib/pure/bson.nim $libdir/pure/bson.nim || exit 1 - chmod 644 $libdir/pure/bson.nim - cp lib/pure/cgi.nim $libdir/pure/cgi.nim || exit 1 + cp lib/pure/cgi.nim $libdir/pure/cgi.nim chmod 644 $libdir/pure/cgi.nim - cp lib/pure/colors.nim $libdir/pure/colors.nim || exit 1 + cp lib/pure/colors.nim $libdir/pure/colors.nim chmod 644 $libdir/pure/colors.nim - cp lib/pure/complex.nim $libdir/pure/complex.nim || exit 1 + cp lib/pure/complex.nim $libdir/pure/complex.nim chmod 644 $libdir/pure/complex.nim - cp lib/pure/cookies.nim $libdir/pure/cookies.nim || exit 1 + cp lib/pure/cookies.nim $libdir/pure/cookies.nim chmod 644 $libdir/pure/cookies.nim - cp lib/pure/dynlib.nim $libdir/pure/dynlib.nim || exit 1 + cp lib/pure/dynlib.nim $libdir/pure/dynlib.nim chmod 644 $libdir/pure/dynlib.nim - cp lib/pure/encodings.nim $libdir/pure/encodings.nim || exit 1 + cp lib/pure/encodings.nim $libdir/pure/encodings.nim chmod 644 $libdir/pure/encodings.nim - cp lib/pure/endians.nim $libdir/pure/endians.nim || exit 1 + cp lib/pure/endians.nim $libdir/pure/endians.nim chmod 644 $libdir/pure/endians.nim - cp lib/pure/events.nim $libdir/pure/events.nim || exit 1 + cp lib/pure/events.nim $libdir/pure/events.nim chmod 644 $libdir/pure/events.nim - cp lib/pure/ftpclient.nim $libdir/pure/ftpclient.nim || exit 1 + cp lib/pure/ftpclient.nim $libdir/pure/ftpclient.nim chmod 644 $libdir/pure/ftpclient.nim - cp lib/pure/gentabs.nim $libdir/pure/gentabs.nim || exit 1 + cp lib/pure/gentabs.nim $libdir/pure/gentabs.nim chmod 644 $libdir/pure/gentabs.nim - cp lib/pure/hashes.nim $libdir/pure/hashes.nim || exit 1 + cp lib/pure/hashes.nim $libdir/pure/hashes.nim chmod 644 $libdir/pure/hashes.nim - cp lib/pure/htmlgen.nim $libdir/pure/htmlgen.nim || exit 1 + cp lib/pure/htmlgen.nim $libdir/pure/htmlgen.nim chmod 644 $libdir/pure/htmlgen.nim - cp lib/pure/htmlparser.nim $libdir/pure/htmlparser.nim || exit 1 + cp lib/pure/htmlparser.nim $libdir/pure/htmlparser.nim chmod 644 $libdir/pure/htmlparser.nim - cp lib/pure/httpclient.nim $libdir/pure/httpclient.nim || exit 1 + cp lib/pure/httpclient.nim $libdir/pure/httpclient.nim chmod 644 $libdir/pure/httpclient.nim - cp lib/pure/httpserver.nim $libdir/pure/httpserver.nim || exit 1 + cp lib/pure/httpserver.nim $libdir/pure/httpserver.nim chmod 644 $libdir/pure/httpserver.nim - cp lib/pure/irc.nim $libdir/pure/irc.nim || exit 1 + cp lib/pure/irc.nim $libdir/pure/irc.nim chmod 644 $libdir/pure/irc.nim - cp lib/pure/json.nim $libdir/pure/json.nim || exit 1 + cp lib/pure/json.nim $libdir/pure/json.nim chmod 644 $libdir/pure/json.nim - cp lib/pure/lexbase.nim $libdir/pure/lexbase.nim || exit 1 + cp lib/pure/lexbase.nim $libdir/pure/lexbase.nim chmod 644 $libdir/pure/lexbase.nim - cp lib/pure/marshal.nim $libdir/pure/marshal.nim || exit 1 + cp lib/pure/marshal.nim $libdir/pure/marshal.nim chmod 644 $libdir/pure/marshal.nim - cp lib/pure/matchers.nim $libdir/pure/matchers.nim || exit 1 + cp lib/pure/matchers.nim $libdir/pure/matchers.nim chmod 644 $libdir/pure/matchers.nim - cp lib/pure/math.nim $libdir/pure/math.nim || exit 1 + cp lib/pure/math.nim $libdir/pure/math.nim chmod 644 $libdir/pure/math.nim - cp lib/pure/md5.nim $libdir/pure/md5.nim || exit 1 + cp lib/pure/md5.nim $libdir/pure/md5.nim chmod 644 $libdir/pure/md5.nim - cp lib/pure/memfiles.nim $libdir/pure/memfiles.nim || exit 1 + cp lib/pure/memfiles.nim $libdir/pure/memfiles.nim chmod 644 $libdir/pure/memfiles.nim - cp lib/pure/oids.nim $libdir/pure/oids.nim || exit 1 + cp lib/pure/mimetypes.nim $libdir/pure/mimetypes.nim + chmod 644 $libdir/pure/mimetypes.nim + cp lib/pure/oids.nim $libdir/pure/oids.nim chmod 644 $libdir/pure/oids.nim - cp lib/pure/os.nim $libdir/pure/os.nim || exit 1 + cp lib/pure/os.nim $libdir/pure/os.nim chmod 644 $libdir/pure/os.nim - cp lib/pure/osproc.nim $libdir/pure/osproc.nim || exit 1 + cp lib/pure/osproc.nim $libdir/pure/osproc.nim chmod 644 $libdir/pure/osproc.nim - cp lib/pure/parsecfg.nim $libdir/pure/parsecfg.nim || exit 1 + cp lib/pure/parsecfg.nim $libdir/pure/parsecfg.nim chmod 644 $libdir/pure/parsecfg.nim - cp lib/pure/parsecsv.nim $libdir/pure/parsecsv.nim || exit 1 + cp lib/pure/parsecsv.nim $libdir/pure/parsecsv.nim chmod 644 $libdir/pure/parsecsv.nim - cp lib/pure/parseopt.nim $libdir/pure/parseopt.nim || exit 1 + cp lib/pure/parseopt.nim $libdir/pure/parseopt.nim chmod 644 $libdir/pure/parseopt.nim - cp lib/pure/parsesql.nim $libdir/pure/parsesql.nim || exit 1 + cp lib/pure/parsesql.nim $libdir/pure/parsesql.nim chmod 644 $libdir/pure/parsesql.nim - cp lib/pure/parseurl.nim $libdir/pure/parseurl.nim || exit 1 + cp lib/pure/parseurl.nim $libdir/pure/parseurl.nim chmod 644 $libdir/pure/parseurl.nim - cp lib/pure/parseutils.nim $libdir/pure/parseutils.nim || exit 1 + cp lib/pure/parseutils.nim $libdir/pure/parseutils.nim chmod 644 $libdir/pure/parseutils.nim - cp lib/pure/parsexml.nim $libdir/pure/parsexml.nim || exit 1 + cp lib/pure/parsexml.nim $libdir/pure/parsexml.nim chmod 644 $libdir/pure/parsexml.nim - cp lib/pure/pegs.nim $libdir/pure/pegs.nim || exit 1 + cp lib/pure/pegs.nim $libdir/pure/pegs.nim chmod 644 $libdir/pure/pegs.nim - cp lib/pure/redis.nim $libdir/pure/redis.nim || exit 1 + cp lib/pure/redis.nim $libdir/pure/redis.nim chmod 644 $libdir/pure/redis.nim - cp lib/pure/romans.nim $libdir/pure/romans.nim || exit 1 + cp lib/pure/romans.nim $libdir/pure/romans.nim chmod 644 $libdir/pure/romans.nim - cp lib/pure/ropes.nim $libdir/pure/ropes.nim || exit 1 + cp lib/pure/ropes.nim $libdir/pure/ropes.nim chmod 644 $libdir/pure/ropes.nim - cp lib/pure/scgi.nim $libdir/pure/scgi.nim || exit 1 + cp lib/pure/scgi.nim $libdir/pure/scgi.nim chmod 644 $libdir/pure/scgi.nim - cp lib/pure/smtp.nim $libdir/pure/smtp.nim || exit 1 + cp lib/pure/smtp.nim $libdir/pure/smtp.nim chmod 644 $libdir/pure/smtp.nim - cp lib/pure/sockets.nim $libdir/pure/sockets.nim || exit 1 + cp lib/pure/sockets.nim $libdir/pure/sockets.nim chmod 644 $libdir/pure/sockets.nim - cp lib/pure/streams.nim $libdir/pure/streams.nim || exit 1 + cp lib/pure/streams.nim $libdir/pure/streams.nim chmod 644 $libdir/pure/streams.nim - cp lib/pure/strtabs.nim $libdir/pure/strtabs.nim || exit 1 + cp lib/pure/strtabs.nim $libdir/pure/strtabs.nim chmod 644 $libdir/pure/strtabs.nim - cp lib/pure/strutils.nim $libdir/pure/strutils.nim || exit 1 + cp lib/pure/strutils.nim $libdir/pure/strutils.nim chmod 644 $libdir/pure/strutils.nim - cp lib/pure/subexes.nim $libdir/pure/subexes.nim || exit 1 + cp lib/pure/subexes.nim $libdir/pure/subexes.nim chmod 644 $libdir/pure/subexes.nim - cp lib/pure/terminal.nim $libdir/pure/terminal.nim || exit 1 + cp lib/pure/templateutil.nim $libdir/pure/templateutil.nim + chmod 644 $libdir/pure/templateutil.nim + cp lib/pure/terminal.nim $libdir/pure/terminal.nim chmod 644 $libdir/pure/terminal.nim - cp lib/pure/times.nim $libdir/pure/times.nim || exit 1 + cp lib/pure/times.nim $libdir/pure/times.nim chmod 644 $libdir/pure/times.nim - cp lib/pure/unicode.nim $libdir/pure/unicode.nim || exit 1 + cp lib/pure/typetraits.nim $libdir/pure/typetraits.nim + chmod 644 $libdir/pure/typetraits.nim + cp lib/pure/unicode.nim $libdir/pure/unicode.nim chmod 644 $libdir/pure/unicode.nim - cp lib/pure/unittest.nim $libdir/pure/unittest.nim || exit 1 + cp lib/pure/unittest.nim $libdir/pure/unittest.nim chmod 644 $libdir/pure/unittest.nim - cp lib/pure/xmldom.nim $libdir/pure/xmldom.nim || exit 1 + cp lib/pure/uri.nim $libdir/pure/uri.nim + chmod 644 $libdir/pure/uri.nim + cp lib/pure/xmldom.nim $libdir/pure/xmldom.nim chmod 644 $libdir/pure/xmldom.nim - cp lib/pure/xmldomparser.nim $libdir/pure/xmldomparser.nim || exit 1 + cp lib/pure/xmldomparser.nim $libdir/pure/xmldomparser.nim chmod 644 $libdir/pure/xmldomparser.nim - cp lib/pure/xmlparser.nim $libdir/pure/xmlparser.nim || exit 1 + cp lib/pure/xmlparser.nim $libdir/pure/xmlparser.nim chmod 644 $libdir/pure/xmlparser.nim - cp lib/pure/xmltree.nim $libdir/pure/xmltree.nim || exit 1 + cp lib/pure/xmltree.nim $libdir/pure/xmltree.nim chmod 644 $libdir/pure/xmltree.nim - cp lib/pure/collections/critbits.nim $libdir/pure/collections/critbits.nim || exit 1 + cp lib/pure/collections/critbits.nim $libdir/pure/collections/critbits.nim chmod 644 $libdir/pure/collections/critbits.nim - cp lib/pure/collections/intsets.nim $libdir/pure/collections/intsets.nim || exit 1 + cp lib/pure/collections/intsets.nim $libdir/pure/collections/intsets.nim chmod 644 $libdir/pure/collections/intsets.nim - cp lib/pure/collections/lists.nim $libdir/pure/collections/lists.nim || exit 1 + cp lib/pure/collections/lists.nim $libdir/pure/collections/lists.nim chmod 644 $libdir/pure/collections/lists.nim - cp lib/pure/collections/queues.nim $libdir/pure/collections/queues.nim || exit 1 + cp lib/pure/collections/queues.nim $libdir/pure/collections/queues.nim chmod 644 $libdir/pure/collections/queues.nim - cp lib/pure/collections/sequtils.nim $libdir/pure/collections/sequtils.nim || exit 1 + cp lib/pure/collections/sequtils.nim $libdir/pure/collections/sequtils.nim chmod 644 $libdir/pure/collections/sequtils.nim - cp lib/pure/collections/sets.nim $libdir/pure/collections/sets.nim || exit 1 + cp lib/pure/collections/sets.nim $libdir/pure/collections/sets.nim chmod 644 $libdir/pure/collections/sets.nim - cp lib/pure/collections/tables.nim $libdir/pure/collections/tables.nim || exit 1 + cp lib/pure/collections/tables.nim $libdir/pure/collections/tables.nim chmod 644 $libdir/pure/collections/tables.nim - cp lib/impure/db_mysql.nim $libdir/impure/db_mysql.nim || exit 1 + cp lib/impure/db_mongo.nim $libdir/impure/db_mongo.nim + chmod 644 $libdir/impure/db_mongo.nim + cp lib/impure/db_mysql.nim $libdir/impure/db_mysql.nim chmod 644 $libdir/impure/db_mysql.nim - cp lib/impure/db_postgres.nim $libdir/impure/db_postgres.nim || exit 1 + cp lib/impure/db_postgres.nim $libdir/impure/db_postgres.nim chmod 644 $libdir/impure/db_postgres.nim - cp lib/impure/db_sqlite.nim $libdir/impure/db_sqlite.nim || exit 1 + cp lib/impure/db_sqlite.nim $libdir/impure/db_sqlite.nim chmod 644 $libdir/impure/db_sqlite.nim - cp lib/impure/dialogs.nim $libdir/impure/dialogs.nim || exit 1 + cp lib/impure/dialogs.nim $libdir/impure/dialogs.nim chmod 644 $libdir/impure/dialogs.nim - cp lib/impure/fpc.nim $libdir/impure/fpc.nim || exit 1 - chmod 644 $libdir/impure/fpc.nim - cp lib/impure/graphics.nim $libdir/impure/graphics.nim || exit 1 + cp lib/impure/graphics.nim $libdir/impure/graphics.nim chmod 644 $libdir/impure/graphics.nim - cp lib/impure/osinfo_posix.nim $libdir/impure/osinfo_posix.nim || exit 1 + cp lib/impure/osinfo_posix.nim $libdir/impure/osinfo_posix.nim chmod 644 $libdir/impure/osinfo_posix.nim - cp lib/impure/osinfo_win.nim $libdir/impure/osinfo_win.nim || exit 1 + cp lib/impure/osinfo_win.nim $libdir/impure/osinfo_win.nim chmod 644 $libdir/impure/osinfo_win.nim - cp lib/impure/rdstdin.nim $libdir/impure/rdstdin.nim || exit 1 + cp lib/impure/rdstdin.nim $libdir/impure/rdstdin.nim chmod 644 $libdir/impure/rdstdin.nim - cp lib/impure/re.nim $libdir/impure/re.nim || exit 1 + cp lib/impure/re.nim $libdir/impure/re.nim chmod 644 $libdir/impure/re.nim - cp lib/impure/ssl.nim $libdir/impure/ssl.nim || exit 1 + cp lib/impure/ssl.nim $libdir/impure/ssl.nim chmod 644 $libdir/impure/ssl.nim - cp lib/impure/web.nim $libdir/impure/web.nim || exit 1 + cp lib/impure/web.nim $libdir/impure/web.nim chmod 644 $libdir/impure/web.nim - cp lib/impure/zipfiles.nim $libdir/impure/zipfiles.nim || exit 1 + cp lib/impure/zipfiles.nim $libdir/impure/zipfiles.nim chmod 644 $libdir/impure/zipfiles.nim - cp lib/wrappers/claro.nim $libdir/wrappers/claro.nim || exit 1 + cp lib/wrappers/claro.nim $libdir/wrappers/claro.nim chmod 644 $libdir/wrappers/claro.nim - cp lib/wrappers/expat.nim $libdir/wrappers/expat.nim || exit 1 + cp lib/wrappers/expat.nim $libdir/wrappers/expat.nim chmod 644 $libdir/wrappers/expat.nim - cp lib/wrappers/iup.nim $libdir/wrappers/iup.nim || exit 1 + cp lib/wrappers/iup.nim $libdir/wrappers/iup.nim chmod 644 $libdir/wrappers/iup.nim - cp lib/wrappers/joyent_http_parser.nim $libdir/wrappers/joyent_http_parser.nim || exit 1 + cp lib/wrappers/joyent_http_parser.nim $libdir/wrappers/joyent_http_parser.nim chmod 644 $libdir/wrappers/joyent_http_parser.nim - cp lib/wrappers/libcurl.nim $libdir/wrappers/libcurl.nim || exit 1 + cp lib/wrappers/libcurl.nim $libdir/wrappers/libcurl.nim chmod 644 $libdir/wrappers/libcurl.nim - cp lib/wrappers/libsvm.nim $libdir/wrappers/libsvm.nim || exit 1 + cp lib/wrappers/libsvm.nim $libdir/wrappers/libsvm.nim chmod 644 $libdir/wrappers/libsvm.nim - cp lib/wrappers/libuv.nim $libdir/wrappers/libuv.nim || exit 1 + cp lib/wrappers/libuv.nim $libdir/wrappers/libuv.nim chmod 644 $libdir/wrappers/libuv.nim - cp lib/wrappers/mongo.nim $libdir/wrappers/mongo.nim || exit 1 + cp lib/wrappers/mongo.nim $libdir/wrappers/mongo.nim chmod 644 $libdir/wrappers/mongo.nim - cp lib/wrappers/mysql.nim $libdir/wrappers/mysql.nim || exit 1 + cp lib/wrappers/mysql.nim $libdir/wrappers/mysql.nim chmod 644 $libdir/wrappers/mysql.nim - cp lib/wrappers/odbcsql.nim $libdir/wrappers/odbcsql.nim || exit 1 + cp lib/wrappers/odbcsql.nim $libdir/wrappers/odbcsql.nim chmod 644 $libdir/wrappers/odbcsql.nim - cp lib/wrappers/openssl.nim $libdir/wrappers/openssl.nim || exit 1 + cp lib/wrappers/openssl.nim $libdir/wrappers/openssl.nim chmod 644 $libdir/wrappers/openssl.nim - cp lib/wrappers/pcre.nim $libdir/wrappers/pcre.nim || exit 1 + cp lib/wrappers/pcre.nim $libdir/wrappers/pcre.nim chmod 644 $libdir/wrappers/pcre.nim - cp lib/wrappers/postgres.nim $libdir/wrappers/postgres.nim || exit 1 + cp lib/wrappers/postgres.nim $libdir/wrappers/postgres.nim chmod 644 $libdir/wrappers/postgres.nim - cp lib/wrappers/python.nim $libdir/wrappers/python.nim || exit 1 + cp lib/wrappers/python.nim $libdir/wrappers/python.nim chmod 644 $libdir/wrappers/python.nim - cp lib/wrappers/sphinx.nim $libdir/wrappers/sphinx.nim || exit 1 + cp lib/wrappers/sphinx.nim $libdir/wrappers/sphinx.nim chmod 644 $libdir/wrappers/sphinx.nim - cp lib/wrappers/sqlite3.nim $libdir/wrappers/sqlite3.nim || exit 1 + cp lib/wrappers/sqlite3.nim $libdir/wrappers/sqlite3.nim chmod 644 $libdir/wrappers/sqlite3.nim - cp lib/wrappers/tcl.nim $libdir/wrappers/tcl.nim || exit 1 + cp lib/wrappers/tcl.nim $libdir/wrappers/tcl.nim chmod 644 $libdir/wrappers/tcl.nim - cp lib/wrappers/tinyc.nim $libdir/wrappers/tinyc.nim || exit 1 + cp lib/wrappers/tinyc.nim $libdir/wrappers/tinyc.nim chmod 644 $libdir/wrappers/tinyc.nim - cp lib/wrappers/tre.nim $libdir/wrappers/tre.nim || exit 1 + cp lib/wrappers/tre.nim $libdir/wrappers/tre.nim chmod 644 $libdir/wrappers/tre.nim - cp lib/wrappers/zmq.nim $libdir/wrappers/zmq.nim || exit 1 + cp lib/wrappers/zmq.nim $libdir/wrappers/zmq.nim chmod 644 $libdir/wrappers/zmq.nim - cp lib/wrappers/cairo/cairo.nim $libdir/wrappers/cairo/cairo.nim || exit 1 + cp lib/wrappers/cairo/cairo.nim $libdir/wrappers/cairo/cairo.nim chmod 644 $libdir/wrappers/cairo/cairo.nim - cp lib/wrappers/cairo/cairoft.nim $libdir/wrappers/cairo/cairoft.nim || exit 1 + cp lib/wrappers/cairo/cairoft.nim $libdir/wrappers/cairo/cairoft.nim chmod 644 $libdir/wrappers/cairo/cairoft.nim - cp lib/wrappers/cairo/cairowin32.nim $libdir/wrappers/cairo/cairowin32.nim || exit 1 + cp lib/wrappers/cairo/cairowin32.nim $libdir/wrappers/cairo/cairowin32.nim chmod 644 $libdir/wrappers/cairo/cairowin32.nim - cp lib/wrappers/cairo/cairoxlib.nim $libdir/wrappers/cairo/cairoxlib.nim || exit 1 + cp lib/wrappers/cairo/cairoxlib.nim $libdir/wrappers/cairo/cairoxlib.nim chmod 644 $libdir/wrappers/cairo/cairoxlib.nim - cp lib/wrappers/gtk/atk.nim $libdir/wrappers/gtk/atk.nim || exit 1 + cp lib/wrappers/gtk/atk.nim $libdir/wrappers/gtk/atk.nim chmod 644 $libdir/wrappers/gtk/atk.nim - cp lib/wrappers/gtk/gdk2.nim $libdir/wrappers/gtk/gdk2.nim || exit 1 + cp lib/wrappers/gtk/gdk2.nim $libdir/wrappers/gtk/gdk2.nim chmod 644 $libdir/wrappers/gtk/gdk2.nim - cp lib/wrappers/gtk/gdk2pixbuf.nim $libdir/wrappers/gtk/gdk2pixbuf.nim || exit 1 + cp lib/wrappers/gtk/gdk2pixbuf.nim $libdir/wrappers/gtk/gdk2pixbuf.nim chmod 644 $libdir/wrappers/gtk/gdk2pixbuf.nim - cp lib/wrappers/gtk/gdkglext.nim $libdir/wrappers/gtk/gdkglext.nim || exit 1 + cp lib/wrappers/gtk/gdkglext.nim $libdir/wrappers/gtk/gdkglext.nim chmod 644 $libdir/wrappers/gtk/gdkglext.nim - cp lib/wrappers/gtk/glib2.nim $libdir/wrappers/gtk/glib2.nim || exit 1 + cp lib/wrappers/gtk/glib2.nim $libdir/wrappers/gtk/glib2.nim chmod 644 $libdir/wrappers/gtk/glib2.nim - cp lib/wrappers/gtk/gtk2.nim $libdir/wrappers/gtk/gtk2.nim || exit 1 + cp lib/wrappers/gtk/gtk2.nim $libdir/wrappers/gtk/gtk2.nim chmod 644 $libdir/wrappers/gtk/gtk2.nim - cp lib/wrappers/gtk/gtkglext.nim $libdir/wrappers/gtk/gtkglext.nim || exit 1 + cp lib/wrappers/gtk/gtkglext.nim $libdir/wrappers/gtk/gtkglext.nim chmod 644 $libdir/wrappers/gtk/gtkglext.nim - cp lib/wrappers/gtk/gtkhtml.nim $libdir/wrappers/gtk/gtkhtml.nim || exit 1 + cp lib/wrappers/gtk/gtkhtml.nim $libdir/wrappers/gtk/gtkhtml.nim chmod 644 $libdir/wrappers/gtk/gtkhtml.nim - cp lib/wrappers/gtk/libglade2.nim $libdir/wrappers/gtk/libglade2.nim || exit 1 + cp lib/wrappers/gtk/libglade2.nim $libdir/wrappers/gtk/libglade2.nim chmod 644 $libdir/wrappers/gtk/libglade2.nim - cp lib/wrappers/gtk/pango.nim $libdir/wrappers/gtk/pango.nim || exit 1 + cp lib/wrappers/gtk/pango.nim $libdir/wrappers/gtk/pango.nim chmod 644 $libdir/wrappers/gtk/pango.nim - cp lib/wrappers/gtk/pangoutils.nim $libdir/wrappers/gtk/pangoutils.nim || exit 1 + cp lib/wrappers/gtk/pangoutils.nim $libdir/wrappers/gtk/pangoutils.nim chmod 644 $libdir/wrappers/gtk/pangoutils.nim - cp lib/wrappers/lua/lauxlib.nim $libdir/wrappers/lua/lauxlib.nim || exit 1 + cp lib/wrappers/lua/lauxlib.nim $libdir/wrappers/lua/lauxlib.nim chmod 644 $libdir/wrappers/lua/lauxlib.nim - cp lib/wrappers/lua/lua.nim $libdir/wrappers/lua/lua.nim || exit 1 + cp lib/wrappers/lua/lua.nim $libdir/wrappers/lua/lua.nim chmod 644 $libdir/wrappers/lua/lua.nim - cp lib/wrappers/lua/lualib.nim $libdir/wrappers/lua/lualib.nim || exit 1 + cp lib/wrappers/lua/lualib.nim $libdir/wrappers/lua/lualib.nim chmod 644 $libdir/wrappers/lua/lualib.nim - cp lib/wrappers/opengl/gl.nim $libdir/wrappers/opengl/gl.nim || exit 1 + cp lib/wrappers/opengl/gl.nim $libdir/wrappers/opengl/gl.nim chmod 644 $libdir/wrappers/opengl/gl.nim - cp lib/wrappers/opengl/glext.nim $libdir/wrappers/opengl/glext.nim || exit 1 + cp lib/wrappers/opengl/glext.nim $libdir/wrappers/opengl/glext.nim chmod 644 $libdir/wrappers/opengl/glext.nim - cp lib/wrappers/opengl/glu.nim $libdir/wrappers/opengl/glu.nim || exit 1 + cp lib/wrappers/opengl/glu.nim $libdir/wrappers/opengl/glu.nim chmod 644 $libdir/wrappers/opengl/glu.nim - cp lib/wrappers/opengl/glut.nim $libdir/wrappers/opengl/glut.nim || exit 1 + cp lib/wrappers/opengl/glut.nim $libdir/wrappers/opengl/glut.nim chmod 644 $libdir/wrappers/opengl/glut.nim - cp lib/wrappers/opengl/glx.nim $libdir/wrappers/opengl/glx.nim || exit 1 + cp lib/wrappers/opengl/glx.nim $libdir/wrappers/opengl/glx.nim chmod 644 $libdir/wrappers/opengl/glx.nim - cp lib/wrappers/opengl/opengl.nim $libdir/wrappers/opengl/opengl.nim || exit 1 + cp lib/wrappers/opengl/opengl.nim $libdir/wrappers/opengl/opengl.nim chmod 644 $libdir/wrappers/opengl/opengl.nim - cp lib/wrappers/opengl/wingl.nim $libdir/wrappers/opengl/wingl.nim || exit 1 + cp lib/wrappers/opengl/wingl.nim $libdir/wrappers/opengl/wingl.nim chmod 644 $libdir/wrappers/opengl/wingl.nim - cp lib/wrappers/sdl/sdl.nim $libdir/wrappers/sdl/sdl.nim || exit 1 + cp lib/wrappers/readline/history.nim $libdir/wrappers/readline/history.nim + chmod 644 $libdir/wrappers/readline/history.nim + cp lib/wrappers/readline/readline.nim $libdir/wrappers/readline/readline.nim + chmod 644 $libdir/wrappers/readline/readline.nim + cp lib/wrappers/readline/rltypedefs.nim $libdir/wrappers/readline/rltypedefs.nim + chmod 644 $libdir/wrappers/readline/rltypedefs.nim + cp lib/wrappers/sdl/sdl.nim $libdir/wrappers/sdl/sdl.nim chmod 644 $libdir/wrappers/sdl/sdl.nim - cp lib/wrappers/sdl/sdl_gfx.nim $libdir/wrappers/sdl/sdl_gfx.nim || exit 1 + cp lib/wrappers/sdl/sdl_gfx.nim $libdir/wrappers/sdl/sdl_gfx.nim chmod 644 $libdir/wrappers/sdl/sdl_gfx.nim - cp lib/wrappers/sdl/sdl_image.nim $libdir/wrappers/sdl/sdl_image.nim || exit 1 + cp lib/wrappers/sdl/sdl_image.nim $libdir/wrappers/sdl/sdl_image.nim chmod 644 $libdir/wrappers/sdl/sdl_image.nim - cp lib/wrappers/sdl/sdl_mixer.nim $libdir/wrappers/sdl/sdl_mixer.nim || exit 1 + cp lib/wrappers/sdl/sdl_mixer.nim $libdir/wrappers/sdl/sdl_mixer.nim chmod 644 $libdir/wrappers/sdl/sdl_mixer.nim - cp lib/wrappers/sdl/sdl_mixer_nosmpeg.nim $libdir/wrappers/sdl/sdl_mixer_nosmpeg.nim || exit 1 + cp lib/wrappers/sdl/sdl_mixer_nosmpeg.nim $libdir/wrappers/sdl/sdl_mixer_nosmpeg.nim chmod 644 $libdir/wrappers/sdl/sdl_mixer_nosmpeg.nim - cp lib/wrappers/sdl/sdl_net.nim $libdir/wrappers/sdl/sdl_net.nim || exit 1 + cp lib/wrappers/sdl/sdl_net.nim $libdir/wrappers/sdl/sdl_net.nim chmod 644 $libdir/wrappers/sdl/sdl_net.nim - cp lib/wrappers/sdl/sdl_ttf.nim $libdir/wrappers/sdl/sdl_ttf.nim || exit 1 + cp lib/wrappers/sdl/sdl_ttf.nim $libdir/wrappers/sdl/sdl_ttf.nim chmod 644 $libdir/wrappers/sdl/sdl_ttf.nim - cp lib/wrappers/sdl/smpeg.nim $libdir/wrappers/sdl/smpeg.nim || exit 1 + cp lib/wrappers/sdl/smpeg.nim $libdir/wrappers/sdl/smpeg.nim chmod 644 $libdir/wrappers/sdl/smpeg.nim - cp lib/wrappers/x11/cursorfont.nim $libdir/wrappers/x11/cursorfont.nim || exit 1 + cp lib/wrappers/x11/cursorfont.nim $libdir/wrappers/x11/cursorfont.nim chmod 644 $libdir/wrappers/x11/cursorfont.nim - cp lib/wrappers/x11/keysym.nim $libdir/wrappers/x11/keysym.nim || exit 1 + cp lib/wrappers/x11/keysym.nim $libdir/wrappers/x11/keysym.nim chmod 644 $libdir/wrappers/x11/keysym.nim - cp lib/wrappers/x11/x.nim $libdir/wrappers/x11/x.nim || exit 1 + cp lib/wrappers/x11/x.nim $libdir/wrappers/x11/x.nim chmod 644 $libdir/wrappers/x11/x.nim - cp lib/wrappers/x11/xatom.nim $libdir/wrappers/x11/xatom.nim || exit 1 + cp lib/wrappers/x11/xatom.nim $libdir/wrappers/x11/xatom.nim chmod 644 $libdir/wrappers/x11/xatom.nim - cp lib/wrappers/x11/xcms.nim $libdir/wrappers/x11/xcms.nim || exit 1 + cp lib/wrappers/x11/xcms.nim $libdir/wrappers/x11/xcms.nim chmod 644 $libdir/wrappers/x11/xcms.nim - cp lib/wrappers/x11/xf86dga.nim $libdir/wrappers/x11/xf86dga.nim || exit 1 + cp lib/wrappers/x11/xf86dga.nim $libdir/wrappers/x11/xf86dga.nim chmod 644 $libdir/wrappers/x11/xf86dga.nim - cp lib/wrappers/x11/xf86vmode.nim $libdir/wrappers/x11/xf86vmode.nim || exit 1 + cp lib/wrappers/x11/xf86vmode.nim $libdir/wrappers/x11/xf86vmode.nim chmod 644 $libdir/wrappers/x11/xf86vmode.nim - cp lib/wrappers/x11/xi.nim $libdir/wrappers/x11/xi.nim || exit 1 + cp lib/wrappers/x11/xi.nim $libdir/wrappers/x11/xi.nim chmod 644 $libdir/wrappers/x11/xi.nim - cp lib/wrappers/x11/xinerama.nim $libdir/wrappers/x11/xinerama.nim || exit 1 + cp lib/wrappers/x11/xinerama.nim $libdir/wrappers/x11/xinerama.nim chmod 644 $libdir/wrappers/x11/xinerama.nim - cp lib/wrappers/x11/xkb.nim $libdir/wrappers/x11/xkb.nim || exit 1 + cp lib/wrappers/x11/xkb.nim $libdir/wrappers/x11/xkb.nim chmod 644 $libdir/wrappers/x11/xkb.nim - cp lib/wrappers/x11/xkblib.nim $libdir/wrappers/x11/xkblib.nim || exit 1 + cp lib/wrappers/x11/xkblib.nim $libdir/wrappers/x11/xkblib.nim chmod 644 $libdir/wrappers/x11/xkblib.nim - cp lib/wrappers/x11/xlib.nim $libdir/wrappers/x11/xlib.nim || exit 1 + cp lib/wrappers/x11/xlib.nim $libdir/wrappers/x11/xlib.nim chmod 644 $libdir/wrappers/x11/xlib.nim - cp lib/wrappers/x11/xrandr.nim $libdir/wrappers/x11/xrandr.nim || exit 1 + cp lib/wrappers/x11/xrandr.nim $libdir/wrappers/x11/xrandr.nim chmod 644 $libdir/wrappers/x11/xrandr.nim - cp lib/wrappers/x11/xrender.nim $libdir/wrappers/x11/xrender.nim || exit 1 + cp lib/wrappers/x11/xrender.nim $libdir/wrappers/x11/xrender.nim chmod 644 $libdir/wrappers/x11/xrender.nim - cp lib/wrappers/x11/xresource.nim $libdir/wrappers/x11/xresource.nim || exit 1 + cp lib/wrappers/x11/xresource.nim $libdir/wrappers/x11/xresource.nim chmod 644 $libdir/wrappers/x11/xresource.nim - cp lib/wrappers/x11/xshm.nim $libdir/wrappers/x11/xshm.nim || exit 1 + cp lib/wrappers/x11/xshm.nim $libdir/wrappers/x11/xshm.nim chmod 644 $libdir/wrappers/x11/xshm.nim - cp lib/wrappers/x11/xutil.nim $libdir/wrappers/x11/xutil.nim || exit 1 + cp lib/wrappers/x11/xutil.nim $libdir/wrappers/x11/xutil.nim chmod 644 $libdir/wrappers/x11/xutil.nim - cp lib/wrappers/x11/xv.nim $libdir/wrappers/x11/xv.nim || exit 1 + cp lib/wrappers/x11/xv.nim $libdir/wrappers/x11/xv.nim chmod 644 $libdir/wrappers/x11/xv.nim - cp lib/wrappers/x11/xvlib.nim $libdir/wrappers/x11/xvlib.nim || exit 1 + cp lib/wrappers/x11/xvlib.nim $libdir/wrappers/x11/xvlib.nim chmod 644 $libdir/wrappers/x11/xvlib.nim - cp lib/wrappers/zip/libzip.nim $libdir/wrappers/zip/libzip.nim || exit 1 + cp lib/wrappers/zip/libzip.nim $libdir/wrappers/zip/libzip.nim chmod 644 $libdir/wrappers/zip/libzip.nim - cp lib/wrappers/zip/zlib.nim $libdir/wrappers/zip/zlib.nim || exit 1 + cp lib/wrappers/zip/zlib.nim $libdir/wrappers/zip/zlib.nim chmod 644 $libdir/wrappers/zip/zlib.nim - cp lib/wrappers/zip/zzip.nim $libdir/wrappers/zip/zzip.nim || exit 1 + cp lib/wrappers/zip/zzip.nim $libdir/wrappers/zip/zzip.nim chmod 644 $libdir/wrappers/zip/zzip.nim - cp lib/wrappers/zip/libzip_all.c $libdir/wrappers/zip/libzip_all.c || exit 1 + cp lib/wrappers/zip/libzip_all.c $libdir/wrappers/zip/libzip_all.c chmod 644 $libdir/wrappers/zip/libzip_all.c - cp lib/windows/mmsystem.nim $libdir/windows/mmsystem.nim || exit 1 + cp lib/windows/mmsystem.nim $libdir/windows/mmsystem.nim chmod 644 $libdir/windows/mmsystem.nim - cp lib/windows/nb30.nim $libdir/windows/nb30.nim || exit 1 + cp lib/windows/nb30.nim $libdir/windows/nb30.nim chmod 644 $libdir/windows/nb30.nim - cp lib/windows/ole2.nim $libdir/windows/ole2.nim || exit 1 + cp lib/windows/ole2.nim $libdir/windows/ole2.nim chmod 644 $libdir/windows/ole2.nim - cp lib/windows/psapi.nim $libdir/windows/psapi.nim || exit 1 + cp lib/windows/psapi.nim $libdir/windows/psapi.nim chmod 644 $libdir/windows/psapi.nim - cp lib/windows/shellapi.nim $libdir/windows/shellapi.nim || exit 1 + cp lib/windows/shellapi.nim $libdir/windows/shellapi.nim chmod 644 $libdir/windows/shellapi.nim - cp lib/windows/shfolder.nim $libdir/windows/shfolder.nim || exit 1 + cp lib/windows/shfolder.nim $libdir/windows/shfolder.nim chmod 644 $libdir/windows/shfolder.nim - cp lib/windows/windows.nim $libdir/windows/windows.nim || exit 1 + cp lib/windows/windows.nim $libdir/windows/windows.nim chmod 644 $libdir/windows/windows.nim - cp lib/windows/winlean.nim $libdir/windows/winlean.nim || exit 1 + cp lib/windows/winlean.nim $libdir/windows/winlean.nim chmod 644 $libdir/windows/winlean.nim - cp lib/posix/posix.nim $libdir/posix/posix.nim || exit 1 + cp lib/posix/posix.nim $libdir/posix/posix.nim chmod 644 $libdir/posix/posix.nim - cp lib/ecmas/dom.nim $libdir/ecmas/dom.nim || exit 1 + cp lib/ecmas/dom.nim $libdir/ecmas/dom.nim chmod 644 $libdir/ecmas/dom.nim echo "installation successful" diff --git a/lib/core/macros.nim b/lib/core/macros.nim index b0f237924d..9d0994c2f5 100755 --- a/lib/core/macros.nim +++ b/lib/core/macros.nim @@ -17,8 +17,9 @@ type TNimrodNodeKind* = enum nnkNone, nnkEmpty, nnkIdent, nnkSym, nnkType, nnkCharLit, nnkIntLit, nnkInt8Lit, - nnkInt16Lit, nnkInt32Lit, nnkInt64Lit, nnkFloatLit, - nnkFloat32Lit, nnkFloat64Lit, nnkStrLit, nnkRStrLit, + nnkInt16Lit, nnkInt32Lit, nnkInt64Lit, nnkUIntLit, nnkUInt8Lit, + nnkUInt16Lit, nnkUInt32Lit, nnkUInt64Lit, nnkFloatLit, + nnkFloat32Lit, nnkFloat64Lit, nnkFloat128Lit, nnkStrLit, nnkRStrLit, nnkTripleStrLit, nnkNilLit, nnkMetaNode, nnkDotCall, nnkCommand, nnkCall, nnkCallStrLit, nnkExprEqExpr, nnkExprColonExpr, nnkIdentDefs, nnkVarTuple, nnkInfix, diff --git a/lib/system.nim b/lib/system.nim index 5d01c5a44d..fe8f7a5172 100755 --- a/lib/system.nim +++ b/lib/system.nim @@ -21,9 +21,15 @@ type int16* {.magic: Int16.} ## signed 16 bit integer type int32* {.magic: Int32.} ## signed 32 bit integer type int64* {.magic: Int64.} ## signed 64 bit integer type + uint* {.magic: UInt.} ## unsigned default integer type + uint8* {.magic: UInt8.} ## unsigned 8 bit integer type + uint16* {.magic: UInt16.} ## unsigned 16 bit integer type + uint32* {.magic: UInt32.} ## unsigned 32 bit integer type + uint64* {.magic: UInt64.} ## unsigned 64 bit integer type float* {.magic: Float.} ## default floating point type float32* {.magic: Float32.} ## 32 bit floating point type float64* {.magic: Float64.} ## 64 bit floating point type + type # we need to start a new type section here, so that ``0`` can have a type bool* {.magic: Bool.} = enum ## built-in boolean type false = 0, true = 1 @@ -49,14 +55,23 @@ type ## a type description (for templates) void* {.magic: "VoidType".} ## meta type to denote the absense of any type - TInteger* = int|int8|int16|int32|int64 + TSignedInt* = distinct int|int8|int16|int32|int64 + ## type class matching all signed integer types + + TUnsignedInt* = distinct uint|uint8|uint16|uint32|uint64 + ## type class matching all unsigned integer types + + TInteger* = distinct TSignedInt|TUnsignedInt ## type class matching all integer types - TOrdinal* = TInteger|bool|enum + TOrdinal* = distinct TInteger|bool|enum ## type class matching all ordinal types; however this includes enums with ## holes. + + TReal* = distinct float|float32|float64 + ## type class matching all floating point number types - TNumber* = TInteger|float|float32|float64 + TNumber* = distinct TInteger|TReal ## type class matching all number types proc defined*(x: expr): bool {.magic: "Defined", noSideEffect.} @@ -517,65 +532,88 @@ proc abs*(x: int64): int64 {.magic: "AbsI64", noSideEffect.} ## is -MININT for its type), an overflow exception is thrown (if overflow ## checking is turned on). -proc `+%` *(x, y: int): int {.magic: "AddU", noSideEffect.} -proc `+%` *(x, y: int8): int8 {.magic: "AddU", noSideEffect.} -proc `+%` *(x, y: int16): int16 {.magic: "AddU", noSideEffect.} -proc `+%` *(x, y: int32): int32 {.magic: "AddU", noSideEffect.} -proc `+%` *(x, y: int64): int64 {.magic: "AddU64", noSideEffect.} +type + UIntMax32 = distinct uint|uint8|uint16|uint32 + IntMax32 = distinct int|int8|int16|int32 + +proc `+` *(x, y: UIntMax32): UIntMax32 {.magic: "AddU", noSideEffect.} +proc `+` *(x, y: UInt64): uint64 {.magic: "AddU64", noSideEffect.} + ## Binary `+` operator for unsigned integers. + +proc `+%` *(x, y: IntMax32): IntMax32 {.magic: "AddU", noSideEffect.} +proc `+%` *(x, y: Int64): Int64 {.magic: "AddU64", noSideEffect.} ## treats `x` and `y` as unsigned and adds them. The result is truncated to ## fit into the result. This implements modulo arithmetic. No overflow ## errors are possible. -proc `-%` *(x, y: int): int {.magic: "SubU", noSideEffect.} -proc `-%` *(x, y: int8): int8 {.magic: "SubU", noSideEffect.} -proc `-%` *(x, y: int16): int16 {.magic: "SubU", noSideEffect.} -proc `-%` *(x, y: int32): int32 {.magic: "SubU", noSideEffect.} -proc `-%` *(x, y: int64): int64 {.magic: "SubU64", noSideEffect.} +proc `-` *(x, y: UIntMax32): UIntMax32 {.magic: "SubU", noSideEffect.} +proc `-` *(x, y: UInt64): UInt64 {.magic: "SubU64", noSideEffect.} + ## Binary `-` operator for unsigned integers. + +proc `-%` *(x, y: IntMax32): IntMax32 {.magic: "SubU", noSideEffect.} +proc `-%` *(x, y: Int64): Int64 {.magic: "SubU64", noSideEffect.} ## treats `x` and `y` as unsigned and subtracts them. The result is ## truncated to fit into the result. This implements modulo arithmetic. ## No overflow errors are possible. -proc `*%` *(x, y: int): int {.magic: "MulU", noSideEffect.} -proc `*%` *(x, y: int8): int8 {.magic: "MulU", noSideEffect.} -proc `*%` *(x, y: int16): int16 {.magic: "MulU", noSideEffect.} -proc `*%` *(x, y: int32): int32 {.magic: "MulU", noSideEffect.} -proc `*%` *(x, y: int64): int64 {.magic: "MulU64", noSideEffect.} +proc `*` *(x, y: UIntMax32): UIntMax32 {.magic: "MulU", noSideEffect.} +proc `*` *(x, y: UInt64): UInt64 {.magic: "MulU64", noSideEffect.} + ## Binary `*` operator for unsigned integers. + +proc `*%` *(x, y: IntMax32): IntMax32 {.magic: "MulU", noSideEffect.} +proc `*%` *(x, y: Int64): Int64 {.magic: "MulU64", noSideEffect.} ## treats `x` and `y` as unsigned and multiplies them. The result is ## truncated to fit into the result. This implements modulo arithmetic. ## No overflow errors are possible. -proc `/%` *(x, y: int): int {.magic: "DivU", noSideEffect.} -proc `/%` *(x, y: int8): int8 {.magic: "DivU", noSideEffect.} -proc `/%` *(x, y: int16): int16 {.magic: "DivU", noSideEffect.} -proc `/%` *(x, y: int32): int32 {.magic: "DivU", noSideEffect.} -proc `/%` *(x, y: int64): int64 {.magic: "DivU64", noSideEffect.} +proc `div` *(x, y: UIntMax32): UIntMax32 {.magic: "DivU", noSideEffect.} +proc `div` *(x, y: UInt64): UInt64 {.magic: "DivU64", noSideEffect.} + ## computes the integer division. This is roughly the same as + ## ``floor(x/y)``. + +proc `/` *(x, y: UIntMax32): UIntMax32 {.magic: "DivU", noSideEffect.} +proc `/` *(x, y: UInt64): UInt64 {.magic: "DivU64", noSideEffect.} + ## computes the integer division. This is roughly the same as + ## ``floor(x/y)``. + +proc `/%` *(x, y: IntMax32): IntMax32 {.magic: "DivU", noSideEffect.} +proc `/%` *(x, y: Int64): Int64 {.magic: "DivU64", noSideEffect.} ## treats `x` and `y` as unsigned and divides them. The result is ## truncated to fit into the result. This implements modulo arithmetic. ## No overflow errors are possible. -proc `%%` *(x, y: int): int {.magic: "ModU", noSideEffect.} -proc `%%` *(x, y: int8): int8 {.magic: "ModU", noSideEffect.} -proc `%%` *(x, y: int16): int16 {.magic: "ModU", noSideEffect.} -proc `%%` *(x, y: int32): int32 {.magic: "ModU", noSideEffect.} -proc `%%` *(x, y: int64): int64 {.magic: "ModU64", noSideEffect.} +proc `%` *(x, y: UIntMax32): UIntMax32 {.magic: "DivU", noSideEffect.} +proc `%` *(x, y: UInt64): UInt64 {.magic: "DivU64", noSideEffect.} + ## computes the integer modulo operation. This is the same as + ## ``x - (x div y) * y``. + +proc `mod` *(x, y: UIntMax32): UIntMax32 {.magic: "DivU", noSideEffect.} +proc `mod` *(x, y: UInt64): UInt64 {.magic: "DivU64", noSideEffect.} + ## computes the integer modulo operation. This is the same as + ## ``x - (x div y) * y``. + +proc `%%` *(x, y: IntMax32): IntMax32 {.magic: "ModU", noSideEffect.} +proc `%%` *(x, y: Int64): Int64 {.magic: "ModU64", noSideEffect.} ## treats `x` and `y` as unsigned and compute the modulo of `x` and `y`. ## The result is truncated to fit into the result. ## This implements modulo arithmetic. ## No overflow errors are possible. -proc `<=%` *(x, y: int): bool {.magic: "LeU", noSideEffect.} -proc `<=%` *(x, y: int8): bool {.magic: "LeU", noSideEffect.} -proc `<=%` *(x, y: int16): bool {.magic: "LeU", noSideEffect.} -proc `<=%` *(x, y: int32): bool {.magic: "LeU", noSideEffect.} -proc `<=%` *(x, y: int64): bool {.magic: "LeU64", noSideEffect.} +proc `<=` *(x, y: UIntMax32): bool {.magic: "LeU", noSideEffect.} +proc `<=` *(x, y: UInt64): bool {.magic: "LeU64", noSideEffect.} + ## Returns true iff ``x <= y``. + +proc `<=%` *(x, y: IntMax32): bool {.magic: "LeU", noSideEffect.} +proc `<=%` *(x, y: Int64): bool {.magic: "LeU64", noSideEffect.} ## treats `x` and `y` as unsigned and compares them. ## Returns true iff ``unsigned(x) <= unsigned(y)``. -proc `<%` *(x, y: int): bool {.magic: "LtU", noSideEffect.} -proc `<%` *(x, y: int8): bool {.magic: "LtU", noSideEffect.} -proc `<%` *(x, y: int16): bool {.magic: "LtU", noSideEffect.} -proc `<%` *(x, y: int32): bool {.magic: "LtU", noSideEffect.} -proc `<%` *(x, y: int64): bool {.magic: "LtU64", noSideEffect.} +proc `<` *(x, y: UIntMax32): bool {.magic: "LtU", noSideEffect.} +proc `<` *(x, y: UInt64): bool {.magic: "LtU64", noSideEffect.} + ## Returns true iff ``unsigned(x) < unsigned(y)``. + +proc `<%` *(x, y: IntMax32): bool {.magic: "LtU", noSideEffect.} +proc `<%` *(x, y: Int64): bool {.magic: "LtU64", noSideEffect.} ## treats `x` and `y` as unsigned and compares them. ## Returns true iff ``unsigned(x) < unsigned(y)``. From df1ec0939946c44989e22e0e51623a77cd72b0e6 Mon Sep 17 00:00:00 2001 From: Zahary Karadjov Date: Tue, 12 Jun 2012 03:36:43 +0300 Subject: [PATCH 13/15] proper indentation in the generated C code --- compiler/ccgcalls.nim | 39 ++++------ compiler/ccgexprs.nim | 144 ++++++++++++++++++------------------- compiler/ccgstmts.nim | 126 ++++++++++++++++---------------- compiler/ccgthreadvars.nim | 5 +- compiler/ccgtrav.nim | 22 +++--- compiler/cgen.nim | 111 +++++++++++++++++----------- 6 files changed, 235 insertions(+), 212 deletions(-) diff --git a/compiler/ccgcalls.nim b/compiler/ccgcalls.nim index 17139f0555..fca708aee3 100644 --- a/compiler/ccgcalls.nim +++ b/compiler/ccgcalls.nim @@ -33,16 +33,14 @@ proc fixupCall(p: BProc, le, ri: PNode, d: var TLoc, pl: PRope) = # reset before pass as 'result' var: resetLoc(p, d) app(pl, addrLoc(d)) - app(pl, ")") - app(p.s(cpsStmts), pl) - appf(p.s(cpsStmts), ";$n") + appf(pl, ");$n") + line(p, cpsStmts, pl) else: var tmp: TLoc getTemp(p, typ.sons[0], tmp) app(pl, addrLoc(tmp)) - app(pl, ")") - app(p.s(cpsStmts), pl) - appf(p.s(cpsStmts), ";$n") + appf(pl, ");$n") + line(p, cpsStmts, pl) genAssignment(p, d, tmp, {}) # no need for deep copying else: app(pl, ")") @@ -53,9 +51,8 @@ proc fixupCall(p: BProc, le, ri: PNode, d: var TLoc, pl: PRope) = list.r = pl genAssignment(p, d, list, {}) # no need for deep copying else: - app(pl, ")") - app(p.s(cpsStmts), pl) - appf(p.s(cpsStmts), ";$n") + appf(pl, ");$n") + line(p, cpsStmts, pl) proc isInCurrentFrame(p: BProc, n: PNode): bool = # checks if `n` is an expression that refers to the current frame; @@ -148,7 +145,7 @@ proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) = proc addComma(r: PRope): PRope = result = if r == nil: r else: con(r, ", ") - const CallPattern = "$1.ClEnv? $1.ClPrc($3$1.ClEnv) : (($4)($1.ClPrc))($2)" + const CallPattern = "$1.ClEnv? $1.ClPrc($3$1.ClEnv) : (($4)($1.ClPrc))($2);$n" var op: TLoc initLocExpr(p, ri.sons[0], op) var pl: PRope @@ -166,7 +163,7 @@ proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) = if i < length - 1: app(pl, ", ") template genCallPattern = - appf(p.s(cpsStmts), CallPattern, op.r, pl, pl.addComma, rawProc) + lineF(p, cpsStmts, CallPattern, op.r, pl, pl.addComma, rawProc) let rawProc = getRawProcType(p, typ) if typ.sons[0] != nil: @@ -181,13 +178,11 @@ proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) = resetLoc(p, d) app(pl, addrLoc(d)) genCallPattern() - appf(p.s(cpsStmts), ";$n") else: var tmp: TLoc getTemp(p, typ.sons[0], tmp) - app(pl, addrLoc(tmp)) + app(pl, addrLoc(tmp)) genCallPattern() - appf(p.s(cpsStmts), ";$n") genAssignment(p, d, tmp, {}) # no need for deep copying else: if d.k == locNone: getTemp(p, typ.sons[0], d) @@ -198,7 +193,6 @@ proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) = genAssignment(p, d, list, {}) # no need for deep copying else: genCallPattern() - appf(p.s(cpsStmts), ";$n") proc genInfixCall(p: BProc, le, ri: PNode, d: var TLoc) = var op, a: TLoc @@ -264,16 +258,14 @@ proc genNamedParamCall(p: BProc, ri: PNode, d: var TLoc) = if d.k == locNone: getTemp(p, typ.sons[0], d) app(pl, "Result: ") app(pl, addrLoc(d)) - app(pl, "]") - app(p.s(cpsStmts), pl) - appf(p.s(cpsStmts), ";$n") + appf(pl, "];$n") + line(p, cpsStmts, pl) else: var tmp: TLoc getTemp(p, typ.sons[0], tmp) app(pl, addrLoc(tmp)) - app(pl, "]") - app(p.s(cpsStmts), pl) - appf(p.s(cpsStmts), ";$n") + appf(pl, "];$n") + line(p, cpsStmts, pl) genAssignment(p, d, tmp, {}) # no need for deep copying else: app(pl, "]") @@ -284,9 +276,8 @@ proc genNamedParamCall(p: BProc, ri: PNode, d: var TLoc) = list.r = pl genAssignment(p, d, list, {}) # no need for deep copying else: - app(pl, "]") - app(p.s(cpsStmts), pl) - appf(p.s(cpsStmts), ";$n") + appf(pl, "];$n") + line(p, cpsStmts, pl) proc genCall(p: BProc, e: PNode, d: var TLoc) = if e.sons[0].typ.callConv == ccClosure: diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index a929b5af04..1e1bf8072a 100755 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -160,7 +160,7 @@ proc getStorageLoc(n: PNode): TStorageLoc = proc genRefAssign(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) = if dest.s == OnStack or optRefcGC notin gGlobalOptions: - appf(p.s(cpsStmts), "$1 = $2;$n", [rdLoc(dest), rdLoc(src)]) + lineF(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)]) if needToKeepAlive in flags: keepAlive(p, dest) elif dest.s == OnHeap: # location is on heap @@ -168,25 +168,25 @@ proc genRefAssign(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) = # # if afSrcIsNotNil in flags: # UseMagic(p.module, 'nimGCref') - # appf(p.s[cpsStmts], 'nimGCref($1);$n', [rdLoc(src)]) + # lineF(p, cpsStmts, 'nimGCref($1);$n', [rdLoc(src)]) # elif afSrcIsNil notin flags: # UseMagic(p.module, 'nimGCref') - # appf(p.s[cpsStmts], 'if ($1) nimGCref($1);$n', [rdLoc(src)]) + # lineF(p, cpsStmts, 'if ($1) nimGCref($1);$n', [rdLoc(src)]) # if afDestIsNotNil in flags: # UseMagic(p.module, 'nimGCunref') - # appf(p.s[cpsStmts], 'nimGCunref($1);$n', [rdLoc(dest)]) + # lineF(p, cpsStmts, 'nimGCunref($1);$n', [rdLoc(dest)]) # elif afDestIsNil notin flags: # UseMagic(p.module, 'nimGCunref') - # appf(p.s[cpsStmts], 'if ($1) nimGCunref($1);$n', [rdLoc(dest)]) - # appf(p.s[cpsStmts], '$1 = $2;$n', [rdLoc(dest), rdLoc(src)]) + # lineF(p, cpsStmts, 'if ($1) nimGCunref($1);$n', [rdLoc(dest)]) + # lineF(p, cpsStmts, '$1 = $2;$n', [rdLoc(dest), rdLoc(src)]) if canFormAcycle(dest.t): - appcg(p.module, p.s(cpsStmts), "#asgnRef((void**) $1, $2);$n", + lineCg(p, cpsStmts, "#asgnRef((void**) $1, $2);$n", [addrLoc(dest), rdLoc(src)]) else: - appcg(p.module, p.s(cpsStmts), "#asgnRefNoCycle((void**) $1, $2);$n", + lineCg(p, cpsStmts, "#asgnRefNoCycle((void**) $1, $2);$n", [addrLoc(dest), rdLoc(src)]) else: - appcg(p.module, p.s(cpsStmts), "#unsureAsgnRef((void**) $1, $2);$n", + lineCg(p, cpsStmts, "#unsureAsgnRef((void**) $1, $2);$n", [addrLoc(dest), rdLoc(src)]) if needToKeepAlive in flags: keepAlive(p, dest) @@ -200,15 +200,15 @@ proc genGenericAsgn(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) = if needToCopy notin flags or tfShallow in skipTypes(dest.t, abstractVarRange).flags: if dest.s == OnStack or optRefcGC notin gGlobalOptions: - appcg(p, cpsStmts, + lineCg(p, cpsStmts, "memcpy((void*)$1, (NIM_CONST void*)$2, sizeof($3));$n", [addrLoc(dest), addrLoc(src), rdLoc(dest)]) if needToKeepAlive in flags: keepAlive(p, dest) else: - appcg(p, cpsStmts, "#genericShallowAssign((void*)$1, (void*)$2, $3);$n", + lineCg(p, cpsStmts, "#genericShallowAssign((void*)$1, (void*)$2, $3);$n", [addrLoc(dest), addrLoc(src), genTypeInfo(p.module, dest.t)]) else: - appcg(p, cpsStmts, "#genericAssign((void*)$1, (void*)$2, $3);$n", + lineCg(p, cpsStmts, "#genericAssign((void*)$1, (void*)$2, $3);$n", [addrLoc(dest), addrLoc(src), genTypeInfo(p.module, dest.t)]) proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) = @@ -216,7 +216,7 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) = # the assignment operation in C. if src.t != nil and src.t.kind == tyPtr: # little HACK to support the new 'var T' as return type: - appcg(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)]) + lineCg(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)]) return var ty = skipTypes(dest.t, abstractVarRange) case ty.kind @@ -226,24 +226,24 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) = if needToCopy notin flags: genRefAssign(p, dest, src, flags) else: - appcg(p, cpsStmts, "#genericSeqAssign($1, $2, $3);$n", + lineCg(p, cpsStmts, "#genericSeqAssign($1, $2, $3);$n", [addrLoc(dest), rdLoc(src), genTypeInfo(p.module, dest.t)]) of tyString: if needToCopy notin flags: genRefAssign(p, dest, src, flags) else: if dest.s == OnStack or optRefcGC notin gGlobalOptions: - appcg(p, cpsStmts, "$1 = #copyString($2);$n", [dest.rdLoc, src.rdLoc]) + lineCg(p, cpsStmts, "$1 = #copyString($2);$n", [dest.rdLoc, src.rdLoc]) if needToKeepAlive in flags: keepAlive(p, dest) elif dest.s == OnHeap: # we use a temporary to care for the dreaded self assignment: var tmp: TLoc getTemp(p, ty, tmp) - appcg(p, cpsStmts, "$3 = $1; $1 = #copyStringRC1($2);$n", + lineCg(p, cpsStmts, "$3 = $1; $1 = #copyStringRC1($2);$n", [dest.rdLoc, src.rdLoc, tmp.rdLoc]) - appcg(p, cpsStmts, "if ($1) #nimGCunrefNoCycle($1);$n", tmp.rdLoc) + lineCg(p, cpsStmts, "if ($1) #nimGCunrefNoCycle($1);$n", tmp.rdLoc) else: - appcg(p, cpsStmts, "#unsureAsgnRef((void**) $1, #copyString($2));$n", + lineCg(p, cpsStmts, "#unsureAsgnRef((void**) $1, #copyString($2));$n", [addrLoc(dest), rdLoc(src)]) if needToKeepAlive in flags: keepAlive(p, dest) of tyTuple, tyObject, tyProc: @@ -251,34 +251,34 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) = if needsComplexAssignment(dest.t): genGenericAsgn(p, dest, src, flags) else: - appcg(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)]) + lineCg(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)]) of tyArray, tyArrayConstr: if needsComplexAssignment(dest.t): genGenericAsgn(p, dest, src, flags) else: - appcg(p, cpsStmts, + lineCg(p, cpsStmts, "memcpy((void*)$1, (NIM_CONST void*)$2, sizeof($1));$n", [rdLoc(dest), rdLoc(src)]) of tyOpenArray: # open arrays are always on the stack - really? What if a sequence is # passed to an open array? if needsComplexAssignment(dest.t): - appcg(p, cpsStmts, # XXX: is this correct for arrays? + lineCg(p, cpsStmts, # XXX: is this correct for arrays? "#genericAssignOpenArray((void*)$1, (void*)$2, $1Len0, $3);$n", [addrLoc(dest), addrLoc(src), genTypeInfo(p.module, dest.t)]) else: - appcg(p, cpsStmts, + lineCg(p, cpsStmts, "memcpy((void*)$1, (NIM_CONST void*)$2, sizeof($1[0])*$1Len0);$n", [rdLoc(dest), rdLoc(src)]) of tySet: if mapType(ty) == ctArray: - appcg(p, cpsStmts, "memcpy((void*)$1, (NIM_CONST void*)$2, $3);$n", + lineCg(p, cpsStmts, "memcpy((void*)$1, (NIM_CONST void*)$2, $3);$n", [rdLoc(dest), rdLoc(src), toRope(getSize(dest.t))]) else: - appcg(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)]) + lineCg(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)]) of tyPtr, tyPointer, tyChar, tyBool, tyEnum, tyCString, tyInt..tyUInt64, tyRange: - appcg(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)]) + lineCg(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)]) else: InternalError("genAssignment(" & $ty.kind & ')') proc expr(p: BProc, e: PNode, d: var TLoc) @@ -317,20 +317,20 @@ proc binaryStmt(p: BProc, e: PNode, d: var TLoc, frmt: string) = if d.k != locNone: InternalError(e.info, "binaryStmt") InitLocExpr(p, e.sons[1], d) InitLocExpr(p, e.sons[2], b) - appcg(p, cpsStmts, frmt, [rdLoc(d), rdLoc(b)]) + lineCg(p, cpsStmts, frmt, [rdLoc(d), rdLoc(b)]) proc unaryStmt(p: BProc, e: PNode, d: var TLoc, frmt: string) = var a: TLoc if (d.k != locNone): InternalError(e.info, "unaryStmt") InitLocExpr(p, e.sons[1], a) - appcg(p, cpsStmts, frmt, [rdLoc(a)]) + lineCg(p, cpsStmts, frmt, [rdLoc(a)]) proc binaryStmtChar(p: BProc, e: PNode, d: var TLoc, frmt: string) = var a, b: TLoc if (d.k != locNone): InternalError(e.info, "binaryStmtChar") InitLocExpr(p, e.sons[1], a) InitLocExpr(p, e.sons[2], b) - appcg(p, cpsStmts, frmt, [rdCharLoc(a), rdCharLoc(b)]) + lineCg(p, cpsStmts, frmt, [rdCharLoc(a), rdCharLoc(b)]) proc binaryExpr(p: BProc, e: PNode, d: var TLoc, frmt: string) = var a, b: TLoc @@ -382,11 +382,11 @@ proc binaryArithOverflow(p: BProc, e: PNode, d: var TLoc, m: TMagic) = else: storage = getTypeDesc(p.module, t) var tmp = getTempName() - appcg(p, cpsLocals, "$1 $2;$n", [storage, tmp]) - appcg(p, cpsStmts, "$1 = #$2($3, $4);$n", [tmp, toRope(prc[m]), + lineCg(p, cpsLocals, "$1 $2;$n", [storage, tmp]) + lineCg(p, cpsStmts, "$1 = #$2($3, $4);$n", [tmp, toRope(prc[m]), rdLoc(a), rdLoc(b)]) if size < platform.IntSize or t.kind in {tyRange, tyEnum, tySet}: - appcg(p, cpsStmts, "if ($1 < $2 || $1 > $3) #raiseOverflow();$n", + lineCg(p, cpsStmts, "if ($1 < $2 || $1 > $3) #raiseOverflow();$n", [tmp, intLiteral(firstOrd(t)), intLiteral(lastOrd(t))]) putIntoDest(p, d, e.typ, ropef("(NI$1)($2)", [toRope(getSize(t)*8), tmp])) @@ -404,7 +404,7 @@ proc unaryArithOverflow(p: BProc, e: PNode, d: var TLoc, m: TMagic) = InitLocExpr(p, e.sons[1], a) t = skipTypes(e.typ, abstractRange) if optOverflowCheck in p.options: - appcg(p, cpsStmts, "if ($1 == $2) #raiseOverflow();$n", + lineCg(p, cpsStmts, "if ($1 == $2) #raiseOverflow();$n", [rdLoc(a), intLiteral(firstOrd(t))]) putIntoDest(p, d, e.typ, ropef(opr[m], [rdLoc(a), toRope(getSize(t) * 8)])) @@ -634,11 +634,11 @@ proc genCheckedRecordField(p: BProc, e: PNode, d: var TLoc) = if id == gBackendId: strLit = getStrLit(p.module, field.name.s) else: strLit = con("TMP", toRope(id)) if op.magic == mNot: - appcg(p, cpsStmts, + lineCg(p, cpsStmts, "if ($1) #raiseFieldError(((#NimStringDesc*) &$2));$n", [rdLoc(test), strLit]) else: - appcg(p, cpsStmts, + lineCg(p, cpsStmts, "if (!($1)) #raiseFieldError(((#NimStringDesc*) &$2));$n", [rdLoc(test), strLit]) appf(r, ".$1", [field.loc.r]) @@ -658,10 +658,10 @@ proc genArrayElem(p: BProc, e: PNode, d: var TLoc) = # semantic pass has already checked for const index expressions if firstOrd(ty) == 0: if (firstOrd(b.t) < firstOrd(ty)) or (lastOrd(b.t) > lastOrd(ty)): - appcg(p, cpsStmts, "if ((NU)($1) > (NU)($2)) #raiseIndexError();$n", + lineCg(p, cpsStmts, "if ((NU)($1) > (NU)($2)) #raiseIndexError();$n", [rdCharLoc(b), intLiteral(lastOrd(ty))]) else: - appcg(p, cpsStmts, "if ($1 < $2 || $1 > $3) #raiseIndexError();$n", + lineCg(p, cpsStmts, "if ($1 < $2 || $1 > $3) #raiseIndexError();$n", [rdCharLoc(b), first, intLiteral(lastOrd(ty))]) if d.k == locNone: d.s = a.s putIntoDest(p, d, elemType(skipTypes(ty, abstractVar)), @@ -681,7 +681,7 @@ proc genOpenArrayElem(p: BProc, e: PNode, d: var TLoc) = initLocExpr(p, e.sons[0], a) initLocExpr(p, e.sons[1], b) # emit range check: if optBoundsCheck in p.options: - appcg(p, cpsStmts, "if ((NU)($1) >= (NU)($2Len0)) #raiseIndexError();$n", + lineCg(p, cpsStmts, "if ((NU)($1) >= (NU)($2Len0)) #raiseIndexError();$n", [rdLoc(b), rdLoc(a)]) # BUGFIX: ``>=`` and not ``>``! if d.k == locNone: d.s = a.s putIntoDest(p, d, elemType(skipTypes(a.t, abstractVar)), @@ -696,11 +696,11 @@ proc genSeqElem(p: BPRoc, e: PNode, d: var TLoc) = ty = skipTypes(ty.sons[0], abstractVarRange) # emit range check: if optBoundsCheck in p.options: if ty.kind == tyString: - appcg(p, cpsStmts, + lineCg(p, cpsStmts, "if ((NU)($1) > (NU)($2->$3)) #raiseIndexError();$n", [rdLoc(b), rdLoc(a), lenField()]) else: - appcg(p, cpsStmts, + lineCg(p, cpsStmts, "if ((NU)($1) >= (NU)($2->$3)) #raiseIndexError();$n", [rdLoc(b), rdLoc(a), lenField()]) if d.k == locNone: d.s = OnHeap @@ -737,9 +737,9 @@ proc genAndOr(p: BProc, e: PNode, d: var TLoc, m: TMagic) = expr(p, e.sons[1], tmp) L = getLabel(p) if m == mOr: - appf(p.s(cpsStmts), "if ($1) goto $2;$n", [rdLoc(tmp), L]) + lineF(p, cpsStmts, "if ($1) goto $2;$n", [rdLoc(tmp), L]) else: - appf(p.s(cpsStmts), "if (!($1)) goto $2;$n", [rdLoc(tmp), L]) + lineF(p, cpsStmts, "if (!($1)) goto $2;$n", [rdLoc(tmp), L]) expr(p, e.sons[2], tmp) fixLabel(p, L) if d.k == locNone: @@ -772,9 +772,9 @@ proc genIfExpr(p: BProc, n: PNode, d: var TLoc) = of nkElifExpr: initLocExpr(p, it.sons[0], a) Lelse = getLabel(p) - appf(p.s(cpsStmts), "if (!$1) goto $2;$n", [rdLoc(a), Lelse]) + lineF(p, cpsStmts, "if (!$1) goto $2;$n", [rdLoc(a), Lelse]) expr(p, it.sons[1], tmp) - appf(p.s(cpsStmts), "goto $1;$n", [Lend]) + lineF(p, cpsStmts, "goto $1;$n", [Lend]) fixLabel(p, Lelse) of nkElseExpr: expr(p, it.sons[0], tmp) @@ -793,7 +793,7 @@ proc genEcho(p: BProc, n: PNode) = for i in countup(1, n.len-1): initLocExpr(p, n.sons[i], a) appf(args, ", ($1)->data", [rdLoc(a)]) - appcg(p, cpsStmts, "printf($1$2);$n", [ + lineCg(p, cpsStmts, "printf($1$2);$n", [ makeCString(repeatStr(n.len-1, "%s") & tnl), args]) include ccgcalls @@ -825,14 +825,14 @@ proc genStrConcat(p: BProc, e: PNode, d: var TLoc) = initLocExpr(p, e.sons[i + 1], a) if skipTypes(e.sons[i + 1].Typ, abstractVarRange).kind == tyChar: Inc(L) - appcg(p.module, appends, "#appendChar($1, $2);$n", [tmp.r, rdLoc(a)]) + appLineCg(p, appends, "#appendChar($1, $2);$n", [tmp.r, rdLoc(a)]) else: if e.sons[i + 1].kind in {nkStrLit..nkTripleStrLit}: Inc(L, len(e.sons[i + 1].strVal)) else: appf(lens, "$1->$2 + ", [rdLoc(a), lenField()]) - appcg(p.module, appends, "#appendString($1, $2);$n", [tmp.r, rdLoc(a)]) - appcg(p, cpsStmts, "$1 = #rawNewString($2$3);$n", [tmp.r, lens, toRope(L)]) + appLineCg(p, appends, "#appendString($1, $2);$n", [tmp.r, rdLoc(a)]) + lineCg(p, cpsStmts, "$1 = #rawNewString($2$3);$n", [tmp.r, lens, toRope(L)]) app(p.s(cpsStmts), appends) if d.k == locNone: d = tmp @@ -863,16 +863,16 @@ proc genStrAppend(p: BProc, e: PNode, d: var TLoc) = initLocExpr(p, e.sons[i + 2], a) if skipTypes(e.sons[i + 2].Typ, abstractVarRange).kind == tyChar: Inc(L) - appcg(p.module, appends, "#appendChar($1, $2);$n", + appLineCg(p, appends, "#appendChar($1, $2);$n", [rdLoc(dest), rdLoc(a)]) else: if e.sons[i + 2].kind in {nkStrLit..nkTripleStrLit}: Inc(L, len(e.sons[i + 2].strVal)) else: appf(lens, "$1->$2 + ", [rdLoc(a), lenField()]) - appcg(p.module, appends, "#appendString($1, $2);$n", + appLineCg(p, appends, "#appendString($1, $2);$n", [rdLoc(dest), rdLoc(a)]) - appcg(p, cpsStmts, "$1 = #resizeString($1, $2$3);$n", + lineCg(p, cpsStmts, "$1 = #resizeString($1, $2$3);$n", [rdLoc(dest), lens, toRope(L)]) keepAlive(p, dest) app(p.s(cpsStmts), appends) @@ -889,7 +889,7 @@ proc genSeqElemAppend(p: BProc, e: PNode, d: var TLoc) = var a, b, dest: TLoc InitLocExpr(p, e.sons[1], a) InitLocExpr(p, e.sons[2], b) - appcg(p, cpsStmts, seqAppendPattern, [ + lineCg(p, cpsStmts, seqAppendPattern, [ rdLoc(a), getTypeDesc(p.module, skipTypes(e.sons[1].typ, abstractVar)), getTypeDesc(p.module, skipTypes(e.sons[2].Typ, abstractVar))]) @@ -901,7 +901,7 @@ proc genSeqElemAppend(p: BProc, e: PNode, d: var TLoc) = proc genReset(p: BProc, n: PNode) = var a: TLoc InitLocExpr(p, n.sons[1], a) - appcg(p, cpsStmts, "#genericReset((void*)$1, $2);$n", + lineCg(p, cpsStmts, "#genericReset((void*)$1, $2);$n", [addrLoc(a), genTypeInfo(p.module, skipTypes(a.t, abstractVarRange))]) proc genNew(p: BProc, e: PNode) = @@ -917,11 +917,11 @@ proc genNew(p: BProc, e: PNode) = if a.s == OnHeap and optRefcGc in gGlobalOptions: # use newObjRC1 as an optimization; and we don't need 'keepAlive' either if canFormAcycle(a.t): - appcg(p, cpsStmts, "if ($1) #nimGCunref($1);$n", a.rdLoc) + lineCg(p, cpsStmts, "if ($1) #nimGCunref($1);$n", a.rdLoc) else: - appcg(p, cpsStmts, "if ($1) #nimGCunrefNoCycle($1);$n", a.rdLoc) + lineCg(p, cpsStmts, "if ($1) #nimGCunrefNoCycle($1);$n", a.rdLoc) b.r = ropecg(p.module, "($1) #newObjRC1($2, sizeof($3))", args) - appcg(p, cpsStmts, "$1 = $2;$n", a.rdLoc, b.rdLoc) + lineCg(p, cpsStmts, "$1 = $2;$n", a.rdLoc, b.rdLoc) else: b.r = ropecg(p.module, "($1) #newObj($2, sizeof($3))", args) genAssignment(p, a, b, {needToKeepAlive}) # set the object type: @@ -935,9 +935,9 @@ proc genNewSeqAux(p: BProc, dest: TLoc, length: PRope) = var call: TLoc initLoc(call, locExpr, dest.t, OnHeap) if dest.s == OnHeap and optRefcGc in gGlobalOptions: - appcg(p, cpsStmts, "if ($1) #nimGCunrefNoCycle($1);$n", dest.rdLoc) + lineCg(p, cpsStmts, "if ($1) #nimGCunrefNoCycle($1);$n", dest.rdLoc) call.r = ropecg(p.module, "($1) #newSeqRC1($2, $3)", args) - appcg(p, cpsStmts, "$1 = $2;$n", dest.rdLoc, call.rdLoc) + lineCg(p, cpsStmts, "$1 = $2;$n", dest.rdLoc, call.rdLoc) else: call.r = ropecg(p.module, "($1) #newSeq($2, $3)", args) genAssignment(p, dest, call, {needToKeepAlive}) @@ -1124,7 +1124,7 @@ proc genSetLengthSeq(p: BProc, e: PNode, d: var TLoc) = else: "$1 = ($3) #setLengthSeq($1, sizeof($4), $2);$n" - appcg(p, cpsStmts, setLenPattern, [ + lineCg(p, cpsStmts, setLenPattern, [ rdLoc(a), rdLoc(b), getTypeDesc(p.module, t), getTypeDesc(p.module, t.sons[0])]) keepAlive(p, a) @@ -1181,7 +1181,7 @@ proc binaryStmtInExcl(p: BProc, e: PNode, d: var TLoc, frmt: string) = assert(d.k == locNone) InitLocExpr(p, e.sons[1], a) InitLocExpr(p, e.sons[2], b) - appf(p.s(cpsStmts), frmt, [rdLoc(a), rdSetElemLoc(b, a.t)]) + lineF(p, cpsStmts, frmt, [rdLoc(a), rdSetElemLoc(b, a.t)]) proc genInOp(p: BProc, e: PNode, d: var TLoc) = var a, b, x, y: TLoc @@ -1257,7 +1257,7 @@ proc genSetOp(p: BProc, e: PNode, d: var TLoc, op: TMagic) = initLocExpr(p, e.sons[1], a) initLocExpr(p, e.sons[2], b) if d.k == locNone: getTemp(p, a.t, d) - appf(p.s(cpsStmts), lookupOpr[op], + lineF(p, cpsStmts, lookupOpr[op], [rdLoc(i), toRope(size), rdLoc(d), rdLoc(a), rdLoc(b)]) of mEqSet: binaryExprChar(p, e, d, "(memcmp($1, $2, " & $(size) & ")==0)") @@ -1267,7 +1267,7 @@ proc genSetOp(p: BProc, e: PNode, d: var TLoc, op: TMagic) = initLocExpr(p, e.sons[1], a) initLocExpr(p, e.sons[2], b) if d.k == locNone: getTemp(p, a.t, d) - appf(p.s(cpsStmts), + lineF(p, cpsStmts, "for ($1 = 0; $1 < $2; $1++) $n" & " $3[$1] = $4[$1] $6 $5[$1];$n", [ rdLoc(i), toRope(size), rdLoc(d), rdLoc(a), rdLoc(b), @@ -1356,9 +1356,9 @@ proc binaryFloatArith(p: BProc, e: PNode, d: var TLoc, m: TMagic) = putIntoDest(p, d, e.typ, ropef("($2 $1 $3)", [ toRope(opr[m]), rdLoc(a), rdLoc(b)])) if optNanCheck in p.options: - appcg(p, cpsStmts, "#nanCheck($1);$n", [rdLoc(d)]) + lineCg(p, cpsStmts, "#nanCheck($1);$n", [rdLoc(d)]) if optInfCheck in p.options: - appcg(p, cpsStmts, "#infCheck($1);$n", [rdLoc(d)]) + lineCg(p, cpsStmts, "#infCheck($1);$n", [rdLoc(d)]) else: binaryArith(p, e, d, m) @@ -1479,35 +1479,35 @@ proc genSetConstr(p: BProc, e: PNode, d: var TLoc) = if d.k == locNone: getTemp(p, e.typ, d) if getSize(e.typ) > 8: # big set: - appf(p.s(cpsStmts), "memset($1, 0, sizeof($1));$n", [rdLoc(d)]) + lineF(p, cpsStmts, "memset($1, 0, sizeof($1));$n", [rdLoc(d)]) for i in countup(0, sonsLen(e) - 1): if e.sons[i].kind == nkRange: getTemp(p, getSysType(tyInt), idx) # our counter initLocExpr(p, e.sons[i].sons[0], a) initLocExpr(p, e.sons[i].sons[1], b) - appf(p.s(cpsStmts), "for ($1 = $3; $1 <= $4; $1++) $n" & + lineF(p, cpsStmts, "for ($1 = $3; $1 <= $4; $1++) $n" & "$2[$1/8] |=(1<<($1%8));$n", [rdLoc(idx), rdLoc(d), rdSetElemLoc(a, e.typ), rdSetElemLoc(b, e.typ)]) else: initLocExpr(p, e.sons[i], a) - appf(p.s(cpsStmts), "$1[$2/8] |=(1<<($2%8));$n", + lineF(p, cpsStmts, "$1[$2/8] |=(1<<($2%8));$n", [rdLoc(d), rdSetElemLoc(a, e.typ)]) else: # small set var ts = "NI" & $(getSize(e.typ) * 8) - appf(p.s(cpsStmts), "$1 = 0;$n", [rdLoc(d)]) + lineF(p, cpsStmts, "$1 = 0;$n", [rdLoc(d)]) for i in countup(0, sonsLen(e) - 1): if e.sons[i].kind == nkRange: getTemp(p, getSysType(tyInt), idx) # our counter initLocExpr(p, e.sons[i].sons[0], a) initLocExpr(p, e.sons[i].sons[1], b) - appf(p.s(cpsStmts), "for ($1 = $3; $1 <= $4; $1++) $n" & + lineF(p, cpsStmts, "for ($1 = $3; $1 <= $4; $1++) $n" & "$2 |=(1<<((" & ts & ")($1)%(sizeof(" & ts & ")*8)));$n", [ rdLoc(idx), rdLoc(d), rdSetElemLoc(a, e.typ), rdSetElemLoc(b, e.typ)]) else: initLocExpr(p, e.sons[i], a) - appf(p.s(cpsStmts), + lineF(p, cpsStmts, "$1 |=(1<<((" & ts & ")($2)%(sizeof(" & ts & ")*8)));$n", [rdLoc(d), rdSetElemLoc(a, e.typ)]) @@ -1548,7 +1548,7 @@ proc genClosure(p: BProc, n: PNode, d: var TLoc) = initLocExpr(p, n.sons[0], a) initLocExpr(p, n.sons[1], b) getTemp(p, n.typ, tmp) - appcg(p, cpsStmts, "$1.ClPrc = $2; $1.ClEnv = $3;$n", + lineCg(p, cpsStmts, "$1.ClPrc = $2; $1.ClEnv = $3;$n", tmp.rdLoc, a.rdLoc, b.rdLoc) putLocIntoDest(p, d, tmp) @@ -1588,10 +1588,10 @@ proc upConv(p: BProc, n: PNode, d: var TLoc) = app(r, ".Sup") t = skipTypes(t.sons[0], abstractInst) if nilCheck != nil: - appcg(p, cpsStmts, "if ($1) #chckObj($2.m_type, $3);$n", + lineCg(p, cpsStmts, "if ($1) #chckObj($2.m_type, $3);$n", [nilCheck, r, genTypeInfo(p.module, dest)]) else: - appcg(p, cpsStmts, "#chckObj($1.m_type, $2);$n", + lineCg(p, cpsStmts, "#chckObj($1.m_type, $2);$n", [r, genTypeInfo(p.module, dest)]) if n.sons[0].typ.kind != tyObject: putIntoDest(p, d, n.typ, diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim index eb4fd7a345..591dd70893 100755 --- a/compiler/ccgstmts.nim +++ b/compiler/ccgstmts.nim @@ -49,12 +49,12 @@ proc loadInto(p: BProc, le, ri: PNode, a: var TLoc) {.inline.} = proc startBlock(p: BProc, start: TFormatStr = "{$n", args: openarray[PRope]): int {.discardable.} = + lineCg(p, cpsStmts, start, args) inc(p.labels) result = len(p.blocks) setlen(p.blocks, result + 1) p.blocks[result].id = p.labels p.blocks[result].nestedTryStmts = p.nestedTryStmts.len - appcg(p, cpsLocals, start, args) proc assignLabel(b: var TBlock): PRope {.inline.} = b.label = con("LA", b.id.toRope) @@ -70,7 +70,7 @@ proc endBlock(p: BProc, blockEnd: PRope) = setlen(p.blocks, topBlock) # this is done after the block is popped so $n is # properly indented when pretty printing is enabled - app(p.s(cpsStmts), blockEnd) + line(p, cpsStmts, blockEnd) var gBlockEndBracket = ropef("}$n") @@ -184,12 +184,12 @@ proc genIfStmt(p: BProc, n: PNode) = initLocExpr(p, it.sons[0], a) Lelse = getLabel(p) inc(p.labels) - appff(p.s(cpsStmts), "if (!$1) goto $2;$n", - "br i1 $1, label %LOC$3, label %$2$n" & "LOC$3: $n", + lineFF(p, cpsStmts, "if (!$1) goto $2;$n", + "br i1 $1, label %LOC$3, label %$2$n" & "LOC$3: $n", [rdLoc(a), Lelse, toRope(p.labels)]) genSimpleBlock(p, it.sons[1]) if sonsLen(n) > 1: - appff(p.s(cpsStmts), "goto $1;$n", "br label %$1$n", [Lend]) + lineFF(p, cpsStmts, "goto $1;$n", "br label %$1$n", [Lend]) fixLabel(p, Lelse) of nkElse: genSimpleBlock(p, it.sons[0]) @@ -211,7 +211,7 @@ proc blockLeaveActions(p: BProc, howMany: int) = if alreadyPoppedCnt > 0: dec alreadyPoppedCnt else: - appcg(p, cpsStmts, "#popSafePoint();$n", []) + lineCg(p, cpsStmts, "#popSafePoint();$n", []) var finallyStmt = lastSon(tryStmt) if finallyStmt.kind == nkFinally: genStmts(p, finallyStmt.sons[0]) @@ -220,14 +220,14 @@ proc blockLeaveActions(p: BProc, howMany: int) = p.nestedTryStmts.add(stack[i]) if gCmd != cmdCompileToCpp: for i in countdown(p.inExceptBlock-1, 0): - appcg(p, cpsStmts, "#popCurrentException();$n", []) + lineCg(p, cpsStmts, "#popCurrentException();$n", []) proc genReturnStmt(p: BProc, t: PNode) = p.beforeRetNeeded = true genLineDir(p, t) if (t.sons[0].kind != nkEmpty): genStmts(p, t.sons[0]) blockLeaveActions(p, min(1, p.nestedTryStmts.len)) - appff(p.s(cpsStmts), "goto BeforeRet;$n", "br label %BeforeRet$n", []) + lineFF(p, cpsStmts, "goto BeforeRet;$n", "br label %BeforeRet$n", []) proc genWhileStmt(p: BProc, t: PNode) = # we don't generate labels here as for example GCC would produce @@ -245,7 +245,7 @@ proc genWhileStmt(p: BProc, t: PNode) = initLocExpr(p, t.sons[0], a) if (t.sons[0].kind != nkIntLit) or (t.sons[0].intVal == 0): let label = assignLabel(p.blocks[p.breakIdx]) - appf(p.s(cpsStmts), "if (!$1) goto $2;$n", [rdLoc(a), label]) + lineF(p, cpsStmts, "if (!$1) goto $2;$n", [rdLoc(a), label]) genStmts(p, t.sons[1]) endBlock(p) @@ -279,7 +279,7 @@ proc genParForStmt(p: BProc, t: PNode) = initLocExpr(p, call.sons[1], rangeA) initLocExpr(p, call.sons[2], rangeB) - appf(p.s(cpsStmts), "#pragma omp parallel for $4$n" & + lineF(p, cpsStmts, "#pragma omp parallel for $4$n" & "for ($1 = $2; $1 <= $3; ++$1)", forLoopVar.loc.rdLoc, rangeA.rdLoc, rangeB.rdLoc, @@ -308,7 +308,7 @@ proc genBreakStmt(p: BProc, t: PNode) = let label = assignLabel(p.blocks[idx]) blockLeaveActions(p, p.nestedTryStmts.len - p.blocks[idx].nestedTryStmts) genLineDir(p, t) - appf(p.s(cpsStmts), "goto $1;$n", [label]) + lineF(p, cpsStmts, "goto $1;$n", [label]) proc getRaiseFrmt(p: BProc): string = if gCmd == cmdCompileToCpp: @@ -329,14 +329,14 @@ proc genRaiseStmt(p: BProc, t: PNode) = var e = rdLoc(a) var typ = skipTypes(t.sons[0].typ, abstractPtrs) genLineDir(p, t) - appcg(p, cpsStmts, getRaiseFrmt(p), [e, makeCString(typ.sym.name.s)]) + lineCg(p, cpsStmts, getRaiseFrmt(p), [e, makeCString(typ.sym.name.s)]) else: genLineDir(p, t) # reraise the last exception: if gCmd == cmdCompileToCpp: - appcg(p, cpsStmts, "throw;$n") + lineCg(p, cpsStmts, "throw;$n") else: - appcg(p, cpsStmts, "#reraiseException();$n") + lineCg(p, cpsStmts, "#reraiseException();$n") proc genCaseGenericBranch(p: BProc, b: PNode, e: TLoc, rangeFormat, eqFormat: TFormatStr, labl: TLabel) = @@ -347,20 +347,20 @@ proc genCaseGenericBranch(p: BProc, b: PNode, e: TLoc, if b.sons[i].kind == nkRange: initLocExpr(p, b.sons[i].sons[0], x) initLocExpr(p, b.sons[i].sons[1], y) - appcg(p, cpsStmts, rangeFormat, + lineCg(p, cpsStmts, rangeFormat, [rdCharLoc(e), rdCharLoc(x), rdCharLoc(y), labl]) else: initLocExpr(p, b.sons[i], x) - appcg(p, cpsStmts, eqFormat, [rdCharLoc(e), rdCharLoc(x), labl]) + lineCg(p, cpsStmts, eqFormat, [rdCharLoc(e), rdCharLoc(x), labl]) proc genCaseSecondPass(p: BProc, t: PNode, labId, until: int): TLabel = var Lend = getLabel(p) for i in 1..until: - appf(p.s(cpsStmts), "LA$1: ;$n", [toRope(labId + i)]) + lineF(p, cpsStmts, "LA$1: ;$n", [toRope(labId + i)]) if t.sons[i].kind == nkOfBranch: var length = sonsLen(t.sons[i]) genSimpleBlock(p, t.sons[i].sons[length - 1]) - appf(p.s(cpsStmts), "goto $1;$n", [Lend]) + lineF(p, cpsStmts, "goto $1;$n", [Lend]) else: genSimpleBlock(p, t.sons[i].sons[0]) result = Lend @@ -375,13 +375,13 @@ proc genIfForCaseUntil(p: BProc, t: PNode, rangeFormat, eqFormat: TFormatStr, genCaseGenericBranch(p, t.sons[i], a, rangeFormat, eqFormat, con("LA", toRope(p.labels))) else: - appf(p.s(cpsStmts), "goto LA$1;$n", [toRope(p.labels)]) + lineF(p, cpsStmts, "goto LA$1;$n", [toRope(p.labels)]) if until < t.len-1: inc(p.labels) var gotoTarget = p.labels - appf(p.s(cpsStmts), "goto LA$1;$n", [toRope(gotoTarget)]) + lineF(p, cpsStmts, "goto LA$1;$n", [toRope(gotoTarget)]) result = genCaseSecondPass(p, t, labId, until) - appf(p.s(cpsStmts), "LA$1: ;$n", [toRope(gotoTarget)]) + lineF(p, cpsStmts, "LA$1: ;$n", [toRope(gotoTarget)]) else: result = genCaseSecondPass(p, t, labId, until) @@ -423,7 +423,7 @@ proc genStringCase(p: BProc, t: PNode) = else: # else statement: nothing to do yet # but we reserved a label, which we use later - appcg(p, cpsStmts, "switch (#hashString($1) & $2) {$n", + lineCg(p, cpsStmts, "switch (#hashString($1) & $2) {$n", [rdLoc(a), toRope(bitMask)]) for j in countup(0, high(branches)): when false: @@ -433,11 +433,11 @@ proc genStringCase(p: BProc, t: PNode) = if interior != brn: echo "BUG! ", interior, "-", brn if branches[j] != nil: - appf(p.s(cpsStmts), "case $1: $n$2break;$n", + lineF(p, cpsStmts, "case $1: $n$2break;$n", [intLiteral(j), branches[j]]) - appf(p.s(cpsStmts), "}$n") # else statement: + lineF(p, cpsStmts, "}$n") # else statement: if t.sons[sonsLen(t) - 1].kind != nkOfBranch: - appf(p.s(cpsStmts), "goto LA$1;$n", [toRope(p.labels)]) + lineF(p, cpsStmts, "goto LA$1;$n", [toRope(p.labels)]) # third pass: generate statements var Lend = genCaseSecondPass(p, t, labId, sonsLen(t)-1) fixLabel(p, Lend) @@ -466,16 +466,16 @@ proc genCaseRange(p: BProc, branch: PNode) = for j in 0 .. length-2: if branch[j].kind == nkRange: if hasSwitchRange in CC[ccompiler].props: - appf(p.s(cpsStmts), "case $1 ... $2:$n", [ + lineF(p, cpsStmts, "case $1 ... $2:$n", [ genLiteral(p, branch[j][0]), genLiteral(p, branch[j][1])]) else: var v = copyNode(branch[j][0]) while v.intVal <= branch[j][1].intVal: - appf(p.s(cpsStmts), "case $1:$n", [genLiteral(p, v)]) + lineF(p, cpsStmts, "case $1:$n", [genLiteral(p, v)]) Inc(v.intVal) else: - appf(p.s(cpsStmts), "case $1:$n", [genLiteral(p, branch[j])]) + lineF(p, cpsStmts, "case $1:$n", [genLiteral(p, branch[j])]) proc genOrdinalCase(p: BProc, n: PNode) = # analyse 'case' statement: @@ -491,7 +491,7 @@ proc genOrdinalCase(p: BProc, n: PNode) = # generate switch part (might be empty): if splitPoint+1 < n.len: - appf(p.s(cpsStmts), "switch ($1) {$n", [rdCharLoc(a)]) + lineF(p, cpsStmts, "switch ($1) {$n", [rdCharLoc(a)]) var hasDefault = false for i in splitPoint+1 .. < n.len: var branch = n[i] @@ -500,13 +500,13 @@ proc genOrdinalCase(p: BProc, n: PNode) = genSimpleBlock(p, branch.lastSon) else: # else part of case statement: - appf(p.s(cpsStmts), "default:$n") + lineF(p, cpsStmts, "default:$n") genSimpleBlock(p, branch[0]) hasDefault = true - appf(p.s(cpsStmts), "break;$n") + lineF(p, cpsStmts, "break;$n") if (hasAssume in CC[ccompiler].props) and not hasDefault: - appf(p.s(cpsStmts), "default: __assume(0);$n") - appf(p.s(cpsStmts), "}$n") + lineF(p, cpsStmts, "default: __assume(0);$n") + lineF(p, cpsStmts, "}$n") if Lend != nil: fixLabel(p, Lend) proc genCaseStmt(p: BProc, t: PNode) = @@ -563,7 +563,7 @@ proc genTryStmtCpp(p: BProc, t: PNode) = length = sonsLen(t) endBlock(p, ropecg(p.module, "} catch (NimException& $1) {$n", [exc])) if optStackTrace in p.Options: - appcg(p, cpsStmts, "#setFrame((TFrame*)&F);$n") + lineCg(p, cpsStmts, "#setFrame((TFrame*)&F);$n") inc p.inExceptBlock i = 1 var catchAllPresent = false @@ -582,22 +582,22 @@ proc genTryStmtCpp(p: BProc, t: PNode) = appcg(p.module, orExpr, "#isObj($1.exp->m_type, $2)", [exc, genTypeInfo(p.module, t.sons[i].sons[j].typ)]) - appf(p.s(cpsStmts), "if ($1) ", [orExpr]) + lineF(p, cpsStmts, "if ($1) ", [orExpr]) genSimpleBlock(p, t.sons[i].sons[blen-1]) inc(i) # reraise the exception if there was no catch all # and none of the handlers matched if not catchAllPresent: - if i > 1: appf(p.s(cpsStmts), "else ") + if i > 1: lineF(p, cpsStmts, "else ") startBlock(p) var finallyBlock = t.lastSon if finallyBlock.kind == nkFinally: genStmts(p, finallyBlock.sons[0]) - appcg(p, cpsStmts, "throw;$n") + lineCg(p, cpsStmts, "throw;$n") endBlock(p) - appf(p.s(cpsStmts), "}$n") # end of catch block + lineF(p, cpsStmts, "}$n") # end of catch block dec p.inExceptBlock discard pop(p.nestedTryStmts) @@ -636,48 +636,52 @@ proc genTryStmt(p: BProc, t: PNode) = genLineDir(p, t) var safePoint = getTempName() discard cgsym(p.module, "E_Base") - appcg(p, cpsLocals, "#TSafePoint $1;$n", [safePoint]) - appcg(p, cpsStmts, "#pushSafePoint(&$1);$n" & - "$1.status = setjmp($1.context);$n", [safePoint]) + lineCg(p, cpsLocals, "#TSafePoint $1;$n", [safePoint]) + lineCg(p, cpsStmts, "#pushSafePoint(&$1);$n", [safePoint]) + lineF(p, cpsStmts, "$1.status = setjmp($1.context);$n", [safePoint]) startBlock(p, "if ($1.status == 0) {$n", [safePoint]) var length = sonsLen(t) add(p.nestedTryStmts, t) genStmts(p, t.sons[0]) - endBlock(p, ropecg(p.module, "#popSafePoint();$n } else {$n#popSafePoint();$n")) - if optStackTrace in p.Options: - appcg(p, cpsStmts, "#setFrame((TFrame*)&F);$n") + linecg(p, cpsStmts, "#popSafePoint();$n") + endBlock(p) + startBlock(p, "else {$n") + lineCg(p, cpsStmts, "#popSafePoint();$n") + if optStackTrace in p.Options: + lineCg(p, cpsStmts, "#setFrame((TFrame*)&F);$n") inc p.inExceptBlock var i = 1 - while (i < length) and (t.sons[i].kind == nkExceptBranch): + while (i < length) and (t.sons[i].kind == nkExceptBranch): var blen = sonsLen(t.sons[i]) - if blen == 1: + if blen == 1: # general except section: - if i > 1: appf(p.s(cpsStmts), "else") + if i > 1: lineF(p, cpsStmts, "else") startBlock(p) - appcg(p, cpsStmts, "$1.status = 0;$n", [safePoint]) + lineCg(p, cpsStmts, "$1.status = 0;$n", [safePoint]) genStmts(p, t.sons[i].sons[0]) - appcg(p, cpsStmts, "#popCurrentException();$n", []) + lineCg(p, cpsStmts, "#popCurrentException();$n") endBlock(p) else: var orExpr: PRope = nil - for j in countup(0, blen - 2): + for j in countup(0, blen - 2): assert(t.sons[i].sons[j].kind == nkType) if orExpr != nil: app(orExpr, "||") - appcg(p.module, orExpr, - "#isObj(#getCurrentException()->Sup.m_type, $1)", + appcg(p.module, orExpr, + "#isObj(#getCurrentException()->Sup.m_type, $1)", [genTypeInfo(p.module, t.sons[i].sons[j].typ)]) - if i > 1: app(p.s(cpsStmts), "else ") + if i > 1: line(p, cpsStmts, "else ") startBlock(p, "if ($1) {$n", [orExpr]) - appcg(p, cpsStmts, "$1.status = 0;$n", [safePoint]) + lineCg(p, cpsStmts, "$1.status = 0;$n", [safePoint]) genStmts(p, t.sons[i].sons[blen-1]) - endBlock(p, ropecg(p.module, "#popCurrentException();}$n")) + lineCg(p, cpsStmts, "#popCurrentException();$n") + endBlock(p) inc(i) dec p.inExceptBlock discard pop(p.nestedTryStmts) - appf(p.s(cpsStmts), "}$n") # end of else block + endBlock(p) # end of else block if i < length and t.sons[i].kind == nkFinally: genSimpleBlock(p, t.sons[i].sons[0]) - appcg(p, cpsStmts, "if ($1.status != 0) #reraiseException();$n", [safePoint]) + lineCg(p, cpsStmts, "if ($1.status != 0) #reraiseException();$n", [safePoint]) proc genAsmOrEmitStmt(p: BProc, t: PNode): PRope = for i in countup(0, sonsLen(t) - 1): @@ -704,7 +708,7 @@ proc genAsmStmt(p: BProc, t: PNode) = assert(t.kind == nkAsmStmt) genLineDir(p, t) var s = genAsmOrEmitStmt(p, t) - appf(p.s(cpsStmts), CC[ccompiler].asmStmtFrmt, [s]) + lineF(p, cpsStmts, CC[ccompiler].asmStmtFrmt, [s]) proc genEmit(p: BProc, t: PNode) = genLineDir(p, t) @@ -713,7 +717,7 @@ proc genEmit(p: BProc, t: PNode) = # top level emit pragma? app(p.module.s[cfsProcHeaders], s) else: - app(p.s(cpsStmts), s) + line(p, cpsStmts, s) var breakPointId: int = 0 @@ -739,7 +743,7 @@ proc genWatchpoint(p: BProc, n: PNode) = var a: TLoc initLocExpr(p, n.sons[1], a) let typ = skipTypes(n.sons[1].typ, abstractVarRange) - appcg(p, cpsStmts, "#dbgRegisterWatchpoint($1, (NCSTRING)$2, $3);$n", + lineCg(p, cpsStmts, "#dbgRegisterWatchpoint($1, (NCSTRING)$2, $3);$n", [a.addrLoc, makeCString(renderTree(n.sons[1])), genTypeInfo(p.module, typ)]) @@ -779,7 +783,7 @@ proc genDiscriminantCheck(p: BProc, a, tmp: TLoc, objtype: PType, if not ContainsOrIncl(p.module.declaredThings, field.id): appcg(p.module, cfsVars, "extern $1", discriminatorTableDecl(p.module, t, field)) - appcg(p, cpsStmts, + lineCg(p, cpsStmts, "#FieldDiscriminantCheck((NI)(NU)($1), (NI)(NU)($2), $3, $4);$n", [rdLoc(a), rdLoc(tmp), discriminatorTableName(p.module, t, field), intLiteral(L+1)]) diff --git a/compiler/ccgthreadvars.nim b/compiler/ccgthreadvars.nim index 38c5c0f5e3..900343b656 100755 --- a/compiler/ccgthreadvars.nim +++ b/compiler/ccgthreadvars.nim @@ -19,9 +19,8 @@ proc AccessThreadLocalVar(p: BProc, s: PSym) = if emulatedThreadVars() and not p.ThreadVarAccessed: p.ThreadVarAccessed = true p.module.usesThreadVars = true - appf(p.procSec(cpsLocals), "NimThreadVars* NimTV;$n") - app(p.procSec(cpsInit), - ropecg(p.module, "NimTV=(NimThreadVars*)#GetThreadLocalVars();$n")) + lineF(p, cpsLocals, "NimThreadVars* NimTV;$n") + lineCg(p, cpsInit, "NimTV = (NimThreadVars*) #GetThreadLocalVars();$n") var nimtv: PRope # nimrod thread vars; the struct body diff --git a/compiler/ccgtrav.nim b/compiler/ccgtrav.nim index d95ea8b09b..75357ff46a 100644 --- a/compiler/ccgtrav.nim +++ b/compiler/ccgtrav.nim @@ -31,17 +31,17 @@ proc genTraverseProc(c: var TTraversalClosure, accessor: PRope, n: PNode) = if (n.sons[0].kind != nkSym): InternalError(n.info, "genTraverseProc") var p = c.p let disc = n.sons[0].sym - p.s(cpsStmts).appf("switch ($1.$2) {$n", accessor, disc.loc.r) + lineF(p, cpsStmts, "switch ($1.$2) {$n", accessor, disc.loc.r) for i in countup(1, sonsLen(n) - 1): let branch = n.sons[i] assert branch.kind in {nkOfBranch, nkElse} if branch.kind == nkOfBranch: genCaseRange(c.p, branch) else: - p.s(cpsStmts).appf("default:$n") + lineF(p, cpsStmts, "default:$n") genTraverseProc(c, accessor, lastSon(branch)) - p.s(cpsStmts).appf("break;$n") - p.s(cpsStmts).appf("} $n") + lineF(p, cpsStmts, "break;$n") + lineF(p, cpsStmts, "} $n") of nkSym: let field = n.sym genTraverseProc(c, ropef("$1.$2", accessor, field.loc.r), field.loc.t) @@ -63,10 +63,10 @@ proc genTraverseProc(c: var TTraversalClosure, accessor: PRope, typ: PType) = let arraySize = lengthOrd(typ.sons[0]) var i: TLoc getTemp(p, getSysType(tyInt), i) - appf(p.s(cpsStmts), "for ($1 = 0; $1 < $2; $1++) {$n", + lineF(p, cpsStmts, "for ($1 = 0; $1 < $2; $1++) {$n", i.r, arraySize.toRope) genTraverseProc(c, ropef("$1[$2]", accessor, i.r), typ.sons[1]) - appf(p.s(cpsStmts), "}$n") + lineF(p, cpsStmts, "}$n") of tyObject: for i in countup(0, sonsLen(typ) - 1): genTraverseProc(c, accessor.parentObj, typ.sons[i]) @@ -79,7 +79,7 @@ proc genTraverseProc(c: var TTraversalClosure, accessor: PRope, typ: PType) = for i in countup(0, sonsLen(typ) - 1): genTraverseProc(c, ropef("$1.Field$2", accessor, i.toRope), typ.sons[i]) of tyRef, tyString, tySequence: - appcg(p, cpsStmts, c.visitorFrmt, accessor) + lineCg(p, cpsStmts, c.visitorFrmt, accessor) else: # no marker procs for closures yet nil @@ -89,10 +89,10 @@ proc genTraverseProcSeq(c: var TTraversalClosure, accessor: PRope, typ: PType) = assert typ.kind == tySequence var i: TLoc getTemp(p, getSysType(tyInt), i) - appf(p.s(cpsStmts), "for ($1 = 0; $1 < $2->$3; $1++) {$n", + lineF(p, cpsStmts, "for ($1 = 0; $1 < $2->$3; $1++) {$n", i.r, accessor, toRope(if gCmd != cmdCompileToCpp: "Sup.len" else: "len")) genTraverseProc(c, ropef("$1->data[$2]", accessor, i.r), typ.sons[0]) - appf(p.s(cpsStmts), "}$n") + lineF(p, cpsStmts, "}$n") proc genTraverseProc(m: BModule, typ: PType, reason: TTypeInfoReason): PRope = var c: TTraversalClosure @@ -106,8 +106,8 @@ proc genTraverseProc(m: BModule, typ: PType, reason: TTypeInfoReason): PRope = let header = ropef("N_NIMCALL(void, $1)(void* p, NI op)", result) let t = getTypeDesc(m, typ) - p.s(cpsLocals).appf("$1 a;$n", t) - p.s(cpsInit).appf("a = ($1)p;$n", t) + lineF(p, cpsLocals, "$1 a;$n", t) + lineF(p, cpsInit, "a = ($1)p;$n", t) c.p = p if typ.kind == tySequence: diff --git a/compiler/cgen.nim b/compiler/cgen.nim index e8073b5557..bf55354c08 100755 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -153,6 +153,34 @@ proc appcg(p: BProc, s: TCProcSection, frmt: TFormatStr, args: openarray[PRope]) = app(p.s(s), ropecg(p.module, frmt, args)) +var indent = "\t".toRope +proc indentLine(p: BProc, r: PRope): PRope = + result = r + for i in countup(0, p.blocks.len-1): prepend(result, indent) + +proc line(p: BProc, s: TCProcSection, r: PRope) = + app(p.s(s), indentLine(p, r)) + +proc line(p: BProc, s: TCProcSection, r: string) = + app(p.s(s), indentLine(p, r.toRope)) + +proc lineF(p: BProc, s: TCProcSection, frmt: TFormatStr, + args: openarray[PRope]) = + app(p.s(s), indentLine(p, ropef(frmt, args))) + +proc lineCg(p: BProc, s: TCProcSection, frmt: TFormatStr, + args: openarray[PRope]) = + app(p.s(s), indentLine(p, ropecg(p.module, frmt, args))) + +proc appLineCg(p: BProc, r: var PRope, frmt: TFormatStr, + args: openarray[PRope]) = + app(r, indentLine(p, ropecg(p.module, frmt, args))) + +proc lineFF(p: BProc, s: TCProcSection, cformat, llvmformat: string, + args: openarray[PRope]) = + if gCmd == cmdCompileToLLVM: lineF(p, s, llvmformat, args) + else: lineF(p, s, cformat, args) + proc safeLineNm(info: TLineInfo): int = result = toLinenumber(info) if result < 0: result = 0 # negative numbers are not allowed in #line @@ -171,11 +199,11 @@ proc genLineDir(p: BProc, t: PNode) = genCLineDir(p.s(cpsStmts), t.info.toFullPath, line) if ({optStackTrace, optEndb} * p.Options == {optStackTrace, optEndb}) and (p.prc == nil or sfPure notin p.prc.flags): - appcg(p, cpsStmts, "#endb($1);$n", [toRope(line)]) + lineCg(p, cpsStmts, "#endb($1);$n", [toRope(line)]) elif ({optLineTrace, optStackTrace} * p.Options == {optLineTrace, optStackTrace}) and (p.prc == nil or sfPure notin p.prc.flags): - appf(p.s(cpsStmts), "F.line = $1;F.filename = $2;$n", + lineF(p, cpsStmts, "F.line = $1;F.filename = $2;$n", [toRope(line), makeCString(toFilename(t.info).extractFilename)]) include "ccgtypes.nim" @@ -211,11 +239,11 @@ proc genObjectInit(p: BProc, section: TCProcSection, t: PType, a: TLoc, while (s.kind == tyObject) and (s.sons[0] != nil): app(r, ".Sup") s = skipTypes(s.sons[0], abstractInst) - appcg(p, section, "$1.m_type = $2;$n", [r, genTypeInfo(p.module, t)]) + lineCg(p, section, "$1.m_type = $2;$n", [r, genTypeInfo(p.module, t)]) of frEmbedded: # worst case for performance: var r = if takeAddr: addrLoc(a) else: rdLoc(a) - appcg(p, section, "#objectInit($1, $2);$n", [r, genTypeInfo(p.module, t)]) + lineCg(p, section, "#objectInit($1, $2);$n", [r, genTypeInfo(p.module, t)]) type TAssignmentFlag = enum @@ -238,16 +266,16 @@ proc resetLoc(p: BProc, loc: var TLoc) = nilLoc.r = toRope("NIM_NIL") genRefAssign(p, loc, nilLoc, {afSrcIsNil}) else: - appf(p.s(cpsStmts), "$1 = 0;$n", [rdLoc(loc)]) + lineF(p, cpsStmts, "$1 = 0;$n", [rdLoc(loc)]) else: if loc.s != OnStack: - appcg(p, cpsStmts, "#genericReset((void*)$1, $2);$n", + lineCg(p, cpsStmts, "#genericReset((void*)$1, $2);$n", [addrLoc(loc), genTypeInfo(p.module, loc.t)]) # XXX: generated reset procs should not touch the m_type # field, so disabling this should be safe: genObjectInit(p, cpsStmts, loc.t, loc, true) else: - appf(p.s(cpsStmts), "memset((void*)$1, 0, sizeof($2));$n", + lineF(p, cpsStmts, "memset((void*)$1, 0, sizeof($2));$n", [addrLoc(loc), rdLoc(loc)]) # XXX: We can be extra clever here and call memset only # on the bytes following the m_type field? @@ -255,9 +283,9 @@ proc resetLoc(p: BProc, loc: var TLoc) = proc constructLoc(p: BProc, loc: TLoc, section = cpsStmts) = if not isComplexValueType(skipTypes(loc.t, abstractVarRange)): - appf(p.s(section), "$1 = 0;$n", [rdLoc(loc)]) + lineF(p, section, "$1 = 0;$n", [rdLoc(loc)]) else: - appf(p.s(section), "memset((void*)$1, 0, sizeof($2));$n", + lineF(p, section, "memset((void*)$1, 0, sizeof($2));$n", [addrLoc(loc), rdLoc(loc)]) genObjectInit(p, section, loc.t, loc, true) @@ -285,7 +313,7 @@ proc getTemp(p: BProc, t: PType, result: var TLoc) = result.r = con("%LOC", toRope(p.labels)) else: result.r = con("LOC", toRope(p.labels)) - appf(p.s(cpsLocals), "$1 $2;$n", [getTypeDesc(p.module, t), result.r]) + lineF(p, cpsLocals, "$1 $2;$n", [getTypeDesc(p.module, t), result.r]) result.k = locTemp result.a = - 1 result.t = getUniqueType(t) @@ -311,9 +339,9 @@ proc keepAlive(p: BProc, toKeepAlive: TLoc) = result.flags = {} if not isComplexValueType(skipTypes(toKeepAlive.t, abstractVarRange)): - appf(p.s[cpsStmts], "$1 = $2;$n", [rdLoc(result), rdLoc(toKeepAlive)]) + lineF(p, cpsStmts, "$1 = $2;$n", [rdLoc(result), rdLoc(toKeepAlive)]) else: - appcg(p, cpsStmts, + lineCg(p, cpsStmts, "memcpy((void*)$1, (NIM_CONST void*)$2, sizeof($3));$n", [addrLoc(result), addrLoc(toKeepAlive), rdLoc(result)]) @@ -355,7 +383,7 @@ proc allocParam(p: BProc, s: PSym) = var tmp = con("%LOC", toRope(p.labels)) incl(s.loc.flags, lfParamCopy) incl(s.loc.flags, lfIndirect) - appf(p.s(cpsInit), "$1 = alloca $3$n" & "store $3 $2, $3* $1$n", + lineF(p, cpsInit, "$1 = alloca $3$n" & "store $3 $2, $3* $1$n", [tmp, s.loc.r, getTypeDesc(p.module, s.loc.t)]) s.loc.r = tmp @@ -365,7 +393,7 @@ proc localDebugInfo(p: BProc, s: PSym) = if skipTypes(s.typ, abstractVar).kind == tyOpenArray: return var a = con("&", s.loc.r) if (s.kind == skParam) and ccgIntroducedPtr(s): a = s.loc.r - appf(p.s(cpsInit), + lineF(p, cpsInit, "F.s[$1].address = (void*)$3; F.s[$1].typ = $4; F.s[$1].name = $2;$n", [toRope(p.frameLen), makeCString(normalize(s.name.s)), a, genTypeInfo(p.module, s.loc.t)]) @@ -378,13 +406,14 @@ proc assignLocalVar(p: BProc, s: PSym) = if s.loc.k == locNone: fillLoc(s.loc, locLocalVar, s.typ, mangleName(s), OnStack) if s.kind == skLet: incl(s.loc.flags, lfNoDeepCopy) - app(p.s(cpsLocals), getTypeDesc(p.module, s.loc.t)) - if sfRegister in s.flags: app(p.s(cpsLocals), " register") + var decl = getTypeDesc(p.module, s.loc.t) + if sfRegister in s.flags: app(decl, " register") #elif skipTypes(s.typ, abstractInst).kind in GcTypeKinds: - # app(p.s[cpsLocals], " GC_GUARD") + # app(decl, " GC_GUARD") if (sfVolatile in s.flags) or (p.nestedTryStmts.len > 0): - app(p.s(cpsLocals), " volatile") - appf(p.s(cpsLocals), " $1;$n", [s.loc.r]) + app(decl, " volatile") + appf(decl, " $1;$n", [s.loc.r]) + line(p, cpsLocals, decl) localDebugInfo(p, s) include ccgthreadvars @@ -427,7 +456,7 @@ proc getLabel(p: BProc): TLabel = result = con("LA", toRope(p.labels)) proc fixLabel(p: BProc, labl: TLabel) = - appf(p.s(cpsStmts), "$1: ;$n", [labl]) + lineF(p, cpsStmts, "$1: ;$n", [labl]) proc genVarPrototype(m: BModule, sym: PSym) proc requestConstImpl(p: BProc, sym: PSym) @@ -545,28 +574,28 @@ proc getFrameDecl(p: BProc) = [toRope(p.frameLen)]) else: slots = nil - appff(p.s(cpsLocals), "volatile struct {TFrame* prev;" & - "NCSTRING procname;NI line;NCSTRING filename;" & - "NI len;$n$1} F;$n", + lineFF(p, cpsLocals, "volatile struct {TFrame* prev;" & + "NCSTRING procname;NI line;NCSTRING filename;" & + "NI len;$1} F;$n", "%TF = type {%TFrame*, i8*, %NI, %NI$1}$n" & "%F = alloca %TF$n", [slots]) inc(p.labels) - prepend(p.s(cpsInit), ropeff("F.len = $1;$n", + prepend(p.s(cpsInit), indentLine(p, ropeff("F.len = $1;$n", "%LOC$2 = getelementptr %TF %F, %NI 4$n" & - "store %NI $1, %NI* %LOC$2$n", [toRope(p.frameLen), toRope(p.labels)])) + "store %NI $1, %NI* %LOC$2$n", [toRope(p.frameLen), toRope(p.labels)]))) proc retIsNotVoid(s: PSym): bool = result = (s.typ.sons[0] != nil) and not isInvalidReturnType(s.typ.sons[0]) proc initFrame(p: BProc, procname, filename: PRope): PRope = result = ropecg(p.module, - "F.procname = $1;$n" & - "F.filename = $2;$n" & - "F.line = 0;$n" & - "#pushFrame((TFrame*)&F);$n", [procname, filename]) + "\tF.procname = $1;$n" & + "\tF.filename = $2;$n" & + "\tF.line = 0;$n" & + "\t#pushFrame((TFrame*)&F);$n", [procname, filename]) proc deinitFrame(p: BProc): PRope = - result = ropecg(p.module, "#popFrame();$n") + result = ropecg(p.module, "\t#popFrame();$n") proc closureSetup(p: BProc, prc: PSym) = if prc.typ.callConv != ccClosure: return @@ -575,8 +604,8 @@ proc closureSetup(p: BProc, prc: PSym) = #echo "created environment: ", env.id, " for ", prc.name.s assignLocalVar(p, env) # generate cast assignment: - appcg(p, cpsStmts, "$1 = ($2) ClEnv;$n", rdLoc(env.loc), - getTypeDesc(p.module, env.typ)) + lineCg(p, cpsStmts, "$1 = ($2) ClEnv;$n", rdLoc(env.loc), + getTypeDesc(p.module, env.typ)) proc genProcAux(m: BModule, prc: PSym) = var p = newProc(prc, m) @@ -590,7 +619,7 @@ proc genProcAux(m: BModule, prc: PSym) = # declare the result symbol: assignLocalVar(p, res) assert(res.loc.r != nil) - returnStmt = ropeff("return $1;$n", "ret $1$n", [rdLoc(res.loc)]) + returnStmt = ropeff("\treturn $1;$n", "ret $1$n", [rdLoc(res.loc)]) initLocalVar(p, res, immediateAsgn=false) else: fillResult(res) @@ -606,10 +635,10 @@ proc genProcAux(m: BModule, prc: PSym) = genStmts(p, prc.getBody) # modifies p.locals, p.init, etc. var generatedProc: PRope if sfPure in prc.flags: - generatedProc = ropeff("$1 {$n$2$3$4}$n", "define $1 {$n$2$3$4}$n", + generatedProc = ropeff("$N$1 {$n$2$3$4}$N$N", "define $1 {$n$2$3$4}$N", [header, p.s(cpsLocals), p.s(cpsInit), p.s(cpsStmts)]) else: - generatedProc = ropeff("$1 {$n", "define $1 {$n", [header]) + generatedProc = ropeff("$N$1 {$N", "$Ndefine $1 {$N", [header]) app(generatedProc, initGCFrame(p)) if optStackTrace in prc.options: getFrameDecl(p) @@ -623,25 +652,25 @@ proc genProcAux(m: BModule, prc: PSym) = if gProcProfile >= 64 * 1024: InternalError(prc.info, "too many procedures for profiling") discard cgsym(m, "profileData") - appf(p.s(cpsLocals), "ticks NIM_profilingStart;$n") + appf(p.s(cpsLocals), "\tticks NIM_profilingStart;$n") if prc.loc.a < 0: - appf(m.s[cfsDebugInit], "profileData[$1].procname = $2;$n", [ + appf(m.s[cfsDebugInit], "\tprofileData[$1].procname = $2;$n", [ toRope(gProcProfile), makeCString(prc.name.s)]) prc.loc.a = gProcProfile inc(gProcProfile) - prepend(p.s(cpsInit), ropef("NIM_profilingStart = getticks();$n")) + prepend(p.s(cpsInit), ropef("\tNIM_profilingStart = getticks();$n")) app(generatedProc, p.s(cpsInit)) app(generatedProc, p.s(cpsStmts)) - if p.beforeRetNeeded: appf(generatedProc, "BeforeRet: $n;") + if p.beforeRetNeeded: appf(generatedProc, "\tBeforeRet: ;$n") app(generatedProc, deinitGCFrame(p)) if optStackTrace in prc.options: app(generatedProc, deinitFrame(p)) if (optProfiler in prc.options) and (gCmd != cmdCompileToLLVM): appf(generatedProc, - "profileData[$1].total += elapsed(getticks(), NIM_profilingStart);$n", + "\tprofileData[$1].total += elapsed(getticks(), NIM_profilingStart);$n", [toRope(prc.loc.a)]) app(generatedProc, returnStmt) - appf(generatedProc, "}$n") + appf(generatedProc, "}$N") app(m.s[cfsProcs], generatedProc) proc genProcPrototype(m: BModule, sym: PSym) = From b11fe5d0b477c58524ed3fc02ede6f13acef9622 Mon Sep 17 00:00:00 2001 From: Zahary Karadjov Date: Thu, 14 Jun 2012 17:33:00 +0300 Subject: [PATCH 14/15] more uint related fixes --- compiler/ast.nim | 3 +- compiler/ccgthreadvars.nim | 7 +- compiler/lexer.nim | 4 + compiler/semexprs.nim | 14 ++- compiler/sigmatch.nim | 2 +- lib/core/typeinfo.nim | 9 +- lib/pure/marshal.nim | 222 ++++++++++++++++++------------------- lib/pure/unicode.nim | 6 +- lib/system/hti.nim | 4 +- lib/windows/windows.nim | 13 +-- lib/wrappers/sdl/sdl.nim | 4 +- tests/reject/tenummix.nim | 2 +- 12 files changed, 151 insertions(+), 139 deletions(-) diff --git a/compiler/ast.nim b/compiler/ast.nim index eb258e383f..a99357a47b 100755 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -329,7 +329,8 @@ type tfEnumHasHoles, # enum cannot be mapped into a range tfShallow, # type can be shallow copied on assignment tfThread, # proc type is marked as ``thread`` - tfLiteral # type represents literal value + tfUniIntLit # type represents literal value that could be either + # singed or unsigned integer (e.g. 100) tfFromGeneric # type is an instantiation of a generic; this is needed # because for instantiations of objects, structural # type equality has to be used diff --git a/compiler/ccgthreadvars.nim b/compiler/ccgthreadvars.nim index 900343b656..4785402e75 100755 --- a/compiler/ccgthreadvars.nim +++ b/compiler/ccgthreadvars.nim @@ -19,9 +19,10 @@ proc AccessThreadLocalVar(p: BProc, s: PSym) = if emulatedThreadVars() and not p.ThreadVarAccessed: p.ThreadVarAccessed = true p.module.usesThreadVars = true - lineF(p, cpsLocals, "NimThreadVars* NimTV;$n") - lineCg(p, cpsInit, "NimTV = (NimThreadVars*) #GetThreadLocalVars();$n") - + appf(p.procSec(cpsLocals), "\tNimThreadVars* NimTV;$n") + app(p.procSec(cpsInit), + ropecg(p.module, "\tNimTV = (NimThreadVars*) #GetThreadLocalVars();$n")) + var nimtv: PRope # nimrod thread vars; the struct body nimtvDeps: seq[PType] = @[] # type deps: every module needs whole struct diff --git a/compiler/lexer.nim b/compiler/lexer.nim index 73a818e321..afa52d6212 100755 --- a/compiler/lexer.nim +++ b/compiler/lexer.nim @@ -403,6 +403,10 @@ proc GetNumber(L: var TLexer): TToken = of tkInt8Lit: result.iNumber = biggestInt(int8(toU8(int(xi)))) of tkInt16Lit: result.iNumber = biggestInt(toU16(int(xi))) of tkInt32Lit: result.iNumber = biggestInt(toU32(xi)) + of tkUIntLit, tkUInt64Lit: result.iNumber = xi + of tkUInt8Lit: result.iNumber = biggestInt(int8(toU8(int(xi)))) + of tkUInt16Lit: result.iNumber = biggestInt(toU16(int(xi))) + of tkUInt32Lit: result.iNumber = biggestInt(toU32(xi)) of tkFloat32Lit: result.fNumber = (cast[PFloat32](addr(xi)))[] # note: this code is endian neutral! diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 8910e54c26..cd97e74b17 100755 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -1283,9 +1283,9 @@ proc semMacroStmt(c: PContext, n: PNode, semCheck = true): PNode = GlobalError(n.info, errInvalidExpressionX, renderTree(a, {renderNoComments})) -proc litIntType(kind: TTypeKind): PType = +proc uniIntType(kind: TTypeKind): PType = result = getSysType(kind).copyType(getCurrOwner(), true) - result.flags.incl(tfLiteral) + result.flags.incl(tfUniIntLit) template memoize(e: expr): expr = var `*guard` {.global.} = false @@ -1317,9 +1317,15 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode = if result.typ == nil: let i = result.intVal if i >= low(int32) and i <= high(int32): - result.typ = litIntType(tyInt).memoize + if i >= 0: + result.typ = uniIntType(tyInt).memoize + else: + result.typ = getSysType(tyInt) else: - result.typ = litIntType(tyInt64).memoize + if i >= 0: + result.typ = uniIntType(tyInt64).memoize + else: + result.typ = getSysType(tyInt64) of nkInt8Lit: if result.typ == nil: result.typ = getSysType(tyInt8) of nkInt16Lit: diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index 168936ed4c..7e985e9815 100755 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -164,7 +164,7 @@ proc handleRange(f, a: PType, min, max: TTypeKind): TTypeRelation = if k == f.kind: result = isSubtype elif f.kind == tyInt and k in {tyInt..tyInt32}: result = isIntConv elif f.kind == tyUInt and k in {tyUInt..tyUInt32}: result = isIntConv - elif f.kind in {tyUInt..tyUInt64} and k == tyInt and tfLiteral in a.flags: + elif f.kind in {tyUInt..tyUInt64} and k == tyInt and tfUniIntLit in a.flags: result = isIntConv elif k >= min and k <= max: result = isConvertible else: result = isNone diff --git a/lib/core/typeinfo.nim b/lib/core/typeinfo.nim index ca2b68cc3f..549e4724a7 100755 --- a/lib/core/typeinfo.nim +++ b/lib/core/typeinfo.nim @@ -43,8 +43,13 @@ type akFloat = 36, ## any represents a float akFloat32 = 37, ## any represents a float32 akFloat64 = 38, ## any represents a float64 - akFloat128 = 39 ## any represents a float128 - + akFloat128 = 39, ## any represents a float128 + akUInt = 40, ## any represents an unsigned int + akUInt8 = 41, ## any represents an unsigned int8 + akUInt16 = 42, ## any represents an unsigned in16 + akUInt32 = 43, ## any represents an unsigned int32 + akUInt64 = 44, ## any represents an unsigned int64 + TAny* = object {.pure.} ## can represent any nimrod value; NOTE: the wrapped ## value can be modified with its wrapper! This means ## that ``TAny`` keeps a non-traced pointer to its diff --git a/lib/pure/marshal.nim b/lib/pure/marshal.nim index fd67fb8499..e8c30331a0 100755 --- a/lib/pure/marshal.nim +++ b/lib/pure/marshal.nim @@ -8,25 +8,25 @@ # ## This module contains procs for serialization and deseralization of -## arbitrary Nimrod data structures. The serialization format uses JSON. -## -## **Restriction**: For objects their type is **not** serialized. This means -## essentially that it does not work if the object has some other runtime -## type than its compiletime type: -## -## .. code-block:: nimrod -## -## type -## TA = object -## TB = object of TA -## f: int -## -## var -## a: ref TA -## b: ref TB -## -## new(b) -## a = b +## arbitrary Nimrod data structures. The serialization format uses JSON. +## +## **Restriction**: For objects their type is **not** serialized. This means +## essentially that it does not work if the object has some other runtime +## type than its compiletime type: +## +## .. code-block:: nimrod +## +## type +## TA = object +## TB = object of TA +## f: int +## +## var +## a: ref TA +## b: ref TB +## +## new(b) +## a = b ## echo($$a[]) # produces "{}", not "{f: 0}" import streams, typeinfo, json, intsets, tables @@ -86,7 +86,7 @@ proc storeAny(s: PStream, a: TAny, stored: var TIntSet) = var x = getString(a) if IsNil(x): s.write("null") else: s.write(escapeJson(x)) - of akInt..akInt64: s.write($getBiggestInt(a)) + of akInt..akInt64, akUInt..akUInt64: s.write($getBiggestInt(a)) of akFloat..akFloat128: s.write($getBiggestFloat(a)) proc loadAny(p: var TJsonParser, a: TAny, t: var TTable[biggestInt, pointer]) = @@ -128,18 +128,18 @@ proc loadAny(p: var TJsonParser, a: TAny, t: var TTable[biggestInt, pointer]) = next(p) of jsonArrayStart: next(p) - invokeNewSeq(a, 0) - var i = 0 + invokeNewSeq(a, 0) + var i = 0 while p.kind != jsonArrayEnd and p.kind != jsonEof: - extendSeq(a) + extendSeq(a) loadAny(p, a[i], t) inc(i) if p.kind == jsonArrayEnd: next(p) else: raiseParseErr(p, "") - else: + else: raiseParseErr(p, "'[' expected for a seq") of akObject, akTuple: - if a.kind == akObject: setObjectRuntimeType(a) + if a.kind == akObject: setObjectRuntimeType(a) if p.kind != jsonObjectStart: raiseParseErr(p, "'{' expected for an object") next(p) while p.kind != jsonObjectEnd and p.kind != jsonEof: @@ -169,13 +169,13 @@ proc loadAny(p: var TJsonParser, a: TAny, t: var TTable[biggestInt, pointer]) = next(p) of jsonArrayStart: next(p) - if a.kind == akRef: invokeNew(a) - else: setPointer(a, alloc0(a.baseTypeSize)) - if p.kind == jsonInt: - t[p.getInt] = getPointer(a) - next(p) - else: raiseParseErr(p, "index for ref type expected") - loadAny(p, a[], t) + if a.kind == akRef: invokeNew(a) + else: setPointer(a, alloc0(a.baseTypeSize)) + if p.kind == jsonInt: + t[p.getInt] = getPointer(a) + next(p) + else: raiseParseErr(p, "index for ref type expected") + loadAny(p, a[], t) if p.kind == jsonArrayEnd: next(p) else: raiseParseErr(p, "']' end of ref-address pair expected") else: raiseParseErr(p, "int for pointer type expected") @@ -197,7 +197,7 @@ proc loadAny(p: var TJsonParser, a: TAny, t: var TTable[biggestInt, pointer]) = setString(a, p.str) next(p) else: raiseParseErr(p, "string expected") - of akInt..akInt64: + of akInt..akInt64, akUInt..akUInt64: if p.kind == jsonInt: setBiggestInt(a, getInt(p)) next(p) @@ -208,7 +208,7 @@ proc loadAny(p: var TJsonParser, a: TAny, t: var TTable[biggestInt, pointer]) = setBiggestFloat(a, getFloat(p)) next(p) return - raiseParseErr(p, "float expected") + raiseParseErr(p, "float expected") of akRange: loadAny(p, a.skipRange, t) proc loadAny(s: PStream, a: TAny, t: var TTable[biggestInt, pointer]) = @@ -220,7 +220,7 @@ proc loadAny(s: PStream, a: TAny, t: var TTable[biggestInt, pointer]) = proc load*[T](s: PStream, data: var T) = ## loads `data` from the stream `s`. Raises `EIO` in case of an error. - var tab = initTable[biggestInt, pointer]() + var tab = initTable[biggestInt, pointer]() loadAny(s, toAny(data), tab) proc store*[T](s: PStream, data: T) = @@ -229,91 +229,91 @@ proc store*[T](s: PStream, data: T) = var d: T shallowCopy(d, data) storeAny(s, toAny(d), stored) - -proc `$$`*[T](x: T): string = - ## returns a string representation of `x`. + +proc `$$`*[T](x: T): string = + ## returns a string representation of `x`. var stored = initIntSet() var d: T shallowCopy(d, x) - var s = newStringStream() + var s = newStringStream() storeAny(s, toAny(d), stored) - result = s.data - -proc to*[T](data: string): T = - ## reads data and transforms it to a ``T``. - var tab = initTable[biggestInt, pointer]() + result = s.data + +proc to*[T](data: string): T = + ## reads data and transforms it to a ``T``. + var tab = initTable[biggestInt, pointer]() loadAny(newStringStream(data), toAny(result), tab) -when isMainModule: - template testit(x: expr) = echo($$to[type(x)]($$x)) - +when isMainModule: + template testit(x: expr) = echo($$to[type(x)]($$x)) + var x: array[0..4, array[0..4, string]] = [ ["test", "1", "2", "3", "4"], ["test", "1", "2", "3", "4"], ["test", "1", "2", "3", "4"], ["test", "1", "2", "3", "4"], ["test", "1", "2", "3", "4"]] testit(x) - var test2: tuple[name: string, s: int] = ("tuple test", 56) - testit(test2) - - type - TE = enum - blah, blah2 - - TestObj = object - test, asd: int - case test2: TE - of blah: - help: string - else: - nil - - PNode = ref TNode - TNode = object - next, prev: PNode - data: string - - proc buildList(): PNode = - new(result) - new(result.next) - new(result.prev) - result.data = "middle" - result.next.data = "next" - result.prev.data = "prev" - result.next.next = result.prev - result.next.prev = result - result.prev.next = result - result.prev.prev = result.next - - var test3: TestObj - test3.test = 42 - test3.test2 = blah - testit(test3) - - var test4: ref tuple[a, b: string] - new(test4) - test4.a = "ref string test: A" - test4.b = "ref string test: B" - testit(test4) - - var test5 = @[(0,1),(2,3),(4,5)] - testit(test5) - - var test6: set[char] = {'A'..'Z', '_'} - testit(test6) - - var test7 = buildList() - echo($$test7) - testit(test7) - - type - TA = object - TB = object of TA - f: int - - var - a: ref TA - b: ref TB - new(b) - a = b + var test2: tuple[name: string, s: int] = ("tuple test", 56) + testit(test2) + + type + TE = enum + blah, blah2 + + TestObj = object + test, asd: int + case test2: TE + of blah: + help: string + else: + nil + + PNode = ref TNode + TNode = object + next, prev: PNode + data: string + + proc buildList(): PNode = + new(result) + new(result.next) + new(result.prev) + result.data = "middle" + result.next.data = "next" + result.prev.data = "prev" + result.next.next = result.prev + result.next.prev = result + result.prev.next = result + result.prev.prev = result.next + + var test3: TestObj + test3.test = 42 + test3.test2 = blah + testit(test3) + + var test4: ref tuple[a, b: string] + new(test4) + test4.a = "ref string test: A" + test4.b = "ref string test: B" + testit(test4) + + var test5 = @[(0,1),(2,3),(4,5)] + testit(test5) + + var test6: set[char] = {'A'..'Z', '_'} + testit(test6) + + var test7 = buildList() + echo($$test7) + testit(test7) + + type + TA = object + TB = object of TA + f: int + + var + a: ref TA + b: ref TB + new(b) + a = b echo($$a[]) # produces "{}", not "{f: 0}" - + diff --git a/lib/pure/unicode.nim b/lib/pure/unicode.nim index e11cd5fe34..f76573788b 100644 --- a/lib/pure/unicode.nim +++ b/lib/pure/unicode.nim @@ -18,9 +18,9 @@ type TRune* = distinct irune ## type that can hold any Unicode character TRune16* = distinct int16 ## 16 bit Unicode character -proc `<=%`*(a, b: TRune): bool {.borrow.} -proc `<%`*(a, b: TRune): bool {.borrow.} -proc `==`*(a, b: TRune): bool {.borrow.} +proc `<=%`*(a, b: TRune): bool = return int(a) <=% int(b) +proc `<%`*(a, b: TRune): bool = return int(a) <% int(b) +proc `==`*(a, b: TRune): bool = return int(a) == int(b) template ones(n: expr): expr = ((1 shl n)-1) diff --git a/lib/system/hti.nim b/lib/system/hti.nim index 1d62b910a4..d79679107f 100755 --- a/lib/system/hti.nim +++ b/lib/system/hti.nim @@ -37,7 +37,9 @@ type # This should be he same as ast.TTypeKind tyPointer, tyOpenArray, tyString, tyCString, tyForward, tyInt, tyInt8, tyInt16, tyInt32, tyInt64, - tyFloat, tyFloat32, tyFloat64, tyFloat128 + tyFloat, tyFloat32, tyFloat64, tyFloat128, + tyUInt, tyUInt8, tyUInt16, tyUInt32, tyUInt64, + tyBigNum, TNimNodeKind = enum nkNone, nkSlot, nkList, nkCase TNimNode {.codegenType, final.} = object diff --git a/lib/windows/windows.nim b/lib/windows/windows.nim index d96c2bbed9..9f7fd2d85b 100755 --- a/lib/windows/windows.nim +++ b/lib/windows/windows.nim @@ -41,10 +41,6 @@ type # WinNT.h -- Defines the 32-Bit Windows types and constants type # BaseTsd.h -- Type definitions for the basic sized types # Give here only the bare minimum, to be expanded as needs arise - UINT8* = int8 - UINT16* = int16 - UINT32* = int32 - UINT64* = int64 LONG32* = int32 ULONG32* = int32 DWORD32* = int32 @@ -95,7 +91,6 @@ type # WinDef.h -- Basic Windows Type Definitions LPCVOID* = pointer # INT* = int # Cannot work and not necessary anyway - UINT* = int PUINT* = ptr int WPARAM* = LONG_PTR @@ -18518,9 +18513,9 @@ proc DisableThreadLibraryCalls*(hLibModule: HMODULE): WINBOOL{.stdcall, proc GetProcAddress*(hModule: HINST, lpProcName: LPCSTR): FARPROC{.stdcall, dynlib: "kernel32", importc: "GetProcAddress".} proc GetVersion*(): DWORD{.stdcall, dynlib: "kernel32", importc: "GetVersion".} -proc GlobalAlloc*(uFlags: UINT, dwBytes: DWORD): HGLOBAL{.stdcall, +proc GlobalAlloc*(uFlags: INT, dwBytes: DWORD): HGLOBAL{.stdcall, dynlib: "kernel32", importc: "GlobalAlloc".} -proc GlobalReAlloc*(hMem: HGLOBAL, dwBytes: DWORD, uFlags: UINT): HGLOBAL{. +proc GlobalReAlloc*(hMem: HGLOBAL, dwBytes: DWORD, uFlags: INT): HGLOBAL{. stdcall, dynlib: "kernel32", importc: "GlobalReAlloc".} proc GlobalSize*(hMem: HGLOBAL): DWORD{.stdcall, dynlib: "kernel32", importc: "GlobalSize".} @@ -23620,8 +23615,8 @@ proc ListView_SetItemPosition32(hwndLV: HWND, i, x, y: int32): LRESULT = proc ListView_SetItemState(hwndLV: HWND, i, data, mask: int32): LRESULT = var gnu_lvi: LV_ITEM - gnu_lvi.stateMask = mask - gnu_lvi.state = data + gnu_lvi.stateMask = uint(mask) + gnu_lvi.state = uint(data) result = SendMessage(hwndLV, LVM_SETITEMSTATE, WPARAM(i), cast[LPARAM](addr(gnu_lvi))) diff --git a/lib/wrappers/sdl/sdl.nim b/lib/wrappers/sdl/sdl.nim index cf4eb452d7..a48cb59efa 100755 --- a/lib/wrappers/sdl/sdl.nim +++ b/lib/wrappers/sdl/sdl.nim @@ -756,9 +756,7 @@ type PUInt8Array* = ptr TUInt8Array TUInt8Array* = array[0..high(int) shr 1, byte] PUInt16* = ptr UInt16 - UInt16* = int16 - PUInt32* = ptr int32 - UInt32* = int32 + PUInt32* = ptr UInt32 PUInt64* = ptr UInt64 UInt64*{.final.} = object hi*: int32 diff --git a/tests/reject/tenummix.nim b/tests/reject/tenummix.nim index f32eb82a77..8965ab3c3b 100644 --- a/tests/reject/tenummix.nim +++ b/tests/reject/tenummix.nim @@ -1,6 +1,6 @@ discard """ file: "system.nim" - line: 640 + line: 678 errormsg: "type mismatch" """ From 382a614a61a8be3957f861b58412d0d785249820 Mon Sep 17 00:00:00 2001 From: Zahary Karadjov Date: Thu, 14 Jun 2012 19:58:47 +0300 Subject: [PATCH 15/15] don't take into account the user config file when building sources --- build.bat | 2 +- build64.bat | 2 +- tools/niminst/niminst.nim | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/build.bat b/build.bat index 6d28dd4c92..494c37497f 100755 --- a/build.bat +++ b/build.bat @@ -2,7 +2,7 @@ REM Generated by niminst SET CC=gcc SET LINKER=gcc -SET COMP_FLAGS=-w -g3 -O0 -O3 -fno-strict-aliasing +SET COMP_FLAGS=-w -O3 -fno-strict-aliasing SET LINK_FLAGS= REM call the compiler: diff --git a/build64.bat b/build64.bat index cc29480560..edc5a8301d 100644 --- a/build64.bat +++ b/build64.bat @@ -2,7 +2,7 @@ REM Generated by niminst SET CC=gcc SET LINKER=gcc -SET COMP_FLAGS=-w -g3 -O0 -O3 -fno-strict-aliasing +SET COMP_FLAGS=-w -O3 -fno-strict-aliasing SET LINK_FLAGS= REM call the compiler: diff --git a/tools/niminst/niminst.nim b/tools/niminst/niminst.nim index 9927d5bcd6..f66bad1f4e 100755 --- a/tools/niminst/niminst.nim +++ b/tools/niminst/niminst.nim @@ -391,7 +391,7 @@ proc srcdist(c: var TConfigData) = if existsDir(dir): removeDir(dir) createDir(dir) var cmd = ("nimrod compile -f --symbolfiles:off --compileonly " & - "--gen_mapping --cc:gcc" & + "--gen_mapping --cc:gcc --skipUserCfg" & " --os:$# --cpu:$# $# $#") % [c.oses[osA-1], c.cpus[cpuA-1], c.nimrodArgs, changeFileExt(c.infile, "nim")]