summary refs log tree commit diff stats
path: root/lib
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2014-08-31 15:25:54 +0200
committerAraq <rumpf_a@web.de>2014-08-31 15:25:54 +0200
commit93eb9c456d4195e4296b0f91d27ba0c3e3ab3f33 (patch)
treeb81273414b1b4be68fcf191efda403b4b2c82282 /lib
parentde29ce8ca84d5cbed173abc1324138fc263c4b42 (diff)
downloadNim-93eb9c456d4195e4296b0f91d27ba0c3e3ab3f33.tar.gz
more stdlib modules work
Diffstat (limited to 'lib')
-rw-r--r--lib/pure/md5.nim60
-rw-r--r--lib/pure/parsecsv.nim2
-rw-r--r--lib/pure/redis.nim346
3 files changed, 204 insertions, 204 deletions
diff --git a/lib/pure/md5.nim b/lib/pure/md5.nim
index 322dbbe1d..3b5453957 100644
--- a/lib/pure/md5.nim
+++ b/lib/pure/md5.nim
@@ -84,14 +84,14 @@ proc decode(dest: var openArray[int8], src: openArray[int32]) =
     dest[i+3] = toU8(src[j] shr 24'i32 and 0xff'i32)
     inc(i, 4)
 
-proc transform(Buffer: pointer, State: var MD5State) = 
+proc transform(buffer: pointer, state: var MD5State) = 
   var
     myBlock: MD5Block
-  encode(myBlock, cast[cstring](Buffer))
-  var a = State[0]
-  var b = State[1]
-  var c = State[2]
-  var d = State[3]
+  encode(myBlock, cast[cstring](buffer))
+  var a = state[0]
+  var b = state[1]
+  var c = state[2]
+  var d = state[3]
   FF(a, b, c, d, myBlock[0], 7'i8, 0xD76AA478'i32)
   FF(d, a, b, c, myBlock[1], 12'i8, 0xE8C7B756'i32)
   FF(c, d, a, b, myBlock[2], 17'i8, 0x242070DB'i32)
@@ -156,52 +156,52 @@ proc transform(Buffer: pointer, State: var MD5State) =
   II(d, a, b, c, myBlock[11], 10'i8, 0xBD3AF235'i32)
   II(c, d, a, b, myBlock[2], 15'i8, 0x2AD7D2BB'i32)
   II(b, c, d, a, myBlock[9], 21'i8, 0xEB86D391'i32)
-  State[0] = State[0] +% a
-  State[1] = State[1] +% b
-  State[2] = State[2] +% c
-  State[3] = State[3] +% d
+  state[0] = state[0] +% a
+  state[1] = state[1] +% b
+  state[2] = state[2] +% c
+  state[3] = state[3] +% d
   
 proc md5Init*(c: var MD5Context) = 
   ## initializes a MD5Context  
-  c.State[0] = 0x67452301'i32
-  c.State[1] = 0xEFCDAB89'i32
-  c.State[2] = 0x98BADCFE'i32
-  c.State[3] = 0x10325476'i32
-  c.Count[0] = 0'i32
-  c.Count[1] = 0'i32
-  zeroMem(addr(c.Buffer), sizeof(MD5Buffer))
+  c.state[0] = 0x67452301'i32
+  c.state[1] = 0xEFCDAB89'i32
+  c.state[2] = 0x98BADCFE'i32
+  c.state[3] = 0x10325476'i32
+  c.count[0] = 0'i32
+  c.count[1] = 0'i32
+  zeroMem(addr(c.buffer), sizeof(MD5buffer))
 
 proc md5Update*(c: var MD5Context, input: cstring, len: int) = 
   ## updates the MD5Context with the `input` data of length `len`
   var input = input
   var Index = (c.count[0] shr 3) and 0x3F
-  c.Count[0] = c.count[0] +% toU32(len shl 3)
-  if c.Count[0] < (len shl 3): c.Count[1] = c.count[1] +% 1'i32
-  c.Count[1] = c.count[1] +% toU32(len shr 29)
+  c.count[0] = c.count[0] +% toU32(len shl 3)
+  if c.count[0] < (len shl 3): c.count[1] = c.count[1] +% 1'i32
+  c.count[1] = c.count[1] +% toU32(len shr 29)
   var PartLen = 64 - Index
   if len >= PartLen: 
-    copyMem(addr(c.Buffer[Index]), input, PartLen)
-    transform(addr(c.Buffer), c.State)
+    copyMem(addr(c.buffer[Index]), input, PartLen)
+    transform(addr(c.buffer), c.state)
     var i = PartLen
     while i + 63 < len: 
-      transform(addr(input[i]), c.State)
+      transform(addr(input[i]), c.state)
       inc(i, 64)
-    copyMem(addr(c.Buffer[0]), addr(input[i]), len-i)
+    copyMem(addr(c.buffer[0]), addr(input[i]), len-i)
   else:
-    copyMem(addr(c.Buffer[Index]), addr(input[0]), len)
+    copyMem(addr(c.buffer[Index]), addr(input[0]), len)
 
 proc md5Final*(c: var MD5Context, digest: var MD5Digest) = 
   ## finishes the MD5Context and stores the result in `digest`
   var
     Bits: MD5CBits
     PadLen: int
-  decode(Bits, c.Count)
-  var Index = (c.Count[0] shr 3) and 0x3F
+  decode(Bits, c.count)
+  var Index = (c.count[0] shr 3) and 0x3F
   if Index < 56: PadLen = 56 - Index
   else: PadLen = 120 - Index
   md5Update(c, padding, PadLen)
   md5Update(c, cast[cstring](addr(Bits)), 8)
-  decode(digest, c.State)
+  decode(digest, c.state)
   zeroMem(addr(c), sizeof(MD5Context))
 
 proc toMD5*(s: string): MD5Digest = 
@@ -216,8 +216,8 @@ proc `$`*(D: MD5Digest): string =
   const digits = "0123456789abcdef"
   result = ""
   for i in 0..15: 
-    add(result, Digits[(D[i] shr 4) and 0xF])
-    add(result, Digits[D[i] and 0xF])
+    add(result, digits[(D[i] shr 4) and 0xF])
+    add(result, digits[D[i] and 0xF])
 
 proc getMD5*(s: string): string =  
   ## computes an MD5 value of `s` and returns its string representation
diff --git a/lib/pure/parsecsv.nim b/lib/pure/parsecsv.nim
index c8abdca4f..f4943ed89 100644
--- a/lib/pure/parsecsv.nim
+++ b/lib/pure/parsecsv.nim
@@ -51,7 +51,7 @@ proc raiseEInvalidCsv(filename: string, line, col: int,
   raise e
 
 proc error(my: CsvParser, pos: int, msg: string) =
-  raiseEInvalidCsv(my.filename, my.LineNumber, getColNumber(my, pos), msg)
+  raiseEInvalidCsv(my.filename, my.lineNumber, getColNumber(my, pos), msg)
 
 proc open*(my: var CsvParser, input: Stream, filename: string,
            separator = ',', quote = '"', escape = '\0',
diff --git a/lib/pure/redis.nim b/lib/pure/redis.nim
index ab3b81f37..52d81b3a4 100644
--- a/lib/pure/redis.nim
+++ b/lib/pure/redis.nim
@@ -31,7 +31,7 @@ type
 
 type
   Redis* = object
-    socket: TSocket
+    socket: Socket
     connected: bool
     pipeline: Pipeline
   
@@ -45,7 +45,7 @@ type
 
 {.deprecated: [TSendMode: SendMode, TRedis: Redis, TRedisStatus: RedisStatus,
      TRedisInteger: RedisInteger, TRedisString: RedisString,
-     TRedisList: RedistList, EInvalidReply: ReplyError, ERedis: RedisError].}
+     TRedisList: RedisList, EInvalidReply: ReplyError, ERedis: RedisError].}
 
 proc newPipeline(): Pipeline =
   new(result)
@@ -56,8 +56,8 @@ proc newPipeline(): Pipeline =
 proc open*(host = "localhost", port = 6379.Port): Redis =
   ## Opens a connection to the redis server.
   result.socket = socket(buffered = false)
-  if result.socket == InvalidSocket:
-    OSError(OSLastError())
+  if result.socket == invalidSocket:
+    raiseOSError(osLastError())
   result.socket.connect(host, port)
   result.pipeline = newPipeline()  
 
@@ -68,9 +68,9 @@ proc raiseInvalidReply(expected, got: char) =
 
 proc raiseNoOK(status: string, pipelineEnabled: bool) =
   if pipelineEnabled and not (status == "QUEUED" or status == "PIPELINED"):
-    raise newException(EInvalidReply, "Expected \"QUEUED\" or \"PIPELINED\" got \"$1\"" % status)
+    raise newException(ReplyError, "Expected \"QUEUED\" or \"PIPELINED\" got \"$1\"" % status)
   elif not pipelineEnabled and status != "OK":
-    raise newException(EInvalidReply, "Expected \"OK\" got \"$1\"" % status)
+    raise newException(ReplyError, "Expected \"OK\" got \"$1\"" % status)
 
 template readSocket(r: Redis, dummyVal:expr): stmt =
   var line {.inject.}: TaintedString = ""
@@ -84,75 +84,75 @@ proc parseStatus(r: Redis, line: string = ""): RedisStatus =
     return "PIPELINED"
 
   if line == "":
-    raise newException(ERedis, "Server closed connection prematurely")
+    raise newException(RedisError, "Server closed connection prematurely")
 
   if line[0] == '-':
-    raise newException(ERedis, strip(line))
+    raise newException(RedisError, strip(line))
   if line[0] != '+':
     raiseInvalidReply('+', line[0])
   
   return line.substr(1) # Strip '+'
 
-proc readStatus(r:TRedis): TRedisStatus =
+proc readStatus(r:Redis): RedisStatus =
   r.readSocket("PIPELINED")
   return r.parseStatus(line)
  
-proc parseInteger(r: TRedis, line: string = ""): TRedisInteger =
+proc parseInteger(r: Redis, line: string = ""): RedisInteger =
   if r.pipeline.enabled: return -1
   
   #if line == "+QUEUED":  # inside of multi
   #  return -1
 
   if line == "":
-    raise newException(ERedis, "Server closed connection prematurely")
+    raise newException(RedisError, "Server closed connection prematurely")
 
   if line[0] == '-':
-    raise newException(ERedis, strip(line))
+    raise newException(RedisError, strip(line))
   if line[0] != ':':
     raiseInvalidReply(':', line[0])
   
   # Strip ':'
   if parseBiggestInt(line, result, 1) == 0:
-    raise newException(EInvalidReply, "Unable to parse integer.") 
+    raise newException(ReplyError, "Unable to parse integer.") 
 
-proc readInteger(r: TRedis): TRedisInteger =
+proc readInteger(r: Redis): RedisInteger =
   r.readSocket(-1)
   return r.parseInteger(line)
 
-proc recv(sock: TSocket, size: int): TaintedString =
+proc recv(sock: Socket, size: int): TaintedString =
   result = newString(size).TaintedString
   if sock.recv(cstring(result), size) != size:
-    raise newException(EInvalidReply, "recv failed")
+    raise newException(ReplyError, "recv failed")
 
-proc parseSingleString(r: TRedis, line:string, allowMBNil = False): TRedisString =
+proc parseSingleString(r: Redis, line:string, allowMBNil = false): RedisString =
   if r.pipeline.enabled: return ""
   
   # Error.
   if line[0] == '-':
-    raise newException(ERedis, strip(line))
+    raise newException(RedisError, strip(line))
   
   # Some commands return a /bulk/ value or a /multi-bulk/ nil. Odd.
   if allowMBNil:
     if line == "*-1":
-       return RedisNil
+       return redisNil
   
   if line[0] != '$':
     raiseInvalidReply('$', line[0])
   
   var numBytes = parseInt(line.substr(1))
   if numBytes == -1:
-    return RedisNil
+    return redisNil
 
   var s = r.socket.recv(numBytes+2)
   result = strip(s.string)
 
-proc readSingleString(r: TRedis): TRedisString =
+proc readSingleString(r: Redis): RedisString =
   r.readSocket("")
   return r.parseSingleString(line)
 
-proc readNext(r: TRedis): TRedisList
+proc readNext(r: Redis): RedisList
 
-proc parseArrayLines(r: TRedis, countLine:string): TRedisList =
+proc parseArrayLines(r: Redis, countLine:string): RedisList =
   if countLine.string[0] != '*':
     raiseInvalidReply('*', countLine.string[0])
 
@@ -166,24 +166,24 @@ proc parseArrayLines(r: TRedis, countLine:string): TRedisList =
       for item in parsed:
         result.add(item)
 
-proc readArrayLines(r: TRedis): TRedisList =
+proc readArrayLines(r: Redis): RedisList =
   r.readSocket(nil)
   return r.parseArrayLines(line)  
 
-proc parseBulkString(r: TRedis, allowMBNil = False, line:string = ""): TRedisString =
+proc parseBulkString(r: Redis, allowMBNil = false, line:string = ""): RedisString =
   if r.pipeline.enabled: return ""
 
   return r.parseSingleString(line, allowMBNil)
 
-proc readBulkString(r: TRedis, allowMBNil = false): TRedisString =
+proc readBulkString(r: Redis, allowMBNil = false): RedisString =
   r.readSocket("")
   return r.parseBulkString(allowMBNil, line)
 
-proc readArray(r: TRedis): TRedisList =
+proc readArray(r: Redis): RedisList =
   r.readSocket(@[])
   return r.parseArrayLines(line)
 
-proc readNext(r: TRedis): TRedisList =
+proc readNext(r: Redis): RedisList =
   r.readSocket(@[])
 
   var res = case line[0]
@@ -192,12 +192,12 @@ proc readNext(r: TRedis): TRedisList =
     of '$': @[r.parseBulkString(true,line)]
     of '*': r.parseArrayLines(line)
     else: 
-      raise newException(EInvalidReply, "readNext failed on line: " & line)
+      raise newException(ReplyError, "readNext failed on line: " & line)
       nil
   r.pipeline.expected -= 1
   return res
 
-proc flushPipeline*(r: TRedis, wasMulti = false): TRedisList =
+proc flushPipeline*(r: Redis, wasMulti = false): RedisList =
   ## Send buffered commands, clear buffer, return results
   if r.pipeline.buffer.len > 0:
     r.socket.send(r.pipeline.buffer)
@@ -216,7 +216,7 @@ proc flushPipeline*(r: TRedis, wasMulti = false): TRedisList =
 
   r.pipeline.expected = 0
 
-proc startPipelining*(r: TRedis) =
+proc startPipelining*(r: Redis) =
   ## Enable command pipelining (reduces network roundtrips).
   ## Note that when enabled, you must call flushPipeline to actually send commands, except
   ## for multi/exec() which enable and flush the pipeline automatically.
@@ -225,7 +225,7 @@ proc startPipelining*(r: TRedis) =
   r.pipeline.expected = 0
   r.pipeline.enabled = true
 
-proc sendCommand(r: TRedis, cmd: string, args: varargs[string]) =
+proc sendCommand(r: Redis, cmd: string, args: varargs[string]) =
   var request = "*" & $(1 + args.len()) & "\c\L"
   request.add("$" & $cmd.len() & "\c\L")
   request.add(cmd & "\c\L")
@@ -239,7 +239,7 @@ proc sendCommand(r: TRedis, cmd: string, args: varargs[string]) =
   else:
     r.socket.send(request)
 
-proc sendCommand(r: TRedis, cmd: string, arg1: string,
+proc sendCommand(r: Redis, cmd: string, arg1: string,
                  args: varargs[string]) =
   var request = "*" & $(2 + args.len()) & "\c\L"
   request.add("$" & $cmd.len() & "\c\L")
@@ -258,68 +258,68 @@ proc sendCommand(r: TRedis, cmd: string, arg1: string,
 
 # Keys
 
-proc del*(r: TRedis, keys: varargs[string]): TRedisInteger =
+proc del*(r: Redis, keys: varargs[string]): RedisInteger =
   ## Delete a key or multiple keys
   r.sendCommand("DEL", keys)
   return r.readInteger()
 
-proc exists*(r: TRedis, key: string): bool =
+proc exists*(r: Redis, key: string): bool =
   ## Determine if a key exists
   r.sendCommand("EXISTS", key)
   return r.readInteger() == 1
 
-proc expire*(r: TRedis, key: string, seconds: int): bool =
+proc expire*(r: Redis, key: string, seconds: int): bool =
   ## Set a key's time to live in seconds. Returns `false` if the key could
   ## not be found or the timeout could not be set.
   r.sendCommand("EXPIRE", key, $seconds)
   return r.readInteger() == 1
 
-proc expireAt*(r: TRedis, key: string, timestamp: int): bool =
+proc expireAt*(r: Redis, key: string, timestamp: int): bool =
   ## Set the expiration for a key as a UNIX timestamp. Returns `false` 
   ## if the key could not be found or the timeout could not be set.
   r.sendCommand("EXPIREAT", key, $timestamp)
   return r.readInteger() == 1
 
-proc keys*(r: TRedis, pattern: string): TRedisList =
+proc keys*(r: Redis, pattern: string): RedisList =
   ## Find all keys matching the given pattern
   r.sendCommand("KEYS", pattern)
   return r.readArray()
 
-proc move*(r: TRedis, key: string, db: int): bool =
+proc move*(r: Redis, key: string, db: int): bool =
   ## Move a key to another database. Returns `true` on a successful move.
   r.sendCommand("MOVE", key, $db)
   return r.readInteger() == 1
 
-proc persist*(r: TRedis, key: string): bool =
+proc persist*(r: Redis, key: string): bool =
   ## Remove the expiration from a key. 
   ## Returns `true` when the timeout was removed.
   r.sendCommand("PERSIST", key)
   return r.readInteger() == 1
   
-proc randomKey*(r: TRedis): TRedisString =
+proc randomKey*(r: Redis): RedisString =
   ## Return a random key from the keyspace
   r.sendCommand("RANDOMKEY")
   return r.readBulkString()
 
-proc rename*(r: TRedis, key, newkey: string): TRedisStatus =
+proc rename*(r: Redis, key, newkey: string): RedisStatus =
   ## Rename a key.
   ## 
   ## **WARNING:** Overwrites `newkey` if it exists!
   r.sendCommand("RENAME", key, newkey)
   raiseNoOK(r.readStatus(), r.pipeline.enabled)
   
-proc renameNX*(r: TRedis, key, newkey: string): bool =
+proc renameNX*(r: Redis, key, newkey: string): bool =
   ## Same as ``rename`` but doesn't continue if `newkey` exists.
   ## Returns `true` if key was renamed.
   r.sendCommand("RENAMENX", key, newkey)
   return r.readInteger() == 1
 
-proc ttl*(r: TRedis, key: string): TRedisInteger =
+proc ttl*(r: Redis, key: string): RedisInteger =
   ## Get the time to live for a key
   r.sendCommand("TTL", key)
   return r.readInteger()
   
-proc keyType*(r: TRedis, key: string): TRedisStatus =
+proc keyType*(r: Redis, key: string): RedisStatus =
   ## Determine the type stored at key
   r.sendCommand("TYPE", key)
   return r.readStatus()
@@ -327,131 +327,131 @@ proc keyType*(r: TRedis, key: string): TRedisStatus =
 
 # Strings
 
-proc append*(r: TRedis, key, value: string): TRedisInteger =
+proc append*(r: Redis, key, value: string): RedisInteger =
   ## Append a value to a key
   r.sendCommand("APPEND", key, value)
   return r.readInteger()
 
-proc decr*(r: TRedis, key: string): TRedisInteger =
+proc decr*(r: Redis, key: string): RedisInteger =
   ## Decrement the integer value of a key by one
   r.sendCommand("DECR", key)
   return r.readInteger()
   
-proc decrBy*(r: TRedis, key: string, decrement: int): TRedisInteger =
+proc decrBy*(r: Redis, key: string, decrement: int): RedisInteger =
   ## Decrement the integer value of a key by the given number
   r.sendCommand("DECRBY", key, $decrement)
   return r.readInteger()
   
-proc get*(r: TRedis, key: string): TRedisString =
+proc get*(r: Redis, key: string): RedisString =
   ## Get the value of a key. Returns `redisNil` when `key` doesn't exist.
   r.sendCommand("GET", key)
   return r.readBulkString()
 
-proc getBit*(r: TRedis, key: string, offset: int): TRedisInteger =
+proc getBit*(r: Redis, key: string, offset: int): RedisInteger =
   ## Returns the bit value at offset in the string value stored at key
   r.sendCommand("GETBIT", key, $offset)
   return r.readInteger()
 
-proc getRange*(r: TRedis, key: string, start, stop: int): TRedisString =
+proc getRange*(r: Redis, key: string, start, stop: int): RedisString =
   ## Get a substring of the string stored at a key
   r.sendCommand("GETRANGE", key, $start, $stop)
   return r.readBulkString()
 
-proc getSet*(r: TRedis, key: string, value: string): TRedisString =
+proc getSet*(r: Redis, key: string, value: string): RedisString =
   ## Set the string value of a key and return its old value. Returns `redisNil`
   ## when key doesn't exist.
   r.sendCommand("GETSET", key, value)
   return r.readBulkString()
 
-proc incr*(r: TRedis, key: string): TRedisInteger =
+proc incr*(r: Redis, key: string): RedisInteger =
   ## Increment the integer value of a key by one.
   r.sendCommand("INCR", key)
   return r.readInteger()
 
-proc incrBy*(r: TRedis, key: string, increment: int): TRedisInteger =
+proc incrBy*(r: Redis, key: string, increment: int): RedisInteger =
   ## Increment the integer value of a key by the given number
   r.sendCommand("INCRBY", key, $increment)
   return r.readInteger()
 
-proc setk*(r: TRedis, key, value: string) = 
+proc setk*(r: Redis, key, value: string) = 
   ## Set the string value of a key.
   ##
   ## NOTE: This function had to be renamed due to a clash with the `set` type.
   r.sendCommand("SET", key, value)
   raiseNoOK(r.readStatus(), r.pipeline.enabled)
 
-proc setNX*(r: TRedis, key, value: string): bool =
+proc setNX*(r: Redis, key, value: string): bool =
   ## Set the value of a key, only if the key does not exist. Returns `true`
   ## if the key was set.
   r.sendCommand("SETNX", key, value)
   return r.readInteger() == 1
 
-proc setBit*(r: TRedis, key: string, offset: int, 
-             value: string): TRedisInteger =
+proc setBit*(r: Redis, key: string, offset: int, 
+             value: string): RedisInteger =
   ## Sets or clears the bit at offset in the string value stored at key
   r.sendCommand("SETBIT", key, $offset, value)
   return r.readInteger()
   
-proc setEx*(r: TRedis, key: string, seconds: int, value: string): TRedisStatus =
+proc setEx*(r: Redis, key: string, seconds: int, value: string): RedisStatus =
   ## Set the value and expiration of a key
   r.sendCommand("SETEX", key, $seconds, value)
   raiseNoOK(r.readStatus(), r.pipeline.enabled)
 
-proc setRange*(r: TRedis, key: string, offset: int, 
-               value: string): TRedisInteger =
+proc setRange*(r: Redis, key: string, offset: int, 
+               value: string): RedisInteger =
   ## Overwrite part of a string at key starting at the specified offset
   r.sendCommand("SETRANGE", key, $offset, value)
   return r.readInteger()
 
-proc strlen*(r: TRedis, key: string): TRedisInteger =
+proc strlen*(r: Redis, key: string): RedisInteger =
   ## Get the length of the value stored in a key. Returns 0 when key doesn't
   ## exist.
   r.sendCommand("STRLEN", key)
   return r.readInteger()
 
 # Hashes
-proc hDel*(r: TRedis, key, field: string): bool =
+proc hDel*(r: Redis, key, field: string): bool =
   ## Delete a hash field at `key`. Returns `true` if the field was removed.
   r.sendCommand("HDEL", key, field)
   return r.readInteger() == 1
 
-proc hExists*(r: TRedis, key, field: string): bool =
+proc hExists*(r: Redis, key, field: string): bool =
   ## Determine if a hash field exists.
   r.sendCommand("HEXISTS", key, field)
   return r.readInteger() == 1
 
-proc hGet*(r: TRedis, key, field: string): TRedisString =
+proc hGet*(r: Redis, key, field: string): RedisString =
   ## Get the value of a hash field
   r.sendCommand("HGET", key, field)
   return r.readBulkString()
 
-proc hGetAll*(r: TRedis, key: string): TRedisList =
+proc hGetAll*(r: Redis, key: string): RedisList =
   ## Get all the fields and values in a hash
   r.sendCommand("HGETALL", key)
   return r.readArray()
 
-proc hIncrBy*(r: TRedis, key, field: string, incr: int): TRedisInteger =
+proc hIncrBy*(r: Redis, key, field: string, incr: int): RedisInteger =
   ## Increment the integer value of a hash field by the given number
   r.sendCommand("HINCRBY", key, field, $incr)
   return r.readInteger()
 
-proc hKeys*(r: TRedis, key: string): TRedisList =
+proc hKeys*(r: Redis, key: string): RedisList =
   ## Get all the fields in a hash
   r.sendCommand("HKEYS", key)
   return r.readArray()
 
-proc hLen*(r: TRedis, key: string): TRedisInteger =
+proc hLen*(r: Redis, key: string): RedisInteger =
   ## Get the number of fields in a hash
   r.sendCommand("HLEN", key)
   return r.readInteger()
 
-proc hMGet*(r: TRedis, key: string, fields: varargs[string]): TRedisList =
+proc hMGet*(r: Redis, key: string, fields: varargs[string]): RedisList =
   ## Get the values of all the given hash fields
   r.sendCommand("HMGET", key, fields)
   return r.readArray()
 
-proc hMSet*(r: TRedis, key: string, 
-            fieldValues: openarray[tuple[field, value: string]]) =
+proc hMSet*(r: Redis, key: string, 
+            fieldValues: openArray[tuple[field, value: string]]) =
   ## Set multiple hash fields to multiple values
   var args = @[key]
   for field, value in items(fieldValues):
@@ -460,24 +460,24 @@ proc hMSet*(r: TRedis, key: string,
   r.sendCommand("HMSET", args)
   raiseNoOK(r.readStatus(), r.pipeline.enabled)
 
-proc hSet*(r: TRedis, key, field, value: string): TRedisInteger =
+proc hSet*(r: Redis, key, field, value: string): RedisInteger =
   ## Set the string value of a hash field
   r.sendCommand("HSET", key, field, value)
   return r.readInteger()
   
-proc hSetNX*(r: TRedis, key, field, value: string): TRedisInteger =
+proc hSetNX*(r: Redis, key, field, value: string): RedisInteger =
   ## Set the value of a hash field, only if the field does **not** exist
   r.sendCommand("HSETNX", key, field, value)
   return r.readInteger()
 
-proc hVals*(r: TRedis, key: string): TRedisList =
+proc hVals*(r: Redis, key: string): RedisList =
   ## Get all the values in a hash
   r.sendCommand("HVALS", key)
   return r.readArray()
   
 # Lists
 
-proc bLPop*(r: TRedis, keys: varargs[string], timeout: int): TRedisList =
+proc bLPop*(r: Redis, keys: varargs[string], timeout: int): RedisList =
   ## Remove and get the *first* element in a list, or block until 
   ## one is available
   var args: seq[string] = @[]
@@ -486,7 +486,7 @@ proc bLPop*(r: TRedis, keys: varargs[string], timeout: int): TRedisList =
   r.sendCommand("BLPOP", args)
   return r.readArray()
 
-proc bRPop*(r: TRedis, keys: varargs[string], timeout: int): TRedisList =
+proc bRPop*(r: Redis, keys: varargs[string], timeout: int): RedisList =
   ## Remove and get the *last* element in a list, or block until one 
   ## is available.
   var args: seq[string] = @[]
@@ -495,8 +495,8 @@ proc bRPop*(r: TRedis, keys: varargs[string], timeout: int): TRedisList =
   r.sendCommand("BRPOP", args)
   return r.readArray()
 
-proc bRPopLPush*(r: TRedis, source, destination: string,
-                 timeout: int): TRedisString =
+proc bRPopLPush*(r: Redis, source, destination: string,
+                 timeout: int): RedisString =
   ## Pop a value from a list, push it to another list and return it; or
   ## block until one is available.
   ##
@@ -504,32 +504,32 @@ proc bRPopLPush*(r: TRedis, source, destination: string,
   r.sendCommand("BRPOPLPUSH", source, destination, $timeout)
   return r.readBulkString(true) # Multi-Bulk nil allowed.
 
-proc lIndex*(r: TRedis, key: string, index: int): TRedisString =
+proc lIndex*(r: Redis, key: string, index: int): RedisString =
   ## Get an element from a list by its index
   r.sendCommand("LINDEX", key, $index)
   return r.readBulkString()
 
-proc lInsert*(r: TRedis, key: string, before: bool, pivot, value: string):
-              TRedisInteger =
+proc lInsert*(r: Redis, key: string, before: bool, pivot, value: string):
+              RedisInteger =
   ## Insert an element before or after another element in a list
   var pos = if before: "BEFORE" else: "AFTER"
   r.sendCommand("LINSERT", key, pos, pivot, value)
   return r.readInteger()
   
-proc lLen*(r: TRedis, key: string): TRedisInteger =
+proc lLen*(r: Redis, key: string): RedisInteger =
   ## Get the length of a list
   r.sendCommand("LLEN", key)
   return r.readInteger()
 
-proc lPop*(r: TRedis, key: string): TRedisString =
+proc lPop*(r: Redis, key: string): RedisString =
   ## Remove and get the first element in a list
   r.sendCommand("LPOP", key)
   return r.readBulkString()
 
-proc lPush*(r: TRedis, key, value: string, create: bool = True): TRedisInteger =
+proc lPush*(r: Redis, key, value: string, create: bool = true): RedisInteger =
   ## Prepend a value to a list. Returns the length of the list after the push.
   ## The ``create`` param specifies whether a list should be created if it
-  ## doesn't exist at ``key``. More specifically if ``create`` is True, `LPUSH` 
+  ## doesn't exist at ``key``. More specifically if ``create`` is true, `LPUSH` 
   ## will be used, otherwise `LPUSHX`.
   if create:
     r.sendCommand("LPUSH", key, value)
@@ -537,42 +537,42 @@ proc lPush*(r: TRedis, key, value: string, create: bool = True): TRedisInteger =
     r.sendCommand("LPUSHX", key, value)
   return r.readInteger()
 
-proc lRange*(r: TRedis, key: string, start, stop: int): TRedisList =
+proc lRange*(r: Redis, key: string, start, stop: int): RedisList =
   ## Get a range of elements from a list. Returns `nil` when `key` 
   ## doesn't exist.
   r.sendCommand("LRANGE", key, $start, $stop)
   return r.readArray()
 
-proc lRem*(r: TRedis, key: string, value: string, count: int = 0): TRedisInteger =
+proc lRem*(r: Redis, key: string, value: string, count: int = 0): RedisInteger =
   ## Remove elements from a list. Returns the number of elements that have been
   ## removed.
   r.sendCommand("LREM", key, $count, value)
   return r.readInteger()
 
-proc lSet*(r: TRedis, key: string, index: int, value: string) =
+proc lSet*(r: Redis, key: string, index: int, value: string) =
   ## Set the value of an element in a list by its index
   r.sendCommand("LSET", key, $index, value)
   raiseNoOK(r.readStatus(), r.pipeline.enabled)
 
-proc lTrim*(r: TRedis, key: string, start, stop: int)  =
+proc lTrim*(r: Redis, key: string, start, stop: int)  =
   ## Trim a list to the specified range
   r.sendCommand("LTRIM", key, $start, $stop)
   raiseNoOK(r.readStatus(), r.pipeline.enabled)
 
-proc rPop*(r: TRedis, key: string): TRedisString =
+proc rPop*(r: Redis, key: string): RedisString =
   ## Remove and get the last element in a list
   r.sendCommand("RPOP", key)
   return r.readBulkString()
   
-proc rPopLPush*(r: TRedis, source, destination: string): TRedisString =
+proc rPopLPush*(r: Redis, source, destination: string): RedisString =
   ## Remove the last element in a list, append it to another list and return it
   r.sendCommand("RPOPLPUSH", source, destination)
   return r.readBulkString()
   
-proc rPush*(r: TRedis, key, value: string, create: bool = True): TRedisInteger =
+proc rPush*(r: Redis, key, value: string, create: bool = true): RedisInteger =
   ## Append a value to a list. Returns the length of the list after the push.
   ## The ``create`` param specifies whether a list should be created if it
-  ## doesn't exist at ``key``. More specifically if ``create`` is True, `RPUSH` 
+  ## doesn't exist at ``key``. More specifically if ``create`` is true, `RPUSH` 
   ## will be used, otherwise `RPUSHX`.
   if create:
     r.sendCommand("RPUSH", key, value)
@@ -582,106 +582,106 @@ proc rPush*(r: TRedis, key, value: string, create: bool = True): TRedisInteger =
 
 # Sets
 
-proc sadd*(r: TRedis, key: string, member: string): TRedisInteger =
+proc sadd*(r: Redis, key: string, member: string): RedisInteger =
   ## Add a member to a set
   r.sendCommand("SADD", key, member)
   return r.readInteger()
 
-proc scard*(r: TRedis, key: string): TRedisInteger =
+proc scard*(r: Redis, key: string): RedisInteger =
   ## Get the number of members in a set
   r.sendCommand("SCARD", key)
   return r.readInteger()
 
-proc sdiff*(r: TRedis, keys: varargs[string]): TRedisList =
+proc sdiff*(r: Redis, keys: varargs[string]): RedisList =
   ## Subtract multiple sets
   r.sendCommand("SDIFF", keys)
   return r.readArray()
 
-proc sdiffstore*(r: TRedis, destination: string,
-                keys: varargs[string]): TRedisInteger =
+proc sdiffstore*(r: Redis, destination: string,
+                keys: varargs[string]): RedisInteger =
   ## Subtract multiple sets and store the resulting set in a key
   r.sendCommand("SDIFFSTORE", destination, keys)
   return r.readInteger()
 
-proc sinter*(r: TRedis, keys: varargs[string]): TRedisList =
+proc sinter*(r: Redis, keys: varargs[string]): RedisList =
   ## Intersect multiple sets
   r.sendCommand("SINTER", keys)
   return r.readArray()
 
-proc sinterstore*(r: TRedis, destination: string,
-                 keys: varargs[string]): TRedisInteger =
+proc sinterstore*(r: Redis, destination: string,
+                 keys: varargs[string]): RedisInteger =
   ## Intersect multiple sets and store the resulting set in a key
   r.sendCommand("SINTERSTORE", destination, keys)
   return r.readInteger()
 
-proc sismember*(r: TRedis, key: string, member: string): TRedisInteger =
+proc sismember*(r: Redis, key: string, member: string): RedisInteger =
   ## Determine if a given value is a member of a set
   r.sendCommand("SISMEMBER", key, member)
   return r.readInteger()
 
-proc smembers*(r: TRedis, key: string): TRedisList =
+proc smembers*(r: Redis, key: string): RedisList =
   ## Get all the members in a set
   r.sendCommand("SMEMBERS", key)
   return r.readArray()
 
-proc smove*(r: TRedis, source: string, destination: string,
-           member: string): TRedisInteger =
+proc smove*(r: Redis, source: string, destination: string,
+           member: string): RedisInteger =
   ## Move a member from one set to another
   r.sendCommand("SMOVE", source, destination, member)
   return r.readInteger()
 
-proc spop*(r: TRedis, key: string): TRedisString =
+proc spop*(r: Redis, key: string): RedisString =
   ## Remove and return a random member from a set
   r.sendCommand("SPOP", key)
   return r.readBulkString()
 
-proc srandmember*(r: TRedis, key: string): TRedisString =
+proc srandmember*(r: Redis, key: string): RedisString =
   ## Get a random member from a set
   r.sendCommand("SRANDMEMBER", key)
   return r.readBulkString()
 
-proc srem*(r: TRedis, key: string, member: string): TRedisInteger =
+proc srem*(r: Redis, key: string, member: string): RedisInteger =
   ## Remove a member from a set
   r.sendCommand("SREM", key, member)
   return r.readInteger()
 
-proc sunion*(r: TRedis, keys: varargs[string]): TRedisList =
+proc sunion*(r: Redis, keys: varargs[string]): RedisList =
   ## Add multiple sets
   r.sendCommand("SUNION", keys)
   return r.readArray()
 
-proc sunionstore*(r: TRedis, destination: string,
-                 key: varargs[string]): TRedisInteger =
+proc sunionstore*(r: Redis, destination: string,
+                 key: varargs[string]): RedisInteger =
   ## Add multiple sets and store the resulting set in a key 
   r.sendCommand("SUNIONSTORE", destination, key)
   return r.readInteger()
 
 # Sorted sets
 
-proc zadd*(r: TRedis, key: string, score: int, member: string): TRedisInteger =
+proc zadd*(r: Redis, key: string, score: int, member: string): RedisInteger =
   ## Add a member to a sorted set, or update its score if it already exists
   r.sendCommand("ZADD", key, $score, member)
   return r.readInteger()
 
-proc zcard*(r: TRedis, key: string): TRedisInteger =
+proc zcard*(r: Redis, key: string): RedisInteger =
   ## Get the number of members in a sorted set
   r.sendCommand("ZCARD", key)
   return r.readInteger()
 
-proc zcount*(r: TRedis, key: string, min: string, max: string): TRedisInteger =
+proc zcount*(r: Redis, key: string, min: string, max: string): RedisInteger =
   ## Count the members in a sorted set with scores within the given values
   r.sendCommand("ZCOUNT", key, min, max)
   return r.readInteger()
 
-proc zincrby*(r: TRedis, key: string, increment: string,
-             member: string): TRedisString =
+proc zincrby*(r: Redis, key: string, increment: string,
+             member: string): RedisString =
   ## Increment the score of a member in a sorted set
   r.sendCommand("ZINCRBY", key, increment, member)
   return r.readBulkString()
 
-proc zinterstore*(r: TRedis, destination: string, numkeys: string,
-                 keys: openarray[string], weights: openarray[string] = [],
-                 aggregate: string = ""): TRedisInteger =
+proc zinterstore*(r: Redis, destination: string, numkeys: string,
+                 keys: openArray[string], weights: openArray[string] = [],
+                 aggregate: string = ""): RedisInteger =
   ## Intersect multiple sorted sets and store the resulting sorted set in
   ## a new key
   var args = @[destination, numkeys]
@@ -698,8 +698,8 @@ proc zinterstore*(r: TRedis, destination: string, numkeys: string,
   
   return r.readInteger()
 
-proc zrange*(r: TRedis, key: string, start: string, stop: string,
-            withScores: bool): TRedisList =
+proc zrange*(r: Redis, key: string, start: string, stop: string,
+            withScores: bool): RedisList =
   ## Return a range of members in a sorted set, by index
   if not withScores:
     r.sendCommand("ZRANGE", key, start, stop)
@@ -707,9 +707,9 @@ proc zrange*(r: TRedis, key: string, start: string, stop: string,
     r.sendCommand("ZRANGE", "WITHSCORES", key, start, stop)
   return r.readArray()
 
-proc zrangebyscore*(r: TRedis, key: string, min: string, max: string, 
-                   withScore: bool = false, limit: bool = False,
-                   limitOffset: int = 0, limitCount: int = 0): TRedisList =
+proc zrangebyscore*(r: Redis, key: string, min: string, max: string, 
+                   withScore: bool = false, limit: bool = false,
+                   limitOffset: int = 0, limitCount: int = 0): RedisList =
   ## Return a range of members in a sorted set, by score
   var args = @[key, min, max]
   
@@ -722,30 +722,30 @@ proc zrangebyscore*(r: TRedis, key: string, min: string, max: string,
   r.sendCommand("ZRANGEBYSCORE", args)
   return r.readArray()
 
-proc zrank*(r: TRedis, key: string, member: string): TRedisString =
+proc zrank*(r: Redis, key: string, member: string): RedisString =
   ## Determine the index of a member in a sorted set
   r.sendCommand("ZRANK", key, member)
   return r.readBulkString()
 
-proc zrem*(r: TRedis, key: string, member: string): TRedisInteger =
+proc zrem*(r: Redis, key: string, member: string): RedisInteger =
   ## Remove a member from a sorted set
   r.sendCommand("ZREM", key, member)
   return r.readInteger()
 
-proc zremrangebyrank*(r: TRedis, key: string, start: string,
-                     stop: string): TRedisInteger =
+proc zremrangebyrank*(r: Redis, key: string, start: string,
+                     stop: string): RedisInteger =
   ## Remove all members in a sorted set within the given indexes
   r.sendCommand("ZREMRANGEBYRANK", key, start, stop)
   return r.readInteger()
 
-proc zremrangebyscore*(r: TRedis, key: string, min: string,
-                      max: string): TRedisInteger =
+proc zremrangebyscore*(r: Redis, key: string, min: string,
+                      max: string): RedisInteger =
   ## Remove all members in a sorted set within the given scores
   r.sendCommand("ZREMRANGEBYSCORE", key, min, max)
   return r.readInteger()
 
-proc zrevrange*(r: TRedis, key: string, start: string, stop: string,
-               withScore: bool): TRedisList =
+proc zrevrange*(r: Redis, key: string, start: string, stop: string,
+               withScore: bool): RedisList =
   ## Return a range of members in a sorted set, by index, 
   ## with scores ordered from high to low
   if withScore:
@@ -753,9 +753,9 @@ proc zrevrange*(r: TRedis, key: string, start: string, stop: string,
   else: r.sendCommand("ZREVRANGE", key, start, stop)
   return r.readArray()
 
-proc zrevrangebyscore*(r: TRedis, key: string, min: string, max: string, 
-                   withScore: bool = false, limit: bool = False,
-                   limitOffset: int = 0, limitCount: int = 0): TRedisList =
+proc zrevrangebyscore*(r: Redis, key: string, min: string, max: string, 
+                   withScore: bool = false, limit: bool = false,
+                   limitOffset: int = 0, limitCount: int = 0): RedisList =
   ## Return a range of members in a sorted set, by score, with
   ## scores ordered from high to low
   var args = @[key, min, max]
@@ -769,20 +769,20 @@ proc zrevrangebyscore*(r: TRedis, key: string, min: string, max: string,
   r.sendCommand("ZREVRANGEBYSCORE", args)
   return r.readArray()
 
-proc zrevrank*(r: TRedis, key: string, member: string): TRedisString =
+proc zrevrank*(r: Redis, key: string, member: string): RedisString =
   ## Determine the index of a member in a sorted set, with
   ## scores ordered from high to low
   r.sendCommand("ZREVRANK", key, member)
   return r.readBulkString()
 
-proc zscore*(r: TRedis, key: string, member: string): TRedisString =
+proc zscore*(r: Redis, key: string, member: string): RedisString =
   ## Get the score associated with the given member in a sorted set
   r.sendCommand("ZSCORE", key, member)
   return r.readBulkString()
 
-proc zunionstore*(r: TRedis, destination: string, numkeys: string,
-                 keys: openarray[string], weights: openarray[string] = [],
-                 aggregate: string = ""): TRedisInteger =
+proc zunionstore*(r: Redis, destination: string, numkeys: string,
+                 keys: openArray[string], weights: openArray[string] = [],
+                 aggregate: string = ""): RedisInteger =
   ## Add multiple sorted sets and store the resulting sorted set in a new key 
   var args = @[destination, numkeys]
   for i in items(keys): args.add(i)
@@ -832,12 +832,12 @@ proc unsubscribe*(r: TRedis, [channel: openarray[string], : string): ???? =
 
 # Transactions
 
-proc discardMulti*(r: TRedis) =
+proc discardMulti*(r: Redis) =
   ## Discard all commands issued after MULTI
   r.sendCommand("DISCARD")
   raiseNoOK(r.readStatus(), r.pipeline.enabled)
 
-proc exec*(r: TRedis): TRedisList =
+proc exec*(r: Redis): RedisList =
   ## Execute all commands issued after MULTI
   r.sendCommand("EXEC")  
   r.pipeline.enabled = false
@@ -846,106 +846,106 @@ proc exec*(r: TRedis): TRedisList =
   return r.flushPipeline(true)
   
 
-proc multi*(r: TRedis) =
+proc multi*(r: Redis) =
   ## Mark the start of a transaction block
   r.startPipelining()
   r.sendCommand("MULTI")
   raiseNoOK(r.readStatus(), r.pipeline.enabled)
 
-proc unwatch*(r: TRedis) =
+proc unwatch*(r: Redis) =
   ## Forget about all watched keys
   r.sendCommand("UNWATCH")
   raiseNoOK(r.readStatus(), r.pipeline.enabled)
 
-proc watch*(r: TRedis, key: varargs[string]) =
+proc watch*(r: Redis, key: varargs[string]) =
   ## Watch the given keys to determine execution of the MULTI/EXEC block 
   r.sendCommand("WATCH", key)
   raiseNoOK(r.readStatus(), r.pipeline.enabled)
 
 # Connection
 
-proc auth*(r: TRedis, password: string) =
+proc auth*(r: Redis, password: string) =
   ## Authenticate to the server
   r.sendCommand("AUTH", password)
   raiseNoOK(r.readStatus(), r.pipeline.enabled)
 
-proc echoServ*(r: TRedis, message: string): TRedisString =
+proc echoServ*(r: Redis, message: string): RedisString =
   ## Echo the given string
   r.sendCommand("ECHO", message)
   return r.readBulkString()
 
-proc ping*(r: TRedis): TRedisStatus =
+proc ping*(r: Redis): RedisStatus =
   ## Ping the server
   r.sendCommand("PING")
   return r.readStatus()
 
-proc quit*(r: TRedis) =
+proc quit*(r: Redis) =
   ## Close the connection
   r.sendCommand("QUIT")
   raiseNoOK(r.readStatus(), r.pipeline.enabled)
 
-proc select*(r: TRedis, index: int): TRedisStatus =
+proc select*(r: Redis, index: int): RedisStatus =
   ## Change the selected database for the current connection 
   r.sendCommand("SELECT", $index)
   return r.readStatus()
 
 # Server
 
-proc bgrewriteaof*(r: TRedis) =
+proc bgrewriteaof*(r: Redis) =
   ## Asynchronously rewrite the append-only file
   r.sendCommand("BGREWRITEAOF")
   raiseNoOK(r.readStatus(), r.pipeline.enabled)
 
-proc bgsave*(r: TRedis) =
+proc bgsave*(r: Redis) =
   ## Asynchronously save the dataset to disk
   r.sendCommand("BGSAVE")
   raiseNoOK(r.readStatus(), r.pipeline.enabled)
 
-proc configGet*(r: TRedis, parameter: string): TRedisList =
+proc configGet*(r: Redis, parameter: string): RedisList =
   ## Get the value of a configuration parameter
   r.sendCommand("CONFIG", "GET", parameter)
   return r.readArray()
 
-proc configSet*(r: TRedis, parameter: string, value: string) =
+proc configSet*(r: Redis, parameter: string, value: string) =
   ## Set a configuration parameter to the given value
   r.sendCommand("CONFIG", "SET", parameter, value)
   raiseNoOK(r.readStatus(), r.pipeline.enabled)
 
-proc configResetStat*(r: TRedis) =
+proc configResetStat*(r: Redis) =
   ## Reset the stats returned by INFO
   r.sendCommand("CONFIG", "RESETSTAT")
   raiseNoOK(r.readStatus(), r.pipeline.enabled)
 
-proc dbsize*(r: TRedis): TRedisInteger =
+proc dbsize*(r: Redis): RedisInteger =
   ## Return the number of keys in the selected database
   r.sendCommand("DBSIZE")
   return r.readInteger()
 
-proc debugObject*(r: TRedis, key: string): TRedisStatus =
+proc debugObject*(r: Redis, key: string): RedisStatus =
   ## Get debugging information about a key
   r.sendCommand("DEBUG", "OBJECT", key)
   return r.readStatus()
 
-proc debugSegfault*(r: TRedis) =
+proc debugSegfault*(r: Redis) =
   ## Make the server crash
   r.sendCommand("DEBUG", "SEGFAULT")
 
-proc flushall*(r: TRedis): TRedisStatus =
+proc flushall*(r: Redis): RedisStatus =
   ## Remove all keys from all databases
   r.sendCommand("FLUSHALL")
   raiseNoOK(r.readStatus(), r.pipeline.enabled)
 
-proc flushdb*(r: TRedis): TRedisStatus =
+proc flushdb*(r: Redis): RedisStatus =
   ## Remove all keys from the current database
   r.sendCommand("FLUSHDB")
   raiseNoOK(r.readStatus(), r.pipeline.enabled)
 
-proc info*(r: TRedis): TRedisString =
+proc info*(r: Redis): RedisString =
   ## Get information and statistics about the server
   r.sendCommand("INFO")
   return r.readBulkString()
 
-proc lastsave*(r: TRedis): TRedisInteger =
+proc lastsave*(r: Redis): RedisInteger =
   ## Get the UNIX time stamp of the last successful save to disk
   r.sendCommand("LASTSAVE")
   return r.readInteger()
@@ -957,24 +957,24 @@ proc monitor*(r: TRedis) =
   raiseNoOK(r.readStatus(), r.pipeline.enabled)
 """
 
-proc save*(r: TRedis) =
+proc save*(r: Redis) =
   ## Synchronously save the dataset to disk
   r.sendCommand("SAVE")
   raiseNoOK(r.readStatus(), r.pipeline.enabled)
 
-proc shutdown*(r: TRedis) =
+proc shutdown*(r: Redis) =
   ## Synchronously save the dataset to disk and then shut down the server
   r.sendCommand("SHUTDOWN")
   var s = "".TaintedString
   r.socket.readLine(s)
-  if s.string.len != 0: raise newException(ERedis, s.string)
+  if s.string.len != 0: raise newException(RedisError, s.string)
 
-proc slaveof*(r: TRedis, host: string, port: string) =
+proc slaveof*(r: Redis, host: string, port: string) =
   ## Make the server a slave of another instance, or promote it as master
   r.sendCommand("SLAVEOF", host, port)
   raiseNoOK(r.readStatus(), r.pipeline.enabled)
 
-iterator hPairs*(r: TRedis, key: string): tuple[key, value: string] =
+iterator hPairs*(r: Redis, key: string): tuple[key, value: string] =
   ## Iterator for keys and values in a hash.
   var 
     contents = r.hGetAll(key)
@@ -986,7 +986,7 @@ iterator hPairs*(r: TRedis, key: string): tuple[key, value: string] =
       yield (k, i)
       k = ""
 
-proc someTests(r: TRedis, how: TSendMode):seq[string] =
+proc someTests(r: Redis, how: SendMode):seq[string] =
   var list:seq[string] = @[]
 
   if how == pipelined:
@@ -1007,10 +1007,10 @@ proc someTests(r: TRedis, how: TSendMode):seq[string] =
   for r in res:
     list.add(r)
   list.add(r.get("invalid_key"))
-  list.add($(r.lpush("mylist","itema")))
-  list.add($(r.lpush("mylist","itemb")))
-  r.ltrim("mylist",0,1)
-  var p = r.lrange("mylist", 0, -1)
+  list.add($(r.lPush("mylist","itema")))
+  list.add($(r.lPush("mylist","itemb")))
+  r.lTrim("mylist",0,1)
+  var p = r.lRange("mylist", 0, -1)
 
   for i in items(p):
     if not isNil(i):
n>>local-scope</span> x:text<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span> y:text<span class="Special"> &lt;- </span>new <span class="Constant">[abcd]</span> run [ <span class="Constant">10</span>:bool/<span class="Special">raw &lt;- </span>equal x, y ] memory-should-contain [ <span class="Constant">10</span><span class="Special"> &lt;- </span><span class="Constant">0</span> <span class="Comment"># abc != abcd</span> ] trace-should-contain [ text-equal: comparing lengths ] trace-should-not-contain [ text-equal: comparing characters ] ] <span class="muScenario">scenario</span> text-equal-with-empty [ <span class="Constant">local-scope</span> x:text<span class="Special"> &lt;- </span>new <span class="Constant">[]</span> y:text<span class="Special"> &lt;- </span>new <span class="Constant">[abcd]</span> run [ <span class="Constant">10</span>:bool/<span class="Special">raw &lt;- </span>equal x, y ] memory-should-contain [ <span class="Constant">10</span><span class="Special"> &lt;- </span><span class="Constant">0</span> <span class="Comment"># &quot;&quot; != abcd</span> ] ] <span class="muScenario">scenario</span> text-equal-common-lengths-but-distinct [ <span class="Constant">local-scope</span> x:text<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span> y:text<span class="Special"> &lt;- </span>new <span class="Constant">[abd]</span> run [ <span class="Constant">10</span>:bool/<span class="Special">raw &lt;- </span>equal x, y ] memory-should-contain [ <span class="Constant">10</span><span class="Special"> &lt;- </span><span class="Constant">0</span> <span class="Comment"># abc != abd</span> ] ] <span class="Comment"># A new type to help incrementally construct texts.</span> <span class="muData">container</span> buffer [ length:num data:text ] <span class="muRecipe">def</span> new-buffer capacity:num<span class="muRecipe"> -&gt; </span>result:&amp;:buffer [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> result<span class="Special"> &lt;- </span>new <span class="Constant">buffer:type</span> *result<span class="Special"> &lt;- </span>put *result, <span class="Constant">length:offset</span>, <span class="Constant">0</span> <span class="Delimiter">{</span> <span class="muControl">break-if</span> capacity <span class="Comment"># capacity not provided</span> capacity<span class="Special"> &lt;- </span>copy <span class="Constant">10</span> <span class="Delimiter">}</span> data:text<span class="Special"> &lt;- </span>new <span class="Constant">character:type</span>, capacity *result<span class="Special"> &lt;- </span>put *result, <span class="Constant">data:offset</span>, data <span class="muControl">return</span> result ] <span class="muRecipe">def</span> grow-buffer buf:&amp;:buffer<span class="muRecipe"> -&gt; </span>buf:&amp;:buffer [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="Comment"># double buffer size</span> olddata:text<span class="Special"> &lt;- </span>get *buf, <span class="Constant">data:offset</span> oldlen:num<span class="Special"> &lt;- </span>length *olddata newlen:num<span class="Special"> &lt;- </span>multiply oldlen, <span class="Constant">2</span> newdata:text<span class="Special"> &lt;- </span>new <span class="Constant">character:type</span>, newlen *buf<span class="Special"> &lt;- </span>put *buf, <span class="Constant">data:offset</span>, newdata <span class="Comment"># copy old contents</span> i:num<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> <span class="Delimiter">{</span> done?:bool<span class="Special"> &lt;- </span>greater-or-equal i, oldlen <span class="muControl">break-if</span> done? src:char<span class="Special"> &lt;- </span>index *olddata, i *newdata<span class="Special"> &lt;- </span>put-index *newdata, i, src i<span class="Special"> &lt;- </span>add i, <span class="Constant">1</span> <span class="muControl">loop</span> <span class="Delimiter">}</span> ] <span class="muRecipe">def</span> buffer-full? in:&amp;:buffer<span class="muRecipe"> -&gt; </span>result:bool [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> len:num<span class="Special"> &lt;- </span>get *in, <span class="Constant">length:offset</span> s:text<span class="Special"> &lt;- </span>get *in, <span class="Constant">data:offset</span> capacity:num<span class="Special"> &lt;- </span>length *s result<span class="Special"> &lt;- </span>greater-or-equal len, capacity ] <span class="Comment"># most broadly applicable definition of append to a buffer: just call to-text</span> <span class="muRecipe">def</span> append buf:&amp;:buffer, x:_elem<span class="muRecipe"> -&gt; </span>buf:&amp;:buffer [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> text:text<span class="Special"> &lt;- </span>to-text x len:num<span class="Special"> &lt;- </span>length *text i:num<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> <span class="Delimiter">{</span> done?:bool<span class="Special"> &lt;- </span>greater-or-equal i, len <span class="muControl">break-if</span> done? c:char<span class="Special"> &lt;- </span>index *text, i buf<span class="Special"> &lt;- </span>append buf, c i<span class="Special"> &lt;- </span>add i, <span class="Constant">1</span> <span class="muControl">loop</span> <span class="Delimiter">}</span> ] <span class="muRecipe">def</span> append buf:&amp;:buffer, c:char<span class="muRecipe"> -&gt; </span>buf:&amp;:buffer [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> len:num<span class="Special"> &lt;- </span>get *buf, <span class="Constant">length:offset</span> <span class="Delimiter">{</span> <span class="Comment"># backspace? just drop last character if it exists and return</span> backspace?:bool<span class="Special"> &lt;- </span>equal c, <span class="Constant">8/backspace</span> <span class="muControl">break-unless</span> backspace? empty?:bool<span class="Special"> &lt;- </span>lesser-or-equal len, <span class="Constant">0</span> <span class="muControl">return-if</span> empty? len<span class="Special"> &lt;- </span>subtract len, <span class="Constant">1</span> *buf<span class="Special"> &lt;- </span>put *buf, <span class="Constant">length:offset</span>, len <span class="muControl">return</span> <span class="Delimiter">}</span> <span class="Delimiter">{</span> <span class="Comment"># grow buffer if necessary</span> full?:bool<span class="Special"> &lt;- </span>buffer-full? buf <span class="muControl">break-unless</span> full? buf<span class="Special"> &lt;- </span>grow-buffer buf <span class="Delimiter">}</span> s:text<span class="Special"> &lt;- </span>get *buf, <span class="Constant">data:offset</span> *s<span class="Special"> &lt;- </span>put-index *s, len, c len<span class="Special"> &lt;- </span>add len, <span class="Constant">1</span> *buf<span class="Special"> &lt;- </span>put *buf, <span class="Constant">length:offset</span>, len ] <span class="muRecipe">def</span> append buf:&amp;:buffer, t:text<span class="muRecipe"> -&gt; </span>buf:&amp;:buffer [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> len:num<span class="Special"> &lt;- </span>length *t i:num<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> <span class="Delimiter">{</span> done?:bool<span class="Special"> &lt;- </span>greater-or-equal i, len <span class="muControl">break-if</span> done? c:char<span class="Special"> &lt;- </span>index *t, i buf<span class="Special"> &lt;- </span>append buf, c i<span class="Special"> &lt;- </span>add i, <span class="Constant">1</span> <span class="muControl">loop</span> <span class="Delimiter">}</span> ] <span class="muScenario">scenario</span> append-to-empty-buffer [ <span class="Constant">local-scope</span> x:&amp;:buffer<span class="Special"> &lt;- </span>new-buffer run [ c:char<span class="Special"> &lt;- </span>copy <span class="Constant">97/a</span> x<span class="Special"> &lt;- </span>append x, c <span class="Constant">10</span>:num/<span class="Special">raw &lt;- </span>get *x, <span class="Constant">length:offset</span> s:text<span class="Special"> &lt;- </span>get *x, <span class="Constant">data:offset</span> <span class="Constant">11</span>:char/<span class="Special">raw &lt;- </span>index *s, <span class="Constant">0</span> <span class="Constant">12</span>:char/<span class="Special">raw &lt;- </span>index *s, <span class="Constant">1</span> ] memory-should-contain [ <span class="Constant">10</span><span class="Special"> &lt;- </span><span class="Constant">1</span> <span class="Comment"># buffer length</span> <span class="Constant">11</span><span class="Special"> &lt;- </span><span class="Constant">97</span> <span class="Comment"># a</span> <span class="Constant">12</span><span class="Special"> &lt;- </span><span class="Constant">0</span> <span class="Comment"># rest of buffer is empty</span> ] ] <span class="muScenario">scenario</span> append-to-buffer [ <span class="Constant">local-scope</span> x:&amp;:buffer<span class="Special"> &lt;- </span>new-buffer c:char<span class="Special"> &lt;- </span>copy <span class="Constant">97/a</span> x<span class="Special"> &lt;- </span>append x, c run [ c<span class="Special"> &lt;- </span>copy <span class="Constant">98/b</span> x<span class="Special"> &lt;- </span>append x, c <span class="Constant">10</span>:num/<span class="Special">raw &lt;- </span>get *x, <span class="Constant">length:offset</span> s:text<span class="Special"> &lt;- </span>get *x, <span class="Constant">data:offset</span> <span class="Constant">11</span>:char/<span class="Special">raw &lt;- </span>index *s, <span class="Constant">0</span> <span class="Constant">12</span>:char/<span class="Special">raw &lt;- </span>index *s, <span class="Constant">1</span> <span class="Constant">13</span>:char/<span class="Special">raw &lt;- </span>index *s, <span class="Constant">2</span> ] memory-should-contain [ <span class="Constant">10</span><span class="Special"> &lt;- </span><span class="Constant">2</span> <span class="Comment"># buffer length</span> <span class="Constant">11</span><span class="Special"> &lt;- </span><span class="Constant">97</span> <span class="Comment"># a</span> <span class="Constant">12</span><span class="Special"> &lt;- </span><span class="Constant">98</span> <span class="Comment"># b</span> <span class="Constant">13</span><span class="Special"> &lt;- </span><span class="Constant">0</span> <span class="Comment"># rest of buffer is empty</span> ] ] <span class="muScenario">scenario</span> append-grows-buffer [ <span class="Constant">local-scope</span> x:&amp;:buffer<span class="Special"> &lt;- </span>new-buffer <span class="Constant">3</span> s1:text<span class="Special"> &lt;- </span>get *x, <span class="Constant">data:offset</span> x<span class="Special"> &lt;- </span>append x, <span class="Constant">[abc]</span> <span class="Comment"># buffer is now full</span> s2:text<span class="Special"> &lt;- </span>get *x, <span class="Constant">data:offset</span> run [ <span class="Constant">10</span>:bool/<span class="Special">raw &lt;- </span>equal s1, s2 <span class="Constant">11</span>:@:char/<span class="Special">raw &lt;- </span>copy *s2 <span class="Constant"> +buffer-filled</span> c:char<span class="Special"> &lt;- </span>copy <span class="Constant">100/d</span> x<span class="Special"> &lt;- </span>append x, c s3:text<span class="Special"> &lt;- </span>get *x, <span class="Constant">data:offset</span> <span class="Constant">20</span>:bool/<span class="Special">raw &lt;- </span>equal s1, s3 <span class="Constant">21</span>:num/<span class="Special">raw &lt;- </span>get *x, <span class="Constant">length:offset</span> <span class="Constant">30</span>:@:char/<span class="Special">raw &lt;- </span>copy *s3 ] memory-should-contain [ <span class="Comment"># before +buffer-filled</span> <span class="Constant">10</span><span class="Special"> &lt;- </span><span class="Constant">1</span> <span class="Comment"># no change in data pointer after original append</span> <span class="Constant">11</span><span class="Special"> &lt;- </span><span class="Constant">3</span> <span class="Comment"># size of data</span> <span class="Constant">12</span><span class="Special"> &lt;- </span><span class="Constant">97</span> <span class="Comment"># data</span> <span class="Constant">13</span><span class="Special"> &lt;- </span><span class="Constant">98</span> <span class="Constant">14</span><span class="Special"> &lt;- </span><span class="Constant">99</span> <span class="Comment"># in the end</span> <span class="Constant">20</span><span class="Special"> &lt;- </span><span class="Constant">0</span> <span class="Comment"># data pointer has grown after second append</span> <span class="Constant">21</span><span class="Special"> &lt;- </span><span class="Constant">4</span> <span class="Comment"># final length</span> <span class="Constant">30</span><span class="Special"> &lt;- </span><span class="Constant">6</span> <span class="Comment"># but data's capacity has doubled</span> <span class="Constant">31</span><span class="Special"> &lt;- </span><span class="Constant">97</span> <span class="Comment"># data</span> <span class="Constant">32</span><span class="Special"> &lt;- </span><span class="Constant">98</span> <span class="Constant">33</span><span class="Special"> &lt;- </span><span class="Constant">99</span> <span class="Constant">34</span><span class="Special"> &lt;- </span><span class="Constant">100</span> <span class="Constant">35</span><span class="Special"> &lt;- </span><span class="Constant">0</span> <span class="Constant">36</span><span class="Special"> &lt;- </span><span class="Constant">0</span> ] ] <span class="muScenario">scenario</span> buffer-append-handles-backspace [ <span class="Constant">local-scope</span> x:&amp;:buffer<span class="Special"> &lt;- </span>new-buffer x<span class="Special"> &lt;- </span>append x, <span class="Constant">[ab]</span> run [ c:char<span class="Special"> &lt;- </span>copy <span class="Constant">8/backspace</span> x<span class="Special"> &lt;- </span>append x, c s:text<span class="Special"> &lt;- </span>buffer-to-array x <span class="Constant">10</span>:@:char/<span class="Special">raw &lt;- </span>copy *s ] memory-should-contain [ <span class="Constant">10</span><span class="Special"> &lt;- </span><span class="Constant">1</span> <span class="Comment"># length</span> <span class="Constant">11</span><span class="Special"> &lt;- </span><span class="Constant">97</span> <span class="Comment"># contents</span> <span class="Constant">12</span><span class="Special"> &lt;- </span><span class="Constant">0</span> ] ] <span class="muRecipe">def</span> buffer-to-array in:&amp;:buffer<span class="muRecipe"> -&gt; </span>result:text [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="Delimiter">{</span> <span class="Comment"># propagate null buffer</span> <span class="muControl">break-if</span> in <span class="muControl">return</span> <span class="Constant">0</span> <span class="Delimiter">}</span> len:num<span class="Special"> &lt;- </span>get *in, <span class="Constant">length:offset</span> s:text<span class="Special"> &lt;- </span>get *in, <span class="Constant">data:offset</span> <span class="Comment"># we can't just return s because it is usually the wrong length</span> result<span class="Special"> &lt;- </span>new <span class="Constant">character:type</span>, len i:num<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> <span class="Delimiter">{</span> done?:bool<span class="Special"> &lt;- </span>greater-or-equal i, len <span class="muControl">break-if</span> done? src:char<span class="Special"> &lt;- </span>index *s, i *result<span class="Special"> &lt;- </span>put-index *result, i, src i<span class="Special"> &lt;- </span>add i, <span class="Constant">1</span> <span class="muControl">loop</span> <span class="Delimiter">}</span> ] <span class="Comment"># Append any number of texts together.</span> <span class="Comment"># A later layer also translates calls to this to implicitly call to-text, so</span> <span class="Comment"># append to string becomes effectively dynamically typed.</span> <span class="Comment">#</span> <span class="Comment"># Beware though: this hack restricts how much 'append' can be overridden. Any</span> <span class="Comment"># new variants that match:</span> <span class="Comment"># append _:text, ___</span> <span class="Comment"># will never ever get used.</span> <span class="muRecipe">def</span> append first:text<span class="muRecipe"> -&gt; </span>result:text [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> buf:&amp;:buffer<span class="Special"> &lt;- </span>new-buffer <span class="Constant">30</span> <span class="Comment"># append first ingredient</span> <span class="Delimiter">{</span> <span class="muControl">break-unless</span> first buf<span class="Special"> &lt;- </span>append buf, first <span class="Delimiter">}</span> <span class="Comment"># append remaining ingredients</span> <span class="Delimiter">{</span> arg:text, arg-found?:bool<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> <span class="muControl">break-unless</span> arg-found? <span class="muControl">loop-unless</span> arg buf<span class="Special"> &lt;- </span>append buf, arg <span class="muControl">loop</span> <span class="Delimiter">}</span> result<span class="Special"> &lt;- </span>buffer-to-array buf ] <span class="muScenario">scenario</span> text-append-1 [ <span class="Constant">local-scope</span> x:text<span class="Special"> &lt;- </span>new <span class="Constant">[hello,]</span> y:text<span class="Special"> &lt;- </span>new <span class="Constant">[ world!]</span> run [ z:text<span class="Special"> &lt;- </span>append x, y <span class="Constant">10</span>:@:char/<span class="Special">raw &lt;- </span>copy *z ] memory-should-contain [ <span class="Constant">10</span>:array:character<span class="Special"> &lt;- </span><span class="Constant">[hello, world!]</span> ] ] <span class="muScenario">scenario</span> text-append-null [ <span class="Constant">local-scope</span> x:text<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> y:text<span class="Special"> &lt;- </span>new <span class="Constant">[ world!]</span> run [ z:text<span class="Special"> &lt;- </span>append x, y <span class="Constant">10</span>:@:char/<span class="Special">raw &lt;- </span>copy *z ] memory-should-contain [ <span class="Constant">10</span>:array:character<span class="Special"> &lt;- </span><span class="Constant">[ world!]</span> ] ] <span class="muScenario">scenario</span> text-append-null-2 [ <span class="Constant">local-scope</span> x:text<span class="Special"> &lt;- </span>new <span class="Constant">[hello,]</span> y:text<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> run [ z:text<span class="Special"> &lt;- </span>append x, y <span class="Constant">10</span>:@:char/<span class="Special">raw &lt;- </span>copy *z ] memory-should-contain [ <span class="Constant">10</span>:array:character<span class="Special"> &lt;- </span><span class="Constant">[hello,]</span> ] ] <span class="muScenario">scenario</span> text-append-multiary [ <span class="Constant">local-scope</span> x:text<span class="Special"> &lt;- </span>new <span class="Constant">[hello, ]</span> y:text<span class="Special"> &lt;- </span>new <span class="Constant">[world]</span> z:text<span class="Special"> &lt;- </span>new <span class="Constant">[!]</span> run [ z:text<span class="Special"> &lt;- </span>append x, y, z <span class="Constant">10</span>:@:char/<span class="Special">raw &lt;- </span>copy *z ] memory-should-contain [ <span class="Constant">10</span>:array:character<span class="Special"> &lt;- </span><span class="Constant">[hello, world!]</span> ] ] <span class="muScenario">scenario</span> replace-character-in-text [ <span class="Constant">local-scope</span> x:text<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span> run [ x<span class="Special"> &lt;- </span>replace x, <span class="Constant">98/b</span>, <span class="Constant">122/z</span> <span class="Constant">10</span>:@:char/<span class="Special">raw &lt;- </span>copy *x ] memory-should-contain [ <span class="Constant">10</span>:array:character<span class="Special"> &lt;- </span><span class="Constant">[azc]</span> ] ] <span class="muRecipe">def</span> replace s:text, oldc:char, newc:char, from:num/optional<span class="muRecipe"> -&gt; </span>s:text [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> len:num<span class="Special"> &lt;- </span>length *s i:num<span class="Special"> &lt;- </span>find-next s, oldc, from done?:bool<span class="Special"> &lt;- </span>greater-or-equal i, len <span class="muControl">return-if</span> done?, s/same-as-ingredient:<span class="Constant">0</span> *s<span class="Special"> &lt;- </span>put-index *s, i, newc i<span class="Special"> &lt;- </span>add i, <span class="Constant">1</span> s<span class="Special"> &lt;- </span>replace s, oldc, newc, i ] <span class="muScenario">scenario</span> replace-character-at-start [ <span class="Constant">local-scope</span> x:text<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span> run [ x<span class="Special"> &lt;- </span>replace x, <span class="Constant">97/a</span>, <span class="Constant">122/z</span> <span class="Constant">10</span>:@:char/<span class="Special">raw &lt;- </span>copy *x ] memory-should-contain [ <span class="Constant">10</span>:array:character<span class="Special"> &lt;- </span><span class="Constant">[zbc]</span> ] ] <span class="muScenario">scenario</span> replace-character-at-end [ <span class="Constant">local-scope</span> x:text<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span> run [ x<span class="Special"> &lt;- </span>replace x, <span class="Constant">99/c</span>, <span class="Constant">122/z</span> <span class="Constant">10</span>:@:char/<span class="Special">raw &lt;- </span>copy *x ] memory-should-contain [ <span class="Constant">10</span>:array:character<span class="Special"> &lt;- </span><span class="Constant">[abz]</span> ] ] <span class="muScenario">scenario</span> replace-character-missing [ <span class="Constant">local-scope</span> x:text<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span> run [ x<span class="Special"> &lt;- </span>replace x, <span class="Constant">100/d</span>, <span class="Constant">122/z</span> <span class="Constant">10</span>:@:char/<span class="Special">raw &lt;- </span>copy *x ] memory-should-contain [ <span class="Constant">10</span>:array:character<span class="Special"> &lt;- </span><span class="Constant">[abc]</span> ] ] <span class="muScenario">scenario</span> replace-all-characters [ <span class="Constant">local-scope</span> x:text<span class="Special"> &lt;- </span>new <span class="Constant">[banana]</span> run [ x<span class="Special"> &lt;- </span>replace x, <span class="Constant">97/a</span>, <span class="Constant">122/z</span> <span class="Constant">10</span>:@:char/<span class="Special">raw &lt;- </span>copy *x ] memory-should-contain [ <span class="Constant">10</span>:array:character<span class="Special"> &lt;- </span><span class="Constant">[bznznz]</span> ] ] <span class="Comment"># replace underscores in first with remaining args</span> <span class="muRecipe">def</span> interpolate template:text<span class="muRecipe"> -&gt; </span>result:text [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="Comment"># consume just the template</span> <span class="Comment"># compute result-len, space to allocate for result</span> tem-len:num<span class="Special"> &lt;- </span>length *template result-len:num<span class="Special"> &lt;- </span>copy tem-len <span class="Delimiter">{</span> <span class="Comment"># while ingredients remain</span> a:text, arg-received?:bool<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> <span class="muControl">break-unless</span> arg-received? <span class="Comment"># result-len = result-len + arg.length - 1 (for the 'underscore' being replaced)</span> a-len:num<span class="Special"> &lt;- </span>length *a result-len<span class="Special"> &lt;- </span>add result-len, a-len result-len<span class="Special"> &lt;- </span>subtract result-len, <span class="Constant">1</span> <span class="muControl">loop</span> <span class="Delimiter">}</span> <span class="Constant">rewind-ingredients</span> _<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> <span class="Comment"># skip template</span> result<span class="Special"> &lt;- </span>new <span class="Constant">character:type</span>, result-len <span class="Comment"># repeatedly copy sections of template and 'holes' into result</span> result-idx:num<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> i:num<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> <span class="Delimiter">{</span> <span class="Comment"># while arg received</span> a:text, arg-received?:bool<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span> <span class="muControl">break-unless</span> arg-received? <span class="Comment"># copy template into result until '_'</span> <span class="Delimiter">{</span> <span class="Comment"># while i &lt; template.length</span> tem-done?:bool<span class="Special"> &lt;- </span>greater-or-equal i, tem-len <span class="muControl">break-if</span> tem-done?, <span class="Constant">+done:label</span> <span class="Comment"># while template[i] != '_'</span> in:char<span class="Special"> &lt;- </span>index *template, i underscore?:bool<span class="Special"> &lt;- </span>equal in, <span class="Constant">95/_</span> <span class="muControl">break-if</span> underscore? <span class="Comment"># result[result-idx] = template[i]</span> *result<span class="Special"> &lt;- </span>put-index *result, result-idx, in i<span class="Special"> &lt;- </span>add i, <span class="Constant">1</span> result-idx<span class="Special"> &lt;- </span>add result-idx, <span class="Constant">1</span> <span class="muControl">loop</span> <span class="Delimiter">}</span> <span class="Comment"># copy 'a' into result</span> j:num<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> <span class="Delimiter">{</span> <span class="Comment"># while j &lt; a.length</span> arg-done?:bool<span class="Special"> &lt;- </span>greater-or-equal j, a-len <span class="muControl">break-if</span> arg-done? <span class="Comment"># result[result-idx] = a[j]</span> in:char<span class="Special"> &lt;- </span>index *a, j *result<span class="Special"> &lt;- </span>put-index *result, result-idx, in j<span class="Special"> &lt;- </span>add j, <span class="Constant">1</span> result-idx<span class="Special"> &lt;- </span>add result-idx, <span class="Constant">1</span> <span class="muControl">loop</span> <span class="Delimiter">}</span> <span class="Comment"># skip '_' in template</span> i<span class="Special"> &lt;- </span>add i, <span class="Constant">1</span> <span class="muControl">loop</span> <span class="Comment"># interpolate next arg</span> <span class="Delimiter">}</span> <span class="Constant"> +done</span> <span class="Comment"># done with holes; copy rest of template directly into result</span> <span class="Delimiter">{</span> <span class="Comment"># while i &lt; template.length</span> tem-done?:bool<span class="Special"> &lt;- </span>greater-or-equal i, tem-len <span class="muControl">break-if</span> tem-done? <span class="Comment"># result[result-idx] = template[i]</span> in:char<span class="Special"> &lt;- </span>index *template, i *result<span class="Special"> &lt;- </span>put-index *result, result-idx, in i<span class="Special"> &lt;- </span>add i, <span class="Constant">1</span> result-idx<span class="Special"> &lt;- </span>add result-idx, <span class="Constant">1</span> <span class="muControl">loop</span> <span class="Delimiter">}</span> ] <span class="muScenario">scenario</span> interpolate-works [ <span class="Constant">local-scope</span> x:text<span class="Special"> &lt;- </span>new <span class="Constant">[abc_ghi]</span> y:text<span class="Special"> &lt;- </span>new <span class="Constant">[def]</span> run [ z:text<span class="Special"> &lt;- </span>interpolate x, y <span class="Constant">10</span>:@:char/<span class="Special">raw &lt;- </span>copy *z ] memory-should-contain [ <span class="Constant">10</span>:array:character<span class="Special"> &lt;- </span><span class="Constant">[abcdefghi]</span> ] ] <span class="muScenario">scenario</span> interpolate-at-start [ <span class="Constant">local-scope</span> x:text<span class="Special"> &lt;- </span>new <span class="Constant">[_, hello!]</span> y:text<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span> run [ z:text<span class="Special"> &lt;- </span>interpolate x, y <span class="Constant">10</span>:@:char/<span class="Special">raw &lt;- </span>copy *z ] memory-should-contain [ <span class="Constant">10</span>:array:character<span class="Special"> &lt;- </span><span class="Constant">[abc, hello!]</span> <span class="Constant">22</span><span class="Special"> &lt;- </span><span class="Constant">0</span> <span class="Comment"># out of bounds</span> ] ] <span class="muScenario">scenario</span> interpolate-at-end [ <span class="Constant">local-scope</span> x:text<span class="Special"> &lt;- </span>new <span class="Constant">[hello, _]</span> y:text<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span> run [ z:text<span class="Special"> &lt;- </span>interpolate x, y <span class="Constant">10</span>:@:char/<span class="Special">raw &lt;- </span>copy *z ] memory-should-contain [ <span class="Constant">10</span>:array:character<span class="Special"> &lt;- </span><span class="Constant">[hello, abc]</span> ] ] <span class="Comment"># result:bool &lt;- space? c:char</span> <span class="muRecipe">def</span> space? c:char<span class="muRecipe"> -&gt; </span>result:bool [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="Comment"># most common case first</span> result<span class="Special"> &lt;- </span>equal c, <span class="Constant">32/space</span> <span class="muControl">return-if</span> result result<span class="Special"> &lt;- </span>equal c, <span class="Constant">10/newline</span> <span class="muControl">return-if</span> result result<span class="Special"> &lt;- </span>equal c, <span class="Constant">9/tab</span> <span class="muControl">return-if</span> result result<span class="Special"> &lt;- </span>equal c, <span class="Constant">13/carriage-return</span> <span class="muControl">return-if</span> result <span class="Comment"># remaining uncommon cases in sorted order</span> <span class="Comment"># <a href="http://unicode.org">http://unicode.org</a> code-points in unicode-set Z and Pattern_White_Space</span> result<span class="Special"> &lt;- </span>equal c, <span class="Constant">11/ctrl-k</span> <span class="muControl">return-if</span> result result<span class="Special"> &lt;- </span>equal c, <span class="Constant">12/ctrl-l</span> <span class="muControl">return-if</span> result result<span class="Special"> &lt;- </span>equal c, <span class="Constant">133/ctrl-0085</span> <span class="muControl">return-if</span> result result<span class="Special"> &lt;- </span>equal c, <span class="Constant">160/no-break-space</span> <span class="muControl">return-if</span> result result<span class="Special"> &lt;- </span>equal c, <span class="Constant">5760/ogham-space-mark</span> <span class="muControl">return-if</span> result result<span class="Special"> &lt;- </span>equal c, <span class="Constant">8192/en-quad</span> <span class="muControl">return-if</span> result result<span class="Special"> &lt;- </span>equal c, <span class="Constant">8193/em-quad</span> <span class="muControl">return-if</span> result result<span class="Special"> &lt;- </span>equal c, <span class="Constant">8194/en-space</span> <span class="muControl">return-if</span> result result<span class="Special"> &lt;- </span>equal c, <span class="Constant">8195/em-space</span> <span class="muControl">return-if</span> result result<span class="Special"> &lt;- </span>equal c, <span class="Constant">8196/three-per-em-space</span> <span class="muControl">return-if</span> result result<span class="Special"> &lt;- </span>equal c, <span class="Constant">8197/four-per-em-space</span> <span class="muControl">return-if</span> result result<span class="Special"> &lt;- </span>equal c, <span class="Constant">8198/six-per-em-space</span> <span class="muControl">return-if</span> result result<span class="Special"> &lt;- </span>equal c, <span class="Constant">8199/figure-space</span> <span class="muControl">return-if</span> result result<span class="Special"> &lt;- </span>equal c, <span class="Constant">8200/punctuation-space</span> <span class="muControl">return-if</span> result result<span class="Special"> &lt;- </span>equal c, <span class="Constant">8201/thin-space</span> <span class="muControl">return-if</span> result result<span class="Special"> &lt;- </span>equal c, <span class="Constant">8202/hair-space</span> <span class="muControl">return-if</span> result result<span class="Special"> &lt;- </span>equal c, <span class="Constant">8206/left-to-right</span> <span class="muControl">return-if</span> result result<span class="Special"> &lt;- </span>equal c, <span class="Constant">8207/right-to-left</span> <span class="muControl">return-if</span> result result<span class="Special"> &lt;- </span>equal c, <span class="Constant">8232/line-separator</span> <span class="muControl">return-if</span> result result<span class="Special"> &lt;- </span>equal c, <span class="Constant">8233/paragraph-separator</span> <span class="muControl">return-if</span> result result<span class="Special"> &lt;- </span>equal c, <span class="Constant">8239/narrow-no-break-space</span> <span class="muControl">return-if</span> result result<span class="Special"> &lt;- </span>equal c, <span class="Constant">8287/medium-mathematical-space</span> <span class="muControl">return-if</span> result result<span class="Special"> &lt;- </span>equal c, <span class="Constant">12288/ideographic-space</span> ] <span class="muRecipe">def</span> trim s:text<span class="muRecipe"> -&gt; </span>result:text [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> len:num<span class="Special"> &lt;- </span>length *s <span class="Comment"># left trim: compute start</span> start:num<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> <span class="Delimiter">{</span> <span class="Delimiter">{</span> at-end?:bool<span class="Special"> &lt;- </span>greater-or-equal start, len <span class="muControl">break-unless</span> at-end? result<span class="Special"> &lt;- </span>new <span class="Constant">character:type</span>, <span class="Constant">0</span> <span class="muControl">return</span> <span class="Delimiter">}</span> curr:char<span class="Special"> &lt;- </span>index *s, start whitespace?:bool<span class="Special"> &lt;- </span>space? curr <span class="muControl">break-unless</span> whitespace? start<span class="Special"> &lt;- </span>add start, <span class="Constant">1</span> <span class="muControl">loop</span> <span class="Delimiter">}</span> <span class="Comment"># right trim: compute end</span> end:num<span class="Special"> &lt;- </span>subtract len, <span class="Constant">1</span> <span class="Delimiter">{</span> not-at-start?:bool<span class="Special"> &lt;- </span>greater-than end, start assert not-at-start?, <span class="Constant">[end ran up against start]</span> curr:char<span class="Special"> &lt;- </span>index *s, end whitespace?:bool<span class="Special"> &lt;- </span>space? curr <span class="muControl">break-unless</span> whitespace? end<span class="Special"> &lt;- </span>subtract end, <span class="Constant">1</span> <span class="muControl">loop</span> <span class="Delimiter">}</span> <span class="Comment"># result = new character[end+1 - start]</span> new-len:num<span class="Special"> &lt;- </span>subtract end, start, <span class="Constant">-1</span> result:text<span class="Special"> &lt;- </span>new <span class="Constant">character:type</span>, new-len <span class="Comment"># copy the untrimmed parts between start and end</span> i:num<span class="Special"> &lt;- </span>copy start j:num<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> <span class="Delimiter">{</span> <span class="Comment"># while i &lt;= end</span> done?:bool<span class="Special"> &lt;- </span>greater-than i, end <span class="muControl">break-if</span> done? <span class="Comment"># result[j] = s[i]</span> src:char<span class="Special"> &lt;- </span>index *s, i *result<span class="Special"> &lt;- </span>put-index *result, j, src i<span class="Special"> &lt;- </span>add i, <span class="Constant">1</span> j<span class="Special"> &lt;- </span>add j, <span class="Constant">1</span> <span class="muControl">loop</span> <span class="Delimiter">}</span> ] <span class="muScenario">scenario</span> trim-unmodified [ <span class="Constant">local-scope</span> x:text<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span> run [ y:text<span class="Special"> &lt;- </span>trim x <span class="Constant">1</span>:@:char/<span class="Special">raw &lt;- </span>copy *y ] memory-should-contain [ <span class="Constant">1</span>:array:character<span class="Special"> &lt;- </span><span class="Constant">[abc]</span> ] ] <span class="muScenario">scenario</span> trim-left [ <span class="Constant">local-scope</span> x:text<span class="Special"> &lt;- </span>new <span class="Constant">[ abc]</span> run [ y:text<span class="Special"> &lt;- </span>trim x <span class="Constant">1</span>:@:char/<span class="Special">raw &lt;- </span>copy *y ] memory-should-contain [ <span class="Constant">1</span>:array:character<span class="Special"> &lt;- </span><span class="Constant">[abc]</span> ] ] <span class="muScenario">scenario</span> trim-right [ <span class="Constant">local-scope</span> x:text<span class="Special"> &lt;- </span>new <span class="Constant">[abc ]</span> run [ y:text<span class="Special"> &lt;- </span>trim x <span class="Constant">1</span>:@:char/<span class="Special">raw &lt;- </span>copy *y ] memory-should-contain [ <span class="Constant">1</span>:array:character<span class="Special"> &lt;- </span><span class="Constant">[abc]</span> ] ] <span class="muScenario">scenario</span> trim-left-right [ <span class="Constant">local-scope</span> x:text<span class="Special"> &lt;- </span>new <span class="Constant">[ abc ]</span> run [ y:text<span class="Special"> &lt;- </span>trim x <span class="Constant">1</span>:@:char/<span class="Special">raw &lt;- </span>copy *y ] memory-should-contain [ <span class="Constant">1</span>:array:character<span class="Special"> &lt;- </span><span class="Constant">[abc]</span> ] ] <span class="muScenario">scenario</span> trim-newline-tab [ <span class="Constant">local-scope</span> x:text<span class="Special"> &lt;- </span>new <span class="Constant">[ abc</span> <span class="Constant">]</span> run [ y:text<span class="Special"> &lt;- </span>trim x <span class="Constant">1</span>:@:char/<span class="Special">raw &lt;- </span>copy *y ] memory-should-contain [ <span class="Constant">1</span>:array:character<span class="Special"> &lt;- </span><span class="Constant">[abc]</span> ] ] <span class="muRecipe">def</span> find-next text:text, pattern:char, idx:num<span class="muRecipe"> -&gt; </span>next-index:num [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> len:num<span class="Special"> &lt;- </span>length *text <span class="Delimiter">{</span> eof?:bool<span class="Special"> &lt;- </span>greater-or-equal idx, len <span class="muControl">break-if</span> eof? curr:char<span class="Special"> &lt;- </span>index *text, idx found?:bool<span class="Special"> &lt;- </span>equal curr, pattern <span class="muControl">break-if</span> found? idx<span class="Special"> &lt;- </span>add idx, <span class="Constant">1</span> <span class="muControl">loop</span> <span class="Delimiter">}</span> <span class="muControl">return</span> idx ] <span class="muScenario">scenario</span> text-find-next [ <span class="Constant">local-scope</span> x:text<span class="Special"> &lt;- </span>new <span class="Constant">[a/b]</span> run [ <span class="Constant">10</span>:num/<span class="Special">raw &lt;- </span>find-next x, <span class="Constant">47/slash</span>, <span class="Constant">0/start-index</span> ] memory-should-contain [ <span class="Constant">10</span><span class="Special"> &lt;- </span><span class="Constant">1</span> ] ] <span class="muScenario">scenario</span> text-find-next-empty [ <span class="Constant">local-scope</span> x:text<span class="Special"> &lt;- </span>new <span class="Constant">[]</span> run [ <span class="Constant">10</span>:num/<span class="Special">raw &lt;- </span>find-next x, <span class="Constant">47/slash</span>, <span class="Constant">0/start-index</span> ] memory-should-contain [ <span class="Constant">10</span><span class="Special"> &lt;- </span><span class="Constant">0</span> ] ] <span class="muScenario">scenario</span> text-find-next-initial [ <span class="Constant">local-scope</span> x:text<span class="Special"> &lt;- </span>new <span class="Constant">[/abc]</span> run [ <span class="Constant">10</span>:num/<span class="Special">raw &lt;- </span>find-next x, <span class="Constant">47/slash</span>, <span class="Constant">0/start-index</span> ] memory-should-contain [ <span class="Constant">10</span><span class="Special"> &lt;- </span><span class="Constant">0</span> <span class="Comment"># prefix match</span> ] ] <span class="muScenario">scenario</span> text-find-next-final [ <span class="Constant">local-scope</span> x:text<span class="Special"> &lt;- </span>new <span class="Constant">[abc/]</span> run [ <span class="Constant">10</span>:num/<span class="Special">raw &lt;- </span>find-next x, <span class="Constant">47/slash</span>, <span class="Constant">0/start-index</span> ] memory-should-contain [ <span class="Constant">10</span><span class="Special"> &lt;- </span><span class="Constant">3</span> <span class="Comment"># suffix match</span> ] ] <span class="muScenario">scenario</span> text-find-next-missing [ <span class="Constant">local-scope</span> x:text<span class="Special"> &lt;- </span>new <span class="Constant">[abcd]</span> run [ <span class="Constant">10</span>:num/<span class="Special">raw &lt;- </span>find-next x, <span class="Constant">47/slash</span>, <span class="Constant">0/start-index</span> ] memory-should-contain [ <span class="Constant">10</span><span class="Special"> &lt;- </span><span class="Constant">4</span> <span class="Comment"># no match</span> ] ] <span class="muScenario">scenario</span> text-find-next-invalid-index [ <span class="Constant">local-scope</span> x:text<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span> run [ <span class="Constant">10</span>:num/<span class="Special">raw &lt;- </span>find-next x, <span class="Constant">47/slash</span>, <span class="Constant">4/start-index</span> ] memory-should-contain [ <span class="Constant">10</span><span class="Special"> &lt;- </span><span class="Constant">4</span> <span class="Comment"># no change</span> ] ] <span class="muScenario">scenario</span> text-find-next-first [ <span class="Constant">local-scope</span> x:text<span class="Special"> &lt;- </span>new <span class="Constant">[ab/c/]</span> run [ <span class="Constant">10</span>:num/<span class="Special">raw &lt;- </span>find-next x, <span class="Constant">47/slash</span>, <span class="Constant">0/start-index</span> ] memory-should-contain [ <span class="Constant">10</span><span class="Special"> &lt;- </span><span class="Constant">2</span> <span class="Comment"># first '/' of multiple</span> ] ] <span class="muScenario">scenario</span> text-find-next-second [ <span class="Constant">local-scope</span> x:text<span class="Special"> &lt;- </span>new <span class="Constant">[ab/c/]</span> run [ <span class="Constant">10</span>:num/<span class="Special">raw &lt;- </span>find-next x, <span class="Constant">47/slash</span>, <span class="Constant">3/start-index</span> ] memory-should-contain [ <span class="Constant">10</span><span class="Special"> &lt;- </span><span class="Constant">4</span> <span class="Comment"># second '/' of multiple</span> ] ] <span class="Comment"># search for a pattern of multiple characters</span> <span class="Comment"># fairly dumb algorithm</span> <span class="muRecipe">def</span> find-next text:text, pattern:text, idx:num<span class="muRecipe"> -&gt; </span>next-index:num [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> first:char<span class="Special"> &lt;- </span>index *pattern, <span class="Constant">0</span> <span class="Comment"># repeatedly check for match at current idx</span> len:num<span class="Special"> &lt;- </span>length *text <span class="Delimiter">{</span> <span class="Comment"># does some unnecessary work checking even when there isn't enough of text left</span> done?:bool<span class="Special"> &lt;- </span>greater-or-equal idx, len <span class="muControl">break-if</span> done? found?:bool<span class="Special"> &lt;- </span>match-at text, pattern, idx <span class="muControl">break-if</span> found? idx<span class="Special"> &lt;- </span>add idx, <span class="Constant">1</span> <span class="Comment"># optimization: skip past indices that definitely won't match</span> idx<span class="Special"> &lt;- </span>find-next text, first, idx <span class="muControl">loop</span> <span class="Delimiter">}</span> <span class="muControl">return</span> idx ] <span class="muScenario">scenario</span> find-next-text-1 [ <span class="Constant">local-scope</span> x:text<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span> y:text<span class="Special"> &lt;- </span>new <span class="Constant">[bc]</span> run [ <span class="Constant">10</span>:num/<span class="Special">raw &lt;- </span>find-next x, y, <span class="Constant">0</span> ] memory-should-contain [ <span class="Constant">10</span><span class="Special"> &lt;- </span><span class="Constant">1</span> ] ] <span class="muScenario">scenario</span> find-next-text-2 [ <span class="Constant">local-scope</span> x:text<span class="Special"> &lt;- </span>new <span class="Constant">[abcd]</span> y:text<span class="Special"> &lt;- </span>new <span class="Constant">[bc]</span> run [ <span class="Constant">10</span>:num/<span class="Special">raw &lt;- </span>find-next x, y, <span class="Constant">1</span> ] memory-should-contain [ <span class="Constant">10</span><span class="Special"> &lt;- </span><span class="Constant">1</span> ] ] <span class="muScenario">scenario</span> find-next-no-match [ <span class="Constant">local-scope</span> x:text<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span> y:text<span class="Special"> &lt;- </span>new <span class="Constant">[bd]</span> run [ <span class="Constant">10</span>:num/<span class="Special">raw &lt;- </span>find-next x, y, <span class="Constant">0</span> ] memory-should-contain [ <span class="Constant">10</span><span class="Special"> &lt;- </span><span class="Constant">3</span> <span class="Comment"># not found</span> ] ] <span class="muScenario">scenario</span> find-next-suffix-match [ <span class="Constant">local-scope</span> x:text<span class="Special"> &lt;- </span>new <span class="Constant">[abcd]</span> y:text<span class="Special"> &lt;- </span>new <span class="Constant">[cd]</span> run [ <span class="Constant">10</span>:num/<span class="Special">raw &lt;- </span>find-next x, y, <span class="Constant">0</span> ] memory-should-contain [ <span class="Constant">10</span><span class="Special"> &lt;- </span><span class="Constant">2</span> ] ] <span class="muScenario">scenario</span> find-next-suffix-match-2 [ <span class="Constant">local-scope</span> x:text<span class="Special"> &lt;- </span>new <span class="Constant">[abcd]</span> y:text<span class="Special"> &lt;- </span>new <span class="Constant">[cde]</span> run [ <span class="Constant">10</span>:num/<span class="Special">raw &lt;- </span>find-next x, y, <span class="Constant">0</span> ] memory-should-contain [ <span class="Constant">10</span><span class="Special"> &lt;- </span><span class="Constant">4</span> <span class="Comment"># not found</span> ] ] <span class="Comment"># checks if pattern matches at index 'idx'</span> <span class="muRecipe">def</span> match-at text:text, pattern:text, idx:num<span class="muRecipe"> -&gt; </span>result:bool [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> pattern-len:num<span class="Special"> &lt;- </span>length *pattern <span class="Comment"># check that there's space left for the pattern</span> <span class="Delimiter">{</span> x:num<span class="Special"> &lt;- </span>length *text x<span class="Special"> &lt;- </span>subtract x, pattern-len enough-room?:bool<span class="Special"> &lt;- </span>lesser-or-equal idx, x <span class="muControl">break-if</span> enough-room? <span class="muControl">return</span> <span class="Constant">0/not-found</span> <span class="Delimiter">}</span> <span class="Comment"># check each character of pattern</span> pattern-idx:num<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> <span class="Delimiter">{</span> done?:bool<span class="Special"> &lt;- </span>greater-or-equal pattern-idx, pattern-len <span class="muControl">break-if</span> done? c:char<span class="Special"> &lt;- </span>index *text, idx exp:char<span class="Special"> &lt;- </span>index *pattern, pattern-idx <span class="Delimiter">{</span> match?:bool<span class="Special"> &lt;- </span>equal c, exp <span class="muControl">break-if</span> match? <span class="muControl">return</span> <span class="Constant">0/not-found</span> <span class="Delimiter">}</span> idx<span class="Special"> &lt;- </span>add idx, <span class="Constant">1</span> pattern-idx<span class="Special"> &lt;- </span>add pattern-idx, <span class="Constant">1</span> <span class="muControl">loop</span> <span class="Delimiter">}</span> <span class="muControl">return</span> <span class="Constant">1/found</span> ] <span class="muScenario">scenario</span> match-at-checks-pattern-at-index [ <span class="Constant">local-scope</span> x:text<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span> y:text<span class="Special"> &lt;- </span>new <span class="Constant">[ab]</span> run [ <span class="Constant">10</span>:bool/<span class="Special">raw &lt;- </span>match-at x, y, <span class="Constant">0</span> ] memory-should-contain [ <span class="Constant">10</span><span class="Special"> &lt;- </span><span class="Constant">1</span> <span class="Comment"># match found</span> ] ] <span class="muScenario">scenario</span> match-at-reflexive [ <span class="Constant">local-scope</span> x:text<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span> run [ <span class="Constant">10</span>:bool/<span class="Special">raw &lt;- </span>match-at x, x, <span class="Constant">0</span> ] memory-should-contain [ <span class="Constant">10</span><span class="Special"> &lt;- </span><span class="Constant">1</span> <span class="Comment"># match found</span> ] ] <span class="muScenario">scenario</span> match-at-outside-bounds [ <span class="Constant">local-scope</span> x:text<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span> y:text<span class="Special"> &lt;- </span>new <span class="Constant">[a]</span> run [ <span class="Constant">10</span>:bool/<span class="Special">raw &lt;- </span>match-at x, y, <span class="Constant">4</span> ] memory-should-contain [ <span class="Constant">10</span><span class="Special"> &lt;- </span><span class="Constant">0</span> <span class="Comment"># never matches</span> ] ] <span class="muScenario">scenario</span> match-at-empty-pattern [ <span class="Constant">local-scope</span> x:text<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span> y:text<span class="Special"> &lt;- </span>new <span class="Constant">[]</span> run [ <span class="Constant">10</span>:bool/<span class="Special">raw &lt;- </span>match-at x, y, <span class="Constant">0</span> ] memory-should-contain [ <span class="Constant">10</span><span class="Special"> &lt;- </span><span class="Constant">1</span> <span class="Comment"># always matches empty pattern given a valid index</span> ] ] <span class="muScenario">scenario</span> match-at-empty-pattern-outside-bound [ <span class="Constant">local-scope</span> x:text<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span> y:text<span class="Special"> &lt;- </span>new <span class="Constant">[]</span> run [ <span class="Constant">10</span>:bool/<span class="Special">raw &lt;- </span>match-at x, y, <span class="Constant">4</span> ] memory-should-contain [ <span class="Constant">10</span><span class="Special"> &lt;- </span><span class="Constant">0</span> <span class="Comment"># no match</span> ] ] <span class="muScenario">scenario</span> match-at-empty-text [ <span class="Constant">local-scope</span> x:text<span class="Special"> &lt;- </span>new <span class="Constant">[]</span> y:text<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span> run [ <span class="Constant">10</span>:bool/<span class="Special">raw &lt;- </span>match-at x, y, <span class="Constant">0</span> ] memory-should-contain [ <span class="Constant">10</span><span class="Special"> &lt;- </span><span class="Constant">0</span> <span class="Comment"># no match</span> ] ] <span class="muScenario">scenario</span> match-at-empty-against-empty [ <span class="Constant">local-scope</span> x:text<span class="Special"> &lt;- </span>new <span class="Constant">[]</span> run [ <span class="Constant">10</span>:bool/<span class="Special">raw &lt;- </span>match-at x, x, <span class="Constant">0</span> ] memory-should-contain [ <span class="Constant">10</span><span class="Special"> &lt;- </span><span class="Constant">1</span> <span class="Comment"># matches because pattern is also empty</span> ] ] <span class="muScenario">scenario</span> match-at-inside-bounds [ <span class="Constant">local-scope</span> x:text<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span> y:text<span class="Special"> &lt;- </span>new <span class="Constant">[bc]</span> run [ <span class="Constant">10</span>:bool/<span class="Special">raw &lt;- </span>match-at x, y, <span class="Constant">1</span> ] memory-should-contain [ <span class="Constant">10</span><span class="Special"> &lt;- </span><span class="Constant">1</span> <span class="Comment"># match</span> ] ] <span class="muScenario">scenario</span> match-at-inside-bounds-2 [ <span class="Constant">local-scope</span> x:text<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span> y:text<span class="Special"> &lt;- </span>new <span class="Constant">[bc]</span> run [ <span class="Constant">10</span>:bool/<span class="Special">raw &lt;- </span>match-at x, y, <span class="Constant">0</span> ] memory-should-contain [ <span class="Constant">10</span><span class="Special"> &lt;- </span><span class="Constant">0</span> <span class="Comment"># no match</span> ] ] <span class="muRecipe">def</span> split s:text, delim:char<span class="muRecipe"> -&gt; </span>result:&amp;:@:text [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="Comment"># empty text? return empty array</span> len:num<span class="Special"> &lt;- </span>length *s <span class="Delimiter">{</span> empty?:bool<span class="Special"> &lt;- </span>equal len, <span class="Constant">0</span> <span class="muControl">break-unless</span> empty? result<span class="Special"> &lt;- </span>new <span class="Delimiter">{</span>(address array character): type<span class="Delimiter">}</span>, <span class="Constant">0</span> <span class="muControl">return</span> <span class="Delimiter">}</span> <span class="Comment"># count #pieces we need room for</span> count:num<span class="Special"> &lt;- </span>copy <span class="Constant">1</span> <span class="Comment"># n delimiters = n+1 pieces</span> idx:num<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> <span class="Delimiter">{</span> idx<span class="Special"> &lt;- </span>find-next s, delim, idx done?:bool<span class="Special"> &lt;- </span>greater-or-equal idx, len <span class="muControl">break-if</span> done? idx<span class="Special"> &lt;- </span>add idx, <span class="Constant">1</span> count<span class="Special"> &lt;- </span>add count, <span class="Constant">1</span> <span class="muControl">loop</span> <span class="Delimiter">}</span> <span class="Comment"># allocate space</span> result<span class="Special"> &lt;- </span>new <span class="Delimiter">{</span>(address array character): type<span class="Delimiter">}</span>, count <span class="Comment"># repeatedly copy slices start..end until delimiter into result[curr-result]</span> curr-result:num<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> start:num<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> <span class="Delimiter">{</span> <span class="Comment"># while next delim exists</span> done?:bool<span class="Special"> &lt;- </span>greater-or-equal start, len <span class="muControl">break-if</span> done? end:num<span class="Special"> &lt;- </span>find-next s, delim, start <span class="Comment"># copy start..end into result[curr-result]</span> dest:text<span class="Special"> &lt;- </span>copy-range s, start, end *result<span class="Special"> &lt;- </span>put-index *result, curr-result, dest <span class="Comment"># slide over to next slice</span> start<span class="Special"> &lt;- </span>add end, <span class="Constant">1</span> curr-result<span class="Special"> &lt;- </span>add curr-result, <span class="Constant">1</span> <span class="muControl">loop</span> <span class="Delimiter">}</span> ] <span class="muScenario">scenario</span> text-split-1 [ <span class="Constant">local-scope</span> x:text<span class="Special"> &lt;- </span>new <span class="Constant">[a/b]</span> run [ y:&amp;:@:text<span class="Special"> &lt;- </span>split x, <span class="Constant">47/slash</span> <span class="Constant">10</span>:num/<span class="Special">raw &lt;- </span>length *y a:text<span class="Special"> &lt;- </span>index *y, <span class="Constant">0</span> b:text<span class="Special"> &lt;- </span>index *y, <span class="Constant">1</span> <span class="Constant">20</span>:@:char/<span class="Special">raw &lt;- </span>copy *a <span class="Constant">30</span>:@:char/<span class="Special">raw &lt;- </span>copy *b ] memory-should-contain [ <span class="Constant">10</span><span class="Special"> &lt;- </span><span class="Constant">2</span> <span class="Comment"># length of result</span> <span class="Constant">20</span>:array:character<span class="Special"> &lt;- </span><span class="Constant">[a]</span> <span class="Constant">30</span>:array:character<span class="Special"> &lt;- </span><span class="Constant">[b]</span> ] ] <span class="muScenario">scenario</span> text-split-2 [ <span class="Constant">local-scope</span> x:text<span class="Special"> &lt;- </span>new <span class="Constant">[a/b/c]</span> run [ y:&amp;:@:text<span class="Special"> &lt;- </span>split x, <span class="Constant">47/slash</span> <span class="Constant">10</span>:num/<span class="Special">raw &lt;- </span>length *y a:text<span class="Special"> &lt;- </span>index *y, <span class="Constant">0</span> b:text<span class="Special"> &lt;- </span>index *y, <span class="Constant">1</span> c:text<span class="Special"> &lt;- </span>index *y, <span class="Constant">2</span> <span class="Constant">20</span>:@:char/<span class="Special">raw &lt;- </span>copy *a <span class="Constant">30</span>:@:char/<span class="Special">raw &lt;- </span>copy *b <span class="Constant">40</span>:@:char/<span class="Special">raw &lt;- </span>copy *c ] memory-should-contain [ <span class="Constant">10</span><span class="Special"> &lt;- </span><span class="Constant">3</span> <span class="Comment"># length of result</span> <span class="Constant">20</span>:array:character<span class="Special"> &lt;- </span><span class="Constant">[a]</span> <span class="Constant">30</span>:array:character<span class="Special"> &lt;- </span><span class="Constant">[b]</span> <span class="Constant">40</span>:array:character<span class="Special"> &lt;- </span><span class="Constant">[c]</span> ] ] <span class="muScenario">scenario</span> text-split-missing [ <span class="Constant">local-scope</span> x:text<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span> run [ y:&amp;:@:text<span class="Special"> &lt;- </span>split x, <span class="Constant">47/slash</span> <span class="Constant">10</span>:num/<span class="Special">raw &lt;- </span>length *y a:text<span class="Special"> &lt;- </span>index *y, <span class="Constant">0</span> <span class="Constant">20</span>:@:char/<span class="Special">raw &lt;- </span>copy *a ] memory-should-contain [ <span class="Constant">10</span><span class="Special"> &lt;- </span><span class="Constant">1</span> <span class="Comment"># length of result</span> <span class="Constant">20</span>:array:character<span class="Special"> &lt;- </span><span class="Constant">[abc]</span> ] ] <span class="muScenario">scenario</span> text-split-empty [ <span class="Constant">local-scope</span> x:text<span class="Special"> &lt;- </span>new <span class="Constant">[]</span> run [ y:&amp;:@:text<span class="Special"> &lt;- </span>split x, <span class="Constant">47/slash</span> <span class="Constant">10</span>:num/<span class="Special">raw &lt;- </span>length *y ] memory-should-contain [ <span class="Constant">10</span><span class="Special"> &lt;- </span><span class="Constant">0</span> <span class="Comment"># empty result</span> ] ] <span class="muScenario">scenario</span> text-split-empty-piece [ <span class="Constant">local-scope</span> x:text<span class="Special"> &lt;- </span>new <span class="Constant">[a/b//c]</span> run [ y:&amp;:@:text<span class="Special"> &lt;- </span>split x:text, <span class="Constant">47/slash</span> <span class="Constant">10</span>:num/<span class="Special">raw &lt;- </span>length *y a:text<span class="Special"> &lt;- </span>index *y, <span class="Constant">0</span> b:text<span class="Special"> &lt;- </span>index *y, <span class="Constant">1</span> c:text<span class="Special"> &lt;- </span>index *y, <span class="Constant">2</span> d:text<span class="Special"> &lt;- </span>index *y, <span class="Constant">3</span> <span class="Constant">20</span>:@:char/<span class="Special">raw &lt;- </span>copy *a <span class="Constant">30</span>:@:char/<span class="Special">raw &lt;- </span>copy *b <span class="Constant">40</span>:@:char/<span class="Special">raw &lt;- </span>copy *c <span class="Constant">50</span>:@:char/<span class="Special">raw &lt;- </span>copy *d ] memory-should-contain [ <span class="Constant">10</span><span class="Special"> &lt;- </span><span class="Constant">4</span> <span class="Comment"># length of result</span> <span class="Constant">20</span>:array:character<span class="Special"> &lt;- </span><span class="Constant">[a]</span> <span class="Constant">30</span>:array:character<span class="Special"> &lt;- </span><span class="Constant">[b]</span> <span class="Constant">40</span>:array:character<span class="Special"> &lt;- </span><span class="Constant">[]</span> <span class="Constant">50</span>:array:character<span class="Special"> &lt;- </span><span class="Constant">[c]</span> ] ] <span class="muRecipe">def</span> split-first text:text, delim:char<span class="muRecipe"> -&gt; </span>x:text, y:text [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="Comment"># empty text? return empty texts</span> len:num<span class="Special"> &lt;- </span>length *text <span class="Delimiter">{</span> empty?:bool<span class="Special"> &lt;- </span>equal len, <span class="Constant">0</span> <span class="muControl">break-unless</span> empty? x:text<span class="Special"> &lt;- </span>new <span class="Constant">[]</span> y:text<span class="Special"> &lt;- </span>new <span class="Constant">[]</span> <span class="muControl">return</span> <span class="Delimiter">}</span> idx:num<span class="Special"> &lt;- </span>find-next text, delim, <span class="Constant">0</span> x:text<span class="Special"> &lt;- </span>copy-range text, <span class="Constant">0</span>, idx idx<span class="Special"> &lt;- </span>add idx, <span class="Constant">1</span> y:text<span class="Special"> &lt;- </span>copy-range text, idx, len ] <span class="muScenario">scenario</span> text-split-first [ <span class="Constant">local-scope</span> x:text<span class="Special"> &lt;- </span>new <span class="Constant">[a/b]</span> run [ y:text, z:text<span class="Special"> &lt;- </span>split-first x, <span class="Constant">47/slash</span> <span class="Constant">10</span>:@:char/<span class="Special">raw &lt;- </span>copy *y <span class="Constant">20</span>:@:char/<span class="Special">raw &lt;- </span>copy *z ] memory-should-contain [ <span class="Constant">10</span>:array:character<span class="Special"> &lt;- </span><span class="Constant">[a]</span> <span class="Constant">20</span>:array:character<span class="Special"> &lt;- </span><span class="Constant">[b]</span> ] ] <span class="muRecipe">def</span> copy-range buf:text, start:num, end:num<span class="muRecipe"> -&gt; </span>result:text [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> <span class="Comment"># if end is out of bounds, trim it</span> len:num<span class="Special"> &lt;- </span>length *buf end:num<span class="Special"> &lt;- </span>min len, end <span class="Comment"># allocate space for result</span> len<span class="Special"> &lt;- </span>subtract end, start result:text<span class="Special"> &lt;- </span>new <span class="Constant">character:type</span>, len <span class="Comment"># copy start..end into result[curr-result]</span> src-idx:num<span class="Special"> &lt;- </span>copy start dest-idx:num<span class="Special"> &lt;- </span>copy <span class="Constant">0</span> <span class="Delimiter">{</span> done?:bool<span class="Special"> &lt;- </span>greater-or-equal src-idx, end <span class="muControl">break-if</span> done? src:char<span class="Special"> &lt;- </span>index *buf, src-idx *result<span class="Special"> &lt;- </span>put-index *result, dest-idx, src src-idx<span class="Special"> &lt;- </span>add src-idx, <span class="Constant">1</span> dest-idx<span class="Special"> &lt;- </span>add dest-idx, <span class="Constant">1</span> <span class="muControl">loop</span> <span class="Delimiter">}</span> ] <span class="muScenario">scenario</span> copy-range-works [ <span class="Constant">local-scope</span> x:text<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span> run [ y:text<span class="Special"> &lt;- </span>copy-range x, <span class="Constant">1</span>, <span class="Constant">3</span> <span class="Constant">1</span>:@:char/<span class="Special">raw &lt;- </span>copy *y ] memory-should-contain [ <span class="Constant">1</span>:array:character<span class="Special"> &lt;- </span><span class="Constant">[bc]</span> ] ] <span class="muScenario">scenario</span> copy-range-out-of-bounds [ <span class="Constant">local-scope</span> x:text<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span> run [ y:text<span class="Special"> &lt;- </span>copy-range x, <span class="Constant">2</span>, <span class="Constant">4</span> <span class="Constant">1</span>:@:char/<span class="Special">raw &lt;- </span>copy *y ] memory-should-contain [ <span class="Constant">1</span>:array:character<span class="Special"> &lt;- </span><span class="Constant">[c]</span> ] ] <span class="muScenario">scenario</span> copy-range-out-of-bounds-2 [ <span class="Constant">local-scope</span> x:text<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span> run [ y:text<span class="Special"> &lt;- </span>copy-range x, <span class="Constant">3</span>, <span class="Constant">3</span> <span class="Constant">1</span>:@:char/<span class="Special">raw &lt;- </span>copy *y ] memory-should-contain [ <span class="Constant">1</span>:array:character<span class="Special"> &lt;- </span><span class="Constant">[]</span> ] ] </pre> </body> </html> <!-- vim: set foldmethod=manual : -->