summary refs log tree commit diff stats
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rwxr-xr-xtests/accept/compile/tdumpast.nim39
-rw-r--r--tests/accept/run/tstringinterp.nim71
-rw-r--r--tests/accept/run/tusingstatement.nim102
3 files changed, 191 insertions, 21 deletions
diff --git a/tests/accept/compile/tdumpast.nim b/tests/accept/compile/tdumpast.nim
index fb31af0ec..8561c6e42 100755
--- a/tests/accept/compile/tdumpast.nim
+++ b/tests/accept/compile/tdumpast.nim
@@ -2,28 +2,26 @@
 
 import macros
 
-proc dumpit(n: PNimrodNode): string {.compileTime.} = 
-  if n == nil: return "nil"
-  result = $n.kind
-  add(result, "(")
-  case n.kind
-  of nnkEmpty: nil # same as nil node in this representation 
-  of nnkNilLit:                  add(result, "nil")
-  of nnkCharLit..nnkInt64Lit:    add(result, $n.intVal)
-  of nnkFloatLit..nnkFloat64Lit: add(result, $n.floatVal)
-  of nnkStrLit..nnkTripleStrLit: add(result, $n.strVal)
-  of nnkIdent:                   add(result, $n.ident)
-  of nnkSym, nnkNone:            assert false
-  else:
-    add(result, dumpit(n[0]))
-    for j in 1..n.len-1:
-      add(result, ", ")
-      add(result, dumpit(n[j]))
-  add(result, ")")
+template plus(a, b: expr): expr =
+  a + b
+
+macro call(e: expr): expr =
+  return newCall("foo", newStrLitNode("bar"))
   
-macro dumpAST(n: stmt): stmt = 
+macro dumpAST(n: stmt): stmt =
   # dump AST as a side-effect and return the inner node
-  echo dumpit(n)
+  echo n.prettyPrint
+  echo n.toYaml
+
+  var plusAst = getAst(plus(1, 2))
+  echo plusAst.prettyPrint
+
+  var callAst = getAst(call())
+  echo callAst.prettyPrint
+
+  var e = parseExpr("foo(bar + baz)")
+  echo e.prettyPrint
+
   result = n[1]
   
 dumpAST:
@@ -32,4 +30,3 @@ dumpAST:
   
   proc sub(x, y: int): int = return x - y
 
-
diff --git a/tests/accept/run/tstringinterp.nim b/tests/accept/run/tstringinterp.nim
new file mode 100644
index 000000000..55baae7ec
--- /dev/null
+++ b/tests/accept/run/tstringinterp.nim
@@ -0,0 +1,71 @@
+discard """
+  file: "tstringinterp.nim"
+  output: "Hello Alice, 64 | Hello Bob, 10"
+"""
+
+import macros, parseutils, strutils
+
+proc concat(strings: openarray[string]) : string =
+  result = newString(0)
+  for s in items(strings): result.add(s)
+
+# This will run though the intee
+template ProcessInterpolations(e: expr) =
+  var 
+    s = e[1].strVal
+    
+  for f in interpolatedFragments(s):
+    if f.kind  == ikString:
+      addString(f.value)
+    else:
+      addExpr(f.value)
+
+macro formatStyleInterpolation(e: expr): expr =
+  var 
+    formatString = ""
+    arrayNode = newNimNode(nnkBracket)
+    idx = 1
+
+  proc addString(s: string) =
+    formatString.add(s)
+
+  proc addExpr(e: expr) =
+    arrayNode.add(e)
+    formatString.add("$" & $(idx))
+    inc idx
+    
+  ProcessInterpolations(e)
+
+  result = parseExpr("\"x\" % [y]")
+  result[1].strVal = formatString
+  result[2] = arrayNode
+
+macro concatStyleInterpolation(e: expr): expr =
+  var args : seq[PNimrodNode]
+  newSeq(args, 0)
+
+  proc addString(s: string)  = args.add(newStrLitNode(s))
+  proc addExpr(e: expr)      = args.add(e)
+
+  ProcessInterpolations(e)
+
+  result = newCall("concat", args)
+
+###
+
+proc sum(a, b, c: int): int =
+  return (a + b + c)
+
+var 
+  alice = "Alice"
+  bob = "Bob"
+  a = 10
+  b = 20
+  c = 34
+
+var
+  s1 = concatStyleInterpolation"Hello ${alice}, ${sum (a, b, c)}}"
+  s2 = formatStyleInterpolation"Hello ${bob}, ${sum (alice.len, bob.len, 2)}"
+
+write(stdout, s1 & " | " & s2)
+
diff --git a/tests/accept/run/tusingstatement.nim b/tests/accept/run/tusingstatement.nim
new file mode 100644
index 000000000..0017af556
--- /dev/null
+++ b/tests/accept/run/tusingstatement.nim
@@ -0,0 +1,102 @@
+discard """
+  file: "tusingstatement.nim"
+  output: "Using test.Closing test."
+"""
+
+import 
+  macros
+
+# This macro mimics the using statement from C#
+#
+# XXX: 
+#  It doen't match the C# version exactly yet.
+#  In particular, it's not recursive, which prevents it from dealing 
+#  with exceptions thrown from the variable initializers when multiple.
+#  variables are used.
+#
+#  Also, since nimrod relies less on exceptions in general, a more
+#  idiomatic definition could be:
+#  var x = init()
+#  if opened(x): 
+#    try:
+#      body
+#    finally:
+#      close(x)
+#
+#  `opened` here could be an overloaded proc which any type can define.
+#  A common practice can be returing an Optional[Resource] obj for which
+#  `opened` is defined to `optional.hasValue`
+macro using(e: expr) : stmt =
+  if e.len != 2:
+    error "Using statement: unexpected number of arguments. Got " &
+      $e.len & ", expected: 1 or more variable assignments and a block"
+
+  var args = e[0]
+  var body = e[1]
+  
+  var 
+    variables : seq[PNimrodNode]
+    closingCalls : seq[PNimrodNode]
+
+  newSeq(variables, 0)
+  newSeq(closingCalls, 0)
+
+  for i in countup(1, args.len-1):
+    if args[i].kind == nnkExprEqExpr:
+      var varName = args[i][0]
+      var varValue = args[i][1]
+ 
+      var varAssignment = newNimNode(nnkIdentDefs)
+      varAssignment.add(varName)
+      varAssignment.add(newNimNode(nnkEmpty)) # empty means no type
+      varAssignment.add(varValue)
+      variables.add(varAssignment)
+
+      closingCalls.add(newCall(!"close", varName))
+    else:
+      error "Using statement: Unexpected expression. Got " &
+        $args[i].kind & " instead of assignment."
+  
+  var varSection = newNimNode(nnkVarSection)
+  varSection.add(variables)
+
+  var finallyBlock = newNimNode(nnkStmtList)
+  finallyBlock.add(closingCalls)
+
+  # XXX: Use a template here once getAst is working properly
+  var targetAst = parseStmt"""block:
+    var
+      x = foo()
+      y = bar()
+
+    try:
+      body()
+
+    finally:
+      close x
+      close y
+  """
+
+  targetAst[0][1][0] = varSection
+  targetAst[0][1][1][0] = body
+  targetAst[0][1][1][1][0] = finallyBlock
+  
+  return targetAst
+
+type 
+  TResource* = object
+    field*: string
+
+proc openResource(param: string): TResource =
+  result.field = param
+
+proc close(r: var TResource) =
+  write(stdout, "Closing " & r.field & ".")
+
+proc use(r: var TResource) =
+  write(stdout, "Using " & r.field & ".")
+
+using(r = openResource("test")):
+  use r
+
+