Merge branch 'devel' into bugfix-2858-testament-sources-system-wide

This commit is contained in:
Oscar Campbell 2015-06-07 13:17:06 +02:00
commit f0b6c03b26
46 changed files with 344 additions and 1226 deletions

0
bootstrap.sh Normal file → Executable file
View file

View file

@ -1,6 +1,6 @@
[Package] [Package]
name = "compiler" name = "compiler"
version = "0.10.3" version = "0.11.3"
author = "Andreas Rumpf" author = "Andreas Rumpf"
description = "Compiler package providing the compiler sources as a library." description = "Compiler package providing the compiler sources as a library."
license = "MIT" license = "MIT"
@ -8,4 +8,4 @@ license = "MIT"
InstallDirs = "doc, compiler" InstallDirs = "doc, compiler"
[Deps] [Deps]
Requires: "nim >= 0.10.3" Requires: "nim >= 0.11.3"

View file

@ -423,6 +423,7 @@ type
# but unfortunately it has measurable impact for compilation # but unfortunately it has measurable impact for compilation
# efficiency # efficiency
nfTransf, # node has been transformed nfTransf, # node has been transformed
nfNoRewrite # node should not be transformed anymore
nfSem # node has been checked for semantics nfSem # node has been checked for semantics
nfLL # node has gone through lambda lifting nfLL # node has gone through lambda lifting
nfDotField # the call can use a dot operator nfDotField # the call can use a dot operator
@ -1345,7 +1346,7 @@ proc propagateToOwner*(owner, elem: PType) =
owner.flags.incl tfHasAsgn owner.flags.incl tfHasAsgn
if owner.kind notin {tyProc, tyGenericInst, tyGenericBody, if owner.kind notin {tyProc, tyGenericInst, tyGenericBody,
tyGenericInvocation}: tyGenericInvocation, tyPtr}:
let elemB = elem.skipTypes({tyGenericInst}) let elemB = elem.skipTypes({tyGenericInst})
if elemB.isGCedMem or tfHasGCedMem in elemB.flags: if elemB.isGCedMem or tfHasGCedMem in elemB.flags:
# for simplicity, we propagate this flag even to generics. We then # for simplicity, we propagate this flag even to generics. We then

View file

@ -2150,7 +2150,7 @@ proc genNamedConstExpr(p: BProc, n: PNode): Rope =
proc genConstSimpleList(p: BProc, n: PNode): Rope = proc genConstSimpleList(p: BProc, n: PNode): Rope =
var length = sonsLen(n) var length = sonsLen(n)
result = rope("{") result = rope("{")
for i in countup(0, length - 2): for i in countup(ord(n.kind == nkObjConstr), length - 2):
addf(result, "$1,$n", [genNamedConstExpr(p, n.sons[i])]) addf(result, "$1,$n", [genNamedConstExpr(p, n.sons[i])])
if length > 0: add(result, genNamedConstExpr(p, n.sons[length - 1])) if length > 0: add(result, genNamedConstExpr(p, n.sons[length - 1]))
addf(result, "}$n", []) addf(result, "}$n", [])

View file

@ -721,6 +721,8 @@ proc genProcPrototype(m: BModule, sym: PSym) =
getTypeDesc(m, sym.loc.t), mangleDynLibProc(sym))) getTypeDesc(m, sym.loc.t), mangleDynLibProc(sym)))
elif not containsOrIncl(m.declaredProtos, sym.id): elif not containsOrIncl(m.declaredProtos, sym.id):
var header = genProcHeader(m, sym) var header = genProcHeader(m, sym)
if sfNoReturn in sym.flags and hasDeclspec in extccomp.CC[cCompiler].props:
header = "__declspec(noreturn) " & header
if sym.typ.callConv != ccInline and crossesCppBoundary(m, sym): if sym.typ.callConv != ccInline and crossesCppBoundary(m, sym):
header = "extern \"C\" " & header header = "extern \"C\" " & header
if sfPure in sym.flags and hasAttribute in CC[cCompiler].props: if sfPure in sym.flags and hasAttribute in CC[cCompiler].props:

View file

@ -946,7 +946,11 @@ proc transformOuterProc(o: POuterContext, n: PNode; it: TIter): PNode =
proc liftLambdas*(fn: PSym, body: PNode): PNode = proc liftLambdas*(fn: PSym, body: PNode): PNode =
# XXX gCmd == cmdCompileToJS does not suffice! The compiletime stuff needs # XXX gCmd == cmdCompileToJS does not suffice! The compiletime stuff needs
# the transformation even when compiling to JS ... # the transformation even when compiling to JS ...
if body.kind == nkEmpty or gCmd == cmdCompileToJS or
# However we can do lifting for the stuff which is *only* compiletime.
let isCompileTime = sfCompileTime in fn.flags or fn.kind == skMacro
if body.kind == nkEmpty or (gCmd == cmdCompileToJS and not isCompileTime) or
fn.skipGenericOwner.kind != skModule: fn.skipGenericOwner.kind != skModule:
# ignore forward declaration: # ignore forward declaration:
result = body result = body

View file

@ -34,7 +34,9 @@ type
errNoneSpeedOrSizeExpectedButXFound, errGuiConsoleOrLibExpectedButXFound, errNoneSpeedOrSizeExpectedButXFound, errGuiConsoleOrLibExpectedButXFound,
errUnknownOS, errUnknownCPU, errGenOutExpectedButXFound, errUnknownOS, errUnknownCPU, errGenOutExpectedButXFound,
errArgsNeedRunOption, errInvalidMultipleAsgn, errColonOrEqualsExpected, errArgsNeedRunOption, errInvalidMultipleAsgn, errColonOrEqualsExpected,
errExprExpected, errUndeclaredIdentifier, errUseQualifier, errTypeExpected, errExprExpected, errUndeclaredIdentifier, errUndeclaredField,
errUndeclaredRoutine, errUseQualifier,
errTypeExpected,
errSystemNeeds, errExecutionOfProgramFailed, errNotOverloadable, errSystemNeeds, errExecutionOfProgramFailed, errNotOverloadable,
errInvalidArgForX, errStmtHasNoEffect, errXExpectsTypeOrValue, errInvalidArgForX, errStmtHasNoEffect, errXExpectsTypeOrValue,
errXExpectsArrayType, errIteratorCannotBeInstantiated, errExprXAmbiguous, errXExpectsArrayType, errIteratorCannotBeInstantiated, errExprXAmbiguous,
@ -190,6 +192,8 @@ const
errColonOrEqualsExpected: "\':\' or \'=\' expected, but found \'$1\'", errColonOrEqualsExpected: "\':\' or \'=\' expected, but found \'$1\'",
errExprExpected: "expression expected, but found \'$1\'", errExprExpected: "expression expected, but found \'$1\'",
errUndeclaredIdentifier: "undeclared identifier: \'$1\'", errUndeclaredIdentifier: "undeclared identifier: \'$1\'",
errUndeclaredField: "undeclared field: \'$1\'",
errUndeclaredRoutine: "attempting to call undeclared routine: \'$1\'",
errUseQualifier: "ambiguous identifier: \'$1\' -- use a qualifier", errUseQualifier: "ambiguous identifier: \'$1\' -- use a qualifier",
errTypeExpected: "type expected", errTypeExpected: "type expected",
errSystemNeeds: "system module needs \'$1\'", errSystemNeeds: "system module needs \'$1\'",

View file

@ -10,8 +10,10 @@
## Nimfix is a tool that helps to convert old-style Nimrod code to Nim code. ## Nimfix is a tool that helps to convert old-style Nimrod code to Nim code.
import strutils, os, parseopt import strutils, os, parseopt
import options, commands, modules, sem, passes, passaux, pretty, msgs, nimconf, import compiler/options, compiler/commands, compiler/modules, compiler/sem,
extccomp, condsyms, lists compiler/passes, compiler/passaux, compiler/nimfix/pretty,
compiler/msgs, compiler/nimconf,
compiler/extccomp, compiler/condsyms, compiler/lists
const Usage = """ const Usage = """
Nimfix - Tool to patch Nim code Nimfix - Tool to patch Nim code

View file

@ -11,8 +11,10 @@
## to convert Nim code into a consistent style. ## to convert Nim code into a consistent style.
import import
strutils, os, options, ast, astalgo, msgs, ropes, idents, strutils, os, intsets, strtabs
intsets, strtabs, semdata, prettybase
import compiler/options, compiler/ast, compiler/astalgo, compiler/msgs,
compiler/semdata, compiler/nimfix/prettybase, compiler/ropes, compiler/idents
type type
StyleCheck* {.pure.} = enum None, Warn, Auto StyleCheck* {.pure.} = enum None, Warn, Auto

View file

@ -7,7 +7,8 @@
# distribution, for details about the copyright. # distribution, for details about the copyright.
# #
import ast, msgs, strutils, idents, lexbase, streams import strutils, lexbase, streams
import compiler/ast, compiler/msgs, compiler/idents
from os import splitFile from os import splitFile
type type

View file

@ -7,330 +7,6 @@
# distribution, for details about the copyright. # distribution, for details about the copyright.
# #
## Nimsuggest is a tool that helps to give editors IDE like capabilities. ## Nimsuggest has been moved to https://github.com/nim-lang/nimsuggest
import strutils, os, parseopt, parseutils, sequtils, net {.error: "This project has moved to the following repo: https://github.com/nim-lang/nimsuggest".}
# Do NOT import suggest. It will lead to wierd bugs with
# suggestionResultHook, because suggest.nim is included by sigmatch.
# So we import that one instead.
import options, commands, modules, sem, passes, passaux, msgs, nimconf,
extccomp, condsyms, lists, net, rdstdin, sexp, sigmatch, ast
when defined(windows):
import winlean
else:
import posix
const Usage = """
Nimsuggest - Tool to give every editor IDE like capabilities for Nim
Usage:
nimsuggest [options] projectfile.nim
Options:
--port:PORT port, by default 6000
--address:HOST binds to that address, by default ""
--stdin read commands from stdin and write results to
stdout instead of using sockets
--epc use emacs epc mode
The server then listens to the connection and takes line-based commands.
In addition, all command line options of Nim that do not affect code generation
are supported.
"""
type
Mode = enum mstdin, mtcp, mepc
var
gPort = 6000.Port
gAddress = ""
gMode: Mode
const
seps = {':', ';', ' ', '\t'}
Help = "usage: sug|con|def|use file.nim[;dirtyfile.nim]:line:col\n"&
"type 'quit' to quit\n" &
"type 'debug' to toggle debug mode on/off\n" &
"type 'terse' to toggle terse mode on/off"
type
EUnexpectedCommand = object of Exception
proc parseQuoted(cmd: string; outp: var string; start: int): int =
var i = start
i += skipWhitespace(cmd, i)
if cmd[i] == '"':
i += parseUntil(cmd, outp, '"', i+1)+2
else:
i += parseUntil(cmd, outp, seps, i)
result = i
proc sexp(s: IdeCmd): SexpNode = sexp($s)
proc sexp(s: TSymKind): SexpNode = sexp($s)
proc sexp(s: Suggest): SexpNode =
# If you change the oder here, make sure to change it over in
# nim-mode.el too.
result = convertSexp([
s.section,
s.symkind,
s.qualifiedPath.map(newSString),
s.filePath,
s.forth,
s.line,
s.column,
s.doc
])
proc sexp(s: seq[Suggest]): SexpNode =
result = newSList()
for sug in s:
result.add(sexp(sug))
proc listEPC(): SexpNode =
let
argspecs = sexp("file line column dirtyfile".split(" ").map(newSSymbol))
docstring = sexp("line starts at 1, column at 0, dirtyfile is optional")
result = newSList()
for command in ["sug", "con", "def", "use"]:
let
cmd = sexp(command)
methodDesc = newSList()
methodDesc.add(cmd)
methodDesc.add(argspecs)
methodDesc.add(docstring)
result.add(methodDesc)
proc execute(cmd: IdeCmd, file, dirtyfile: string, line, col: int) =
gIdeCmd = cmd
if cmd == ideUse:
modules.resetAllModules()
var isKnownFile = true
let dirtyIdx = file.fileInfoIdx(isKnownFile)
if dirtyfile.len != 0: msgs.setDirtyFile(dirtyIdx, dirtyfile)
else: msgs.setDirtyFile(dirtyIdx, nil)
resetModule dirtyIdx
if dirtyIdx != gProjectMainIdx:
resetModule gProjectMainIdx
gTrackPos = newLineInfo(dirtyIdx, line, col)
gErrorCounter = 0
if not isKnownFile:
compileProject()
compileProject(dirtyIdx)
proc executeEPC(cmd: IdeCmd, args: SexpNode) =
let
file = args[0].getStr
line = args[1].getNum
column = args[2].getNum
var dirtyfile = ""
if len(args) > 3:
dirtyfile = args[3].getStr(nil)
execute(cmd, file, dirtyfile, int(line), int(column))
proc returnEPC(socket: var Socket, uid: BiggestInt, s: SexpNode, return_symbol = "return") =
let response = $convertSexp([newSSymbol(return_symbol), uid, s])
socket.send(toHex(len(response), 6))
socket.send(response)
proc connectToNextFreePort(server: Socket, host: string, start = 30000): int =
result = start
while true:
try:
server.bindaddr(Port(result), host)
return
except OsError:
when defined(windows):
let checkFor = WSAEADDRINUSE.OSErrorCode
else:
let checkFor = EADDRINUSE.OSErrorCode
if osLastError() != checkFor:
raise getCurrentException()
else:
result += 1
proc parseCmdLine(cmd: string) =
template toggle(sw) =
if sw in gGlobalOptions:
excl(gGlobalOptions, sw)
else:
incl(gGlobalOptions, sw)
return
template err() =
echo Help
return
var opc = ""
var i = parseIdent(cmd, opc, 0)
case opc.normalize
of "sug": gIdeCmd = ideSug
of "con": gIdeCmd = ideCon
of "def": gIdeCmd = ideDef
of "use": gIdeCmd = ideUse
of "quit": quit()
of "debug": toggle optIdeDebug
of "terse": toggle optIdeTerse
else: err()
var dirtyfile = ""
var orig = ""
i = parseQuoted(cmd, orig, i)
if cmd[i] == ';':
i = parseQuoted(cmd, dirtyfile, i+1)
i += skipWhile(cmd, seps, i)
var line = -1
var col = 0
i += parseInt(cmd, line, i)
i += skipWhile(cmd, seps, i)
i += parseInt(cmd, col, i)
execute(gIdeCmd, orig, dirtyfile, line, col-1)
proc serve() =
case gMode:
of mstdin:
echo Help
var line = ""
while readLineFromStdin("> ", line):
parseCmdLine line
echo ""
flushFile(stdout)
of mtcp:
var server = newSocket()
server.bindAddr(gPort, gAddress)
var inp = "".TaintedString
server.listen()
while true:
var stdoutSocket = newSocket()
msgs.writelnHook = proc (line: string) =
stdoutSocket.send(line & "\c\L")
accept(server, stdoutSocket)
stdoutSocket.readLine(inp)
parseCmdLine inp.string
stdoutSocket.send("\c\L")
stdoutSocket.close()
of mepc:
var server = newSocket()
let port = connectToNextFreePort(server, "localhost")
var inp = "".TaintedString
server.listen()
echo(port)
var client = newSocket()
# Wait for connection
accept(server, client)
while true:
var sizeHex = ""
if client.recv(sizeHex, 6) != 6:
raise newException(ValueError, "didn't get all the hexbytes")
var size = 0
if parseHex(sizeHex, size) == 0:
raise newException(ValueError, "invalid size hex: " & $sizeHex)
var messageBuffer = ""
if client.recv(messageBuffer, size) != size:
raise newException(ValueError, "didn't get all the bytes")
let
message = parseSexp($messageBuffer)
messageType = message[0].getSymbol
case messageType:
of "call":
var results: seq[Suggest] = @[]
suggestionResultHook = proc (s: Suggest) =
results.add(s)
let
uid = message[1].getNum
cmd = parseIdeCmd(message[2].getSymbol)
args = message[3]
executeEPC(cmd, args)
returnEPC(client, uid, sexp(results))
of "return":
raise newException(EUnexpectedCommand, "no return expected")
of "return-error":
raise newException(EUnexpectedCommand, "no return expected")
of "epc-error":
stderr.writeln("recieved epc error: " & $messageBuffer)
raise newException(IOError, "epc error")
of "methods":
returnEPC(client, message[1].getNum, listEPC())
else:
raise newException(EUnexpectedCommand, "unexpected call: " & messageType)
proc mainCommand =
registerPass verbosePass
registerPass semPass
gCmd = cmdIdeTools
incl gGlobalOptions, optCaasEnabled
isServing = true
wantMainModule()
appendStr(searchPaths, options.libpath)
if gProjectFull.len != 0:
# current path is always looked first for modules
prependStr(searchPaths, gProjectPath)
# do not stop after the first error:
msgs.gErrorMax = high(int)
compileProject()
serve()
proc processCmdLine*(pass: TCmdLinePass, cmd: string) =
var p = parseopt.initOptParser(cmd)
while true:
parseopt.next(p)
case p.kind
of cmdEnd: break
of cmdLongoption, cmdShortOption:
case p.key.normalize
of "port":
gPort = parseInt(p.val).Port
gMode = mtcp
of "address":
gAddress = p.val
gMode = mtcp
of "stdin": gMode = mstdin
of "epc":
gMode = mepc
gVerbosity = 0 # Port number gotta be first.
else: processSwitch(pass, p)
of cmdArgument:
options.gProjectName = unixToNativePath(p.key)
# if processArgument(pass, p, argsCount): break
proc handleCmdLine() =
if paramCount() == 0:
stdout.writeln(Usage)
else:
processCmdLine(passCmd1, "")
if gProjectName != "":
try:
gProjectFull = canonicalizePath(gProjectName)
except OSError:
gProjectFull = gProjectName
var p = splitFile(gProjectFull)
gProjectPath = p.dir
gProjectName = p.name
else:
gProjectPath = getCurrentDir()
loadConfigs(DefaultConfig) # load all config files
# now process command line arguments again, because some options in the
# command line can overwite the config file's settings
extccomp.initVars()
processCmdLine(passCmd2, "")
mainCommand()
when false:
proc quitCalled() {.noconv.} =
writeStackTrace()
addQuitProc(quitCalled)
condsyms.initDefines()
defineSymbol "nimsuggest"
handleCmdline()

View file

@ -1,17 +0,0 @@
# Special configuration file for the Nim project
gc:markAndSweep
hint[XDeclaredButNotUsed]:off
path:"$projectPath/../.."
path:"$lib/packages/docutils"
path:"../../compiler"
define:useStdoutAsStdmsg
define:nimsuggest
cs:partial
#define:useNodeIds
define:booting
#define:noDocgen

View file

@ -64,6 +64,7 @@ proc setBaseFlags*(n: PNode, base: TNumericalBase)
proc parseSymbol*(p: var TParser, allowNil = false): PNode proc parseSymbol*(p: var TParser, allowNil = false): PNode
proc parseTry(p: var TParser; isExpr: bool): PNode proc parseTry(p: var TParser; isExpr: bool): PNode
proc parseCase(p: var TParser): PNode proc parseCase(p: var TParser): PNode
proc parseStmtPragma(p: var TParser): PNode
# implementation # implementation
proc getTok(p: var TParser) = proc getTok(p: var TParser) =
@ -499,9 +500,12 @@ proc parsePar(p: var TParser): PNode =
#| parKeyw = 'discard' | 'include' | 'if' | 'while' | 'case' | 'try' #| parKeyw = 'discard' | 'include' | 'if' | 'while' | 'case' | 'try'
#| | 'finally' | 'except' | 'for' | 'block' | 'const' | 'let' #| | 'finally' | 'except' | 'for' | 'block' | 'const' | 'let'
#| | 'when' | 'var' | 'mixin' #| | 'when' | 'var' | 'mixin'
#| par = '(' optInd (&parKeyw complexOrSimpleStmt ^+ ';' #| par = '(' optInd
#| | simpleExpr ('=' expr (';' complexOrSimpleStmt ^+ ';' )? )? #| ( &parKeyw complexOrSimpleStmt ^+ ';'
#| | (':' expr)? (',' (exprColonEqExpr comma?)*)? )? #| | ';' complexOrSimpleStmt ^+ ';'
#| | pragmaStmt
#| | simpleExpr ( ('=' expr (';' complexOrSimpleStmt ^+ ';' )? )
#| | (':' expr (',' exprColonEqExpr ^+ ',' )? ) ) )
#| optPar ')' #| optPar ')'
# #
# unfortunately it's ambiguous: (expr: expr) vs (exprStmt); however a # unfortunately it's ambiguous: (expr: expr) vs (exprStmt); however a
@ -521,6 +525,8 @@ proc parsePar(p: var TParser): PNode =
getTok(p) getTok(p)
optInd(p, result) optInd(p, result)
semiStmtList(p, result) semiStmtList(p, result)
elif p.tok.tokType == tkCurlyDotLe:
result.add(parseStmtPragma(p))
elif p.tok.tokType != tkParRi: elif p.tok.tokType != tkParRi:
var a = simpleExpr(p) var a = simpleExpr(p)
if p.tok.tokType == tkEquals: if p.tok.tokType == tkEquals:

View file

@ -130,7 +130,9 @@ proc matchNested(c: PPatternContext, p, n: PNode, rpn: bool): bool =
proc matches(c: PPatternContext, p, n: PNode): bool = proc matches(c: PPatternContext, p, n: PNode): bool =
# hidden conversions (?) # hidden conversions (?)
if isPatternParam(c, p): if nfNoRewrite in n.flags:
result = false
elif isPatternParam(c, p):
result = bindOrCheck(c, p.sym, n) result = bindOrCheck(c, p.sym, n)
elif n.kind == nkSym and p.kind == nkIdent: elif n.kind == nkSym and p.kind == nkIdent:
result = p.ident.id == n.sym.name.id result = p.ident.id == n.sym.name.id

View file

@ -9,7 +9,8 @@
## The builtin 'system.locals' implemented as a plugin. ## The builtin 'system.locals' implemented as a plugin.
import plugins, ast, astalgo, magicsys, lookups, semdata, lowerings import compiler/plugins, compiler/ast, compiler/astalgo, compiler/magicsys,
compiler/lookups, compiler/semdata, compiler/lowerings
proc semLocals(c: PContext, n: PNode): PNode = proc semLocals(c: PContext, n: PNode): PNode =
var counter = 0 var counter = 0

View file

@ -37,7 +37,7 @@ const
wImportc, wExportc, wNodecl, wMagic, wDeprecated, wBorrow, wExtern, wImportc, wExportc, wNodecl, wMagic, wDeprecated, wBorrow, wExtern,
wImportCpp, wImportObjC, wError, wDiscardable, wGensym, wInject, wRaises, wImportCpp, wImportObjC, wError, wDiscardable, wGensym, wInject, wRaises,
wTags, wLocks, wGcSafe} wTags, wLocks, wGcSafe}
exprPragmas* = {wLine, wLocks} exprPragmas* = {wLine, wLocks, wNoRewrite}
stmtPragmas* = {wChecks, wObjChecks, wFieldChecks, wRangechecks, stmtPragmas* = {wChecks, wObjChecks, wFieldChecks, wRangechecks,
wBoundchecks, wOverflowchecks, wNilchecks, wAssertions, wWarnings, wHints, wBoundchecks, wOverflowchecks, wNilchecks, wAssertions, wWarnings, wHints,
wLinedir, wStacktrace, wLinetrace, wOptimization, wHint, wWarning, wError, wLinedir, wStacktrace, wLinetrace, wOptimization, wHint, wWarning, wError,
@ -859,6 +859,8 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
c.module.flags.incl sfExperimental c.module.flags.incl sfExperimental
else: else:
localError(it.info, "'experimental' pragma only valid as toplevel statement") localError(it.info, "'experimental' pragma only valid as toplevel statement")
of wNoRewrite:
noVal(it)
else: invalidPragma(it) else: invalidPragma(it)
else: invalidPragma(it) else: invalidPragma(it)
else: processNote(c, it) else: processNote(c, it)

View file

@ -209,7 +209,10 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
pickBest(callOp) pickBest(callOp)
if overloadsState == csEmpty and result.state == csEmpty: if overloadsState == csEmpty and result.state == csEmpty:
localError(n.info, errUndeclaredIdentifier, considerQuotedIdent(f).s) if nfDotField in n.flags and nfExplicitCall notin n.flags:
localError(n.info, errUndeclaredField, considerQuotedIdent(f).s)
else:
localError(n.info, errUndeclaredRoutine, considerQuotedIdent(f).s)
return return
elif result.state != csMatch: elif result.state != csMatch:
if nfExprCall in n.flags: if nfExprCall in n.flags:

View file

@ -207,9 +207,9 @@ proc markGcUnsafe(a: PEffects; reason: PNode) =
a.owner.gcUnsafetyReason = newSym(skUnknown, getIdent("<unknown>"), a.owner.gcUnsafetyReason = newSym(skUnknown, getIdent("<unknown>"),
a.owner, reason.info) a.owner, reason.info)
proc listGcUnsafety(s: PSym; onlyWarning: bool) = proc listGcUnsafety(s: PSym; onlyWarning: bool; cycleCheck: var IntSet) =
let u = s.gcUnsafetyReason let u = s.gcUnsafetyReason
if u != nil: if u != nil and not cycleCheck.containsOrIncl(u.id):
let msgKind = if onlyWarning: warnGcUnsafe2 else: errGenerated let msgKind = if onlyWarning: warnGcUnsafe2 else: errGenerated
if u.kind in {skLet, skVar}: if u.kind in {skLet, skVar}:
message(s.info, msgKind, message(s.info, msgKind,
@ -218,7 +218,7 @@ proc listGcUnsafety(s: PSym; onlyWarning: bool) =
elif u.kind in routineKinds: elif u.kind in routineKinds:
# recursive call *always* produces only a warning so the full error # recursive call *always* produces only a warning so the full error
# message is printed: # message is printed:
listGcUnsafety(u, true) listGcUnsafety(u, true, cycleCheck)
message(s.info, msgKind, message(s.info, msgKind,
"'$#' is not GC-safe as it calls '$#'" % "'$#' is not GC-safe as it calls '$#'" %
[s.name.s, u.name.s]) [s.name.s, u.name.s])
@ -227,6 +227,10 @@ proc listGcUnsafety(s: PSym; onlyWarning: bool) =
message(u.info, msgKind, message(u.info, msgKind,
"'$#' is not GC-safe as it performs an indirect call here" % s.name.s) "'$#' is not GC-safe as it performs an indirect call here" % s.name.s)
proc listGcUnsafety(s: PSym; onlyWarning: bool) =
var cycleCheck = initIntSet()
listGcUnsafety(s, onlyWarning, cycleCheck)
proc useVar(a: PEffects, n: PNode) = proc useVar(a: PEffects, n: PNode) =
let s = n.sym let s = n.sym
if isLocalVar(a, s): if isLocalVar(a, s):

View file

@ -1268,6 +1268,8 @@ proc semPragmaBlock(c: PContext, n: PNode): PNode =
of wLocks: of wLocks:
result = n result = n
result.typ = n.sons[1].typ result.typ = n.sons[1].typ
of wNoRewrite:
incl(result.flags, nfNoRewrite)
else: discard else: discard
proc semStaticStmt(c: PContext, n: PNode): PNode = proc semStaticStmt(c: PContext, n: PNode): PNode =

View file

@ -55,7 +55,7 @@ type
wFloatchecks, wNanChecks, wInfChecks, wFloatchecks, wNanChecks, wInfChecks,
wAssertions, wPatterns, wWarnings, wAssertions, wPatterns, wWarnings,
wHints, wOptimization, wRaises, wWrites, wReads, wSize, wEffects, wTags, wHints, wOptimization, wRaises, wWrites, wReads, wSize, wEffects, wTags,
wDeadCodeElim, wSafecode, wNoForward, wDeadCodeElim, wSafecode, wNoForward, wNoRewrite,
wPragma, wPragma,
wCompileTime, wNoInit, wCompileTime, wNoInit,
wPassc, wPassl, wBorrow, wDiscardable, wPassc, wPassl, wBorrow, wDiscardable,
@ -139,7 +139,7 @@ const
"assertions", "patterns", "warnings", "hints", "assertions", "patterns", "warnings", "hints",
"optimization", "raises", "writes", "reads", "size", "effects", "tags", "optimization", "raises", "writes", "reads", "size", "effects", "tags",
"deadcodeelim", "safecode", "noforward", "deadcodeelim", "safecode", "noforward", "norewrite",
"pragma", "pragma",
"compiletime", "noinit", "compiletime", "noinit",
"passc", "passl", "borrow", "discardable", "fieldchecks", "passc", "passl", "borrow", "discardable", "fieldchecks",

View file

@ -11,8 +11,8 @@
* `FloatInvalidOpError <system.html#FloatInvalidOpError>`_ * `FloatInvalidOpError <system.html#FloatInvalidOpError>`_
* `FloatOverflowError <system.html#FloatOverflowError>`_ * `FloatOverflowError <system.html#FloatOverflowError>`_
* `FloatUnderflowError <system.html#FloatUnderflowError>`_ * `FloatUnderflowError <system.html#FloatUnderflowError>`_
* `FieldError <system.html#InvalidFieldError>`_ * `FieldError <system.html#FieldError>`_
* `IndexError <system.html#InvalidIndexError>`_ * `IndexError <system.html#IndexError>`_
* `ObjectAssignmentError <system.html#ObjectAssignmentError>`_ * `ObjectAssignmentError <system.html#ObjectAssignmentError>`_
* `ObjectConversionError <system.html#ObjectConversionError>`_ * `ObjectConversionError <system.html#ObjectConversionError>`_
* `ValueError <system.html#ValueError>`_ * `ValueError <system.html#ValueError>`_

View file

@ -340,6 +340,8 @@ proc `[]`*(x: Any, fieldName: string): Any =
if n != nil: if n != nil:
result.value = x.value +!! n.offset result.value = x.value +!! n.offset
result.rawType = n.typ result.rawType = n.typ
elif x.rawType.kind == tyObject and x.rawType.base != nil:
return `[]`(TAny(value: x.value, rawType: x.rawType.base), fieldName)
else: else:
raise newException(ValueError, "invalid field name: " & fieldName) raise newException(ValueError, "invalid field name: " & fieldName)

View file

@ -114,7 +114,7 @@ type
atEnd: bool atEnd: bool
PZipFileStream* = PZipFileStream* =
ref ZipFileStream ## a reader stream of a file within a zip archive ref TZipFileStream ## a reader stream of a file within a zip archive
proc fsClose(s: Stream) = zip_fclose(PZipFileStream(s).f) proc fsClose(s: Stream) = zip_fclose(PZipFileStream(s).f)
proc fsAtEnd(s: Stream): bool = PZipFileStream(s).atEnd proc fsAtEnd(s: Stream): bool = PZipFileStream(s).atEnd

View file

@ -99,16 +99,13 @@ proc lowerBound*[T](a: openArray[T], key: T, cmp: proc(x,y: T): int {.closure.})
## arr.insert(4, arr.lowerBound(4)) ## arr.insert(4, arr.lowerBound(4))
## `after running the above arr is `[1,2,3,4,5,6,7,8,9]` ## `after running the above arr is `[1,2,3,4,5,6,7,8,9]`
result = a.low result = a.low
var pos = result var count = a.high - a.low + 1
var count, step: int var step, pos: int
count = a.high - a.low + 1
while count != 0: while count != 0:
pos = result
step = count div 2 step = count div 2
pos += step pos = result + step
if cmp(a[pos], key) < 0: if cmp(a[pos], key) < 0:
pos.inc result = pos + 1
result = pos
count -= step + 1 count -= step + 1
else: else:
count = step count = step
@ -331,3 +328,16 @@ proc prevPermutation*[T](x: var openarray[T]): bool {.discardable.} =
swap x[i-1], x[j] swap x[i-1], x[j]
result = true result = true
when isMainModule:
# Tests for lowerBound
var arr = @[1,2,3,5,6,7,8,9]
assert arr.lowerBound(0) == 0
assert arr.lowerBound(4) == 3
assert arr.lowerBound(5) == 3
assert arr.lowerBound(10) == 8
arr = @[1,5,10]
assert arr.lowerBound(4) == 1
assert arr.lowerBound(5) == 1
assert arr.lowerBound(6) == 2

View file

@ -91,13 +91,13 @@ type
# TODO: Save AF, domain etc info and reuse it in procs which need it like connect. # TODO: Save AF, domain etc info and reuse it in procs which need it like connect.
proc newAsyncSocket*(fd: AsyncFD, isBuff: bool): AsyncSocket = proc newAsyncSocket*(fd: AsyncFD, buffered = true): AsyncSocket =
## Creates a new ``AsyncSocket`` based on the supplied params. ## Creates a new ``AsyncSocket`` based on the supplied params.
assert fd != osInvalidSocket.AsyncFD assert fd != osInvalidSocket.AsyncFD
new(result) new(result)
result.fd = fd.SocketHandle result.fd = fd.SocketHandle
result.isBuffered = isBuff result.isBuffered = buffered
if isBuff: if buffered:
result.currPos = 0 result.currPos = 0
proc newAsyncSocket*(domain: Domain = AF_INET, typ: SockType = SOCK_STREAM, proc newAsyncSocket*(domain: Domain = AF_INET, typ: SockType = SOCK_STREAM,

View file

@ -13,7 +13,7 @@
when defined(windows): when defined(windows):
import winlean, os, strutils, math import winlean, os, strutils, math
proc `-`(a, b: TFILETIME): int64 = a.rdFileTime - b.rdFileTime proc `-`(a, b: FILETIME): int64 = a.rdFileTime - b.rdFileTime
elif defined(linux): elif defined(linux):
from cpuinfo import countProcessors from cpuinfo import countProcessors
@ -25,14 +25,14 @@ type
ThreadPoolState* = object ThreadPoolState* = object
when defined(windows): when defined(windows):
prevSysKernel, prevSysUser, prevProcKernel, prevProcUser: TFILETIME prevSysKernel, prevSysUser, prevProcKernel, prevProcUser: FILETIME
calls*: int calls*: int
proc advice*(s: var ThreadPoolState): ThreadPoolAdvice = proc advice*(s: var ThreadPoolState): ThreadPoolAdvice =
when defined(windows): when defined(windows):
var var
sysIdle, sysKernel, sysUser, sysIdle, sysKernel, sysUser,
procCreation, procExit, procKernel, procUser: TFILETIME procCreation, procExit, procKernel, procUser: FILETIME
if getSystemTimes(sysIdle, sysKernel, sysUser) == 0 or if getSystemTimes(sysIdle, sysKernel, sysUser) == 0 or
getProcessTimes(Handle(-1), procCreation, procExit, getProcessTimes(Handle(-1), procCreation, procExit,
procKernel, procUser) == 0: procKernel, procUser) == 0:

View file

@ -108,7 +108,7 @@ proc del*(monitor: FSMonitor, wd: cint) =
proc getEvent(m: FSMonitor, fd: cint): seq[MonitorEvent] = proc getEvent(m: FSMonitor, fd: cint): seq[MonitorEvent] =
result = @[] result = @[]
let size = (sizeof(TINotifyEvent)+2000)*MaxEvents let size = (sizeof(INotifyEvent)+2000)*MaxEvents
var buffer = newString(size) var buffer = newString(size)
let le = read(fd, addr(buffer[0]), size) let le = read(fd, addr(buffer[0]), size)
@ -117,7 +117,7 @@ proc getEvent(m: FSMonitor, fd: cint): seq[MonitorEvent] =
var i = 0 var i = 0
while i < le: while i < le:
var event = cast[ptr TINotifyEvent](addr(buffer[i])) var event = cast[ptr INotifyEvent](addr(buffer[i]))
var mev: MonitorEvent var mev: MonitorEvent
mev.wd = event.wd mev.wd = event.wd
if event.len.int != 0: if event.len.int != 0:
@ -129,7 +129,7 @@ proc getEvent(m: FSMonitor, fd: cint): seq[MonitorEvent] =
if (event.mask.int and IN_MOVED_FROM) != 0: if (event.mask.int and IN_MOVED_FROM) != 0:
# Moved from event, add to m's collection # Moved from event, add to m's collection
movedFrom.add(event.cookie.cint, (mev.wd, mev.name)) movedFrom.add(event.cookie.cint, (mev.wd, mev.name))
inc(i, sizeof(TINotifyEvent) + event.len.int) inc(i, sizeof(INotifyEvent) + event.len.int)
continue continue
elif (event.mask.int and IN_MOVED_TO) != 0: elif (event.mask.int and IN_MOVED_TO) != 0:
mev.kind = MonitorMoved mev.kind = MonitorMoved
@ -159,7 +159,7 @@ proc getEvent(m: FSMonitor, fd: cint): seq[MonitorEvent] =
mev.fullname = "" mev.fullname = ""
result.add(mev) result.add(mev)
inc(i, sizeof(TINotifyEvent) + event.len.int) inc(i, sizeof(INotifyEvent) + event.len.int)
# If movedFrom events have not been matched with a moveTo. File has # If movedFrom events have not been matched with a moveTo. File has
# been moved to an unwatched location, emit a MonitorDelete. # been moved to an unwatched location, emit a MonitorDelete.

View file

@ -119,13 +119,13 @@ proc toOSFlags*(socketFlags: set[SocketFlag]): cint =
result = result or MSG_PEEK result = result or MSG_PEEK
of SocketFlag.SafeDisconn: continue of SocketFlag.SafeDisconn: continue
proc newSocket(fd: SocketHandle, isBuff: bool): Socket = proc newSocket*(fd: SocketHandle, buffered = true): Socket =
## Creates a new socket as specified by the params. ## Creates a new socket as specified by the params.
assert fd != osInvalidSocket assert fd != osInvalidSocket
new(result) new(result)
result.fd = fd result.fd = fd
result.isBuffered = isBuff result.isBuffered = buffered
if isBuff: if buffered:
result.currPos = 0 result.currPos = 0
proc newSocket*(domain, typ, protocol: cint, buffered = true): Socket = proc newSocket*(domain, typ, protocol: cint, buffered = true): Socket =

View file

@ -1,698 +0,0 @@
#
#
# Nim's Runtime Library
# (c) Copyright 2015 Andreas Rumpf, Dominik Picheta
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
import
hashes, strutils, lexbase, streams, unicode, macros
type
SexpEventKind* = enum ## enumeration of all events that may occur when parsing
sexpError, ## an error occurred during parsing
sexpEof, ## end of file reached
sexpString, ## a string literal
sexpSymbol, ## a symbol
sexpInt, ## an integer literal
sexpFloat, ## a float literal
sexpNil, ## the value ``nil``
sexpDot, ## the dot to separate car/cdr
sexpListStart, ## start of a list: the ``(`` token
sexpListEnd, ## end of a list: the ``)`` token
TokKind = enum # must be synchronized with SexpEventKind!
tkError,
tkEof,
tkString,
tkSymbol,
tkInt,
tkFloat,
tkNil,
tkDot,
tkParensLe,
tkParensRi
tkSpace
SexpError* = enum ## enumeration that lists all errors that can occur
errNone, ## no error
errInvalidToken, ## invalid token
errParensRiExpected, ## ``)`` expected
errQuoteExpected, ## ``"`` expected
errEofExpected, ## EOF expected
SexpParser* = object of BaseLexer ## the parser object.
a: string
tok: TokKind
kind: SexpEventKind
err: SexpError
{.deprecated: [TTokKind: TokKind].}
const
errorMessages: array [SexpError, string] = [
"no error",
"invalid token",
"')' expected",
"'\"' or \"'\" expected",
"EOF expected",
]
tokToStr: array [TokKind, string] = [
"invalid token",
"EOF",
"string literal",
"symbol",
"int literal",
"float literal",
"nil",
".",
"(", ")", "space"
]
proc close*(my: var SexpParser) {.inline.} =
## closes the parser `my` and its associated input stream.
lexbase.close(my)
proc str*(my: SexpParser): string {.inline.} =
## returns the character data for the events: ``sexpInt``, ``sexpFloat``,
## ``sexpString``
assert(my.kind in {sexpInt, sexpFloat, sexpString})
result = my.a
proc getInt*(my: SexpParser): BiggestInt {.inline.} =
## returns the number for the event: ``sexpInt``
assert(my.kind == sexpInt)
result = parseBiggestInt(my.a)
proc getFloat*(my: SexpParser): float {.inline.} =
## returns the number for the event: ``sexpFloat``
assert(my.kind == sexpFloat)
result = parseFloat(my.a)
proc kind*(my: SexpParser): SexpEventKind {.inline.} =
## returns the current event type for the SEXP parser
result = my.kind
proc getColumn*(my: SexpParser): int {.inline.} =
## get the current column the parser has arrived at.
result = getColNumber(my, my.bufpos)
proc getLine*(my: SexpParser): int {.inline.} =
## get the current line the parser has arrived at.
result = my.lineNumber
proc errorMsg*(my: SexpParser): string =
## returns a helpful error message for the event ``sexpError``
assert(my.kind == sexpError)
result = "($1, $2) Error: $3" % [$getLine(my), $getColumn(my), errorMessages[my.err]]
proc errorMsgExpected*(my: SexpParser, e: string): string =
## returns an error message "`e` expected" in the same format as the
## other error messages
result = "($1, $2) Error: $3" % [$getLine(my), $getColumn(my), e & " expected"]
proc handleHexChar(c: char, x: var int): bool =
result = true # Success
case c
of '0'..'9': x = (x shl 4) or (ord(c) - ord('0'))
of 'a'..'f': x = (x shl 4) or (ord(c) - ord('a') + 10)
of 'A'..'F': x = (x shl 4) or (ord(c) - ord('A') + 10)
else: result = false # error
proc parseString(my: var SexpParser): TokKind =
result = tkString
var pos = my.bufpos + 1
var buf = my.buf
while true:
case buf[pos]
of '\0':
my.err = errQuoteExpected
result = tkError
break
of '"':
inc(pos)
break
of '\\':
case buf[pos+1]
of '\\', '"', '\'', '/':
add(my.a, buf[pos+1])
inc(pos, 2)
of 'b':
add(my.a, '\b')
inc(pos, 2)
of 'f':
add(my.a, '\f')
inc(pos, 2)
of 'n':
add(my.a, '\L')
inc(pos, 2)
of 'r':
add(my.a, '\C')
inc(pos, 2)
of 't':
add(my.a, '\t')
inc(pos, 2)
of 'u':
inc(pos, 2)
var r: int
if handleHexChar(buf[pos], r): inc(pos)
if handleHexChar(buf[pos], r): inc(pos)
if handleHexChar(buf[pos], r): inc(pos)
if handleHexChar(buf[pos], r): inc(pos)
add(my.a, toUTF8(Rune(r)))
else:
# don't bother with the error
add(my.a, buf[pos])
inc(pos)
of '\c':
pos = lexbase.handleCR(my, pos)
buf = my.buf
add(my.a, '\c')
of '\L':
pos = lexbase.handleLF(my, pos)
buf = my.buf
add(my.a, '\L')
else:
add(my.a, buf[pos])
inc(pos)
my.bufpos = pos # store back
proc parseNumber(my: var SexpParser) =
var pos = my.bufpos
var buf = my.buf
if buf[pos] == '-':
add(my.a, '-')
inc(pos)
if buf[pos] == '.':
add(my.a, "0.")
inc(pos)
else:
while buf[pos] in Digits:
add(my.a, buf[pos])
inc(pos)
if buf[pos] == '.':
add(my.a, '.')
inc(pos)
# digits after the dot:
while buf[pos] in Digits:
add(my.a, buf[pos])
inc(pos)
if buf[pos] in {'E', 'e'}:
add(my.a, buf[pos])
inc(pos)
if buf[pos] in {'+', '-'}:
add(my.a, buf[pos])
inc(pos)
while buf[pos] in Digits:
add(my.a, buf[pos])
inc(pos)
my.bufpos = pos
proc parseSymbol(my: var SexpParser) =
var pos = my.bufpos
var buf = my.buf
if buf[pos] in IdentStartChars:
while buf[pos] in IdentChars:
add(my.a, buf[pos])
inc(pos)
my.bufpos = pos
proc getTok(my: var SexpParser): TokKind =
setLen(my.a, 0)
case my.buf[my.bufpos]
of '-', '0'..'9': # numbers that start with a . are not parsed
# correctly.
parseNumber(my)
if {'.', 'e', 'E'} in my.a:
result = tkFloat
else:
result = tkInt
of '"': #" # gotta fix nim-mode
result = parseString(my)
of '(':
inc(my.bufpos)
result = tkParensLe
of ')':
inc(my.bufpos)
result = tkParensRi
of '\0':
result = tkEof
of 'a'..'z', 'A'..'Z', '_':
parseSymbol(my)
if my.a == "nil":
result = tkNil
else:
result = tkSymbol
of ' ':
result = tkSpace
inc(my.bufpos)
of '.':
result = tkDot
inc(my.bufpos)
else:
inc(my.bufpos)
result = tkError
my.tok = result
# ------------- higher level interface ---------------------------------------
type
SexpNodeKind* = enum ## possible SEXP node types
SNil,
SInt,
SFloat,
SString,
SSymbol,
SList,
SCons
SexpNode* = ref SexpNodeObj ## SEXP node
SexpNodeObj* {.acyclic.} = object
case kind*: SexpNodeKind
of SString:
str*: string
of SSymbol:
symbol*: string
of SInt:
num*: BiggestInt
of SFloat:
fnum*: float
of SList:
elems*: seq[SexpNode]
of SCons:
car: SexpNode
cdr: SexpNode
of SNil:
discard
Cons = tuple[car: SexpNode, cdr: SexpNode]
SexpParsingError* = object of ValueError ## is raised for a SEXP error
proc raiseParseErr*(p: SexpParser, msg: string) {.noinline, noreturn.} =
## raises an `ESexpParsingError` exception.
raise newException(SexpParsingError, errorMsgExpected(p, msg))
proc newSString*(s: string): SexpNode {.procvar.}=
## Creates a new `SString SexpNode`.
new(result)
result.kind = SString
result.str = s
proc newSStringMove(s: string): SexpNode =
new(result)
result.kind = SString
shallowCopy(result.str, s)
proc newSInt*(n: BiggestInt): SexpNode {.procvar.} =
## Creates a new `SInt SexpNode`.
new(result)
result.kind = SInt
result.num = n
proc newSFloat*(n: float): SexpNode {.procvar.} =
## Creates a new `SFloat SexpNode`.
new(result)
result.kind = SFloat
result.fnum = n
proc newSNil*(): SexpNode {.procvar.} =
## Creates a new `SNil SexpNode`.
new(result)
proc newSCons*(car, cdr: SexpNode): SexpNode {.procvar.} =
## Creates a new `SCons SexpNode`
new(result)
result.kind = SCons
result.car = car
result.cdr = cdr
proc newSList*(): SexpNode {.procvar.} =
## Creates a new `SList SexpNode`
new(result)
result.kind = SList
result.elems = @[]
proc newSSymbol*(s: string): SexpNode {.procvar.} =
new(result)
result.kind = SSymbol
result.symbol = s
proc newSSymbolMove(s: string): SexpNode =
new(result)
result.kind = SSymbol
shallowCopy(result.symbol, s)
proc getStr*(n: SexpNode, default: string = ""): string =
## Retrieves the string value of a `SString SexpNode`.
##
## Returns ``default`` if ``n`` is not a ``SString``.
if n.kind != SString: return default
else: return n.str
proc getNum*(n: SexpNode, default: BiggestInt = 0): BiggestInt =
## Retrieves the int value of a `SInt SexpNode`.
##
## Returns ``default`` if ``n`` is not a ``SInt``.
if n.kind != SInt: return default
else: return n.num
proc getFNum*(n: SexpNode, default: float = 0.0): float =
## Retrieves the float value of a `SFloat SexpNode`.
##
## Returns ``default`` if ``n`` is not a ``SFloat``.
if n.kind != SFloat: return default
else: return n.fnum
proc getSymbol*(n: SexpNode, default: string = ""): string =
## Retrieves the int value of a `SList SexpNode`.
##
## Returns ``default`` if ``n`` is not a ``SList``.
if n.kind != SSymbol: return default
else: return n.symbol
proc getElems*(n: SexpNode, default: seq[SexpNode] = @[]): seq[SexpNode] =
## Retrieves the int value of a `SList SexpNode`.
##
## Returns ``default`` if ``n`` is not a ``SList``.
if n.kind == SNil: return @[]
elif n.kind != SList: return default
else: return n.elems
proc getCons*(n: SexpNode, defaults: Cons = (newSNil(), newSNil())): Cons =
## Retrieves the cons value of a `SList SexpNode`.
##
## Returns ``default`` if ``n`` is not a ``SList``.
if n.kind == SCons: return (n.car, n.cdr)
elif n.kind == SList: return (n.elems[0], n.elems[1])
else: return defaults
proc sexp*(s: string): SexpNode =
## Generic constructor for SEXP data. Creates a new `SString SexpNode`.
new(result)
result.kind = SString
result.str = s
proc sexp*(n: BiggestInt): SexpNode =
## Generic constructor for SEXP data. Creates a new `SInt SexpNode`.
new(result)
result.kind = SInt
result.num = n
proc sexp*(n: float): SexpNode =
## Generic constructor for SEXP data. Creates a new `SFloat SexpNode`.
new(result)
result.kind = SFloat
result.fnum = n
proc sexp*(b: bool): SexpNode =
## Generic constructor for SEXP data. Creates a new `SSymbol
## SexpNode` with value t or `SNil SexpNode`.
new(result)
if b:
result.kind = SSymbol
result.symbol = "t"
else:
result.kind = SNil
proc sexp*(elements: openArray[SexpNode]): SexpNode =
## Generic constructor for SEXP data. Creates a new `SList SexpNode`
new(result)
result.kind = SList
newSeq(result.elems, elements.len)
for i, p in pairs(elements): result.elems[i] = p
proc sexp*(s: SexpNode): SexpNode =
result = s
proc toSexp(x: NimNode): NimNode {.compiletime.} =
case x.kind
of nnkBracket:
result = newNimNode(nnkBracket)
for i in 0 .. <x.len:
result.add(toSexp(x[i]))
else:
result = x
result = prefix(result, "sexp")
macro convertSexp*(x: expr): expr =
## Convert an expression to a SexpNode directly, without having to specify
## `%` for every element.
result = toSexp(x)
proc `==`* (a,b: SexpNode): bool =
## Check two nodes for equality
if a.isNil:
if b.isNil: return true
return false
elif b.isNil or a.kind != b.kind:
return false
else:
return case a.kind
of SString:
a.str == b.str
of SInt:
a.num == b.num
of SFloat:
a.fnum == b.fnum
of SNil:
true
of SList:
a.elems == b.elems
of SSymbol:
a.symbol == b.symbol
of SCons:
a.car == b.car and a.cdr == b.cdr
proc hash* (n:SexpNode): Hash =
## Compute the hash for a SEXP node
case n.kind
of SList:
result = hash(n.elems)
of SInt:
result = hash(n.num)
of SFloat:
result = hash(n.fnum)
of SString:
result = hash(n.str)
of SNil:
result = hash(0)
of SSymbol:
result = hash(n.symbol)
of SCons:
result = hash(n.car) !& hash(n.cdr)
proc len*(n: SexpNode): int =
## If `n` is a `SList`, it returns the number of elements.
## If `n` is a `JObject`, it returns the number of pairs.
## Else it returns 0.
case n.kind
of SList: result = n.elems.len
else: discard
proc `[]`*(node: SexpNode, index: int): SexpNode =
## Gets the node at `index` in a List. Result is undefined if `index`
## is out of bounds
assert(not isNil(node))
assert(node.kind == SList)
return node.elems[index]
proc add*(father, child: SexpNode) =
## Adds `child` to a SList node `father`.
assert father.kind == SList
father.elems.add(child)
# ------------- pretty printing ----------------------------------------------
proc indent(s: var string, i: int) =
s.add(spaces(i))
proc newIndent(curr, indent: int, ml: bool): int =
if ml: return curr + indent
else: return indent
proc nl(s: var string, ml: bool) =
if ml: s.add("\n")
proc escapeJson*(s: string): string =
## Converts a string `s` to its JSON representation.
result = newStringOfCap(s.len + s.len shr 3)
result.add("\"")
for x in runes(s):
var r = int(x)
if r >= 32 and r <= 127:
var c = chr(r)
case c
of '"': result.add("\\\"") #" # gotta fix nim-mode
of '\\': result.add("\\\\")
else: result.add(c)
else:
result.add("\\u")
result.add(toHex(r, 4))
result.add("\"")
proc copy*(p: SexpNode): SexpNode =
## Performs a deep copy of `a`.
case p.kind
of SString:
result = newSString(p.str)
of SInt:
result = newSInt(p.num)
of SFloat:
result = newSFloat(p.fnum)
of SNil:
result = newSNil()
of SSymbol:
result = newSSymbol(p.symbol)
of SList:
result = newSList()
for i in items(p.elems):
result.elems.add(copy(i))
of SCons:
result = newSCons(copy(p.car), copy(p.cdr))
proc toPretty(result: var string, node: SexpNode, indent = 2, ml = true,
lstArr = false, currIndent = 0) =
case node.kind
of SString:
if lstArr: result.indent(currIndent)
result.add(escapeJson(node.str))
of SInt:
if lstArr: result.indent(currIndent)
result.add($node.num)
of SFloat:
if lstArr: result.indent(currIndent)
result.add($node.fnum)
of SNil:
if lstArr: result.indent(currIndent)
result.add("nil")
of SSymbol:
if lstArr: result.indent(currIndent)
result.add($node.symbol)
of SList:
if lstArr: result.indent(currIndent)
if len(node.elems) != 0:
result.add("(")
result.nl(ml)
for i in 0..len(node.elems)-1:
if i > 0:
result.add(" ")
result.nl(ml) # New Line
toPretty(result, node.elems[i], indent, ml,
true, newIndent(currIndent, indent, ml))
result.nl(ml)
result.indent(currIndent)
result.add(")")
else: result.add("nil")
of SCons:
if lstArr: result.indent(currIndent)
result.add("(")
toPretty(result, node.car, indent, ml,
true, newIndent(currIndent, indent, ml))
result.add(" . ")
toPretty(result, node.cdr, indent, ml,
true, newIndent(currIndent, indent, ml))
result.add(")")
proc pretty*(node: SexpNode, indent = 2): string =
## Converts `node` to its Sexp Representation, with indentation and
## on multiple lines.
result = ""
toPretty(result, node, indent)
proc `$`*(node: SexpNode): string =
## Converts `node` to its SEXP Representation on one line.
result = ""
toPretty(result, node, 0, false)
iterator items*(node: SexpNode): SexpNode =
## Iterator for the items of `node`. `node` has to be a SList.
assert node.kind == SList
for i in items(node.elems):
yield i
iterator mitems*(node: var SexpNode): var SexpNode =
## Iterator for the items of `node`. `node` has to be a SList. Items can be
## modified.
assert node.kind == SList
for i in mitems(node.elems):
yield i
proc eat(p: var SexpParser, tok: TokKind) =
if p.tok == tok: discard getTok(p)
else: raiseParseErr(p, tokToStr[tok])
proc parseSexp(p: var SexpParser): SexpNode =
## Parses SEXP from a SEXP Parser `p`.
case p.tok
of tkString:
# we capture 'p.a' here, so we need to give it a fresh buffer afterwards:
result = newSStringMove(p.a)
p.a = ""
discard getTok(p)
of tkInt:
result = newSInt(parseBiggestInt(p.a))
discard getTok(p)
of tkFloat:
result = newSFloat(parseFloat(p.a))
discard getTok(p)
of tkNil:
result = newSNil()
discard getTok(p)
of tkSymbol:
result = newSSymbolMove(p.a)
p.a = ""
discard getTok(p)
of tkParensLe:
result = newSList()
discard getTok(p)
while p.tok notin {tkParensRi, tkDot}:
result.add(parseSexp(p))
if p.tok != tkSpace: break
discard getTok(p)
if p.tok == tkDot:
eat(p, tkDot)
eat(p, tkSpace)
result.add(parseSexp(p))
result = newSCons(result[0], result[1])
eat(p, tkParensRi)
of tkSpace, tkDot, tkError, tkParensRi, tkEof:
raiseParseErr(p, "(")
proc open*(my: var SexpParser, input: Stream) =
## initializes the parser with an input stream.
lexbase.open(my, input)
my.kind = sexpError
my.a = ""
proc parseSexp*(s: Stream): SexpNode =
## Parses from a buffer `s` into a `SexpNode`.
var p: SexpParser
p.open(s)
discard getTok(p) # read first token
result = p.parseSexp()
p.close()
proc parseSexp*(buffer: string): SexpNode =
## Parses Sexp from `buffer`.
result = parseSexp(newStringStream(buffer))
when isMainModule:
let testSexp = parseSexp("""(1 (98 2) nil (2) foobar "foo" 9.234)""")
assert(testSexp[0].getNum == 1)
assert(testSexp[1][0].getNum == 98)
assert(testSexp[2].getElems == @[])
assert(testSexp[4].getSymbol == "foobar")
assert(testSexp[5].getStr == "foo")
let alist = parseSexp("""((1 . 2) (2 . "foo"))""")
assert(alist[0].getCons.car.getNum == 1)
assert(alist[0].getCons.cdr.getNum == 2)
assert(alist[1].getCons.cdr.getStr == "foo")
# Generator:
var j = convertSexp([true, false, "foobar", [1, 2, "baz"]])
assert($j == """(t nil "foobar" (1 2 "baz"))""")

View file

@ -99,6 +99,7 @@ template test*(name: expr, body: stmt): stmt {.immediate, dirty.} =
body body
except: except:
when not defined(js):
checkpoint("Unhandled exception: " & getCurrentExceptionMsg()) checkpoint("Unhandled exception: " & getCurrentExceptionMsg())
echo getCurrentException().getStackTrace() echo getCurrentException().getStackTrace()
fail() fail()
@ -114,9 +115,7 @@ proc checkpoint*(msg: string) =
template fail* = template fail* =
bind checkpoints bind checkpoints
for msg in items(checkpoints): for msg in items(checkpoints):
# this used to be 'echo' which now breaks due to a bug. XXX will revisit echo msg
# this issue later.
stdout.writeln msg
when not defined(ECMAScript): when not defined(ECMAScript):
if abortOnError: quit(1) if abortOnError: quit(1)

View file

@ -17,6 +17,60 @@ proc raiseOverflow {.compilerproc, noinline.} =
proc raiseDivByZero {.compilerproc, noinline.} = proc raiseDivByZero {.compilerproc, noinline.} =
sysFatal(DivByZeroError, "division by zero") sysFatal(DivByZeroError, "division by zero")
when defined(builtinOverflow):
# Builtin compiler functions for improved performance
when sizeof(clong) == 8:
proc addInt64Overflow[T: int64|int](a, b: T, c: var T): bool {.
importc: "__builtin_saddl_overflow", nodecl, nosideeffect.}
proc subInt64Overflow[T: int64|int](a, b: T, c: var T): bool {.
importc: "__builtin_ssubl_overflow", nodecl, nosideeffect.}
proc mulInt64Overflow[T: int64|int](a, b: T, c: var T): bool {.
importc: "__builtin_smull_overflow", nodecl, nosideeffect.}
elif sizeof(clonglong) == 8:
proc addInt64Overflow[T: int64|int](a, b: T, c: var T): bool {.
importc: "__builtin_saddll_overflow", nodecl, nosideeffect.}
proc subInt64Overflow[T: int64|int](a, b: T, c: var T): bool {.
importc: "__builtin_ssubll_overflow", nodecl, nosideeffect.}
proc mulInt64Overflow[T: int64|int](a, b: T, c: var T): bool {.
importc: "__builtin_smulll_overflow", nodecl, nosideeffect.}
when sizeof(int) == 8:
proc addIntOverflow(a, b: int, c: var int): bool {.inline.} =
addInt64Overflow(a, b, c)
proc subIntOverflow(a, b: int, c: var int): bool {.inline.} =
subInt64Overflow(a, b, c)
proc mulIntOverflow(a, b: int, c: var int): bool {.inline.} =
mulInt64Overflow(a, b, c)
elif sizeof(int) == 4 and sizeof(cint) == 4:
proc addIntOverflow(a, b: int, c: var int): bool {.
importc: "__builtin_sadd_overflow", nodecl, nosideeffect.}
proc subIntOverflow(a, b: int, c: var int): bool {.
importc: "__builtin_ssub_overflow", nodecl, nosideeffect.}
proc mulIntOverflow(a, b: int, c: var int): bool {.
importc: "__builtin_smul_overflow", nodecl, nosideeffect.}
proc addInt64(a, b: int64): int64 {.compilerProc, inline.} =
if addInt64Overflow(a, b, result):
raiseOverflow()
proc subInt64(a, b: int64): int64 {.compilerProc, inline.} =
if subInt64Overflow(a, b, result):
raiseOverflow()
proc mulInt64(a, b: int64): int64 {.compilerproc, inline.} =
if mulInt64Overflow(a, b, result):
raiseOverflow()
else:
proc addInt64(a, b: int64): int64 {.compilerProc, inline.} = proc addInt64(a, b: int64): int64 {.compilerProc, inline.} =
result = a +% b result = a +% b
if (result xor a) >= int64(0) or (result xor b) >= int64(0): if (result xor a) >= int64(0) or (result xor b) >= int64(0):
@ -29,28 +83,6 @@ proc subInt64(a, b: int64): int64 {.compilerProc, inline.} =
return result return result
raiseOverflow() raiseOverflow()
proc negInt64(a: int64): int64 {.compilerProc, inline.} =
if a != low(int64): return -a
raiseOverflow()
proc absInt64(a: int64): int64 {.compilerProc, inline.} =
if a != low(int64):
if a >= 0: return a
else: return -a
raiseOverflow()
proc divInt64(a, b: int64): int64 {.compilerProc, inline.} =
if b == int64(0):
raiseDivByZero()
if a == low(int64) and b == int64(-1):
raiseOverflow()
return a div b
proc modInt64(a, b: int64): int64 {.compilerProc, inline.} =
if b == int64(0):
raiseDivByZero()
return a mod b
# #
# This code has been inspired by Python's source code. # This code has been inspired by Python's source code.
# The native int product x*y is either exactly right or *way* off, being # The native int product x*y is either exactly right or *way* off, being
@ -94,6 +126,27 @@ proc mulInt64(a, b: int64): int64 {.compilerproc.} =
return result return result
raiseOverflow() raiseOverflow()
proc negInt64(a: int64): int64 {.compilerProc, inline.} =
if a != low(int64): return -a
raiseOverflow()
proc absInt64(a: int64): int64 {.compilerProc, inline.} =
if a != low(int64):
if a >= 0: return a
else: return -a
raiseOverflow()
proc divInt64(a, b: int64): int64 {.compilerProc, inline.} =
if b == int64(0):
raiseDivByZero()
if a == low(int64) and b == int64(-1):
raiseOverflow()
return a div b
proc modInt64(a, b: int64): int64 {.compilerProc, inline.} =
if b == int64(0):
raiseDivByZero()
return a mod b
proc absInt(a: int): int {.compilerProc, inline.} = proc absInt(a: int): int {.compilerProc, inline.} =
if a != low(int): if a != low(int):
@ -246,6 +299,21 @@ elif false: # asmVersion and (defined(gcc) or defined(llvm_gcc)):
:"%edx" :"%edx"
""" """
when not declared(addInt) and defined(builtinOverflow):
proc addInt(a, b: int): int {.compilerProc, inline.} =
if addIntOverflow(a, b, result):
raiseOverflow()
when not declared(subInt) and defined(builtinOverflow):
proc subInt(a, b: int): int {.compilerProc, inline.} =
if subIntOverflow(a, b, result):
raiseOverflow()
when not declared(mulInt) and defined(builtinOverflow):
proc mulInt(a, b: int): int {.compilerProc, inline.} =
if mulIntOverflow(a, b, result):
raiseOverflow()
# Platform independent versions of the above (slower!) # Platform independent versions of the above (slower!)
when not declared(addInt): when not declared(addInt):
proc addInt(a, b: int): int {.compilerProc, inline.} = proc addInt(a, b: int): int {.compilerProc, inline.} =

View file

@ -58,7 +58,7 @@ type
stat: GcStat stat: GcStat
additionalRoots: CellSeq # dummy roots for GC_ref/unref additionalRoots: CellSeq # dummy roots for GC_ref/unref
{.deprecated: [TWalkOp: WalkOp, TFinalizer: Finalizer, TGcStat: GcStat, {.deprecated: [TWalkOp: WalkOp, TFinalizer: Finalizer, TGcStat: GcStat,
TGlobalMarkerProc: GlobalMarkerProc, TGcHeap, GcHeap].} TGlobalMarkerProc: GlobalMarkerProc, TGcHeap: GcHeap].}
var var
gch {.rtlThreadVar.}: GcHeap gch {.rtlThreadVar.}: GcHeap

View file

@ -690,6 +690,7 @@ const
ERROR_IO_PENDING* = 997 # a.k.a WSA_IO_PENDING ERROR_IO_PENDING* = 997 # a.k.a WSA_IO_PENDING
FILE_FLAG_OVERLAPPED* = 1073741824 FILE_FLAG_OVERLAPPED* = 1073741824
WSAECONNABORTED* = 10053 WSAECONNABORTED* = 10053
WSAEADDRINUSE* = 10048
WSAECONNRESET* = 10054 WSAECONNRESET* = 10054
WSAEDISCON* = 10101 WSAEDISCON* = 10101
WSAENETRESET* = 10052 WSAENETRESET* = 10052

View file

@ -60,7 +60,7 @@ else:
type type
Arg* = int Arg* = int
SArg* = int SArg* = int
{deprecated: [TArg: Arg, TSArg: SArg].} {.deprecated: [TArg: Arg, TSArg: SArg].}
when defined(windows) and defined(x86): when defined(windows) and defined(x86):
type type

View file

@ -29,7 +29,7 @@ elif defined(macosx):
else: else:
const const
readlineDll* = "libreadline.so.6(|.0)" readlineDll* = "libreadline.so.6(|.0)"
# mangle "'TCommandFunc'" TCommandFunc # mangle "'CommandFunc'" CommandFunc
# mangle TvcpFunc TvcpFunc # mangle TvcpFunc TvcpFunc
import rltypedefs import rltypedefs
@ -80,7 +80,7 @@ const
type type
KEYMAP_ENTRY*{.pure, final.} = object KEYMAP_ENTRY*{.pure, final.} = object
typ*: char typ*: char
function*: TCommandFunc function*: CommandFunc
{.deprecated: [TKEYMAP_ENTRY: KEYMAP_ENTRY].} {.deprecated: [TKEYMAP_ENTRY: KEYMAP_ENTRY].}
@ -243,7 +243,7 @@ when not defined(macosx):
type type
FUNMAP*{.pure, final.} = object FUNMAP*{.pure, final.} = object
name*: cstring name*: cstring
function*: TCommandFunc function*: CommandFunc
{.deprecated: [TFUNMAP: FUNMAP].} {.deprecated: [TFUNMAP: FUNMAP].}
@ -610,31 +610,31 @@ proc discard_argument*(): cint{.cdecl, importc: "rl_discard_argument",
dynlib: readlineDll.} dynlib: readlineDll.}
# Utility functions to bind keys to readline commands. # Utility functions to bind keys to readline commands.
proc add_defun*(a2: cstring, a3: TCommandFunc, a4: cint): cint{.cdecl, proc add_defun*(a2: cstring, a3: CommandFunc, a4: cint): cint{.cdecl,
importc: "rl_add_defun", dynlib: readlineDll.} importc: "rl_add_defun", dynlib: readlineDll.}
proc bind_key*(a2: cint, a3: TCommandFunc): cint{.cdecl, proc bind_key*(a2: cint, a3: CommandFunc): cint{.cdecl,
importc: "rl_bind_key", dynlib: readlineDll.} importc: "rl_bind_key", dynlib: readlineDll.}
proc bind_key_in_map*(a2: cint, a3: TCommandFunc, a4: PKeymap): cint{.cdecl, proc bind_key_in_map*(a2: cint, a3: CommandFunc, a4: PKeymap): cint{.cdecl,
importc: "rl_bind_key_in_map", dynlib: readlineDll.} importc: "rl_bind_key_in_map", dynlib: readlineDll.}
proc unbind_key*(a2: cint): cint{.cdecl, importc: "rl_unbind_key", proc unbind_key*(a2: cint): cint{.cdecl, importc: "rl_unbind_key",
dynlib: readlineDll.} dynlib: readlineDll.}
proc unbind_key_in_map*(a2: cint, a3: PKeymap): cint{.cdecl, proc unbind_key_in_map*(a2: cint, a3: PKeymap): cint{.cdecl,
importc: "rl_unbind_key_in_map", dynlib: readlineDll.} importc: "rl_unbind_key_in_map", dynlib: readlineDll.}
proc bind_key_if_unbound*(a2: cint, a3: TCommandFunc): cint{.cdecl, proc bind_key_if_unbound*(a2: cint, a3: CommandFunc): cint{.cdecl,
importc: "rl_bind_key_if_unbound", dynlib: readlineDll.} importc: "rl_bind_key_if_unbound", dynlib: readlineDll.}
proc bind_key_if_unbound_in_map*(a2: cint, a3: TCommandFunc, a4: PKeymap): cint{. proc bind_key_if_unbound_in_map*(a2: cint, a3: CommandFunc, a4: PKeymap): cint{.
cdecl, importc: "rl_bind_key_if_unbound_in_map", dynlib: readlineDll.} cdecl, importc: "rl_bind_key_if_unbound_in_map", dynlib: readlineDll.}
proc unbind_function_in_map*(a2: TCommandFunc, a3: PKeymap): cint{.cdecl, proc unbind_function_in_map*(a2: CommandFunc, a3: PKeymap): cint{.cdecl,
importc: "rl_unbind_function_in_map", dynlib: readlineDll.} importc: "rl_unbind_function_in_map", dynlib: readlineDll.}
proc unbind_command_in_map*(a2: cstring, a3: PKeymap): cint{.cdecl, proc unbind_command_in_map*(a2: cstring, a3: PKeymap): cint{.cdecl,
importc: "rl_unbind_command_in_map", dynlib: readlineDll.} importc: "rl_unbind_command_in_map", dynlib: readlineDll.}
proc bind_keyseq*(a2: cstring, a3: TCommandFunc): cint{.cdecl, proc bind_keyseq*(a2: cstring, a3: CommandFunc): cint{.cdecl,
importc: "rl_bind_keyseq", dynlib: readlineDll.} importc: "rl_bind_keyseq", dynlib: readlineDll.}
proc bind_keyseq_in_map*(a2: cstring, a3: TCommandFunc, a4: PKeymap): cint{. proc bind_keyseq_in_map*(a2: cstring, a3: CommandFunc, a4: PKeymap): cint{.
cdecl, importc: "rl_bind_keyseq_in_map", dynlib: readlineDll.} cdecl, importc: "rl_bind_keyseq_in_map", dynlib: readlineDll.}
proc bind_keyseq_if_unbound*(a2: cstring, a3: TCommandFunc): cint{.cdecl, proc bind_keyseq_if_unbound*(a2: cstring, a3: CommandFunc): cint{.cdecl,
importc: "rl_bind_keyseq_if_unbound", dynlib: readlineDll.} importc: "rl_bind_keyseq_if_unbound", dynlib: readlineDll.}
proc bind_keyseq_if_unbound_in_map*(a2: cstring, a3: TCommandFunc, proc bind_keyseq_if_unbound_in_map*(a2: cstring, a3: CommandFunc,
a4: PKeymap): cint{.cdecl, a4: PKeymap): cint{.cdecl,
importc: "rl_bind_keyseq_if_unbound_in_map", dynlib: readlineDll.} importc: "rl_bind_keyseq_if_unbound_in_map", dynlib: readlineDll.}
proc generic_bind*(a2: cint, a3: cstring, a4: cstring, a5: PKeymap): cint{. proc generic_bind*(a2: cint, a3: cstring, a4: cstring, a5: PKeymap): cint{.
@ -645,7 +645,7 @@ proc variable_bind*(a2: cstring, a3: cstring): cint{.cdecl,
importc: "rl_variable_bind", dynlib: readlineDll.} importc: "rl_variable_bind", dynlib: readlineDll.}
# Backwards compatibility, use rl_bind_keyseq_in_map instead. # Backwards compatibility, use rl_bind_keyseq_in_map instead.
proc set_key*(a2: cstring, a3: TCommandFunc, a4: PKeymap): cint{.cdecl, proc set_key*(a2: cstring, a3: CommandFunc, a4: PKeymap): cint{.cdecl,
importc: "rl_set_key", dynlib: readlineDll.} importc: "rl_set_key", dynlib: readlineDll.}
# Backwards compatibility, use rl_generic_bind instead. # Backwards compatibility, use rl_generic_bind instead.
@ -657,15 +657,15 @@ proc translate_keyseq*(a2: cstring, a3: cstring, a4: ptr cint): cint{.cdecl,
importc: "rl_translate_keyseq", dynlib: readlineDll.} importc: "rl_translate_keyseq", dynlib: readlineDll.}
proc untranslate_keyseq*(a2: cint): cstring{.cdecl, proc untranslate_keyseq*(a2: cint): cstring{.cdecl,
importc: "rl_untranslate_keyseq", dynlib: readlineDll.} importc: "rl_untranslate_keyseq", dynlib: readlineDll.}
proc named_function*(a2: cstring): TCommandFunc{.cdecl, proc named_function*(a2: cstring): CommandFunc{.cdecl,
importc: "rl_named_function", dynlib: readlineDll.} importc: "rl_named_function", dynlib: readlineDll.}
proc function_of_keyseq*(a2: cstring, a3: PKeymap, a4: ptr cint): TCommandFunc{. proc function_of_keyseq*(a2: cstring, a3: PKeymap, a4: ptr cint): CommandFunc{.
cdecl, importc: "rl_function_of_keyseq", dynlib: readlineDll.} cdecl, importc: "rl_function_of_keyseq", dynlib: readlineDll.}
proc list_funmap_names*(){.cdecl, importc: "rl_list_funmap_names", proc list_funmap_names*(){.cdecl, importc: "rl_list_funmap_names",
dynlib: readlineDll.} dynlib: readlineDll.}
proc invoking_keyseqs_in_map*(a2: TCommandFunc, a3: PKeymap): cstringArray{. proc invoking_keyseqs_in_map*(a2: CommandFunc, a3: PKeymap): cstringArray{.
cdecl, importc: "rl_invoking_keyseqs_in_map", dynlib: readlineDll.} cdecl, importc: "rl_invoking_keyseqs_in_map", dynlib: readlineDll.}
proc invoking_keyseqs*(a2: TCommandFunc): cstringArray{.cdecl, proc invoking_keyseqs*(a2: CommandFunc): cstringArray{.cdecl,
importc: "rl_invoking_keyseqs", dynlib: readlineDll.} importc: "rl_invoking_keyseqs", dynlib: readlineDll.}
proc function_dumper*(a2: cint){.cdecl, importc: "rl_function_dumper", proc function_dumper*(a2: cint){.cdecl, importc: "rl_function_dumper",
dynlib: readlineDll.} dynlib: readlineDll.}
@ -688,7 +688,7 @@ proc get_keymap_name_from_edit_mode*(): cstring{.cdecl,
importc: "rl_get_keymap_name_from_edit_mode", dynlib: readlineDll.} importc: "rl_get_keymap_name_from_edit_mode", dynlib: readlineDll.}
# Functions for manipulating the funmap, which maps command names to functions. # Functions for manipulating the funmap, which maps command names to functions.
proc add_funmap_entry*(a2: cstring, a3: TCommandFunc): cint{.cdecl, proc add_funmap_entry*(a2: cstring, a3: CommandFunc): cint{.cdecl,
importc: "rl_add_funmap_entry", dynlib: readlineDll.} importc: "rl_add_funmap_entry", dynlib: readlineDll.}
proc funmap_names*(): cstringArray{.cdecl, importc: "rl_funmap_names", proc funmap_names*(): cstringArray{.cdecl, importc: "rl_funmap_names",
dynlib: readlineDll.} dynlib: readlineDll.}
@ -828,7 +828,7 @@ proc username_completion_function*(a2: cstring, a3: cint): cstring{.cdecl,
importc: "rl_username_completion_function", dynlib: readlineDll.} importc: "rl_username_completion_function", dynlib: readlineDll.}
proc filename_completion_function*(a2: cstring, a3: cint): cstring{.cdecl, proc filename_completion_function*(a2: cstring, a3: cint): cstring{.cdecl,
importc: "rl_filename_completion_function", dynlib: readlineDll.} importc: "rl_filename_completion_function", dynlib: readlineDll.}
proc completion_mode*(a2: TCommandFunc): cint{.cdecl, proc completion_mode*(a2: CommandFunc): cint{.cdecl,
importc: "rl_completion_mode", dynlib: readlineDll.} importc: "rl_completion_mode", dynlib: readlineDll.}
# **************************************************************** # ****************************************************************
# #
@ -883,7 +883,7 @@ when false:
# The current value of the numeric argument specified by the user. # The current value of the numeric argument specified by the user.
var numeric_arg*{.importc: "rl_numeric_arg", dynlib: readlineDll.}: cint var numeric_arg*{.importc: "rl_numeric_arg", dynlib: readlineDll.}: cint
# The address of the last command function Readline executed. # The address of the last command function Readline executed.
var last_func*{.importc: "rl_last_func", dynlib: readlineDll.}: TCommandFunc var last_func*{.importc: "rl_last_func", dynlib: readlineDll.}: CommandFunc
# The name of the terminal to use. # The name of the terminal to use.
var terminal_name*{.importc: "rl_terminal_name", dynlib: readlineDll.}: cstring var terminal_name*{.importc: "rl_terminal_name", dynlib: readlineDll.}: cstring
# The input and output streams. # The input and output streams.
@ -1186,7 +1186,7 @@ type
rlstate*: cint rlstate*: cint
done*: cint done*: cint
kmap*: PKeymap # input state kmap*: PKeymap # input state
lastfunc*: TCommandFunc lastfunc*: CommandFunc
insmode*: cint insmode*: cint
edmode*: cint edmode*: cint
kseqlen*: cint kseqlen*: cint

View file

@ -775,7 +775,7 @@ type
Arg*{.final.} = object Arg*{.final.} = object
buf*: array[0..ERR_MAX_STRLEN - 1, int8] buf*: array[0..ERR_MAX_STRLEN - 1, int8]
Perror* = ptr Terror Perror* = ptr Error
Error*{.final.} = object # This is a numeric value corresponding to the current error Error*{.final.} = object # This is a numeric value corresponding to the current error
# SDL_rwops.h types # SDL_rwops.h types
# This is the read/write operation structure -- very basic # This is the read/write operation structure -- very basic
@ -814,7 +814,7 @@ type
theType*: cint theType*: cint
mem*: Mem mem*: Mem
RWops* = RWops # SDL_timer.h types # SDL_timer.h types
# Function prototype for the timer callback function # Function prototype for the timer callback function
TimerCallback* = proc (interval: int32): int32{.cdecl.} TimerCallback* = proc (interval: int32): int32{.cdecl.}
NewTimerCallback* = proc (interval: int32, param: pointer): int32{.cdecl.} NewTimerCallback* = proc (interval: int32, param: pointer): int32{.cdecl.}
@ -950,8 +950,8 @@ type
EventAction* = enum # Application visibility event structure EventAction* = enum # Application visibility event structure
ADDEVENT, PEEKEVENT, GETEVENT ADDEVENT, PEEKEVENT, GETEVENT
PActiveEvent* = ptr ActiveEvent PActiveEvent* = ptr TActiveEvent
ActiveEvent*{.final.} = object # SDL_ACTIVEEVENT TActiveEvent*{.final.} = object # SDL_ACTIVEEVENT
# Keyboard event structure # Keyboard event structure
kind*: EventKind kind*: EventKind
gain*: byte # Whether given states were gained or lost (1/0) gain*: byte # Whether given states were gained or lost (1/0)
@ -1032,8 +1032,8 @@ type
w*: cint # New width w*: cint # New width
h*: cint # New height h*: cint # New height
PUserEvent* = ptr UserEvent PUserEvent* = ptr TUserEvent
UserEvent*{.final.} = object # SDL_USEREVENT through SDL_NUMEVENTS-1 TUserEvent*{.final.} = object # SDL_USEREVENT through SDL_NUMEVENTS-1
kind*: EventKind kind*: EventKind
code*: cint # User defined event code code*: cint # User defined event code
data1*: pointer # User defined data pointer data1*: pointer # User defined data pointer
@ -1044,7 +1044,7 @@ type
TWrite: Write, TBool: Bool, TUInt8Array: UInt8Array, TWrite: Write, TBool: Bool, TUInt8Array: UInt8Array,
TGrabMode: GrabMode, Terrorcode: Errorcode, TStdio: Stdio, TGrabMode: GrabMode, Terrorcode: Errorcode, TStdio: Stdio,
TMem: Mem, TSeek: Seek, TRead: Read, TClose: Close, TMem: Mem, TSeek: Seek, TRead: Read, TClose: Close,
TTimerCallback: TimerCallback, TNewTimerCallback: NewTimerCallabck, TTimerCallback: TimerCallback, TNewTimerCallback: NewTimerCallback,
TTimerID: TimerID, TAudioSpecCallback: AudioSpecCallback, TTimerID: TimerID, TAudioSpecCallback: AudioSpecCallback,
TAudioSpec: AudioSpec, TAudioCVTFilter: AudioCVTFilter, TAudioSpec: AudioSpec, TAudioCVTFilter: AudioCVTFilter,
TAudioCVTFilterArray: AudioCVTFilterArray, TAudioCVT: AudioCVT, TAudioCVTFilterArray: AudioCVTFilterArray, TAudioCVT: AudioCVT,
@ -1053,9 +1053,12 @@ type
TJoystick: Joystick, TJoyAxisEvent: JoyAxisEvent, TRWops: RWops, TJoystick: Joystick, TJoyAxisEvent: JoyAxisEvent, TRWops: RWops,
TJoyBallEvent: JoyBallEvent, TJoyHatEvent: JoyHatEvent, TJoyBallEvent: JoyBallEvent, TJoyHatEvent: JoyHatEvent,
TJoyButtonEvent: JoyButtonEvent, TBallDelta: BallDelta, TJoyButtonEvent: JoyButtonEvent, TBallDelta: BallDelta,
Tversion: Version, TMod: Mod, TActiveEvent: ActiveEvent, Tversion: Version, TMod: Mod,
# TActiveEvent: ActiveEvent, # Naming conflict when we drop the `T`
TMouseMotionEvent: MouseMotionEvent, TMouseButtonEvent: MouseButtonEvent, TMouseMotionEvent: MouseMotionEvent, TMouseButtonEvent: MouseButtonEvent,
TResizeEvent: ResizeEvent, TUserEvent: UserEvent].} TResizeEvent: ResizeEvent,
# TUserEvent: UserEvent # Naming conflict when we drop the `T`
].}
when defined(Unix): when defined(Unix):
type #These are the various supported subsystems under UNIX type #These are the various supported subsystems under UNIX
@ -1136,8 +1139,8 @@ else:
{.deprecated: [TSysWMinfo: SysWMinfo].} {.deprecated: [TSysWMinfo: SysWMinfo].}
type type
PSysWMEvent* = ptr SysWMEvent PSysWMEvent* = ptr TSysWMEvent
SysWMEvent*{.final.} = object TSysWMEvent*{.final.} = object
kind*: EventKind kind*: EventKind
msg*: PSysWMmsg msg*: PSysWMmsg
@ -1172,12 +1175,12 @@ type
PColorArray* = ptr ColorArray PColorArray* = ptr ColorArray
ColorArray* = array[0..65000, Color] ColorArray* = array[0..65000, Color]
PPalette* = ptr TPalette PPalette* = ptr Palette
Palette*{.final.} = object # Everything in the pixel format structure is read-only Palette*{.final.} = object # Everything in the pixel format structure is read-only
ncolors*: int ncolors*: int
colors*: PColorArray colors*: PColorArray
PPixelFormat* = ptr TPixelFormat PPixelFormat* = ptr PixelFormat
PixelFormat*{.final.} = object # The structure passed to the low level blit functions PixelFormat*{.final.} = object # The structure passed to the low level blit functions
palette*: PPalette palette*: PPalette
bitsPerPixel*: byte bitsPerPixel*: byte
@ -1269,7 +1272,8 @@ type
wmCursor*: pointer # Window-manager cursor wmCursor*: pointer # Window-manager cursor
{.deprecated: [TRect: Rect, TSurface: Surface, TEvent: Event, TColor: Color, {.deprecated: [TRect: Rect, TSurface: Surface, TEvent: Event, TColor: Color,
TEventFilter: EventFilter, TColorArray: ColorArray, TEventFilter: EventFilter, TColorArray: ColorArray,
TSysWMEvent: SysWMEvent, TExposeEvent: ExposeEvent, # TSysWMEvent: SysWMEvent, # Naming conflict when we drop the `T`
TExposeEvent: ExposeEvent,
TQuitEvent: QuitEvent, TPalette: Palette, TPixelFormat: PixelFormat, TQuitEvent: QuitEvent, TPalette: Palette, TPixelFormat: PixelFormat,
TBlitInfo: BlitInfo, TBlit: Blit, TVideoInfo: VideoInfo, TBlitInfo: BlitInfo, TBlit: Blit, TVideoInfo: VideoInfo,
TOverlay: Overlay, TGLAttr: GLAttr, TCursor: Cursor].} TOverlay: Overlay, TGLAttr: GLAttr, TCursor: Cursor].}
@ -1300,7 +1304,7 @@ type # This is the system-independent thread info struc
threadid*: int32 threadid*: int32
handle*: SYS_ThreadHandle handle*: SYS_ThreadHandle
status*: int status*: int
errbuf*: Terror errbuf*: Error
data*: pointer data*: pointer
PKeyStateArr* = ptr KeyStateArr PKeyStateArr* = ptr KeyStateArr
@ -2211,7 +2215,7 @@ proc glLoadLibrary*(filename: cstring): int{.cdecl,
proc glGetProcAddress*(procname: cstring): pointer{.cdecl, proc glGetProcAddress*(procname: cstring): pointer{.cdecl,
importc: "SDL_GL_GetProcAddress", dynlib: LibName.} importc: "SDL_GL_GetProcAddress", dynlib: LibName.}
# Set an attribute of the OpenGL subsystem before intialization. # Set an attribute of the OpenGL subsystem before intialization.
proc glSetAttribute*(attr: TGLAttr, value: int): int{.cdecl, proc glSetAttribute*(attr: GLAttr, value: int): int{.cdecl,
importc: "SDL_GL_SetAttribute", dynlib: LibName.} importc: "SDL_GL_SetAttribute", dynlib: LibName.}
# Get an attribute of the OpenGL subsystem from the windowing # Get an attribute of the OpenGL subsystem from the windowing
# interface, such as glX. This is of course different from getting # interface, such as glX. This is of course different from getting
@ -2220,7 +2224,7 @@ proc glSetAttribute*(attr: TGLAttr, value: int): int{.cdecl,
# #
# Developers should track the values they pass into SDL_GL_SetAttribute # Developers should track the values they pass into SDL_GL_SetAttribute
# themselves if they want to retrieve these values. # themselves if they want to retrieve these values.
proc glGetAttribute*(attr: TGLAttr, value: var int): int{.cdecl, proc glGetAttribute*(attr: GLAttr, value: var int): int{.cdecl,
importc: "SDL_GL_GetAttribute", dynlib: LibName.} importc: "SDL_GL_GetAttribute", dynlib: LibName.}
# Swap the OpenGL buffers, if double-buffering is supported. # Swap the OpenGL buffers, if double-buffering is supported.
proc glSwapBuffers*(){.cdecl, importc: "SDL_GL_SwapBuffers", dynlib: LibName.} proc glSwapBuffers*(){.cdecl, importc: "SDL_GL_SwapBuffers", dynlib: LibName.}
@ -2267,7 +2271,7 @@ proc wmToggleFullScreen*(surface: PSurface): int{.cdecl,
# Grabbing means that the mouse is confined to the application window, # Grabbing means that the mouse is confined to the application window,
# and nearly all keyboard input is passed directly to the application, # and nearly all keyboard input is passed directly to the application,
# and not interpreted by a window manager, if any. # and not interpreted by a window manager, if any.
proc wmGrabInput*(mode: TGrabMode): GrabMode{.cdecl, proc wmGrabInput*(mode: GrabMode): GrabMode{.cdecl,
importc: "SDL_WM_GrabInput", dynlib: LibName.} importc: "SDL_WM_GrabInput", dynlib: LibName.}
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
# mouse-routines # mouse-routines

View file

@ -1,6 +1,6 @@
discard """ discard """
line: 7 line: 7
errormsg: "undeclared identifier: 'items'" errormsg: "attempting to call undeclared routine: 'items'"
""" """
type a = enum b,c,d type a = enum b,c,d

View file

@ -1,10 +1,7 @@
discard """ discard """
disabled: "true" output: '''[OK] >:)'''
""" """
# Unittest uses lambdalifting at compile-time which we disable for the JS
# codegen! So this cannot and will not work for quite some time.
import unittest import unittest
suite "Bacon": suite "Bacon":

View file

@ -1,7 +1,7 @@
discard """ discard """
file: "tissue710.nim" file: "tissue710.nim"
line: 8 line: 8
errorMsg: "undeclared identifier: '||'" errorMsg: "attempting to call undeclared routine: '||'"
""" """
var sum = 0 var sum = 0
for x in 3..1000: for x in 3..1000:

View file

@ -1,7 +1,7 @@
discard """ discard """
file: "tnoop.nim" file: "tnoop.nim"
line: 11 line: 11
errormsg: "undeclared identifier: 'a'" errormsg: "attempting to call undeclared routine: 'a'"
""" """

View file

@ -1,7 +1,7 @@
discard """ discard """
file: "topaque.nim" file: "topaque.nim"
line: 16 line: 16
errormsg: "undeclared identifier: \'buffer\'" errormsg: "undeclared field: \'buffer\'"
""" """
# Test the new opaque types # Test the new opaque types

View file

@ -0,0 +1,26 @@
# bug #2854
import locks, threadpool, osproc
const MAX_WORKERS = 10
type
Killer = object
lock: Lock
bailed {.guard: lock.}: bool
processes {.guard: lock.}: array[0..MAX_WORKERS-1, foreign ptr Process]
template hold(lock: Lock, body: stmt) =
lock.acquire
defer: lock.release
{.locks: [lock].}:
body
proc initKiller*(): Killer =
initLock(result.lock)
result.lock.hold:
result.bailed = false
for i, _ in result.processes:
result.processes[i] = nil
var killer = initKiller()

View file

@ -1,7 +1,7 @@
discard """ discard """
file: "twrongtupleaccess.nim" file: "twrongtupleaccess.nim"
line: 9 line: 9
errormsg: "undeclared identifier: \'setBLAH\'" errormsg: "attempting to call undeclared routine: \'setBLAH\'"
""" """
# Bugfix # Bugfix

14
tests/vm/tconstobj.nim Normal file
View file

@ -0,0 +1,14 @@
discard """
output: '''(name: hello)'''
"""
# bug #2774
type Foo = object
name: string
const fooArray = [
Foo(name: "hello")
]
echo fooArray[0]

View file

@ -538,7 +538,7 @@ when haveZipLib:
var n = "$#.zip" % proj var n = "$#.zip" % proj
if c.outdir.len == 0: n = "build" / n if c.outdir.len == 0: n = "build" / n
else: n = c.outdir / n else: n = c.outdir / n
var z: TZipArchive var z: ZipArchive
if open(z, n, fmWrite): if open(z, n, fmWrite):
addFile(z, proj / buildBatFile32, "build" / buildBatFile32) addFile(z, proj / buildBatFile32, "build" / buildBatFile32)
addFile(z, proj / buildBatFile64, "build" / buildBatFile64) addFile(z, proj / buildBatFile64, "build" / buildBatFile64)