diff options
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/ast.nim | 4 | ||||
-rw-r--r-- | compiler/condsyms.nim | 1 | ||||
-rw-r--r-- | compiler/msgs.nim | 2 | ||||
-rw-r--r-- | compiler/parser.nim | 9 | ||||
-rw-r--r-- | compiler/pbraces.nim | 5 | ||||
-rw-r--r-- | compiler/semtypes.nim | 16 |
6 files changed, 34 insertions, 3 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim index 5b68e9712..d4ffbcfa4 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -212,6 +212,8 @@ type nkIteratorTy, # iterator type nkSharedTy, # 'shared T' # we use 'nkPostFix' for the 'not nil' addition + nkInTy, # prefix `in` used to mark contravariant types + nkOutTy, # prefix `out` used to mark covariant types nkEnumTy, # enum body nkEnumFieldDef, # `ident = expr` in an enumeration nkArgList, # argument list @@ -268,6 +270,8 @@ type sfDiscardable, # returned value may be discarded implicitly sfOverriden, # proc is overriden sfGenSym # symbol is 'gensym'ed; do not add to symbol table + sfCovariant # covariant generic param + sfContravariant # contravariant generic param TSymFlags* = set[TSymFlag] diff --git a/compiler/condsyms.nim b/compiler/condsyms.nim index 4303fd6c8..a4f47ac72 100644 --- a/compiler/condsyms.nim +++ b/compiler/condsyms.nim @@ -103,3 +103,4 @@ proc initDefines*() = defineSymbol("nimNewShiftOps") defineSymbol("nimDistros") defineSymbol("nimHasCppDefine") + defineSymbol("nimGenericInOutFlags") diff --git a/compiler/msgs.nim b/compiler/msgs.nim index 3a97f1ed2..1842ce1de 100644 --- a/compiler/msgs.nim +++ b/compiler/msgs.nim @@ -113,6 +113,7 @@ type errGenericLambdaNotAllowed, errProcHasNoConcreteType, errCompilerDoesntSupportTarget, + errInOutFlagNotExtern, errUser, warnCannotOpenFile, warnOctalEscape, warnXIsNeverRead, warnXmightNotBeenInit, @@ -380,6 +381,7 @@ const "of the generic paramers can be inferred from the expected signature.", errProcHasNoConcreteType: "'$1' doesn't have a concrete type, due to unspecified generic parameters.", errCompilerDoesntSupportTarget: "The current compiler \'$1\' doesn't support the requested compilation target", + errInOutFlagNotExtern: "`in` and `out` flags can be used only with imported types", errUser: "$1", warnCannotOpenFile: "cannot open \'$1\'", warnOctalEscape: "octal escape sequences do not exist; leading zero is ignored", diff --git a/compiler/parser.nim b/compiler/parser.nim index e4c04c0f7..f4d1aca15 100644 --- a/compiler/parser.nim +++ b/compiler/parser.nim @@ -1523,6 +1523,13 @@ proc parseGenericParam(p: var TParser): PNode = # progress guaranteed while true: case p.tok.tokType + of tkIn, tkOut: + let kind = if p.tok.tokType == tkIn: nkInTy + else: nkOutTy + a = newNodeP(kind, p) + getTok(p) + expectIdent(p) + a.addSon(parseSymbol(p)) of tkSymbol, tkAccent: a = parseSymbol(p) if a.kind == nkEmpty: return @@ -1551,7 +1558,7 @@ proc parseGenericParamList(p: var TParser): PNode = getTok(p) optInd(p, result) # progress guaranteed - while p.tok.tokType in {tkSymbol, tkAccent}: + while p.tok.tokType in {tkSymbol, tkAccent, tkIn, tkOut}: var a = parseGenericParam(p) addSon(result, a) if p.tok.tokType notin {tkComma, tkSemiColon}: break diff --git a/compiler/pbraces.nim b/compiler/pbraces.nim index b59fbc6cf..fa4ccc139 100644 --- a/compiler/pbraces.nim +++ b/compiler/pbraces.nim @@ -1336,6 +1336,11 @@ proc parseGenericParam(p: var TParser): PNode = result = newNodeP(nkIdentDefs, p) while true: case p.tok.tokType + of tkIn, tkOut: + let t = p.tok.tokType + getTok(p) + expectIdent(p) + a = parseSymbol(p) of tkSymbol, tkAccent: a = parseSymbol(p) if a.kind == nkEmpty: return diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index 16066da91..5cc5a1ecf 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -1584,10 +1584,22 @@ proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode = # type for each generic param. the index # of the parameter will be stored in the # attached symbol. + var paramName = a.sons[j] + var covarianceFlag = sfPure + + if paramName.kind in {nkInTy, nkOutTy}: + if father == nil or sfImportc notin father.sym.flags: + localError(paramName.info, errInOutFlagNotExtern) + paramName = paramName[0] + covarianceFlag = if paramName.kind == nkInTy: sfContravariant + else: sfCovariant + var s = if finalType.kind == tyStatic or tfWildcard in typ.flags: - newSymG(skGenericParam, a.sons[j], c).linkTo(finalType) + newSymG(skGenericParam, paramName, c).linkTo(finalType) else: - newSymG(skType, a.sons[j], c).linkTo(finalType) + newSymG(skType, paramName, c).linkTo(finalType) + + if covarianceFlag != sfPure: s.flags.incl(covarianceFlag) if def.kind != nkEmpty: s.ast = def if father != nil: addSonSkipIntLit(father, s.typ) s.position = result.len |