SQLite wrapper

This commit is contained in:
Andreas Rumpf 2010-02-24 01:04:39 +01:00
commit f41bd71e61
43 changed files with 321 additions and 93 deletions

View file

@ -16,7 +16,7 @@ cc = gcc
path="$lib/pure" path="$lib/pure"
path="$lib/impure" path="$lib/impure"
path="$lib/wrappers" path="$lib/newwrap"
path="$lib/wrappers/cairo" path="$lib/wrappers/cairo"
path="$lib/wrappers/gtk" path="$lib/wrappers/gtk"
path="$lib/wrappers/lua" path="$lib/wrappers/lua"

View file

@ -1,5 +1,6 @@
Mario Ray Mahardhika
Philippe Lhoste Philippe Lhoste
Alexander Rødseth Mario Ray Mahardhika
Jonathan Plona
Dominik Picheta Dominik Picheta
Jonathan Plona
Alexander Rødseth

View file

@ -1,4 +1,4 @@
# Test the new CGI module # Test/show CGI module
import strtabs, cgi import strtabs, cgi

View file

@ -4,7 +4,7 @@ import
var hCurl = curl_easy_init() var hCurl = curl_easy_init()
if hCurl != nil: if hCurl != nil:
discard curl_easy_setopt(hCurl, CURLOPT_VERBOSE, True) discard curl_easy_setopt(hCurl, CURLOPT_VERBOSE, True)
discard curl_easy_setopt(hCurl, CURLOPT_URL, "http://nimrod.ethexor.com") discard curl_easy_setopt(hCurl, CURLOPT_URL, "http://force7.de/nimrod")
discard curl_easy_perform(hCurl) discard curl_easy_perform(hCurl)
curl_easy_cleanup(hCurl) curl_easy_cleanup(hCurl)

View file

@ -60,12 +60,12 @@ proc dbFormat(formatstr: TSqlQuery, args: openarray[string]): string =
else: else:
add(result, c) add(result, c)
proc TryQuery*(db: TDbConn, query: TSqlQuery, args: openarray[string]): bool = proc TryExec*(db: TDbConn, query: TSqlQuery, args: openarray[string]): bool =
## tries to execute the query and returns true if successful, false otherwise. ## tries to execute the query and returns true if successful, false otherwise.
var q = dbFormat(query, args) var q = dbFormat(query, args)
return mysqlRealQuery(db, q, q.len) == 0'i32 return mysqlRealQuery(db, q, q.len) == 0'i32
proc Query*(db: TDbConn, query: TSqlQuery, args: openarray[string]) = proc Exec*(db: TDbConn, query: TSqlQuery, args: openarray[string]) =
## executes the query and raises EDB if not successful. ## executes the query and raises EDB if not successful.
var q = dbFormat(query, args) var q = dbFormat(query, args)
if mysqlRealQuery(db, q, q.len) != 0'i32: dbError(db) if mysqlRealQuery(db, q, q.len) != 0'i32: dbError(db)
@ -84,7 +84,7 @@ iterator FastRows*(db: TDbConn, query: TSqlQuery,
## executes the query and iterates over the result dataset. This is very ## executes the query and iterates over the result dataset. This is very
## fast, but potenially dangerous: If the for-loop-body executes another ## fast, but potenially dangerous: If the for-loop-body executes another
## query, the results can be undefined. For Postgres it is safe though. ## query, the results can be undefined. For Postgres it is safe though.
Query(db, query, args) Exec(db, query, args)
var sqlres = mysqlUseResult(db) var sqlres = mysqlUseResult(db)
if sqlres != nil: if sqlres != nil:
var L = int(mysql_num_fields(sqlres)) var L = int(mysql_num_fields(sqlres))
@ -103,7 +103,7 @@ proc GetAllRows*(db: TDbConn, query: TSqlQuery,
args: openarray[string]): seq[TRow] = args: openarray[string]): seq[TRow] =
## executes the query and returns the whole result dataset. ## executes the query and returns the whole result dataset.
result = @[] result = @[]
Query(db, query, args) Exec(db, query, args)
var sqlres = mysqlUseResult(db) var sqlres = mysqlUseResult(db)
if sqlres != nil: if sqlres != nil:
var L = int(mysql_num_fields(sqlres)) var L = int(mysql_num_fields(sqlres))
@ -149,11 +149,11 @@ proc InsertID*(db: TDbConn, query: TSqlQuery, args: openArray[string]): int64 =
result = TryInsertID(db, query, args) result = TryInsertID(db, query, args)
if result < 0: dbError(db) if result < 0: dbError(db)
proc QueryAffectedRows*(db: TDbConn, query: TSqlQuery, proc ExecAffectedRows*(db: TDbConn, query: TSqlQuery,
args: openArray[string]): int64 = args: openArray[string]): int64 =
## runs the query (typically "UPDATE") and returns the ## runs the query (typically "UPDATE") and returns the
## number of affected rows ## number of affected rows
Query(db, query, args) Exec(db, query, args)
result = mysql_affected_rows(db) result = mysql_affected_rows(db)
proc Close*(db: TDbConn) = proc Close*(db: TDbConn) =

View file

@ -59,7 +59,7 @@ proc dbFormat(formatstr: TSqlQuery, args: openarray[string]): string =
else: else:
add(result, c) add(result, c)
proc TryQuery*(db: TDbConn, query: TSqlQuery, proc TryExec*(db: TDbConn, query: TSqlQuery,
args: openarray[string]): bool = args: openarray[string]): bool =
## tries to execute the query and returns true if successful, false otherwise. ## tries to execute the query and returns true if successful, false otherwise.
var q = dbFormat(query, args) var q = dbFormat(query, args)
@ -67,7 +67,7 @@ proc TryQuery*(db: TDbConn, query: TSqlQuery,
result = PQresultStatus(res) == PGRES_COMMAND_OK result = PQresultStatus(res) == PGRES_COMMAND_OK
PQclear(res) PQclear(res)
proc Query*(db: TDbConn, query: TSqlQuery, args: openarray[string]) = proc Exec*(db: TDbConn, query: TSqlQuery, args: openarray[string]) =
## executes the query and raises EDB if not successful. ## executes the query and raises EDB if not successful.
var q = dbFormat(query, args) var q = dbFormat(query, args)
var res = PQExec(db, q) var res = PQExec(db, q)
@ -143,7 +143,7 @@ proc InsertID*(db: TDbConn, query: TSqlQuery,
result = TryInsertID(db, query, args) result = TryInsertID(db, query, args)
if result < 0: dbError(db) if result < 0: dbError(db)
proc QueryAffectedRows*(db: TDbConn, query: TSqlQuery, proc ExecAffectedRows*(db: TDbConn, query: TSqlQuery,
args: openArray[string]): int64 = args: openArray[string]): int64 =
## executes the query (typically "UPDATE") and returns the ## executes the query (typically "UPDATE") and returns the
## number of affected rows. ## number of affected rows.

178
lib/impure/db_sqlite.nim Normal file
View file

@ -0,0 +1,178 @@
#
#
# Nimrod's Runtime Library
# (c) Copyright 2010 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
## A higher level `PostgreSQL`:idx: database wrapper. This interface
## is implemented for other databases too.
import strutils, sqlite3
type
TDbConn* = PSqlite3 ## encapsulates a database connection
TRow* = seq[string] ## a row of a dataset
EDb* = object of EIO ## exception that is raised if a database error occurs
TSqlQuery* = distinct string ## an SQL query string
proc sql*(query: string): TSqlQuery {.noSideEffect, inline.} =
## constructs a TSqlQuery from the string `query`. This is supposed to be
## used as a raw-string-literal modifier:
## ``sql"update user set counter = counter + 1"``
##
## If assertions are turned off, it does nothing. If assertions are turned
## on, later versions will check the string for valid syntax.
result = TSqlQuery(query)
proc dbError(db: TDbConn) {.noreturn.} =
## raises an EDb exception.
var e: ref EDb
new(e)
e.msg = $sqlite3.errmsg(db)
raise e
proc dbError*(msg: string) {.noreturn.} =
## raises an EDb exception with message `msg`.
var e: ref EDb
new(e)
e.msg = msg
raise e
proc dbQuote(s: string): string =
result = "'"
for c in items(s):
if c == '\'': add(result, "''")
else: add(result, c)
add(result, '\'')
proc dbFormat(formatstr: TSqlQuery, args: openarray[string]): string =
result = ""
var a = 0
for c in items(string(formatstr)):
if c == '?':
add(result, dbQuote(args[a]))
inc(a)
else:
add(result, c)
proc TryExec*(db: TDbConn, query: TSqlQuery,
args: openarray[string]): bool =
## tries to execute the query and returns true if successful, false otherwise.
var q = dbFormat(query, args)
var stmt: sqlite3.PStmt
if prepare_v2(db, q, q.len, stmt, nil) == SQLITE_OK:
if step(stmt) == SQLITE_DONE:
result = finalize(stmt) == SQLITE_OK
proc Exec*(db: TDbConn, query: TSqlQuery, args: openarray[string]) =
## executes the query and raises EDB if not successful.
if not TryExec(db, query, args): dbError(db)
proc newRow(L: int): TRow =
newSeq(result, L)
for i in 0..L-1: result[i] = ""
proc setupQuery(db: TDbConn, query: TSqlQuery,
args: openarray[string]): PStmt =
var q = dbFormat(query, args)
if prepare_v2(db, q, q.len, result, nil) != SQLITE_OK: dbError(db)
proc setRow(stmt: PStmt, r: var TRow, cols: int) =
for col in 0..cols-1:
setLen(r[col], column_bytes(stmt, col)) # set capacity
setLen(r[col], 0)
add(r[col], column_text(stmt, col))
iterator FastRows*(db: TDbConn, query: TSqlQuery,
args: openarray[string]): TRow =
## executes the query and iterates over the result dataset. This is very
## fast, but potenially dangerous: If the for-loop-body executes another
## query, the results can be undefined. For Sqlite it is safe though.
var stmt = setupQuery(db, query, args)
var L = int(columnCount(stmt))
var result = newRow(L)
while step(stmt) == SQLITE_ROW:
setRow(stmt, result, L)
yield result
if finalize(stmt) != SQLITE_OK: dbError(db)
proc GetAllRows*(db: TDbConn, query: TSqlQuery,
args: openarray[string]): seq[TRow] =
## executes the query and returns the whole result dataset.
result = @[]
for r in FastRows(db, query, args):
result.add(r)
iterator Rows*(db: TDbConn, query: TSqlQuery,
args: openarray[string]): TRow =
## same as `FastRows`, but slower and safe.
for r in FastRows(db, query, args): yield r
proc GetValue*(db: TDbConn, query: TSqlQuery,
args: openarray[string]): string =
## executes the query and returns the result dataset's the first column
## of the first row. Returns "" if the dataset contains no rows.
var stmt = setupQuery(db, query, args)
if step(stmt) == SQLITE_ROW:
result = newString(column_bytes(stmt, 0))
setLen(result, 0)
add(result, column_text(stmt, 0))
if finalize(stmt) != SQLITE_OK: dbError(db)
else:
result = ""
proc TryInsertID*(db: TDbConn, query: TSqlQuery,
args: openarray[string]): int64 =
## executes the query (typically "INSERT") and returns the
## generated ID for the row or -1 in case of an error.
if tryExec(db, query, args):
result = last_insert_rowid(db)
else:
result = -1
proc InsertID*(db: TDbConn, query: TSqlQuery,
args: openArray[string]): int64 =
## executes the query (typically "INSERT") and returns the
## generated ID for the row. For Postgre this adds
## ``RETURNING id`` to the query, so it only works if your primary key is
## named ``id``.
result = TryInsertID(db, query, args)
if result < 0: dbError(db)
proc ExecAffectedRows*(db: TDbConn, query: TSqlQuery,
args: openArray[string]): int64 =
## executes the query (typically "UPDATE") and returns the
## number of affected rows.
Exec(db, query, args)
result = changes(db)
proc Close*(db: TDbConn) =
## closes the database connection.
if sqlite3.close(db) != SQLITE_OK:
dbError(db)
proc Open*(connection, user, password, database: string): TDbConn =
## opens a database connection. Raises `EDb` if the connection could not
## be established. Only the ``connection`` parameter is used for ``sqlite``.
var db: TDbConn
if sqlite3.open(connection, db) == SQLITE_OK:
return db
else:
dbError(db)
when isMainModule:
var db = open("db.sql", "", "", "")
Exec(db, sql"create table tbl1(one varchar(10), two smallint)", [])
exec(db, sql"insert into tbl1 values('hello!',10)", [])
exec(db, sql"insert into tbl1 values('goodbye', 20)", [])
#db.query("create table tbl1(one varchar(10), two smallint)")
#db.query("insert into tbl1 values('hello!',10)")
#db.query("insert into tbl1 values('goodbye', 20)")
for r in db.rows(sql"select * from tbl1", []):
echo(r[0], r[1])
db_sqlite.close(db)

View file

@ -17,7 +17,7 @@
## Currently only requesting URLs is implemented. The implementation depends ## Currently only requesting URLs is implemented. The implementation depends
## on the libcurl library! ## on the libcurl library!
## ##
## **Deprecated since version 0.8.6:** Use the httpclient module instead. ## **Deprecated since version 0.8.6:** Use the ``httpclient`` module instead.
## ##
{.deprecated.} {.deprecated.}

View file

@ -96,30 +96,24 @@ const
SQLITE_TRANSIENT* = cast[pointer](- 1) SQLITE_TRANSIENT* = cast[pointer](- 1)
type type
sqlite_int64* = int64
PPPChar* = ptr ptr cstring
TSqlite3 {.pure, final.} = object TSqlite3 {.pure, final.} = object
PSqlite3* = ptr TSqlite3 PSqlite3* = ptr TSqlite3
PPSqlite3* = ptr PSqlite3 PPSqlite3* = ptr PSqlite3
TSqlLite3Context{.pure, final.} = object TContext{.pure, final.} = object
Pcontext* = ptr TSqlLite3Context Pcontext* = ptr TContext
Tstmt{.pure, final.} = object Tstmt{.pure, final.} = object
Pstmt* = ptr Tstmt Pstmt* = ptr Tstmt
PPsqlite3_stmt* = ptr Pstmt
Tvalue{.pure, final.} = object Tvalue{.pure, final.} = object
Pvalue* = ptr Tvalue Pvalue* = ptr Tvalue
PPsqlite3_value* = ptr Pvalue #Callback function types PPValue* = ptr Pvalue
#Notice that most functions
#were named using as prefix the Tcallback* = proc (para1: pointer, para2: int32, para3,
#function name that uses them, para4: cstringArray): int32{.cdecl.}
#rather than describing their functions
Tcallback* = proc (para1: pointer, para2: int32, para3: var cstring,
para4: var cstring): int32{.cdecl.}
Tbind_destructor_func* = proc (para1: pointer){.cdecl.} Tbind_destructor_func* = proc (para1: pointer){.cdecl.}
Tcreate_function_step_func* = proc (para1: Pcontext, para2: int32, Tcreate_function_step_func* = proc (para1: Pcontext, para2: int32,
para3: PPsqlite3_value){.cdecl.} para3: PPValue){.cdecl.}
Tcreate_function_func_func* = proc (para1: Pcontext, para2: int32, Tcreate_function_func_func* = proc (para1: Pcontext, para2: int32,
para3: PPsqlite3_value){.cdecl.} para3: PPValue){.cdecl.}
Tcreate_function_final_func* = proc (para1: Pcontext){.cdecl.} Tcreate_function_final_func* = proc (para1: Pcontext){.cdecl.}
Tresult_func* = proc (para1: pointer){.cdecl.} Tresult_func* = proc (para1: pointer){.cdecl.}
Tcreate_collation_func* = proc (para1: pointer, para2: int32, para3: pointer, Tcreate_collation_func* = proc (para1: pointer, para2: int32, para3: pointer,
@ -131,7 +125,7 @@ proc close*(para1: PSqlite3): int32{.cdecl, dynlib: Lib, importc: "sqlite3_close
proc exec*(para1: PSqlite3, sql: cstring, para3: Tcallback, para4: pointer, proc exec*(para1: PSqlite3, sql: cstring, para3: Tcallback, para4: pointer,
errmsg: var cstring): int32{.cdecl, dynlib: Lib, errmsg: var cstring): int32{.cdecl, dynlib: Lib,
importc: "sqlite3_exec".} importc: "sqlite3_exec".}
proc last_insert_rowid*(para1: PSqlite3): sqlite_int64{.cdecl, dynlib: Lib, proc last_insert_rowid*(para1: PSqlite3): int64{.cdecl, dynlib: Lib,
importc: "sqlite3_last_insert_rowid".} importc: "sqlite3_last_insert_rowid".}
proc changes*(para1: PSqlite3): int32{.cdecl, dynlib: Lib, importc: "sqlite3_changes".} proc changes*(para1: PSqlite3): int32{.cdecl, dynlib: Lib, importc: "sqlite3_changes".}
proc total_changes*(para1: PSqlite3): int32{.cdecl, dynlib: Lib, proc total_changes*(para1: PSqlite3): int32{.cdecl, dynlib: Lib,
@ -183,10 +177,15 @@ proc errcode*(db: PSqlite3): int32{.cdecl, dynlib: Lib, importc: "sqlite3_errcod
proc errmsg*(para1: PSqlite3): cstring{.cdecl, dynlib: Lib, importc: "sqlite3_errmsg".} proc errmsg*(para1: PSqlite3): cstring{.cdecl, dynlib: Lib, importc: "sqlite3_errmsg".}
proc errmsg16*(para1: PSqlite3): pointer{.cdecl, dynlib: Lib, proc errmsg16*(para1: PSqlite3): pointer{.cdecl, dynlib: Lib,
importc: "sqlite3_errmsg16".} importc: "sqlite3_errmsg16".}
proc prepare*(db: PSqlite3, zSql: cstring, nBytes: int32, ppStmt: PPsqlite3_stmt, proc prepare*(db: PSqlite3, zSql: cstring, nBytes: int32, ppStmt: var PStmt,
pzTail: ptr cstring): int32{.cdecl, dynlib: Lib, pzTail: ptr cstring): int32{.cdecl, dynlib: Lib,
importc: "sqlite3_prepare".} importc: "sqlite3_prepare".}
proc prepare16*(db: PSqlite3, zSql: pointer, nBytes: int32, ppStmt: PPsqlite3_stmt,
proc prepare_v2*(db: PSqlite3, zSql: cstring, nByte: cint, ppStmt: var PStmt,
pzTail: ptr cstring): cint {.
importc: "sqlite3_prepare_v2", cdecl, dynlib: Lib.}
proc prepare16*(db: PSqlite3, zSql: pointer, nBytes: int32, ppStmt: var PStmt,
pzTail: var pointer): int32{.cdecl, dynlib: Lib, pzTail: var pointer): int32{.cdecl, dynlib: Lib,
importc: "sqlite3_prepare16".} importc: "sqlite3_prepare16".}
proc bind_blob*(para1: Pstmt, para2: int32, para3: pointer, n: int32, proc bind_blob*(para1: Pstmt, para2: int32, para3: pointer, n: int32,
@ -196,7 +195,7 @@ proc bind_double*(para1: Pstmt, para2: int32, para3: float64): int32{.cdecl,
dynlib: Lib, importc: "sqlite3_bind_double".} dynlib: Lib, importc: "sqlite3_bind_double".}
proc bind_int*(para1: Pstmt, para2: int32, para3: int32): int32{.cdecl, proc bind_int*(para1: Pstmt, para2: int32, para3: int32): int32{.cdecl,
dynlib: Lib, importc: "sqlite3_bind_int".} dynlib: Lib, importc: "sqlite3_bind_int".}
proc bind_int64*(para1: Pstmt, para2: int32, para3: sqlite_int64): int32{.cdecl, proc bind_int64*(para1: Pstmt, para2: int32, para3: int64): int32{.cdecl,
dynlib: Lib, importc: "sqlite3_bind_int64".} dynlib: Lib, importc: "sqlite3_bind_int64".}
proc bind_null*(para1: Pstmt, para2: int32): int32{.cdecl, dynlib: Lib, proc bind_null*(para1: Pstmt, para2: int32): int32{.cdecl, dynlib: Lib,
importc: "sqlite3_bind_null".} importc: "sqlite3_bind_null".}
@ -248,7 +247,7 @@ proc column_double*(para1: Pstmt, iCol: int32): float64{.cdecl, dynlib: Lib,
importc: "sqlite3_column_double".} importc: "sqlite3_column_double".}
proc column_int*(para1: Pstmt, iCol: int32): int32{.cdecl, dynlib: Lib, proc column_int*(para1: Pstmt, iCol: int32): int32{.cdecl, dynlib: Lib,
importc: "sqlite3_column_int".} importc: "sqlite3_column_int".}
proc column_int64*(para1: Pstmt, iCol: int32): sqlite_int64{.cdecl, dynlib: Lib, proc column_int64*(para1: Pstmt, iCol: int32): int64{.cdecl, dynlib: Lib,
importc: "sqlite3_column_int64".} importc: "sqlite3_column_int64".}
proc column_text*(para1: Pstmt, iCol: int32): cstring{.cdecl, dynlib: Lib, proc column_text*(para1: Pstmt, iCol: int32): cstring{.cdecl, dynlib: Lib,
importc: "sqlite3_column_text".} importc: "sqlite3_column_text".}
@ -283,7 +282,7 @@ proc value_double*(para1: Pvalue): float64{.cdecl, dynlib: Lib,
importc: "sqlite3_value_double".} importc: "sqlite3_value_double".}
proc value_int*(para1: Pvalue): int32{.cdecl, dynlib: Lib, proc value_int*(para1: Pvalue): int32{.cdecl, dynlib: Lib,
importc: "sqlite3_value_int".} importc: "sqlite3_value_int".}
proc value_int64*(para1: Pvalue): sqlite_int64{.cdecl, dynlib: Lib, proc value_int64*(para1: Pvalue): int64{.cdecl, dynlib: Lib,
importc: "sqlite3_value_int64".} importc: "sqlite3_value_int64".}
proc value_text*(para1: Pvalue): cstring{.cdecl, dynlib: Lib, proc value_text*(para1: Pvalue): cstring{.cdecl, dynlib: Lib,
importc: "sqlite3_value_text".} importc: "sqlite3_value_text".}
@ -315,7 +314,7 @@ proc result_error16*(para1: Pcontext, para2: pointer, para3: int32){.cdecl,
dynlib: Lib, importc: "sqlite3_result_error16".} dynlib: Lib, importc: "sqlite3_result_error16".}
proc result_int*(para1: Pcontext, para2: int32){.cdecl, dynlib: Lib, proc result_int*(para1: Pcontext, para2: int32){.cdecl, dynlib: Lib,
importc: "sqlite3_result_int".} importc: "sqlite3_result_int".}
proc result_int64*(para1: Pcontext, para2: sqlite_int64){.cdecl, dynlib: Lib, proc result_int64*(para1: Pcontext, para2: int64){.cdecl, dynlib: Lib,
importc: "sqlite3_result_int64".} importc: "sqlite3_result_int64".}
proc result_null*(para1: Pcontext){.cdecl, dynlib: Lib, proc result_null*(para1: Pcontext){.cdecl, dynlib: Lib,
importc: "sqlite3_result_null".} importc: "sqlite3_result_null".}

View file

@ -1,7 +1,7 @@
# #
# #
# Nimrod's Runtime Library # Nimrod's Runtime Library
# (c) Copyright 2009 Andreas Rumpf # (c) Copyright 2010 Andreas Rumpf
# #
# See the file "copying.txt", included in this # See the file "copying.txt", included in this
# distribution, for details about the copyright. # distribution, for details about the copyright.
@ -35,41 +35,41 @@ type
iterator objectFields*[T](x: T, skipInherited: bool): tuple[ iterator objectFields*[T](x: T, skipInherited: bool): tuple[
key: string, val: TVariant] {.magic: "ObjectFields"} key: string, val: TVariant] {.magic: "ObjectFields"}
proc `<>`*(x: ordinal): TVariant = proc `?`*(x: ordinal): TVariant =
result.kind = vtEnum result.kind = vtEnum
result.vint = x result.vint = x
proc `<>`*(x: biggestInt): TVariant = proc `?`*(x: biggestInt): TVariant =
result.kind = vtInt result.kind = vtInt
result.vint = x result.vint = x
proc `<>`*(x: char): TVariant = proc `?`*(x: char): TVariant =
result.kind = vtChar result.kind = vtChar
result.vint = ord(x) result.vint = ord(x)
proc `<>`*(x: bool): TVariant = proc `?`*(x: bool): TVariant =
result.kind = vtBool result.kind = vtBool
result.vint = ord(x) result.vint = ord(x)
proc `<>`*(x: biggestFloat): TVariant = proc `?`*(x: biggestFloat): TVariant =
result.kind = vtFloat result.kind = vtFloat
result.vfloat = x result.vfloat = x
proc `<>`*(x: string): TVariant = proc `?`*(x: string): TVariant =
result.kind = vtString result.kind = vtString
result.vstring = x result.vstring = x
proc `<>`*[T](x: openArray[T]): TVariant = proc `?`*[T](x: openArray[T]): TVariant =
result.kind = vtSeq result.kind = vtSeq
newSeq(result.q, x.len) newSeq(result.q, x.len)
for i in 0..x.len-1: result.q[i] = <>x[i] for i in 0..x.len-1: result.q[i] = <>x[i]
proc `<>`*[T](x: set[T]): TVariant = proc `?`*[T](x: set[T]): TVariant =
result.kind = vtSet result.kind = vtSet
result.q = @[] result.q = @[]
for a in items(x): result.q.add(<>a) for a in items(x): result.q.add(<>a)
proc `<>`* [T: object](x: T): TVariant {.magic: "ToVariant".} proc `?`* [T: object](x: T): TVariant {.magic: "ToVariant".}
## this converts a value to a variant ("boxing") ## this converts a value to a variant ("boxing")
proc `><`*[T](v: TVariant, typ: T): T {.magic: "FromVariant".} proc `><`*[T](v: TVariant, typ: T): T {.magic: "FromVariant".}
@ -140,10 +140,10 @@ proc `[]=`* (a, b, c: TVariant) =
variantError() variantError()
else: variantError() else: variantError()
proc `[]`* (a: TVariant, b: int): TVariant {.inline} = return a[<>b] proc `[]`* (a: TVariant, b: int): TVariant {.inline} = return a[?b]
proc `[]`* (a: TVariant, b: string): TVariant {.inline} = return a[<>b] proc `[]`* (a: TVariant, b: string): TVariant {.inline} = return a[?b]
proc `[]=`* (a: TVariant, b: int, c: TVariant) {.inline} = a[<>b] = c proc `[]=`* (a: TVariant, b: int, c: TVariant) {.inline} = a[?b] = c
proc `[]=`* (a: TVariant, b: string, c: TVariant) {.inline} = a[<>b] = c proc `[]=`* (a: TVariant, b: string, c: TVariant) {.inline} = a[?b] = c
proc `+`* (x, y: TVariant): TVariant = proc `+`* (x, y: TVariant): TVariant =
case x.vtype case x.vtype

View file

@ -133,6 +133,22 @@ proc skip(my: var TYamlLexer) =
var buf = my.buf var buf = my.buf
while true: while true:
case buf[pos] case buf[pos]
of '#':
# skip line comment:
inc(pos)
while true:
case buf[pos]
of '\0': break
of '\c':
pos = lexbase.HandleCR(my, pos)
buf = my.buf
break
of '\L':
pos = lexbase.HandleLF(my, pos)
buf = my.buf
break
else:
inc(pos)
of '/': of '/':
if buf[pos+1] == '/': if buf[pos+1] == '/':
# skip line comment: # skip line comment:
@ -186,6 +202,26 @@ proc skip(my: var TYamlLexer) =
break break
my.bufpos = pos my.bufpos = pos
proc parseDirective(my: var TYamlLexer) =
var pos = my.bufpos
var buf = my.buf
inc(pos)
while buf[pos] in {'\t', ' '}: inc(pos)
while true:
case buf[pos]
of '\0': break
of '\c':
pos = lexbase.HandleCR(my, pos)
buf = my.buf
break
of '\L':
pos = lexbase.HandleLF(my, pos)
buf = my.buf
break
else:
add(my.a, buf[pos])
inc(pos)
proc parseNumber(my: var TYamlLexer) = proc parseNumber(my: var TYamlLexer) =
var pos = my.bufpos var pos = my.bufpos
var buf = my.buf var buf = my.buf
@ -230,11 +266,16 @@ proc getTok(my: var TYamlLexer): TTokKind =
setLen(my.a, 0) setLen(my.a, 0)
skip(my) # skip whitespace, comments skip(my) # skip whitespace, comments
case my.buf[my.bufpos] case my.buf[my.bufpos]
of '-':
inc(my.bufpos)
result = tkHyphen
of '-', '.', '0'..'9': of '-', '.', '0'..'9':
parseNumber(my) parseNumber(my)
result = tkNumber result = tkNumber
of '"': of '"':
result = parseString(my) result = parseString(my)
of '\'':
result = parseSingleQuote(my)
of '[': of '[':
inc(my.bufpos) inc(my.bufpos)
result = tkBracketLe result = tkBracketLe
@ -253,8 +294,30 @@ proc getTok(my: var TYamlLexer): TTokKind =
of ':': of ':':
inc(my.bufpos) inc(my.bufpos)
result = tkColon result = tkColon
of '\0': of '?':
result = tkEof inc(my.bufpos)
result = tkQust
of '!':
inc(my.bufpos)
result = tkExcl
of '&':
inc(my.bufpos)
result = tkAmp
of '*':
inc(my.bufpos)
result = tkStar
of '|':
parseLiteralBlockScalar(my)
result = tkLiteralBlockScalar
of '>':
parseFoldedBlockScalar(my)
result = tkFoldedBlockScalar
of '%':
parseDirective(my)
result = tkDirective
of '@', '`':
inc(my.bufpos)
result = tkReserved
of 'a'..'z', 'A'..'Z', '_': of 'a'..'z', 'A'..'Z', '_':
parseName(my) parseName(my)
case my.a case my.a
@ -262,6 +325,8 @@ proc getTok(my: var TYamlLexer): TTokKind =
of "true": result = tkTrue of "true": result = tkTrue
of "false": result = tkFalse of "false": result = tkFalse
else: result = tkError else: result = tkError
of '\0':
result = tkEof
else: else:
inc(my.bufpos) inc(my.bufpos)
result = tkError result = tkError

View file

@ -1,7 +1,7 @@
# #
# #
# Nimrod's Runtime Library # Nimrod's Runtime Library
# (c) Copyright 2009 Andreas Rumpf # (c) Copyright 2010 Andreas Rumpf
# #
# See the file "copying.txt", included in this # See the file "copying.txt", included in this
# distribution, for details about the copyright. # distribution, for details about the copyright.
@ -112,8 +112,8 @@ type
#were named using as prefix the #were named using as prefix the
#function name that uses them, #function name that uses them,
#rather than describing their functions #rather than describing their functions
Tsqlite3_callback* = proc (para1: pointer, para2: int32, para3: var cstring, Tsqlite3_callback* = proc (para1: pointer, para2: int32, para3,
para4: var cstring): int32{.cdecl.} para4: cstringArray): int32{.cdecl.}
Tbind_destructor_func* = proc (para1: pointer){.cdecl.} Tbind_destructor_func* = proc (para1: pointer){.cdecl.}
Tcreate_function_step_func* = proc (para1: Psqlite3_context, para2: int32, Tcreate_function_step_func* = proc (para1: Psqlite3_context, para2: int32,
para3: PPsqlite3_value){.cdecl.} para3: PPsqlite3_value){.cdecl.}

View file

@ -1,34 +0,0 @@
# Hallo world program
echo("Hi! What's your name?")
var name = readLine(stdin)
if name == "Andreas":
echo("What a nice name!")
elif name == "":
echo("Don't you have a name?")
else:
echo("Your name is not Andreas...")
for i in 0..name.len-1:
if name[i] == 'm':
echo("hey, there is an *m* in your name!")
echo("Please give your password: (12345)")
var pw = readLine(stdin)
while pw != "12345":
echo("Wrong password! Next try: ")
pw = readLine(stdin)
echo("""Login complete!
What do you want to do?
delete-everything
restart-computer
go-for-a-walk""")
case readline(stdin)
of "delete-everything", "restart-computer":
echo("permission denied")
of "go-for-a-walk": echo("please yourself")
else: echo("unknown command")

5
tests/reject/tatomic.nim Normal file
View file

@ -0,0 +1,5 @@
var
atomic: int
echo atomic

14
tests/testdata/doc1.xml vendored Normal file
View file

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8" ?>
<root>
<tag>
<test arg="blah" arg2="test"/>
<test2>
bla ah absy hsh
hsh
sjj
</test2>
<test><teh>bla</teh></test>
</tag>
</root>