diff options
author | Zahary Karadjov <zahary@gmail.com> | 2017-04-10 21:28:11 +0300 |
---|---|---|
committer | Zahary Karadjov <zahary@gmail.com> | 2017-04-10 23:58:05 +0300 |
commit | a3f19c87fb2134db25543f1e15b96144df5638dc (patch) | |
tree | eeb93b47e30ac8add3ead8255be97c3b3b1c1d44 | |
parent | f7b10e213b81588d560e37aa5f7c8b0d10ea5689 (diff) | |
download | Nim-a3f19c87fb2134db25543f1e15b96144df5638dc.tar.gz |
lift parameter-less do block to lambdas
-rw-r--r-- | compiler/ast.nim | 1 | ||||
-rw-r--r-- | compiler/evaltempl.nim | 6 | ||||
-rw-r--r-- | compiler/parser.nim | 13 | ||||
-rw-r--r-- | compiler/semstmts.nim | 6 | ||||
-rw-r--r-- | compiler/sigmatch.nim | 13 | ||||
-rw-r--r-- | compiler/vm.nim | 3 | ||||
-rw-r--r-- | lib/js/jsffi.nim | 10 | ||||
-rw-r--r-- | tests/clearmsg/tmacroerrorproc.nim | 6 | ||||
-rw-r--r-- | tests/closure/tdonotation.nim | 6 | ||||
-rw-r--r-- | tests/js/tjsffi.nim | 8 |
10 files changed, 46 insertions, 26 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim index 982654229..5b68e9712 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -452,6 +452,7 @@ type nfExprCall # this is an attempt to call a regular expression nfIsRef # this node is a 'ref' node; used for the VM nfPreventCg # this node should be ignored by the codegen + nfBlockArg # this a stmtlist appearing in a call (e.g. a do block) TNodeFlags* = set[TNodeFlag] TTypeFlag* = enum # keep below 32 for efficiency reasons (now: 30) diff --git a/compiler/evaltempl.nim b/compiler/evaltempl.nim index 50ed4e32b..fda0b79dd 100644 --- a/compiler/evaltempl.nim +++ b/compiler/evaltempl.nim @@ -90,11 +90,7 @@ proc evalTemplateArgs(n: PNode, s: PSym; fromHlo: bool): PNode = result = newNodeI(nkArgList, n.info) for i in 1 .. givenRegularParams: - let p = n[i] - if p != nil and p.kind == nkDo and s.typ.sons[i].kind in {tyStmt, tyExpr}: - result.addSon p[bodyPos] - else: - result.addSon p + result.addSon n[i] # handle parameters with default values, which were # not supplied by the user diff --git a/compiler/parser.nim b/compiler/parser.nim index 178006e46..2607d2e3d 100644 --- a/compiler/parser.nim +++ b/compiler/parser.nim @@ -1170,13 +1170,11 @@ proc postExprBlocks(p: var TParser, x: PNode): PNode = skipComment(p, result) if p.tok.tokType notin {tkOf, tkElif, tkElse, tkExcept}: var stmtList = newNodeP(nkStmtList, p) - let body = parseStmt(p) - stmtList.add body - - if stmtList.len == 1 and stmtList[0].kind == nkStmtList: - # to keep backwards compatibility (see tests/vm/tstringnil) - stmtList = stmtList[0] + stmtList.add parseStmt(p) + # to keep backwards compatibility (see tests/vm/tstringnil) + if stmtList[0].kind == nkStmtList: stmtList = stmtList[0] + stmtList.flags.incl nfBlockArg if openingParams.kind != nkEmpty: result.add newProcNode(nkDo, stmtList.info, stmtList, params = openingParams, pragmas = openingPragmas) @@ -1209,7 +1207,10 @@ proc postExprBlocks(p: var TParser, x: PNode): PNode = else: break eat(p, tkColon) nextBlock.addSon parseStmt(p) + + nextBlock.flags.incl nfBlockArg result.add nextBlock + if nextBlock.kind == nkElse: break else: if openingParams.kind != nkEmpty: diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 63fea997a..e52a1b5cc 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -1652,7 +1652,11 @@ proc semStmtList(c: PContext, n: PNode, flags: TExprFlags): PNode = else: discard if result.len == 1 and - c.inTypeClass == 0 and # concept bodies should be preserved as a stmt list + # concept bodies should be preserved as a stmt list: + c.inTypeClass == 0 and + # also, don't make life complicated for macros. + # they will always expect a proper stmtlist: + nfBlockArg notin n.flags and result.sons[0].kind != nkDefer: result = result.sons[0] diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index 0aa972093..89c885c64 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -1259,7 +1259,6 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation = of tyGenericInvocation: var x = a.skipGenericAlias - # XXX: This is very hacky. It should be moved back into liftTypeParam if x.kind == tyGenericInst and c.calleeSym != nil and c.calleeSym.kind == skProc: let inst = prepareMetatypeForSigmatch(c.c, c.bindings, c.call.info, f) @@ -1639,6 +1638,10 @@ proc incMatches(m: var TCandidate; r: TTypeRelation; convMatch = 1) = of isEqual: inc(m.exactMatches) of isNone: discard +template matchesVoidProc(t: PType): bool = + (t.kind == tyProc and t.len == 1 and t.sons[0] == nil) or + (t.kind == tyBuiltInTypeClass and t.sons[0].kind == tyProc) + proc paramTypesMatchAux(m: var TCandidate, f, a: PType, argSemantized, argOrig: PNode): PNode = var @@ -1775,6 +1778,14 @@ proc paramTypesMatchAux(m: var TCandidate, f, a: PType, inc(m.genericMatches) m.fauxMatch = a.kind return arg + elif a.kind == tyVoid and f.matchesVoidProc and argOrig.kind == nkStmtList: + # lift do blocks without params to lambdas + let lifted = c.semExpr(c, newProcNode(nkDo, argOrig.info, argOrig), {}) + if f.kind == tyBuiltInTypeClass: + inc m.genericMatches + put(m, f, lifted.typ) + inc m.convMatches + return implicitConv(nkHiddenStdConv, f, lifted, m, c) result = userConvMatch(c, m, f, a, arg) # check for a base type match, which supports varargs[T] without [] # constructor in a call: diff --git a/compiler/vm.nim b/compiler/vm.nim index d311de255..14800fb13 100644 --- a/compiler/vm.nim +++ b/compiler/vm.nim @@ -1599,8 +1599,7 @@ proc setupMacroParam(x: PNode, typ: PType): TFullReg = putIntoReg(result, x) else: result.kind = rkNode - var n = if typ.kind in {tyStmt,tyExpr} and x.kind == nkDo: x[bodyPos] - else: x + var n = x if n.kind in {nkHiddenSubConv, nkHiddenStdConv}: n = n.sons[1] n = n.canonValue n.flags.incl nfIsRef diff --git a/lib/js/jsffi.nim b/lib/js/jsffi.nim index 7aa80b39b..e0310e33a 100644 --- a/lib/js/jsffi.nim +++ b/lib/js/jsffi.nim @@ -112,6 +112,12 @@ proc toJs*[T](val: T): JsObject {. importcpp: "(#)" .} template toJs*(s: string): JsObject = cstring(s).toJs +macro jsFromAst*(n: untyped): untyped = + result = n + if n.kind == nnkStmtList: + result = newProc(procType = nnkDo, body = result) + return quote: toJs(`result`) + proc `&`*(a, b: cstring): cstring {.importcpp: "(# + #)".} ## Concatenation operator for JavaScript strings @@ -220,7 +226,7 @@ macro `.=`*(obj: JsObject, field: static[cstring], value: untyped): untyped = macro `.()`*(obj: JsObject, field: static[cstring], - args: varargs[JsObject, toJs]): JsObject = + args: varargs[JsObject, jsFromAst]): JsObject = ## Experimental "method call" operator for type JsObject. ## Takes the name of a method of the JavaScript object (`field`) and calls ## it with `args` as arguments, returning a JsObject (which may be discarded, @@ -244,7 +250,7 @@ macro `.()`*(obj: JsObject, if not mangledNames.hasKey($field): mangledNames[$field] = $mangleJsName(field) importString = "#." & mangledNames[$field] & "(@)" - result = quote do: + result = quote: proc helper(o: JsObject): JsObject {. importcpp: `importString`, gensym, discardable .} helper(`obj`) diff --git a/tests/clearmsg/tmacroerrorproc.nim b/tests/clearmsg/tmacroerrorproc.nim index 9a6ff6a06..cd9b15e25 100644 --- a/tests/clearmsg/tmacroerrorproc.nim +++ b/tests/clearmsg/tmacroerrorproc.nim @@ -7,7 +7,7 @@ discard """ import macros macro mixer(n: typed): untyped = - expectKind(n, nnkCharLit) - + expectKind(n[0], nnkCharLit) + mixer: - echo "owh" \ No newline at end of file + echo "owh" diff --git a/tests/closure/tdonotation.nim b/tests/closure/tdonotation.nim index 5acb17da2..94eba8ddb 100644 --- a/tests/closure/tdonotation.nim +++ b/tests/closure/tdonotation.nim @@ -35,11 +35,11 @@ b.onFocusLost: b.onFocusLost do: echo "lost focus 2" -b.onUserEvent("UserEvent 1") do: +b.onUserEvent "UserEvent 1" do: discard -b.onUserEvent("UserEvent 2"): +b.onUserEvent "UserEvent 2": discard -b.onUserEvent("UserEvent 3", () => echo "event 2") +b.onUserEvent("UserEvent 3", () => echo "event 3") diff --git a/tests/js/tjsffi.nim b/tests/js/tjsffi.nim index be8e2efb7..99a475a8e 100644 --- a/tests/js/tjsffi.nim +++ b/tests/js/tjsffi.nim @@ -1,5 +1,6 @@ discard """ - output: '''true +output: ''' +true true true true @@ -19,7 +20,8 @@ true 2 12 Event { name: 'click: test' } -Event { name: 'reloaded: test' }''' +Event { name: 'reloaded: test' } +''' """ import macros, jsffi, jsconsole @@ -306,6 +308,6 @@ block: on("click") do (e: Event): console.log e - jslib.on("reloaded") do: + jslib.on "reloaded" do: console.log jsarguments[0] |