diff options
author | Araq <rumpf_a@web.de> | 2012-04-21 03:22:53 +0200 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2012-04-21 03:22:53 +0200 |
commit | 7511a05b27e919c61703fea31f8d6d99cb2eae05 (patch) | |
tree | 083742a578b22765a324899b9644cedb87298a18 | |
parent | 4aba7421f57d0f653ef928f012982957404416f9 (diff) | |
parent | a05f0aa6b5d80bb10e1a854b60ed0af6e9f6f234 (diff) | |
download | Nim-7511a05b27e919c61703fea31f8d6d99cb2eae05.tar.gz |
resolved conflict for news.txt
-rwxr-xr-x | compiler/parser.nim | 111 | ||||
-rwxr-xr-x | compiler/semtypes.nim | 149 | ||||
-rwxr-xr-x | compiler/semtypinst.nim | 6 | ||||
-rwxr-xr-x | compiler/sigmatch.nim | 31 | ||||
-rwxr-xr-x | lib/impure/graphics.nim | 107 | ||||
-rwxr-xr-x | lib/posix/posix.nim | 4 | ||||
-rwxr-xr-x | lib/system.nim | 31 | ||||
-rw-r--r-- | tests/run/tenumitems.nim | 2 | ||||
-rwxr-xr-x | web/news.txt | 7 |
9 files changed, 244 insertions, 204 deletions
diff --git a/compiler/parser.nim b/compiler/parser.nim index 78e5b2455..78e39bcd2 100755 --- a/compiler/parser.nim +++ b/compiler/parser.nim @@ -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) diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index b9bab5da6..f9420d410 100755 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -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) diff --git a/compiler/semtypinst.nim b/compiler/semtypinst.nim index 0c44205de..bfd706bea 100755 --- a/compiler/semtypinst.nim +++ b/compiler/semtypinst.nim @@ -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) diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index da804c2cb..9881e84a3 100755 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -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: diff --git a/lib/impure/graphics.nim b/lib/impure/graphics.nim index aa4d08dd8..9ddb69768 100755 --- a/lib/impure/graphics.nim +++ b/lib/impure/graphics.nim @@ -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) diff --git a/lib/posix/posix.nim b/lib/posix/posix.nim index f8d49ddb4..ca29f5fcc 100755 --- a/lib/posix/posix.nim +++ b/lib/posix/posix.nim @@ -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, diff --git a/lib/system.nim b/lib/system.nim index 9a00979d5..128ec921c 100755 --- a/lib/system.nim +++ b/lib/system.nim @@ -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 + + TNumber* = TInteger|float|float32|float64 + ## type class matching all number types -proc defined*[T](x: T): bool {.magic: "Defined", noSideEffect.} +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 diff --git a/tests/run/tenumitems.nim b/tests/run/tenumitems.nim index 516839fb3..f4f04e2c0 100644 --- a/tests/run/tenumitems.nim +++ b/tests/run/tenumitems.nim @@ -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 diff --git a/web/news.txt b/web/news.txt index 1a1c5fe3b..a1816d474 100755 --- a/web/news.txt +++ b/web/news.txt @@ -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 |