summary refs log tree commit diff stats
path: root/tests/accept
diff options
context:
space:
mode:
authorZahary Karadjov <zahary@gmail.comy>2011-09-11 21:43:12 +0300
committerZahary Karadjov <zahary@gmail.comy>2011-09-20 14:13:45 +0300
commit9acfc43119d42d7265497fd6ae60eda3903d9938 (patch)
treee9d729a2080c5bca1b45c979865977e43babb3f5 /tests/accept
parentdbcca9b3b994e3339c9a03c3846b7162147679fd (diff)
downloadNim-9acfc43119d42d7265497fd6ae60eda3903d9938.tar.gz
using statement (ala C#) implemented as macro (added as test).
simplified the usage of the interpolatedFragments iterator.
Diffstat (limited to 'tests/accept')
-rw-r--r--tests/accept/run/tstringinterp.nim25
-rw-r--r--tests/accept/run/tusingstatement.nim102
2 files changed, 109 insertions, 18 deletions
diff --git a/tests/accept/run/tstringinterp.nim b/tests/accept/run/tstringinterp.nim
index 83bd37709..55baae7ec 100644
--- a/tests/accept/run/tstringinterp.nim
+++ b/tests/accept/run/tstringinterp.nim
@@ -1,6 +1,6 @@
 discard """
   file: "tstringinterp.nim"
-  output: "Hello Alice \$ 64 | Hello Bob, 10"
+  output: "Hello Alice, 64 | Hello Bob, 10"
 """
 
 import macros, parseutils, strutils
@@ -13,23 +13,12 @@ proc concat(strings: openarray[string]) : string =
 template ProcessInterpolations(e: expr) =
   var 
     s = e[1].strVal
-    stringStart = 0
- 
-  for i in interpolatedFragments(s):
-    var leadingString = s[stringStart..i.interpStart-1]
-    var interpolatedExpr = s[i.exprStart..i.exprEnd]
-
-    addString(leadingString)
-
-    var interpTargetAst = parseExpr("$(x)")
-    interpTargetAst[1][0] = parseExpr(interpolatedExpr)
-    addExpr(interpTargetAst)
     
-    stringStart = i.interpEnd + 1
-
-  if stringStart != s.len:
-    var endingString = s[stringStart..s.len]
-    addString(endingString)
+  for f in interpolatedFragments(s):
+    if f.kind  == ikString:
+      addString(f.value)
+    else:
+      addExpr(f.value)
 
 macro formatStyleInterpolation(e: expr): expr =
   var 
@@ -75,7 +64,7 @@ var
   c = 34
 
 var
-  s1 = concatStyleInterpolation"Hello ${alice} \$ ${sum (a, b, c)}"
+  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
+
+