Merge branch 'type-classes' into upstream

This commit is contained in:
Zahary Karadjov 2013-09-03 03:14:56 +03:00
commit 6082595e96
27 changed files with 594 additions and 249 deletions

View file

@ -178,6 +178,7 @@ type
nkIncludeStmt, # an include statement
nkBindStmt, # a bind statement
nkMixinStmt, # a mixin statement
nkUsingStmt, # an using statement
nkCommentStmt, # a comment statement
nkStmtListExpr, # a statement list followed by an expr; this is used
# to allow powerful multi-line templates
@ -190,6 +191,7 @@ type
nkTypeOfExpr, # type(1+2)
nkObjectTy, # object body
nkTupleTy, # tuple body
nkTypeClassTy, # user-defined type class
nkRecList, # list of object parts
nkRecCase, # case section of object
nkRecWhen, # when section of object
@ -215,7 +217,7 @@ type
TNodeKinds* = set[TNodeKind]
type
TSymFlag* = enum # already 30 flags!
TSymFlag* = enum # already 32 flags!
sfUsed, # read access of sym (for warnings) or simply used
sfExported, # symbol is exported from module
sfFromGeneric, # symbol is instantiation of a generic; this is needed
@ -352,6 +354,8 @@ type
# efficiency
nfTransf, # node has been transformed
nfSem # node has been checked for semantics
nfDelegate # the call can use a delegator
nfExprCall # this is an attempt to call a regular expression
TNodeFlags* = set[TNodeFlag]
TTypeFlag* = enum # keep below 32 for efficiency reasons (now: 23)
@ -616,6 +620,7 @@ type
TScope* = object
depthLevel*: int
symbols*: TStrTable
usingSyms*: seq[PNode]
parent*: PScope
PScope* = ref TScope
@ -688,6 +693,7 @@ type
# for enum types a list of symbols
# for tyInt it can be the int literal
# for procs and tyGenericBody, it's the
# the body of the user-defined type class
# formal param list
# else: unused
destructor*: PSym # destructor. warning: nil here may not necessary
@ -700,6 +706,7 @@ type
# -1 means that the size is unkwown
align*: int # the type's alignment requirements
loc*: TLoc
testeeName*: PIdent # the test variable in user-defined type classes
TPair*{.final.} = object
key*, val*: PObject
@ -771,7 +778,8 @@ const
tyProc, tyString, tyError}
ExportableSymKinds* = {skVar, skConst, skProc, skMethod, skType, skIterator,
skMacro, skTemplate, skConverter, skEnumField, skLet, skStub}
PersistentNodeFlags*: TNodeFlags = {nfBase2, nfBase8, nfBase16, nfAllConst}
PersistentNodeFlags*: TNodeFlags = {nfBase2, nfBase8, nfBase16,
nfAllConst, nfDelegate}
namePos* = 0
patternPos* = 1 # empty except for term rewriting macros
genericParamsPos* = 2
@ -1074,6 +1082,7 @@ proc assignType(dest, src: PType) =
dest.size = src.size
dest.align = src.align
dest.destructor = src.destructor
dest.testeeName = src.testeeName
# this fixes 'type TLock = TSysLock':
if src.sym != nil:
if dest.sym != nil:

View file

@ -430,11 +430,14 @@ proc debugTree(n: PNode, indent: int, maxRecDepth: int): PRope =
appf(result, ",$N$1\"info\": $2", [istr, lineInfoToStr(n.info)])
appf(result, "$N$1}", [spaces(indent)])
proc debug(n: PSym) =
#writeln(stdout, ropeToStr(symToYaml(n, 0, 1)))
writeln(stdout, ropeToStr(ropef("$1_$2: $3, $4", [
toRope(n.name.s), toRope(n.id), flagsToStr(n.flags),
flagsToStr(n.loc.flags)])))
proc debug(n: PSym) =
if n == nil:
writeln(stdout, "null")
else:
#writeln(stdout, ropeToStr(symToYaml(n, 0, 1)))
writeln(stdout, ropeToStr(ropef("$1_$2: $3, $4", [
toRope(n.name.s), toRope(n.id), flagsToStr(n.flags),
flagsToStr(n.loc.flags)])))
proc debug(n: PType) =
writeln(stdout, ropeToStr(debugType(n)))

View file

@ -53,7 +53,8 @@ type
features: TSandboxFlags
globals*: TIdNodeTable # state of global vars
getType*: proc(n: PNode): PNode {.closure.}
handleIsOperator*: proc(n: PNode): PNode {.closure.}
PEvalContext* = ref TEvalContext
TEvalFlag = enum
@ -916,33 +917,6 @@ proc evalTypeTrait*(trait, operand: PNode, context: PSym): PNode =
else:
internalAssert false
proc evalIsOp*(n: PNode): PNode =
InternalAssert n.sonsLen == 3 and
n[1].kind == nkSym and n[1].sym.kind == skType and
n[2].kind in {nkStrLit..nkTripleStrLit, nkType}
let t1 = n[1].sym.typ
if n[2].kind in {nkStrLit..nkTripleStrLit}:
case n[2].strVal.normalize
of "closure":
let t = skipTypes(t1, abstractRange)
result = newIntNode(nkIntLit, ord(t.kind == tyProc and
t.callConv == ccClosure and
tfIterator notin t.flags))
of "iterator":
let t = skipTypes(t1, abstractRange)
result = newIntNode(nkIntLit, ord(t.kind == tyProc and
t.callConv == ccClosure and
tfIterator in t.flags))
else:
let t2 = n[2].typ
var match = if t2.kind == tyTypeClass: matchTypeClass(t2, t1)
else: sameType(t1, t2)
result = newIntNode(nkIntLit, ord(match))
result.typ = n.typ
proc expectString(n: PNode) =
if n.kind notin nkStrKinds:
GlobalError(n.info, errStringLiteralExpected)
@ -1038,7 +1012,7 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode =
result = evalTypeTrait(n[0], operand, c.module)
of mIs:
n.sons[1] = evalAux(c, n.sons[1], {})
result = evalIsOp(n)
result = c.handleIsOperator(n)
of mSlurp: result = evalSlurp(evalAux(c, n.sons[1], {}), c.module)
of mStaticExec:
let cmd = evalAux(c, n.sons[1], {})
@ -1466,8 +1440,7 @@ proc eval*(c: PEvalContext, n: PNode): PNode =
else:
stackTrace(c, result.info, errCannotInterpretNodeX, renderTree(n))
proc evalConstExprAux(module, prc: PSym, e: PNode, mode: TEvalMode): PNode =
var p = newEvalContext(module, mode)
proc evalConstExprAux*(p: PEvalContext, module, prc: PSym, e: PNode): PNode =
var s = newStackFrame()
s.call = e
s.prc = prc
@ -1476,12 +1449,6 @@ proc evalConstExprAux(module, prc: PSym, e: PNode, mode: TEvalMode): PNode =
if result != nil and result.kind == nkExceptBranch: result = nil
popStackFrame(p)
proc evalConstExpr*(module: PSym, e: PNode): PNode =
result = evalConstExprAux(module, nil, e, emConst)
proc evalStaticExpr*(module: PSym, e: PNode, prc: PSym): PNode =
result = evalConstExprAux(module, prc, e, emStatic)
proc setupMacroParam(x: PNode): PNode =
result = x
if result.kind == nkHiddenStdConv: result = result.sons[1]

View file

@ -103,4 +103,5 @@ proc IdentEq*(id: PIdent, name: string): bool =
result = id.id == getIdent(name).id
var idAnon* = getIdent":anonymous"
let idDelegator* = getIdent":delegator"

View file

@ -41,7 +41,7 @@ type
tkGeneric, tkIf, tkImport, tkIn, tkInclude, tkInterface,
tkIs, tkIsnot, tkIterator,
tkLambda, tkLet,
tkMacro, tkMethod, tkMixin, tkMod, tkNil, tkNot, tkNotin,
tkMacro, tkMethod, tkMixin, tkUsing, tkMod, tkNil, tkNot, tkNotin,
tkObject, tkOf, tkOr, tkOut,
tkProc, tkPtr, tkRaise, tkRef, tkReturn, tkShared, tkShl, tkShr, tkStatic,
tkTemplate,
@ -75,7 +75,7 @@ const
"finally", "for", "from", "generic", "if",
"import", "in", "include", "interface", "is", "isnot", "iterator",
"lambda", "let",
"macro", "method", "mixin", "mod",
"macro", "method", "mixin", "using", "mod",
"nil", "not", "notin", "object", "of", "or",
"out", "proc", "ptr", "raise", "ref", "return",
"shared", "shl", "shr", "static",

View file

@ -92,6 +92,7 @@ type
errInvalidSectionStart, errGridTableNotImplemented, errGeneralParseError,
errNewSectionExpected, errWhitespaceExpected, errXisNoValidIndexFile,
errCannotRenderX, errVarVarTypeNotAllowed, errInstantiateXExplicitely,
errOnlyACallOpCanBeDelegator, errUsingNoSymbol,
errXExpectsTwoArguments,
errXExpectsObjectTypes, errXcanNeverBeOfThisSubtype, errTooManyIterations,
@ -319,6 +320,8 @@ const
errCannotRenderX: "cannot render reStructuredText element \'$1\'",
errVarVarTypeNotAllowed: "type \'var var\' is not allowed",
errInstantiateXExplicitely: "instantiate '$1' explicitely",
errOnlyACallOpCanBeDelegator: "only a call operator can be a delegator",
errUsingNoSymbol: "'$1' is not a variable, constant or a proc name",
errXExpectsTwoArguments: "\'$1\' expects two arguments",
errXExpectsObjectTypes: "\'$1\' expects object types",
errXcanNeverBeOfThisSubtype: "\'$1\' can never be of this subtype",

View file

@ -927,9 +927,10 @@ proc parseExpr(p: var TParser): PNode =
of tkTry: result = parseTry(p)
else: result = simpleExpr(p)
proc parseEnum(p: var TParser): PNode
proc parseObject(p: var TParser): PNode
proc parseDistinct(p: var TParser): PNode
proc parseEnum(p: var TParser): PNode
proc parseTypeClass(p: var TParser): PNode
proc primary(p: var TParser, mode: TPrimaryMode): PNode =
#| typeKeyw = 'var' | 'ref' | 'ptr' | 'shared' | 'type' | 'tuple'
@ -959,6 +960,7 @@ proc primary(p: var TParser, mode: TPrimaryMode): PNode =
of tkRef: result = parseTypeDescKAux(p, nkRefTy, mode)
of tkPtr: result = parseTypeDescKAux(p, nkPtrTy, mode)
of tkShared: result = parseTypeDescKAux(p, nkSharedTy, mode)
of tkDistinct: result = parseTypeDescKAux(p, nkDistinctTy, mode)
of tkType: result = parseTypeDescKAux(p, nkTypeOfExpr, mode)
of tkTuple: result = parseTuple(p, mode == pmTypeDef)
of tkProc: result = parseProcExpr(p, mode notin {pmTypeDesc, pmTypeDef})
@ -983,12 +985,11 @@ proc primary(p: var TParser, mode: TPrimaryMode): PNode =
else:
result = newNodeP(nkObjectTy, p)
getTok(p)
of tkDistinct:
of tkGeneric:
if mode == pmTypeDef:
result = parseDistinct(p)
result = parseTypeClass(p)
else:
result = newNodeP(nkDistinctTy, p)
getTok(p)
parMessage(p, errInvalidToken, p.tok)
of tkAddr:
result = newNodeP(nkAddr, p)
getTokNoInd(p)
@ -1612,6 +1613,32 @@ proc parseObject(p: var TParser): PNode =
return
addSon(result, parseObjectPart(p))
proc parseTypeClass(p: var TParser): PNode =
result = newNodeP(nkTypeClassTy, p)
getTok(p)
addSon(result, p.parseSymbol)
if p.tok.tokType == tkCurlyDotLe and p.validInd:
addSon(result, parsePragma(p))
else:
addSon(result, ast.emptyNode)
if p.tok.tokType == tkOf and p.tok.indent < 0:
var a = newNodeP(nkOfInherit, p)
getTok(p)
while true:
addSon(a, parseTypeDesc(p))
if p.tok.tokType != tkComma: break
getTok(p)
addSon(result, a)
else:
addSon(result, ast.emptyNode)
if p.tok.tokType == tkComment:
skipComment(p, result)
# an initial IND{>} HAS to follow:
if not realInd(p):
addSon(result, emptyNode)
else:
addSon(result, parseStmt(p))
proc parseDistinct(p: var TParser): PNode =
#| distinct = 'distinct' optInd typeDesc
result = newNodeP(nkDistinctTy, p)
@ -1747,6 +1774,7 @@ proc complexOrSimpleStmt(p: var TParser): PNode =
of tkVar: result = parseSection(p, nkVarSection, parseVariable)
of tkBind: result = parseBind(p, nkBindStmt)
of tkMixin: result = parseBind(p, nkMixinStmt)
of tkUsing: result = parseBind(p, nkUsingStmt)
else: result = simpleStmt(p)
proc parseStmt(p: var TParser): PNode =

View file

@ -24,13 +24,14 @@ const
wCompilerProc, wProcVar, wDeprecated, wVarargs, wCompileTime, wMerge,
wBorrow, wExtern, wImportCompilerProc, wThread, wImportCpp, wImportObjC,
wNoStackFrame, wError, wDiscardable, wNoInit, wDestructor, wCodegenDecl,
wGenSym, wInject, wRaises, wTags, wOperator}
wGenSym, wInject, wRaises, wTags, wOperator, wDelegator}
converterPragmas* = procPragmas
methodPragmas* = procPragmas
templatePragmas* = {wImmediate, wDeprecated, wError, wGenSym, wInject, wDirty}
templatePragmas* = {wImmediate, wDeprecated, wError, wGenSym, wInject, wDirty,
wDelegator}
macroPragmas* = {FirstCallConv..LastCallConv, wImmediate, wImportc, wExportc,
wNodecl, wMagic, wNosideEffect, wCompilerProc, wDeprecated, wExtern,
wImportcpp, wImportobjc, wError, wDiscardable, wGenSym, wInject}
wImportcpp, wImportobjc, wError, wDiscardable, wGenSym, wInject, wDelegator}
iteratorPragmas* = {FirstCallConv..LastCallConv, wNosideEffect, wSideEffect,
wImportc, wExportc, wNodecl, wMagic, wDeprecated, wBorrow, wExtern,
wImportcpp, wImportobjc, wError, wDiscardable, wGenSym, wInject, wRaises,

View file

@ -132,14 +132,42 @@ proc ParamsTypeCheck(c: PContext, typ: PType) {.inline.} =
LocalError(typ.n.info, errXisNoType, typeToString(typ))
proc expectMacroOrTemplateCall(c: PContext, n: PNode): PSym
proc semTemplateExpr(c: PContext, n: PNode, s: PSym, semCheck = true): PNode
proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym,
semCheck: bool = true): PNode
proc semDirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode
proc semWhen(c: PContext, n: PNode, semCheck: bool = true): PNode
proc IsOpImpl(c: PContext, n: PNode): PNode
proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym,
semCheck: bool = true): PNode
proc symFromType(t: PType, info: TLineInfo): PSym =
if t.sym != nil: return t.sym
result = newSym(skType, getIdent"AnonType", t.owner, info)
result.flags.incl sfAnon
result.typ = t
proc symNodeFromType(c: PContext, t: PType, info: TLineInfo): PNode =
result = newSymNode(symFromType(t, info), info)
result.typ = makeTypeDesc(c, t)
proc createEvalContext(c: PContext, mode: TEvalMode): PEvalContext =
result = newEvalContext(c.module, mode)
result.getType = proc (n: PNode): PNode =
var e = tryExpr(c, n)
if e == nil:
result = symNodeFromType(c, errorType(c), n.info)
elif e.typ == nil:
result = newSymNode(getSysSym"void")
else:
result = symNodeFromType(c, e.typ, n.info)
result.handleIsOperator = proc (n: PNode): PNode =
result = IsOpImpl(c, n)
proc evalConstExpr(c: PContext, module: PSym, e: PNode): PNode =
result = evalConstExprAux(c.createEvalContext(emConst), module, nil, e)
proc evalStaticExpr(c: PContext, module: PSym, e: PNode, prc: PSym): PNode =
result = evalConstExprAux(c.createEvalContext(emStatic), module, prc, e)
proc semConstExpr(c: PContext, n: PNode): PNode =
var e = semExprWithType(c, n)
@ -148,7 +176,7 @@ proc semConstExpr(c: PContext, n: PNode): PNode =
return n
result = getConstExpr(c.module, e)
if result == nil:
result = evalConstExpr(c.module, e)
result = evalConstExpr(c, c.module, e)
if result == nil or result.kind == nkEmpty:
if e.info != n.info:
pushInfoContext(n.info)
@ -161,16 +189,6 @@ proc semConstExpr(c: PContext, n: PNode): PNode =
include hlo, seminst, semcall
proc symFromType(t: PType, info: TLineInfo): PSym =
if t.sym != nil: return t.sym
result = newSym(skType, getIdent"AnonType", t.owner, info)
result.flags.incl sfAnon
result.typ = t
proc symNodeFromType(c: PContext, t: PType, info: TLineInfo): PNode =
result = newSymNode(symFromType(t, info), info)
result.typ = makeTypeDesc(c, t)
proc semAfterMacroCall(c: PContext, n: PNode, s: PSym): PNode =
inc(evalTemplateCounter)
if evalTemplateCounter > 100:
@ -205,15 +223,7 @@ proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym,
GlobalError(n.info, errRecursiveDependencyX, sym.name.s)
if c.evalContext == nil:
c.evalContext = newEvalContext(c.module, emStatic)
c.evalContext.getType = proc (n: PNode): PNode =
var e = tryExpr(c, n)
if e == nil:
result = symNodeFromType(c, errorType(c), n.info)
elif e.typ == nil:
result = newSymNode(getSysSym"void")
else:
result = symNodeFromType(c, e.typ, n.info)
c.evalContext = c.createEvalContext(emStatic)
result = evalMacroCall(c.evalContext, n, nOrig, sym)
if semCheck: result = semAfterMacroCall(c, result, sym)
@ -250,6 +260,7 @@ proc myOpen(module: PSym): PPassContext =
if c.p != nil: InternalError(module.info, "sem.myOpen")
c.semConstExpr = semConstExpr
c.semExpr = semExpr
c.semTryExpr = tryExpr
c.semOperand = semOperand
c.semConstBoolExpr = semConstBoolExpr
c.semOverloadedCall = semOverloadedCall

View file

@ -34,36 +34,35 @@ proc sameMethodDispatcher(a, b: PSym): bool =
proc determineType(c: PContext, s: PSym)
proc resolveOverloads(c: PContext, n, orig: PNode,
filter: TSymKinds): TCandidate =
var initialBinding: PNode
var f = n.sons[0]
if f.kind == nkBracketExpr:
# fill in the bindings:
initialBinding = f
f = f.sons[0]
else:
initialBinding = nil
var
o: TOverloadIter
alt, z: TCandidate
template best: expr = result
#Message(n.info, warnUser, renderTree(n))
var sym = initOverloadIter(o, c, f)
proc
pickBestCandidate(c: PContext, headSymbol: PNode,
n, orig: PNode,
initialBinding: PNode,
filter: TSymKinds,
best, alt: var TCandidate,
errors: var seq[string]) =
var o: TOverloadIter
var sym = initOverloadIter(o, c, headSymbol)
var symScope = o.lastOverloadScope
var z: TCandidate
if sym == nil: return
initCandidate(best, sym, initialBinding, symScope)
initCandidate(alt, sym, initialBinding, symScope)
best.state = csNoMatch
while sym != nil:
if sym.kind in filter:
determineType(c, sym)
initCandidate(z, sym, initialBinding, o.lastOverloadScope)
z.calleeSym = sym
matches(c, n, orig, z)
if errors != nil:
errors.safeAdd(getProcHeader(sym))
if z.errors != nil:
for err in z.errors:
errors[errors.len - 1].add("\n " & err)
if z.state == csMatch:
# little hack so that iterators are preferred over everything else:
if sym.kind == skIterator: inc(z.exactMatches, 200)
@ -74,17 +73,100 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
if cmp < 0: best = z # x is better than the best so far
elif cmp == 0: alt = z # x is as good as the best so far
else: nil
sym = nextOverloadIter(o, c, f)
sym = nextOverloadIter(o, c, headSymbol)
if best.state == csEmpty:
# no overloaded proc found
# do not generate an error yet; the semantic checking will check for
# an overloaded () operator
elif alt.state == csMatch and cmpCandidates(best, alt) == 0 and
not sameMethodDispatcher(best.calleeSym, alt.calleeSym):
if best.state != csMatch:
InternalError(n.info, "x.state is not csMatch")
#writeMatches(best)
proc NotFoundError*(c: PContext, n: PNode, errors: seq[string]) =
# Gives a detailed error message; this is separated from semOverloadedCall,
# as semOverlodedCall is already pretty slow (and we need this information
# only in case of an error).
if c.InCompilesContext > 0:
# fail fast:
GlobalError(n.info, errTypeMismatch, "")
var result = msgKindToString(errTypeMismatch)
add(result, describeArgs(c, n, 1 + ord(nfDelegate in n.flags)))
add(result, ')')
var candidates = ""
for err in errors:
add(candidates, err)
add(candidates, "\n")
if candidates != "":
add(result, "\n" & msgKindToString(errButExpected) & "\n" & candidates)
LocalError(n.Info, errGenerated, result)
proc gatherUsedSyms(c: PContext, usedSyms: var seq[PNode]) =
for scope in walkScopes(c.currentScope):
if scope.usingSyms != nil:
for s in scope.usingSyms: usedSyms.safeAdd(s)
proc resolveOverloads(c: PContext, n, orig: PNode,
filter: TSymKinds): TCandidate =
var initialBinding: PNode
var alt: TCandidate
var f = n.sons[0]
if f.kind == nkBracketExpr:
# fill in the bindings:
initialBinding = f
f = f.sons[0]
else:
initialBinding = nil
var errors: seq[string]
var usedSyms: seq[PNode]
template pickBest(headSymbol: expr) =
pickBestCandidate(c, headSymbol, n, orig, initialBinding,
filter, result, alt, errors)
gatherUsedSyms(c, usedSyms)
if usedSyms != nil:
var hiddenArg = if usedSyms.len > 1: newNode(nkClosedSymChoice, n.info, usedSyms)
else: usedSyms[0]
n.sons.insert(hiddenArg, 1)
orig.sons.insert(hiddenArg, 1)
pickBest(f)
if result.state != csMatch:
n.sons.delete(1)
orig.sons.delete(1)
else: return
pickBest(f)
let overloadsState = result.state
if overloadsState != csMatch:
if nfDelegate in n.flags:
InternalAssert f.kind == nkIdent
let calleeName = newStrNode(nkStrLit, f.ident.s)
calleeName.info = n.info
let callOp = newIdentNode(idDelegator, n.info)
n.sons[0..0] = [callOp, calleeName]
orig.sons[0..0] = [callOp, calleeName]
pickBest(callOp)
if overloadsState == csEmpty and result.state == csEmpty:
LocalError(n.info, errUndeclaredIdentifier, considerAcc(f).s)
return
elif result.state != csMatch:
if nfExprCall in n.flags:
LocalError(n.info, errExprXCannotBeCalled,
renderTree(n, {renderNoComments}))
else:
errors = @[]
pickBest(f)
NotFoundError(c, n, errors)
return
if alt.state == csMatch and cmpCandidates(result, alt) == 0 and
not sameMethodDispatcher(result.calleeSym, alt.calleeSym):
InternalAssert result.state == csMatch
#writeMatches(result)
#writeMatches(alt)
if c.inCompilesContext > 0:
# quick error message for performance of 'compiles' built-in:
@ -98,7 +180,7 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
add(args, ")")
LocalError(n.Info, errGenerated, msgKindToString(errAmbiguousCallXYZ) % [
getProcHeader(best.calleeSym), getProcHeader(alt.calleeSym),
getProcHeader(result.calleeSym), getProcHeader(alt.calleeSym),
args])
@ -155,6 +237,7 @@ proc semOverloadedCall(c: PContext, n, nOrig: PNode,
filter: TSymKinds): PNode =
var r = resolveOverloads(c, n, nOrig, filter)
if r.state == csMatch: result = semResolvedCall(c, n, r)
# else: result = errorNode(c, n)
proc explicitGenericInstError(n: PNode): PNode =
LocalError(n.info, errCannotInstantiateX, renderTree(n))

View file

@ -72,6 +72,7 @@ type
libs*: TLinkedList # all libs used by this module
semConstExpr*: proc (c: PContext, n: PNode): PNode {.nimcall.} # for the pragmas
semExpr*: proc (c: PContext, n: PNode, flags: TExprFlags = {}): PNode {.nimcall.}
semTryExpr*: proc (c: PContext, n: PNode, flags: TExprFlags = {}): PNode {.nimcall.}
semOperand*: proc (c: PContext, n: PNode, flags: TExprFlags = {}): PNode {.nimcall.}
semConstBoolExpr*: proc (c: PContext, n: PNode): PNode {.nimcall.} # XXX bite the bullet
semOverloadedCall*: proc (c: PContext, n, nOrig: PNode,
@ -204,6 +205,11 @@ proc makeTypeDesc*(c: PContext, typ: PType): PType =
result = newTypeS(tyTypeDesc, c)
result.addSonSkipIntLit(typ.AssertNotNil)
proc makeTypeSymNode*(c: PContext, typ: PType, info: TLineInfo): PNode =
let typedesc = makeTypeDesc(c, typ)
let sym = newSym(skType, idAnon, getCurrOwner(), info).linkTo(typedesc)
return newSymNode(sym, info)
proc newTypeS(kind: TTypeKind, c: PContext): PType =
result = newType(kind, getCurrOwner())

View file

@ -248,7 +248,11 @@ proc semLowHigh(c: PContext, n: PNode, m: TMagic): PNode =
of tyInt..tyInt64, tyChar, tyBool, tyEnum, tyUInt8, tyUInt16, tyUInt32:
# do not skip the range!
n.typ = n.sons[1].typ.skipTypes(abstractVar)
else: LocalError(n.info, errInvalidArgForX, opToStr[m])
of tyGenericParam:
# leave it for now, it will be resolved in semtypinst
n.typ = getSysType(tyInt)
else:
LocalError(n.info, errInvalidArgForX, opToStr[m])
result = n
proc semSizeof(c: PContext, n: PNode): PNode =
@ -295,6 +299,39 @@ proc semOf(c: PContext, n: PNode): PNode =
n.typ = getSysType(tyBool)
result = n
proc IsOpImpl(c: PContext, n: PNode): PNode =
InternalAssert n.sonsLen == 3 and
n[1].kind == nkSym and n[1].sym.kind == skType and
n[2].kind in {nkStrLit..nkTripleStrLit, nkType}
let t1 = n[1].sym.typ.skipTypes({tyTypeDesc})
if n[2].kind in {nkStrLit..nkTripleStrLit}:
case n[2].strVal.normalize
of "closure":
let t = skipTypes(t1, abstractRange)
result = newIntNode(nkIntLit, ord(t.kind == tyProc and
t.callConv == ccClosure and
tfIterator notin t.flags))
of "iterator":
let t = skipTypes(t1, abstractRange)
result = newIntNode(nkIntLit, ord(t.kind == tyProc and
t.callConv == ccClosure and
tfIterator in t.flags))
else:
var match: bool
let t2 = n[2].typ
if t2.kind == tyTypeClass:
var m: TCandidate
InitCandidate(m, t2)
match = matchUserTypeClass(c, m, emptyNode, t2, t1) != nil
else:
match = sameType(t1, t2)
result = newIntNode(nkIntLit, ord(match))
result.typ = n.typ
proc semIs(c: PContext, n: PNode): PNode =
if sonsLen(n) != 3:
LocalError(n.info, errXExpectsTwoArguments, "is")
@ -303,21 +340,21 @@ proc semIs(c: PContext, n: PNode): PNode =
n.typ = getSysType(tyBool)
n.sons[1] = semExprWithType(c, n[1], {efDetermineType})
if n[1].typ.kind != tyTypeDesc:
LocalError(n[0].info, errTypeExpected)
if n[2].kind notin {nkStrLit..nkTripleStrLit}:
let t2 = semTypeNode(c, n[2], nil)
n.sons[2] = newNodeIT(nkType, n[2].info, t2)
if n[1].typ.sonsLen == 0:
if n[1].typ.kind != tyTypeDesc:
n.sons[1] = makeTypeSymNode(c, n[1].typ, n[1].info)
elif n[1].typ.sonsLen == 0:
# this is a typedesc variable, leave for evals
return
else:
let t1 = n[1].typ.sons[0]
# BUGFIX: don't evaluate this too early: ``T is void``
if not containsGenericType(t1): result = evalIsOp(n)
let t1 = n[1].typ.sons[0]
# BUGFIX: don't evaluate this too early: ``T is void``
if not containsGenericType(t1): result = IsOpImpl(c, n)
proc semOpAux(c: PContext, n: PNode) =
const flags = {efDetermineType}
for i in countup(1, n.sonsLen-1):
@ -594,18 +631,18 @@ proc evalAtCompileTime(c: PContext, n: PNode): PNode =
call.add(a)
#echo "NOW evaluating at compile time: ", call.renderTree
if sfCompileTime in callee.flags:
result = evalStaticExpr(c.module, call, c.p.owner)
result = evalStaticExpr(c, c.module, call, c.p.owner)
if result.isNil:
LocalError(n.info, errCannotInterpretNodeX, renderTree(call))
else:
result = evalConstExpr(c.module, call)
result = evalConstExpr(c, c.module, call)
if result.isNil: result = n
#if result != n:
# echo "SUCCESS evaluated at compile time: ", call.renderTree
proc semStaticExpr(c: PContext, n: PNode): PNode =
let a = semExpr(c, n.sons[0])
result = evalStaticExpr(c.module, a, c.p.owner)
result = evalStaticExpr(c, c.module, a, c.p.owner)
if result.isNil:
LocalError(n.info, errCannotInterpretNodeX, renderTree(n))
result = emptyNode
@ -649,7 +686,7 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
result = n.sons[0]
result.kind = nkCall
for i in countup(1, sonsLen(n) - 1): addSon(result, n.sons[i])
return semExpr(c, result, flags)
return semDirectOp(c, result, flags)
else:
n.sons[0] = semExpr(c, n.sons[0])
let nOrig = n.copyTree
@ -699,14 +736,13 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
# Now that nkSym does not imply an iteration over the proc/iterator space,
# the old ``prc`` (which is likely an nkIdent) has to be restored:
if result == nil:
# XXX: hmm, what kind of symbols will end up here?
# do we really need to try the overload resolution?
n.sons[0] = prc
nOrig.sons[0] = prc
n.flags.incl nfExprCall
result = semOverloadedCallAnalyseEffects(c, n, nOrig, flags)
if result == nil:
if c.inCompilesContext > 0 or gErrorCounter == 0:
LocalError(n.info, errExprXCannotBeCalled,
renderTree(n, {renderNoComments}))
return errorNode(c, n)
if result == nil: return errorNode(c, n)
#result = afterCallActions(c, result, nOrig, flags)
fixAbstractType(c, result)
analyseIfAddressTakenInCall(c, result)
@ -734,12 +770,7 @@ proc semDirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
let nOrig = n.copyTree
#semLazyOpAux(c, n)
result = semOverloadedCallAnalyseEffects(c, n, nOrig, flags)
if result == nil:
result = overloadedCallOpr(c, n)
if result == nil:
NotFoundError(c, n)
return errorNode(c, n)
result = afterCallActions(c, result, nOrig, flags)
if result != nil: result = afterCallActions(c, result, nOrig, flags)
proc buildStringify(c: PContext, arg: PNode): PNode =
if arg.typ != nil and
@ -946,20 +977,11 @@ proc dotTransformation(c: PContext, n: PNode): PNode =
addSon(result, copyTree(n[0]))
else:
var i = considerAcc(n.sons[1])
var f = searchInScopes(c, i)
# if f != nil and f.kind == skStub: loadStub(f)
# ``loadStub`` is not correct here as we don't care for ``f`` really
if f != nil:
# BUGFIX: do not check for (f.kind in {skProc, skMethod, skIterator}) here
# This special node kind is to merge with the call handler in `semExpr`.
result = newNodeI(nkDotCall, n.info)
addSon(result, newIdentNode(i, n[1].info))
addSon(result, copyTree(n[0]))
else:
if not ContainsOrIncl(c.UnknownIdents, i.id):
LocalError(n.Info, errUndeclaredFieldX, i.s)
result = errorNode(c, n)
result = newNodeI(nkDotCall, n.info)
result.flags.incl nfDelegate
addSon(result, newIdentNode(i, n[1].info))
addSon(result, copyTree(n[0]))
proc semFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
# this is difficult, because the '.' is used in many different contexts
# in Nimrod. We first allow types in the semantic checking.
@ -1307,6 +1329,22 @@ proc newAnonSym(kind: TSymKind, info: TLineInfo,
result = newSym(kind, idAnon, owner, info)
result.flags = {sfGenSym}
proc semUsing(c: PContext, n: PNode): PNode =
result = newNodeI(nkEmpty, n.info)
for e in n.sons:
let usedSym = semExpr(c, e)
if usedSym.kind == nkSym:
case usedSym.sym.kind
of skLocalVars + {skConst}:
c.currentScope.usingSyms.safeAdd(usedSym)
continue
of skProcKinds:
addDeclAt(c.currentScope, usedSym.sym)
continue
else: nil
LocalError(e.info, errUsingNoSymbol, e.renderTree)
proc semExpandToAst(c: PContext, n: PNode): PNode =
var macroCall = n[1]
var expandedSym = expectMacroOrTemplateCall(c, macroCall)
@ -1834,7 +1872,8 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
of nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand, nkCallStrLit:
# check if it is an expression macro:
checkMinSonsLen(n, 1)
var s = qualifiedLookup(c, n.sons[0], {checkUndeclared})
let mode = if nfDelegate in n.flags: {} else: {checkUndeclared}
var s = qualifiedLookup(c, n.sons[0], mode)
if s != nil:
case s.kind
of skMacro:
@ -1868,6 +1907,8 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
elif isSymChoice(n.sons[0]) or n[0].kind == nkBracketExpr and
isSymChoice(n[0][0]):
result = semDirectOp(c, n, flags)
elif nfDelegate in n.flags:
result = semDirectOp(c, n, flags)
else:
result = semIndirectOp(c, n, flags)
of nkWhen:
@ -1943,6 +1984,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
of nkForStmt, nkParForStmt: result = semFor(c, n)
of nkCaseStmt: result = semCase(c, n)
of nkReturnStmt: result = semReturn(c, n)
of nkUsingStmt: result = semUsing(c, n)
of nkAsmStmt: result = semAsm(c, n)
of nkYieldStmt: result = semYield(c, n)
of nkPragma: pragma(c, c.p.owner, n, stmtPragmas)
@ -1974,4 +2016,4 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
else:
LocalError(n.info, errInvalidExpressionX,
renderTree(n, {renderNoComments}))
incl(result.flags, nfSem)
if result != nil: incl(result.flags, nfSem)

View file

@ -113,6 +113,7 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode,
result.typ = getSysType(tyString)
of mInstantiationInfo: result = semInstantiationInfo(c, n)
of mOrd: result = semOrd(c, n)
of mHigh: result = semLowHigh(c, n, mHigh)
of mShallowCopy: result = semShallowCopy(c, n, flags)
of mNBindSym: result = semBindSym(c, n)
of mLocals: result = semLocals(c, n)

View file

@ -838,7 +838,14 @@ proc semProcAnnotation(c: PContext, prc: PNode): PNode =
var it = n.sons[i]
var key = if it.kind == nkExprColonExpr: it.sons[0] else: it
let m = lookupMacro(c, key)
if m == nil: continue
if m == nil:
if key.kind == nkIdent and key.ident.id == ord(wDelegator):
if considerAcc(prc.sons[namePos]).s == "()":
prc.sons[namePos] = newIdentNode(idDelegator, prc.info)
prc.sons[pragmasPos] = copyExcept(n, i)
else:
LocalError(prc.info, errOnlyACallOpCanBeDelegator)
continue
# we transform ``proc p {.m, rest.}`` into ``m(do: proc p {.rest.})`` and
# let the semantic checker deal with it:
var x = newNodeI(nkCall, n.info)
@ -1147,7 +1154,7 @@ proc semPragmaBlock(c: PContext, n: PNode): PNode =
proc semStaticStmt(c: PContext, n: PNode): PNode =
let a = semStmt(c, n.sons[0])
result = evalStaticExpr(c.module, a, c.p.owner)
result = evalStaticExpr(c, c.module, a, c.p.owner)
if result.isNil:
LocalError(n.info, errCannotInterpretNodeX, renderTree(n))
result = emptyNode

View file

@ -608,7 +608,7 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
if genericParams.sons[i].sym.name.id == finalTypId.id:
return genericParams.sons[i].typ
var s = newSym(skType, finalTypId, getCurrOwner(), info)
var s = newSym(skType, finalTypId, typeClass.sym, info)
if typId == nil: s.flags.incl(sfAnon)
s.linkTo(typeClass)
s.position = genericParams.len
@ -871,6 +871,21 @@ proc freshType(res, prev: PType): PType {.inline.} =
else:
result = res
proc semTypeClass(c: PContext, n: PNode, prev: PType): PType =
# if n.sonsLen == 0: return newConstraint(c, tyTypeClass)
result = newOrPrevType(tyTypeClass, prev, c)
result.testeeName = considerAcc(n[0])
result.n = n[3]
let
pragmas = n[1]
inherited = n[2]
if inherited.kind != nkEmpty:
for n in inherited.sons:
let typ = semTypeNode(c, n, nil)
result.sons.safeAdd(typ)
proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
result = nil
if gCmd == cmdIdeTools: suggestExpr(c, n)
@ -973,6 +988,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
result = newOrPrevType(tyError, prev, c)
of nkObjectTy: result = semObjectNode(c, n, prev)
of nkTupleTy: result = semTuple(c, n, prev)
of nkTypeClassTy: result = semTypeClass(c, n, prev)
of nkRefTy: result = semAnyRef(c, n, tyRef, prev)
of nkPtrTy: result = semAnyRef(c, n, tyPtr, prev)
of nkVarTy: result = semVarType(c, n, prev)

View file

@ -148,12 +148,13 @@ proc handleGenericInvokation(cl: var TReplTypeVars, t: PType): PType =
if result != nil: return
for i in countup(1, sonsLen(t) - 1):
var x = t.sons[i]
if x.kind == tyGenericParam:
if x.kind == tyGenericParam:
x = lookupTypeVar(cl, x)
if header == nil: header = copyType(t, t.owner, false)
header.sons[i] = x
propagateToOwner(header, x)
#idTablePut(cl.typeMap, body.sons[i-1], x)
#idTablePut(cl.typeMap, body.sons[i-1], x)
if header != nil:
# search again after first pass:
result = searchInstTypes(header)
@ -200,6 +201,9 @@ proc ReplaceTypeVarsT*(cl: var TReplTypeVars, t: PType): PType =
result = lookupTypeVar(cl, t)
if result.kind == tyGenericInvokation:
result = handleGenericInvokation(cl, result)
of tyExpr:
if t.sym != nil and t.sym.kind == skGenericParam:
result = lookupTypeVar(cl, t)
of tyGenericInvokation:
result = handleGenericInvokation(cl, t)
of tyGenericBody:

View file

@ -40,7 +40,9 @@ type
# be instantiated
typedescMatched: bool
inheritancePenalty: int # to prefer closest father object type
errors*: seq[string] # additional clarifications to be displayed to the
# user if overload resolution fails
TTypeRelation* = enum # order is important!
isNone, isConvertible,
isIntConv,
@ -200,28 +202,6 @@ proc describeArgs*(c: PContext, n: PNode, startIdx = 1): string =
add(result, argTypeToString(arg))
if i != sonsLen(n) - 1: add(result, ", ")
proc NotFoundError*(c: PContext, n: PNode) =
# Gives a detailed error message; this is separated from semOverloadedCall,
# as semOverlodedCall is already pretty slow (and we need this information
# only in case of an error).
if c.InCompilesContext > 0:
# fail fast:
GlobalError(n.info, errTypeMismatch, "")
var result = msgKindToString(errTypeMismatch)
add(result, describeArgs(c, n))
add(result, ')')
var candidates = ""
var o: TOverloadIter
var sym = initOverloadIter(o, c, n.sons[0])
while sym != nil:
if sym.kind in RoutineKinds:
add(candidates, getProcHeader(sym))
add(candidates, "\n")
sym = nextOverloadIter(o, c, n.sons[0])
if candidates != "":
add(result, "\n" & msgKindToString(errButExpected) & "\n" & candidates)
LocalError(n.Info, errGenerated, result)
proc typeRel(c: var TCandidate, f, a: PType): TTypeRelation
proc concreteType(c: TCandidate, t: PType): PType =
case t.kind
@ -643,7 +623,10 @@ proc typeRel(c: var TCandidate, f, a: PType): TTypeRelation =
else:
result = isNone
else:
result = matchTypeClass(c, f, a)
if a.kind == tyTypeClass:
result = isGeneric
else:
result = matchTypeClass(c, f, a)
if result == isGeneric:
var concrete = concreteType(c, a)
@ -754,35 +737,93 @@ proc localConvMatch(c: PContext, m: var TCandidate, f, a: PType,
result.typ = getInstantiatedType(c, arg, m, base(f))
m.baseTypeMatch = true
proc matchUserTypeClass*(c: PContext, m: var TCandidate,
arg: PNode, f, a: PType): PNode =
if f.n == nil:
let r = typeRel(m, f, a)
return if r == isGeneric: arg else: nil
var prev = PType(idTableGet(m.bindings, f))
if prev != nil:
if sameType(prev, a): return arg
else: return nil
# pushInfoContext(arg.info)
openScope(c)
var testee = newSym(skParam, f.testeeName, f.sym, f.sym.info)
testee.typ = a
addDecl(c, testee)
for stmt in f.n:
var e = c.semTryExpr(c, copyTree(stmt))
if e == nil:
let expStr = renderTree(stmt, {renderNoComments})
m.errors.safeAdd("can't compile " & expStr & " for " & a.typeToString)
return nil
case e.kind
of nkReturnStmt:
nil
of nkTypeSection: nil
of nkConstDef: nil
else:
if e.typ.kind == tyBool:
let verdict = c.semConstExpr(c, e)
if verdict.intVal == 0:
let expStr = renderTree(stmt, {renderNoComments})
m.errors.safeAdd(expStr & " doesn't hold for " & a.typeToString)
return nil
closeScope(c)
result = arg
put(m.bindings, f, a)
proc ParamTypesMatchAux(c: PContext, m: var TCandidate, f, a: PType,
arg, argOrig: PNode): PNode =
argSemantized, argOrig: PNode): PNode =
var arg = argSemantized
var r: TTypeRelation
let fMaybeExpr = f.skipTypes({tyDistinct})
if fMaybeExpr.kind == tyExpr:
case fMaybeExpr.kind
of tyExpr:
if fMaybeExpr.sonsLen == 0:
r = isGeneric
else:
let match = matchTypeClass(m, fMaybeExpr, a)
if match != isGeneric: r = isNone
if a.kind == tyExpr:
InternalAssert a.len > 0
r = typeRel(m, f.lastSon, a.lastSon)
else:
# XXX: Ideally, this should happen much earlier somewhere near
# semOpAux, but to do that, we need to be able to query the
# overload set to determine whether compile-time value is expected
# for the param before entering the full-blown sigmatch algorithm.
# This is related to the immediate pragma since querying the
# overload set could help there too.
var evaluated = c.semConstExpr(c, arg)
if evaluated != nil:
r = isGeneric
arg.typ = newTypeS(tyExpr, c)
arg.typ.sons = @[evaluated.typ]
arg.typ.n = evaluated
let match = matchTypeClass(m, fMaybeExpr, a)
if match != isGeneric: r = isNone
else:
# XXX: Ideally, this should happen much earlier somewhere near
# semOpAux, but to do that, we need to be able to query the
# overload set to determine whether compile-time value is expected
# for the param before entering the full-blown sigmatch algorithm.
# This is related to the immediate pragma since querying the
# overload set could help there too.
var evaluated = c.semConstExpr(c, arg)
if evaluated != nil:
r = isGeneric
arg.typ = newTypeS(tyExpr, c)
arg.typ.sons = @[evaluated.typ]
arg.typ.n = evaluated
if r == isGeneric:
put(m.bindings, f, arg.typ)
of tyTypeClass:
if fMaybeExpr.n != nil:
let match = matchUserTypeClass(c, m, arg, fMaybeExpr, a)
if match != nil:
r = isGeneric
arg = match
else:
r = isNone
else:
r = typeRel(m, f, a)
else:
r = typeRel(m, f, a)
case r
of isConvertible:
inc(m.convMatches)

View file

@ -445,6 +445,7 @@ proc TypeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
if t.len == 0: result = "typedesc"
else: result = "typedesc[" & constraintsToStr(t) & "]"
of tyTypeClass:
if t.n != nil: return t.sym.owner.name.s
case t.len
of 0: result = "typeclass[]"
of 1: result = "typeclass[" & consToStr(t.sons[0]) & "]"

View file

@ -28,7 +28,7 @@ type
wElif, wElse, wEnd, wEnum, wExcept, wExport,
wFinally, wFor, wFrom, wGeneric, wIf, wImport, wIn,
wInclude, wInterface, wIs, wIsnot, wIterator, wLambda, wLet,
wMacro, wMethod, wMixin, wMod, wNil,
wMacro, wMethod, wMixin, wUsing, wMod, wNil,
wNot, wNotin, wObject, wOf, wOr, wOut, wProc, wPtr, wRaise, wRef, wReturn,
wShared, wShl, wShr, wStatic, wTemplate, wTry, wTuple, wType, wVar,
wWhen, wWhile, wWith, wWithout, wXor, wYield,
@ -39,7 +39,8 @@ type
wDestroy,
wImmediate, wDestructor, wImportCpp, wImportObjC,
wImmediate, wDestructor, wDelegator,
wImportCpp, wImportObjC,
wImportCompilerProc,
wImportc, wExportc, wIncompleteStruct, wRequiresInit,
wAlign, wNodecl, wPure, wSideeffect, wHeader,
@ -71,7 +72,7 @@ type
wPrivate, wProtected, wPublic, wRegister, wReinterpret_cast,
wShort, wSigned, wSizeof, wStatic_cast, wStruct, wSwitch,
wThis, wThrow, wTrue, wTypedef, wTypeid, wTypename,
wUnion, wUnsigned, wUsing, wVirtual, wVoid, wVolatile, wWchar_t,
wUnion, wUnsigned, wVirtual, wVoid, wVolatile, wWchar_t,
wAlignas, wAlignof, wConstexpr, wDecltype, wNullptr, wNoexcept,
wThread_local, wStatic_assert, wChar16_t, wChar32_t,
@ -94,7 +95,7 @@ const
cppNimSharedKeywords* = {
wAsm, wBreak, wCase, wConst, wContinue, wDo, wElse, wEnum, wExport,
wFor, wIf, wReturn, wStatic, wTemplate, wTry, wWhile}
wFor, wIf, wReturn, wStatic, wTemplate, wTry, wWhile, wUsing }
specialWords*: array[low(TSpecialWord)..high(TSpecialWord), string] = ["",
@ -106,7 +107,7 @@ const
"finally", "for", "from", "generic", "if",
"import", "in", "include", "interface", "is", "isnot", "iterator",
"lambda", "let",
"macro", "method", "mixin", "mod", "nil", "not", "notin",
"macro", "method", "mixin", "using", "mod", "nil", "not", "notin",
"object", "of", "or",
"out", "proc", "ptr", "raise", "ref", "return",
"shared", "shl", "shr", "static",
@ -120,7 +121,8 @@ const
"destroy",
"immediate", "destructor", "importcpp", "importobjc",
"immediate", "destructor", "delegator",
"importcpp", "importobjc",
"importcompilerproc", "importc", "exportc", "incompletestruct",
"requiresinit", "align", "nodecl", "pure", "sideeffect",
"header", "nosideeffect", "noreturn", "merge", "lib", "dynlib",
@ -152,7 +154,7 @@ const
"private", "protected", "public", "register", "reinterpret_cast",
"short", "signed", "sizeof", "static_cast", "struct", "switch",
"this", "throw", "true", "typedef", "typeid",
"typename", "union", "unsigned", "using", "virtual", "void", "volatile",
"typename", "union", "unsigned", "virtual", "void", "volatile",
"wchar_t",
"alignas", "alignof", "constexpr", "decltype", "nullptr", "noexcept",