mirror of
https://github.com/nim-lang/Nim.git
synced 2026-04-19 14:00:35 +00:00
resolved conflict for news.txt
This commit is contained in:
@@ -477,42 +477,8 @@ proc primarySuffix(p: var TParser, r: PNode): PNode =
|
||||
result = indexExprList(p, result, nkCurlyExpr, tkCurlyRi)
|
||||
else: break
|
||||
|
||||
proc primary(p: var TParser, skipSuffix = false): PNode =
|
||||
# prefix operator?
|
||||
if isOperator(p.tok):
|
||||
let isSigil = IsSigilLike(p.tok)
|
||||
result = newNodeP(nkPrefix, p)
|
||||
var a = newIdentNodeP(p.tok.ident, p)
|
||||
addSon(result, a)
|
||||
getTok(p)
|
||||
optInd(p, a)
|
||||
if isSigil:
|
||||
#XXX prefix operators
|
||||
addSon(result, primary(p, true))
|
||||
result = primarySuffix(p, result)
|
||||
else:
|
||||
addSon(result, primary(p))
|
||||
return
|
||||
elif p.tok.tokType == tkAddr:
|
||||
result = newNodeP(nkAddr, p)
|
||||
getTok(p)
|
||||
addSon(result, primary(p))
|
||||
return
|
||||
elif p.tok.tokType == tkStatic:
|
||||
result = newNodeP(nkStaticExpr, p)
|
||||
getTok(p)
|
||||
addSon(result, primary(p))
|
||||
return
|
||||
elif p.tok.tokType == tkBind:
|
||||
result = newNodeP(nkBind, p)
|
||||
getTok(p)
|
||||
optInd(p, result)
|
||||
addSon(result, primary(p))
|
||||
return
|
||||
result = identOrLiteral(p)
|
||||
if not skipSuffix:
|
||||
result = primarySuffix(p, result)
|
||||
|
||||
proc primary(p: var TParser, skipSuffix = false): PNode
|
||||
|
||||
proc lowestExprAux(p: var TParser, limit: int): PNode =
|
||||
result = primary(p)
|
||||
# expand while operators have priorities higher than 'limit'
|
||||
@@ -642,7 +608,7 @@ proc parseParamList(p: var TParser, retColon = true): PNode =
|
||||
var a: PNode
|
||||
result = newNodeP(nkFormalParams, p)
|
||||
addSon(result, ast.emptyNode) # return type
|
||||
if p.tok.tokType == tkParLe:
|
||||
if p.tok.tokType == tkParLe:
|
||||
getTok(p)
|
||||
optInd(p, result)
|
||||
while true:
|
||||
@@ -660,9 +626,9 @@ proc parseParamList(p: var TParser, retColon = true): PNode =
|
||||
optInd(p, a)
|
||||
optPar(p)
|
||||
eat(p, tkParRi)
|
||||
let b = if retColon: p.tok.tokType == tkColon
|
||||
else: p.tok.tokType == tkOpr and IdentEq(p.tok.ident, "->")
|
||||
if b:
|
||||
let hasRet = if retColon: p.tok.tokType == tkColon
|
||||
else: p.tok.tokType == tkOpr and IdentEq(p.tok.ident, "->")
|
||||
if hasRet:
|
||||
getTok(p)
|
||||
optInd(p, result)
|
||||
result.sons[0] = parseTypeDesc(p)
|
||||
@@ -696,6 +662,7 @@ proc parseProcExpr(p: var TParser, isExpr: bool): PNode =
|
||||
info: TLineInfo
|
||||
info = parLineInfo(p)
|
||||
getTok(p)
|
||||
let hasSignature = p.tok.tokType in {tkParLe, tkColon}
|
||||
params = parseParamList(p)
|
||||
pragmas = optPragmas(p)
|
||||
if (p.tok.tokType == tkEquals) and isExpr:
|
||||
@@ -709,8 +676,9 @@ proc parseProcExpr(p: var TParser, isExpr: bool): PNode =
|
||||
addSon(result, parseStmt(p))
|
||||
else:
|
||||
result = newNodeI(nkProcTy, info)
|
||||
addSon(result, params)
|
||||
addSon(result, pragmas)
|
||||
if hasSignature:
|
||||
addSon(result, params)
|
||||
addSon(result, pragmas)
|
||||
|
||||
proc isExprStart(p: TParser): bool =
|
||||
case p.tok.tokType
|
||||
@@ -724,39 +692,70 @@ proc parseTypeDescKAux(p: var TParser, kind: TNodeKind): PNode =
|
||||
result = newNodeP(kind, p)
|
||||
getTok(p)
|
||||
optInd(p, result)
|
||||
if isExprStart(p):
|
||||
if not isOperator(p.tok) and isExprStart(p):
|
||||
addSon(result, parseTypeDesc(p))
|
||||
|
||||
proc parseExpr(p: var TParser): PNode =
|
||||
#
|
||||
#expr ::= lowestExpr
|
||||
# | 'if' expr ':' expr ('elif' expr ':' expr)* 'else' ':' expr
|
||||
# | 'var' [expr]
|
||||
# | 'ref' [expr]
|
||||
# | 'ptr' [expr]
|
||||
# | 'type' expr
|
||||
# | 'tuple' [tupleDesc]
|
||||
# | 'enum'
|
||||
# | 'object'
|
||||
# |
|
||||
# | 'proc' paramList [pragma] ['=' stmt]
|
||||
# | 'when' expr ':' expr ('elif' expr ':' expr)* 'else' ':' expr
|
||||
#
|
||||
case p.tok.toktype
|
||||
case p.tok.tokType:
|
||||
of tkIf: result = parseIfExpr(p, nkIfExpr)
|
||||
of tkWhen: result = parseIfExpr(p, nkWhenExpr)
|
||||
else: result = lowestExpr(p)
|
||||
|
||||
proc primary(p: var TParser, skipSuffix = false): PNode =
|
||||
# prefix operator?
|
||||
if isOperator(p.tok):
|
||||
let isSigil = IsSigilLike(p.tok)
|
||||
result = newNodeP(nkPrefix, p)
|
||||
var a = newIdentNodeP(p.tok.ident, p)
|
||||
addSon(result, a)
|
||||
getTok(p)
|
||||
optInd(p, a)
|
||||
if isSigil:
|
||||
#XXX prefix operators
|
||||
addSon(result, primary(p, true))
|
||||
result = primarySuffix(p, result)
|
||||
else:
|
||||
addSon(result, primary(p))
|
||||
return
|
||||
|
||||
case p.tok.tokType:
|
||||
of tkVar: result = parseTypeDescKAux(p, nkVarTy)
|
||||
of tkRef: result = parseTypeDescKAux(p, nkRefTy)
|
||||
of tkPtr: result = parseTypeDescKAux(p, nkPtrTy)
|
||||
of tkType: result = parseTypeDescKAux(p, nkTypeOfExpr)
|
||||
of tkTuple: result = parseTuple(p)
|
||||
of tkProc: result = parseProcExpr(p, true)
|
||||
of tkIf: result = parseIfExpr(p, nkIfExpr)
|
||||
of tkWhen: result = parseIfExpr(p, nkWhenExpr)
|
||||
of tkEnum:
|
||||
result = newNodeP(nkEnumTy, p)
|
||||
getTok(p)
|
||||
of tkObject:
|
||||
result = newNodeP(nkObjectTy, p)
|
||||
getTok(p)
|
||||
else: result = lowestExpr(p)
|
||||
of tkDistinct:
|
||||
result = newNodeP(nkDistinctTy, p)
|
||||
getTok(p)
|
||||
of tkAddr:
|
||||
result = newNodeP(nkAddr, p)
|
||||
getTok(p)
|
||||
addSon(result, primary(p))
|
||||
of tkStatic:
|
||||
result = newNodeP(nkStaticExpr, p)
|
||||
getTok(p)
|
||||
addSon(result, primary(p))
|
||||
of tkBind:
|
||||
result = newNodeP(nkBind, p)
|
||||
getTok(p)
|
||||
optInd(p, result)
|
||||
addSon(result, primary(p))
|
||||
else:
|
||||
result = identOrLiteral(p)
|
||||
if not skipSuffix:
|
||||
result = primarySuffix(p, result)
|
||||
|
||||
proc parseTypeDesc(p: var TParser): PNode =
|
||||
if p.tok.toktype == tkProc: result = parseProcExpr(p, false)
|
||||
|
||||
@@ -16,8 +16,13 @@ proc newOrPrevType(kind: TTypeKind, prev: PType, c: PContext): PType =
|
||||
else:
|
||||
result = prev
|
||||
if result.kind == tyForward: result.kind = kind
|
||||
|
||||
proc semEnum(c: PContext, n: PNode, prev: PType): PType =
|
||||
|
||||
proc newConstraint(c: PContext, k: TTypeKind): PType =
|
||||
result = newTypeS(tyTypeClass, c)
|
||||
result.addSon(newTypeS(k, c))
|
||||
|
||||
proc semEnum(c: PContext, n: PNode, prev: PType): PType =
|
||||
if n.sonsLen == 0: return newConstraint(c, tyEnum)
|
||||
var
|
||||
counter, x: BiggestInt
|
||||
e: PSym
|
||||
@@ -92,29 +97,30 @@ proc semContainer(c: PContext, n: PNode, kind: TTypeKind, kindStr: string,
|
||||
addSon(result, base)
|
||||
else:
|
||||
GlobalError(n.info, errXExpectsOneTypeParam, kindStr)
|
||||
|
||||
proc semAnyRef(c: PContext, n: PNode, kind: TTypeKind, kindStr: string,
|
||||
prev: PType): PType =
|
||||
result = newOrPrevType(kind, prev, c)
|
||||
if sonsLen(n) == 1:
|
||||
|
||||
proc semAnyRef(c: PContext, n: PNode, kind: TTypeKind, prev: PType): PType =
|
||||
if sonsLen(n) == 1:
|
||||
result = newOrPrevType(kind, prev, c)
|
||||
var base = semTypeNode(c, n.sons[0], nil)
|
||||
addSon(result, base)
|
||||
else:
|
||||
GlobalError(n.info, errXExpectsOneTypeParam, kindStr)
|
||||
else:
|
||||
result = newConstraint(c, kind)
|
||||
|
||||
proc semVarType(c: PContext, n: PNode, prev: PType): PType =
|
||||
result = newOrPrevType(tyVar, prev, c)
|
||||
if sonsLen(n) == 1:
|
||||
result = newOrPrevType(tyVar, prev, c)
|
||||
var base = semTypeNode(c, n.sons[0], nil)
|
||||
if base.kind == tyVar: GlobalError(n.info, errVarVarTypeNotAllowed)
|
||||
addSon(result, base)
|
||||
else:
|
||||
GlobalError(n.info, errXExpectsOneTypeParam, "var")
|
||||
else:
|
||||
result = newConstraint(c, tyVar)
|
||||
|
||||
proc semDistinct(c: PContext, n: PNode, prev: PType): PType =
|
||||
result = newOrPrevType(tyDistinct, prev, c)
|
||||
if sonsLen(n) == 1: addSon(result, semTypeNode(c, n.sons[0], nil))
|
||||
else: GlobalError(n.info, errXExpectsOneTypeParam, "distinct")
|
||||
if sonsLen(n) == 1:
|
||||
result = newOrPrevType(tyDistinct, prev, c)
|
||||
addSon(result, semTypeNode(c, n.sons[0], nil))
|
||||
else:
|
||||
result = newConstraint(c, tyDistinct)
|
||||
|
||||
proc semRangeAux(c: PContext, n: PNode, prev: PType): PType =
|
||||
assert IsRange(n)
|
||||
@@ -184,7 +190,11 @@ proc semTypeIdent(c: PContext, n: PNode): PSym =
|
||||
# This is a typedesc param. is it already bound?
|
||||
# it's not bound when it's also used as return type for example
|
||||
if result.typ.sonsLen > 0:
|
||||
return result.typ.sons[0].sym
|
||||
let bound = result.typ.sons[0].sym
|
||||
if bound != nil:
|
||||
return bound
|
||||
else:
|
||||
return result.typ.sym
|
||||
else:
|
||||
return result.typ.sym
|
||||
if result.kind != skType: GlobalError(n.info, errTypeExpected)
|
||||
@@ -197,8 +207,8 @@ proc semTypeIdent(c: PContext, n: PNode): PSym =
|
||||
GlobalError(n.info, errIdentifierExpected)
|
||||
|
||||
proc semTuple(c: PContext, n: PNode, prev: PType): PType =
|
||||
var
|
||||
typ: PType
|
||||
if n.sonsLen == 0: return newConstraint(c, tyTuple)
|
||||
var typ: PType
|
||||
result = newOrPrevType(tyTuple, prev, c)
|
||||
result.n = newNodeI(nkRecList, n.info)
|
||||
var check = initIntSet()
|
||||
@@ -458,7 +468,8 @@ proc skipGenericInvokation(t: PType): PType {.inline.} =
|
||||
if result.kind == tyGenericBody:
|
||||
result = lastSon(result)
|
||||
|
||||
proc semObjectNode(c: PContext, n: PNode, prev: PType): PType =
|
||||
proc semObjectNode(c: PContext, n: PNode, prev: PType): PType =
|
||||
if n.sonsLen == 0: return newConstraint(c, tyObject)
|
||||
var check = initIntSet()
|
||||
var pos = 0
|
||||
var base: PType = nil
|
||||
@@ -529,6 +540,36 @@ proc paramTypeClass(c: PContext, paramType: PType, procKind: TSymKind):
|
||||
result.typ = copyType(paramType, getCurrOwner(), false)
|
||||
else: nil
|
||||
|
||||
proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
|
||||
paramType: PType, paramName: string): PType =
|
||||
## Params having implicit generic types or pseudo types such as 'expr'
|
||||
## need to be added to the generic params lists.
|
||||
## 'expr' is different from 'expr{string}' so we must first call
|
||||
## paramTypeClass to get the actual type we are going to use.
|
||||
result = paramType
|
||||
var (typeClass, paramTypId) = paramTypeClass(c, paramType, procKind)
|
||||
let isAnon = paramTypId == nil
|
||||
if typeClass != nil:
|
||||
if isAnon: paramTypId = getIdent(paramName & ":type")
|
||||
if genericParams == nil:
|
||||
# genericParams is nil when the proc is being instantiated
|
||||
# the resolved type will be in scope then
|
||||
result = SymtabGet(c.tab, paramTypId).AssertNotNil.typ
|
||||
else:
|
||||
block addImplicitGeneric:
|
||||
# is this a bindOnce type class already present in the param list?
|
||||
for i in countup(0, genericParams.len - 1):
|
||||
if genericParams.sons[i].sym.name == paramTypId:
|
||||
result = genericParams.sons[i].typ
|
||||
break addImplicitGeneric
|
||||
|
||||
var s = newSym(skType, paramTypId, getCurrOwner())
|
||||
if isAnon: s.flags.incl(sfAnon)
|
||||
s.linkTo(typeClass)
|
||||
s.position = genericParams.len
|
||||
genericParams.addSon(newSymNode(s))
|
||||
result = typeClass
|
||||
|
||||
proc semProcTypeNode(c: PContext, n, genericParams: PNode,
|
||||
prev: PType, kind: TSymKind): PType =
|
||||
var
|
||||
@@ -576,37 +617,15 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
|
||||
if skipTypes(typ, {tyGenericInst}).kind == tyEmpty: continue
|
||||
for j in countup(0, length-3):
|
||||
var arg = newSymS(skParam, a.sons[j], c)
|
||||
var endingType = typ
|
||||
var (typeClass, paramTypId) = paramTypeClass(c, typ, kind)
|
||||
if typeClass != nil:
|
||||
if paramTypId == nil: paramTypId = getIdent(arg.name.s & ":type")
|
||||
if genericParams == nil:
|
||||
# genericParams is nil when the proc is being instantiated
|
||||
# the resolved type will be in scope then
|
||||
endingType = SymtabGet(c.tab, paramTypId).AssertNotNil.typ
|
||||
else:
|
||||
block addImplicitGeneric:
|
||||
# is this a bindOnce type class already present in the param list?
|
||||
for i in countup(0, genericParams.len - 1):
|
||||
if genericParams.sons[i].sym.name == paramTypId:
|
||||
endingType = genericParams.sons[i].typ
|
||||
break addImplicitGeneric
|
||||
|
||||
var s = newSym(skType, paramTypId, getCurrOwner())
|
||||
s.flags.incl(sfAnon)
|
||||
s.linkTo(typeClass)
|
||||
s.position = genericParams.len
|
||||
genericParams.addSon(newSymNode(s))
|
||||
endingType = typeClass
|
||||
|
||||
arg.typ = endingType
|
||||
var finalType = liftParamType(c, kind, genericParams, typ, arg.name.s)
|
||||
arg.typ = finalType
|
||||
arg.position = counter
|
||||
inc(counter)
|
||||
if def != nil and def.kind != nkEmpty: arg.ast = copyTree(def)
|
||||
if ContainsOrIncl(check, arg.name.id):
|
||||
LocalError(a.sons[j].info, errAttemptToRedefine, arg.name.s)
|
||||
addSon(result.n, newSymNode(arg))
|
||||
addSon(result, endingType)
|
||||
addSon(result, finalType)
|
||||
addParamOrResult(c, arg, kind)
|
||||
|
||||
if n.sons[0].kind != nkEmpty:
|
||||
@@ -614,6 +633,8 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
|
||||
# turn explicit 'void' return type into 'nil' because the rest of the
|
||||
# compiler only checks for 'nil':
|
||||
if skipTypes(r, {tyGenericInst}).kind != tyEmpty:
|
||||
if r.sym == nil or sfAnon notin r.sym.flags:
|
||||
r = liftParamType(c, kind, genericParams, r, "result")
|
||||
result.sons[0] = r
|
||||
res.typ = result.sons[0]
|
||||
|
||||
@@ -708,8 +729,8 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
|
||||
if sonsLen(n) == 1: result = semTypeNode(c, n.sons[0], prev)
|
||||
else: GlobalError(n.info, errTypeExpected)
|
||||
of nkCallKinds:
|
||||
let op = n.sons[0].ident.id
|
||||
if op in {ord(wAnd), ord(wOr)}:
|
||||
let op = n.sons[0].ident
|
||||
if op.id in {ord(wAnd), ord(wOr)} or op.s == "|":
|
||||
var
|
||||
t1 = semTypeNode(c, n.sons[1], nil)
|
||||
t2 = semTypeNode(c, n.sons[2], nil)
|
||||
@@ -720,7 +741,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
|
||||
result = newTypeS(tyTypeClass, c)
|
||||
result.addSon(t1)
|
||||
result.addSon(t2)
|
||||
result.flags.incl(if op == ord(wAnd): tfAll else: tfAny)
|
||||
result.flags.incl(if op.id == ord(wAnd): tfAll else: tfAny)
|
||||
else:
|
||||
result = semTypeFromMacro(c, n)
|
||||
of nkCurlyExpr:
|
||||
@@ -766,11 +787,12 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
|
||||
GlobalError(n.info, errTypeExpected)
|
||||
of nkObjectTy: result = semObjectNode(c, n, prev)
|
||||
of nkTupleTy: result = semTuple(c, n, prev)
|
||||
of nkRefTy: result = semAnyRef(c, n, tyRef, "ref", prev)
|
||||
of nkPtrTy: result = semAnyRef(c, n, tyPtr, "ptr", prev)
|
||||
of nkRefTy: result = semAnyRef(c, n, tyRef, prev)
|
||||
of nkPtrTy: result = semAnyRef(c, n, tyPtr, prev)
|
||||
of nkVarTy: result = semVarType(c, n, prev)
|
||||
of nkDistinctTy: result = semDistinct(c, n, prev)
|
||||
of nkProcTy:
|
||||
if n.sonsLen == 0: return newConstraint(c, tyProc)
|
||||
checkSonsLen(n, 2)
|
||||
openScope(c.tab)
|
||||
result = semProcTypeNode(c, n.sons[0], nil, prev, skProc)
|
||||
@@ -778,7 +800,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
|
||||
var s = newSymS(skProc, newIdentNode(getIdent("dummy"), n.info), c)
|
||||
s.typ = result
|
||||
pragma(c, s, n.sons[1], procTypePragmas)
|
||||
closeScope(c.tab)
|
||||
closeScope(c.tab)
|
||||
of nkEnumTy: result = semEnum(c, n, prev)
|
||||
of nkType: result = n.typ
|
||||
of nkStmtListType: result = semStmtListType(c, n, prev)
|
||||
@@ -828,29 +850,12 @@ proc processMagicType(c: PContext, m: PSym) =
|
||||
of mPNimrodNode: nil
|
||||
else: GlobalError(m.info, errTypeExpected)
|
||||
|
||||
proc newConstraint(c: PContext, k: TTypeKind): PType =
|
||||
result = newTypeS(tyTypeClass, c)
|
||||
result.addSon(newTypeS(k, c))
|
||||
|
||||
proc semGenericConstraints(c: PContext, n: PNode, result: PType) =
|
||||
case n.kind
|
||||
of nkProcTy: result.addSon(newConstraint(c, tyProc))
|
||||
of nkEnumTy: result.addSon(newConstraint(c, tyEnum))
|
||||
of nkObjectTy: result.addSon(newConstraint(c, tyObject))
|
||||
of nkTupleTy: result.addSon(newConstraint(c, tyTuple))
|
||||
of nkDistinctTy: result.addSon(newConstraint(c, tyDistinct))
|
||||
of nkVarTy: result.addSon(newConstraint(c, tyVar))
|
||||
of nkPtrTy: result.addSon(newConstraint(c, tyPtr))
|
||||
of nkRefTy: result.addSon(newConstraint(c, tyRef))
|
||||
of nkInfix:
|
||||
semGenericConstraints(c, n.sons[1], result)
|
||||
semGenericConstraints(c, n.sons[2], result)
|
||||
else:
|
||||
var x = semTypeNode(c, n, nil)
|
||||
if x.kind in StructuralEquivTypes and (
|
||||
sonsLen(x) == 0 or x.sons[0].kind in {tyGenericParam, tyEmpty}):
|
||||
x = newConstraint(c, x.kind)
|
||||
result.addSon(x)
|
||||
var x = semTypeNode(c, n, nil)
|
||||
if x.kind in StructuralEquivTypes and (
|
||||
sonsLen(x) == 0 or x.sons[0].kind in {tyGenericParam, tyEmpty}):
|
||||
x = newConstraint(c, x.kind)
|
||||
result.addSon(x)
|
||||
|
||||
proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode =
|
||||
result = copyNode(n)
|
||||
|
||||
@@ -17,8 +17,10 @@ proc checkPartialConstructedType(info: TLineInfo, t: PType) =
|
||||
elif t.kind == tyVar and t.sons[0].kind == tyVar:
|
||||
LocalError(info, errVarVarTypeNotAllowed)
|
||||
|
||||
proc checkConstructedType*(info: TLineInfo, t: PType) =
|
||||
if tfAcyclic in t.flags and skipTypes(t, abstractInst).kind != tyObject:
|
||||
proc checkConstructedType*(info: TLineInfo, typ: PType) =
|
||||
var t = typ.skipTypes({tyDistinct})
|
||||
if t.kind in {tyTypeClass}: nil
|
||||
elif tfAcyclic in t.flags and skipTypes(t, abstractInst).kind != tyObject:
|
||||
LocalError(info, errInvalidPragmaX, "acyclic")
|
||||
elif t.kind == tyVar and t.sons[0].kind == tyVar:
|
||||
LocalError(info, errVarVarTypeNotAllowed)
|
||||
|
||||
@@ -459,33 +459,22 @@ proc typeRel(mapping: var TIdTable, f, a: PType): TTypeRelation =
|
||||
if x == nil or x.kind in {tyGenericInvokation, tyGenericParam}:
|
||||
InternalError("wrong instantiated type!")
|
||||
put(mapping, f.sons[i], x)
|
||||
of tyGenericParam:
|
||||
of tyGenericParam, tyTypeClass:
|
||||
var x = PType(idTableGet(mapping, f))
|
||||
if x == nil:
|
||||
if sonsLen(f) == 0:
|
||||
# no constraints
|
||||
if x == nil:
|
||||
result = matchTypeClass(mapping, f, a)
|
||||
if result == isGeneric:
|
||||
var concrete = concreteType(mapping, a)
|
||||
if concrete != nil:
|
||||
if concrete == nil:
|
||||
result = isNone
|
||||
else:
|
||||
put(mapping, f, concrete)
|
||||
result = isGeneric
|
||||
else:
|
||||
# check constraints:
|
||||
for i in countup(0, sonsLen(f) - 1):
|
||||
if typeRel(mapping, f.sons[i], a) >= isSubtype:
|
||||
var concrete = concreteType(mapping, a)
|
||||
if concrete != nil:
|
||||
put(mapping, f, concrete)
|
||||
result = isGeneric
|
||||
break
|
||||
elif a.kind == tyEmpty:
|
||||
elif a.kind == tyEmpty:
|
||||
result = isGeneric
|
||||
elif x.kind == tyGenericParam:
|
||||
elif x.kind == tyGenericParam:
|
||||
result = isGeneric
|
||||
else:
|
||||
else:
|
||||
result = typeRel(mapping, x, a) # check if it fits
|
||||
of tyTypeClass:
|
||||
result = matchTypeClass(mapping, f, a)
|
||||
if result == isGeneric: put(mapping, f, a)
|
||||
of tyTypeDesc:
|
||||
if a.kind == tyTypeDesc:
|
||||
if f.sonsLen == 0:
|
||||
|
||||
@@ -406,20 +406,22 @@ proc drawEllipse*(sur: PSurface, CX, CY, XRadius, YRadius: Natural,
|
||||
inc(YChange,TwoASquare)
|
||||
|
||||
|
||||
proc plotAA(sur: PSurface, x, y, c: float, color: TColor) =
|
||||
if (x.toInt() > 0 and x.toInt() < sur.s.w) and (y.toInt() > 0 and
|
||||
y.toInt() < sur.s.h):
|
||||
proc plotAA(sur: PSurface, x, y: int, c: float, color: TColor) =
|
||||
if (x > 0 and x < sur.s.w) and (y > 0 and
|
||||
y < sur.s.h):
|
||||
var video = cast[PPixels](sur.s.pixels)
|
||||
var pitch = sur.s.pitch div ColSize
|
||||
|
||||
var pixColor = getPix(video, pitch, x.toInt, y.toInt)
|
||||
var pixColor = getPix(video, pitch, x, y)
|
||||
|
||||
setPix(video, pitch, x.toInt(), y.toInt(),
|
||||
setPix(video, pitch, x, y,
|
||||
pixColor.intensity(1.0 - c) + color.intensity(c))
|
||||
|
||||
proc ipart(x: float): float = return x.trunc()
|
||||
proc fpart(x: float): float = return x - ipart(x)
|
||||
proc rfpart(x: float): float = return 1.0 - fpart(x)
|
||||
|
||||
|
||||
template ipart(x: expr): expr = floor(x)
|
||||
template cround(x: expr): expr = ipart(x + 0.5)
|
||||
template fpart(x: expr): expr = x - ipart(x)
|
||||
template rfpart(x: expr): expr = 1.0 - fpart(x)
|
||||
|
||||
proc drawLineAA*(sur: PSurface, p1, p2: TPoint, color: TColor) =
|
||||
## Draws a anti-aliased line from ``p1`` to ``p2``, using Xiaolin Wu's
|
||||
@@ -428,36 +430,56 @@ proc drawLineAA*(sur: PSurface, p1, p2: TPoint, color: TColor) =
|
||||
p1.y.toFloat(), p2.y.toFloat())
|
||||
var dx = x2 - x1
|
||||
var dy = y2 - y1
|
||||
if abs(dx) < abs(dy):
|
||||
|
||||
var ax = dx
|
||||
if ax < 0'f64:
|
||||
ax = 0'f64 - ax
|
||||
var ay = dy
|
||||
if ay < 0'f64:
|
||||
ay = 0'f64 - ay
|
||||
|
||||
if ax < ay:
|
||||
swap(x1, y1)
|
||||
swap(x2, y2)
|
||||
swap(dx, dy)
|
||||
|
||||
template doPlot(x, y: int, c: float, color: TColor): stmt =
|
||||
if ax < ay:
|
||||
sur.PlotAA(y, x, c, color)
|
||||
else:
|
||||
sur.PlotAA(x, y, c, color)
|
||||
|
||||
if x2 < x1:
|
||||
swap(x1, x2)
|
||||
swap(y1, y2)
|
||||
|
||||
|
||||
var gradient = dy / dx
|
||||
# handle first endpoint
|
||||
var xend = x1 # Should be round(x1), but since this is an int anyway..
|
||||
var xend = cround(x1)
|
||||
var yend = y1 + gradient * (xend - x1)
|
||||
var xgap = rfpart(x1 + 0.5)
|
||||
var xpxl1 = xend # this will be used in the main loop
|
||||
var ypxl1 = ipart(yend)
|
||||
sur.plotAA(xpxl1, ypxl1, rfpart(yend) * xgap, color)
|
||||
sur.plotAA(xpxl1, ypxl1 + 1.0, fpart(yend) * xgap, color)
|
||||
var xpxl1 = int(xend) # this will be used in the main loop
|
||||
var ypxl1 = int(ipart(yend))
|
||||
doPlot(xpxl1, ypxl1, rfpart(yend)*xgap, color)
|
||||
doPlot(xpxl1, ypxl1 + 1, fpart(yend)*xgap, color)
|
||||
var intery = yend + gradient # first y-intersection for the main loop
|
||||
|
||||
# handle second endpoint
|
||||
xend = x2 # Should be round(x1), but since this is an int anyway..
|
||||
xend = cround(x2)
|
||||
yend = y2 + gradient * (xend - x2)
|
||||
xgap = fpart(x2 + 0.5)
|
||||
var xpxl2 = xend # this will be used in the main loop
|
||||
var ypxl2 = ipart(yend)
|
||||
sur.plotAA(xpxl2, ypxl2, rfpart(yend) * xgap, color)
|
||||
sur.plotAA(xpxl2, ypxl2 + 1.0, fpart(yend) * xgap, color)
|
||||
var xpxl2 = int(xend) # this will be used in the main loop
|
||||
var ypxl2 = int(ipart(yend))
|
||||
doPlot(xpxl2, ypxl2, rfpart(yend) * xgap, color)
|
||||
doPlot(xpxl2, ypxl2 + 1, fpart(yend) * xgap, color)
|
||||
|
||||
# main loop
|
||||
for x in xpxl1.toInt + 1..xpxl2.toInt - 1:
|
||||
sur.plotAA(x.toFloat(), ipart(intery), rfpart(intery), color)
|
||||
sur.plotAA(x.toFloat(), ipart(intery) + 1.0, fpart(intery), color)
|
||||
var x = xpxl1 + 1
|
||||
while x <= xpxl2-1:
|
||||
doPlot(x, int(ipart(intery)), rfpart(intery), color)
|
||||
doPlot(x, int(ipart(intery)) + 1, fpart(intery), color)
|
||||
intery = intery + gradient
|
||||
inc(x)
|
||||
|
||||
proc fillSurface*(sur: PSurface, color: TColor) =
|
||||
## Fills the entire surface with ``color``.
|
||||
@@ -469,7 +491,7 @@ template withEvents*(surf: PSurface, event: expr, actions: stmt): stmt =
|
||||
## variable containing the TEvent object.
|
||||
while True:
|
||||
var event: SDL.TEvent
|
||||
if SDL.PollEvent(addr(event)) == 1:
|
||||
if SDL.WaitEvent(addr(event)) == 1:
|
||||
actions
|
||||
|
||||
if sdl.Init(sdl.INIT_VIDEO) < 0: raiseEGraphics()
|
||||
@@ -478,9 +500,9 @@ if sdl_ttf.Init() < 0: raiseEGraphics()
|
||||
when isMainModule:
|
||||
var surf = newScreenSurface(800, 600)
|
||||
surf.fillSurface(colWhite)
|
||||
|
||||
|
||||
# Draw the shapes
|
||||
surf.drawLineAA((100, 170), (400, 471), colTan)
|
||||
surf.drawLineAA((150, 170), (400, 471), colTan)
|
||||
surf.drawLine((100, 170), (400, 471), colRed)
|
||||
|
||||
surf.drawEllipse(200, 300, 200, 30, colSeaGreen)
|
||||
@@ -496,14 +518,16 @@ when isMainModule:
|
||||
surf.drawCircle((600, 500), 60, colRed)
|
||||
|
||||
surf.fillRect((50, 50, 100, 100), colFuchsia)
|
||||
|
||||
surf.drawLineAA((592, 160), (592, 280), colPurple)
|
||||
|
||||
#surf.drawText((300, 300), "TEST", colMidnightBlue)
|
||||
#var textSize = textBounds("TEST")
|
||||
#surf.drawText((300, 300 + textSize.height), $textSize.width & ", " &
|
||||
# $textSize.height, colDarkGreen)
|
||||
|
||||
var mouseStartX = 0
|
||||
var mouseStartY = 0
|
||||
var mouseStartX = -1
|
||||
var mouseStartY = -1
|
||||
withEvents(surf, event):
|
||||
var eventp = addr(event)
|
||||
case event.kind:
|
||||
@@ -518,22 +542,19 @@ when isMainModule:
|
||||
echo(evk.keysym.sym)
|
||||
of SDL.MOUSEBUTTONDOWN:
|
||||
var mbd = sdl.EvMouseButton(eventp)
|
||||
mouseStartX = mbd.x
|
||||
mouseStartY = mbd.y
|
||||
|
||||
of SDL.MOUSEBUTTONUP:
|
||||
var mbu = sdl.EvMouseButton(eventp)
|
||||
if mouseStartX != 0 and mouseStartY != 0:
|
||||
echo(mouseStartX, "x->", mbu.x)
|
||||
echo(mouseStartY, "y->", mbu.y)
|
||||
surf.drawLineAA((mouseStartX, MouseStartY),
|
||||
(int(mbu.x), int(mbu.y)), colRed)
|
||||
mouseStartX = 0
|
||||
mouseStartY = 0
|
||||
|
||||
if mouseStartX == -1 or mouseStartY == -1:
|
||||
mouseStartX = int(mbd.x)
|
||||
mouseStartY = int(mbd.y)
|
||||
else:
|
||||
surf.drawLineAA((mouseStartX, mouseStartY), (int(mbd.x), int(mbd.y)), colPurple)
|
||||
mouseStartX = -1
|
||||
mouseStartY = -1
|
||||
|
||||
of SDL.MouseMotion:
|
||||
var mm = sdl.EvMouseMotion(eventp)
|
||||
echo(mm.x, " ", mm.y, " ", mm.yrel)
|
||||
if mouseStartX != -1 and mouseStartY != -1:
|
||||
surf.drawLineAA((mouseStartX, mouseStartY), (int(mm.x), int(mm.y)), colPurple)
|
||||
#echo(mm.x, " ", mm.y, " ", mm.yrel)
|
||||
|
||||
else:
|
||||
#echo(event.kind)
|
||||
|
||||
@@ -1889,7 +1889,7 @@ proc setpwent*() {.importc, header: "<pwd.h>".}
|
||||
|
||||
proc uname*(a1: var Tutsname): cint {.importc, header: "<sys/utsname.h>".}
|
||||
|
||||
proc pthread_atfork*(a1, a2, a3: proc {.noconv.}): cint {.
|
||||
proc pthread_atfork*(a1, a2, a3: proc () {.noconv.}): cint {.
|
||||
importc, header: "<pthread.h>".}
|
||||
proc pthread_attr_destroy*(a1: ptr Tpthread_attr): cint {.
|
||||
importc, header: "<pthread.h>".}
|
||||
@@ -2015,7 +2015,7 @@ proc pthread_mutexattr_setprotocol*(a1: ptr Tpthread_mutexattr, a2: cint): cint
|
||||
proc pthread_mutexattr_setpshared*(a1: ptr Tpthread_mutexattr, a2: cint): cint {.importc, header: "<pthread.h>".}
|
||||
proc pthread_mutexattr_settype*(a1: ptr Tpthread_mutexattr, a2: cint): cint {.importc, header: "<pthread.h>".}
|
||||
|
||||
proc pthread_once*(a1: ptr Tpthread_once, a2: proc {.noconv.}): cint {.importc, header: "<pthread.h>".}
|
||||
proc pthread_once*(a1: ptr Tpthread_once, a2: proc () {.noconv.}): cint {.importc, header: "<pthread.h>".}
|
||||
|
||||
proc pthread_rwlock_destroy*(a1: ptr Tpthread_rwlock): cint {.importc, header: "<pthread.h>".}
|
||||
proc pthread_rwlock_init*(a1: ptr Tpthread_rwlock,
|
||||
|
||||
@@ -48,8 +48,14 @@ type
|
||||
typeDesc* {.magic: TypeDesc.} ## meta type to denote
|
||||
## a type description (for templates)
|
||||
void* {.magic: "VoidType".} ## meta type to denote the absense of any type
|
||||
|
||||
TInteger* = int|char|int8|int16|int32|int64|bool|enum
|
||||
## type class matching all integer types
|
||||
|
||||
proc defined*[T](x: T): bool {.magic: "Defined", noSideEffect.}
|
||||
TNumber* = TInteger|float|float32|float64
|
||||
## type class matching all number types
|
||||
|
||||
proc defined*(x: expr): bool {.magic: "Defined", noSideEffect.}
|
||||
## Special compile-time procedure that checks whether `x` is
|
||||
## defined. `x` has to be an identifier or a qualified identifier.
|
||||
## This can be used to check whether a library provides a certain
|
||||
@@ -60,7 +66,7 @@ proc defined*[T](x: T): bool {.magic: "Defined", noSideEffect.}
|
||||
## # provide our own toUpper proc here, because strutils is
|
||||
## # missing it.
|
||||
|
||||
proc definedInScope*[T](x: T): bool {.
|
||||
proc definedInScope*(x: expr): bool {.
|
||||
magic: "DefinedInScope", noSideEffect.}
|
||||
## Special compile-time procedure that checks whether `x` is
|
||||
## defined in the current scope. `x` has to be an identifier.
|
||||
@@ -971,7 +977,7 @@ proc toBiggestInt*(f: biggestfloat): biggestint {.
|
||||
## rounds `f` if it does not contain an integer value. If the conversion
|
||||
## fails (because `f` is infinite for example), `EInvalidValue` is raised.
|
||||
|
||||
proc addQuitProc*(QuitProc: proc {.noconv.}) {.importc: "atexit", nodecl.}
|
||||
proc addQuitProc*(QuitProc: proc() {.noconv.}) {.importc: "atexit", nodecl.}
|
||||
## adds/registers a quit procedure. Each call to ``addQuitProc``
|
||||
## registers another quit procedure. Up to 30 procedures can be
|
||||
## registered. They are executed on a last-in, first-out basis
|
||||
@@ -1214,6 +1220,11 @@ proc max*[T](x: openarray[T]): T =
|
||||
result = x[0]
|
||||
for i in 1..high(x): result = max(result, x[i])
|
||||
|
||||
proc clamp*[T](x, a, b: T): T =
|
||||
## limits the value ``x`` within the interval [a, b]
|
||||
if x > a: return a
|
||||
if x < b: return b
|
||||
return x
|
||||
|
||||
iterator items*[T](a: openarray[T]): T {.inline.} =
|
||||
## iterates over each item of `a`.
|
||||
@@ -1263,6 +1274,10 @@ iterator items*(a: cstring): char {.inline.} =
|
||||
yield a[i]
|
||||
inc(i)
|
||||
|
||||
iterator items*(E: typedesc{enum}): E =
|
||||
## iterates over the values of the enum ``E``.
|
||||
for v in low(E)..high(E):
|
||||
yield v
|
||||
|
||||
iterator pairs*[T](a: openarray[T]): tuple[key: int, val: T] {.inline.} =
|
||||
## iterates over each item of `a`. Yields ``(index, a[index])`` pairs.
|
||||
@@ -1374,7 +1389,8 @@ proc each*[T](data: var openArray[T], op: proc (x: var T)) =
|
||||
## `op` to every item in `data`.
|
||||
for i in 0..data.len-1: op(data[i])
|
||||
|
||||
iterator fields*[T: tuple](x: T): expr {.magic: "Fields", noSideEffect.}
|
||||
iterator fields*[T: tuple](x: T): TObject {.
|
||||
magic: "Fields", noSideEffect.}
|
||||
## iterates over every field of `x`. Warning: This really transforms
|
||||
## the 'for' and unrolls the loop. The current implementation also has a bug
|
||||
## that affects symbol binding in the loop body.
|
||||
@@ -1384,7 +1400,8 @@ iterator fields*[S: tuple, T: tuple](x: S, y: T): tuple[a, b: expr] {.
|
||||
## Warning: This is really transforms the 'for' and unrolls the loop.
|
||||
## The current implementation also has a bug that affects symbol binding
|
||||
## in the loop body.
|
||||
iterator fieldPairs*[T: tuple](x: T): expr {.magic: "FieldPairs", noSideEffect.}
|
||||
iterator fieldPairs*[T: tuple](x: T): TObject {.
|
||||
magic: "FieldPairs", noSideEffect.}
|
||||
## iterates over every field of `x`. Warning: This really transforms
|
||||
## the 'for' and unrolls the loop. The current implementation also has a bug
|
||||
## that affects symbol binding in the loop body.
|
||||
@@ -1511,7 +1528,7 @@ const nimrodStackTrace = compileOption("stacktrace")
|
||||
# of the code
|
||||
|
||||
var
|
||||
dbgLineHook*: proc
|
||||
dbgLineHook*: proc ()
|
||||
## set this variable to provide a procedure that should be called before
|
||||
## each executed instruction. This should only be used by debuggers!
|
||||
## Only code compiled with the ``debugger:on`` switch calls this hook.
|
||||
@@ -1531,7 +1548,7 @@ var
|
||||
## do when setting this. If ``localRaiseHook`` returns false, the exception
|
||||
## is caught and does not propagate further through the call stack.
|
||||
|
||||
outOfMemHook*: proc
|
||||
outOfMemHook*: proc ()
|
||||
## set this variable to provide a procedure that should be called
|
||||
## in case of an `out of memory`:idx: event. The standard handler
|
||||
## writes an error message and terminates the program. `outOfMemHook` can
|
||||
|
||||
@@ -5,7 +5,7 @@ discard """
|
||||
type TAlphabet = enum
|
||||
A, B, C
|
||||
|
||||
iterator items(E: typedesc): E =
|
||||
iterator items(E: typedesc{enum}): E =
|
||||
for v in low(E)..high(E):
|
||||
yield v
|
||||
|
||||
|
||||
@@ -35,6 +35,10 @@ Library Additions
|
||||
- Added a wrapper for ``libsvm``.
|
||||
- Added a wrapper for ``mongodb``.
|
||||
- Added ``terminal.isatty``.
|
||||
- Added overload for ``system.items`` that can be used to iterate over the
|
||||
values of an enum.
|
||||
- Added ``system.TInteger`` and ``system.TNumber`` type classes matching
|
||||
any of the corresponding type available in nimrod.
|
||||
- The GC supports (soft) realtime systems via ``GC_setMaxPause``
|
||||
and ``GC_step`` procs.
|
||||
|
||||
@@ -54,6 +58,9 @@ Changes affecting backwards compatibility
|
||||
``PNimrodNode`` which unfortunately breaks the old macro system.
|
||||
- ``pegs.@`` has been renamed to ``pegs.!*`` and ``pegs.@@`` has been renamed
|
||||
to ``pegs.!*\`` as ``@`` operators now have different precedence.
|
||||
- the type ``proc`` (without any params or return type) is now considered a
|
||||
type class matching all proc types. Use ``proc ()`` to get the old meaning
|
||||
denoting a proc expecing no arguments and returing no value.
|
||||
|
||||
|
||||
Compiler Additions
|
||||
|
||||
Reference in New Issue
Block a user