Skip to content

Commit

Permalink
also add preferred syms to not break routines
Browse files Browse the repository at this point in the history
  • Loading branch information
metagn committed Sep 23, 2023
1 parent 391f759 commit d58eb41
Show file tree
Hide file tree
Showing 10 changed files with 120 additions and 81 deletions.
3 changes: 2 additions & 1 deletion compiler/ast.nim
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,7 @@ type
nfHasComment # node has a comment
nfSkipFieldChecking # node skips field visable checking
nfOpenSym # node is a captured sym but can be overriden by local symbols
nfPreferredSym # node is a preferred sym in a symchoice

TNodeFlags* = set[TNodeFlag]
TTypeFlag* = enum # keep below 32 for efficiency reasons (now: 47)
Expand Down Expand Up @@ -1093,7 +1094,7 @@ const
nfIsRef, nfIsPtr, nfPreventCg, nfLL,
nfFromTemplate, nfDefaultRefsParam,
nfExecuteOnReload, nfLastRead,
nfFirstWrite, nfSkipFieldChecking, nfOpenSym}
nfFirstWrite, nfSkipFieldChecking, nfOpenSym, nfPreferredSym}
namePos* = 0
patternPos* = 1 # empty except for term rewriting macros
genericParamsPos* = 2
Expand Down
33 changes: 31 additions & 2 deletions compiler/lookups.nim
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,7 @@ type
m*: PSym
mode*: TOverloadIterMode
symChoiceIndex*: int
symChoiceLastPreferred: bool
fallback: PSym
currentScope: PScope
importIdx: int
Expand Down Expand Up @@ -599,6 +600,11 @@ proc lookUp*(c: PContext, n: PNode): PSym =
var ident = considerQuotedIdent(c, n)
result = searchInScopes(c, ident, amb)
if result == nil: result = errorUndeclaredIdentifierHint(c, n, ident)
of nkOpenSymChoice, nkClosedSymChoice:
if nfPreferredSym in n[0].flags:
result = n[0].sym
else:
result = nil
else:
internalError(c.config, n.info, "lookUp")
return nil
Expand Down Expand Up @@ -679,6 +685,11 @@ proc qualifiedLookUp*(c: PContext, n: PNode, flags: set[TLookupFlag]): PSym =
localError(c.config, n[1].info, "identifier expected, but got: " &
renderTree(n[1]))
result = errorSym(c, n[1])
of nkOpenSymChoice, nkClosedSymChoice:
if nfPreferredSym in n[0].flags:
result = n[0].sym
else:
result = nil
else:
result = nil
when false:
Expand Down Expand Up @@ -712,7 +723,16 @@ proc initOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
of nkSym:
if nfOpenSym notin n.flags:
result = n.sym
o.mode = oimDone
if nfPreferredSym in n.flags:
o.mode = oimSymChoiceLocalLookup
o.symChoiceLastPreferred = true
o.currentScope = c.currentScope
o.it.h = result.name.h
o.it.name = result.name
o.marked = initIntSet()
incl(o.marked, result.id)
else:
o.mode = oimDone
else:
result = initOverloadIter(o, c, newIdentNode(n.sym.name, n.info))
if result == nil:
Expand Down Expand Up @@ -745,6 +765,7 @@ proc initOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
o.mode = oimSymChoice
if n[0].kind == nkSym:
result = n[0].sym
o.symChoiceLastPreferred = nfPreferredSym in n[0].flags
else:
o.mode = oimDone
return nil
Expand All @@ -763,6 +784,11 @@ proc lastOverloadScope*(o: TOverloadIter): int =
else: o.currentScope.depthLevel
of oimSelfModule: result = 1
of oimOtherModule: result = 0
of oimSymChoice, oimSymChoiceLocalLookup:
if o.symChoiceLastPreferred:
result = 999
else:
result = -1
else: result = -1

proc nextOverloadIterImports(o: var TOverloadIter, c: PContext, n: PNode): PSym =
Expand Down Expand Up @@ -824,6 +850,7 @@ proc nextOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
of oimOtherModule:
result = nextModuleIter(o.mit, c.graph)
of oimSymChoice:
o.symChoiceLastPreferred = false
if o.symChoiceIndex < n.len:
result = n[o.symChoiceIndex].sym
incl(o.marked, result.id)
Expand All @@ -848,13 +875,15 @@ proc nextOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
else:
result = nil
of oimSymChoiceLocalLookup:
o.symChoiceLastPreferred = false
if o.currentScope != nil:
result = nextIdentExcluding(o.it, o.currentScope.symbols, o.marked)
while result == nil:
o.currentScope = o.currentScope.parent
if o.currentScope != nil:
let name = if n.kind == nkSym: n.sym.name else: n[0].sym.name
result = firstIdentExcluding(o.it, o.currentScope.symbols,
n[0].sym.name, o.marked)
name, o.marked)
else:
o.importIdx = 0
result = symChoiceExtension(o, c, n)
Expand Down
61 changes: 32 additions & 29 deletions compiler/semexprs.nim
Original file line number Diff line number Diff line change
Expand Up @@ -55,16 +55,16 @@ proc semOperand(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
result = semExpr(c, n, flags + {efOperand, efAllowSymChoice})
if result.typ != nil:
# XXX tyGenericInst here?
#if result.typ.kind == tyProc and hasUnresolvedParams(result, {efOperand}):
# #and tfUnresolved in result.typ.flags:
# let owner = result.typ.owner
# let err =
# # consistent error message with evaltempl/semMacroExpr
# if owner != nil and owner.kind in {skTemplate, skMacro}:
# errMissingGenericParamsForTemplate % n.renderTree
# else:
# errProcHasNoConcreteType % n.renderTree
# localError(c.config, n.info, err)
if result.typ.kind == tyProc and hasUnresolvedParams(result, {efOperand}):
#and tfUnresolved in result.typ.flags:
let owner = result.typ.owner
let err =
# consistent error message with evaltempl/semMacroExpr
if owner != nil and owner.kind in {skTemplate, skMacro}:
errMissingGenericParamsForTemplate % n.renderTree
else:
errProcHasNoConcreteType % n.renderTree
localError(c.config, n.info, err)
if result.typ.kind in {tyVar, tyLent}: result = newDeref(result)
elif {efWantStmt, efAllowStmt} * flags != {}:
result.typ = newTypeS(tyVoid, c)
Expand Down Expand Up @@ -139,16 +139,11 @@ proc semSymChoice(c: PContext, n: PNode, flags: TExprFlags = {}, expectedType: P
if isSymChoice(result) and efAllowSymChoice notin flags:
# some contexts might want sym choices preserved for later disambiguation
# in general though they are ambiguous
let first = n[0].sym
var foundSym: PSym = nil
if first.kind == skEnumField and
not isAmbiguous(c, first.name, {skEnumField}, foundSym) and
foundSym == first:
# choose the first resolved enum field, i.e. the latest in scope
# to mirror behavior before overloadable enums
result = n[0]
let first = n[0]
if nfPreferredSym in first.flags:
result = first
else:
var err = "ambiguous identifier '" & first.name.s &
var err = "ambiguous identifier '" & first.sym.name.s &
"' -- use one of the following:\n"
for child in n:
let candidate = child.sym
Expand Down Expand Up @@ -1025,7 +1020,7 @@ proc afterCallActions(c: PContext; n, orig: PNode, flags: TExprFlags; expectedTy
of skMacro: result = semMacroExpr(c, result, orig, callee, flags, expectedType)
of skTemplate: result = semTemplateExpr(c, result, callee, flags, expectedType)
else:
if callee.magic == mNone:
if callee.magic notin {mArrGet, mArrPut, mNBindSym}:
semFinishOperands(c, result)
activate(c, result)
fixAbstractType(c, result)
Expand Down Expand Up @@ -1286,12 +1281,6 @@ proc readTypeParameter(c: PContext, typ: PType,
proc semSym(c: PContext, n: PNode, sym: PSym, flags: TExprFlags): PNode =
result = nil
assert n.kind in nkIdentKinds + {nkDotExpr}
if n.kind == nkSym and nfOpenSym in n.flags:
let id = newIdentNode(n.sym.name, n.info)
c.isAmbiguous = false
let s2 = qualifiedLookUp(c, id, {})
if s2 != nil and s2 != sym and not c.isAmbiguous:
return semSym(c, id, s2, flags)
let s = getGenSym(c, sym)
case s.kind
of skConst:
Expand Down Expand Up @@ -2960,13 +2949,17 @@ proc getNilType(c: PContext): PType =
c.nilTypeCache = result

proc enumFieldSymChoice(c: PContext, n: PNode, s: PSym): PNode =
var o: TOverloadIter
var o: TOverloadIter = default(TOverloadIter)
var firstPreferred = true
var i = 0
var a = initOverloadIter(o, c, n)
let firstScope = lastOverloadScope(o)
while a != nil:
if a.kind == skEnumField:
inc(i)
if i > 1: break
if i > 1:
firstPreferred = firstScope > lastOverloadScope(o)
break
a = nextOverloadIter(o, c, n)
let info = getCallLineInfo(n)
if i <= 1:
Expand All @@ -2986,6 +2979,8 @@ proc enumFieldSymChoice(c: PContext, n: PNode, s: PSym): PNode =
result.add newSymNode(a, info)
onUse(info, a)
a = nextOverloadIter(o, c, n)
if firstPreferred:
result[0].flags.incl nfPreferredSym

proc semPragmaStmt(c: PContext; n: PNode) =
if c.p.owner.kind == skModule:
Expand Down Expand Up @@ -3070,9 +3065,17 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}, expectedType: PType
of nkClosedSymChoice, nkOpenSymChoice:
result = semSymChoice(c, result, flags, expectedType)
of nkSym:
let s = n.sym
if nfOpenSym in n.flags:
let id = newIdentNode(s.name, n.info)
c.isAmbiguous = false
let s2 = qualifiedLookUp(c, id, {})
if s2 != nil and s2 != s and not c.isAmbiguous:
result = semExpr(c, id, flags, expectedType)
return
# because of the changed symbol binding, this does not mean that we
# don't have to check the symbol for semantics here again!
result = semSym(c, n, n.sym, flags)
result = semSym(c, n, s, flags)
of nkEmpty, nkNone, nkCommentStmt, nkType:
discard
of nkNilLit:
Expand Down
18 changes: 9 additions & 9 deletions compiler/semgnrc.nim
Original file line number Diff line number Diff line change
Expand Up @@ -65,14 +65,8 @@ proc semGenericStmtSymbol(c: PContext, n: PNode, s: PSym,
template maybeDotChoice(c: PContext, n: PNode, s: PSym, fromDotExpr: bool) =
if fromDotExpr:
result = symChoice(c, n, s, scForceOpen)
if result.kind == nkOpenSymChoice and result.len == 1:
result = result[0]
result.flags.incl nfOpenSym
result.typ = nil
else:
result = symChoice(c, n, s, scOpen)
#if result.kind == nkSym:
# result.flags.excl nfOpenSym
case s.kind
of skUnknown:
# Introduced in this pass! Leave it as an identifier.
Expand Down Expand Up @@ -100,6 +94,9 @@ proc semGenericStmtSymbol(c: PContext, n: PNode, s: PSym,
result = n
else:
result = newSymNodeTypeDesc(s, c.idgen, n.info)
if withinMixin in flags:
result.flags.incl nfOpenSym
result.typ = nil
onUse(n.info, s)
of skParam:
result = n
Expand All @@ -108,15 +105,18 @@ proc semGenericStmtSymbol(c: PContext, n: PNode, s: PSym,
if (s.typ != nil) and
(s.typ.flags * {tfGenericTypeParam, tfImplicitTypeParam} == {}):
result = newSymNodeTypeDesc(s, c.idgen, n.info)
if withinMixin in flags:
result.flags.incl nfOpenSym
result.typ = nil
else:
result = n
onUse(n.info, s)
else:
result = newSymNode(s, n.info)
onUse(n.info, s)
if withinMixin in flags and result.kind == nkSym:
result.flags.incl nfOpenSym
result.typ = nil
if withinMixin in flags:
result.flags.incl nfOpenSym
result.typ = nil

proc lookup(c: PContext, n: PNode, flags: TSemGenericFlags,
ctx: var GenericCtx): PNode =
Expand Down
36 changes: 20 additions & 16 deletions compiler/semtempl.nim
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,17 @@ proc symChoice(c: PContext, n: PNode, s: PSym, r: TSymChoiceRule;
isField = false): PNode =
var
a: PSym
o: TOverloadIter
o: TOverloadIter = default(TOverloadIter)
firstPreferred = true
var i = 0
a = initOverloadIter(o, c, n)
let firstScope = lastOverloadScope(o)
while a != nil:
if a.kind != skModule:
inc(i)
if i > 1: break
if i > 1:
firstPreferred = firstScope > lastOverloadScope(o)
break
a = nextOverloadIter(o, c, n)
let info = getCallLineInfo(n)
if i <= 1 and r != scForceOpen:
Expand All @@ -67,11 +71,18 @@ proc symChoice(c: PContext, n: PNode, s: PSym, r: TSymChoiceRule;
# for instance 'nextTry' is both in tables.nim and astalgo.nim ...
if not isField or sfGenSym notin s.flags:
result = newSymNode(s, info)
if r in {scOpen, scForceOpen}:
result.flags.incl nfOpenSym
result.typ = nil
markUsed(c, info, s)
onUse(info, s)
if r == scClosed or n.kind == nkDotExpr or
(s.magic != mNone and s.kind in routineKinds):
markUsed(c, info, s)
onUse(info, s)
else:
if s.kind in routineKinds:
result.flags.incl nfPreferredSym
else:
result.flags.incl nfOpenSym
result.typ = nil
incl(s.flags, sfUsed)
markOwnerModuleAsUsed(c, s)
else:
result = n
elif i == 0:
Expand All @@ -91,6 +102,8 @@ proc symChoice(c: PContext, n: PNode, s: PSym, r: TSymChoiceRule;
result.add newSymNode(a, info)
onUse(info, a)
a = nextOverloadIter(o, c, n)
if firstPreferred:
result[0].flags.incl nfPreferredSym

proc semBindStmt(c: PContext, n: PNode, toBind: var IntSet): PNode =
result = copyNode(n)
Expand Down Expand Up @@ -574,15 +587,6 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
inc c.noGenSym
result[1] = semTemplBody(c, n[1])
dec c.noGenSym
if false and result[1].kind == nkSym and result[1].sym.kind in routineKinds and
nfOpenSym notin result[1].flags:
# prevent `dotTransformation` from rewriting this node to `nkIdent`
# by making it a symchoice
# in generics this becomes `nkClosedSymChoice` but this breaks code
# as the old behavior here was that this became `nkIdent`
var choice = newNodeIT(nkOpenSymChoice, n[1].info, newTypeS(tyNone, c.c))
choice.add result[1]
result[1] = choice
else:
result = semTemplBodySons(c, n)
of nkExprColonExpr, nkExprEqExpr:
Expand Down
4 changes: 4 additions & 0 deletions compiler/sigmatch.nim
Original file line number Diff line number Diff line change
Expand Up @@ -2351,6 +2351,10 @@ proc paramTypesMatch*(m: var TCandidate, f, a: PType,
# See tsymchoice_for_expr as an example. 'f.kind == tyUntyped' should match
# anyway:
if f.kind in {tyUntyped, tyTyped}: result = arg
elif nfPreferredSym in arg[0].flags:
markUsed(m.c, arg.info, arg[0].sym)
onUse(arg.info, arg[0].sym)
result = paramTypesMatchAux(m, f, arg[0].typ, arg[0], argOrig)
else: result = nil
else:
# only one valid interpretation found:
Expand Down
5 changes: 0 additions & 5 deletions lib/pure/collections/tables.nim
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,6 @@ template get(t, key): untyped =
raiseKeyError(key)

proc enlarge[A, B](t: var Table[A, B]) =
bind nextTry
var n: KeyValuePairSeq[A, B]
newSeq(n, len(t.data) * growthFactor)
swap(t.data, n)
Expand Down Expand Up @@ -797,7 +796,6 @@ iterator allValues*[A, B](t: Table[A, B]; key: A): B {.deprecated:
for i in 1..3: a.add('z', 10*i)
doAssert toSeq(a.pairs).sorted == @[('a', 3), ('b', 5), ('z', 10), ('z', 20), ('z', 30)]
doAssert sorted(toSeq(a.allValues('z'))) == @[10, 20, 30]
bind nextTry
var h: Hash = genHash(key) and high(t.data)
let L = len(t)
while isFilled(t.data[h].hcode):
Expand Down Expand Up @@ -1283,7 +1281,6 @@ proc rawInsert[A, B](t: var OrderedTable[A, B],
t.last = h

proc enlarge[A, B](t: var OrderedTable[A, B]) =
bind nextTry
var n: OrderedKeyValuePairSeq[A, B]
newSeq(n, len(t.data) * growthFactor)
var h = t.first
Expand Down Expand Up @@ -2252,7 +2249,6 @@ type

proc ctRawInsert[A](t: CountTable[A], data: var seq[tuple[key: A, val: int]],
key: A, val: int) =
bind nextTry
var h: Hash = hash(key) and high(data)
while data[h].val != 0: h = nextTry(h, high(data))
data[h].key = key
Expand All @@ -2266,7 +2262,6 @@ proc enlarge[A](t: var CountTable[A]) =
swap(t.data, n)

proc rawGet[A](t: CountTable[A], key: A): int =
bind nextTry
if t.data.len == 0:
return -1
var h: Hash = hash(key) and high(t.data) # start with real hash value
Expand Down
Loading

0 comments on commit d58eb41

Please sign in to comment.