diff options
author | Andreas Rumpf <ar@kimeta.de> | 2014-04-13 00:40:17 +0200 |
---|---|---|
committer | Andreas Rumpf <ar@kimeta.de> | 2014-04-13 00:40:17 +0200 |
commit | 2e9950afe8911f27560c32d2f26d2d5c6d6e6cd3 (patch) | |
tree | ff8c11fdc144ffda92f7e83cbde7e655903d2380 /lib | |
parent | fe387888bdd0ae26fe88e886604f9e101634633d (diff) | |
parent | e333b8bc1ef27014066172c04881df191a4971fe (diff) | |
download | Nim-2e9950afe8911f27560c32d2f26d2d5c6d6e6cd3.tar.gz |
Merge branch 'devel' of https://github.com/Araq/Nimrod into devel
Diffstat (limited to 'lib')
-rw-r--r-- | lib/pure/json.nim | 111 | ||||
-rw-r--r-- | lib/pure/math.nim | 4 | ||||
-rw-r--r-- | lib/pure/streams.nim | 80 | ||||
-rw-r--r-- | lib/pure/strutils.nim | 20 | ||||
-rw-r--r-- | lib/system/jssys.nim | 54 |
5 files changed, 188 insertions, 81 deletions
diff --git a/lib/pure/json.nim b/lib/pure/json.nim index 7424bbae9..4250847e5 100644 --- a/lib/pure/json.nim +++ b/lib/pure/json.nim @@ -861,26 +861,97 @@ proc parseJson(p: var TJsonParser): PJsonNode = of tkError, tkCurlyRi, tkBracketRi, tkColon, tkComma, tkEof: raiseParseErr(p, "{") -proc parseJson*(s: PStream, filename: string): PJsonNode = - ## Parses from a stream `s` into a `PJsonNode`. `filename` is only needed - ## for nice error messages. - var p: TJsonParser - p.open(s, filename) - discard getTok(p) # read first token - result = p.parseJson() - p.close() - -proc parseJson*(buffer: string): PJsonNode = - ## Parses JSON from `buffer`. - result = parseJson(newStringStream(buffer), "input") - -proc parseFile*(filename: string): PJsonNode = - ## Parses `file` into a `PJsonNode`. - var stream = newFileStream(filename, fmRead) - if stream == nil: - raise newException(EIO, "cannot read from file: " & filename) - result = parseJson(stream, filename) - +when not defined(js): + proc parseJson*(s: PStream, filename: string): PJsonNode = + ## Parses from a stream `s` into a `PJsonNode`. `filename` is only needed + ## for nice error messages. + var p: TJsonParser + p.open(s, filename) + discard getTok(p) # read first token + result = p.parseJson() + p.close() + + proc parseJson*(buffer: string): PJsonNode = + ## Parses JSON from `buffer`. + result = parseJson(newStringStream(buffer), "input") + + proc parseFile*(filename: string): PJsonNode = + ## Parses `file` into a `PJsonNode`. + var stream = newFileStream(filename, fmRead) + if stream == nil: + raise newException(EIO, "cannot read from file: " & filename) + result = parseJson(stream, filename) +else: + from math import `mod` + type + TJSObject = object + proc parseNativeJson(x: cstring): TJSObject {.importc: "JSON.parse".} + + proc getVarType(x): TJsonNodeKind = + result = JNull + proc getProtoName(y): cstring + {.importc: "Object.prototype.toString.call".} + case $getProtoName(x) # TODO: Implicit returns fail here. + of "[object Array]": return JArray + of "[object Object]": return JObject + of "[object Number]": + if cast[float](x) mod 1.0 == 0: + return JInt + else: + return JFloat + of "[object Boolean]": return JBool + of "[object Null]": return JNull + of "[object String]": return JString + else: assert false + + proc len(x: TJSObject): int = + assert x.getVarType == JArray + asm """ + return `x`.length; + """ + + proc `[]`(x: TJSObject, y: string): TJSObject = + assert x.getVarType == JObject + asm """ + return `x`[`y`]; + """ + + proc `[]`(x: TJSObject, y: int): TJSObject = + assert x.getVarType == JArray + asm """ + return `x`[`y`]; + """ + + proc convertObject(x: TJSObject): PJsonNode = + case getVarType(x) + of JArray: + result = newJArray() + for i in 0 .. <x.len: + result.add(x[i].convertObject()) + of JObject: + result = newJObject() + asm """for (property in `x`) { + if (`x`.hasOwnProperty(property)) { + """ + var nimProperty: cstring + var nimValue: TJSObject + asm "`nimProperty` = property; `nimValue` = `x`[property];" + result[$nimProperty] = nimValue.convertObject() + asm "}}" + of JInt: + result = newJInt(cast[int](x)) + of JFloat: + result = newJFloat(cast[float](x)) + of JString: + result = newJString($cast[cstring](x)) + of JBool: + result = newJBool(cast[bool](x)) + of JNull: + result = newJNull() + + proc parseJson*(buffer: string): PJsonNode = + return parseNativeJson(buffer).convertObject() + when false: import os var s = newFileStream(ParamStr(1), fmRead) diff --git a/lib/pure/math.nim b/lib/pure/math.nim index d258e9a7c..3997b059f 100644 --- a/lib/pure/math.nim +++ b/lib/pure/math.nim @@ -19,8 +19,8 @@ when defined(Posix) and not defined(haiku): {.passl: "-lm".} - -import times +when not defined(js): + import times const PI* = 3.1415926535897932384626433 ## the circle constant PI (Ludolph's number) diff --git a/lib/pure/streams.nim b/lib/pure/streams.nim index e944dd2fc..3b6dc87a5 100644 --- a/lib/pure/streams.nim +++ b/lib/pure/streams.nim @@ -239,45 +239,47 @@ proc newStringStream*(s: string = ""): PStringStream = result.readDataImpl = ssReadData result.writeDataImpl = ssWriteData -type - PFileStream* = ref TFileStream ## a stream that encapsulates a `TFile` - TFileStream* = object of TStream - f: TFile - -proc fsClose(s: PStream) = - if PFileStream(s).f != nil: - close(PFileStream(s).f) - PFileStream(s).f = nil -proc fsFlush(s: PStream) = flushFile(PFileStream(s).f) -proc fsAtEnd(s: PStream): bool = return endOfFile(PFileStream(s).f) -proc fsSetPosition(s: PStream, pos: int) = setFilePos(PFileStream(s).f, pos) -proc fsGetPosition(s: PStream): int = return int(getFilePos(PFileStream(s).f)) - -proc fsReadData(s: PStream, buffer: pointer, bufLen: int): int = - result = readBuffer(PFileStream(s).f, buffer, bufLen) - -proc fsWriteData(s: PStream, buffer: pointer, bufLen: int) = - if writeBuffer(PFileStream(s).f, buffer, bufLen) != bufLen: - raise newEIO("cannot write to stream") - -proc newFileStream*(f: TFile): PFileStream = - ## creates a new stream from the file `f`. - new(result) - result.f = f - result.closeImpl = fsClose - result.atEndImpl = fsAtEnd - result.setPositionImpl = fsSetPosition - result.getPositionImpl = fsGetPosition - result.readDataImpl = fsReadData - result.writeDataImpl = fsWriteData - result.flushImpl = fsFlush - -proc newFileStream*(filename: string, mode: TFileMode): PFileStream = - ## creates a new stream from the file named `filename` with the mode `mode`. - ## If the file cannot be opened, nil is returned. See the `system - ## <system.html>`_ module for a list of available TFileMode enums. - var f: TFile - if open(f, filename, mode): result = newFileStream(f) +when not defined(js): + + type + PFileStream* = ref TFileStream ## a stream that encapsulates a `TFile` + TFileStream* = object of TStream + f: TFile + + proc fsClose(s: PStream) = + if PFileStream(s).f != nil: + close(PFileStream(s).f) + PFileStream(s).f = nil + proc fsFlush(s: PStream) = flushFile(PFileStream(s).f) + proc fsAtEnd(s: PStream): bool = return endOfFile(PFileStream(s).f) + proc fsSetPosition(s: PStream, pos: int) = setFilePos(PFileStream(s).f, pos) + proc fsGetPosition(s: PStream): int = return int(getFilePos(PFileStream(s).f)) + + proc fsReadData(s: PStream, buffer: pointer, bufLen: int): int = + result = readBuffer(PFileStream(s).f, buffer, bufLen) + + proc fsWriteData(s: PStream, buffer: pointer, bufLen: int) = + if writeBuffer(PFileStream(s).f, buffer, bufLen) != bufLen: + raise newEIO("cannot write to stream") + + proc newFileStream*(f: TFile): PFileStream = + ## creates a new stream from the file `f`. + new(result) + result.f = f + result.closeImpl = fsClose + result.atEndImpl = fsAtEnd + result.setPositionImpl = fsSetPosition + result.getPositionImpl = fsGetPosition + result.readDataImpl = fsReadData + result.writeDataImpl = fsWriteData + result.flushImpl = fsFlush + + proc newFileStream*(filename: string, mode: TFileMode): PFileStream = + ## creates a new stream from the file named `filename` with the mode `mode`. + ## If the file cannot be opened, nil is returned. See the `system + ## <system.html>`_ module for a list of available TFileMode enums. + var f: TFile + if open(f, filename, mode): result = newFileStream(f) when true: diff --git a/lib/pure/strutils.nim b/lib/pure/strutils.nim index b63224cec..bd6814dcc 100644 --- a/lib/pure/strutils.nim +++ b/lib/pure/strutils.nim @@ -264,6 +264,19 @@ iterator split*(s: string, sep: char): string = yield substr(s, first, last-1) inc(last) +iterator split*(s: string, sep: string): string = + ## Splits the string `s` into substrings using a string separator. + ## + ## Substrings are separated by the string `sep`. + var last = 0 + if len(s) > 0: + while last <= len(s): + var first = last + while last < len(s) and s.substr(last, last + <sep.len) != sep: + inc(last) + yield substr(s, first, last-1) + inc(last, sep.len) + iterator splitLines*(s: string): string = ## Splits the string `s` into its containing lines. Every newline ## combination (CR, LF, CR-LF) is supported. The result strings contain @@ -329,6 +342,13 @@ proc split*(s: string, sep: char): seq[string] {.noSideEffect, ## of substrings. accumulateResult(split(s, sep)) +proc split*(s: string, sep: string): seq[string] {.noSideEffect, + rtl, extern: "nsuSplitString".} = + ## Splits the string `s` into substrings using a string separator. + ## + ## Substrings are separated by the string `sep`. + accumulateResult(split(s, sep)) + proc toHex*(x: BiggestInt, len: int): string {.noSideEffect, rtl, extern: "nsuToHex".} = ## Converts `x` to its hexadecimal representation. The resulting string diff --git a/lib/system/jssys.nim b/lib/system/jssys.nim index 1720804c4..52f8873cf 100644 --- a/lib/system/jssys.nim +++ b/lib/system/jssys.nim @@ -12,7 +12,7 @@ when defined(nodejs): else: proc alert*(s: cstring) {.importc, nodecl.} -proc log*(s: cstring) {.importc: "console.log", nodecl.} +proc log*(s: cstring) {.importc: "console.log", varargs, nodecl.} type PSafePoint = ptr TSafePoint @@ -27,11 +27,19 @@ type line: int # current line number filename: cstring + PJSError = ref object + columnNumber {.importc.}: int + fileName {.importc.}: cstring + lineNumber {.importc.}: int + message {.importc.}: cstring + stack {.importc.}: cstring + var framePtr {.importc, nodecl, volatile.}: PCallFrame excHandler {.importc, nodecl, volatile.}: PSafePoint = nil # list of exception handlers # a global variable for the root of all try blocks + lastJSError {.importc, nodecl, volatile.}: PJSError = nil {.push stacktrace: off, profiler:off.} proc nimBoolToStr(x: bool): string {.compilerproc.} = @@ -43,8 +51,12 @@ proc nimCharToStr(x: char): string {.compilerproc.} = result[0] = x proc getCurrentExceptionMsg*(): string = - if excHandler != nil: return $excHandler.exc.msg - return "" + if excHandler != nil and excHandler.exc != nil: + return $excHandler.exc.msg + elif lastJSError != nil: + return $lastJSError.message + else: + return "" proc auxWriteStackTrace(f: PCallFrame): string = type @@ -77,11 +89,13 @@ proc auxWriteStackTrace(f: PCallFrame): string = add(result, "\n") proc rawWriteStackTrace(): string = - if framePtr == nil: - result = "No stack traceback available\n" - else: - result = "Traceback (most recent call last)\n"& auxWriteStackTrace(framePtr) + if framePtr != nil: + result = "Traceback (most recent call last)\n" & auxWriteStackTrace(framePtr) framePtr = nil + elif lastJSError != nil: + result = $lastJSError.stack + else: + result = "No stack traceback available\n" proc raiseException(e: ref E_Base, ename: cstring) {. compilerproc, asmNoStackFrame.} = @@ -472,17 +486,17 @@ proc ze*(a: int): int {.compilerproc.} = proc ze64*(a: int64): int64 {.compilerproc.} = result = a -proc ToU8(a: int): int8 {.asmNoStackFrame, compilerproc.} = +proc toU8*(a: int): int8 {.asmNoStackFrame, compilerproc.} = asm """ return `a`; """ -proc ToU16(a: int): int16 {.asmNoStackFrame, compilerproc.} = +proc toU16*(a: int): int16 {.asmNoStackFrame, compilerproc.} = asm """ return `a`; """ -proc ToU32(a: int): int32 {.asmNoStackFrame, compilerproc.} = +proc toU32*(a: int64): int32 {.asmNoStackFrame, compilerproc.} = asm """ return `a`; """ @@ -503,17 +517,17 @@ proc nimCopy(x: pointer, ti: PNimType): pointer {.compilerproc.} proc nimCopyAux(dest, src: Pointer, n: ptr TNimNode) {.compilerproc.} = case n.kind - of nkNone: sysAssert(false, "NimCopyAux") + of nkNone: sysAssert(false, "nimCopyAux") of nkSlot: - asm "`dest`[`n`.offset] = NimCopy(`src`[`n`.offset], `n`.typ);" + asm "`dest`[`n`.offset] = nimCopy(`src`[`n`.offset], `n`.typ);" of nkList: for i in 0..n.len-1: - NimCopyAux(dest, src, n.sons[i]) + nimCopyAux(dest, src, n.sons[i]) of nkCase: asm """ - `dest`[`n`.offset] = NimCopy(`src`[`n`.offset], `n`.typ); + `dest`[`n`.offset] = nimCopy(`src`[`n`.offset], `n`.typ); for (var i = 0; i < `n`.sons.length; ++i) { - NimCopyAux(`dest`, `src`, `n`.sons[i][1]); + nimCopyAux(`dest`, `src`, `n`.sons[i][1]); } """ @@ -534,17 +548,17 @@ proc nimCopy(x: pointer, ti: PNimType): pointer = for (var key in `x`) { `result`[key] = `x`[key]; } """ of tyTuple, tyObject: - if ti.base != nil: result = NimCopy(x, ti.base) + if ti.base != nil: result = nimCopy(x, ti.base) elif ti.kind == tyObject: asm "`result` = {m_type: `ti`};" else: asm "`result` = {};" - NimCopyAux(result, x, ti.node) + nimCopyAux(result, x, ti.node) of tySequence, tyArrayConstr, tyOpenArray, tyArray: asm """ `result` = new Array(`x`.length); for (var i = 0; i < `x`.length; ++i) { - `result`[i] = NimCopy(`x`[i], `ti`.base); + `result`[i] = nimCopy(`x`[i], `ti`.base); } """ of tyString: @@ -584,12 +598,12 @@ proc genericReset(x: Pointer, ti: PNimType): pointer {.compilerproc.} = else: result = nil -proc ArrayConstr(len: int, value: pointer, typ: PNimType): pointer {. +proc arrayConstr(len: int, value: pointer, typ: PNimType): pointer {. asmNoStackFrame, compilerproc.} = # types are fake asm """ var result = new Array(`len`); - for (var i = 0; i < `len`; ++i) result[i] = NimCopy(`value`, `typ`); + for (var i = 0; i < `len`; ++i) result[i] = nimCopy(`value`, `typ`); return result; """ |