summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2012-04-21 03:22:53 +0200
committerAraq <rumpf_a@web.de>2012-04-21 03:22:53 +0200
commit7511a05b27e919c61703fea31f8d6d99cb2eae05 (patch)
tree083742a578b22765a324899b9644cedb87298a18
parent4aba7421f57d0f653ef928f012982957404416f9 (diff)
parenta05f0aa6b5d80bb10e1a854b60ed0af6e9f6f234 (diff)
downloadNim-7511a05b27e919c61703fea31f8d6d99cb2eae05.tar.gz
resolved conflict for news.txt
-rwxr-xr-xcompiler/parser.nim111
-rwxr-xr-xcompiler/semtypes.nim149
-rwxr-xr-xcompiler/semtypinst.nim6
-rwxr-xr-xcompiler/sigmatch.nim31
-rwxr-xr-xlib/impure/graphics.nim107
-rwxr-xr-xlib/posix/posix.nim4
-rwxr-xr-xlib/system.nim31
-rw-r--r--tests/run/tenumitems.nim2
-rwxr-xr-xweb/news.txt7
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