jstypes.nim 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. #
  2. #
  3. # The Nim Compiler
  4. # (c) Copyright 2013 Andreas Rumpf
  5. #
  6. # See the file "copying.txt", included in this
  7. # distribution, for details about the copyright.
  8. #
  9. ## Type info generation for the JS backend.
  10. proc genTypeInfo(p: PProc, typ: PType): Rope
  11. proc genObjectFields(p: PProc, typ: PType, n: PNode): Rope =
  12. var
  13. s, u: Rope
  14. length: int
  15. field: PSym
  16. b: PNode
  17. result = nil
  18. case n.kind
  19. of nkRecList:
  20. length = sonsLen(n)
  21. if length == 1:
  22. result = genObjectFields(p, typ, n.sons[0])
  23. else:
  24. s = nil
  25. for i in countup(0, length - 1):
  26. if i > 0: add(s, ", \L")
  27. add(s, genObjectFields(p, typ, n.sons[i]))
  28. result = ("{kind: 2, len: $1, offset: 0, " &
  29. "typ: null, name: null, sons: [$2]}") % [rope(length), s]
  30. of nkSym:
  31. field = n.sym
  32. s = genTypeInfo(p, field.typ)
  33. result = ("{kind: 1, offset: \"$1\", len: 0, " &
  34. "typ: $2, name: $3, sons: null}") %
  35. [mangleName(p.module, field), s,
  36. makeJSString(field.name.s)]
  37. of nkRecCase:
  38. length = sonsLen(n)
  39. if (n.sons[0].kind != nkSym): internalError(p.config, n.info, "genObjectFields")
  40. field = n.sons[0].sym
  41. s = genTypeInfo(p, field.typ)
  42. for i in countup(1, length - 1):
  43. b = n.sons[i] # branch
  44. u = nil
  45. case b.kind
  46. of nkOfBranch:
  47. if sonsLen(b) < 2:
  48. internalError(p.config, b.info, "genObjectFields; nkOfBranch broken")
  49. for j in countup(0, sonsLen(b) - 2):
  50. if u != nil: add(u, ", ")
  51. if b.sons[j].kind == nkRange:
  52. addf(u, "[$1, $2]", [rope(getOrdValue(b.sons[j].sons[0])),
  53. rope(getOrdValue(b.sons[j].sons[1]))])
  54. else:
  55. add(u, rope(getOrdValue(b.sons[j])))
  56. of nkElse:
  57. u = rope(lengthOrd(p.config, field.typ))
  58. else: internalError(p.config, n.info, "genObjectFields(nkRecCase)")
  59. if result != nil: add(result, ", \L")
  60. addf(result, "[setConstr($1), $2]",
  61. [u, genObjectFields(p, typ, lastSon(b))])
  62. result = ("{kind: 3, offset: \"$1\", len: $3, " &
  63. "typ: $2, name: $4, sons: [$5]}") % [
  64. mangleName(p.module, field), s,
  65. rope(lengthOrd(p.config, field.typ)), makeJSString(field.name.s), result]
  66. else: internalError(p.config, n.info, "genObjectFields")
  67. proc objHasTypeField(t: PType): bool {.inline.} =
  68. tfInheritable in t.flags or t.sons[0] != nil
  69. proc genObjectInfo(p: PProc, typ: PType, name: Rope) =
  70. let kind = if objHasTypeField(typ): tyObject else: tyTuple
  71. var s = ("var $1 = {size: 0, kind: $2, base: null, node: null, " &
  72. "finalizer: null};$n") % [name, rope(ord(kind))]
  73. prepend(p.g.typeInfo, s)
  74. addf(p.g.typeInfo, "var NNI$1 = $2;$n",
  75. [rope(typ.id), genObjectFields(p, typ, typ.n)])
  76. addf(p.g.typeInfo, "$1.node = NNI$2;$n", [name, rope(typ.id)])
  77. if (typ.kind == tyObject) and (typ.sons[0] != nil):
  78. addf(p.g.typeInfo, "$1.base = $2;$n",
  79. [name, genTypeInfo(p, typ.sons[0].skipTypes(skipPtrs))])
  80. proc genTupleFields(p: PProc, typ: PType): Rope =
  81. var s: Rope = nil
  82. for i in 0 ..< typ.len:
  83. if i > 0: add(s, ", \L")
  84. s.addf("{kind: 1, offset: \"Field$1\", len: 0, " &
  85. "typ: $2, name: \"Field$1\", sons: null}",
  86. [i.rope, genTypeInfo(p, typ.sons[i])])
  87. result = ("{kind: 2, len: $1, offset: 0, " &
  88. "typ: null, name: null, sons: [$2]}") % [rope(typ.len), s]
  89. proc genTupleInfo(p: PProc, typ: PType, name: Rope) =
  90. var s = ("var $1 = {size: 0, kind: $2, base: null, node: null, " &
  91. "finalizer: null};$n") % [name, rope(ord(typ.kind))]
  92. prepend(p.g.typeInfo, s)
  93. addf(p.g.typeInfo, "var NNI$1 = $2;$n",
  94. [rope(typ.id), genTupleFields(p, typ)])
  95. addf(p.g.typeInfo, "$1.node = NNI$2;$n", [name, rope(typ.id)])
  96. proc genEnumInfo(p: PProc, typ: PType, name: Rope) =
  97. let length = sonsLen(typ.n)
  98. var s: Rope = nil
  99. for i in countup(0, length - 1):
  100. if (typ.n.sons[i].kind != nkSym): internalError(p.config, typ.n.info, "genEnumInfo")
  101. let field = typ.n.sons[i].sym
  102. if i > 0: add(s, ", \L")
  103. let extName = if field.ast == nil: field.name.s else: field.ast.strVal
  104. addf(s, "\"$1\": {kind: 1, offset: $1, typ: $2, name: $3, len: 0, sons: null}",
  105. [rope(field.position), name, makeJSString(extName)])
  106. var n = ("var NNI$1 = {kind: 2, offset: 0, typ: null, " &
  107. "name: null, len: $2, sons: {$3}};$n") % [rope(typ.id), rope(length), s]
  108. s = ("var $1 = {size: 0, kind: $2, base: null, node: null, " &
  109. "finalizer: null};$n") % [name, rope(ord(typ.kind))]
  110. prepend(p.g.typeInfo, s)
  111. add(p.g.typeInfo, n)
  112. addf(p.g.typeInfo, "$1.node = NNI$2;$n", [name, rope(typ.id)])
  113. if typ.sons[0] != nil:
  114. addf(p.g.typeInfo, "$1.base = $2;$n",
  115. [name, genTypeInfo(p, typ.sons[0])])
  116. proc genTypeInfo(p: PProc, typ: PType): Rope =
  117. let t = typ.skipTypes({tyGenericInst, tyDistinct, tyAlias, tySink})
  118. result = "NTI$1" % [rope(t.id)]
  119. if containsOrIncl(p.g.typeInfoGenerated, t.id): return
  120. case t.kind
  121. of tyDistinct:
  122. result = genTypeInfo(p, t.sons[0])
  123. of tyPointer, tyProc, tyBool, tyChar, tyCString, tyString, tyInt..tyUInt64:
  124. var s =
  125. "var $1 = {size: 0,kind: $2,base: null,node: null,finalizer: null};$n" %
  126. [result, rope(ord(t.kind))]
  127. prepend(p.g.typeInfo, s)
  128. of tyVar, tyLent, tyRef, tyPtr, tySequence, tyRange, tySet:
  129. var s =
  130. "var $1 = {size: 0,kind: $2,base: null,node: null,finalizer: null};$n" %
  131. [result, rope(ord(t.kind))]
  132. prepend(p.g.typeInfo, s)
  133. addf(p.g.typeInfo, "$1.base = $2;$n",
  134. [result, genTypeInfo(p, t.lastSon)])
  135. of tyArray:
  136. var s =
  137. "var $1 = {size: 0,kind: $2,base: null,node: null,finalizer: null};$n" %
  138. [result, rope(ord(t.kind))]
  139. prepend(p.g.typeInfo, s)
  140. addf(p.g.typeInfo, "$1.base = $2;$n",
  141. [result, genTypeInfo(p, t.sons[1])])
  142. of tyEnum: genEnumInfo(p, t, result)
  143. of tyObject: genObjectInfo(p, t, result)
  144. of tyTuple: genTupleInfo(p, t, result)
  145. of tyStatic:
  146. if t.n != nil: result = genTypeInfo(p, lastSon t)
  147. else: internalError(p.config, "genTypeInfo(" & $t.kind & ')')
  148. else: internalError(p.config, "genTypeInfo(" & $t.kind & ')')