vmmarshal.nim 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. #
  2. #
  3. # The Nim Compiler
  4. # (c) Copyright 2015 Andreas Rumpf
  5. #
  6. # See the file "copying.txt", included in this
  7. # distribution, for details about the copyright.
  8. #
  9. ## Implements marshaling for the VM.
  10. import ast, astalgo, idents, types, msgs,
  11. options, lineinfos
  12. import std/[streams, json, intsets, tables]
  13. when defined(nimPreviewSlimSystem):
  14. import std/[assertions, formatfloat]
  15. proc ptrToInt(x: PNode): int {.inline.} =
  16. result = cast[int](x) # don't skip alignment
  17. proc getField(n: PNode; position: int): PSym =
  18. case n.kind
  19. of nkRecList:
  20. result = nil
  21. for i in 0..<n.len:
  22. result = getField(n[i], position)
  23. if result != nil: return
  24. of nkRecCase:
  25. result = getField(n[0], position)
  26. if result != nil: return
  27. for i in 1..<n.len:
  28. case n[i].kind
  29. of nkOfBranch, nkElse:
  30. result = getField(lastSon(n[i]), position)
  31. if result != nil: return
  32. else: discard
  33. of nkSym:
  34. if n.sym.position == position: result = n.sym
  35. else: result = nil
  36. else: result = nil
  37. proc storeAny(s: var string; t: PType; a: PNode; stored: var IntSet; conf: ConfigRef)
  38. proc storeObj(s: var string; typ: PType; x: PNode; stored: var IntSet; conf: ConfigRef) =
  39. assert x.kind == nkObjConstr
  40. let start = 1
  41. for i in start..<x.len:
  42. if i > start: s.add(", ")
  43. var it = x[i]
  44. if it.kind == nkExprColonExpr:
  45. if it[0].kind == nkSym:
  46. let field = it[0].sym
  47. s.add(escapeJson(field.name.s))
  48. s.add(": ")
  49. storeAny(s, field.typ, it[1], stored, conf)
  50. elif typ.n != nil:
  51. let field = getField(typ.n, i)
  52. s.add(escapeJson(field.name.s))
  53. s.add(": ")
  54. storeAny(s, field.typ, it, stored, conf)
  55. proc storeAny(s: var string; t: PType; a: PNode; stored: var IntSet;
  56. conf: ConfigRef) =
  57. case t.kind
  58. of tyNone: assert false
  59. of tyBool: s.add($(a.intVal != 0))
  60. of tyChar:
  61. let ch = char(a.intVal)
  62. if ch < '\128':
  63. s.add(escapeJson($ch))
  64. else:
  65. s.add($int(ch))
  66. of tyArray, tySequence:
  67. if t.kind == tySequence and a.kind == nkNilLit: s.add("null")
  68. else:
  69. s.add("[")
  70. for i in 0..<a.len:
  71. if i > 0: s.add(", ")
  72. storeAny(s, t.elemType, a[i], stored, conf)
  73. s.add("]")
  74. of tyTuple:
  75. s.add("{")
  76. for i, ti in t.ikids:
  77. if i > 0: s.add(", ")
  78. s.add("\"Field" & $i)
  79. s.add("\": ")
  80. storeAny(s, ti, a[i].skipColon, stored, conf)
  81. s.add("}")
  82. of tyObject:
  83. s.add("{")
  84. storeObj(s, t, a, stored, conf)
  85. s.add("}")
  86. of tySet:
  87. s.add("[")
  88. for i in 0..<a.len:
  89. if i > 0: s.add(", ")
  90. if a[i].kind == nkRange:
  91. var x = copyNode(a[i][0])
  92. storeAny(s, t.elementType, x, stored, conf)
  93. inc x.intVal
  94. while x.intVal <= a[i][1].intVal:
  95. s.add(", ")
  96. storeAny(s, t.elementType, x, stored, conf)
  97. inc x.intVal
  98. else:
  99. storeAny(s, t.elementType, a[i], stored, conf)
  100. s.add("]")
  101. of tyRange, tyGenericInst, tyAlias, tySink:
  102. storeAny(s, t.skipModifier, a, stored, conf)
  103. of tyEnum:
  104. # we need a slow linear search because of enums with holes:
  105. for e in items(t.n):
  106. if e.sym.position == a.intVal:
  107. s.add e.sym.name.s.escapeJson
  108. break
  109. of tyPtr, tyRef:
  110. var x = a
  111. if isNil(x) or x.kind == nkNilLit: s.add("null")
  112. elif stored.containsOrIncl(x.ptrToInt):
  113. # already stored, so we simply write out the pointer as an int:
  114. s.add($x.ptrToInt)
  115. else:
  116. # else as a [value, key] pair:
  117. # (reversed order for convenient x[0] access!)
  118. s.add("[")
  119. s.add($x.ptrToInt)
  120. s.add(", ")
  121. storeAny(s, t.elementType, a, stored, conf)
  122. s.add("]")
  123. of tyString, tyCstring:
  124. if a.kind == nkNilLit: s.add("null")
  125. else: s.add(escapeJson(a.strVal))
  126. of tyInt..tyInt64, tyUInt..tyUInt64: s.add($a.intVal)
  127. of tyFloat..tyFloat128: s.add($a.floatVal)
  128. else:
  129. internalError conf, a.info, "cannot marshal at compile-time " & t.typeToString
  130. proc storeAny*(s: var string; t: PType; a: PNode; conf: ConfigRef) =
  131. var stored = initIntSet()
  132. storeAny(s, t, a, stored, conf)
  133. proc loadAny(p: var JsonParser, t: PType,
  134. tab: var Table[BiggestInt, PNode];
  135. cache: IdentCache;
  136. conf: ConfigRef;
  137. idgen: IdGenerator): PNode =
  138. case t.kind
  139. of tyNone:
  140. result = nil
  141. assert false
  142. of tyBool:
  143. case p.kind
  144. of jsonFalse: result = newIntNode(nkIntLit, 0)
  145. of jsonTrue: result = newIntNode(nkIntLit, 1)
  146. else: raiseParseErr(p, "'true' or 'false' expected for a bool")
  147. next(p)
  148. of tyChar:
  149. if p.kind == jsonString:
  150. var x = p.str
  151. result = nil
  152. if x.len == 1:
  153. result = newIntNode(nkIntLit, ord(x[0]))
  154. next(p)
  155. return
  156. elif p.kind == jsonInt:
  157. result = newIntNode(nkIntLit, getInt(p))
  158. next(p)
  159. return
  160. else:
  161. result = nil
  162. raiseParseErr(p, "string of length 1 expected for a char")
  163. of tyEnum:
  164. result = nil
  165. if p.kind == jsonString:
  166. for e in items(t.n):
  167. if e.sym.name.s == p.str:
  168. result = newIntNode(nkIntLit, e.sym.position)
  169. next(p)
  170. return
  171. raiseParseErr(p, "string expected for an enum")
  172. of tyArray:
  173. if p.kind != jsonArrayStart: raiseParseErr(p, "'[' expected for an array")
  174. next(p)
  175. result = newNode(nkBracket)
  176. while p.kind != jsonArrayEnd and p.kind != jsonEof:
  177. result.add loadAny(p, t.elemType, tab, cache, conf, idgen)
  178. if p.kind == jsonArrayEnd: next(p)
  179. else: raiseParseErr(p, "']' end of array expected")
  180. of tySequence:
  181. case p.kind
  182. of jsonNull:
  183. result = newNode(nkNilLit)
  184. next(p)
  185. of jsonArrayStart:
  186. next(p)
  187. result = newNode(nkBracket)
  188. while p.kind != jsonArrayEnd and p.kind != jsonEof:
  189. result.add loadAny(p, t.elemType, tab, cache, conf, idgen)
  190. if p.kind == jsonArrayEnd: next(p)
  191. else: raiseParseErr(p, "")
  192. else:
  193. result = nil
  194. raiseParseErr(p, "'[' expected for a seq")
  195. of tyTuple:
  196. if p.kind != jsonObjectStart: raiseParseErr(p, "'{' expected for an object")
  197. next(p)
  198. result = newNode(nkTupleConstr)
  199. var i = 0
  200. let tupleLen = t.kidsLen
  201. while p.kind != jsonObjectEnd and p.kind != jsonEof:
  202. if p.kind != jsonString:
  203. raiseParseErr(p, "string expected for a field name")
  204. next(p)
  205. if i >= tupleLen:
  206. raiseParseErr(p, "too many fields to tuple type " & typeToString(t))
  207. result.add loadAny(p, t[i], tab, cache, conf, idgen)
  208. inc i
  209. if p.kind == jsonObjectEnd: next(p)
  210. else: raiseParseErr(p, "'}' end of object expected")
  211. of tyObject:
  212. if p.kind != jsonObjectStart: raiseParseErr(p, "'{' expected for an object")
  213. next(p)
  214. result = newNode(nkObjConstr)
  215. result.sons = @[newNode(nkEmpty)]
  216. while p.kind != jsonObjectEnd and p.kind != jsonEof:
  217. if p.kind != jsonString:
  218. raiseParseErr(p, "string expected for a field name")
  219. let ident = getIdent(cache, p.str)
  220. let field = lookupInRecord(t.n, ident)
  221. if field.isNil:
  222. raiseParseErr(p, "unknown field for object of type " & typeToString(t))
  223. next(p)
  224. let pos = field.position + 1
  225. if pos >= result.len:
  226. setLen(result.sons, pos + 1)
  227. let fieldNode = newNode(nkExprColonExpr)
  228. fieldNode.add newSymNode(newSym(skField, ident, idgen, nil, unknownLineInfo))
  229. fieldNode.add loadAny(p, field.typ, tab, cache, conf, idgen)
  230. result[pos] = fieldNode
  231. if p.kind == jsonObjectEnd: next(p)
  232. else: raiseParseErr(p, "'}' end of object expected")
  233. of tySet:
  234. if p.kind != jsonArrayStart: raiseParseErr(p, "'[' expected for a set")
  235. next(p)
  236. result = newNode(nkCurly)
  237. while p.kind != jsonArrayEnd and p.kind != jsonEof:
  238. result.add loadAny(p, t.elementType, tab, cache, conf, idgen)
  239. if p.kind == jsonArrayEnd: next(p)
  240. else: raiseParseErr(p, "']' end of array expected")
  241. of tyPtr, tyRef:
  242. case p.kind
  243. of jsonNull:
  244. result = newNode(nkNilLit)
  245. next(p)
  246. of jsonInt:
  247. result = tab.getOrDefault(p.getInt)
  248. if result.isNil:
  249. raiseParseErr(p, "cannot load object with address " & $p.getInt)
  250. next(p)
  251. of jsonArrayStart:
  252. result = nil
  253. next(p)
  254. if p.kind == jsonInt:
  255. let idx = p.getInt
  256. next(p)
  257. result = loadAny(p, t.elementType, tab, cache, conf, idgen)
  258. tab[idx] = result
  259. else: raiseParseErr(p, "index for ref type expected")
  260. if p.kind == jsonArrayEnd: next(p)
  261. else: raiseParseErr(p, "']' end of ref-address pair expected")
  262. else:
  263. result = nil
  264. raiseParseErr(p, "int for pointer type expected")
  265. of tyString, tyCstring:
  266. case p.kind
  267. of jsonNull:
  268. result = newNode(nkNilLit)
  269. next(p)
  270. of jsonString:
  271. result = newStrNode(nkStrLit, p.str)
  272. next(p)
  273. else:
  274. result = nil
  275. raiseParseErr(p, "string expected")
  276. of tyInt..tyInt64, tyUInt..tyUInt64:
  277. if p.kind == jsonInt:
  278. result = newIntNode(nkIntLit, getInt(p))
  279. next(p)
  280. return
  281. else:
  282. result = nil
  283. raiseParseErr(p, "int expected")
  284. of tyFloat..tyFloat128:
  285. if p.kind == jsonFloat:
  286. result = newFloatNode(nkFloatLit, getFloat(p))
  287. next(p)
  288. return
  289. else:
  290. result = nil
  291. raiseParseErr(p, "float expected")
  292. of tyRange, tyGenericInst, tyAlias, tySink:
  293. result = loadAny(p, t.skipModifier, tab, cache, conf, idgen)
  294. else:
  295. result = nil
  296. internalError conf, "cannot marshal at compile-time " & t.typeToString
  297. proc loadAny*(s: string; t: PType; cache: IdentCache; conf: ConfigRef; idgen: IdGenerator): PNode =
  298. var tab = initTable[BiggestInt, PNode]()
  299. var p: JsonParser = default(JsonParser)
  300. open(p, newStringStream(s), "unknown file")
  301. next(p)
  302. result = loadAny(p, t, tab, cache, conf, idgen)
  303. close(p)