mirror of
https://github.com/nim-lang/Nim.git
synced 2026-02-12 06:18:51 +00:00
260 lines
6.6 KiB
Nim
260 lines
6.6 KiB
Nim
proc constType(t: Snippet): Snippet =
|
|
# needs manipulation of `t` in nifc
|
|
"NIM_CONST " & t
|
|
|
|
proc constPtrType(t: Snippet): Snippet =
|
|
t & "* NIM_CONST"
|
|
|
|
proc ptrConstType(t: Snippet): Snippet =
|
|
"NIM_CONST " & t & "*"
|
|
|
|
proc ptrType(t: Snippet): Snippet =
|
|
t & "*"
|
|
|
|
proc cppRefType(t: Snippet): Snippet =
|
|
t & "&"
|
|
|
|
const
|
|
CallingConvToStr: array[TCallingConvention, string] = ["N_NIMCALL",
|
|
"N_STDCALL", "N_CDECL", "N_SAFECALL",
|
|
"N_SYSCALL", # this is probably not correct for all platforms,
|
|
# but one can #define it to what one wants
|
|
"N_INLINE", "N_NOINLINE", "N_FASTCALL", "N_THISCALL", "N_CLOSURE", "N_NOCONV",
|
|
"N_NOCONV" #ccMember is N_NOCONV
|
|
]
|
|
|
|
proc procPtrTypeUnnamed(rettype, params: Snippet): Snippet =
|
|
rettype & "(*)" & params
|
|
|
|
proc procPtrTypeUnnamedNimCall(rettype, params: Snippet): Snippet =
|
|
rettype & "(N_RAW_NIMCALL*)" & params
|
|
|
|
proc procPtrTypeUnnamed(callConv: TCallingConvention, rettype, params: Snippet): Snippet =
|
|
CallingConvToStr[callConv] & "_PTR(" & rettype & ", )" & params
|
|
|
|
type CppCaptureKind = enum None, ByReference, ByCopy
|
|
|
|
template addCppLambda(builder: var Builder, captures: CppCaptureKind, params: Snippet, body: typed) =
|
|
builder.add("[")
|
|
case captures
|
|
of None: discard
|
|
of ByReference: builder.add("&")
|
|
of ByCopy: builder.add("=")
|
|
builder.add("] ")
|
|
builder.add(params)
|
|
builder.addLineEndIndent(" {")
|
|
body
|
|
builder.addLineEndDedent("}")
|
|
|
|
proc cCast(typ, value: Snippet): Snippet =
|
|
"((" & typ & ") " & value & ")"
|
|
|
|
proc wrapPar(value: Snippet): Snippet =
|
|
# used for expression group, no-op on sexp
|
|
"(" & value & ")"
|
|
|
|
proc removeSinglePar(value: Snippet): Snippet =
|
|
# removes a single paren layer expected to exist, to silence Wparentheses-equality
|
|
assert value[0] == '(' and value[^1] == ')'
|
|
value[1..^2]
|
|
|
|
template addCast(builder: var Builder, typ: Snippet, valueBody: typed) =
|
|
## adds a cast to `typ` with value built by `valueBody`
|
|
builder.add "(("
|
|
builder.add typ
|
|
builder.add ") "
|
|
valueBody
|
|
builder.add ")"
|
|
|
|
proc cAddr(value: Snippet): Snippet =
|
|
"(&" & value & ")"
|
|
|
|
proc cLabelAddr(value: TLabel): Snippet =
|
|
"&&" & value
|
|
|
|
proc cDeref(value: Snippet): Snippet =
|
|
"(*" & value & ")"
|
|
|
|
proc subscript(a, b: Snippet): Snippet =
|
|
a & "[" & b & "]"
|
|
|
|
proc dotField(a, b: Snippet): Snippet =
|
|
a & "." & b
|
|
|
|
proc derefField(a, b: Snippet): Snippet =
|
|
a & "->" & b
|
|
|
|
type CallBuilder = object
|
|
needsComma: bool
|
|
|
|
proc initCallBuilder(builder: var Builder, callee: Snippet): CallBuilder =
|
|
result = CallBuilder(needsComma: false)
|
|
builder.add(callee)
|
|
builder.add("(")
|
|
|
|
const cArgumentSeparator = ", "
|
|
|
|
proc addArgumentSeparator(builder: var Builder) =
|
|
# no-op on NIFC
|
|
# used by "single argument" builders
|
|
builder.add(cArgumentSeparator)
|
|
|
|
template addArgument(builder: var Builder, call: var CallBuilder, valueBody: typed) =
|
|
if call.needsComma:
|
|
builder.addArgumentSeparator()
|
|
else:
|
|
call.needsComma = true
|
|
valueBody
|
|
|
|
proc finishCallBuilder(builder: var Builder, call: CallBuilder) =
|
|
builder.add(")")
|
|
|
|
template addCall(builder: var Builder, call: out CallBuilder, callee: Snippet, body: typed) =
|
|
call = initCallBuilder(builder, callee)
|
|
body
|
|
finishCallBuilder(builder, call)
|
|
|
|
proc addCall(builder: var Builder, callee: Snippet, args: varargs[Snippet]) =
|
|
builder.add(callee)
|
|
builder.add("(")
|
|
if args.len != 0:
|
|
builder.add(args[0])
|
|
for i in 1 ..< args.len:
|
|
builder.add(", ")
|
|
builder.add(args[i])
|
|
builder.add(")")
|
|
|
|
proc cCall(callee: Snippet, args: varargs[Snippet]): Snippet =
|
|
result = callee
|
|
result.add("(")
|
|
if args.len != 0:
|
|
result.add(args[0])
|
|
for i in 1 ..< args.len:
|
|
result.add(", ")
|
|
result.add(args[i])
|
|
result.add(")")
|
|
|
|
proc addSizeof(builder: var Builder, val: Snippet) =
|
|
builder.add("sizeof(")
|
|
builder.add(val)
|
|
builder.add(")")
|
|
|
|
proc addAlignof(builder: var Builder, val: Snippet) =
|
|
builder.add("NIM_ALIGNOF(")
|
|
builder.add(val)
|
|
builder.add(")")
|
|
|
|
proc addOffsetof(builder: var Builder, val, member: Snippet) =
|
|
builder.add("offsetof(")
|
|
builder.add(val)
|
|
builder.add(", ")
|
|
builder.add(member)
|
|
builder.add(")")
|
|
|
|
template cSizeof(val: Snippet): Snippet =
|
|
"sizeof(" & val & ")"
|
|
|
|
template cAlignof(val: Snippet): Snippet =
|
|
"NIM_ALIGNOF(" & val & ")"
|
|
|
|
template cOffsetof(val, member: Snippet): Snippet =
|
|
"offsetof(" & val & ", " & member & ")"
|
|
|
|
type TypedBinaryOp = enum
|
|
Add, Sub, Mul, Div, Mod
|
|
Shr, Shl, BitAnd, BitOr, BitXor
|
|
|
|
const typedBinaryOperators: array[TypedBinaryOp, string] = [
|
|
Add: "+",
|
|
Sub: "-",
|
|
Mul: "*",
|
|
Div: "/",
|
|
Mod: "%",
|
|
Shr: ">>",
|
|
Shl: "<<",
|
|
BitAnd: "&",
|
|
BitOr: "|",
|
|
BitXor: "^"
|
|
]
|
|
|
|
type TypedUnaryOp = enum
|
|
Neg, BitNot
|
|
|
|
const typedUnaryOperators: array[TypedUnaryOp, string] = [
|
|
Neg: "-",
|
|
BitNot: "~",
|
|
]
|
|
|
|
type UntypedBinaryOp = enum
|
|
LessEqual, LessThan, GreaterEqual, GreaterThan, Equal, NotEqual
|
|
And, Or
|
|
|
|
const untypedBinaryOperators: array[UntypedBinaryOp, string] = [
|
|
LessEqual: "<=",
|
|
LessThan: "<",
|
|
GreaterEqual: ">=",
|
|
GreaterThan: ">",
|
|
Equal: "==",
|
|
NotEqual: "!=",
|
|
And: "&&",
|
|
Or: "||"
|
|
]
|
|
|
|
type UntypedUnaryOp = enum
|
|
Not
|
|
|
|
const untypedUnaryOperators: array[UntypedUnaryOp, string] = [
|
|
Not: "!"
|
|
]
|
|
|
|
proc addOp(builder: var Builder, binOp: TypedBinaryOp, t: Snippet, a, b: Snippet) =
|
|
builder.add('(')
|
|
builder.add(a)
|
|
builder.add(' ')
|
|
builder.add(typedBinaryOperators[binOp])
|
|
builder.add(' ')
|
|
builder.add(b)
|
|
builder.add(')')
|
|
|
|
proc addOp(builder: var Builder, unOp: TypedUnaryOp, t: Snippet, a: Snippet) =
|
|
builder.add('(')
|
|
builder.add(typedUnaryOperators[unOp])
|
|
builder.add('(')
|
|
builder.add(a)
|
|
builder.add("))")
|
|
|
|
proc addOp(builder: var Builder, binOp: UntypedBinaryOp, a, b: Snippet) =
|
|
builder.add('(')
|
|
builder.add(a)
|
|
builder.add(' ')
|
|
builder.add(untypedBinaryOperators[binOp])
|
|
builder.add(' ')
|
|
builder.add(b)
|
|
builder.add(')')
|
|
|
|
proc addOp(builder: var Builder, unOp: UntypedUnaryOp, a: Snippet) =
|
|
builder.add('(')
|
|
builder.add(untypedUnaryOperators[unOp])
|
|
builder.add('(')
|
|
builder.add(a)
|
|
builder.add("))")
|
|
|
|
template cOp(binOp: TypedBinaryOp, t: Snippet, a, b: Snippet): Snippet =
|
|
'(' & a & ' ' & typedBinaryOperators[binOp] & ' ' & b & ')'
|
|
|
|
template cOp(binOp: TypedUnaryOp, t: Snippet, a: Snippet): Snippet =
|
|
'(' & typedUnaryOperators[binOp] & '(' & a & "))"
|
|
|
|
template cOp(binOp: UntypedBinaryOp, a, b: Snippet): Snippet =
|
|
'(' & a & ' ' & untypedBinaryOperators[binOp] & ' ' & b & ')'
|
|
|
|
template cOp(binOp: UntypedUnaryOp, a: Snippet): Snippet =
|
|
'(' & untypedUnaryOperators[binOp] & '(' & a & "))"
|
|
|
|
template cIfExpr(cond, a, b: Snippet): Snippet =
|
|
# XXX used for `min` and `max`, maybe add nifc primitives for these
|
|
"(" & cond & " ? " & a & " : " & b & ")"
|
|
|
|
template cUnlikely(val: Snippet): Snippet =
|
|
"NIM_UNLIKELY(" & val & ")"
|