From e879da5791f66f8c7220885682ed623e7dd0daea Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Sun, 24 Sep 2017 11:21:52 +0200 Subject: [PATCH] some work to make 'opt' a first class type --- compiler/ast.nim | 12 ++----- compiler/canonicalizer.nim | 2 +- compiler/ccgutils.nim | 4 +-- compiler/jsgen.nim | 10 +++--- compiler/semasgn.nim | 4 +-- compiler/semexprs.nim | 10 ++---- compiler/semstmts.nim | 2 +- compiler/semtypes.nim | 2 ++ compiler/sighashes.nim | 2 +- compiler/sigmatch.nim | 2 +- compiler/types.nim | 68 ++++++++++++++++---------------------- compiler/vmdeps.nim | 3 +- lib/core/macros.nim | 2 +- 13 files changed, 52 insertions(+), 71 deletions(-) diff --git a/compiler/ast.nim b/compiler/ast.nim index 79e1105e13..8237c161eb 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -404,14 +404,8 @@ type # instantiation and prior to this it has the potential to # be any type. - tyFieldAccessor - # Expressions such as Type.field (valid in contexts such - # as the `is` operator and magics like `high` and `low`). - # Could be lifted to a single argument proc returning the - # field value. - # sons[0]: type of containing object or tuple - # sons[1]: field type - # .n: nkDotExpr storing the field name + tyOpt + # Builtin optional type tyVoid # now different from tyEmpty, hurray! @@ -624,7 +618,7 @@ type mSwap, mIsNil, mArrToSeq, mCopyStr, mCopyStrLast, mNewString, mNewStringOfCap, mParseBiggestFloat, mReset, - mArray, mOpenArray, mRange, mSet, mSeq, mVarargs, + mArray, mOpenArray, mRange, mSet, mSeq, mOpt, mVarargs, mRef, mPtr, mVar, mDistinct, mVoid, mTuple, mOrdinal, mInt, mInt8, mInt16, mInt32, mInt64, diff --git a/compiler/canonicalizer.nim b/compiler/canonicalizer.nim index d17d928c85..6972f5acfa 100644 --- a/compiler/canonicalizer.nim +++ b/compiler/canonicalizer.nim @@ -130,7 +130,7 @@ proc hashType(c: var MD5Context, t: PType) = c.hashSym body.sym for i in countup(1, sonsLen(t) - 2): c.hashType t.sons[i] - of tyFromExpr, tyFieldAccessor: + of tyFromExpr: c.hashTree(t.n) of tyArray: c.hashTree(t.sons[0].n) diff --git a/compiler/ccgutils.nim b/compiler/ccgutils.nim index 6a7aa89515..315efbd641 100644 --- a/compiler/ccgutils.nim +++ b/compiler/ccgutils.nim @@ -100,7 +100,7 @@ proc getUniqueType*(key: PType): PType = if result == nil: gCanonicalTypes[k] = key result = key - of tyTypeDesc, tyTypeClasses, tyGenericParam, tyFromExpr, tyFieldAccessor: + of tyTypeDesc, tyTypeClasses, tyGenericParam, tyFromExpr: if key.isResolvedUserTypeClass: return getUniqueType(lastSon(key)) if key.sym != nil: @@ -126,7 +126,7 @@ proc getUniqueType*(key: PType): PType = result = slowSearch(key, k) of tyGenericInvocation, tyGenericBody, tyOpenArray, tyArray, tySet, tyRange, tyTuple, - tySequence, tyForward, tyVarargs, tyProxy: + tySequence, tyForward, tyVarargs, tyProxy, tyOpt: # we have to do a slow linear search because types may need # to be compared by their structure: result = slowSearch(key, k) diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim index bffe196df4..0f8d763c27 100644 --- a/compiler/jsgen.nim +++ b/compiler/jsgen.nim @@ -187,12 +187,12 @@ proc mapType(typ: PType): TJSTypeKind = of tyBool: result = etyBool of tyFloat..tyFloat128: result = etyFloat of tySet: result = etyObject # map a set to a table - of tyString, tySequence: result = etySeq + of tyString, tySequence, tyOpt: result = etySeq of tyObject, tyArray, tyTuple, tyOpenArray, tyVarargs: result = etyObject of tyNil: result = etyNull of tyGenericInst, tyGenericParam, tyGenericBody, tyGenericInvocation, - tyNone, tyFromExpr, tyForward, tyEmpty, tyFieldAccessor, + tyNone, tyFromExpr, tyForward, tyEmpty, tyExpr, tyStmt, tyTypeDesc, tyTypeClasses, tyVoid, tyAlias: result = etyNone of tyInferred: @@ -927,7 +927,7 @@ proc genAsgnAux(p: PProc, x, y: PNode, noCopyNeeded: bool) = # we don't care if it's an etyBaseIndex (global) of a string, it's # still a string that needs to be copied properly: - if x.typ.skipTypes(abstractInst).kind in {tySequence, tyString}: + if x.typ.skipTypes(abstractInst).kind in {tySequence, tyOpt, tyString}: xtyp = etySeq case xtyp of etySeq: @@ -971,7 +971,7 @@ proc genFastAsgn(p: PProc, n: PNode) = # See bug #5933. So we try to be more compatible with the C backend semantics # here for 'shallowCopy'. This is an educated guess and might require further # changes later: - let noCopy = n[0].typ.skipTypes(abstractInst).kind in {tySequence, tyString} + let noCopy = n[0].typ.skipTypes(abstractInst).kind in {tySequence, tyOpt, tyString} genAsgnAux(p, n.sons[0], n.sons[1], noCopyNeeded=noCopy) proc genSwap(p: PProc, n: PNode) = @@ -1550,7 +1550,7 @@ proc createVar(p: PProc, typ: PType, indirect: bool): Rope = result = putToSeq("[null, 0]", indirect) else: result = putToSeq("null", indirect) - of tySequence, tyString, tyCString, tyPointer, tyProc: + of tySequence, tyOpt, tyString, tyCString, tyPointer, tyProc: result = putToSeq("null", indirect) of tyStatic: if t.n != nil: diff --git a/compiler/semasgn.nim b/compiler/semasgn.nim index f2144037c6..b51d7167b2 100644 --- a/compiler/semasgn.nim +++ b/compiler/semasgn.nim @@ -185,7 +185,7 @@ proc liftBodyAux(c: var TLiftCtx; t: PType; body, x, y: PNode) = case t.kind of tyNone, tyEmpty, tyVoid: discard of tyPointer, tySet, tyBool, tyChar, tyEnum, tyInt..tyUInt64, tyCString, - tyPtr, tyString, tyRef: + tyPtr, tyString, tyRef, tyOpt: defaultOp(c, t, body, x, y) of tyArray, tySequence: if tfHasAsgn in t.flags: @@ -227,7 +227,7 @@ proc liftBodyAux(c: var TLiftCtx; t: PType; body, x, y: PNode) = tyTypeDesc, tyGenericInvocation, tyForward: internalError(c.info, "assignment requested for type: " & typeToString(t)) of tyOrdinal, tyRange, tyInferred, - tyGenericInst, tyFieldAccessor, tyStatic, tyVar, tyAlias: + tyGenericInst, tyStatic, tyVar, tyAlias: liftBodyAux(c, lastSon(t), body, x, y) of tyUnused, tyUnused0, tyUnused1, tyUnused2: internalError("liftBodyAux") diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 903db115f9..fb86eae05c 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -246,8 +246,7 @@ proc semLowHigh(c: PContext, n: PNode, m: TMagic): PNode = localError(n.info, errXExpectsTypeOrValue, opToStr[m]) else: n.sons[1] = semExprWithType(c, n.sons[1], {efDetermineType}) - var typ = skipTypes(n.sons[1].typ, abstractVarRange + - {tyTypeDesc, tyFieldAccessor}) + var typ = skipTypes(n.sons[1].typ, abstractVarRange + {tyTypeDesc}) case typ.kind of tySequence, tyString, tyCString, tyOpenArray, tyVarargs: n.typ = getSysType(tyInt) @@ -255,7 +254,7 @@ proc semLowHigh(c: PContext, n: PNode, m: TMagic): PNode = n.typ = typ.sons[0] # indextype of tyInt..tyInt64, tyChar, tyBool, tyEnum, tyUInt8, tyUInt16, tyUInt32: # do not skip the range! - n.typ = n.sons[1].typ.skipTypes(abstractVar + {tyFieldAccessor}) + n.typ = n.sons[1].typ.skipTypes(abstractVar) of tyGenericParam: # prepare this for resolving in semtypinst: # we must use copyTree here in order to avoid creating a cycle @@ -279,7 +278,7 @@ proc isOpImpl(c: PContext, n: PNode, flags: TExprFlags): PNode = n[1].typ != nil and n[1].typ.kind == tyTypeDesc and n[2].kind in {nkStrLit..nkTripleStrLit, nkType} - let t1 = n[1].typ.skipTypes({tyTypeDesc, tyFieldAccessor}) + let t1 = n[1].typ.skipTypes({tyTypeDesc}) if n[2].kind in {nkStrLit..nkTripleStrLit}: case n[2].strVal.normalize @@ -1087,9 +1086,6 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode = if field != nil: n.typ = makeTypeDesc(c, field.typ) return n - #n.typ = newTypeWithSons(c, tyFieldAccessor, @[ty, field.typ]) - #n.typ.n = copyTree(n) - #return n else: tryReadingGenericParam(ty) return diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 35f0cf6dc3..7ad13bebbf 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -1234,7 +1234,7 @@ proc semInferredLambda(c: PContext, pt: TIdTable, n: PNode): PNode = s.typ = n.typ for i in 1.. 0: result = firstOrd(lastSon(t)) @@ -639,7 +619,7 @@ proc firstOrd(t: PType): BiggestInt = internalError("invalid kind for first(" & $t.kind & ')') result = 0 -proc lastOrd(t: PType): BiggestInt = +proc lastOrd*(t: PType): BiggestInt = case t.kind of tyBool: result = 1 of tyChar: result = 255 @@ -666,7 +646,7 @@ proc lastOrd(t: PType): BiggestInt = of tyEnum: assert(t.n.sons[sonsLen(t.n) - 1].kind == nkSym) result = t.n.sons[sonsLen(t.n) - 1].sym.position - of tyGenericInst, tyDistinct, tyTypeDesc, tyFieldAccessor, tyAlias: + of tyGenericInst, tyDistinct, tyTypeDesc, tyAlias: result = lastOrd(lastSon(t)) of tyProxy: result = 0 of tyOrdinal: @@ -676,7 +656,7 @@ proc lastOrd(t: PType): BiggestInt = internalError("invalid kind for last(" & $t.kind & ')') result = 0 -proc lengthOrd(t: PType): BiggestInt = +proc lengthOrd*(t: PType): BiggestInt = case t.kind of tyInt64, tyInt32, tyInt: result = lastOrd(t) of tyDistinct: result = lengthOrd(t.sons[0]) @@ -689,6 +669,14 @@ proc lengthOrd(t: PType): BiggestInt = else: result = lastOrd(t) - firstOrd(t) + 1 +proc isCompatibleToCString*(a: PType): bool = + if a.kind == tyArray: + if (firstOrd(a.sons[0]) == 0) and + (skipTypes(a.sons[0], {tyRange, tyGenericInst, tyAlias}).kind in + {tyInt..tyInt64, tyUInt..tyUInt64}) and + (a.sons[1].kind == tyChar): + result = true + # -------------- type equality ----------------------------------------------- type @@ -989,7 +977,7 @@ proc sameTypeAux(x, y: PType, c: var TSameTypeClosure): bool = result = a.sym.position == b.sym.position of tyGenericInvocation, tyGenericBody, tySequence, tyOpenArray, tySet, tyRef, tyPtr, tyVar, - tyArray, tyProc, tyVarargs, tyOrdinal, tyTypeClasses, tyFieldAccessor: + tyArray, tyProc, tyVarargs, tyOrdinal, tyTypeClasses, tyOpt: cycleCheck() if a.kind == tyUserTypeClass and a.n != nil: return a.n == b.n result = sameChildrenAux(a, b, c) and sameFlags(a, b) @@ -1144,7 +1132,7 @@ proc typeAllowedAux(marker: var IntSet, typ: PType, kind: TSymKind, of tyTypeClasses: if not (tfGenericTypeParam in t.flags or taField notin flags): result = t of tyGenericBody, tyGenericParam, tyGenericInvocation, - tyNone, tyForward, tyFromExpr, tyFieldAccessor: + tyNone, tyForward, tyFromExpr: result = t of tyNil: if kind != skConst: result = t @@ -1160,7 +1148,7 @@ proc typeAllowedAux(marker: var IntSet, typ: PType, kind: TSymKind, of tyOpenArray, tyVarargs: if kind != skParam: result = t else: result = typeAllowedAux(marker, t.sons[0], skVar, flags) - of tySequence: + of tySequence, tyOpt: if t.sons[0].kind != tyEmpty: result = typeAllowedAux(marker, t.sons[0], skVar, flags+{taHeap}) of tyArray: @@ -1359,7 +1347,7 @@ proc computeSizeAux(typ: PType, a: var BiggestInt): BiggestInt = typ.size = result typ.align = int16(a) -proc computeSize(typ: PType): BiggestInt = +proc computeSize*(typ: PType): BiggestInt = var a: BiggestInt = 1 result = computeSizeAux(typ, a) @@ -1368,7 +1356,7 @@ proc getReturnType*(s: PSym): PType = assert s.kind in skProcKinds result = s.typ.sons[0] -proc getSize(typ: PType): BiggestInt = +proc getSize*(typ: PType): BiggestInt = result = computeSize(typ) if result < 0: internalError("getSize: " & $typ.kind) diff --git a/compiler/vmdeps.nim b/compiler/vmdeps.nim index b9bbba551e..12fc455bd8 100644 --- a/compiler/vmdeps.nim +++ b/compiler/vmdeps.nim @@ -250,6 +250,7 @@ proc mapTypeToAstX(t: PType; info: TLineInfo; result = mapTypeToBracket("ref", mRef, t, info) of tyVar: result = mapTypeToBracket("var", mVar, t, info) of tySequence: result = mapTypeToBracket("seq", mSeq, t, info) + of tyOpt: result = mapTypeToBracket("opt", mOpt, t, info) of tyProc: if inst: result = newNodeX(nkProcTy) @@ -304,7 +305,7 @@ proc mapTypeToAstX(t: PType; info: TLineInfo; of tyNot: result = mapTypeToBracket("not", mNot, t, info) of tyAnything: result = atomicType("anything", mNone) of tyInferred: internalAssert false - of tyStatic, tyFromExpr, tyFieldAccessor: + of tyStatic, tyFromExpr: if inst: if t.n != nil: result = t.n.copyTree else: result = atomicType("void", mVoid) diff --git a/lib/core/macros.nim b/lib/core/macros.nim index 28b3dd7ab9..8c70d2b476 100644 --- a/lib/core/macros.nim +++ b/lib/core/macros.nim @@ -97,7 +97,7 @@ type ntyError, ntyBuiltinTypeClass, ntyUserTypeClass, ntyUserTypeClassInst, ntyCompositeTypeClass, ntyInferred, ntyAnd, ntyOr, ntyNot, - ntyAnything, ntyStatic, ntyFromExpr, ntyFieldAccessor, ntyVoid + ntyAnything, ntyStatic, ntyFromExpr, ntyOpt, ntyVoid TNimTypeKinds* {.deprecated.} = set[NimTypeKind] NimSymKind* = enum