slurp uses path; unidecode is improved and threadsafe

This commit is contained in:
Araq 2011-10-08 01:17:06 +02:00
commit e956abbadd
9 changed files with 76 additions and 48 deletions

View file

@ -65,7 +65,7 @@ proc popStackFrame*(c: PEvalContext) {.inline.} =
if (c.tos == nil): InternalError("popStackFrame") if (c.tos == nil): InternalError("popStackFrame")
c.tos = c.tos.next c.tos = c.tos.next
proc eval*(c: PEvalContext, n: PNode): PNode proc evalMacroCall*(c: PEvalContext, n: PNode, sym: PSym): PNode
proc evalAux(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode proc evalAux(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode
proc stackTraceAux(x: PStackFrame) = proc stackTraceAux(x: PStackFrame) =
@ -835,24 +835,6 @@ proc evalTemplate(n: PNode, sym: PSym): PNode =
dec(evalTemplateCounter) dec(evalTemplateCounter)
proc evalMacroCall*(c: PEvalContext, n: PNode, sym: PSym): PNode =
inc(evalTemplateCounter)
if evalTemplateCounter > 100:
GlobalError(n.info, errTemplateInstantiationTooNested)
var s = newStackFrame()
s.call = n
setlen(s.params, 2)
s.params[0] = newNodeIT(nkNilLit, n.info, sym.typ.sons[0])
s.params[1] = n
pushStackFrame(c, s)
discard eval(c, sym.ast.sons[codePos])
result = s.params[0]
popStackFrame(c)
if cyclicTree(result): GlobalError(n.info, errCyclicTree)
dec(evalTemplateCounter)
proc evalExpandToAst(c: PEvalContext, original: PNode): PNode = proc evalExpandToAst(c: PEvalContext, original: PNode): PNode =
var var
n = original.copyTree n = original.copyTree
@ -1258,6 +1240,24 @@ proc evalConstExpr*(module: PSym, e: PNode): PNode =
if result != nil and result.kind == nkExceptBranch: result = nil if result != nil and result.kind == nkExceptBranch: result = nil
popStackFrame(p) popStackFrame(p)
proc evalMacroCall*(c: PEvalContext, n: PNode, sym: PSym): PNode =
# XXX GlobalError() is ugly here, but I don't know a better solution for now
inc(evalTemplateCounter)
if evalTemplateCounter > 100:
GlobalError(n.info, errTemplateInstantiationTooNested)
var s = newStackFrame()
s.call = n
setlen(s.params, 2)
s.params[0] = newNodeIT(nkNilLit, n.info, sym.typ.sons[0])
s.params[1] = n
pushStackFrame(c, s)
discard eval(c, sym.ast.sons[codePos])
result = s.params[0]
popStackFrame(c)
if cyclicTree(result): GlobalError(n.info, errCyclicTree)
dec(evalTemplateCounter)
proc myOpen(module: PSym, filename: string): PPassContext = proc myOpen(module: PSym, filename: string): PPassContext =
var c = newEvalContext(module, filename, false) var c = newEvalContext(module, filename, false)
pushStackFrame(c, newStackFrame()) pushStackFrame(c, newStackFrame())

View file

@ -942,7 +942,7 @@ proc semSlurp(c: PContext, n: PNode, flags: TExprFlags): PNode =
if sonsLen(n) == 2: if sonsLen(n) == 2:
var a = expectStringArg(c, n, 0) var a = expectStringArg(c, n, 0)
try: try:
var content = readFile(a.strVal) var content = readFile(a.strVal.FindFile)
result = newStrNode(nkStrLit, content) result = newStrNode(nkStrLit, content)
result.typ = getSysType(tyString) result.typ = getSysType(tyString)
result.info = n.info result.info = n.info

View file

@ -1547,9 +1547,8 @@ The rules for compile-time computability are:
computable arguments. computable arguments.
Constants cannot be of type ``var`` or ``object``, nor can Constants cannot be of type ``ptr``, ``ref``, ``var`` or ``object``, nor can
they contain such a type. For the types ``ptr`` and ``ref`` only the they contain such a type.
constant literal ``nil`` is possible.
If statement If statement
@ -3322,7 +3321,11 @@ improve compile times.
A thread proc is passed to ``createThread`` and invoked indirectly; so the A thread proc is passed to ``createThread`` and invoked indirectly; so the
``thread`` pragma implies ``procvar``. ``thread`` pragma implies ``procvar``.
If a global variable can also be marked with the ``thread`` pragma; it is
Threadvar pragma
----------------
A global variable can be marked with the `threadvar`:idx: pragma; it is
a `thead-local`:idx: variable then: a `thead-local`:idx: variable then:
.. code-block:: nimrod .. code-block:: nimrod

View file

@ -218,7 +218,7 @@ proc `$`*(t: PStringTable): string {.rtl, extern: "nstDollar".} =
result.add("}") result.add("}")
when isMainModule: when isMainModule:
const x = {"k": "v", "11": "22", "565": "67"}.newStringTable var x = {"k": "v", "11": "22", "565": "67"}.newStringTable
assert x["k"] == "v" assert x["k"] == "v"
assert x["11"] == "22" assert x["11"] == "22"
assert x["565"] == "67" assert x["565"] == "67"

View file

@ -972,9 +972,9 @@ proc c_sprintf(buf, frmt: CString) {.nodecl, importc: "sprintf", varargs,
type type
TFloatFormat* = enum ## the different modes of floating point formating TFloatFormat* = enum ## the different modes of floating point formating
ffDefault, ## use the shorter floating point notation ffDefault, ## use the shorter floating point notation
ffDecimal, ## use decimal floating point notation ffDecimal, ## use decimal floating point notation
ffScientific ## use scientific notation (using ``e`` character) ffScientific ## use scientific notation (using ``e`` character)
proc formatBiggestFloat*(f: BiggestFloat, format: TFloatFormat = ffDefault, proc formatBiggestFloat*(f: BiggestFloat, format: TFloatFormat = ffDefault,
precision = 16): string {.noSideEffect, precision = 16): string {.noSideEffect,

View file

@ -1,7 +1,7 @@
# #
# #
# Nimrod's Runtime Library # Nimrod's Runtime Library
# (c) Copyright 2010 Andreas Rumpf # (c) Copyright 2011 Andreas Rumpf
# #
# See the file "copying.txt", included in this # See the file "copying.txt", included in this
# distribution, for details about the copyright. # distribution, for details about the copyright.
@ -22,23 +22,32 @@
## strictly one-way transformation. However a human reader will probably ## strictly one-way transformation. However a human reader will probably
## still be able to guess what original string was meant from the context. ## still be able to guess what original string was meant from the context.
## ##
## This module needs the data file "unidecode.dat" to work, so it has to be ## This module needs the data file "unidecode.dat" to work: You can either
## shipped with the application! ## ship this file with your application and initialize this module with the
## `loadUnidecodeTable` proc or you can define the ``embedUnidecodeTable``
## symbol to embed the file as a resource into your application.
import unicode import unicode
proc loadTranslationTable(filename: string): seq[string] = when defined(embedUnidecodeTable):
newSeq(result, 0xffff) import strutils
var i = 0
for line in lines(filename):
result[i] = line
inc(i)
var const translationTable = splitLines(slurp"unidecode/unidecode.dat")
translationTable: seq[string] else:
# shared is fine for threading:
var translationTable: seq[string]
var proc loadUnidecodeTable*(datafile = "unidecode.dat") =
datafile* = "unidecode.dat" ## location can be overwritten for deployment ## loads the datafile that `unidecode` to work. Unless this module is
## compiled with the ``embedUnidecodeTable`` symbol defined, this needs
## to be called by the main thread before any thread can make a call
## to `unidecode`.
when not defined(embedUnidecodeTable):
newSeq(translationTable, 0xffff)
var i = 0
for line in lines(datafile):
translationTable[i] = line
inc(i)
proc unidecode*(s: string): string = proc unidecode*(s: string): string =
## Finds the sequence of ASCII characters that is the closest approximation ## Finds the sequence of ASCII characters that is the closest approximation
@ -51,15 +60,14 @@ proc unidecode*(s: string): string =
## ##
## Results in: "Bei Jing" ## Results in: "Bei Jing"
## ##
assert(not isNil(translationTable))
result = "" result = ""
for r in runes(s): for r in runes(s):
var c = int(r) var c = int(r)
if c <=% 127: add(result, chr(c)) if c <=% 127: add(result, chr(c))
elif c <=% 0xffff: elif c <% translationTable.len: add(result, translationTable[c-128])
if isNil(translationTable):
translationTable = loadTranslationTable(datafile)
add(result, translationTable[c-128])
when isMainModule: when isMainModule:
loadUnidecodeTable("lib/pure/unidecode/unidecode.dat")
echo unidecode("Äußerst") echo unidecode("Äußerst")

View file

@ -0,0 +1,9 @@
discard """
cmd: "nimrod cc --hints:on -d:embedUnidecodeTable $# $#"
output: "Ausserst"
"""
import unidecode
unidecode("Äußerst")

View file

@ -1,12 +1,15 @@
Version 0.8.14 Version 0.8.14
============== ==============
- fix the 'const' issues - optimize unused constants away
- 'let x = y'; const ptr/ref - 'let x = y'; const ptr/ref
- fix actors.nim - fix actors.nim
- make threadvar efficient again on linux after testing - make threadvar efficient again on linux after testing
- test the sort implementation again - test the sort implementation again
- optional indentation for 'case' statement - optional indentation for 'case' statement
- ``bind`` as a declaration
- document splicing
- fix unidecode.nim
version 0.9.0 version 0.9.0
@ -20,6 +23,7 @@ version 0.9.0
- implement closures; implement proper coroutines - implement closures; implement proper coroutines
- make exceptions compatible with C++ exceptions - make exceptions compatible with C++ exceptions
- ``=`` should be overloadable; requires specialization for ``=`` - ``=`` should be overloadable; requires specialization for ``=``
- 'const' objects including case objects
Bugs Bugs
---- ----
@ -93,6 +97,7 @@ Low priority
------------ ------------
- ``with proc `+`(x, y: T): T`` for generic code - ``with proc `+`(x, y: T): T`` for generic code
- new feature: ``distinct T with operations``
- find a way for easy constructors and destructors; (destructors are much more - find a way for easy constructors and destructors; (destructors are much more
important than constructors) important than constructors)
- code generated for type information is wasteful - code generated for type information is wasteful

View file

@ -37,6 +37,7 @@ Changes affecting backwards compatibility
- The ``is`` operator is now used to check type equivalence in generic code. - The ``is`` operator is now used to check type equivalence in generic code.
- The ``pure`` pragma for procs has been renamed to ``noStackFrame``. - The ``pure`` pragma for procs has been renamed to ``noStackFrame``.
- The threading API has been completely redesigned. - The threading API has been completely redesigned.
- The interface of the ``unidecode`` module changed and it's now thread-safe.
Language Additions Language Additions
@ -50,6 +51,7 @@ Language Additions
a compile-time error. a compile-time error.
- There is a new ``discardable`` pragma that can be used to mark a routine - There is a new ``discardable`` pragma that can be used to mark a routine
so that its result can be discarded implicitely. so that its result can be discarded implicitely.
- Constants can now have the type ``seq``.
Compiler Additions Compiler Additions
@ -74,6 +76,7 @@ Library Additions
- Added ``system.mainThreadId``. - Added ``system.mainThreadId``.
- Added ``system.allocShared``, ``system.allocShared0``, - Added ``system.allocShared``, ``system.allocShared0``,
``system.deallocShared``, ``system.reallocShared``. ``system.deallocShared``, ``system.reallocShared``.
- Slicing as implemented by the system module now supports *splicing*.
- Added explicit channels for thread communication. - Added explicit channels for thread communication.
- Added ``matchers`` module for email address etc. matching. - Added ``matchers`` module for email address etc. matching.
- Added ``strutils.unindent``, ``strutils.countLines``. - Added ``strutils.unindent``, ``strutils.countLines``.