diff options
author | Zahary Karadjov <zahary@gmail.com> | 2012-04-06 05:02:48 +0300 |
---|---|---|
committer | Zahary Karadjov <zahary@gmail.com> | 2012-04-06 13:46:31 +0300 |
commit | efb53233cb3434b94b28060f0a642c51049cb09d (patch) | |
tree | 00f51557f8d12355402ede92e27c497d9dc13c53 | |
parent | 98b7bdaa5050a9b3709e8a27fd44477a2a28e4f7 (diff) | |
download | Nim-efb53233cb3434b94b28060f0a642c51049cb09d.tar.gz |
the foundations of a type traits module; better error messages for expr, typedesc and typeclasses params
-rwxr-xr-x | compiler/ast.nim | 8 | ||||
-rwxr-xr-x | compiler/evals.nim | 20 | ||||
-rwxr-xr-x | compiler/msgs.nim | 3 | ||||
-rwxr-xr-x | compiler/semexprs.nim | 10 | ||||
-rwxr-xr-x | compiler/semfold.nim | 2 | ||||
-rw-r--r-- | compiler/semmagic.nim | 11 | ||||
-rwxr-xr-x | compiler/semtypes.nim | 6 | ||||
-rwxr-xr-x | compiler/types.nim | 17 |
8 files changed, 65 insertions, 12 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim index 972ba7924..c6a2b32e7 100755 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -243,8 +243,13 @@ const sfFakeConst* = sfDeadCodeElim # const cannot be put into a data section sfDispatcher* = sfDeadCodeElim # copied method symbol is the dispatcher sfNoInit* = sfMainModule # don't generate code to init the variable + sfImmediate* = sfDeadCodeElim # macro or template is immediately expanded # without considering any possible overloads + + sfAnon* = sfCompilerProc # symbol name that was generated by the compiler + # the compiler will avoid printing such names + # in user messages. const # getting ready for the future expr/stmt merge @@ -358,7 +363,8 @@ const type TMagic* = enum # symbols that require compiler magic: - mNone, mDefined, mDefinedInScope, mLow, mHigh, mSizeOf, mIs, mOf, + mNone, + mDefined, mDefinedInScope, mLow, mHigh, mSizeOf, mTypeTrait, mIs, mOf, mEcho, mShallowCopy, mSlurp, mParseExprToAst, mParseStmtToAst, mExpandToAst, mUnaryLt, mSucc, diff --git a/compiler/evals.nim b/compiler/evals.nim index 84d3023a5..92726ae31 100755 --- a/compiler/evals.nim +++ b/compiler/evals.nim @@ -490,7 +490,7 @@ proc evalSwap(c: PEvalContext, n: PNode): PNode = proc evalSym(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode = var s = n.sym case s.kind - of skProc, skConverter, skMacro: + of skProc, skConverter, skMacro, skType: result = n #result = s.getBody of skVar, skLet, skForVar, skTemp, skResult: @@ -891,7 +891,24 @@ proc evalTemplate*(n: PNode, sym: PSym): PNode = result = evalTemplateAux(sym.getBody, args, sym) dec(evalTemplateCounter) + +proc evalTypeTrait*(n: PNode, context: PSym): PNode = + ## XXX: This should be pretty much guaranteed to be true + # by the type traits procs' signitures, but until the + # code is more mature it doesn't hurt to be extra safe + internalAssert n.sons.len >= 2 and + n.sons[1].sym.typ.kind == tyTypeDesc + let typ = n.sons[1].sym.typ.skipTypes({tyTypeDesc}) + case n.sons[0].sym.name.s + of "name": + result = newStrNode(nkStrLit, typ.typeToString) + result.typ = newType(tyString, context) + result.info = n.info + + else: + internalAssert false + proc evalExpandToAst(c: PEvalContext, original: PNode): PNode = var n = original.copyTree @@ -941,6 +958,7 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode = of mParseExprToAst: result = evalParseExpr(c, n) of mParseStmtToAst: result = evalParseStmt(c, n) of mExpandToAst: result = evalExpandToAst(c, n) + of mTypeTrait: result = evalTypeTrait(n, c.module) of mNLen: result = evalAux(c, n.sons[1], {efLValue}) if isSpecial(result): return diff --git a/compiler/msgs.nim b/compiler/msgs.nim index df9064ab2..87f5e5650 100755 --- a/compiler/msgs.nim +++ b/compiler/msgs.nim @@ -667,3 +667,6 @@ template AssertNotNil*(e: expr): expr = if(e == nil): InternalError($InstantiationInfo()) e +template InternalAssert*(e: bool): stmt = + if not e: InternalError($InstantiationInfo()) + diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 8ab4c5f63..bca27a43d 100755 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -1314,11 +1314,11 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode = Message(n.info, warnDeprecated, "bind") result = semExpr(c, n.sons[0], flags) of nkTypeOfExpr: - var typ = semTypeNode(c, n, nil) - if typ.sym == nil: - typ = copyType(typ, typ.owner, true) - typ.linkTo(newSym(skType, getIdent"typedesc", typ.owner)) - result = newSymNode(typ.sym, n.info) + var typ = semTypeNode(c, n, nil).skipTypes({tyTypeDesc}) + typ = makeTypedesc(c, typ) + var sym = newSym(skType, getIdent"TypeOfExpr", typ.owner).linkTo(typ) + sym.flags.incl(sfAnon) + result = newSymNode(sym, n.info) of nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand, nkCallStrLit: # check if it is an expression macro: checkMinSonsLen(n, 1) diff --git a/compiler/semfold.nim b/compiler/semfold.nim index 956667091..82ee7de13 100755 --- a/compiler/semfold.nim +++ b/compiler/semfold.nim @@ -206,7 +206,7 @@ proc evalOp(m: TMagic, n, a, b, c: PNode): PNode = of mNewString, mNewStringOfCap, mExit, mInc, ast.mDec, mEcho, mSwap, mAppendStrCh, mAppendStrStr, mAppendSeqElem, mSetLengthStr, mSetLengthSeq, - mParseExprToAst, mParseStmtToAst, mExpandToAst, + mParseExprToAst, mParseStmtToAst, mExpandToAst, mTypeTrait, mNLen..mNError, mEqRef: nil of mRand: diff --git a/compiler/semmagic.nim b/compiler/semmagic.nim index 4f120e2ab..e6861f2e4 100644 --- a/compiler/semmagic.nim +++ b/compiler/semmagic.nim @@ -8,6 +8,7 @@ # # This include file implements the semantic checking for magics. +# included from sem.nim proc semIsPartOf(c: PContext, n: PNode, flags: TExprFlags): PNode = var r = isPartOf(n[1], n[2]) @@ -43,11 +44,21 @@ proc semInstantiationInfo(c: PContext, n: PNode): PNode = result.add(filename) result.add(line) +proc semTypeTraits(c: PContext, n: PNode): PNode = + checkMinSonsLen(n, 2) + internalAssert n.sons[1].kind == nkSym + if n.sons[1].sym.kind == skType: + result = evalTypeTrait(n, GetCurrOwner()) + else: + # pass unmodified to evals + result = n + proc magicsAfterOverloadResolution(c: PContext, n: PNode, flags: TExprFlags): PNode = case n[0].sym.magic of mSlurp: result = semSlurp(c, n, flags) of mIsPartOf: result = semIsPartOf(c, n, flags) + of mTypeTrait: result = semTypeTraits(c, n) of mAstToStr: result = newStrNodeT(renderTree(n[1], {renderNoComments}), n) result.typ = getSysType(tyString) diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index 38cf19406..8479810d2 100755 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -583,8 +583,8 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode, break addImplicitGeneric var s = newSym(skType, paramTypId, getCurrOwner()) - s.typ = typeClass - s.typ.sym = s + s.flags.incl(sfAnon) + s.linkTo(typeClass) s.position = genericParams.len genericParams.addSon(newSymNode(s)) endingType = typeClass @@ -693,7 +693,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType = of nkTypeOfExpr: # for ``type(countup(1,3))``, see ``tests/ttoseq``. checkSonsLen(n, 1) - result = semExprWithType(c, n.sons[0], {efInTypeof}).typ + result = semExprWithType(c, n.sons[0], {efInTypeof, efAllowType}).typ of nkPar: if sonsLen(n) == 1: result = semTypeNode(c, n.sons[0], prev) else: GlobalError(n.info, errTypeExpected) diff --git a/compiler/types.nim b/compiler/types.nim index 3f7c2c820..15390bed7 100755 --- a/compiler/types.nim +++ b/compiler/types.nim @@ -372,6 +372,13 @@ proc rangeToStr(n: PNode): string = assert(n.kind == nkRange) result = ValueToString(n.sons[0]) & ".." & ValueToString(n.sons[1]) +proc constraintsToStr(t: PType): string = + let sep = if tfAny in t.flags: " or " else: " and " + result = "" + for i in countup(0, t.sons.len - 1): + if i > 0: result.add(sep) + result.add(t.sons[i].typeToString) + proc TypeToString(typ: PType, prefer: TPreferedDesc = preferName): string = const typeToStr: array[TTypeKind, string] = ["None", "bool", "Char", "empty", @@ -387,7 +394,7 @@ proc TypeToString(typ: PType, prefer: TPreferedDesc = preferName): string = var t = typ result = "" if t == nil: return - if prefer == preferName and t.sym != nil: + if prefer == preferName and t.sym != nil and sfAnon notin t.sym.flags: return t.sym.Name.s case t.Kind of tyGenericBody, tyGenericInst, tyGenericInvokation: @@ -396,6 +403,14 @@ proc TypeToString(typ: PType, prefer: TPreferedDesc = preferName): string = if i > 1: add(result, ", ") add(result, typeToString(t.sons[i])) add(result, ']') + of tyTypeDesc: + if t.sons.len == 0: result = "typedesc" + else: result = "typedesc{" & constraintsToStr(t) & "}" + of tyTypeClass: + result = constraintsToStr(t) + of tyExpr: + if t.sons.len == 0: result = "expr" + else: result = "expr{" & constraintsToStr(t) & "}" of tyArray: if t.sons[0].kind == tyRange: result = "array[" & rangeToStr(t.sons[0].n) & ", " & |