feat: backtick raw/multi-line strings + QBE backend fixes

- Add backtick raw string literals (Go-style ): no escape processing, multi-line
- C backend: handle backtick strings in emitExpr
- Self-hosted lexer: lexScanBacktickString support
- QBE backend: handle backtick strings in data sections
- QBE: remove broken extern declarations (QBE resolves at link time)
- QBE: fix comparison result types (ceql → w, extend to l)
- QBE: fix SSA parameter name clash (_p_ prefix for params)
- QBE: const inlining via HirLower + QBE emitter
- QBE: proper type mapping for bool/char types
- hir_lower: collect dkConst declarations for const propagation
This commit is contained in:
2026-06-02 11:33:29 +03:00
parent d1160ca5d1
commit 70cfa4f721
14 changed files with 2193 additions and 64 deletions
+4 -1
View File
@@ -160,8 +160,11 @@ proc emitExpr(be: var CBackend, node: HirNode): string =
else: return "false"
of tkStringLiteral:
var text = node.litToken.text
# Backtick raw string: strip backticks, escape content for C
if text.len >= 2 and text[0] == '`' and text[text.len-1] == '`':
text = "\"" & cEscape(text[1 ..< text.len-1]) & "\""
# If text has no surrounding quotes, it's from constFoldConstDecl (already unescaped)
if text.len >= 2 and text[0] == '"' and text[text.len-1] == '"':
elif text.len >= 2 and text[0] == '"' and text[text.len-1] == '"':
# Strip c8" c16" c32" prefixes — in C they are just regular string literals
if text.startsWith("c32\""):
text = "\"" & cEscape(text[4 ..< text.len-1]) & "\""
+17
View File
@@ -277,6 +277,18 @@ proc scanString(lex: var Lexer, startLoc: SourceLocation, prefixLen: int): Token
discard lex.advance() # closing "
result = lex.makeToken(tkStringLiteral, startLoc, startPos)
proc scanBacktickString(lex: var Lexer, startLoc: SourceLocation): Token =
## Scan a backtick-delimited raw string literal: content is literal,
## no escape processing, newlines are preserved.
let startPos = lex.pos - 1 # include the opening backtick
while not lex.isAtEnd() and lex.peek() != '`':
discard lex.advance()
if lex.isAtEnd():
lex.emitError(startLoc, "unterminated backtick string literal")
else:
discard lex.advance() # closing backtick
result = lex.makeToken(tkStringLiteral, startLoc, startPos)
proc scanChar(lex: var Lexer, startLoc: SourceLocation, prefixLen: int): Token =
let startPos = lex.pos - prefixLen
if lex.peek() == '\'':
@@ -523,6 +535,11 @@ proc nextToken(lex: var Lexer): Token =
if c == '"':
return lex.scanString(startLoc, 0)
# Backtick-delimited raw string: `...`
if c == '`':
discard lex.advance()
return lex.scanBacktickString(startLoc)
# Char prefixes: c8' c16' c32' — must come before ident check
if c == 'c' and lex.peek(1) in {'8', '1', '3'}:
let d = lex.peek(1)
+1 -1
View File
@@ -5,7 +5,7 @@ type
##Literals
tkIntLiteral # 42 0xFF 0b1010 0o77
tkFloatLiteral # 3.14 1.0e-9
tkStringLiteral # "hello" c8"hello" c16"hello" c32"hello"
tkStringLiteral # "hello" c8"hello" c16"hello" c32"hello" `raw multi-line`
tkCharLiteral # 'A' c8'A' c16'A' c32'A'
tkBoolLiteral # true false