distinguish properly between nkOpen and nkClosedSymChoice
This commit is contained in:
parent
9a7f0cd851
commit
b5b5e6e76d
15 changed files with 107 additions and 50 deletions
|
|
@ -104,7 +104,8 @@ type
|
||||||
|
|
||||||
nkTableConstr, # a table constructor {expr: expr}
|
nkTableConstr, # a table constructor {expr: expr}
|
||||||
nkBind, # ``bind expr`` node
|
nkBind, # ``bind expr`` node
|
||||||
nkSymChoice, # symbol choice node
|
nkClosedSymChoice, # symbol choice node; a list of nkSyms (closed)
|
||||||
|
nkOpenSymChoice, # symbol choice node; a list of nkSyms (open)
|
||||||
nkHiddenStdConv, # an implicit standard type conversion
|
nkHiddenStdConv, # an implicit standard type conversion
|
||||||
nkHiddenSubConv, # an implicit type conversion from a subtype
|
nkHiddenSubConv, # an implicit type conversion from a subtype
|
||||||
# to a supertype
|
# to a supertype
|
||||||
|
|
@ -473,6 +474,11 @@ const
|
||||||
mInRange, mInSet, mRepr,
|
mInRange, mInSet, mRepr,
|
||||||
mRand,
|
mRand,
|
||||||
mCopyStr, mCopyStrLast}
|
mCopyStr, mCopyStrLast}
|
||||||
|
# magics that require special semantic checking and
|
||||||
|
# thus cannot be overloaded (also documented in the spec!):
|
||||||
|
SpecialSemMagics* = {
|
||||||
|
mDefined, mDefinedInScope, mCompiles, mLow, mHigh, mSizeOf, mIs, mOf,
|
||||||
|
mEcho, mShallowCopy, mExpandToAst}
|
||||||
|
|
||||||
type
|
type
|
||||||
PNode* = ref TNode
|
PNode* = ref TNode
|
||||||
|
|
|
||||||
|
|
@ -230,7 +230,7 @@ proc InitOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
|
||||||
LocalError(n.sons[1].info, errIdentifierExpected,
|
LocalError(n.sons[1].info, errIdentifierExpected,
|
||||||
renderTree(n.sons[1]))
|
renderTree(n.sons[1]))
|
||||||
result = errorSym(c, n.sons[1])
|
result = errorSym(c, n.sons[1])
|
||||||
of nkSymChoice:
|
of nkClosedSymChoice, nkOpenSymChoice:
|
||||||
o.mode = oimSymChoice
|
o.mode = oimSymChoice
|
||||||
result = n.sons[0].sym
|
result = n.sons[0].sym
|
||||||
o.stackPtr = 1
|
o.stackPtr = 1
|
||||||
|
|
@ -269,7 +269,7 @@ proc nextOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
|
||||||
result = n.sons[o.stackPtr].sym
|
result = n.sons[o.stackPtr].sym
|
||||||
Incl(o.inSymChoice, result.id)
|
Incl(o.inSymChoice, result.id)
|
||||||
inc(o.stackPtr)
|
inc(o.stackPtr)
|
||||||
else:
|
elif n.kind == nkOpenSymChoice:
|
||||||
# try 'local' symbols too for Koenig's lookup:
|
# try 'local' symbols too for Koenig's lookup:
|
||||||
o.mode = oimSymChoiceLocalLookup
|
o.mode = oimSymChoiceLocalLookup
|
||||||
o.stackPtr = c.tab.tos-1
|
o.stackPtr = c.tab.tos-1
|
||||||
|
|
|
||||||
|
|
@ -379,7 +379,8 @@ proc lsub(n: PNode): int =
|
||||||
of nkPar, nkCurly, nkBracket, nkClosure: result = lcomma(n) + 2
|
of nkPar, nkCurly, nkBracket, nkClosure: result = lcomma(n) + 2
|
||||||
of nkTableConstr:
|
of nkTableConstr:
|
||||||
result = if n.len > 0: lcomma(n) + 2 else: len("{:}")
|
result = if n.len > 0: lcomma(n) + 2 else: len("{:}")
|
||||||
of nkSymChoice: result = lsons(n) + len("()") + sonsLen(n) - 1
|
of nkClosedSymChoice, nkOpenSymChoice:
|
||||||
|
result = lsons(n) + len("()") + sonsLen(n) - 1
|
||||||
of nkTupleTy: result = lcomma(n) + len("tuple[]")
|
of nkTupleTy: result = lcomma(n) + len("tuple[]")
|
||||||
of nkDotExpr: result = lsons(n) + 1
|
of nkDotExpr: result = lsons(n) + 1
|
||||||
of nkBind: result = lsons(n) + len("bind_")
|
of nkBind: result = lsons(n) + len("bind_")
|
||||||
|
|
@ -833,7 +834,7 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
|
||||||
put(g, tkParLe, "(")
|
put(g, tkParLe, "(")
|
||||||
gcomma(g, n, 1)
|
gcomma(g, n, 1)
|
||||||
put(g, tkParRi, ")")
|
put(g, tkParRi, ")")
|
||||||
of nkSymChoice:
|
of nkClosedSymChoice, nkOpenSymChoice:
|
||||||
put(g, tkParLe, "(")
|
put(g, tkParLe, "(")
|
||||||
for i in countup(0, sonsLen(n) - 1):
|
for i in countup(0, sonsLen(n) - 1):
|
||||||
if i > 0: put(g, tkOpr, "|")
|
if i > 0: put(g, tkOpr, "|")
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@
|
||||||
## This module implements semantic checking for calls.
|
## This module implements semantic checking for calls.
|
||||||
# included from sem.nim
|
# included from sem.nim
|
||||||
|
|
||||||
proc sameMethodDispatcher(a, b: PSym): bool =
|
proc sameMethodDispatcher(a, b: PSym): bool =
|
||||||
result = false
|
result = false
|
||||||
if a.kind == skMethod and b.kind == skMethod:
|
if a.kind == skMethod and b.kind == skMethod:
|
||||||
var aa = lastSon(a.ast)
|
var aa = lastSon(a.ast)
|
||||||
|
|
@ -132,11 +132,11 @@ proc explicitGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode =
|
||||||
if safeLen(s.ast.sons[genericParamsPos]) != n.len-1:
|
if safeLen(s.ast.sons[genericParamsPos]) != n.len-1:
|
||||||
return explicitGenericInstError(n)
|
return explicitGenericInstError(n)
|
||||||
result = explicitGenericSym(c, n, s)
|
result = explicitGenericSym(c, n, s)
|
||||||
elif a.kind == nkSymChoice:
|
elif a.kind in {nkClosedSymChoice, nkOpenSymChoice}:
|
||||||
# choose the generic proc with the proper number of type parameters.
|
# choose the generic proc with the proper number of type parameters.
|
||||||
# XXX I think this could be improved by reusing sigmatch.ParamTypesMatch.
|
# XXX I think this could be improved by reusing sigmatch.ParamTypesMatch.
|
||||||
# It's good enough for now.
|
# It's good enough for now.
|
||||||
result = newNodeI(nkSymChoice, n.info)
|
result = newNodeI(a.kind, n.info)
|
||||||
for i in countup(0, len(a)-1):
|
for i in countup(0, len(a)-1):
|
||||||
var candidate = a.sons[i].sym
|
var candidate = a.sons[i].sym
|
||||||
if candidate.kind in {skProc, skMethod, skConverter, skIterator}:
|
if candidate.kind in {skProc, skMethod, skConverter, skIterator}:
|
||||||
|
|
@ -144,8 +144,9 @@ proc explicitGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode =
|
||||||
# type parameters:
|
# type parameters:
|
||||||
if safeLen(candidate.ast.sons[genericParamsPos]) == n.len-1:
|
if safeLen(candidate.ast.sons[genericParamsPos]) == n.len-1:
|
||||||
result.add(explicitGenericSym(c, n, candidate))
|
result.add(explicitGenericSym(c, n, candidate))
|
||||||
# get rid of nkSymChoice if not ambiguous:
|
# get rid of nkClosedSymChoice if not ambiguous:
|
||||||
if result.len == 1: result = result[0]
|
if result.len == 1 and a.kind == nkClosedSymChoice:
|
||||||
|
result = result[0]
|
||||||
# candidateCount != 1: return explicitGenericInstError(n)
|
# candidateCount != 1: return explicitGenericInstError(n)
|
||||||
else:
|
else:
|
||||||
result = explicitGenericInstError(n)
|
result = explicitGenericInstError(n)
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,7 @@ proc semExprNoDeref(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||||
result.typ = errorType(c)
|
result.typ = errorType(c)
|
||||||
|
|
||||||
proc semSymGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode =
|
proc semSymGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode =
|
||||||
result = symChoice(c, n, s)
|
result = symChoice(c, n, s, scClosed)
|
||||||
|
|
||||||
proc inlineConst(n: PNode, s: PSym): PNode {.inline.} =
|
proc inlineConst(n: PNode, s: PSym): PNode {.inline.} =
|
||||||
result = copyTree(s.ast)
|
result = copyTree(s.ast)
|
||||||
|
|
@ -72,7 +72,7 @@ proc semSym(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
|
||||||
if sfProcVar notin s.flags and s.typ.callConv == ccDefault and
|
if sfProcVar notin s.flags and s.typ.callConv == ccDefault and
|
||||||
smoduleId != c.module.id and smoduleId != c.friendModule.id:
|
smoduleId != c.module.id and smoduleId != c.friendModule.id:
|
||||||
LocalError(n.info, errXCannotBePassedToProcVar, s.name.s)
|
LocalError(n.info, errXCannotBePassedToProcVar, s.name.s)
|
||||||
result = symChoice(c, n, s)
|
result = symChoice(c, n, s, scClosed)
|
||||||
if result.kind == nkSym:
|
if result.kind == nkSym:
|
||||||
markIndirect(c, result.sym)
|
markIndirect(c, result.sym)
|
||||||
if isGenericRoutine(result.sym):
|
if isGenericRoutine(result.sym):
|
||||||
|
|
@ -182,6 +182,9 @@ proc isCastable(dst, src: PType): bool =
|
||||||
(skipTypes(dst, abstractInst).kind in IntegralTypes) or
|
(skipTypes(dst, abstractInst).kind in IntegralTypes) or
|
||||||
(skipTypes(src, abstractInst).kind in IntegralTypes)
|
(skipTypes(src, abstractInst).kind in IntegralTypes)
|
||||||
|
|
||||||
|
proc isSymChoice(n: PNode): bool {.inline.} =
|
||||||
|
result = n.kind in {nkClosedSymChoice, nkOpenSymChoice}
|
||||||
|
|
||||||
proc semConv(c: PContext, n: PNode, s: PSym): PNode =
|
proc semConv(c: PContext, n: PNode, s: PSym): PNode =
|
||||||
if sonsLen(n) != 2:
|
if sonsLen(n) != 2:
|
||||||
LocalError(n.info, errConvNeedsOneArg)
|
LocalError(n.info, errConvNeedsOneArg)
|
||||||
|
|
@ -191,7 +194,7 @@ proc semConv(c: PContext, n: PNode, s: PSym): PNode =
|
||||||
addSon(result, copyTree(n.sons[0]))
|
addSon(result, copyTree(n.sons[0]))
|
||||||
addSon(result, semExprWithType(c, n.sons[1]))
|
addSon(result, semExprWithType(c, n.sons[1]))
|
||||||
var op = result.sons[1]
|
var op = result.sons[1]
|
||||||
if op.kind != nkSymChoice:
|
if not isSymChoice(op):
|
||||||
checkConvertible(result.info, result.typ, op.typ)
|
checkConvertible(result.info, result.typ, op.typ)
|
||||||
else:
|
else:
|
||||||
for i in countup(0, sonsLen(op) - 1):
|
for i in countup(0, sonsLen(op) - 1):
|
||||||
|
|
@ -830,7 +833,7 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
## returns nil if it's not a built-in field access
|
## returns nil if it's not a built-in field access
|
||||||
checkSonsLen(n, 2)
|
checkSonsLen(n, 2)
|
||||||
# early exit for this; see tests/compile/tbindoverload.nim:
|
# early exit for this; see tests/compile/tbindoverload.nim:
|
||||||
if n.sons[1].kind == nkSymChoice: return
|
if isSymChoice(n.sons[1]): return
|
||||||
|
|
||||||
var s = qualifiedLookup(c, n, {checkAmbiguity, checkUndeclared})
|
var s = qualifiedLookup(c, n, {checkAmbiguity, checkUndeclared})
|
||||||
if s != nil:
|
if s != nil:
|
||||||
|
|
@ -910,7 +913,7 @@ proc semFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
# in Nimrod. We first allow types in the semantic checking.
|
# in Nimrod. We first allow types in the semantic checking.
|
||||||
result = builtinFieldAccess(c, n, flags)
|
result = builtinFieldAccess(c, n, flags)
|
||||||
if result == nil:
|
if result == nil:
|
||||||
if n.sons[1].kind == nkSymChoice:
|
if isSymChoice(n.sons[1]):
|
||||||
result = newNodeI(nkDotCall, n.info)
|
result = newNodeI(nkDotCall, n.info)
|
||||||
addSon(result, n.sons[1])
|
addSon(result, n.sons[1])
|
||||||
addSon(result, copyTree(n[0]))
|
addSon(result, copyTree(n[0]))
|
||||||
|
|
@ -1222,6 +1225,7 @@ proc semShallowCopy(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
|
|
||||||
proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
|
proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
|
||||||
# this is a hotspot in the compiler!
|
# this is a hotspot in the compiler!
|
||||||
|
# DON'T forget to update ast.SpecialSemMagics if you add a magic here!
|
||||||
result = n
|
result = n
|
||||||
case s.magic # magics that need special treatment
|
case s.magic # magics that need special treatment
|
||||||
of mDefined: result = semDefined(c, setMs(n, s), false)
|
of mDefined: result = semDefined(c, setMs(n, s), false)
|
||||||
|
|
@ -1518,8 +1522,8 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||||
else:
|
else:
|
||||||
#liMessage(n.info, warnUser, renderTree(n));
|
#liMessage(n.info, warnUser, renderTree(n));
|
||||||
result = semIndirectOp(c, n, flags)
|
result = semIndirectOp(c, n, flags)
|
||||||
elif n.sons[0].kind == nkSymChoice or n[0].kind == nkBracketExpr and
|
elif isSymChoice(n.sons[0]) or n[0].kind == nkBracketExpr and
|
||||||
n[0][0].kind == nkSymChoice:
|
isSymChoice(n[0][0]):
|
||||||
result = semDirectOp(c, n, flags)
|
result = semDirectOp(c, n, flags)
|
||||||
else:
|
else:
|
||||||
result = semIndirectOp(c, n, flags)
|
result = semIndirectOp(c, n, flags)
|
||||||
|
|
@ -1576,7 +1580,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||||
checkMinSonsLen(n, 2)
|
checkMinSonsLen(n, 2)
|
||||||
of nkTableConstr:
|
of nkTableConstr:
|
||||||
result = semTableConstr(c, n)
|
result = semTableConstr(c, n)
|
||||||
of nkSymChoice:
|
of nkClosedSymChoice, nkOpenSymChoice:
|
||||||
LocalError(n.info, errExprXAmbiguous, renderTree(n, {renderNoComments}))
|
LocalError(n.info, errExprXAmbiguous, renderTree(n, {renderNoComments}))
|
||||||
# error correction: Pick first element:
|
# error correction: Pick first element:
|
||||||
result = n.sons[0]
|
result = n.sons[0]
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@
|
||||||
# A problem is that it cannot be detected if the symbol is introduced
|
# A problem is that it cannot be detected if the symbol is introduced
|
||||||
# as in ``var x = ...`` or used because macros/templates can hide this!
|
# as in ``var x = ...`` or used because macros/templates can hide this!
|
||||||
# So we have to eval templates/macros right here so that symbol
|
# So we have to eval templates/macros right here so that symbol
|
||||||
# lookup can be accurate.
|
# lookup can be accurate. XXX But this can only be done for immediate macros!
|
||||||
|
|
||||||
# included from sem.nim
|
# included from sem.nim
|
||||||
|
|
||||||
|
|
@ -47,8 +47,8 @@ proc semGenericStmtSymbol(c: PContext, n: PNode, s: PSym): PNode =
|
||||||
# Introduced in this pass! Leave it as an identifier.
|
# Introduced in this pass! Leave it as an identifier.
|
||||||
result = n
|
result = n
|
||||||
of skProc, skMethod, skIterator, skConverter:
|
of skProc, skMethod, skIterator, skConverter:
|
||||||
result = symChoice(c, n, s)
|
result = symChoice(c, n, s, scOpen)
|
||||||
of skTemplate:
|
of skTemplate:
|
||||||
result = semTemplateExpr(c, n, s, false)
|
result = semTemplateExpr(c, n, s, false)
|
||||||
of skMacro:
|
of skMacro:
|
||||||
result = semMacroExpr(c, n, s, false)
|
result = semMacroExpr(c, n, s, false)
|
||||||
|
|
@ -75,7 +75,8 @@ proc semGenericStmt(c: PContext, n: PNode,
|
||||||
if withinBind in flags:
|
if withinBind in flags:
|
||||||
localError(n.info, errUndeclaredIdentifier, n.ident.s)
|
localError(n.info, errUndeclaredIdentifier, n.ident.s)
|
||||||
else:
|
else:
|
||||||
if withinBind in flags or s.id in toBind: result = symChoice(c, n, s)
|
if withinBind in flags or s.id in toBind:
|
||||||
|
result = symChoice(c, n, s, scClosed)
|
||||||
else: result = semGenericStmtSymbol(c, n, s)
|
else: result = semGenericStmtSymbol(c, n, s)
|
||||||
of nkDotExpr:
|
of nkDotExpr:
|
||||||
var s = QualifiedLookUp(c, n, {})
|
var s = QualifiedLookUp(c, n, {})
|
||||||
|
|
@ -104,7 +105,7 @@ proc semGenericStmt(c: PContext, n: PNode,
|
||||||
of skUnknown, skParam:
|
of skUnknown, skParam:
|
||||||
# Leave it as an identifier.
|
# Leave it as an identifier.
|
||||||
of skProc, skMethod, skIterator, skConverter:
|
of skProc, skMethod, skIterator, skConverter:
|
||||||
result.sons[0] = symChoice(c, n.sons[0], s)
|
result.sons[0] = symChoice(c, n.sons[0], s, scOpen)
|
||||||
first = 1
|
first = 1
|
||||||
of skGenericParam:
|
of skGenericParam:
|
||||||
result.sons[0] = newSymNode(s, n.sons[0].info)
|
result.sons[0] = newSymNode(s, n.sons[0].info)
|
||||||
|
|
@ -114,7 +115,7 @@ proc semGenericStmt(c: PContext, n: PNode,
|
||||||
if (s.typ != nil) and (s.typ.kind != tyGenericParam):
|
if (s.typ != nil) and (s.typ.kind != tyGenericParam):
|
||||||
result.sons[0] = newSymNode(s, n.sons[0].info)
|
result.sons[0] = newSymNode(s, n.sons[0].info)
|
||||||
first = 1
|
first = 1
|
||||||
else:
|
else:
|
||||||
result.sons[0] = newSymNode(s, n.sons[0].info)
|
result.sons[0] = newSymNode(s, n.sons[0].info)
|
||||||
first = 1
|
first = 1
|
||||||
for i in countup(first, sonsLen(result) - 1):
|
for i in countup(first, sonsLen(result) - 1):
|
||||||
|
|
|
||||||
|
|
@ -49,16 +49,22 @@ proc semBindSym(c: PContext, n: PNode): PNode =
|
||||||
result = copyNode(n)
|
result = copyNode(n)
|
||||||
result.add(n.sons[0])
|
result.add(n.sons[0])
|
||||||
|
|
||||||
let sl = c.semConstExpr(c, n.sons[1])
|
let sl = semConstExpr(c, n.sons[1])
|
||||||
if sl.kind notin {nkStrLit, nkRStrLit, nkTripleStrLit}:
|
if sl.kind notin {nkStrLit, nkRStrLit, nkTripleStrLit}:
|
||||||
LocalError(n.info, errStringLiteralExpected)
|
LocalError(n.sons[1].info, errStringLiteralExpected)
|
||||||
|
return errorNode(c, n)
|
||||||
|
|
||||||
|
let isMixin = semConstExpr(c, n.sons[2])
|
||||||
|
if isMixin.kind != nkIntLit or isMixin.intVal < 0 or
|
||||||
|
isMixin.intVal > high(TSymChoiceRule).int:
|
||||||
|
LocalError(n.sons[2].info, errConstExprExpected)
|
||||||
return errorNode(c, n)
|
return errorNode(c, n)
|
||||||
|
|
||||||
let id = newIdentNode(getIdent(sl.strVal), n.info)
|
let id = newIdentNode(getIdent(sl.strVal), n.info)
|
||||||
let s = QualifiedLookUp(c, id)
|
let s = QualifiedLookUp(c, id)
|
||||||
if s != nil:
|
if s != nil:
|
||||||
# we need to mark all symbols:
|
# we need to mark all symbols:
|
||||||
let sc = symChoice(c, id, s)
|
var sc = symChoice(c, id, s, TSymChoiceRule(isMixin.intVal))
|
||||||
result.add(sc)
|
result.add(sc)
|
||||||
else:
|
else:
|
||||||
LocalError(n.sons[1].info, errUndeclaredIdentifier, sl.strVal)
|
LocalError(n.sons[1].info, errUndeclaredIdentifier, sl.strVal)
|
||||||
|
|
|
||||||
|
|
@ -40,8 +40,12 @@ proc symBinding(n: PNode): TSymBinding =
|
||||||
of wInject: return spInject
|
of wInject: return spInject
|
||||||
else: nil
|
else: nil
|
||||||
|
|
||||||
proc symChoice(c: PContext, n: PNode, s: PSym): PNode =
|
type
|
||||||
var
|
TSymChoiceRule = enum
|
||||||
|
scClosed, scOpen, scForceOpen
|
||||||
|
|
||||||
|
proc symChoice(c: PContext, n: PNode, s: PSym, r: TSymChoiceRule): PNode =
|
||||||
|
var
|
||||||
a: PSym
|
a: PSym
|
||||||
o: TOverloadIter
|
o: TOverloadIter
|
||||||
var i = 0
|
var i = 0
|
||||||
|
|
@ -50,17 +54,17 @@ proc symChoice(c: PContext, n: PNode, s: PSym): PNode =
|
||||||
a = nextOverloadIter(o, c, n)
|
a = nextOverloadIter(o, c, n)
|
||||||
inc(i)
|
inc(i)
|
||||||
if i > 1: break
|
if i > 1: break
|
||||||
if i <= 1:
|
if i <= 1 and r != scForceOpen:
|
||||||
# XXX this makes more sense but breaks bootstrapping for now:
|
# XXX this makes more sense but breaks bootstrapping for now:
|
||||||
# (s.kind notin routineKinds or s.magic != mNone):
|
# (s.kind notin routineKinds or s.magic != mNone):
|
||||||
# for some reason 'nextTry' is copied and considered as a candidate in
|
# for instance 'nextTry' is both in tables.nim and astalgo.nim ...
|
||||||
# tables.nim
|
|
||||||
result = newSymNode(s, n.info)
|
result = newSymNode(s, n.info)
|
||||||
markUsed(n, s)
|
markUsed(n, s)
|
||||||
else:
|
else:
|
||||||
# semantic checking requires a type; ``fitNode`` deals with it
|
# semantic checking requires a type; ``fitNode`` deals with it
|
||||||
# appropriately
|
# appropriately
|
||||||
result = newNodeIT(nkSymChoice, n.info, newTypeS(tyNone, c))
|
let kind = if r == scClosed: nkClosedSymChoice else: nkOpenSymChoice
|
||||||
|
result = newNodeIT(kind, n.info, newTypeS(tyNone, c))
|
||||||
a = initOverloadIter(o, c, n)
|
a = initOverloadIter(o, c, n)
|
||||||
while a != nil:
|
while a != nil:
|
||||||
incl(a.flags, sfUsed)
|
incl(a.flags, sfUsed)
|
||||||
|
|
@ -78,7 +82,7 @@ proc semBindStmt(c: PContext, n: PNode, toBind: var TIntSet): PNode =
|
||||||
let s = QualifiedLookUp(c, a)
|
let s = QualifiedLookUp(c, a)
|
||||||
if s != nil:
|
if s != nil:
|
||||||
# we need to mark all symbols:
|
# we need to mark all symbols:
|
||||||
let sc = symChoice(c, n, s)
|
let sc = symChoice(c, n, s, scClosed)
|
||||||
if sc.kind == nkSym:
|
if sc.kind == nkSym:
|
||||||
toBind.incl(sc.sym.id)
|
toBind.incl(sc.sym.id)
|
||||||
else:
|
else:
|
||||||
|
|
@ -178,7 +182,7 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
|
||||||
incl(s.flags, sfUsed)
|
incl(s.flags, sfUsed)
|
||||||
result = newSymNode(s, n.info)
|
result = newSymNode(s, n.info)
|
||||||
elif Contains(c.toBind, s.id):
|
elif Contains(c.toBind, s.id):
|
||||||
result = symChoice(c.c, n, s)
|
result = symChoice(c.c, n, s, scClosed)
|
||||||
elif s.owner == c.owner:
|
elif s.owner == c.owner:
|
||||||
InternalAssert sfGenSym in s.flags
|
InternalAssert sfGenSym in s.flags
|
||||||
incl(s.flags, sfUsed)
|
incl(s.flags, sfUsed)
|
||||||
|
|
@ -294,7 +298,7 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
|
||||||
if n.kind == nkDotExpr or n.kind == nkAccQuoted:
|
if n.kind == nkDotExpr or n.kind == nkAccQuoted:
|
||||||
let s = QualifiedLookUp(c.c, n, {})
|
let s = QualifiedLookUp(c.c, n, {})
|
||||||
if s != nil and Contains(c.toBind, s.id):
|
if s != nil and Contains(c.toBind, s.id):
|
||||||
return symChoice(c.c, n, s)
|
return symChoice(c.c, n, s, scClosed)
|
||||||
result = n
|
result = n
|
||||||
for i in countup(0, sonsLen(n) - 1):
|
for i in countup(0, sonsLen(n) - 1):
|
||||||
result.sons[i] = semTemplBody(c, n.sons[i])
|
result.sons[i] = semTemplBody(c, n.sons[i])
|
||||||
|
|
@ -308,7 +312,7 @@ proc semTemplBodyDirty(c: var TemplCtx, n: PNode): PNode =
|
||||||
if s.owner == c.owner and s.kind == skParam:
|
if s.owner == c.owner and s.kind == skParam:
|
||||||
result = newSymNode(s, n.info)
|
result = newSymNode(s, n.info)
|
||||||
elif Contains(c.toBind, s.id):
|
elif Contains(c.toBind, s.id):
|
||||||
result = symChoice(c.c, n, s)
|
result = symChoice(c.c, n, s, scClosed)
|
||||||
of nkBind:
|
of nkBind:
|
||||||
result = semTemplBodyDirty(c, n.sons[0])
|
result = semTemplBodyDirty(c, n.sons[0])
|
||||||
of nkBindStmt:
|
of nkBindStmt:
|
||||||
|
|
@ -321,7 +325,7 @@ proc semTemplBodyDirty(c: var TemplCtx, n: PNode): PNode =
|
||||||
if n.kind == nkDotExpr or n.kind == nkAccQuoted:
|
if n.kind == nkDotExpr or n.kind == nkAccQuoted:
|
||||||
let s = QualifiedLookUp(c.c, n, {})
|
let s = QualifiedLookUp(c.c, n, {})
|
||||||
if s != nil and Contains(c.toBind, s.id):
|
if s != nil and Contains(c.toBind, s.id):
|
||||||
return symChoice(c.c, n, s)
|
return symChoice(c.c, n, s, scClosed)
|
||||||
result = n
|
result = n
|
||||||
for i in countup(0, sonsLen(n) - 1):
|
for i in countup(0, sonsLen(n) - 1):
|
||||||
result.sons[i] = semTemplBodyDirty(c, n.sons[i])
|
result.sons[i] = semTemplBodyDirty(c, n.sons[i])
|
||||||
|
|
|
||||||
|
|
@ -703,7 +703,7 @@ proc ParamTypesMatchAux(c: PContext, m: var TCandidate, f, a: PType,
|
||||||
|
|
||||||
proc ParamTypesMatch(c: PContext, m: var TCandidate, f, a: PType,
|
proc ParamTypesMatch(c: PContext, m: var TCandidate, f, a: PType,
|
||||||
arg, argOrig: PNode): PNode =
|
arg, argOrig: PNode): PNode =
|
||||||
if arg == nil or arg.kind != nkSymChoice:
|
if arg == nil or arg.kind != nkClosedSymChoice:
|
||||||
result = ParamTypesMatchAux(c, m, f, a, arg, argOrig)
|
result = ParamTypesMatchAux(c, m, f, a, arg, argOrig)
|
||||||
else:
|
else:
|
||||||
# CAUTION: The order depends on the used hashing scheme. Thus it is
|
# CAUTION: The order depends on the used hashing scheme. Thus it is
|
||||||
|
|
|
||||||
|
|
@ -85,7 +85,7 @@ proc suggestObject(c: PContext, n: PNode, outputs: var int) =
|
||||||
|
|
||||||
proc nameFits(c: PContext, s: PSym, n: PNode): bool =
|
proc nameFits(c: PContext, s: PSym, n: PNode): bool =
|
||||||
var op = n.sons[0]
|
var op = n.sons[0]
|
||||||
if op.kind == nkSymChoice: op = op.sons[0]
|
if op.kind in {nkOpenSymChoice, nkClosedSymChoice}: op = op.sons[0]
|
||||||
var opr: PIdent
|
var opr: PIdent
|
||||||
case op.kind
|
case op.kind
|
||||||
of nkSym: opr = op.sym.name
|
of nkSym: opr = op.sym.name
|
||||||
|
|
|
||||||
|
|
@ -143,7 +143,8 @@ proc SwapOperands*(op: PNode) =
|
||||||
proc IsRange*(n: PNode): bool {.inline.} =
|
proc IsRange*(n: PNode): bool {.inline.} =
|
||||||
if n.kind == nkInfix:
|
if n.kind == nkInfix:
|
||||||
if n[0].kind == nkIdent and n[0].ident.id == ord(wDotDot) or
|
if n[0].kind == nkIdent and n[0].ident.id == ord(wDotDot) or
|
||||||
n[0].kind == nkSymChoice and n[0][1].sym.name.id == ord(wDotDot):
|
n[0].kind in {nkClosedSymChoice, nkOpenSymChoice} and
|
||||||
|
n[0][1].sym.name.id == ord(wDotDot):
|
||||||
result = true
|
result = true
|
||||||
|
|
||||||
proc whichPragma*(n: PNode): TSpecialWord =
|
proc whichPragma*(n: PNode): TSpecialWord =
|
||||||
|
|
|
||||||
|
|
@ -117,7 +117,7 @@ proc isCompatibleToCString(a: PType): bool =
|
||||||
result = true
|
result = true
|
||||||
|
|
||||||
proc getProcHeader(sym: PSym): string =
|
proc getProcHeader(sym: PSym): string =
|
||||||
result = sym.name.s & '('
|
result = sym.owner.name.s & '.' & sym.name.s & '('
|
||||||
var n = sym.typ.n
|
var n = sym.typ.n
|
||||||
for i in countup(1, sonsLen(n) - 1):
|
for i in countup(1, sonsLen(n) - 1):
|
||||||
var p = n.sons[i]
|
var p = n.sons[i]
|
||||||
|
|
|
||||||
|
|
@ -2362,6 +2362,19 @@ notation. (Thus an operator can have more than two parameters):
|
||||||
|
|
||||||
assert `*+`(3, 4, 6) == `*`(a, `+`(b, c))
|
assert `*+`(3, 4, 6) == `*`(a, `+`(b, c))
|
||||||
|
|
||||||
|
|
||||||
|
Nonoverloadable builtins
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
The following builtin procs cannot be overloaded for reasons of implementation
|
||||||
|
simplicity (they require specialized semantic checking)::
|
||||||
|
|
||||||
|
defined, definedInScope, compiles, low, high, sizeOf,
|
||||||
|
is, of, echo, shallowCopy, getAst
|
||||||
|
|
||||||
|
Thus they act more like keywords than like ordinary identifiers; unlike a
|
||||||
|
keyword however, a redefinition may `shadow`:id: the definition in
|
||||||
|
the ``system`` module.
|
||||||
|
|
||||||
|
|
||||||
Var parameters
|
Var parameters
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,10 @@ type
|
||||||
nnkBracket, nnkBracketExpr, nnkPragmaExpr, nnkRange,
|
nnkBracket, nnkBracketExpr, nnkPragmaExpr, nnkRange,
|
||||||
nnkDotExpr, nnkCheckedFieldExpr, nnkDerefExpr, nnkIfExpr,
|
nnkDotExpr, nnkCheckedFieldExpr, nnkDerefExpr, nnkIfExpr,
|
||||||
nnkElifExpr, nnkElseExpr, nnkLambda, nnkDo, nnkAccQuoted,
|
nnkElifExpr, nnkElseExpr, nnkLambda, nnkDo, nnkAccQuoted,
|
||||||
nnkTableConstr, nnkBind, nnkSymChoice, nnkHiddenStdConv,
|
nnkTableConstr, nnkBind,
|
||||||
|
nnkClosedSymChoice,
|
||||||
|
nnkOpenSymChoice,
|
||||||
|
nnkHiddenStdConv,
|
||||||
nnkHiddenSubConv, nnkHiddenCallConv, nnkConv, nnkCast, nnkStaticExpr,
|
nnkHiddenSubConv, nnkHiddenCallConv, nnkConv, nnkCast, nnkStaticExpr,
|
||||||
nnkAddr, nnkHiddenAddr, nnkHiddenDeref, nnkObjDownConv,
|
nnkAddr, nnkHiddenAddr, nnkHiddenDeref, nnkObjDownConv,
|
||||||
nnkObjUpConv, nnkChckRangeF, nnkChckRange64, nnkChckRange,
|
nnkObjUpConv, nnkChckRangeF, nnkChckRange64, nnkChckRange,
|
||||||
|
|
@ -186,12 +189,29 @@ proc newIdentNode*(i: string): PNimrodNode {.compileTime.} =
|
||||||
result = newNimNode(nnkIdent)
|
result = newNimNode(nnkIdent)
|
||||||
result.ident = !i
|
result.ident = !i
|
||||||
|
|
||||||
proc bindSym*(ident: string): PNimrodNode {.magic: "NBindSym".}
|
type
|
||||||
|
TBindSymRule* = enum ## specifies how ``bindSym`` behaves
|
||||||
|
brClosed, ## only the symbols in current scope are bound
|
||||||
|
brOpen, ## open wrt overloaded symbols, but may be a single
|
||||||
|
## symbol if not ambiguous (the rules match that of
|
||||||
|
## binding in generics)
|
||||||
|
brForceOpen ## same as brOpen, but it will always be open even
|
||||||
|
## if not ambiguous (this cannot be achieved with
|
||||||
|
## any other means in the language currently)
|
||||||
|
|
||||||
|
proc bindSym*(ident: string, rule: TBindSymRule = brClosed): PNimrodNode {.
|
||||||
|
magic: "NBindSym".}
|
||||||
## creates a node that binds `ident` to a symbol node. The bound symbol
|
## creates a node that binds `ident` to a symbol node. The bound symbol
|
||||||
## needs to be predeclared in a ``bind`` statement!
|
## may be an overloaded symbol.
|
||||||
|
## If ``rule == brClosed`` either an ``nkClosedSymChoice`` tree is
|
||||||
|
## returned or ``nkSym`` if the symbol is not ambiguous.
|
||||||
|
## If ``rule == brOpen`` either an ``nkOpenSymChoice`` tree is
|
||||||
|
## returned or ``nkSym`` if the symbol is not ambiguous.
|
||||||
|
## If ``rule == brForceOpen`` always an ``nkOpenSymChoice`` tree is
|
||||||
|
## returned even if the symbol is not ambiguous.
|
||||||
|
|
||||||
proc toStrLit*(n: PNimrodNode): PNimrodNode {.compileTime.} =
|
proc toStrLit*(n: PNimrodNode): PNimrodNode {.compileTime.} =
|
||||||
## converts the AST `n` to the concrete Nimrod code and wraps that
|
## converts the AST `n` to the concrete Nimrod code and wraps that
|
||||||
## in a string literal node
|
## in a string literal node
|
||||||
return newStrLitNode(repr(n))
|
return newStrLitNode(repr(n))
|
||||||
|
|
||||||
|
|
|
||||||
8
todo.txt
8
todo.txt
|
|
@ -1,6 +1,10 @@
|
||||||
version 0.9.0
|
version 0.9.0
|
||||||
=============
|
=============
|
||||||
|
|
||||||
|
- make 'bind' default for templates and introduce 'mixin'
|
||||||
|
- introduce 'callsite' magic and make macros and templates the same
|
||||||
|
- implement generic templates/macros
|
||||||
|
|
||||||
- implement "closure tuple consists of a single 'ref'" optimization
|
- implement "closure tuple consists of a single 'ref'" optimization
|
||||||
- implement for loop transformation for first class iterators
|
- implement for loop transformation for first class iterators
|
||||||
|
|
||||||
|
|
@ -29,8 +33,6 @@ Bugs
|
||||||
version 0.9.XX
|
version 0.9.XX
|
||||||
==============
|
==============
|
||||||
|
|
||||||
- make 'bind' default for templates and introduce 'mixin'
|
|
||||||
- distinguish between open and closed nkSymChoice
|
|
||||||
- JS gen:
|
- JS gen:
|
||||||
- fix exception handling
|
- fix exception handling
|
||||||
|
|
||||||
|
|
@ -44,7 +46,6 @@ version 0.9.XX
|
||||||
- ``hoist`` pragma for loop hoisting
|
- ``hoist`` pragma for loop hoisting
|
||||||
- document destructors; don't work yet when used as expression
|
- document destructors; don't work yet when used as expression
|
||||||
- make use of ``tyIter`` to fix the implicit items/pairs issue
|
- make use of ``tyIter`` to fix the implicit items/pairs issue
|
||||||
- introduce 'callsite' magic and make macros and templates the same
|
|
||||||
- better support for macros that rewrite procs
|
- better support for macros that rewrite procs
|
||||||
- macros need access to types and symbols
|
- macros need access to types and symbols
|
||||||
- document nimdoc properly finally
|
- document nimdoc properly finally
|
||||||
|
|
@ -56,7 +57,6 @@ version 0.9.XX
|
||||||
- proc specialization in the code gen for write barrier specialization
|
- proc specialization in the code gen for write barrier specialization
|
||||||
- tlastmod returns wrong results on BSD (Linux, MacOS X: works)
|
- tlastmod returns wrong results on BSD (Linux, MacOS X: works)
|
||||||
- nested tuple unpacking; tuple unpacking in non-var-context
|
- nested tuple unpacking; tuple unpacking in non-var-context
|
||||||
- 'nimrod def': does not always work?
|
|
||||||
- test branch coverage
|
- test branch coverage
|
||||||
- make pegs support a compile-time option and make c2nim use regexes instead
|
- make pegs support a compile-time option and make c2nim use regexes instead
|
||||||
per default?
|
per default?
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue