Merge branch 'devel' of https://github.com/Araq/Nimrod into devel
This commit is contained in:
commit
2e9950afe8
10 changed files with 313 additions and 85 deletions
|
|
@ -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()
|
||||
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 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()
|
||||
|
||||
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 false:
|
||||
import os
|
||||
var s = newFileStream(ParamStr(1), fmRead)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
when not defined(js):
|
||||
|
||||
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))
|
||||
type
|
||||
PFileStream* = ref TFileStream ## a stream that encapsulates a `TFile`
|
||||
TFileStream* = object of TStream
|
||||
f: TFile
|
||||
|
||||
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 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 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 fsReadData(s: PStream, buffer: pointer, bufLen: int): int =
|
||||
result = readBuffer(PFileStream(s).f, buffer, bufLen)
|
||||
|
||||
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)
|
||||
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:
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
"""
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue