summary refs log tree commit diff stats
path: root/tests/showoff
diff options
context:
space:
mode:
Diffstat (limited to 'tests/showoff')
-rw-r--r--tests/showoff/tdrdobbs_examples.nim134
-rw-r--r--tests/showoff/tformatopt.nim57
-rw-r--r--tests/showoff/tgenericmacrotypes.nim55
-rw-r--r--tests/showoff/thello2.nim11
-rw-r--r--tests/showoff/thtml1.nim11
-rw-r--r--tests/showoff/thtml2.nim37
-rw-r--r--tests/showoff/tonce.nim22
-rw-r--r--tests/showoff/tquasiquote.nim14
8 files changed, 341 insertions, 0 deletions
diff --git a/tests/showoff/tdrdobbs_examples.nim b/tests/showoff/tdrdobbs_examples.nim
new file mode 100644
index 000000000..c61e177dc
--- /dev/null
+++ b/tests/showoff/tdrdobbs_examples.nim
@@ -0,0 +1,134 @@
+discard """
+  output: '''108
+11 -1 1936
+0.4
+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: NimNode): NimNode {.compileTime.} =
+  template `@`(current, field: untyped): untyped =
+    newDotExpr(current, newIdentNode(astToStr(field)))
+
+  template `==@`(n, pattern: untyped): untyped =
+    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: untyped): bool =
+  result = matchAgainst(n, pattern)
+
+proc isPolyTerm2(n: Formula): bool = n =~ c * x^c
+
+echo isPolyTerm2(myFormula), isPolyTerm2(Formula(kind: fkLit, value: 0.7))
diff --git a/tests/showoff/tformatopt.nim b/tests/showoff/tformatopt.nim
new file mode 100644
index 000000000..420dd026b
--- /dev/null
+++ b/tests/showoff/tformatopt.nim
@@ -0,0 +1,57 @@
+discard """
+  output: '''(a: 3
+b: 4
+s: abc
+)'''
+"""
+
+import macros
+
+proc invalidFormatString() =
+  echo "invalidFormatString"
+
+template formatImpl(handleChar: untyped) =
+  var i = 0
+  while i < f.len:
+    if f[i] == '$':
+      case f[i+1]
+      of '1'..'9':
+        var j = 0
+        i += 1
+        while f[i] in {'0'..'9'}:
+          j = j * 10 + ord(f[i]) - ord('0')
+          i += 1
+        result.add(a[j-1])
+      else:
+        invalidFormatString()
+    else:
+      result.add(handleChar(f[i]))
+      i += 1
+
+proc `%`*(f: string, a: openArray[string]): string =
+  template identity(x: untyped): untyped = x
+  result = ""
+  formatImpl(identity)
+
+macro optFormat{`%`(f, a)}(f: string{lit}, a: openArray[string]): untyped =
+  result = newNimNode(nnkBracket)
+  let f = f.strVal
+  formatImpl(newLit)
+  result = nestList(newIdentNode("&"), result)
+
+template optAdd1{x = y; add(x, z)}(x, y, z: string) =
+  x = y & z
+
+proc `/&` [T: object](x: T): string =
+  result = "("
+  for name, value in fieldPairs(x):
+    result.add("$1: $2\n" % [name, $value])
+  result.add(")")
+
+type
+  MyObject = object
+    a, b: int
+    s: string
+
+let obj = MyObject(a: 3, b: 4, s: "abc")
+echo(/&obj)
diff --git a/tests/showoff/tgenericmacrotypes.nim b/tests/showoff/tgenericmacrotypes.nim
new file mode 100644
index 000000000..cc07f4355
--- /dev/null
+++ b/tests/showoff/tgenericmacrotypes.nim
@@ -0,0 +1,55 @@
+# issue #7974
+
+import macros
+
+macro genTypeA(arg: typed): untyped =
+  if arg.typeKind != ntyTypeDesc:
+    error("expected typedesc", arg)
+
+  result = arg.getTypeInst[1]
+
+macro genTypeB(arg: typed): untyped =
+  if arg.typeKind != ntyTypeDesc:
+    error("expected typedesc", arg)
+
+
+  let typeSym = arg.getTypeInst[1]
+  result =
+    nnkTupleTy.newTree(
+      nnkIdentDefs.newTree(
+        ident"a", typeSym, newEmptyNode()
+      )
+    )
+
+type
+  # this is the trivial case, MyTypeA[T] is basically just T, nothing else. But it works.
+  MyTypeA[T] = genTypeA(T)
+  # in this case I generate `tuple[a: T]`. This this is something the compiler does not want
+  MyTypeB[T] = genTypeB(T)
+
+# these are just alias types for int32 and float32, nothing really happens, but it works
+var a1: MyTypeA[int32]
+doAssert a1 is MyTypeA[int32]
+doAssert a1 is int32
+a1 = 0'i32
+var a2: MyTypeA[float32]
+doAssert a2 is MyTypeA[float32]
+doAssert a2 is float32
+a2 = 0'f32
+var a3: MyTypeA[float32]
+doAssert a3 is MyTypeA[float32]
+doAssert a3 is float32
+a3 = 0'f32
+
+var b1: MyTypeB[int32]   # cannot generate VM code fur tuple[a: int32]
+doAssert b1 is MyTypeB[int32]
+doAssert b1 is tuple[a: int32]
+b1 = (a: 0'i32)
+var b2: MyTypeB[float32]
+doAssert b2 is MyTypeB[float32]
+doAssert b2 is tuple[a: float32]
+b2 = (a: 0'f32)
+var b3: MyTypeB[float32]
+doAssert b3 is MyTypeB[float32]
+doAssert b3 is tuple[a: float32]
+b3 = (a: 0'f32)
diff --git a/tests/showoff/thello2.nim b/tests/showoff/thello2.nim
new file mode 100644
index 000000000..3ccb4e3be
--- /dev/null
+++ b/tests/showoff/thello2.nim
@@ -0,0 +1,11 @@
+discard """
+  output: '''(a: 3, b: 4, s: "abc")'''
+"""
+
+type
+  MyObject = object
+        a, b: int
+        s: string
+
+let obj = MyObject(a: 3, b: 4, s: "abc")
+echo obj
diff --git a/tests/showoff/thtml1.nim b/tests/showoff/thtml1.nim
new file mode 100644
index 000000000..fe0cd3b1e
--- /dev/null
+++ b/tests/showoff/thtml1.nim
@@ -0,0 +1,11 @@
+discard """
+  output: "<br>"
+"""
+
+template htmlTag(tag: untyped) =
+  proc tag(): string = "<" & astToStr(tag) & ">"
+
+htmlTag(br)
+htmlTag(html)
+
+echo br()
diff --git a/tests/showoff/thtml2.nim b/tests/showoff/thtml2.nim
new file mode 100644
index 000000000..dcf6534a5
--- /dev/null
+++ b/tests/showoff/thtml2.nim
@@ -0,0 +1,37 @@
+discard """
+  output: "<html><head><title>now look at this</title></head><body><ul><li>Nim is quite capable</li></ul></body></html>"
+"""
+
+import strutils
+
+template html(name, matter: untyped) =
+  proc name(): string =
+    result = "<html>"
+    matter
+    result.add("</html>")
+
+template nestedTag(tag: untyped) =
+  template tag(matter: untyped) =
+    result.add("<" & astToStr(tag) & ">")
+    matter
+    result.add("</" & astToStr(tag) & ">")
+
+template simpleTag(tag: untyped) =
+  template tag(matter: untyped) =
+    result.add("<$1>$2</$1>" % [astToStr(tag), matter])
+
+nestedTag body
+nestedTag head
+nestedTag ul
+simpleTag title
+simpleTag li
+
+
+html mainPage:
+  head:
+    title "now look at this"
+  body:
+    ul:
+      li "Nim is quite capable"
+
+echo mainPage()
diff --git a/tests/showoff/tonce.nim b/tests/showoff/tonce.nim
new file mode 100644
index 000000000..ed2684dcf
--- /dev/null
+++ b/tests/showoff/tonce.nim
@@ -0,0 +1,22 @@
+discard """
+  output: '''first call of p
+some call of p
+new instantiation
+some call of p'''
+"""
+
+template once(body) =
+  var x {.global.} = false
+  if not x:
+    x = true
+    body
+
+proc p() =
+  once:
+    echo "first call of p"
+  echo "some call of p"
+
+p()
+once:
+  echo "new instantiation"
+p()
diff --git a/tests/showoff/tquasiquote.nim b/tests/showoff/tquasiquote.nim
new file mode 100644
index 000000000..404712a02
--- /dev/null
+++ b/tests/showoff/tquasiquote.nim
@@ -0,0 +1,14 @@
+discard """
+  outputsub: '''tquasiquote.nim(14, 8): Check failed: 1 > 2'''
+"""
+
+import macros
+
+macro check(ex: untyped): untyped =
+  var info = ex.lineInfo
+  var expString = ex.toStrLit
+  result = quote do:
+    if not `ex`:
+      echo `info`, ": Check failed: ", `expString`
+
+check 1 > 2