summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2013-11-29 20:42:12 +0100
committerAraq <rumpf_a@web.de>2013-11-29 20:42:12 +0100
commit2dcbc6493a8bcebc7dc9364b4a834853e1263639 (patch)
tree1ec88f7165d73164481337e36aca8d6529f0c261
parentf10a23e669cb6f17098b3d38c6bb5236ff91f9e9 (diff)
downloadNim-2dcbc6493a8bcebc7dc9364b4a834853e1263639.tar.gz
fixes #686
-rw-r--r--compiler/sem.nim30
-rw-r--r--compiler/semexprs.nim14
-rw-r--r--tests/compile/tgeneric.nim8
-rw-r--r--tests/run/tdrdobbs_examples.nim134
4 files changed, 166 insertions, 20 deletions
diff --git a/compiler/sem.nim b/compiler/sem.nim
index ea53afbeb..eda444252 100644
--- a/compiler/sem.nim
+++ b/compiler/sem.nim
@@ -140,26 +140,27 @@ proc IsOpImpl(c: PContext, n: PNode): PNode
 proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym,
                   semCheck: bool = true): PNode
 
-proc symFromType(t: PType, info: TLineInfo): PSym =
-  if t.sym != nil: return t.sym
-  result = newSym(skType, getIdent"AnonType", t.owner, info)
-  result.flags.incl sfAnon
-  result.typ = t
+when false:
+  proc symFromType(t: PType, info: TLineInfo): PSym =
+    if t.sym != nil: return t.sym
+    result = newSym(skType, getIdent"AnonType", t.owner, info)
+    result.flags.incl sfAnon
+    result.typ = t
 
-proc symNodeFromType(c: PContext, t: PType, info: TLineInfo): PNode =
-  result = newSymNode(symFromType(t, info), info)
-  result.typ = makeTypeDesc(c, t)
+  proc symNodeFromType(c: PContext, t: PType, info: TLineInfo): PNode =
+    result = newSymNode(symFromType(t, info), info)
+    result.typ = makeTypeDesc(c, t)
 
 proc createEvalContext(c: PContext, mode: TEvalMode): PEvalContext =
   result = newEvalContext(c.module, mode)
   result.getType = proc (n: PNode): PNode =
-    var e = tryExpr(c, n)
-    if e == nil:
-      result = symNodeFromType(c, errorType(c), n.info)
-    elif e.typ == nil:
+    result = tryExpr(c, n)
+    if result == nil:
+      result = newSymNode(errorSym(c, n))
+    elif result.typ == nil:
       result = newSymNode(getSysSym"void")
     else:
-      result = symNodeFromType(c, e.typ, n.info)
+      result.typ = makeTypeDesc(c, result.typ)
 
   result.handleIsOperator = proc (n: PNode): PNode =
     result = IsOpImpl(c, n)
@@ -210,7 +211,8 @@ proc semAfterMacroCall(c: PContext, n: PNode, s: PSym): PNode =
     of tyTypeDesc:
       if n.kind == nkStmtList: result.kind = nkStmtListType
       var typ = semTypeNode(c, result, nil)
-      result = symNodeFromType(c, typ, n.info)
+      result.typ = makeTypeDesc(c, typ)
+      #result = symNodeFromType(c, typ, n.info)
     else:
       result = semExpr(c, result)
       result = fitNode(c, s.typ.sons[0], result)
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index 337224aef..775d4e7a0 100644
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -191,7 +191,7 @@ proc isCastable(dst, src: PType): bool =
 proc isSymChoice(n: PNode): bool {.inline.} =
   result = n.kind in nkSymChoices
 
-proc semConv(c: PContext, n: PNode, s: PSym): PNode =
+proc semConv(c: PContext, n: PNode): PNode =
   if sonsLen(n) != 2:
     LocalError(n.info, errConvNeedsOneArg)
     return n
@@ -738,8 +738,7 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
   elif t != nil and t.kind == tyTypeDesc:
     if n.len == 1: return semObjConstr(c, n, flags)
     let destType = t.skipTypes({tyTypeDesc, tyGenericInst})
-    result = semConv(c, n, symFromType(destType, n.info))
-    return
+    return semConv(c, n)
   else:
     result = overloadedCallOpr(c, n)
     # Now that nkSym does not imply an iteration over the proc/iterator space,
@@ -1048,7 +1047,9 @@ proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode =
     # The result so far is a tyTypeDesc bound 
     # a tyGenericBody. The line below will substitute
     # it with the instantiated type.
-    result = symNodeFromType(c, semTypeNode(c, n, nil), n.info)
+    result = n
+    result.typ = makeTypeDesc(c, semTypeNode(c, n, nil))
+    #result = symNodeFromType(c, semTypeNode(c, n, nil), n.info)
   of tyTuple: 
     checkSonsLen(n, 2)
     n.sons[0] = makeDeref(n.sons[0])
@@ -1883,7 +1884,8 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
     result = semExpr(c, n.sons[0], flags)
   of nkTypeOfExpr, nkTupleTy, nkRefTy..nkEnumTy:
     var typ = semTypeNode(c, n, nil).skipTypes({tyTypeDesc})
-    result = symNodeFromType(c, typ, n.info)
+    result.typ = makeTypeDesc(c, typ)
+    #result = symNodeFromType(c, typ, n.info)
   of nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand, nkCallStrLit: 
     # check if it is an expression macro:
     checkMinSonsLen(n, 1)
@@ -1906,7 +1908,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
       of skType:
         # XXX think about this more (``set`` procs)
         if n.len == 2:
-          result = semConv(c, n, s)
+          result = semConv(c, n)
         elif n.len == 1:
           result = semObjConstr(c, n, flags)
         elif Contains(c.AmbiguousSymbols, s.id): 
diff --git a/tests/compile/tgeneric.nim b/tests/compile/tgeneric.nim
index 8bda15c42..9292b729f 100644
--- a/tests/compile/tgeneric.nim
+++ b/tests/compile/tgeneric.nim
@@ -8,4 +8,12 @@ proc foo(models: seq[TTable[string, float]]): seq[float] =
   for model in models.items:
     result.add model["foobar"]
 
+# bug #686
+type TType[T; A] = array[A, T]
+
+proc foo[T](p: TType[T, range[0..1]]) =
+  echo "foo"
+proc foo[T](p: TType[T, range[0..2]]) =
+  echo "bar"
+
 
diff --git a/tests/run/tdrdobbs_examples.nim b/tests/run/tdrdobbs_examples.nim
new file mode 100644
index 000000000..d1e0585d2
--- /dev/null
+++ b/tests/run/tdrdobbs_examples.nim
@@ -0,0 +1,134 @@
+discard """
+  output: '''108
+11 -1 1936
+4.000000000000002-e001
+true
+truefalse'''
+"""
+
+proc `++`(x: var int; y: int = 1; z: int = 0) =
+  x = x + y + z
+
+var g = 70
+++g
+g ++ 7
+g.`++`(10, 20)
+echo g 
+
+
+#let lv = stdin.readline
+#var vv = stdin.readline
+#vv = "abc" # valid, reassignment allowed
+#lv = "abc" # fails at compile time
+
+#proc square(x: int): int = x*x
+
+template square(x: int): int =
+  # ensure 'x' is only evaluated once:
+  let y = x
+  y * y
+
+proc mostSignificantBit(n: int): int =
+  # naive algorithm:
+  var n = n
+  while n != 0:
+    n = n shr 1
+    result += 1
+  result -= 1
+
+const msb3999 = mostSignificantBit(3999)
+
+echo msb3999, " ", mostSignificantBit(0), " ", square(44)
+
+proc filter[T](a: openarray[T], predicate: proc (x: T): bool): seq[T] =
+  result = @[] # @[] constructs the empty seq
+  for x in a:
+    if predicate(x): result.add(x)
+
+proc map[T, S](a: openarray[T], fn: proc (x: T): S): seq[S] =
+  newSeq(result, a.len)
+  for i in 0 .. <a.len: result[i] = fn(a[i])
+
+
+type
+  FormulaKind = enum
+    fkVar,        ## element is a variable like 'X'
+    fkLit,        ## element is a literal like 0.1
+    fkAdd,        ## element is an addition operation
+    fkMul,        ## element is a multiplication operation
+    fkExp         ## element is an exponentiation operation 
+
+type
+  Formula = ref object
+    case kind: FormulaKind
+    of fkVar: name: string
+    of fkLit: value: float
+    of fkAdd, fkMul, fkExp: left, right: Formula
+
+from math import pow
+
+proc evaluate(n: Formula, varToVal: proc (name: string): float): float =
+  case n.kind
+  of fkVar: varToVal(n.name)
+  of fkLit: n.value
+  of fkAdd: evaluate(n.left, varToVal) + evaluate(n.right, varToVal)
+  of fkMul: evaluate(n.left, varToVal) * evaluate(n.right, varToVal)
+  of fkExp: pow(evaluate(n.left, varToVal), evaluate(n.right, varToVal))
+
+echo evaluate(Formula(kind: fkLit, value: 0.4), nil)
+
+proc isPolyTerm(n: Formula): bool =
+  n.kind == fkMul and n.left.kind == fkLit and (let e = n.right; 
+    e.kind == fkExp and e.left.kind == fkVar and e.right.kind == fkLit)
+
+proc isPolynomial(n: Formula): bool =
+  isPolyTerm(n) or 
+    (n.kind == fkAdd and isPolynomial(n.left) and isPolynomial(n.right))
+
+let myFormula = Formula(kind: fkMul,
+                        left: Formula(kind: fkLit, value: 2.0),
+                        right: Formula(kind: fkExp, 
+                          left: Formula(kind: fkVar, name: "x"),
+                          right: Formula(kind: fkLit, value: 5.0)))
+
+echo isPolyTerm(myFormula)
+
+proc pat2kind(pattern: string): FormulaKind =
+  case pattern
+  of "^": fkExp
+  of "*": fkMul
+  of "+": fkAdd
+  of "x": fkVar
+  of "c": fkLit
+  else:   fkVar # no error reporting for reasons of simplicity
+
+import macros
+
+proc matchAgainst(n, pattern: PNimrodNode): PNimrodNode {.compileTime.} =
+  template `@`(current, field: expr): expr =
+    newDotExpr(current, newIdentNode(astToStr(field)))
+
+  template `==@`(n, pattern: expr): expr =
+    newCall("==", n@kind, newIdentNode($pat2kind($pattern.ident)))
+
+  case pattern.kind
+  of CallNodes:
+    result = newCall("and",
+      n ==@ pattern[0],
+      matchAgainst(n@left, pattern[1]))
+    if pattern.len == 3:
+      result = newCall("and", result.copy,
+        matchAgainst(n@right, pattern[2]))
+  of nnkIdent:
+    result = n ==@ pattern
+  of nnkPar:
+    result = matchAgainst(n, pattern[0])
+  else:
+    error "invalid pattern"
+
+macro `=~` (n: Formula, pattern: expr): bool =
+  result = matchAgainst(n, pattern)
+
+proc isPolyTerm2(n: Formula): bool = n =~ c * x^c
+
+echo isPolyTerm2(myFormula), isPolyTerm2(Formula(kind: fkLit, value: 0.7))