Add a toy program to set up a minimal environment

import types, objects, querying, verbs, builtins, rdstdin, strutils

var world = createWorld()
var root = blankObject()
root.level = 0
world.add(root)
root.owner = root
root.setPropR("name", "root")
root.setPropR("aliases", @[])
root.setPropR("rootprop", "yes")

var genericContainer = root.createChild()
world.add(genericContainer)
genericContainer.setPropR("name", "generic container")
genericContainer.setPropR("contents", @[])

var nowhere = genericContainer.createChild()
world.add(nowhere)

var genericThing = root.createChild()

world.add(genericThing)
genericThing.setPropR("name", "generic thing")

genericContainer.changeParent(genericThing)

var genericRoom = genericContainer.createChild()
world.add(genericRoom)
genericRoom.setPropR("name", "generic room")
genericRoom.setPropR("nexit", genericRoom)
genericRoom.setPropR("eexit", genericRoom)
genericRoom.setPropR("sexit", genericRoom)
genericRoom.setPropR("wexit", genericRoom)
genericRoom.setPropR("uexit", genericRoom)
genericRoom.setPropR("dexit", genericRoom)

var room = genericRoom.createChild()
world.add(room)
room.setPropR("name", "a room")

var genericPlayer = genericThing.createChild()
world.add(genericPlayer)
genericPlayer.setPropR("name", "generic player")

genericPlayer.isPlayer = true

var player = genericPlayer.createChild()
world.add(player)
player.setPropR("name", "the player")

discard player.moveTo(room)

var eval = newVerb(
  names =  "eval",
  owner = root,

  pubRead = true,
  pubWrite = true,
  pubExec = true,

  doSpec = oStr,
  prepSpec = pNone,
  ioSpec = oNone
)
eval.setCode("(try (echo \"=> \" (eval dobjstr)) (echo error))")
world.verbObj.verbs.add(eval)
player.level = 0

while true:
  let command = readLineFromStdin("> ").strip()

  if command.len == 0: continue
  discard player.handleCommand(command).isType(dNil)


import unittest, nre, optional_t.nonstrict

suite "Misc tests":
  test "unicode":
    check("".find(re("", "8")).match == "")
    check("перевірка".replace(re(r"\w", "uW"), "") == "")

Add tests for empty or non-empty match

import unittest, nre, strutils, optional_t.nonstrict

suite "Misc tests":
  test "unicode":
    check("".find(re("", "8")).match == "")
    check("перевірка".replace(re(r"\w", "uW"), "") == "")

  test "empty or non-empty match":
    check("abc".findall(re"|.").join(":") == ":a::b::c:")
    check("abc".findall(re".|").join(":") == "a:b:c:")

    check("abc".replace(re"|.", "x") == "xxxxxxx")
    check("abc".replace(re".|", "x") == "xxxx")

    check("abc".split(re"|.").join(":") == ":::::")
    check("abc".split(re".|").join(":") == ":::")


import parseopt2, strutils

import common

type
  CliParams = ref object
    version*: string

let doc = """
choosenim: The Nim toolchain installer.

Choose a job. Choose a mortgage. Choose life. Choose Nim.

Usage:
  choosenim <version>

Options:
  -h --help     Show this screen.
  --version     Show version.
"""

proc writeHelp() =
  echo(doc)
  quit(QuitFailure)

proc writeVersion() =
  echo("choosenim v$1 ($2 $3)" % [chooseNimVersion, CompileDate, CompileTime])
  quit(QuitSuccess)

proc newCliParams(): CliParams =
  new result
  result.version = ""

proc getCliParams*(): CliParams =
  result = newCliParams()
  for kind, key, val in getopt():
    case kind
    of cmdArgument:
      result.version = key
    of cmdLongOption, cmdShortOption:
      case key
      of "help", "h": writeHelp()
      of "version", "v": writeVersion()
      else: discard
    of cmdEnd: assert(false)

  if result.version == "":
    writeHelp()

Add host OS/CPU to version output.

import parseopt2, strutils

import common

type
  CliParams = ref object
    version*: string

let doc = """
choosenim: The Nim toolchain installer.

Choose a job. Choose a mortgage. Choose life. Choose Nim.

Usage:
  choosenim <version>

Options:
  -h --help     Show this screen.
  --version     Show version.
"""

proc writeHelp() =
  echo(doc)
  quit(QuitFailure)

proc writeVersion() =
  echo("choosenim v$1 ($2 $3) [$4/$5]" %
       [chooseNimVersion, CompileDate, CompileTime, hostOS, hostCPU])
  quit(QuitSuccess)

proc newCliParams(): CliParams =
  new result
  result.version = ""

proc getCliParams*(): CliParams =
  result = newCliParams()
  for kind, key, val in getopt():
    case kind
    of cmdArgument:
      result.version = key
    of cmdLongOption, cmdShortOption:
      case key
      of "help", "h": writeHelp()
      of "version", "v": writeVersion()
      else: discard
    of cmdEnd: assert(false)

  if result.version == "":
    writeHelp()


proc `:=`*[T](x: var T, y: T): T =
  ## A assignment expression like convenience operator
  x = y
  x

iterator maybePar*(parallel: bool, a, b: int): int =
  ## if flag is true yield `` `||`(a,b) `` else ``countup(a,b)``.
  if parallel:
    for i in `||`(a, b): yield i
  else:
    for i in a .. b: yield i

Add `enumerate` for Python refugees/porting other CLI utility code.

proc `:=`*[T](x: var T, y: T): T =
  ## A assignment expression like convenience operator
  x = y
  x

iterator maybePar*(parallel: bool, a, b: int): int =
  ## if flag is true yield `` `||`(a,b) `` else ``countup(a,b)``.
  if parallel:
    for i in `||`(a, b): yield i
  else:
    for i in a .. b: yield i

import macros

macro enumerate*(x: ForLoopStmt): untyped =
  ## Generic enumerate macro
  expectKind x, nnkForStmt
  result = newStmtList()
  result.add newVarStmt(x[0], newLit(0))
  var body = x[^1]
  if body.kind != nnkStmtList:
    body = newTree(nnkStmtList, body)
  body.add newCall(bindSym"inc", x[0])
  var newFor = newTree(nnkForStmt)
  for i in 1..x.len-3:
    newFor.add x[i]
  newFor.add x[^2][1]
  newFor.add body
  result.add newFor


import os, parsecfg, streams

proc cfToCL*(path: string, subCmdName="", quiet=false): seq[string] =
  ## Drive Nim stdlib parsecfg to get either specific subcommand parameters if
  ## ``subCmdName`` is non-empty or else global command parameters.
  var activeSection = subCmdName.len == 0
  var f = newFileStream(path, fmRead)
  if f == nil:
    if not quiet:
      stderr.write "cannot open: ", path, "\n"
      return
    else: raise newException(IOError, "")
  var p: CfgParser
  open(p, f, path)
  while true:
    var e = p.next
    case e.kind
    of cfgEof:
      break
    of cfgSectionStart:
      activeSection = e.section == subCmdName
    of cfgKeyValuePair, cfgOption:
      when defined(debugCfToCL):
        echo "key: ", e.key.repr, " val: ", e.value.repr
      if activeSection:
        result.add("--" & e.key & "=" & e.value)
    of cfgError: echo e.msg
  close(p)

proc envToCL*(evarName: string): seq[string] =
  var e = os.getEnv(evarName)
  if e.len == 0:
    return
  let sp = e.parseCmdLine               #See os.parseCmdLine for details
  result = result & sp
  when defined(debugEnvToCL):
    echo "parsed $", varNm, " into: ", sp

Add a way to both be quiet and not raise an exception.

import os, parsecfg, streams

proc cfToCL*(path: string, subCmdName="", quiet=false,
             noRaise=false): seq[string] =
  ## Drive Nim stdlib parsecfg to get either specific subcommand parameters if
  ## ``subCmdName`` is non-empty or else global command parameters.
  var activeSection = subCmdName.len == 0
  var f = newFileStream(path, fmRead)
  if f == nil:
    if not quiet:
      stderr.write "cannot open: ", path, "\n"
      return
    elif not noRaise: raise newException(IOError, "")
    else: return
  var p: CfgParser
  open(p, f, path)
  while true:
    var e = p.next
    case e.kind
    of cfgEof:
      break
    of cfgSectionStart:
      activeSection = e.section == subCmdName
    of cfgKeyValuePair, cfgOption:
      when defined(debugCfToCL):
        echo "key: ", e.key.repr, " val: ", e.value.repr
      if activeSection:
        result.add("--" & e.key & "=" & e.value)
    of cfgError: echo e.msg
  close(p)

proc envToCL*(evarName: string): seq[string] =
  var e = os.getEnv(evarName)
  if e.len == 0:
    return
  let sp = e.parseCmdLine               #See os.parseCmdLine for details
  result = result & sp
  when defined(debugEnvToCL):
    echo "parsed $", varNm, " into: ", sp


import os, parsecfg, streams

proc cfToCL*(path: string, subCmdName=""): seq[string] =
  ## Drive Nim stdlib parsecfg to get either specific subcommand parameters if
  ## ``subCmdName`` is non-empty or else global command parameters.
  var activeSection = subCmdName.len == 0
  var f = newFileStream(path, fmRead)
  if f == nil:
    stderr.write "cannot open: ", path, "\n"
    return
  var p: CfgParser
  open(p, f, path)
  while true:
    var e = p.next
    case e.kind
    of cfgEof:
      break
    of cfgSectionStart:
      activeSection = e.section == subCmdName
    of cfgKeyValuePair, cfgOption:
      when defined(debugCfToCL):
        echo "key: ", e.key.repr, " val: ", e.value.repr
      if activeSection:
        result.add("--" & e.key & "=" & e.value)
    of cfgError: echo e.msg
  close(p)

proc envToCL*(evarName: string): seq[string] =
  var e = os.getEnv(evarName)
  if e.len == 0:
    return
  let sp = e.parseCmdLine               #See os.parseCmdLine for details
  result = result & sp
  when defined(debugEnvToCL):
    echo "parsed $", varNm, " into: ", sp

Add an optional quiet mode for various best-effort/search path situations.

import os, parsecfg, streams

proc cfToCL*(path: string, subCmdName="", quiet=false): seq[string] =
  ## Drive Nim stdlib parsecfg to get either specific subcommand parameters if
  ## ``subCmdName`` is non-empty or else global command parameters.
  var activeSection = subCmdName.len == 0
  var f = newFileStream(path, fmRead)
  if f == nil:
    if not quiet:
      stderr.write "cannot open: ", path, "\n"
    return
  var p: CfgParser
  open(p, f, path)
  while true:
    var e = p.next
    case e.kind
    of cfgEof:
      break
    of cfgSectionStart:
      activeSection = e.section == subCmdName
    of cfgKeyValuePair, cfgOption:
      when defined(debugCfToCL):
        echo "key: ", e.key.repr, " val: ", e.value.repr
      if activeSection:
        result.add("--" & e.key & "=" & e.value)
    of cfgError: echo e.msg
  close(p)

proc envToCL*(evarName: string): seq[string] =
  var e = os.getEnv(evarName)
  if e.len == 0:
    return
  let sp = e.parseCmdLine               #See os.parseCmdLine for details
  result = result & sp
  when defined(debugEnvToCL):
    echo "parsed $", varNm, " into: ", sp


discard """
  output: '''foo
js 3.14'''
"""

# This file tests the JavaScript generator

#  #335
proc foo() =
  var bar = "foo"
  proc baz() =
    echo bar
  baz()
foo()

# #376
when not defined(JS):
  proc foo(val: float): string = "no js " & $val
else:
  proc foo(val: float): string = "js " & $val

echo foo(3.14)

Test JS proc header codegen

discard """
  output: '''foo
js 3.14
7'''
"""

# This file tests the JavaScript generator

#  #335
proc foo() =
  var bar = "foo"
  proc baz() =
    echo bar
  baz()
foo()

# #376
when not defined(JS):
  proc foo(val: float): string = "no js " & $val
else:
  proc foo(val: float): string = "js " & $val

echo foo(3.14)

# #2495
type C = concept x

proc test(x: C, T: typedesc): T =
  cast[T](x)

echo 7.test(int8)


import times
import os
import re
import strformat

if paramCount() == 0:
  echo "Usage: ./benchmark <filename>"
  quit(QuitFailure)

proc measure(data:string, pattern:string) =
  let time = cpuTime()
  let r_pattern = re(pattern)
  let matches: seq[string] = data.findAll(r_pattern)
  let elapsed_time = cpuTime() - time
  echo &"{elapsed_time * 1e3} - {len(matches)}"

let data = readFile(paramStr(1))

measure(data, r"[\w\.+-]+@[\w\.-]+\.[\w\.-]+")

measure(data, r"[\w]+://[^/\s?#]+[^\s?#]+(?:\?[^\s#]*)?(?:#[^\s]*)?")

measure(data, r"(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9])")

Add count to the measurement

import times
import os
import re
import strformat

if paramCount() == 0:
  echo "Usage: ./benchmark <filename>"
  quit(QuitFailure)

proc measure(data:string, pattern:string) =
  let time = cpuTime()
  let r_pattern = re(pattern)
  let matches: seq[string] = data.findAll(r_pattern)
  let count = len(matches)
  let elapsed_time = cpuTime() - time
  echo &"{elapsed_time * 1e3} - {count}"

let data = readFile(paramStr(1))

measure(data, r"[\w\.+-]+@[\w\.-]+\.[\w\.-]+")

measure(data, r"[\w]+://[^/\s?#]+[^\s?#]+(?:\?[^\s#]*)?(?:#[^\s]*)?")

measure(data, r"(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9])")


discard """
  output: '''9'''
"""

type
  n32 = range[0..high(int)]
  n8* = range[0'i8..high(int8)]

proc `+`*(a: n32, b: n32{nkIntLit}): n32 = discard

proc `-`*(a: n8, b: n8): n8 = n8(system.`-`(a, b))

var x, y: n8
var z: int16

# ensure this doesn't call our '-' but system.`-` for int16:
echo z - n8(9)

Fix typo in new test

discard """
  output: '''-9'''
"""

type
  n32 = range[0..high(int)]
  n8* = range[0'i8..high(int8)]

proc `+`*(a: n32, b: n32{nkIntLit}): n32 = discard

proc `-`*(a: n8, b: n8): n8 = n8(system.`-`(a, b))

var x, y: n8
var z: int16

# ensure this doesn't call our '-' but system.`-` for int16:
echo z - n8(9)


proc demo(alpha: int, version=false, item: string, args: seq[string]): int =
  ## demo entry point with varied, meaningless parameters.  A Nim invocation
  ## might be: demo(alpha=2, @[ "hi", "ho" ]) corresponding to the command
  ## invocation "demo --alpha=2 hi ho" (assuming executable gets named demo).
  if version:
    echo "0.0.0"
    return 0
  echo "alpha:", alpha, " version:", version, " item:", repr(item)
  for i, arg in args: echo "positional[", i, "]: ", repr(arg)
  return 42

when isMainModule:
  import cligen
  dispatch(demo,
           implicitDefault = @[ "item" ], mandatoryOverride = @[ "version" ])

Rename ``version`` to ``bypass`` so that people don't get the wrong idea how to proceed with --version-type activity.

proc demo(alpha: int, bypass=false, item: string, args: seq[string]): int =
  ## demo entry point with varied, meaningless parameters.  A Nim invocation
  ## might be: demo(alpha=2, @[ "hi", "ho" ]) corresponding to the command
  ## invocation "demo --alpha=2 hi ho" (assuming executable gets named demo).
  if bypass:
    echo "0.0.0"
    return 0
  echo "alpha:", alpha, " bypass:", bypass, " item:", repr(item)
  for i, arg in args: echo "positional[", i, "]: ", repr(arg)
  return 42

when isMainModule:
  import cligen
  dispatch(demo,
           implicitDefault = @[ "item" ], mandatoryOverride = @[ "bypass" ])


proc demo(alpha: int=1, item: string="hi", args: seq[string]): int =
  ## demo entry point with varied, meaningless parameters.  A Nim invocation
  ## might be: demo(alpha=2, @[ "hi", "ho" ]) corresponding to the command
  ## invocation "demo --alpha=2 hi ho" (assuming executable gets named demo).
  echo "alpha:", alpha, " item:", repr(item)
  for i, arg in args: echo "positional[", i, "]: ", repr(arg)
  return 42

when isMainModule:
  import cligen; include cligen/mergeCfgEnv

  when defined(versionGit):
    const vsn = staticExec "git log -1 | head -n1"
    clCfg.version = vsn
    dispatch(demo)
  elif defined(versionNimble):
    const nimbleFile = staticRead "../cligen.nimble"  #Use YOURPKG not cligen
    clCfg.version = versionFromNimble(nimbleFile)
    dispatch(demo)
  else:
    clCfg.version = "1.5"
    when defined(versionShort):
      dispatch(demo, short = { "version": 'V' })
    else:
      dispatch(demo, cmdName="Version")

Use git describe in example for a better version string.

proc demo(alpha: int=1, item: string="hi", args: seq[string]): int =
  ## demo entry point with varied, meaningless parameters.  A Nim invocation
  ## might be: demo(alpha=2, @[ "hi", "ho" ]) corresponding to the command
  ## invocation "demo --alpha=2 hi ho" (assuming executable gets named demo).
  echo "alpha:", alpha, " item:", repr(item)
  for i, arg in args: echo "positional[", i, "]: ", repr(arg)
  return 42

when isMainModule:
  import cligen; include cligen/mergeCfgEnv

  when defined(versionGit):
    const vsn = staticExec "git describe --tags HEAD"
    clCfg.version = vsn
    dispatch(demo)
  elif defined(versionNimble):
    const nimbleFile = staticRead "../cligen.nimble"  #Use YOURPKG not cligen
    clCfg.version = versionFromNimble(nimbleFile)
    dispatch(demo)
  else:
    clCfg.version = "1.5"
    when defined(versionShort):
      dispatch(demo, short = { "version": 'V' })
    else:
      dispatch(demo, cmdName="Version")


import narmos
import stdio
import usart
import shell
import cstrmatch
import assertions

var  tickCount: int

#timerHandler(tickCallback):
#  inc(tickCount)

shellHandler(printTicks):
  printf("Tick Count: %d", tickCount)

shellHandler(argExample):
  for x in 1..argc-1:
    if argv[x] ~= "foo":
      printf("handler for 'foo'\n")
    elif argv[x] ~= "bar":
      printf("handler for 'bar'\n")
    elif argv[x] ~= "baz":
      printf("handler for 'baz'\n")
    else:
      printf("Unhandled arg: %d - %s", x, argv[x])

declareTask(setupTask):
  # Init the debug usart
  usart2.init(115200)
  printf("\nHello world\n")

  shell.init()
  shell.registerCommand("ticks", "print number of elapsed ticks", printTicks)
  shell.registerCommand("arg", "arg example [foo, bar, baz]", argExample)

  #var tickTimer = rtos.createSoftTimer("Tick", 1000, true, nil, tickCallback)
  #assertFatal(tickTimer == nil)

  #discard rtos.startSoftTimer(tick_timer, 0)

when isMainModule:
  stdio.enableUnbufferedIO()
  discard createTask(setupTask, 1024)

  startScheduler()

Add single shot and periodic timer examples

import narmos
import stdio
import usart
import shell
import cstrmatch
import assertions

var  tickCount: int

declareTimer(tickCallback):
  inc(tickCount)

declareTimer(TenSecondNotification):
  printf("It's been 10 seconds: (%dms)\n", systemTime().uint32)

shellHandler(printTicks):
  printf("Tick Count: %d\n", tickCount)

shellHandler(printTime):
  printf("System Time (u32 scaled): %ld\n", systemTime().uint32)

shellHandler(argExample):
  for x in 1..argc-1:
    if argv[x] ~= "foo":
      printf("handler for 'foo'\n")
    elif argv[x] ~= "bar":
      printf("handler for 'bar'\n")
    elif argv[x] ~= "baz":
      printf("handler for 'baz'\n")
    else:
      printf("Unhandled arg: %d - %s", x, argv[x])

declareTask(setupTask):
  # Init the debug usart
  usart2.init(115200)
  printf("\nHello world\n")

  shell.init()
  shell.registerCommand("ticks", "print number of elapsed ticks", printTicks)
  shell.registerCommand("time", "print the system time", printTime)
  shell.registerCommand("arg", "arg example [foo, bar, baz]", argExample)

  discard startPeriodicTimer(tickCallback, 1000)
  discard startOneShotTimer(TenSecondNotification, 10 * 1000)

when isMainModule:
  stdio.enableUnbufferedIO()
  discard createTask(setupTask, 1024)

  startScheduler()


import unicode

when not defined(js):
  import httpclient, logging, asyncdispatch, json

  proc getCountryForIP*(ip: string): Future[string] {.async.} =
    ## Returns a two-letter ISO code specifying the country that the
    ## IP address belongs to, if the country cannot be determined "" is returned.
    var client = newAsyncHttpClient()

    let responseFut = client.getContent("http://freegeoip.net/json/" & ip)
    yield responseFut
    if responseFut.failed:
      warn("Error retrieving country by IP: " & responseFut.error.msg)
      return ""

    let obj = parseJson(responseFut.read())
    return obj["country_code"].getStr()

proc getUnicodeForCountry*(iso: string): string =
  ## Retrieves a country flag unicode character for the specified ISO two-letter
  ## country code.
  let base = 127397
  result = "  "
  for c in iso:
    result.add($Rune(base + c.ord))

when isMainModule:
  doAssert getUnicodeForCountry("DE") == "🇩🇪"

Return " " when country code is invalid.

import unicode

when not defined(js):
  import httpclient, logging, asyncdispatch, json

  proc getCountryForIP*(ip: string): Future[string] {.async.} =
    ## Returns a two-letter ISO code specifying the country that the
    ## IP address belongs to, if the country cannot be determined "" is returned.
    var client = newAsyncHttpClient()

    let responseFut = client.getContent("http://freegeoip.net/json/" & ip)
    yield responseFut
    if responseFut.failed:
      warn("Error retrieving country by IP: " & responseFut.error.msg)
      return ""

    let obj = parseJson(responseFut.read())
    return obj["country_code"].getStr()

proc getUnicodeForCountry*(iso: string): string =
  ## Retrieves a country flag unicode character for the specified ISO two-letter
  ## country code.
  let base = 127397
  result = ""
  for c in iso:
    result.add($Rune(base + c.ord))

  if result.len == 0:
    return "  "

when isMainModule:
  doAssert getUnicodeForCountry("DE") == "🇩🇪"


import rtos
import stdio
import usart

var tick_count: int

proc blink_callback(exp_timer: timer_handle): void =
  printf("tick_count: %d\n", tick_count)
  tick_count += 1

proc setup_task(params: pointer): void =

  # Init the debug usart
  usart2.init(115200)
  printf("Hello world\n")
  var blink_timer = rtos.create_soft_timer("Blink", 1000, true, blink_callback)

  discard rtos.start_soft_timer(blink_timer, 0)

  rtos.delete_task(nil)

when isMainModule:
  stdio.enable_unbuffered_io()
  discard rtos.create_task(setup_task, "Setup Task", 100, 8)
  rtos.start_scheduler()

Enable debug shell in hello world app

import rtos
import stdio
import usart
import shell

var tick_count: int

proc tick_callback(exp_timer: timer_handle): void =
  tick_count += 1

shell_handler(print_ticks):
  printf("Tick Count: %d", tick_count)

proc setup_task(params: pointer): void =

  # Init the debug usart
  usart2.init(115200)
  printf("Hello world\n")

  shell.init()
  discard shell.register_command("ticks", "print number of elapsed ticks", print_ticks)

  var tick_timer = rtos.create_soft_timer("Tick", 1000, true, tick_callback)

  discard rtos.start_soft_timer(tick_timer, 0)

  rtos.delete_task(nil)

when isMainModule:
  stdio.enable_unbuffered_io()
  discard rtos.create_task(setup_task, "Setup Task", 100, 8)
  rtos.start_scheduler()


proc demo(alpha=1, verb=false, args: seq[string], stuff: seq[string]): int=
  ## demo entry point with varied, meaningless parameters.
  echo "alpha:", alpha, " verb:", verb, " stuff:", repr(stuff)
  for i, arg in args: echo "args[", i, "]: ", repr(arg)
  return 42

when isMainModule:
  import cligen
  dispatch(demo, positional="stuff",
           help={ "stuff" : "stuffies (1 or more strings)" })

Make help for positionals look a little more like auto-generated (but diff to be a good demo!).

proc demo(alpha=1, verb=false, args: seq[string], stuff: seq[string]): int=
  ## demo entry point with varied, meaningless parameters.
  echo "alpha:", alpha, " verb:", verb, " stuff:", repr(stuff)
  for i, arg in args: echo "args[", i, "]: ", repr(arg)
  return 42

when isMainModule:
  import cligen
  dispatch(demo, positional="stuff",
           help={ "stuff" : "[ stuffies (1 or more strings) ]" })


discard """
 matrix: "--gc:boehm"
"""

import "../../src/schema_order.nim"

# Objective: Create, sort, and validate a simple Option schema order.
block:
  let graph = new_schema_dependency_graph()
  graph.add_dependency("Game", "Option")
  graph.add_dependency("Some", "Option")
  graph.add_dependency("Player", "Some")
  graph.add_dependency("Game", "Player")
  graph.add_dependency("None", "Option")

  let order = graph.sort_topological()
  assert order == @["Option", "Some", "Player", "Game", "None"]

Fix test: `graph` needs to be a var.

discard """
 matrix: "--gc:boehm"
"""

import "../../src/schema_order.nim"

# Objective: Create, sort, and validate a simple Option schema order.
block:
  var graph = new_schema_dependency_graph()
  graph.add_dependency("Game", "Option")
  graph.add_dependency("Some", "Option")
  graph.add_dependency("Player", "Some")
  graph.add_dependency("Game", "Player")
  graph.add_dependency("None", "Option")

  let order = graph.sort_topological()
  assert order == @["Option", "Some", "Player", "Game", "None"]


# Set cc = clang in compiler's config/nim.cfg for better performance
import strutils, sequtils, times

type
    Route = object
        dest, cost: int
    Node = object
        neighbours: seq[Route]

proc readPlaces: tuple[nodes: seq[Node], num: int] =
    let lines    = toSeq("agraph".lines)
    let numNodes = lines[0].parseInt
    var nodes    = newSeqWith(numNodes, Node(neighbours: newSeq[Route]()))

    for i in 1.. < lines.len:
        let nums = lines[i].split(' ')
        if nums.len < 3:
            break

        let node      = nums[0].parseInt
        let neighbour = nums[1].parseInt
        let cost      = nums[2].parseInt

        nodes[node].neighbours.add(
            Route(dest: neighbour, cost: cost))

    return (nodes, numNodes)

proc getLongestPath(nodes: seq[Node], nodeId: int, visited: var seq[bool]): int =
    visited[nodeId] = true
    for neighbour in nodes[nodeId].neighbours:
        if not visited[neighbour.dest]:
            let dist = neighbour.cost + getLongestPath(nodes, neighbour.dest, visited)
            if dist > result:
                result = dist

    visited[nodeId] = false

proc main =
    let (nodes, numNodes) = readPlaces()
    var visited  = newSeqWith(numNodes, false)
    let start    = cpuTime()
    let result   = getLongestPath(nodes, 0, visited)
    let duration = cpuTime() - start

    echo result, " LANGUAGE NIM ", int(duration * 1000)

main()

Speed up Nim again by making it simpler

import strutils, sequtils, times

type
    Route = object
        dest, cost: int
    Node = object
        neighbours: seq[Route]

let lines    = toSeq("agraph".lines)
let numNodes = lines[0].parseInt
var nodes    = newSeqWith(numNodes, Node(neighbours: newSeq[Route]()))

for i in 1.. < lines.len:
    let nums = lines[i].split(' ')
    if nums.len < 3:
        break

    let node      = nums[0].parseInt
    let neighbour = nums[1].parseInt
    let cost      = nums[2].parseInt

    nodes[node].neighbours.add(Route(dest: neighbour, cost: cost))

var visited  = newSeq[bool](numNodes)
let start    = cpuTime()

proc getLongestPath(nodeId: int): int =
    visited[nodeId] = true
    for neighbour in nodes[nodeId].neighbours:
        if not visited[neighbour.dest]:
            let dist = neighbour.cost + getLongestPath(neighbour.dest)
            if dist > result:
                result = dist

    visited[nodeId] = false

let result   = getLongestPath(0)
let duration = cpuTime() - start

echo result, " LANGUAGE NIM ", int(duration * 1000)


discard """
  output: '''140
5-120-120
359'''
"""
import math

proc optarg(x:int, y:int = 0):int = x + 3 * y
proc singlearg(x:int):int = 20*x
echo optarg 1, singlearg 2

proc foo(x: int): int = x-1
proc foo(x, y: int): int = x-y

let x = optarg foo 7.foo
let y = singlearg foo(1, foo 8)
let z = singlearg 1.foo foo 8

echo x, y, z

let a = [2,4,8].map do (d:int) -> int: d + 1
echo a[0], a[1], a[2]

Remove spurious import added in the last commit.

discard """
  output: '''140
5-120-120
359'''
"""
#import math

proc optarg(x:int, y:int = 0):int = x + 3 * y
proc singlearg(x:int):int = 20*x
echo optarg 1, singlearg 2

proc foo(x: int): int = x-1
proc foo(x, y: int): int = x-y

let x = optarg foo 7.foo
let y = singlearg foo(1, foo 8)
let z = singlearg 1.foo foo 8

echo x, y, z

let a = [2,4,8].map do (d:int) -> int: d + 1
echo a[0], a[1], a[2]


import nake

const
  DefaultOptions = "--verbosity:0 --hint[XDeclaredButNotUsed]:off"
  MainDeps =
    @["types", "objects", "scripting", "querying", "verbs", "builtins", "persist"]
  Exes = {
    "main": MainDeps,
    "test": MainDeps
  }

task defaultTask, "builds everything":
  for info in Exes:
    let (exe, deps) = info
    runTask(exe)

proc simpleBuild(name: string, deps: seq[string]) =
  task name, "builds " & name:
    let sourceFile = name & ".nim"
    var refresh = false
    for dep in deps:
      let depName = dep & ".nim"
      refresh = refresh or name.needsRefresh(depName)

    refresh = refresh or name.needsRefresh(sourceFile)

    if refresh:
      if direShell(nimExe, DefaultOptions, "c", name):
        echo "success building " & name
    else:
      echo name & " is up to date"

task "clean", "removes executables":
  for info in Exes:
    let (exe, deps) = info
    echo "removing " & exe
    removeFile(exe)

  echo "removing nimcache"
  removeDir("nimcache")

task "tests", "run tests":
  runTask("test")
  direShell("./test")

for info in Exes:
  let (exe, deps) = info
  simpleBuild(exe, deps)

Add setup and setupmin tasks

import nake

const
  DefaultOptions = "--verbosity:0 --hint[XDeclaredButNotUsed]:off"
  MainDeps =
    @["types", "objects", "scripting", "querying", "verbs", "builtins", "persist"]
  Exes = {
    "main": MainDeps,
    "test": MainDeps,
    "setupmin": MainDeps
  }

task defaultTask, "builds everything":
  for info in Exes:
    let (exe, deps) = info
    runTask(exe)

proc simpleBuild(name: string, deps: seq[string]) =
  task name, "builds " & name:
    let sourceFile = name & ".nim"
    var refresh = false
    for dep in deps:
      let depName = dep & ".nim"
      refresh = refresh or name.needsRefresh(depName)

    refresh = refresh or name.needsRefresh(sourceFile)

    if refresh:
      if direShell(nimExe, DefaultOptions, "c", name):
        echo "success building " & name
    else:
      echo name & " is up to date"

task "clean", "removes executables":
  for info in Exes:
    let (exe, deps) = info
    echo "removing " & exe
    removeFile(exe)

  echo "removing nimcache"
  removeDir("nimcache")

task "tests", "run tests":
  runTask("test")
  direShell("./test")

task "setup", "sets up a minimal world":
  runTask("setupmin")
  stdout.write "setting up a minimal world to use (worlds/min)... "
  direShell("./setupmin")
  echo "done!"
  echo "use this world by running \"main\" (nake main && ./main)"

for info in Exes:
  let (exe, deps) = info
  simpleBuild(exe, deps)


import httpclient
import json

type
  Episode* = object of RootObj
    name: string
    air_date: int
    season: int
    episode: int
    is_movie: bool

const
  API_ENDPOINT: string = "http://ponyapi.apps.xeserv.us"

proc getJson(endpoint: string): json.JsonNode =
  var
    data = httpclient.getContent(API_ENDPOINT & "/" & endpoint)
    jsonTable = json.parseJson data

  return jsonTable

proc newest*(): Episode =
  var
    data = getJson("/newest")["episode"]
    ep = Episode(name:     data["name"].getStr,
                 air_date: data["air_date"].getNum.int,
                 season:   data["season"].getNum.int,
                 episode:  data["episode"].getNum.int,
                 is_movie: data["is_movie"].getBVal)

  return ep

proc `$`*(ep: Episode): string =
  return "Episode:: name:" & ep.name & " season:" & $ep.season & " episode:" & $ep.episode & " air_date:" & $ep.air_date & " is_movie:" & $ep.is_movie

when isMainModule:
  import unittest

  suite "ponyapi tests":
    var ep: Episode

    test "Newest episode lookup":
      try:
        ep = newest()

      except:
        echo getCurrentExceptionMsg()
        fail

    test "stringify episode":
      echo ep

Add more features to the nim client

import httpclient
import json

type
  Episode* = object of RootObj
    name: string
    air_date: int
    season: int
    episode: int
    is_movie: bool

const
  API_ENDPOINT: string = "http://ponyapi.apps.xeserv.us"

proc getJson(endpoint: string): json.JsonNode =
  var
    data = httpclient.getContent(API_ENDPOINT & "/" & endpoint)
    jsonTable = json.parseJson data

  return jsonTable

proc newEpisodeFromNode(data: json.JsonNode): Episode =
  Episode(name:     data["name"].getStr,
          air_date: data["air_date"].getNum.int,
          season:   data["season"].getNum.int,
          episode:  data["episode"].getNum.int,
          is_movie: data["is_movie"].getBVal)

proc newest*(): Episode =
  getJson("/newest")["episode"].newEpisodeFromNode

proc random*(): Episode =
  getJson("/random")["episode"].newEpisodeFromNode

proc get_episode*(season, episode: int): Episode =
  getJson("/season/" & $season & "/episode/" & $episode)["episode"].newEpisodeFromNode

when isMainModule:
  import unittest

  suite "ponyapi tests":
    var ep: Episode

    test "Newest episode lookup":
      try:
        ep = newest()

      except:
        echo getCurrentExceptionMsg()
        fail

    test "stringify episode":
      echo ep

    test "random episode":
      echo random()

    test "get episode":
      var myEp = get_episode(2, 14) # best episode
      assert myEp.name == "The Last Roundup"


import rtos
import stdio
import usart
import shell

var tick_count: int

proc tick_callback(exp_timer: timer_handle): void =
  tick_count += 1

shell_handler(print_ticks):
  printf("Tick Count: %d", tick_count)

proc setup_task(params: pointer): void =

  # Init the debug usart
  usart2.init(115200)
  printf("Hello world\n")

  shell.init()
  discard shell.register_command("ticks", "print number of elapsed ticks", print_ticks)

  var tick_timer = rtos.create_soft_timer("Tick", 1000, true, tick_callback)

  discard rtos.start_soft_timer(tick_timer, 0)

  rtos.delete_task(nil)

when isMainModule:
  stdio.enable_unbuffered_io()
  discard rtos.create_task(setup_task, "Setup Task", 100, 8)
  rtos.start_scheduler()

Add multiarg shell handler to hello_world example

import rtos
import stdio
import usart
import shell
import cstrmatch

var tick_count: int

proc tick_callback(exp_timer: timer_handle): void =
  tick_count += 1

shell_handler(print_ticks):
  printf("Tick Count: %d", tick_count)

shell_handler(arg_example):
  for x in 1..argc-1:
    if argv[x] ~= "foo":
      printf("handler for 'foo'\n")
    elif argv[x] ~= "bar":
      printf("handler for 'bar'\n")
    elif argv[x] ~= "baz":
      printf("handler for 'baz'\n")
    else:
      printf("Unhandled arg: %d - %s", x, argv[x])

proc setup_task(params: pointer): void =

  # Init the debug usart
  usart2.init(115200)
  printf("Hello world\n")

  shell.init()
  discard shell.register_command("ticks", "print number of elapsed ticks", print_ticks)
  discard shell.register_command("arg", "arg example [foo, bar, baz]", arg_example)

  var tick_timer = rtos.create_soft_timer("Tick", 1000, true, tick_callback)

  discard rtos.start_soft_timer(tick_timer, 0)

  rtos.delete_task(nil)

when isMainModule:
  stdio.enable_unbuffered_io()
  discard rtos.create_task(setup_task, "Setup Task", 100, 8)
  rtos.start_scheduler()


discard """
  output: '''140
5-120'''
"""

proc optarg(x:int):int = x
proc singlearg(x:int):int = 20*x
echo optarg 1, singlearg 2

proc foo(x: int): int = x-1
proc foo(x, y: int): int = x-y

let x = optarg foo 7.foo
let y = singlearg foo(1, foo 8)

echo x, y

Fix optarg() and added two more tests.

discard """
  output: '''140
5-120-120
359'''
"""
import math

proc optarg(x:int, y:int = 0):int = x + 3 * y
proc singlearg(x:int):int = 20*x
echo optarg 1, singlearg 2

proc foo(x: int): int = x-1
proc foo(x, y: int): int = x-y

let x = optarg foo 7.foo
let y = singlearg foo(1, foo 8)
let z = singlearg 1.foo foo 8

echo x, y, z

let a = [2,4,8].map do (d:int) -> int: d + 1
echo a[0], a[1], a[2]


# This tests if things work if the wrapped user-proc uses identifiers also in
# our generated dispatch proc.  Should be fine as long as no imports pull in a
# name like "disapatcherFoo".

proc demo(usage=1, cmdline="bad name", getopt="ho", args: seq[string]): int =
  echo "usage:", usage, " cmdline:", repr(cmdline), " getopt:", getopt
  for i, arg in args: echo "positional[", i, "]: ", repr(arg)
  return 42

when isMainModule:
  import cligen
  dispatch(demo)

Use purpose of program for test command doc.

proc demo(usage=1, cmdline="bad name", getopt="ho", args: seq[string]): int =
  ## This tests if things work when a wrapped user-proc uses identifiers also
  ## used in our generated dispatch proc.
  echo "usage:", usage, " cmdline:", repr(cmdline), " getopt:", getopt
  for i, arg in args: echo "positional[", i, "]: ", repr(arg)
  return 42

when isMainModule:
  import cligen
  dispatch(demo)


discard """
errormsg: "Error: ordinal type expected"
line: 10
"""

# https://github.com/nim-lang/Nim/issues/9908

type
    X = enum
        a = ("a", "b")

Fix test case expected output

discard """
errormsg: "ordinal type expected"
line: 10
"""

# https://github.com/nim-lang/Nim/issues/9908

type
    X = enum
        a = ("a", "b")


import nake

const
  DefaultOptions = "--verbosity:0"
  MainDeps =
    @["types", "objects", "scripting", "querying", "verbs", "builtins"]
  Exes = {
    "main": MainDeps,
    "test": MainDeps
  }

task defaultTask, "builds everything":
  for info in Exes:
    let (exe, deps) = info
    runTask(exe)

proc simpleBuild(name: string, deps: seq[string]) =
  task name, "builds " & name:
    let sourceFile = name & ".nim"
    var refresh = false
    for dep in deps:
      let depName = dep & ".nim"
      refresh = refresh or name.needsRefresh(depName)

    refresh = refresh or name.needsRefresh(sourceFile)

    if refresh:
      if direShell(nimExe, DefaultOptions, "c", name):
        echo "success building " & name
    else:
      echo name & " is up to date"

task "clean", "removes executables":
  for info in Exes:
    let (exe, deps) = info
    echo "removing " & exe
    removeFile(exe)

  echo "removing nimcache"
  removeDir("nimcache")

task "tests", "run tests":
  runTask("test")
  direShell("./test")

for info in Exes:
  let (exe, deps) = info
  simpleBuild(exe, deps)

Add persist as a dependency

import nake

const
  DefaultOptions = "--verbosity:0"
  MainDeps =
    @["types", "objects", "scripting", "querying", "verbs", "builtins", "persist"]
  Exes = {
    "main": MainDeps,
    "test": MainDeps
  }

task defaultTask, "builds everything":
  for info in Exes:
    let (exe, deps) = info
    runTask(exe)

proc simpleBuild(name: string, deps: seq[string]) =
  task name, "builds " & name:
    let sourceFile = name & ".nim"
    var refresh = false
    for dep in deps:
      let depName = dep & ".nim"
      refresh = refresh or name.needsRefresh(depName)

    refresh = refresh or name.needsRefresh(sourceFile)

    if refresh:
      if direShell(nimExe, DefaultOptions, "c", name):
        echo "success building " & name
    else:
      echo name & " is up to date"

task "clean", "removes executables":
  for info in Exes:
    let (exe, deps) = info
    echo "removing " & exe
    removeFile(exe)

  echo "removing nimcache"
  removeDir("nimcache")

task "tests", "run tests":
  runTask("test")
  direShell("./test")

for info in Exes:
  let (exe, deps) = info
  simpleBuild(exe, deps)


import posix

var lastBadDev = 0.Dev
proc getxattr*(path: string, name: string, dev: Dev=0): int =
  proc getxattr(path:cstring; name:cstring; value:pointer; size:csize): csize {.
      importc: "getxattr", header: "sys/xattr.h".}
  if dev == lastBadDev: errno = EOPNOTSUPP; return -1
  result = getxattr(path.cstring, name.cstring, nil, 0).int
  if result == -1 and errno == EOPNOTSUPP:
    lastBadDev = dev

Make compile on FreeBSD. Not well tested for ACL presence, though.

import posix

var lastBadDev = 0.Dev
when defined(linux):
  proc getxattr*(path: string, name: string, dev: Dev=0): int =
    proc getxattr(path: cstring; name: cstring; value: pointer;
        size: csize): csize {. importc: "getxattr", header: "sys/xattr.h".}
    if dev == lastBadDev: errno = EOPNOTSUPP; return -1
    result = getxattr(path.cstring, name.cstring, nil, 0).int
    if result == -1 and errno == EOPNOTSUPP:
      lastBadDev = dev
elif defined(freebsd):
  import strutils
  proc getxattr*(path: string, name: string, dev: Dev=0): int =
    const EA_NS_SYS = 2.cint
    proc extattr_get_file(path:cstring, attrnamespace: cint, attrnames: cstring,
                          data: cstring, nbytes: csize): csize {.
            importc: "extattr_get_file", header: "sys/extattr.h".}
    if dev == lastBadDev: errno = EOPNOTSUPP; return -1
    let nms = name.split('.')
    result = extattr_get_file(path.cstring, EA_NS_SYS, name.cstring, nil, 0).int
    if result == -1 and errno == EOPNOTSUPP:
      lastBadDev = dev
else:
  proc getxattr*(path: string, name: string, dev: Dev=0): int =
    errno = EOPNOTSUPP
    -1


import types, objects, querying, verbs, builtins, rdstdin, strutils, persist

let
  world = loadWorld("min")
  player = world.getObjects()[8]

while true:
  let command = readLineFromStdin("> ").strip()

  if command.len == 0: continue
  discard player.handleCommand(command).isType(dNil)

Clean up output proc of the player in question

import types, objects, querying, verbs, builtins, rdstdin, strutils, persist

let
  world = loadWorld("min")
  player = world.getObjects()[8]

player.output = proc(obj: MObject, msg: string) =
  echo msg

while true:
  let command = readLineFromStdin("> ").strip()

  if command.len == 0: continue
  discard player.handleCommand(command).isType(dNil)


import types, objects, querying, verbs, builtins, persist, os, strutils, rdstdin

let
  world = loadWorld("min")
  player = world.getObjects()[8]

player.output = proc(obj: MObject, msg: string) =
  echo msg

proc myEscape(s: string): string =
  s.replace("\"", "\\\"")

while true:
  var command = readLineFromStdin("> ").strip()

  if command.contains("<>"):
    discard os.execShellCmd("vim edit.tmp")
    command = command.replace("<>", readFile("edit.tmp").myEscape())

  if command.len == 0: continue

  discard player.handleCommand(command).isType(dNil)
  while world.numTasks() > 0:
    world.tick()

removeFile("edit.tmp")

Add tool for editing verbs

import types, objects, querying, verbs, builtins, persist, os, strutils, rdstdin, re

let
  world = loadWorld("min")
  player = world.getObjects()[8]

player.output = proc(obj: MObject, msg: string) =
  echo msg

proc myEscape(s: string): string =
  s.replace("\"", "\\\"")

while true:
  var command = readLineFromStdin("> ").strip()

  if command.contains("<>"):
    discard os.execShellCmd("vim edit.tmp")
    command = command.replace("<>", readFile("edit.tmp").myEscape())

  if command =~ re"vedit (.+?):(.*)":
    try:
      echo matches.repr
      let objID = parseInt(matches[0][2..^1])
      let verbname = matches[1]

      let obj = world.getObjects()[objID]
      let verb = obj.getVerb(verbname)
      let code = verb.code

      writeFile("edit.tmp", code)
      discard os.execShellCmd("vim edit.tmp")
      let newCode = readFile("edit.tmp")

      verb.setCode(newCode)
      echo "Succesfully edited verb '$1'" % verbname
      world.persist()

    except:
      echo "There was a problem editing the verb."

    continue

  if command.len == 0: continue

  discard player.handleCommand(command).isType(dNil)
  while world.numTasks() > 0:
    world.tick()

removeFile("edit.tmp")


# Copyright 2017 Mamy André-Ratsimbazafy
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

proc `$`*[T](t: CudaTensor[T]): string {.noSideEffect.} =
  ## Pretty-print a CudaTensor (when using ``echo`` for example)
  let desc = "Tensor of shape " & t.shape.join("x") & " of type \"" & T.name & "\" on backend \"" & "Cuda" & "\""
  if t.rank <= 2:
    return desc & "\n" & t.disp2d
  elif t.rank == 3:
    return desc & "\n" & t.disp3d
  elif t.rank == 4:
    return desc & "\n" & t.disp4d
  else:
    return desc & "\n" & " -- NotImplemented: Display not implemented for tensors of rank > 4"

Convert CudaTensor to Tensor for display

# Copyright 2017 Mamy André-Ratsimbazafy
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

proc `$`*[T](t: CudaTensor[T]): string {.noSideEffect.} =
  ## Pretty-print a CudaTensor (when using ``echo`` for example)
  let desc = "Tensor of shape " & t.shape.join("x") & " of type \"" & T.name & "\" on backend \"" & "Cuda" & "\""

  let cpu_t = t.cpu()

  if t.rank <= 2:
    return desc & "\n" & cpu_t.disp2d
  elif t.rank == 3:
    return desc & "\n" & cpu_t.disp3d
  elif t.rank == 4:
    return desc & "\n" & cpu_t.disp4d
  else:
    return desc & "\n" & " -- NotImplemented: Display not implemented for tensors of rank > 4"


# Copyright 2017 Mamy André-Ratsimbazafy
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# ###################################################
# Global Cuda and CuBLAS state

# CuBLAS stream for parallel async processing on GPU
# Computations/Memcpy on different streams are done in simultaneously
# Streams are also necessary for async Cuda procs like cudaMemcpyAsync
var defaultStream: cublas_api.cudaStream_t
check cudaStreamCreate(addr defaultStream)

# CuBLAS handle
# Note: it prevents {.noSideEffect.} in all CuBLAS proc :/
var defaultHandle: cublasHandle_t
check cublasCreate(addr defaultHandle)

proc cudaRelease() {.noconv.}=
  # Release all cuda resources
  check cudaStreamDestroy(defaultStream)
  check cublasDestroy(defaultHandle)

  when defined(debug):
    echo "CUDA and CuBLAS resources successfully released"

addQuitProc(cudaRelease)

Destroy CuBLAS handle before CUDA stream

# Copyright 2017 Mamy André-Ratsimbazafy
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# ###################################################
# Global Cuda and CuBLAS state

# CuBLAS stream for parallel async processing on GPU
# Computations/Memcpy on different streams are done in simultaneously
# Streams are also necessary for async Cuda procs like cudaMemcpyAsync
var defaultStream: cublas_api.cudaStream_t
check cudaStreamCreate(addr defaultStream)

# CuBLAS handle
# Note: it prevents {.noSideEffect.} in all CuBLAS proc :/
var defaultHandle: cublasHandle_t
check cublasCreate(addr defaultHandle)

proc cudaRelease() {.noconv.}=
  # Release all cuda resources
  check cublasDestroy(defaultHandle)
  check cudaStreamDestroy(defaultStream)

  when defined(debug):
    echo "CUDA and CuBLAS resources successfully released"

addQuitProc(cudaRelease)


import types, objects, querying, verbs, builtins, persist, os, strutils, rdstdin, re, tables

let
  world = loadWorld("min")
  player = world.getObjects()[8]

world.check()

player.output = proc(obj: MObject, msg: string) =
  echo msg

proc myEscape(s: string): string =
  s.replace("\"", "\\\"")

while true:
  var command = readLineFromStdin("> ").strip()

  if command.contains("<>"):
    discard os.execShellCmd("vim edit.tmp -c 'set syntax=scheme'")
    command = command.replace("<>", readFile("edit.tmp").myEscape())

  if command =~ re"vedit (.+?):(.*)":
    try:
      let verbname = matches[1]

      let objs = player.query(matches[0].strip(), global = true)
      let obj = objs[0]

      let verb = obj.getVerb(verbname)
      if verb == nil:
        raise newException(Exception, "Verb doesn't exist")

      let code = verb.code

      writeFile("edit.tmp", code)
      discard os.execShellCmd("vim edit.tmp")
      let newCode = readFile("edit.tmp")

      verb.setCode(newCode)
      echo "Succesfully edited verb '$1'" % verbname
      world.persist()

    except:
      echo "There was a problem editing the verb."

    continue

  if command.len == 0: continue

  discard player.handleCommand(command).isType(dNil)
  while world.numTasks() > 0:
    world.tick()

removeFile("edit.tmp")

Set syntax to scheme in the correct place

import types, objects, querying, verbs, builtins, persist, os, strutils, rdstdin, re, tables

let
  world = loadWorld("min")
  player = world.getObjects()[8]

world.check()

player.output = proc(obj: MObject, msg: string) =
  echo msg

proc myEscape(s: string): string =
  s.replace("\"", "\\\"")

while true:
  var command = readLineFromStdin("> ").strip()

  if command.contains("<>"):
    discard os.execShellCmd("vim edit.tmp")
    command = command.replace("<>", readFile("edit.tmp").myEscape())

  if command =~ re"vedit (.+?):(.*)":
    try:
      let verbname = matches[1]

      let objs = player.query(matches[0].strip(), global = true)
      let obj = objs[0]

      let verb = obj.getVerb(verbname)
      if verb == nil:
        raise newException(Exception, "Verb doesn't exist")

      let code = verb.code

      writeFile("edit.tmp", code)
      discard os.execShellCmd("vim edit.tmp -c \"set syntax=scheme\"")
      let newCode = readFile("edit.tmp")

      verb.setCode(newCode)
      echo "Succesfully edited verb '$1'" % verbname
      world.persist()

    except:
      echo "There was a problem editing the verb."

    continue

  if command.len == 0: continue

  discard player.handleCommand(command).isType(dNil)
  while world.numTasks() > 0:
    world.tick()

removeFile("edit.tmp")


const OMP_FOR_ANNOTATION = "if(ompsize > " & $OMP_FOR_THRESHOLD & ")"

template omp_parallel_countup(i: untyped, size: Natural, body: untyped): untyped =
  let ompsize = size
  for i in `||`(0, ompsize, OMP_FOR_ANNOTATION):
    body

template omp_parallel_forup(i: untyped, start, size: Natural, body: untyped): untyped =
  let ompsize = size
  for i in `||`(start, ompsize, OMP_FOR_ANNOTATION):
    body

Add OpenMP flag and export proc

# Copyright 2017 The Arraymancer contributors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

when defined(openmp):
  {.passC: "-fopenmp".}

const OMP_FOR_ANNOTATION = "if(ompsize > " & $OMP_FOR_THRESHOLD & ")"

template omp_parallel_countup*(i: untyped, size: Natural, body: untyped): untyped =
  let ompsize = size
  for i in `||`(0, ompsize, OMP_FOR_ANNOTATION):
    body

template omp_parallel_forup*(i: untyped, start, size: Natural, body: untyped): untyped =
  let ompsize = size
  for i in `||`(start, ompsize, OMP_FOR_ANNOTATION):
    body


import os
import times
import parsecfg
import subs_mysql
import subs_windows
import types

var
  currJob, lastJob: Job = getCurrentJob()
  currAct: Activity
  conn = OpenDbConnection()

currAct.job.title = currJob.title
currAct.job.path = currJob.path
currAct.begin = getTime()
currAct.finish = getTime()
currAct.idle = false

conn = OpenDbConnection()
while true:
  currJob = getCurrentJob()
  if isIdle(1000*60*15):
    currAct.idle = true
  else:
    if not (currJob == lastJob):
      if currAct.finish - currAct.begin > 0:
        if AppendRecord(conn, currAct) == -1:
          conn = OpenDbConnection()
          discard AppendRecord(conn, currAct)
      lastJob = currJob
      currAct.job.title = currJob.title
      currAct.job.path = currJob.path
      currAct.begin = getTime()
      currAct.finish = getTime()
      currAct.idle = false
    else:
      currAct.finish = getTime()

  sleep(500)

Set a special "program" for idle peroid

import os
import times
import parsecfg
import subs_mysql
import subs_windows
import types

var
  currJob, lastJob: Job = getCurrentJob()
  currAct: Activity
  conn = OpenDbConnection()
  tagRules = conn.GetTagRules()

currAct.job.title = currJob.title
currAct.job.path = currJob.path
currAct.begin = getTime()
currAct.finish = getTime()
currAct.idle = false

while true:
  currJob = getCurrentJob()
  if isIdle(1000*60*15):
    currAct.idle = true
    currAct.job.title = "Idle"
    currAct.job.path = "Idle"
  else:
    if not (currJob == lastJob):
      if currAct.finish - currAct.begin > 0:
        var res = AppendRecord(conn, currAct)
        if res == -1:
          conn = OpenDbConnection()
          res = AppendRecord(conn, currAct)
        # deal with tags
        discard conn.ApplyTag(res, GetFittedTags(currAct, tagRules))

      lastJob = currJob
      currAct.job.title = currJob.title
      currAct.job.path = currJob.path
      currAct.begin = getTime()
      currAct.finish = getTime()
      currAct.idle = false
    else:
      currAct.finish = getTime()

  sleep(500)


import os, strutils, cligen/cfUt

{.push warning[ProveField]: off.}
proc mergeParams(cmdNames: seq[string],
                 cmdLine=os.commandLineParams()): seq[string] =
  ## This is an include file to provide query & merge of alternate sources for
  ## command-line parameters according to common conventions.  First it looks
  ## for and parses a ${PROG_CONFIG:-${XDG_CONFIG_HOME:-$HOME/.config}}/PROG
  ## config file where PROG=cmdNames[0] (uppercase in env vars, but samecase
  ## otherwise).  Then it looks for a $PROG environment variables ('_' extended
  ## for multi-commands, e.g. $PROG_SUBCMD).  Finally, it appends the passed
  ## ``cmdLine`` (usually command-line-entered parameters or @["--help"]).
  when defined(debugMergeParams):
    echo "mergeParams got cmdNames: ", repr(cmdNames)
  var cfPath = os.getEnv(strutils.toUpperAscii(cmdNames[0]) & "_CONFIG")
  if cfPath.len == 0:
    cfPath = os.getConfigDir() & cmdNames[0] & "/config"
    if not existsFile(cfPath):
      cfPath = cfPath[0..^8]
  if existsFile(cfPath):
    result.add cfToCL(cfPath, if cmdNames.len > 1: cmdNames[1] else: "")
  result.add envToCL(strutils.toUpperAscii(strutils.join(cmdNames, "_")))
  result = result & cmdLine
{.pop.}

Make more robust in case `cmdNames` is the empty seq.

import os, strutils, cligen/cfUt

{.push warning[ProveField]: off.}
proc mergeParams(cmdNames: seq[string],
                 cmdLine=os.commandLineParams()): seq[string] =
  ## This is an include file to provide query & merge of alternate sources for
  ## command-line parameters according to common conventions.  First it looks
  ## for and parses a ${PROG_CONFIG:-${XDG_CONFIG_HOME:-$HOME/.config}}/PROG
  ## config file where PROG=cmdNames[0] (uppercase in env vars, but samecase
  ## otherwise).  Then it looks for a $PROG environment variables ('_' extended
  ## for multi-commands, e.g. $PROG_SUBCMD).  Finally, it appends the passed
  ## ``cmdLine`` (usually command-line-entered parameters or @["--help"]).
  when defined(debugMergeParams):
    echo "mergeParams got cmdNames: ", repr(cmdNames)
  if cmdNames.len > 0:
    var cfPath = os.getEnv(strutils.toUpperAscii(cmdNames[0]) & "_CONFIG")
    if cfPath.len == 0:
      cfPath = os.getConfigDir() & cmdNames[0] & "/config"
      if not existsFile(cfPath):
        cfPath = cfPath[0..^8]
    if existsFile(cfPath):
      result.add cfToCL(cfPath, if cmdNames.len > 1: cmdNames[1] else: "")
    result.add envToCL(strutils.toUpperAscii(strutils.join(cmdNames, "_")))
  result = result & cmdLine
{.pop.}


import os, strutils
import abstract_asset_bundle, url_stream

import nimx/pathutils

var resourceUrlMapper*: proc(p: string): string # Deprecated

when defined(js) or defined(emscripten):
    proc urlForResourcePath*(path: string): string {.deprecated.} =
        if resourceUrlMapper.isNil:
            path
        else:
            resourceUrlMapper(path)

type WebAssetBundle* = ref object of AssetBundle
    mHref: string
    mBaseUrl: string

proc newWebAssetBundle*(): WebAssetBundle =
    result.new()
    result.mHref = getCurrentHref().parentDir()
    result.mBaseUrl = result.mHref & "/res"

method urlForPath*(ab: WebAssetBundle, path: string): string =
    if resourceUrlMapper.isNil:
        result = ab.mBaseUrl & "/" & path
    else:
        result = resourceUrlMapper("res/" & path)
        if not result.startsWith("http"):
            result = ab.mHref & "/" & result

Fix JS compilation with newer nim

import os, strutils
import abstract_asset_bundle, url_stream

import nimx/pathutils

var resourceUrlMapper*: proc(p: string): string # Deprecated

when defined(js) or defined(emscripten):
    proc urlForResourcePath*(path: string): string {.deprecated.} =
        if resourceUrlMapper.isNil:
            path
        else:
            resourceUrlMapper(path)

type WebAssetBundle* = ref object of AssetBundle
    mHref: string
    mBaseUrl: string

proc newWebAssetBundle*(): WebAssetBundle =
    result.new()
    result.mHref = getCurrentHref().parentDir()
    result.mBaseUrl = result.mHref & "/res"

method urlForPath*(ab: WebAssetBundle, path: string): string =
    {.gcsafe.}:
        if resourceUrlMapper.isNil:
            result = ab.mBaseUrl & "/" & path
        else:
            result = resourceUrlMapper("res/" & path)
            if not result.startsWith("http"):
                result = ab.mHref & "/" & result


Add an example that uses different framing for request & replies.

import std/[posix, strutils, tables], cligen/[osUt, mslice, magic, procpool]

type Excl = enum compress,tar,soft,apptype,elf,text,cdf,tokens,encoding,ascii
const e2Flag = {  # CSV & json missing; Maybe cligen/magic needs updating?
  apptype : MAGIC_NO_CHECK_APPTYPE , ascii   : MAGIC_NO_CHECK_ASCII   ,
  encoding: MAGIC_NO_CHECK_ENCODING, tokens  : MAGIC_NO_CHECK_TOKENS  ,
  cdf     : MAGIC_NO_CHECK_CDF     , compress: MAGIC_NO_CHECK_COMPRESS,
  elf     : MAGIC_NO_CHECK_ELF     , soft    : MAGIC_NO_CHECK_SOFT    ,
  tar     : MAGIC_NO_CHECK_TAR     , text    : MAGIC_NO_CHECK_TEXT    }.toTable

var gFlags = 0.cint
proc count(histo: var CountTable[string], s: MSlice) = histo.inc $s

proc classify = # Reply with same path as input if it passes filter.
  var m = magic_open(gFlags)
  if m == nil or magic_load(m, nil) != 0:
    stderr.write "cannot load magic DB: %s\n\t", m.magic_error, "\n"
    quit 1
  for path in stdin.getDelim('\0'):
    let fileType = $m.magic_file(path.cstring)
    discard wrLenBuf(1, fileType)

proc fkindc*(gen="find $1 -print0", dlr1=".", excl: set[Excl]={}, jobs=0) =
  ## Use ``gen`` and ``dlr1`` to generate paths and histogram by `file(1)` type.
  var histo: CountTable[string]
  for e in excl: gFlags = gFlags or cint(e2Flag[e]) # Set up gFlags for libmagic
  let inp = popen(cstring(gen % dlr1), "r".cstring) # Fire input path generator
  var pp = initProcPool(classify, framesLenPfx, jobs) # Start & drive kids
  pp.eval0term(inp.getDelim('\0'), histo.count)     # Replies=0-term file types
  discard inp.pclose
  histo.sort
  for k, ct in histo: echo ct, '\t', k

when isMainModule:
  import cligen; dispatch fkindc, short={"excl": 'x'}, help={
    "gen" : "generator cmd with dlr1 -> $1",
    "dlr1": "$1 for gen fmt; Eg. *\". -type f\"*",
    "excl": "tests to exclude like `file(1)`",
    "jobs": "use this many kids (0=auto)" }


discard """
  output: "@[]"
"""
import htmlparser
import xmltree
import strutils
from streams import newStringStream

## builds the two cases below and test that
## ``//[dd,li]`` has "
that
" as children
##
##

##
this

##

##
that

##

##

##
##

##

##
that

##

##

for ltype in [["dl","dd"], ["ul","li"]]:
  let desc_item = if ltype[0]=="dl": "
this
" else: ""
  let item = "$1<$2>
that
</$2>" % [desc_item, ltype[1]]
  let list = """ <$1>
   $2
</$1> """ % [ltype[0], item]

  var errors : seq[string] = @[]

  let parseH = parseHtml(newStringStream(list),"statichtml", errors =errors)

  echo $parseH.findAll(ltype[1])[0].child("p") == "
that
"


import strutils

proc sum_digits(n: int): int =
  for c in $ n:
    result += parseInt($ c)

when isMainModule:
  echo "Enter a number"
  let num = readLine(stdin).parseInt()
  echo "Sum of digits is: ", sum_digits(num)


Add program to generate docs for builtins

import strutils
import nre
import options
import streams

const
  builtinsSourceFile = "src/builtins.nim"

proc gendocs*(instream = newFileStream(builtinsSourceFile, fmRead),
              outstream = newFileStream(stdout)) =
  var currentComment = ""

  while not instream.atEnd():
    let line = instream.readLine()
    if line.strip().len == 0:
      continue

    if line[0] == '#' and line[1] == '#':
      if line.len == 2:
        currentComment &= "\n"
      else:
        if line[2] == ' ':
          currentComment &= line[3..^1] & "\n"
        else:
          currentComment &= line[2..^1] & "\n"
    elif line[0..9] == "defBuiltin":
      let matchOpt = line.match(re"""defBuiltin "([^"]+)":.*""")
      if matchOpt.isSome:
        let builtinName = matchOpt.get.captures.toSeq[0]
        let bNameLen = builtinName.len
        let numTildes = if bNameLen < 4: 4 else: bnameLen
        outstream.writeLine(builtinName)
        outStream.writeLine(repeat('~', numTildes))
        outstream.writeLine(currentComment)
      currentComment = ""

when isMainModule:
  gendocs()


discard """
    output: '''likely occurrence
unlikely occurrence'''
"""

if likely(true):
    echo "likely occurrence"

if unlikely 4 == 34:
    echo "~~wrong branch taken~~"
else:
    echo "unlikely occurrence"


import md5, re, os, strutils, osproc

let
  markdownFilesGlob = getCurrentDir() / "content" / "*.md"
  configFilePath = getCurrentDir() / "validcodehashes.txt"

for filePath in walkFiles(markdownFilesGlob):
  let file = open(filePath, fmRead)
  let fileContents = file.readAll()
  file.close()

  let sourceSegments = fileContents.findAll(re"""(?i)```\s*nimrod[\s\S]*?```""")
  for match in sourceSegments:
    let code = match.replacef(re"""(?i)```\s*nimrod[ \t]*\s([\s\S]*?)```""", "$1")
    let codeHash = code.getMD5()
    if not configFilePath.readFile().contains(codeHash):  # Hasn't been verified yet
      let tempCodePath = getTempDir() / "code.nim"
      tempCodePath.writeFile(code)
      let (output, exitCode) = execCmdEx("nimrod c -r --verbosity:0 " & tempCodePath)

      var printableCode = ""
      for line in code.splitLines():
        printableCode.add("    " & line & "\n")

      var printableOutput = ""
      if output != nil:
        for line in output.splitLines():
          printableOutput.add("> " & line & "\n")

      echo filePath
      stdout.write(printableCode & printableOutput)

      stdout.write("Everything ok? (y/n) ")
      case stdin.readLine.toLower:
        of "y":
          configFilePath.writeFile(configFilePath.readFile() & "\n" & codeHash)
        of "n":
          discard

      echo "===================="


Add a very simple timing program to measure procpool dispatch overhead.

import std/posix, cligen/[procpool, osUt, posixUt], cligen

var ibuf, obuf: string

proc doSin() =
  var buf: string
  buf.setLen ibuf.len + 1
  while stdin.ureadBuffer(buf[0].addr, ibuf.len) == ibuf.len:
    discard stdout.uriteBuffer(obuf[0].addr, obuf.len)

proc ppBench(input=1, output=1, n=500000, jobs=1, rTOms=0, wTOms=0): int =
  ## Measure procpool overhead vs input-output sizes & jobs as specified.
  let rT = Timeval(tv_usec: 1000 * rTOms.clong) # set select timeouts
  let wT = Timeval(tv_usec: 1000 * wTOms.clong)
  for i in 1..max(1, input ): ibuf.add ($i)[^1] # populate dummy buffers with..
  for i in 1..max(1, output): obuf.add ($i)[^1] #..last digits of numbers
  obuf.add '\0'
  iterator genWork: string = (for i in 1..n: yield ibuf)
  let t0 = getTmNs()                            # Time starting kids and..
  var pp = initProcPool(doSin, frames0term, jobs, toR=rT, toW=wT)
  pp.eval0term(genWork(), noop)                 #..then generate & run work.
  echo "amortized dispatch overhead/job (ns): ", int(dtNs(t0).float / n.float)

dispatch ppBench, help={
  "input" : "bytes to input to pipes", "output": "bytes to output to pipes",
  "n"     : "number of jobs to time" , "jobs"  : "this many parallel kids" ,
  "rTOms" : "read select timeout(ms)", "wTOms" : "write select timeout(ms)"}


Add Nim version of the converter from SQL scripts to SQLite database

import sqlite3
import parseopt2
import strutils
import times
import os

proc writeHelp()=
  echo("SQL2SQLite <SQL Filename>")

proc writeVersion()=
  echo("SQL2SQLite 0.0.1")

var
  filename = ""
  time1, time2: float

time1 = epochTime()

for kind, key, val in getopt():
  case kind
  of cmdArgument:
    filename = key
  of cmdLongOption, cmdShortOption:
    case key
    of "help", "h": writeHelp()
    of "version", "v": writeVersion()
    else: discard
  else:
    discard

block main:
  if filename.len == 0:
    # no filename has been given, so we show the help:
    writeHelp()
    break
  else:
    var
      conn: PSqlite3
      query: string = ""
      errmsg: cstring
      flag: int32

    var sqliteName = filename & ".db3"

    discard open(sqliteName, conn)

    discard conn.exec("BEGIN TRANSACTION".cstring, nil, nil, errmsg)

    for fp in walkFiles(filename & "_*.sql"):
      echo("Working with " & fp)
      for line in lines(fp):
        # iterate over the file
        if line[0..1] == "--" or line.len == 0:
          continue
        query &= line

        if line[line.len-1] == ';':
          # conn.exec(sql(query))
          if query[0..5] == "CREATE" or query[0..5] == "INSERT":
            flag = conn.exec(query.cstring, nil, nil, errmsg)
            if flag != 0:
              echo(query)
          query = ""

    discard conn.exec("END TRANSACTION".cstring, nil, nil, errmsg)
    discard conn.close()

time2 = epochTime() - time1
echo("Program finished in $1 seconds." % $time2)


# test some things of the os module

import os

proc walkDirTree(root: string) =
  for k, f in walkDir(root):
    case k
    of pcFile, pcLinkToFile: echo(f)
    of pcDir: walkDirTree(f)
    of pcLinkToDir: discard

walkDirTree(".")

Add os tests for directory creation, iteration and deletion

discard """
  output: '''true
true
true
true
true
true
true
true
true
All:
__really_obscure_dir_name/are.x
__really_obscure_dir_name/created
__really_obscure_dir_name/dirs
__really_obscure_dir_name/files.q
__really_obscure_dir_name/some
__really_obscure_dir_name/test
__really_obscure_dir_name/testing.r
__really_obscure_dir_name/these.txt
Files:
__really_obscure_dir_name/are.x
__really_obscure_dir_name/files.q
__really_obscure_dir_name/testing.r
__really_obscure_dir_name/these.txt
Dirs:
__really_obscure_dir_name/created
__really_obscure_dir_name/dirs
__really_obscure_dir_name/some
__really_obscure_dir_name/test
false
false
false
false
false
false
false
false
false
'''
"""
# test os path creation, iteration, and deletion

import os

let files = @["these.txt", "are.x", "testing.r", "files.q"]
let dirs = @["some", "created", "test", "dirs"]

let dname = "__really_obscure_dir_name"

createDir(dname)
echo dirExists(dname)

# Test creating files and dirs
for dir in dirs:
  createDir(dname/dir)
  echo dirExists(dname/dir)

for file in files:
  let fh = open(dname/file, fmReadWrite)
  fh.close()
  echo fileExists(dname/file)

echo "All:"

for path in walkPattern(dname/"*"):
  echo path

echo "Files:"

for path in walkFiles(dname/"*"):
  echo path

echo "Dirs:"

for path in walkDirs(dname/"*"):
  echo path

# Test removal of files dirs
for dir in dirs:
  removeDir(dname/dir)
  echo dirExists(dname/dir)

for file in files:
  removeFile(dname/file)
  echo fileExists(dname/file)

removeDir(dname)
echo dirExists(dname)


var state = 0

while state != 25:
  echo "Balance: " , state
  echo "Insert a coin (penny, nickel, dime, quarter)"

  let coin = readLine(stdin)

  case coin
    of "penny":
      state += 1
    of "nickel":
      state += 5
    of "dime":
      state += 10
    of "quarter":
      state += 25
    else:
      echo "Not a coin"

echo "Here's your quarter"


var doors: array[100, bool]

# Initialize doors to be closed
for i in 0..99:
  doors[i] = false

for i in 0..99:
  var j = i
  while j < 100:
    doors[j] = (not doors[j])
    j += i + 1

# Print the value of open doors
for d in 0..99:
  if doors[d]:
    echo "Door ", d + 1, " is open"


from strformat import fmt

proc lyric_99_bottles(num: int) =
  if num == 99:
    echo "99 bottles of beer on the wall, 99 bottles of beer."
  elif num == 0:
    echo "Take one down and pass it around, no more bottles of beer on the wall."
    echo "No more bottles of beer on the wall, no more bottles of beer."
    echo "Go to the store and buy some more, 99 bottles of beer on the wall."
    return
  else:
    echo fmt"Take one down and pass it around, {num} bottles of beer on the wall."
    echo fmt"{num} bottles of beer on the wall, {num} bottles of beer."

  lyric_99_bottles(num - 1)

lyric_99_bottles(99)


from strutils import parseInt

proc gcd(x, y: int): int =
  if x == 0:
    return y
  result = gcd(y mod x, x)

proc euler_totient(n: int): int =
  result = 1
  for i in 2..< n:
    if gcd(n,i) == 1:
      inc result

when isMainModule:
  echo "Enter a number"
  let num = readLine(stdin).parseInt()
  echo euler_totient(num)


type
  Regex = distinct string

const maxSubpatterns = 10

proc re(x: string): Regex =
  result = Regex(x)

proc match(s: string, pattern: Regex, captures: var openArray[string]): bool =
  true

template optRe{re(x)}(x: string{lit}): Regex =
  var g {.global.} = re(x)
  g

template `=~`(s: string, pattern: Regex): bool =
  when not definedInScope(matches):
    var matches {.inject.}: array[maxSubPatterns, string]
  match(s, pattern, matches)

for line in lines("input.txt"):
  if line =~ re"(\w+)=(\w+)":
    echo "key-value pair; key: ", matches[0], " value: ", matches[1]

Use declaredInScope instead of definedInScope

type
  Regex = distinct string

const maxSubpatterns = 10

proc re(x: string): Regex =
  result = Regex(x)

proc match(s: string, pattern: Regex, captures: var openArray[string]): bool =
  true

template optRe{re(x)}(x: string{lit}): Regex =
  var g {.global.} = re(x)
  g

template `=~`(s: string, pattern: Regex): bool =
  when not declaredInScope(matches):
    var matches {.inject.}: array[maxSubPatterns, string]
  match(s, pattern, matches)

for line in lines("input.txt"):
  if line =~ re"(\w+)=(\w+)":
    echo "key-value pair; key: ", matches[0], " value: ", matches[1]


Introduce fused ops to avoid catastrophic cancellation

# Copyright 2017 the Arraymancer contributors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import math

# Importing this library provides fusion operations.
# Those gives either a performance improvements (Fused Multiply-Add)
# Or accuracy improvement by avoiding catastrophic cancellation

proc ln1p*(x: float32): float32 {.importc: "log1pf", header: "<math.h>".}
proc ln1p*(x: float64): float64 {.importc: "log1p", header: "<math.h>".}
  ## Compute ln( 1+x ) and avoids catastrophic cancellation if x << 1
  ## i.e. if x << 1 ln(1+x) ~= x but normal float rounding would do ln(1) = 0 instead.

proc expm1*(x: float32): float32 {.importc: "expm1f", header: "<math.h>".}
proc expm1*(x: float64): float64 {.importc: "expm1", header: "<math.h>".}
  ## Compute exp(x) - 1 and avoids catastrophic cancellation if x ~= 0
  ## i.e. if x ~= 0 exp(x) - 1 ~= x but normal float rounding would do exp(0) - 1 = 0 instead.

## The auto-rewrite do not seem to work :/

# template rewriteLn1p*{ln(`+`(1,x))}(x: typed): type(x) =
#   ## Fuse ``ln(1 + x)`` into a single operation.
#   ##
#   ## Operation fusion leverage the Nim compiler and should not be called explicitly.
#   ln1p x
#
# template rewriteLn1p*{ln(`+`(x,1))}(x: typed): type(x) =
#   ## Fuse ``ln(x + 1)`` into a single operation.
#   ##
#   ## Operation fusion leverage the Nim compiler and should not be called explicitly.
#   ln1p x

# Note: we don't create the FMA proc as detection of hardware support happens at GCC
# compilation time. Furthermore, the fallback is slower than doing (x*y) + z
# because the fallback do the intermediate computation at full precision.
# So, trust the compiler


import dbus

let bus = getBus(dbus.DBUS_BUS_SESSION)
var msg = makeCall("com.zielmicha.test",
             ObjectPath("/com/zielmicha/test"),
             "com.zielmicha.test",
             "hello")

msg.append(newVariant("hi"))

let pending = bus.sendMessageWithReply(msg)
let reply = pending.waitForReply()
reply.raiseIfError()

var it = reply.iterate
let v = it.unpackCurrent(DbusValue)
assert v.asNative(string) == "Hello, world!"
it.advanceIter
let val = it.unpackCurrent(DbusValue)
assert val.kind == dtString
assert val.asNative(string) == "hi"


Add spawn test. Hangs most of the time on linux x64 at least.

discard """
  output: '''4
8'''
  cmd: "nimrod $target --threads:on $options $file"
"""

var
  x, y = 0

proc p1 =
  for i in 0 .. 1_000_000:
    discard

  inc x

proc p2 =
  for i in 0 .. 1_000_000:
    discard

  inc y, 2

for i in 0.. 3:
  spawn(p1())
  spawn(p2())

sync()

echo x
echo y


discard """
  line: 7
  errormsg: "'spawn' takes a call expression of type void"
  cmd: "nimrod $target --threads:on $options $file"
"""

spawn(1)


Add test case for infinite recursion in semtypes

discard """
  errormsg: "illegal recursion in type 'XIM'"
  line: 8
"""

type
  XIM* = ptr XIM
  XIMProc* = proc (a2: XIM)


Add a test case for the EvError handling issue

discard """
  file: "tasynceverror.nim"
  exitcode: 1
  outputsub: "Error: unhandled exception: Connection reset by peer [Exception]"
"""

import
    asyncdispatch,
    asyncnet,
    rawsockets,
    os

const
    testHost = "127.0.0.1"
    testPort = Port(17357)

proc createListenSocket(host: string, port: Port): TAsyncFD =
    result = newAsyncRawSocket()

    SocketHandle(result).setSockOptInt(SOL_SOCKET, SO_REUSEADDR, 1)

    var aiList = getAddrInfo(host, port, AF_INET)
    if SocketHandle(result).bindAddr(aiList.ai_addr, aiList.ai_addrlen.Socklen) < 0'i32:
      dealloc(aiList)
      raiseOSError(osLastError())
    dealloc(aiList)

    if SocketHandle(result).listen(1) < 0'i32:
        raiseOSError(osLastError())

proc testAsyncSend() {.async.} =
    var
        ls = createListenSocket(testHost, testPort)
        s = newAsyncSocket()

    await s.connect(testHost, testPort)

    var ps = await ls.accept()
    SocketHandle(ls).close()

    await ps.send("test 1", flags={})
    s.close()
    # This send should raise EPIPE
    await ps.send("test 2", flags={})
    SocketHandle(ps).close()

# The bug was, when the poll function handled EvError for us,
# our callbacks may never get executed, thus making the event
# loop block indefinitely. This is a timer to keep everything
# rolling. 400 ms is an arbitrary value, should be enough though.
proc timer() {.async.} =
    await sleepAsync(400)
    echo("Timer expired.")
    quit(2)

asyncCheck(testAsyncSend())
waitFor(timer())


discard """
  output: "@[]"
"""
import htmlparser
import xmltree
import strutils
from streams import newStringStream

## builds the two cases below and test that
## ``//[dd,li]`` has "
that
" as children
##
##

##
this

##

##
that

##

##

##
##

##

##
that

##

##

for ltype in [["dl","dd"], ["ul","li"]]:
  let desc_item = if ltype[0]=="dl": "
this
" else: ""
  let item = "$1<$2>
that
</$2>" % [desc_item, ltype[1]]
  let list = """ <$1>
   $2
</$1> """ % [ltype[0], item]

  var errors : seq[string] = @[]

  let parseH = parseHtml(newStringStream(list),"statichtml", errors =errors)

  echo $parseH.findAll(ltype[1])[0].child("p") == "
that
"

Update htmlparser test ``output`` variable

discard """
  output: true
"""
import htmlparser
import xmltree
import strutils
from streams import newStringStream

## builds the two cases below and test that
## ``//[dd,li]`` has "
that
" as children
##
##

##
this

##

##
that

##

##

##
##

##

##
that

##

##

for ltype in [["dl","dd"], ["ul","li"]]:
  let desc_item = if ltype[0]=="dl": "
this
" else: ""
  let item = "$1<$2>
that
</$2>" % [desc_item, ltype[1]]
  let list = """ <$1>
   $2
</$1> """ % [ltype[0], item]

  var errors : seq[string] = @[]

  let parseH = parseHtml(newStringStream(list),"statichtml", errors =errors)

  if $parseH.findAll(ltype[1])[0].child("p") != "
that
":
    echo "case " & ltype[0] & " failed !"
    quit(2)

echo "true"


import jester, strtabs, json, asyncio, sockets

get "/json":
  var obj = %{"message": %"Hello, World!"}
  resp($obj)

var disp = newDispatcher()
disp.register(port = TPort(9000), http=false)
while disp.poll(): nil

Set Content-Type as application/json for the Jester benchmark.

import jester, strtabs, json, asyncio, sockets

get "/json":
  var obj = %{"message": %"Hello, World!"}
  resp($obj, "application/json")

var disp = newDispatcher()
disp.register(port = TPort(9000), http=false)
while disp.poll(): nil


# Copyright 2017 the Arraymancer contributors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import  ../../tensor/tensor,
        ../../nn_primitives/nn_primitives,
        ../../autograd/autograd

type ReshapeGate* [TT] = ref object of Gate[TT]
  cached_input_shape: MetadataArray
  cached_output_shape: varargs[int]|MetadataArray

method forward*[TT](self: ReshapeGate[TT], a: Variable[TT]): Variable[TT] {.inline, locks:0.}=
  new result

  result.tape = a.tape
  result.value = a.value.reshape(self.cached_output_shape)

method backward*[TT](self: ReshapeGate[TT], gradient: TT): SmallDiffs[TT] {.noInit, inline, locks:0.}=
  result[0] = gradient.reshape(self.cached_input_shape)

template reshapeT[TT](a: Variable[TT], shape: varargs[int]|MetadataArray): Variable[TT] =
  # Gate
  var gate: ReshapeGate[TT]
  new gate
  gate.arity = 1
  gate.cached_input_shape = a.shape
  gate.cached_output_shape = shape

  # Node
  var node: Node[TT]
  new node

  node.gate = gate
  node.parents[0] = a

  a.tape.push(node)

  # Resulting var
  result = gate.forward(a)
  result.ancestor = node
  node.child = result

proc reshape*[TT](a: Variable[TT], shape: varargs[int]): Variable[TT] =
  ## Input:
  ##   - A variable
  ##   - A shape
  reshapeT(a, shape)

proc reshape*[TT](a: Variable[TT], shape: MetadataArray): Variable[TT] =
  ## Input:
  ##   - A variable
  ##   - A shape
  reshapeT(a, shape)

proc flatten*[TT](a: Variable[TT]): Variable[TT] =
  ## Input:
  ##   - A variable
  reshapeT(a, 1)


discard """
output: '''1
0
1
0
1
0
1
0'''
"""

import macros

macro test(a: typed, b: typed): expr =
  newLit(a == b)

echo test(1, 1)
echo test(1, 2)

type
  Obj = object of RootObj
  Other = object of RootObj

echo test(Obj, Obj)
echo test(Obj, Other)

var a, b: int

echo test(a, a)
echo test(a, b)

macro test2: expr =
  newLit(bindSym"Obj" == bindSym"Obj")

macro test3: expr =
  newLit(bindSym"Obj" == bindSym"Other")

echo test2()
echo test3()


import strutils

proc sum_digits(n: int): int =
  for c in $ n:
    result += parseInt($ c)

when isMainModule:
  echo "Enter a number"
  let num = readLine(stdin).parseInt()
  echo "Sum of digits is: ", sum_digits(num)


Add a new example of `forPath` that actually cares about hierarchy/ has a non-trivial post-recurse clause.

import strformat, cligen, posix, cligen/[dents, posixUt, statx]

proc rr*(roots: seq[string], xdev=false): int =
  ## Like rm -rf but a bit faster.  Does nothing if no ``roots`` specified.
  if roots.len == 0: return
  var dfds: seq[cint]
  for root in roots:
    forPath(root,0,false,false,xdev, depth,path,dfd,nmAt,ino,dt,lst,dst):
      if dt != DT_DIR:
        if unlinkat(dfd, path[nmAt..^1], 0) != 0:
          stderr.log &"rr({path}): {strerror(errno)}\n"
      elif dfds.len > 0 and dfds[^1] == dfd: discard
      else: dfds.add dfd
    do: discard                   # Pre-recurse
    do:                           # Post-recurse (dt == DT_DIR guaranteed)
      if unlinkat(dfds.pop, path[nmAt..^1], AT_REMOVEDIR) != 0:
        stderr.log &"rr({path}): {strerror(errno)}\n"
        # Future dir-unlinks are doomed to fail ENOTEMPTY except maybe ENOENT
        # here if in a race with another unlinker.  Forfeit races & quit here.
        quit(1)
    do: recFailDefault("rr")      # Cannot recurse
  return 0

when isMainModule:
  dispatch(rr, help = { "xdev" : "block recursion across device boundaries" })


Add semi-automatic multi-cmd example. Does not quite work, though.

proc demo(alpha=1, beta=2.0, verb=false, item="", files: seq[string]): int =
  ## demo entry point with varied, meaningless parameters.
  echo "alpha:", alpha, " beta:", beta, " verb:", verb, " item:", repr(item)
  for i, f in files: echo "args[", i, "]: ", repr(f)
  return 42

proc show(gamma=1, iota=2.0, verb=false, paths: seq[string]): int =
  ## show entry point with varied, meaningless parameters.
  echo "gamma:", gamma, " iota:", iota, " verb:", verb
  for i, p in paths: echo "args[", i, "]: ", repr(p)
  return 42

when isMainModule:
  import cligen, os

  dispatchGen(demo, doc="  This does the demo.", help = {
              "alpha" : "This is a very long parameter help string which " &
                        "ordinarily should be auto-wrapped by alignTable " &
                        "into a multi-line format unless you have eagle " &
                        "eyes, a gigantic monitor, or maybe a little bit of " &
                        "both. :-)",
              "beta" : "This is more modest, but might still wrap around " &
                       "once or twice or so.",
              "verb" : "on=chatty, off=quiet. 'Nuff said." })

  dispatchGen(show, doc="  This shows me something.")

  #XXX Top-level getopt loop currently eats all options.
  proc multi(beta=1, subcmd: string, subcmdArgs: seq[string]): int =
    case subcmd
    of "demo": quit(dispatch_demo(cmdline = subcmdArgs))
    of "show": quit(dispatch_show(cmdline = subcmdArgs))
    of "help":
        echo "Usage:\n  ManualMulti demo|show [subcommand-args]\n"
        echo "    This is a multiple-dispatch cmd.  Subcommand syntax:\n"
        # Don't have multiple Usage: stuff in there.  Also indent subcmd help.
        let use = "ManualMulti $command $args\n$doc\nOptions:\n$options"
        discard dispatch_demo(cmdline = @[ "--help" ], prefix="    ", usage=use)
        discard dispatch_show(cmdline = @[ "--help" ], prefix="    ", usage=use)
        quit(0)
    else: echo "unknown subcommand: ", subcmd
    quit(1)

  dispatch(multi)


Add test for objvariant construction order

discard """
  output: "SUCCESS"
"""

# A test to ensure that the order in which a variant
# object is constructed doesn't matter.

type
  NodeKind = enum
    Literal, Operator

  Node = ref object
    case kind: NodeKind
    of Literal:
      value: int
    of Operator:
      left, right: Node
      operator: char

# The trees used through out this test should
# be the same after construction, the only difference
# being the way we specify their construction.
# This will test that all the values are what we expect.
proc assertTree(root: Node) =
  # check root of tree
  assert root.kind == Operator
  assert root.operator == '*'

  # check left subtree
  assert root.left.value == 5
  assert root.left.kind == Literal

  # check right subtree
  assert root.right.kind == Operator
  assert root.right.operator == '+'

  assert root.right.left.value == 5
  assert root.right.left.kind == Literal

  assert root.right.right.value == 10
  assert root.right.right.kind == Literal

proc newLiteralNode(value: int): Node =
  result = Node(
    kind: Literal,
    value: value
  )

var rootOrder1 = Node(
  kind: Operator,
  operator: '*',
  left: newLiteralNode(5),
  right: Node(
    left: newLiteralNode(5),
    right: newLiteralNode(10),
    kind: Operator,
    operator: '+'
  )
)
assertTree(rootOrder1)

var rootOrder2 = Node(
  operator: '*',
  kind: Operator,
  left: newLiteralNode(5),
  right: Node(
    left: newLiteralNode(5),
    right: newLiteralNode(10),
    kind: Operator,
    operator: '+'
  )
)
assertTree(rootOrder2)

var rootOrder3 = Node(
  left: newLiteralNode(5),
  operator: '*',
  kind: Operator,
  right: Node(
    left: newLiteralNode(5),
    right: newLiteralNode(10),
    kind: Operator,
    operator: '+'
  )
)
assertTree(rootOrder3)

var rootOrder4 = Node(
  left: newLiteralNode(5),
  operator: '*',
  kind: Operator,
  right: Node(
    left: newLiteralNode(5),
    kind: Operator,
    operator: '+',
    right: newLiteralNode(10)
  )
)
assertTree(rootOrder4)

var rootOrder5 = Node(
  left: newLiteralNode(5),
  operator: '*',
  kind: Operator,
  right: Node(
    left: newLiteralNode(5),
    operator: '+',
    right: newLiteralNode(10),
    kind: Operator
  )
)
assertTree(rootOrder5)

echo "SUCCESS"


import memfiles
var inp = memfiles.open("readme.txt")
var buffer: TaintedString = ""
for line in lines(, buffer):
  echo("#" & line & "#")
close(inp)

Fix accidentally deleted inp argument.

import memfiles
var inp = memfiles.open("readme.txt")
var buffer: TaintedString = ""
for line in lines(inp, buffer):
  echo("#" & line & "#")
close(inp)


#' @rdname dplyr::tbl_sql
#' @export
tbl_sql <- function(subclass, src, from, ..., vars = NULL) {
  assert_that(is.character(from), length(from) == 1)

  from <- db_table_source(src$con, src$path, from)

  tbl <- make_tbl(c(subclass, "sql"),
    src = src,              # src object
    from = from,            # table, join, or raw sql
    select = vars,          # SELECT: list of symbols
    summarise = FALSE,      #   interpret select as aggreagte functions?
    mutate = FALSE,         #   do select vars include new variables?
    where = NULL,           # WHERE: list of calls
    group_by = NULL,        # GROUP_BY: list of names
    order_by = NULL         # ORDER_BY: list of calls
  )
  update(tbl)
}

Remove reference to dplyr rdname


library("ggplot2")
library("reshape2")
setwd("~/dev/BitFunnel/src/Scripts")

# png(filename="wat.png",width=800,height=600)
png(filename="talk.png",width=1600,height=1200)
# df <- read.csv(header=FALSE, file="wat.csv")
df <- read.csv(header=FALSE, file="talk.csv")
## df <- read.csv(file="wat.csv")
## munged <- melt(df)
## ggplot(munged, aes(x=variable, y=value)) + geom_point()

# plot single
# ggplot(data=df, aes(x=factor(V1), y=V2)) + geom_bar(stat="identity") + labs(x = "Number of cache misses", y = "count")

# plot uniform 20 vs. buggy distribution
# ggplot(data=df, aes(x=factor(V1), y=V2)) + geom_bar(stat="identity") + facet_wrap(~ V3, ncol=1) + labs(x = "Number of cache misses", y = "count")

# plot for talk
ggplot(data=df, aes(x=factor(V1), y=V2)) + geom_bar(stat="identity") + labs(x = "Memory accesses", y = "Percent") +
  theme(axis.text = element_text(size=40),
        axis.title = element_text(size=40))

dev.off()

Make plot somewhat less ugly.

library("ggplot2")
library("reshape2")
setwd("~/dev/BitFunnel/src/Scripts")

# png(filename="wat.png",width=800,height=600)
png(filename="talk.png",width=1600,height=1200)
# df <- read.csv(header=FALSE, file="wat.csv")
df <- read.csv(header=FALSE, file="talk.csv")
## df <- read.csv(file="wat.csv")
## munged <- melt(df)
## ggplot(munged, aes(x=variable, y=value)) + geom_point()

# plot single
# ggplot(data=df, aes(x=factor(V1), y=V2)) + geom_bar(stat="identity") + labs(x = "Number of cache misses", y = "count")

# plot uniform 20 vs. buggy distribution
# ggplot(data=df, aes(x=factor(V1), y=V2)) + geom_bar(stat="identity") + facet_wrap(~ V3, ncol=1) + labs(x = "Number of cache misses", y = "count")

# plot for talk
ggplot(data=df, aes(x=factor(V1), y=V2)) + geom_bar(stat="identity") + labs(x = "Memory accesses", y = "Percent") +
  theme_bw() +
  theme(axis.text = element_text(size=40),
        axis.title = element_text(size=40))

dev.off()


#' SlurmContainer R6 object.
#'
#' A slurm container is simply a directory with a specific
#' structure, particulary it has a submit.slurm script at the
#' top level.
SlurmContainer <- R6::R6Class("SlurmContainer",
    public = list(
        dir = NULL,
        initialize = function(dir = ".") {
            name <- paste0("job_", private$rand_alphanumeric())
            dir <- paste(dir, name, sep = "/")

            for (sub_dir in c("/input", "/ouput", "/sources", "/.objects")) {
                dir.create(paste0(dir, sub_dir), recursive = TRUE,
                           showWarnings = FALSE)
            }
        }
    ),
    private = list(
        rand_alphanumeric = function(len = 3) {
            population <- c(rep(0:9, each = 5), LETTERS, letters)
            samp <- sample(population, len, replace = TRUE)
            return(paste(samp, collapse = ''))
        }
    )
)

Make dir of container full path

#' SlurmContainer R6 object.
#'
#' A slurm container is simply a directory with a specific
#' structure, particulary it has a submit.slurm script at the
#' top level.
SlurmContainer <- R6::R6Class("SlurmContainer",
    public = list(
        dir = NULL,
        initialize = function(dir = ".") {
            name <- paste0("job_", private$rand_alphanumeric())
            dir <- paste(getwd(), dir, name, sep = "/")
            self$dir <- dir

            for (sub_dir in c("/input", "/ouput", "/sources", "/.objects")) {
                dir.create(paste0(dir, sub_dir), recursive = TRUE,
                           showWarnings = FALSE)
            }
        }
    ),
    private = list(
        rand_alphanumeric = function(len = 3) {
            population <- c(rep(0:9, each = 5), LETTERS, letters)
            samp <- sample(population, len, replace = TRUE)
            return(paste(samp, collapse = ''))
        }
    )
)


REBOL [
    System: "REBOL [R3] Language Interpreter and Run-time Environment"
    Title: "REBOL 3 Mezzanine: Control"
    Rights: {
        Copyright 2012 REBOL Technologies
        REBOL is a trademark of REBOL Technologies
    }
    License: {
        Licensed under the Apache License, Version 2.0
        See: http://www.apache.org/licenses/LICENSE-2.0
    }
]

launch: func [
    {Runs a script as a separate process; return immediately.}
    script [file! string! none!] "The name of the script"
    /args arg [string! block! none!] "Arguments to the script"
    /wait "Wait for the process to terminate"
][
    if file? script [script: to-local-file clean-path script]
    args: reduce [to-local-file system/options/boot script]
    if arg [append args arg]
    either wait [call/wait args] [call args]
]

wrap: func [
    "Evaluates a block, wrapping all set-words as locals."
    body [block!] "Block to evaluate"
][
    do bind/copy/set body make object! 0
]

Add CHECK-SET routine per suggestion from @earl

REBOL [
    System: "REBOL [R3] Language Interpreter and Run-time Environment"
    Title: "REBOL 3 Mezzanine: Control"
    Rights: {
        Copyright 2012 REBOL Technologies
        REBOL is a trademark of REBOL Technologies
    }
    License: {
        Licensed under the Apache License, Version 2.0
        See: http://www.apache.org/licenses/LICENSE-2.0
    }
]

launch: func [
    {Runs a script as a separate process; return immediately.}
    script [file! string! none!] "The name of the script"
    /args arg [string! block! none!] "Arguments to the script"
    /wait "Wait for the process to terminate"
][
    if file? script [script: to-local-file clean-path script]
    args: reduce [to-local-file system/options/boot script]
    if arg [append args arg]
    either wait [call/wait args] [call args]
]

wrap: func [
    "Evaluates a block, wrapping all set-words as locals."
    body [block!] "Block to evaluate"
][
    do bind/copy/set body make object! 0
]

check-set: func [
    "Set optional value via set-word or set-path, TRUE unless UNSET!"

    'target [set-word! set-path!]
    value [unset! any-value!]
][
    any-value? set/any target :value
]


library(mongoplyr)

conn <- mongo(db = "mongoplyr_tests", collection = "restaurants")

MongoPipeline() %>%
  match(.borough == "Manhattan" & .cuisine == "Pizza") %>%
  execute(conn) -> pizzaPlacesInManhattan

MongoPipeline() %>%
  group(by = .list(cuisine = .cuisine, borough = .borough), count = .sum(1)) %>%
  execute(conn) -> cuisineFrequencyByBorough

boroughs <- c("Manhattan", "Staten Island", "Bronx", "Queens", "Brooklyn")
getRandomNYBorough <- function()
{
  sample(boroughs, 1)
}

getNYBoroughByIndex <- function(i)
{
	boroughs[[i]]
}

MongoPipeline() %>%
  match(.borough == getRandomNYBorough()) %>%
  execute(conn) -> restaurantsInRandomBorough

MongoPipeline() %>%
  match(.borough == getNYBoroughByIndex(5)) %>%
  execute(conn) -> restaurantsInBrooklynByIndex

Fix tabs/spaces in example file


####### generate .sh script for "git clone"
##### Set git directory structure file path
gitweb<-"https://git.chromium.org/gitweb/?a=project_index"
#####
shell.df<-read.csv(gitweb,header=F)

### save git repository tree in local
write.table(shell.df,"chromium_git_repo_tree.txt",col.names=F,row.names=F,quote=F,append=F)

###generage shell script for "git clone"
shell_top.df<-matrix(c("#!/bin/sh","cd git_repo"),2,1)
write.table(shell_top.df,"git_clone.sh",row.names=F,col.names=F,quote=F,append=F)

shell.df[,1]<-gsub("^(.*)\\.git","git clone https://git\\.chromium\\.org/git/\\1\\.git \\1",shell.df[,1])
write.table(shell.df,"git_clone.sh",row.names=F,col.names=F,quote=F,append=T)

### make directory for git clone
dir.create("git_repo")

##### This scriot is only for The Chromium Project
##### in other(not Chromium) project,
##### run "git clone --recursive ..."
##### and
##### run "ls -aR | grep \.git:$ | sed -e 's/\.\/\(.*\):/\1/' > chromium_git_repo_tree.txt"
##### in top directory

Change git repository list's URL

####### generate .sh script for "git clone"
##### Set git directory structure file path
gitweb<-"http://git.chromium.org/gitweb/?a=project_index"
#####
shell.df<-read.csv(gitweb,header=F)

### save git repository tree in local
write.table(shell.df,"chromium_git_repo_tree.txt",col.names=F,row.names=F,quote=F,append=F)

###generage shell script for "git clone"
shell_top.df<-matrix(c("#!/bin/sh","cd git_repo"),2,1)
write.table(shell_top.df,"git_clone.sh",row.names=F,col.names=F,quote=F,append=F)

shell.df[,1]<-gsub("^(.*)\\.git","git clone https://git\\.chromium\\.org/git/\\1\\.git \\1",shell.df[,1])
write.table(shell.df,"git_clone.sh",row.names=F,col.names=F,quote=F,append=T)

### make directory for git clone
dir.create("git_repo")

##### This scriot is only for The Chromium Project
##### in other(not Chromium) project,
##### run "git clone --recursive ..."
##### and
##### run "ls -aR | grep \.git:$ | sed -e 's/\.\/\(.*\):/\1/' > chromium_git_repo_tree.txt"
##### in top directory


context('Test that modules works with knitr')

check_knitr = function () skip_if_not_installed('knitr')

test_that('modules are found when knitr is not loaded', {
    check_knitr()
    # Ensure knitr isn’t loaded
    unloadNamespace('knitr')
    expect_paths_equal(script_path(), getwd())
})

test_that('modules are found when knitr is loaded', {
    check_knitr()
    loadNamespace('knitr')
    on.exit(unloadNamespace('knitr'))
    expect_paths_equal(script_path(), getwd())
})

test_that('modules are found inside a knitr document', {
    check_knitr()
    on.exit(unloadNamespace('knitr'))

    input = 'support/knitr/doc.rmd'
    # Ensure that a different working directory is used.
    knitr::opts_knit$set(root.dir = getwd())
    output = knitr::knit(input, quiet = TRUE)
    on.exit(unlink(output), add = TRUE)

    expected = '```\n## knitr/a\n```'
    expect_match(paste(readLines(output), collapse = '\n'), expected)
})

Fix test that unloads the knitr package

context('Test that modules works with knitr')

check_knitr = function () skip_if_not_installed('knitr')

safe_unload_namespace = function (ns) {
    users = getNamespaceUsers(ns)
    for (user in users) safe_unload_namespace(user)
    unloadNamespace(ns)
}

test_that('modules are found when knitr is not loaded', {
    check_knitr()
    # Ensure knitr isn’t loaded
    safe_unload_namespace('knitr')
    expect_paths_equal(script_path(), getwd())
})

test_that('modules are found when knitr is loaded', {
    check_knitr()
    loadNamespace('knitr')
    on.exit(safe_unload_namespace('knitr'))
    expect_paths_equal(script_path(), getwd())
})

test_that('modules are found inside a knitr document', {
    check_knitr()
    on.exit(safe_unload_namespace('knitr'))

    input = 'support/knitr/doc.rmd'
    # Ensure that a different working directory is used.
    knitr::opts_knit$set(root.dir = getwd())
    output = knitr::knit(input, quiet = TRUE)
    on.exit(unlink(output), add = TRUE)

    expected = '```\n## knitr/a\n```'
    expect_match(paste(readLines(output), collapse = '\n'), expected)
})