mirror of
https://github.com/nim-lang/Nim.git
synced 2026-01-21 20:10:44 +00:00
The PR branch had merge conflicts with `devel` due to a major compiler refactoring that extracted type definitions from `compiler/ast.nim` into a new `compiler/astdef.nim` file. ## Changes - Resolved conflict in `compiler/ast.nim` by accepting `devel`'s refactored structure - Merged 763 commits from `devel` branch (commit range: `ce6a345..b3273e7`) - Preserved original PR changes removing deprecated symbols from `lib/core/macros.nim` The core PR functionality (removal of deprecated macros API since v0.18.1) remains intact while incorporating the upstream AST refactoring. <!-- START COPILOT CODING AGENT TIPS --> --- 💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more [Copilot coding agent tips](https://gh.io/copilot-coding-agent-tips) in the docs. --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: ringabout <43030857+ringabout@users.noreply.github.com>
153 lines
5.7 KiB
Nim
153 lines
5.7 KiB
Nim
#
|
|
#
|
|
# The Nim Compiler
|
|
# (c) Copyright 2018 Andreas Rumpf
|
|
#
|
|
# See the file "copying.txt", included in this
|
|
# distribution, for details about the copyright.
|
|
#
|
|
|
|
# included from cgen.nim
|
|
|
|
## This include file contains the logic to produce constant string
|
|
## and seq literals. The code here is responsible that
|
|
## ``const x = ["a", "b"]`` works without hidden runtime creation code.
|
|
## The price is that seqs and strings are not purely a library
|
|
## implementation.
|
|
|
|
template detectVersion(field, corename) =
|
|
if m.g.config.selectedGC in {gcArc, gcOrc, gcAtomicArc, gcHooks}:
|
|
result = 2
|
|
else:
|
|
result = 1
|
|
|
|
proc detectStrVersion(m: BModule): int =
|
|
detectVersion(strVersion, "nimStrVersion")
|
|
|
|
proc detectSeqVersion(m: BModule): int =
|
|
detectVersion(seqVersion, "nimSeqVersion")
|
|
|
|
# ----- Version 1: GC'ed strings and seqs --------------------------------
|
|
|
|
proc genStringLiteralDataOnlyV1(m: BModule, s: string; result: var Rope) =
|
|
cgsym(m, "TGenericSeq")
|
|
let tmp = getTempName(m)
|
|
result.add tmp
|
|
var res = newBuilder("")
|
|
res.addVarWithTypeAndInitializer(AlwaysConst, name = tmp):
|
|
res.addSimpleStruct(m, name = "", baseType = ""):
|
|
res.addField(name = "Sup", typ = "TGenericSeq")
|
|
res.addArrayField(name = "data", elementType = NimChar, len = s.len + 1)
|
|
do:
|
|
var strInit: StructInitializer
|
|
res.addStructInitializer(strInit, kind = siOrderedStruct):
|
|
res.addField(strInit, name = "Sup"):
|
|
var seqInit: StructInitializer
|
|
res.addStructInitializer(seqInit, kind = siOrderedStruct):
|
|
res.addField(seqInit, name = "len"):
|
|
res.addIntValue(s.len)
|
|
res.addField(seqInit, name = "reserved"):
|
|
res.add(cCast(NimInt, cOp(BitOr, NimUint, cCast(NimUint, cIntValue(s.len)), NimStrlitFlag)))
|
|
res.addField(strInit, name = "data"):
|
|
res.add(makeCString(s))
|
|
m.s[cfsStrData].add(extract(res))
|
|
|
|
proc genStringLiteralV1(m: BModule; n: PNode; result: var Builder) =
|
|
if s.isNil:
|
|
result.add(cCast(ptrType(cgsymValue(m, "NimStringDesc")), NimNil))
|
|
else:
|
|
let id = nodeTableTestOrSet(m.dataCache, n, m.labels)
|
|
var name: string = ""
|
|
if id == m.labels:
|
|
# string literal not found in the cache:
|
|
genStringLiteralDataOnlyV1(m, n.strVal, name)
|
|
else:
|
|
name = m.tmpBase & $id
|
|
result.add(cCast(ptrType(cgsymValue(m, "NimStringDesc")), cAddr(name)))
|
|
|
|
# ------ Version 2: destructor based strings and seqs -----------------------
|
|
|
|
proc genStringLiteralDataOnlyV2(m: BModule, s: string; result: Rope; isConst: bool) =
|
|
var res = newBuilder("")
|
|
res.addVarWithTypeAndInitializer(
|
|
if isConst: AlwaysConst else: Global,
|
|
name = result):
|
|
res.addSimpleStruct(m, name = "", baseType = ""):
|
|
res.addField(name = "cap", typ = NimInt)
|
|
res.addArrayField(name = "data", elementType = NimChar, len = s.len + 1)
|
|
do:
|
|
var structInit: StructInitializer
|
|
res.addStructInitializer(structInit, kind = siOrderedStruct):
|
|
res.addField(structInit, name = "cap"):
|
|
res.add(cOp(BitOr, NimInt, cIntValue(s.len), NimStrlitFlag))
|
|
res.addField(structInit, name = "data"):
|
|
res.add(makeCString(s))
|
|
m.s[cfsStrData].add(extract(res))
|
|
|
|
proc genStringLiteralV2(m: BModule; n: PNode; isConst: bool; result: var Builder) =
|
|
let id = nodeTableTestOrSet(m.dataCache, n, m.labels)
|
|
var litName: string
|
|
if id == m.labels:
|
|
cgsym(m, "NimStrPayload")
|
|
cgsym(m, "NimStringV2")
|
|
# string literal not found in the cache:
|
|
litName = getTempName(m)
|
|
genStringLiteralDataOnlyV2(m, n.strVal, litName, isConst)
|
|
else:
|
|
litName = m.tmpBase & $id
|
|
let tmp = getTempName(m)
|
|
result.add tmp
|
|
var res = newBuilder("")
|
|
res.addVarWithInitializer(
|
|
if isConst: AlwaysConst else: Global,
|
|
name = tmp,
|
|
typ = "NimStringV2"):
|
|
var strInit: StructInitializer
|
|
res.addStructInitializer(strInit, kind = siOrderedStruct):
|
|
res.addField(strInit, name = "len"):
|
|
res.addIntValue(n.strVal.len)
|
|
res.addField(strInit, name = "p"):
|
|
res.add(cCast(ptrType("NimStrPayload"), cAddr(litName)))
|
|
m.s[cfsStrData].add(extract(res))
|
|
|
|
proc genStringLiteralV2Const(m: BModule; n: PNode; isConst: bool; result: var Builder) =
|
|
let id = nodeTableTestOrSet(m.dataCache, n, m.labels)
|
|
var pureLit: Rope
|
|
if id == m.labels:
|
|
pureLit = getTempName(m)
|
|
cgsym(m, "NimStrPayload")
|
|
cgsym(m, "NimStringV2")
|
|
# string literal not found in the cache:
|
|
genStringLiteralDataOnlyV2(m, n.strVal, pureLit, isConst)
|
|
else:
|
|
pureLit = m.tmpBase & rope(id)
|
|
var strInit: StructInitializer
|
|
result.addStructInitializer(strInit, kind = siOrderedStruct):
|
|
result.addField(strInit, name = "len"):
|
|
result.addIntValue(n.strVal.len)
|
|
result.addField(strInit, name = "p"):
|
|
result.add(cCast(ptrType("NimStrPayload"), cAddr(pureLit)))
|
|
|
|
# ------ Version selector ---------------------------------------------------
|
|
|
|
proc genStringLiteralDataOnly(m: BModule; s: string; info: TLineInfo;
|
|
isConst: bool; result: var Rope) =
|
|
case detectStrVersion(m)
|
|
of 0, 1: genStringLiteralDataOnlyV1(m, s, result)
|
|
of 2:
|
|
let tmp = getTempName(m)
|
|
genStringLiteralDataOnlyV2(m, s, tmp, isConst)
|
|
result.add tmp
|
|
else:
|
|
localError(m.config, info, "cannot determine how to produce code for string literal")
|
|
|
|
proc genNilStringLiteral(m: BModule; info: TLineInfo; result: var Builder) =
|
|
result.add(cCast(ptrType(cgsymValue(m, "NimStringDesc")), NimNil))
|
|
|
|
proc genStringLiteral(m: BModule; n: PNode; result: var Builder) =
|
|
case detectStrVersion(m)
|
|
of 0, 1: genStringLiteralV1(m, n, result)
|
|
of 2: genStringLiteralV2(m, n, isConst = true, result)
|
|
else:
|
|
localError(m.config, n.info, "cannot determine how to produce code for string literal")
|