cbuilderexprs.nim 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. # XXX make complex ones like bitOr use builder instead
  2. # XXX add stuff like NI, NIM_NIL as constants
  3. proc constType(t: Snippet): Snippet =
  4. # needs manipulation of `t` in nifc
  5. "NIM_CONST " & t
  6. proc constPtrType(t: Snippet): Snippet =
  7. t & "* NIM_CONST"
  8. proc ptrConstType(t: Snippet): Snippet =
  9. "NIM_CONST " & t & "*"
  10. proc ptrType(t: Snippet): Snippet =
  11. t & "*"
  12. const
  13. CallingConvToStr: array[TCallingConvention, string] = ["N_NIMCALL",
  14. "N_STDCALL", "N_CDECL", "N_SAFECALL",
  15. "N_SYSCALL", # this is probably not correct for all platforms,
  16. # but one can #define it to what one wants
  17. "N_INLINE", "N_NOINLINE", "N_FASTCALL", "N_THISCALL", "N_CLOSURE", "N_NOCONV",
  18. "N_NOCONV" #ccMember is N_NOCONV
  19. ]
  20. proc procPtrTypeUnnamed(rettype, params: Snippet): Snippet =
  21. rettype & "(*)" & params
  22. proc procPtrTypeUnnamedNimCall(rettype, params: Snippet): Snippet =
  23. rettype & "(N_RAW_NIMCALL*)" & params
  24. proc cCast(typ, value: Snippet): Snippet =
  25. "((" & typ & ") " & value & ")"
  26. proc wrapPar(value: Snippet): Snippet =
  27. # used for expression group, no-op on sexp
  28. "(" & value & ")"
  29. proc removeSinglePar(value: Snippet): Snippet =
  30. # removes a single paren layer expected to exist, to silence Wparentheses-equality
  31. assert value[0] == '(' and value[^1] == ')'
  32. value[1..^2]
  33. template addCast(builder: var Builder, typ: Snippet, valueBody: typed) =
  34. ## adds a cast to `typ` with value built by `valueBody`
  35. builder.add "(("
  36. builder.add typ
  37. builder.add ") "
  38. valueBody
  39. builder.add ")"
  40. proc cAddr(value: Snippet): Snippet =
  41. "&" & value
  42. proc cDeref(value: Snippet): Snippet =
  43. "(*" & value & ")"
  44. proc subscript(a, b: Snippet): Snippet =
  45. a & "[" & b & "]"
  46. proc dotField(a, b: Snippet): Snippet =
  47. a & "." & b
  48. proc derefField(a, b: Snippet): Snippet =
  49. a & "->" & b
  50. proc bitOr(a, b: Snippet): Snippet =
  51. "(" & a & " | " & b & ")"
  52. type CallBuilder = object
  53. needsComma: bool
  54. proc initCallBuilder(builder: var Builder, callee: Snippet): CallBuilder =
  55. result = CallBuilder(needsComma: false)
  56. builder.add(callee)
  57. builder.add("(")
  58. template addArgument(builder: var Builder, call: var CallBuilder, valueBody: typed) =
  59. if call.needsComma:
  60. builder.add(", ")
  61. else:
  62. call.needsComma = true
  63. valueBody
  64. proc finishCallBuilder(builder: var Builder, call: CallBuilder) =
  65. builder.add(")")
  66. template addCall(builder: var Builder, call: out CallBuilder, callee: Snippet, body: typed) =
  67. call = initCallBuilder(builder, callee)
  68. body
  69. finishCallBuilder(builder, call)
  70. proc addCall(builder: var Builder, callee: Snippet, args: varargs[Snippet]) =
  71. builder.add(callee)
  72. builder.add("(")
  73. if args.len != 0:
  74. builder.add(args[0])
  75. for i in 1 ..< args.len:
  76. builder.add(", ")
  77. builder.add(args[i])
  78. builder.add(")")
  79. proc cCall(callee: Snippet, args: varargs[Snippet]): Snippet =
  80. result = callee
  81. result.add("(")
  82. if args.len != 0:
  83. result.add(args[0])
  84. for i in 1 ..< args.len:
  85. result.add(", ")
  86. result.add(args[i])
  87. result.add(")")
  88. proc addSizeof(builder: var Builder, val: Snippet) =
  89. builder.add("sizeof(")
  90. builder.add(val)
  91. builder.add(")")
  92. proc addAlignof(builder: var Builder, val: Snippet) =
  93. builder.add("NIM_ALIGNOF(")
  94. builder.add(val)
  95. builder.add(")")
  96. proc addOffsetof(builder: var Builder, val, member: Snippet) =
  97. builder.add("offsetof(")
  98. builder.add(val)
  99. builder.add(", ")
  100. builder.add(member)
  101. builder.add(")")
  102. template cSizeof(val: Snippet): Snippet =
  103. "sizeof(" & val & ")"
  104. template cAlignof(val: Snippet): Snippet =
  105. "NIM_ALIGNOF(" & val & ")"
  106. template cOffsetof(val, member: Snippet): Snippet =
  107. "offsetof(" & val & ", " & member & ")"
  108. type TypedBinaryOp = enum
  109. Add, Sub, Mul, Div, Mod
  110. Shr, Shl, BitAnd, BitOr, BitXor
  111. const typedBinaryOperators: array[TypedBinaryOp, string] = [
  112. Add: "+",
  113. Sub: "-",
  114. Mul: "*",
  115. Div: "/",
  116. Mod: "%",
  117. Shr: ">>",
  118. Shl: "<<",
  119. BitAnd: "&",
  120. BitOr: "|",
  121. BitXor: "^"
  122. ]
  123. type TypedUnaryOp = enum
  124. Neg, BitNot
  125. const typedUnaryOperators: array[TypedUnaryOp, string] = [
  126. Neg: "-",
  127. BitNot: "~",
  128. ]
  129. type UntypedBinaryOp = enum
  130. LessEqual, LessThan, GreaterEqual, GreaterThan, Equal, NotEqual
  131. And, Or
  132. const untypedBinaryOperators: array[UntypedBinaryOp, string] = [
  133. LessEqual: "<=",
  134. LessThan: "<",
  135. GreaterEqual: ">=",
  136. GreaterThan: ">",
  137. Equal: "==",
  138. NotEqual: "!=",
  139. And: "&&",
  140. Or: "||"
  141. ]
  142. type UntypedUnaryOp = enum
  143. Not
  144. const untypedUnaryOperators: array[UntypedUnaryOp, string] = [
  145. Not: "!"
  146. ]
  147. proc addOp(builder: var Builder, binOp: TypedBinaryOp, t: Snippet, a, b: Snippet) =
  148. builder.add('(')
  149. builder.add(a)
  150. builder.add(' ')
  151. builder.add(typedBinaryOperators[binOp])
  152. builder.add(' ')
  153. builder.add(b)
  154. builder.add(')')
  155. proc addOp(builder: var Builder, unOp: TypedUnaryOp, t: Snippet, a: Snippet) =
  156. builder.add('(')
  157. builder.add(typedUnaryOperators[unOp])
  158. builder.add('(')
  159. builder.add(a)
  160. builder.add("))")
  161. proc addOp(builder: var Builder, binOp: UntypedBinaryOp, a, b: Snippet) =
  162. builder.add('(')
  163. builder.add(a)
  164. builder.add(' ')
  165. builder.add(untypedBinaryOperators[binOp])
  166. builder.add(' ')
  167. builder.add(b)
  168. builder.add(')')
  169. proc addOp(builder: var Builder, unOp: UntypedUnaryOp, a: Snippet) =
  170. builder.add('(')
  171. builder.add(untypedUnaryOperators[unOp])
  172. builder.add('(')
  173. builder.add(a)
  174. builder.add("))")
  175. template cOp(binOp: TypedBinaryOp, t: Snippet, a, b: Snippet): Snippet =
  176. '(' & a & ' ' & typedBinaryOperators[binOp] & ' ' & b & ')'
  177. template cOp(binOp: TypedUnaryOp, t: Snippet, a: Snippet): Snippet =
  178. '(' & typedUnaryOperators[binOp] & '(' & a & "))"
  179. template cOp(binOp: UntypedBinaryOp, a, b: Snippet): Snippet =
  180. '(' & a & ' ' & untypedBinaryOperators[binOp] & ' ' & b & ')'
  181. template cOp(binOp: UntypedUnaryOp, a: Snippet): Snippet =
  182. '(' & untypedUnaryOperators[binOp] & '(' & a & "))"
  183. template cIfExpr(cond, a, b: Snippet): Snippet =
  184. # XXX used for `min` and `max`, maybe add nifc primitives for these
  185. "(" & cond & " ? " & a & " : " & b & ")"