diff options
author | Zahary Karadjov <zahary@gmail.comy> | 2011-09-11 21:43:12 +0300 |
---|---|---|
committer | Zahary Karadjov <zahary@gmail.comy> | 2011-09-20 14:13:45 +0300 |
commit | 9acfc43119d42d7265497fd6ae60eda3903d9938 (patch) | |
tree | e9d729a2080c5bca1b45c979865977e43babb3f5 /tests/accept | |
parent | dbcca9b3b994e3339c9a03c3846b7162147679fd (diff) | |
download | Nim-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.nim | 25 | ||||
-rw-r--r-- | tests/accept/run/tusingstatement.nim | 102 |
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 + + |