mirror of
https://github.com/logos-messaging/nim-ffi.git
synced 2026-07-27 01:53:26 +00:00
70 lines
1.9 KiB
Nim
70 lines
1.9 KiB
Nim
## Literal rendering for `{.ffiConst.}` values, shared by the C/C++/Rust generators.
|
|
## The registry stores Nim's `$value`; each backend re-quotes it for its syntax.
|
|
|
|
import std/strutils
|
|
import ./types_ir
|
|
|
|
func cByteEscape(ch: char): string =
|
|
## 3-digit octal: C caps an octal escape at 3 digits, so a following digit
|
|
## can't be swallowed into it the way it can with `\x`.
|
|
return "\\" & toOct(ord(ch), 3)
|
|
|
|
func rustByteEscape(ch: char): string =
|
|
return "\\x" & toHex(ord(ch), 2)
|
|
|
|
func escapeLit(
|
|
s: string, byteEscape: proc(ch: char): string {.noSideEffect, nimcall.}
|
|
): string =
|
|
var escaped = ""
|
|
for ch in s:
|
|
case ch
|
|
of '"':
|
|
escaped.add("\\\"")
|
|
of '\\':
|
|
escaped.add("\\\\")
|
|
of '\n':
|
|
escaped.add("\\n")
|
|
of '\r':
|
|
escaped.add("\\r")
|
|
of '\t':
|
|
escaped.add("\\t")
|
|
else:
|
|
if ch < ' ' or ch == '\x7F':
|
|
escaped.add(byteEscape(ch))
|
|
else:
|
|
escaped.add(ch)
|
|
return escaped
|
|
|
|
func cEscapeStringLit*(s: string): string =
|
|
return escapeLit(s, cByteEscape)
|
|
|
|
func rustEscapeStringLit*(s: string): string =
|
|
return escapeLit(s, rustByteEscape)
|
|
|
|
func cConstValue*(t: FFIType, value: string): string =
|
|
## C/C++ literal. Every emission site is a typed declaration, so the declared
|
|
## type already fixes the width; only the two cases the type can't rescue get
|
|
## a suffix — `ULL` because a decimal above `INT64_MAX` fits no signed type,
|
|
## and `f` because a bare `1.5` is a double and narrowing it warns.
|
|
case t.kind
|
|
of ftStr:
|
|
return "\"" & cEscapeStringLit(value) & "\""
|
|
of ftScalar:
|
|
case t.scalar
|
|
of skU64:
|
|
return value & "ULL"
|
|
of skF32:
|
|
return value & "f"
|
|
else:
|
|
return value
|
|
else:
|
|
return value
|
|
|
|
func rustConstValue*(t: FFIType, value: string): string =
|
|
## Rust literal; the declared type annotation carries the width, so no suffix.
|
|
case t.kind
|
|
of ftStr:
|
|
return "\"" & rustEscapeStringLit(value) & "\""
|
|
else:
|
|
return value
|