summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--lib/pure/json.nim111
-rw-r--r--lib/pure/math.nim4
-rw-r--r--lib/pure/streams.nim80
3 files changed, 134 insertions, 61 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: