magicsys.nim 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. #
  2. #
  3. # The Nim Compiler
  4. # (c) Copyright 2012 Andreas Rumpf
  5. #
  6. # See the file "copying.txt", included in this
  7. # distribution, for details about the copyright.
  8. #
  9. # Built-in types and compilerprocs are registered here.
  10. import
  11. ast, astalgo, hashes, msgs, platform, nversion, times, idents, rodread
  12. var systemModule*: PSym
  13. var
  14. gSysTypes: array[TTypeKind, PType]
  15. compilerprocs: TStrTable
  16. exposed: TStrTable
  17. proc nilOrSysInt*: PType = gSysTypes[tyInt]
  18. proc registerSysType*(t: PType) =
  19. if gSysTypes[t.kind] == nil: gSysTypes[t.kind] = t
  20. proc newSysType(kind: TTypeKind, size: int): PType =
  21. result = newType(kind, systemModule)
  22. result.size = size
  23. result.align = size.int16
  24. proc getSysSym*(name: string): PSym =
  25. result = strTableGet(systemModule.tab, getIdent(name))
  26. if result == nil:
  27. rawMessage(errSystemNeeds, name)
  28. result = newSym(skError, getIdent(name), systemModule, systemModule.info)
  29. result.typ = newType(tyError, systemModule)
  30. if result.kind == skStub: loadStub(result)
  31. if result.kind == skAlias: result = result.owner
  32. proc createMagic*(name: string, m: TMagic): PSym =
  33. result = newSym(skProc, getIdent(name), nil, unknownLineInfo())
  34. result.magic = m
  35. let
  36. opNot* = createMagic("not", mNot)
  37. opContains* = createMagic("contains", mInSet)
  38. proc getSysMagic*(name: string, m: TMagic): PSym =
  39. var ti: TIdentIter
  40. let id = getIdent(name)
  41. var r = initIdentIter(ti, systemModule.tab, id)
  42. while r != nil:
  43. if r.kind == skStub: loadStub(r)
  44. if r.magic == m:
  45. # prefer the tyInt variant:
  46. if r.typ.sons[0] != nil and r.typ.sons[0].kind == tyInt: return r
  47. result = r
  48. r = nextIdentIter(ti, systemModule.tab)
  49. if result != nil: return result
  50. rawMessage(errSystemNeeds, name)
  51. result = newSym(skError, id, systemModule, systemModule.info)
  52. result.typ = newType(tyError, systemModule)
  53. proc sysTypeFromName*(name: string): PType =
  54. result = getSysSym(name).typ
  55. proc getSysType*(kind: TTypeKind): PType =
  56. result = gSysTypes[kind]
  57. if result == nil:
  58. case kind
  59. of tyInt: result = sysTypeFromName("int")
  60. of tyInt8: result = sysTypeFromName("int8")
  61. of tyInt16: result = sysTypeFromName("int16")
  62. of tyInt32: result = sysTypeFromName("int32")
  63. of tyInt64: result = sysTypeFromName("int64")
  64. of tyUInt: result = sysTypeFromName("uint")
  65. of tyUInt8: result = sysTypeFromName("uint8")
  66. of tyUInt16: result = sysTypeFromName("uint16")
  67. of tyUInt32: result = sysTypeFromName("uint32")
  68. of tyUInt64: result = sysTypeFromName("uint64")
  69. of tyFloat: result = sysTypeFromName("float")
  70. of tyFloat32: result = sysTypeFromName("float32")
  71. of tyFloat64: return sysTypeFromName("float64")
  72. of tyFloat128: result = sysTypeFromName("float128")
  73. of tyBool: result = sysTypeFromName("bool")
  74. of tyChar: result = sysTypeFromName("char")
  75. of tyString: result = sysTypeFromName("string")
  76. of tyCString: result = sysTypeFromName("cstring")
  77. of tyPointer: result = sysTypeFromName("pointer")
  78. of tyNil: result = newSysType(tyNil, ptrSize)
  79. else: internalError("request for typekind: " & $kind)
  80. gSysTypes[kind] = result
  81. if result.kind != kind:
  82. internalError("wanted: " & $kind & " got: " & $result.kind)
  83. if result == nil: internalError("type not found: " & $kind)
  84. var
  85. intTypeCache: array[-5..64, PType]
  86. proc resetSysTypes* =
  87. systemModule = nil
  88. initStrTable(compilerprocs)
  89. initStrTable(exposed)
  90. for i in low(gSysTypes)..high(gSysTypes):
  91. gSysTypes[i] = nil
  92. for i in low(intTypeCache)..high(intTypeCache):
  93. intTypeCache[i] = nil
  94. proc getIntLitType*(literal: PNode): PType =
  95. # we cache some common integer literal types for performance:
  96. let value = literal.intVal
  97. if value >= low(intTypeCache) and value <= high(intTypeCache):
  98. result = intTypeCache[value.int]
  99. if result == nil:
  100. let ti = getSysType(tyInt)
  101. result = copyType(ti, ti.owner, false)
  102. result.n = literal
  103. intTypeCache[value.int] = result
  104. else:
  105. let ti = getSysType(tyInt)
  106. result = copyType(ti, ti.owner, false)
  107. result.n = literal
  108. proc getFloatLitType*(literal: PNode): PType =
  109. # for now we do not cache these:
  110. result = newSysType(tyFloat, size=8)
  111. result.n = literal
  112. proc skipIntLit*(t: PType): PType {.inline.} =
  113. if t.n != nil:
  114. if t.kind in {tyInt, tyFloat}:
  115. return getSysType(t.kind)
  116. result = t
  117. proc addSonSkipIntLit*(father, son: PType) =
  118. if isNil(father.sons): father.sons = @[]
  119. let s = son.skipIntLit
  120. add(father.sons, s)
  121. propagateToOwner(father, s)
  122. proc setIntLitType*(result: PNode) =
  123. let i = result.intVal
  124. case platform.intSize
  125. of 8: result.typ = getIntLitType(result)
  126. of 4:
  127. if i >= low(int32) and i <= high(int32):
  128. result.typ = getIntLitType(result)
  129. else:
  130. result.typ = getSysType(tyInt64)
  131. of 2:
  132. if i >= low(int16) and i <= high(int16):
  133. result.typ = getIntLitType(result)
  134. elif i >= low(int32) and i <= high(int32):
  135. result.typ = getSysType(tyInt32)
  136. else:
  137. result.typ = getSysType(tyInt64)
  138. of 1:
  139. # 8 bit CPUs are insane ...
  140. if i >= low(int8) and i <= high(int8):
  141. result.typ = getIntLitType(result)
  142. elif i >= low(int16) and i <= high(int16):
  143. result.typ = getSysType(tyInt16)
  144. elif i >= low(int32) and i <= high(int32):
  145. result.typ = getSysType(tyInt32)
  146. else:
  147. result.typ = getSysType(tyInt64)
  148. else: internalError(result.info, "invalid int size")
  149. proc getCompilerProc*(name: string): PSym =
  150. let ident = getIdent(name)
  151. result = strTableGet(compilerprocs, ident)
  152. if result == nil:
  153. result = strTableGet(rodCompilerprocs, ident)
  154. if result != nil:
  155. strTableAdd(compilerprocs, result)
  156. if result.kind == skStub: loadStub(result)
  157. if result.kind == skAlias: result = result.owner
  158. proc registerCompilerProc*(s: PSym) =
  159. strTableAdd(compilerprocs, s)
  160. proc registerNimScriptSymbol*(s: PSym) =
  161. # Nimscript symbols must be al unique:
  162. let conflict = strTableGet(exposed, s.name)
  163. if conflict == nil:
  164. strTableAdd(exposed, s)
  165. else:
  166. localError(s.info, "symbol conflicts with other .exportNims symbol at: " &
  167. $conflict.info)
  168. proc getNimScriptSymbol*(name: string): PSym =
  169. strTableGet(exposed, getIdent(name))
  170. proc resetNimScriptSymbols*() = initStrTable(exposed)
  171. initStrTable(compilerprocs)
  172. initStrTable(exposed)