Error processing request

Parameters

CONTENT_LENGTH0
REQUEST_METHODGET
REQUEST_URI/revision/tailcall?V=47
QUERY_STRINGV=47
CONTENT_TYPE
DOCUMENT_URI/revision/tailcall
DOCUMENT_ROOT/var/www/nikit/nikit/nginx/../docroot
SCGI1
SERVER_PROTOCOLHTTP/1.1
HTTPSon
REMOTE_ADDR172.70.127.90
REMOTE_PORT65258
SERVER_PORT4443
SERVER_NAMEwiki.tcl-lang.org
HTTP_HOSTwiki.tcl-lang.org
HTTP_CONNECTIONKeep-Alive
HTTP_ACCEPT_ENCODINGgzip, br
HTTP_X_FORWARDED_FOR3.145.191.22
HTTP_CF_RAY87aa1c308ad92ade-ORD
HTTP_X_FORWARDED_PROTOhttps
HTTP_CF_VISITOR{"scheme":"https"}
HTTP_ACCEPT*/*
HTTP_USER_AGENTMozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; ClaudeBot/1.0; [email protected])
HTTP_CF_CONNECTING_IP3.145.191.22
HTTP_CDN_LOOPcloudflare
HTTP_CF_IPCOUNTRYUS

Body


Error

Unknow state transition: LINE -> END

-code

1

-level

0

-errorstack

INNER {returnImm {Unknow state transition: LINE -> END} {}} CALL {my render_wikit tailcall '''\[http://www.tcl.tk/man/tcl/TclCmd/tailcall.htm%|%tailcall\]''',\ a\ \[Tcl\ Commands%|%built-in\]\ \[Tcl\]\ command,\ executes\ a\ command\ in\ place\ of\ the\ current\ncommand.\n\n\n\n**\ Synopsis\ **\n\n\ \ \ \ :\ \ \ '''tailcall'''\ ''command''\ ?''arg''...?\n\n\n\n**\ See\ Also\ **\n\n\ \ \ \[Tail\ call\ optimization\]:\ \ \ \n\n\ \ \ \[TIP\]#\[http://tip.tcl.tk/327%|%327\]:\ \ \ \n\n\ \ \ \[wrapping\ commands\]:\ \ \ wrap\ commands\ by\ using\ `\[interp\ invokehidden\]`\ together\ with\ `tailcall`\n\n\n\n**\ Description\ **\n\n'''`tailcall`'''\ interprets\ its\ arguments\ as\ a\ command\ and\ executes\ the\ncommand,replacing\ the\ \[stack\ frame%|%execution\ frame\]\ of\ the\ command\ that\ninvoked\ `tailcall`.\ \ Unlike\ `\[uplevel\]`,\ it\ does\ not\ \[eval%|%evaluate\]\ its\narguments\ as\ a\ script,\ so\ \[double\ substitution\]\ does\ not\ occur.\n\nUnlike\ some\ other\ languages,\ `tailcall`\ is\ not\ limited\ to\ executing\ only\ its\ncaller,\ but\ can\ execute\ any\ command.\ \ The\ command\ to\ be\ executed\ is\ resolved\ in\nthe\ current\ context\ before\ `tailcall`\ replaces\ the\ context.\n\n`tailcall`\ is\ made\ possible\ by\ \[NRE\].\ \ It\ first\ became\ available\ as\n`\[::tcl::unsupported::tailcall\]`\ in\ the\ release\ of\ Tcl8.6a2.\n\nContrast\ the\ following\ two\ commands:\n\n======\ntailcall\ foo\ \[bar\]\ \$var\nreturn\ \[uplevel\ 1\ \[list\ foo\ \[bar\]\ \$var1\]\]\n======\n\nThere\ are\ a\ couple\ of\ differences:\n\n\ \ \ 1.\ '''foo'''\ is\ resolved\ in\ the\ ''current''\ context,\ not\ in\ the\ caller's\n\ \ \ 1.\ the\ stack\ frame\ is\ ''really''\ gone,\ not\ just\ ''virtually''.\ This\ has\ positive\ effects\ on\ memory,\ and\ a\ possibly\ confusing\ effect\ on\ stack\ traces.\n\n\nTo\ `tailcall`\ a\ script:\n\n======\ntailcall\ try\ \$script\n======\n\n----\n\n\[WHD\]:\ Let\ me\ see\ if\ I\ understand\ what\ this\ does.\n\n======\nproc\ fred\ \{\}\ \{\n\ \ \ \ george\n\}\n\nproc\ george\ \{\}\ \{\n\ \ \ \ \ tailcall\ harry\n\}\n======\n\nIf\ I\ call\ fred,\ it's\ almost\ as\ though\ fred\ called\ harry\ directly,\ instead\ of\ngeorge.\ \ Not\ so?\n\n\[MS\]:\ \ yup\ -\ all\ traces\ of\ george\ are\ gone\ from\ the\ program\ stack\ when\ harry\ is\ncalled.\ Now,\ if\ harry\ resolves\ to\ a\ different\ command\ in\ george's\ current\nnamespace\ than\ it\ would\ under\ fred's,\ the\ harry\ that\ is\ called\ is\ george's\ and\nnot\ fred's\ (no\ diff\ if\ the\ commands\ are\ FQ,\ of\ course).\n\nI\ think\ this\ does\ pretty\ much\ what\ delegation\ is\ supposed\ to\ do,\ right?\n\n----\n\n\[jima\]\ 2009-10-15:\ Perhaps\ this\ has\ been\ asked\ before\ or\ somewhere\ else...\n\nIs\ this\ an\ optimization\ that\ takes\ place\ at\ bytecode\ generation\ time?\n\nI\ mean,\ once\ fred\ knows\ that\ has\ to\ call\ harry\ directly\ the\ bytecodes\ generated\nwould\ be\ the\ ones\ equivalent\ to\ have\ said:\n\n======\nproc\ fred\ \{\}\ \{\n\ \ \ \ harry\n\}\n======\n\nI\ reckon\ I\ am\ not\ familiar\ with\ all\ the\ internals\ of\ Tcl\ but\ I\ find\ this\ would\nbe\ an\ interesting\ thing.\ Wouldn't\ this\ be\ a\ new\ way\ to\ have\ some\ sort\ of\nmacros?\n\n\[MS\]:\ \ Currently,\ `tailcall`\ is\ not\ bytecompiled.\ Everything\ happens\ at\nruntime.\ That\ extremely\ simple\ example\ could\ indeed\ be\ bytecoded\ in\ a\ minute,\nbut\ things\ get\ more\ involved\ as\ soon\ as\ `fred`\ has\ a\ bit\ more\ structure\ to\nit:\ arguments,\ local\ variables,\ namespace\ issues\ both\ for\ variable\ and\ command\nlookup,\ multiple\ exit\ points\ with\ different\ (or\ no)\ `tailcall`\ in\ them,\netc.\n\n\[jima\]:\ Thanks\ a\ lot\ Miguel\ for\ the\ answer.\ I\ see\ the\ point.\ I\ guess\ this\ is\nthe\ same\ with\ `\[uplevel\]\ 1`,\ isn't\ it?\n\n======\nproc\ fred\ \{\}\ \{\n\ \ \ \ uplevel\ 1\ \{\n\ \ \ \ \ \ \ \ #code\ here\n\ \ \ \ \}\n\}\n======\n\nWould\ it\ be\ interesting\ to\ define\ a\ case\ (like\ a\ contract)\ saying\ if\ your\ proc\nis\ simple\ enough\ then\ it\ gets\ bytecompiled\ and\ you\ get\ some\ benefits?\n\n\[MS\]:\ \ you\ do\ not\ mean\ \"bytecompiled\"\ but\ rather\ \"inlined\ into\ the\ caller\",\ as\nall\ `\[proc\]`\ bodies\ get\ bytecompiled.\ There\ are\ quite\ a\ few\ other\ issues\ with\ that,\nespecially\ to\ accomodate\ Tcl's\ dynamic\ nature.\ Changing\ one\ inlined\ proc\ would\ncause\ a\ spoiling\ of\ all\ bytecodes\ and\ recompilation\ of\ the\ world,\ at\ least\ with\nthe\ current\ approach\ to\ bytecode\ lifetime\ management.\n\n----\n\n\[AMG\]:\ Sounds\ a\ lot\ like\ `exec`\ in\ \[Unix\ shells\].\ \ See\ \[execline\]\ for\ more\ninformation\ on\ a\ noninteractive\ Unix\ shell\ where\ everything\ is\ done\ with\nexec/tailcall.\n\n\n\n----\n\n\[PYK\]\ 2015-12-06:\ \ \ Combine\ `tailcall`\ with\ an\ \[identity\ function%|%identity\]\ncommand\ to\ emulate\ `\[return\]`:\n\n\n======\nproc\ p1\ \{\}\ \{\n\ \ \ \ \ \ \ \ tailcall\ lindex\ \{Hello\ from\ p1\}\n\}\n======\n\n\n\n\n\n**\ Interaction\ with\ `\[try\]`\ **\n\n===none\n'''%'''\ proc\ foo\ \{\}\ \{puts\ \{I'm\ foo\}\}\n'''%'''\ proc\ bar\ \{\}\ \{puts\ \{I'm\ bar\}\;\ try\ \{tailcall\ foo\}\ finally\ \{puts\ exiting\}\}\n'''%'''\ foo\n''I'm\ foo''\n'''%'''\ bar\n''I'm\ bar''\n''exiting''\n''I'm\ foo''\n===\n31-03-2015\ \[HE\]\ I'm\ sure\ \;-)\ that\ I\ don't\ understood\ what\ happend\ there.\ Why\ \"exiting\"\ is\ printed\ before\ \"I'm\ foo\"\ when\ I\ call\ bar?\nIf\ I\ change\ bar\ to\n======\nproc\ bar\ \{\}\ \{puts\ \{I'm\ bar\}\;\ try\ \{puts\ tryBody\;\ tailcall\ foo\}\ finally\ \{puts\ exiting\}\;\ puts\ afterwards\}\n======\nand\ call\ it,\ I\ get:\n======none\nI'm\ bar\ntryBody\nexiting\nI'm\ foo\n======\nWhat\ I\ see\ is\ that\ tailcall\ replace\ the\ rest\ of\ proc\ even\ inside\ the\ body\ of\ try.\ \nBut\ then,\ why\ is\ the\ finally\ clause\ executed?\nAnd\ even,\ if\ we\ assume\ the\ finally\ clause\ has\ to\ be\ executed\ because\ it\ is\ documented\ always\ to\ be\ executed,\ \nthen\ there\ would\ be\ the\ question,\ why\ before\ the\ execution\ of\ the\ tailcall\ command?\n\n\[AMG\]:\ \[\[foo\]\]\ is\ invoked\ by\ replacing\ \[\[bar\]\]\ which\ implies\ the\ intervening\ \[\[\[try\]\]\]\ block\ must\ exit\ before\ \[\[foo\]\]\ can\ start.\n\n----\n\[wdb\]:\ Apparently,\ the\ `tailcall`\ closes\ one\ of\ the\ last\ gaps\ in\nTcl:\ Tail\ recursion\ as\ known\ in\ \[Scheme\].\n\n\n\n**\ Example:\ Cause\ Caller\ to\ Return\ **\n\n======\nproc\ one\ \{\}\ \{\n\ \ \ \ two\n\ \ \ \ return\ 8\n\}\n\nproc\ two\ \{\}\ \{\n\ \ \ \ tailcall\ return\ 5\n\}\n\none\ \;#\ ->\ 5\n======\n\n`one`\ returns\ `5`,\ not\ `8`,\ because\ by\ invoking\ two,\ which,\ through\ `\[tailcall\]`,\ is\ replaced\ by\ `\[return\]`.\n\n\n\n**\ Example:\ \ Factorial\ **\n\n\[NEM\]:\ As\ a\ test/demo\ of\ how\ to\ use\ this\ facility,\ here\ is\ a\ simple\ benchmark\nusing\ the\ factorial\ function:\n\n======\npackage\ require\ Tcl\ 8.6a1\nnamespace\ import\ ::tcl::mathop::*\ninterp\ alias\ \{\}\ tailcall\ \{\}\ tcl::unsupported::tailcall\n\n#\ Naive\ recursive\ factorial\ function\nproc\ fac\ n\ \{\n\ \ \ \ if\ \{\$n\ <=\ 1\}\ \{\n\ \ \ \ \ \ \ \ return\ 1\n\ \ \ \ \}\ else\ \{\n\ \ \ \ \ \ \ \ *\ \$n\ \[fac\ \[-\ \$n\ 1\]\]\n\ \ \ \ \}\n\}\n\n#\ Tail-recursive\ factorial\nproc\ fac-tr\ \{n\ \{k\ 1\}\}\ \{\n\ \ \ \ if\ \{\$n\ <=\ 1\}\ \{\n\ \ \ \ \ \ \ \ return\ \$k\n\ \ \ \ \}\ else\ \{\n\ \ \ \ \ \ \ \ tailcall\ fac-tr\ \[-\ \$n\ 1\]\ \[*\ \$n\ \$k\]\n\ \ \ \ \}\n\}\n\n#\ Iterative\ factorial\nproc\ fac-i\ n\ \{\n\ \ \ \ for\ \{set\ k\ 1\}\ \{\$n\ >\ 1\}\ \{incr\ n\ -1\}\ \{\n\ \ \ \ \ \ \ \ set\ k\ \[expr\ \{\$n*\$k\}\]\n\ \ \ \ \}\n\ \ \ \ return\ \$k\n\}\n\nproc\ test\ \{\}\ \{\n\ \ \ \ set\ fmt\ \{%-10s\ ..%-12.12s\ %s\}\n\ \ \ \ puts\ \[format\ \$fmt\ Implementation\ Result\ Time\]\n\ \ \ \ foreach\ n\ \{1\ 5\ 10\ 100\ 500\ 1000\ 2500\ 5000\ 10000\}\ \{\n\ \ \ \ \ \ \ \ puts\ \"\\nfac\ \$n:\"\n\ \ \ \ \ \ \ \ foreach\ impl\ \{fac\ fac-i\ fac-tr\}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ if\ \{\[catch\ \{\$impl\ \$n\}\ result\]\}\ \{\ \n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ set\ result\ n/a\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ set\ time\ n/a\n\ \ \ \ \ \ \ \ \ \ \ \ \}\ else\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ set\ time\ \[time\ \[list\ \$impl\ \$n\]\ 10\]\n\ \ \ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \ \ \ \ puts\ \[format\ \$fmt\ \$impl\ \$result\ \$time\]\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \}\n\}\ntest\n======\n\nPutting\ this\ in\ a\ table,\ we\ get\ (timings\ taken\ on\ Linux\ box,\ 2.66GHz,\ 1GB\ RAM):\n\n%|\ N\ |\ `fac`\ Time\ |\ `fac-i`\ Time\ |\ `fac-tr`\ Time\ |%\n&|\ 1\ |\ 3.2\ |\ 3.0\ |\ 2.8\ |&\n&|\ 5\ |\ 10.1\ |\ 4.7\ |\ 19.4\ |&\n&|\ 10\ |\ 18.4\ |\ 6.4\ |\ 37.9\ |&\n&|\ 100\ |\ 345.5\ |\ 267.4\ |\ 717.8\ |&\n&|\ 500\ |\ 3133.9\ |\ 3715.6\ |\ 6182.5\ |&\n&|\ 1000\ |\ n/a\ |\ 13811.7\ |\ 19764.3\ |&\n&|\ 2500\ |\ n/a\ |\ 65121.1\ |\ 84556.5\ |&\n&|\ 5000\ |\ n/a\ |\ 241176.8\ |\ 288136.1\ |&\n&|\ 10000\ |\ n/a\ |\ 987057.8\ |\ 1643480.7\ |&\n\nAs\ we\ can\ see,\ the\ tail-recursive\ version\ is\ slightly\ slower\ than\ the\ iterative\nversion,\ and\ unlike\ the\ naive\ version,\ manages\ to\ not\ blow\ the\ stack.\n\n\n\n**\ Using\ Tailcall\ for\ Callbacks\ **\n**Using\ Tailcall\ for\ Callbacks**\n\[Napier\ /\ Dash\ Automation\]\ -\ 12-28-015\n\[Napier\ /\ Dash\ Automation\]\ 2015-12-28:\n\n======\nproc\ callback\ \{args\}\ \{tailcall\ namespace\ code\ \$args\}\n\nnamespace\ eval\ foo\ \{\nproc\ myProc\ var\ \{puts\ \$var\}\n\ \ \ \ \ proc\ myCall\ \{\}\ \{\ after\ 5000\ \[callback\ myProc\ \$::myVar\]\ \}\n\nafter\ 5000\ \[callback\ myProc\ \$myVar\]\n\n**\ Emulating\ `tailcall`\ **\n\n\[Lars\ H\]\ 2010-05-09:\ As\ of\ late,\ when\ writing\ an\ `\[uplevel\]`,\ I've\ sometimes\nfound\ myself\ thinking\ \"That\ would\ be\ slicker\ with\ `\[tailcall\]`,\ but\ I\ can't\nrely\ on\ 8.6\ features\ in\ this\ project\".\ Today\ it\ occurred\ to\ me\ that\ one\ can\nhowever\ use\ a\ `\[proc\]`\ to\ emulate\ the\ properties\ of\ `tailcall`\ that\ would\nbe\ needed\ in\ these\ cases,\ and\ thus\ provide\ a\ route\ for\ forward\ compatibility.\n\nThe\ main\ situation\ I've\ encountered\ is\ that\ of\ delegating\ to\ another\ command\nwhich\ may\ make\ use\ of\ `\[upvar\]`\ or\ `\[uplevel\]`.\ That's\ basically\ taken\ncare\ of\ by\n\n======\nproc\ utailcall\ args\ \{uplevel\ 2\ \$args\}\n======\n\nalthough\ it's\ safer\ to\ make\ it\n\n======\nproc\ utailcall\ args\ \{return\ -code\ return\ \[uplevel\ 2\ \$args\]\}\n======\n\nin\ case\ the\ \"terminate\ proc\ early\"\ aspect\ of\ `tailcall`\ is\ relied\ upon\;\ this\nis\ easy\ to\ do\ without\ thinking\ much\ about\ it.\n\nAnother\ aspect\ of\ `tailcall`\ is\ the\ name\ resolution\ of\ the\ called\ command.\nThis\ can\ be\ done\ as\ follows\n\n======\nproc\ ntailcall\ \{cmd\ args\}\ \{\n\ \ \ \ return\ -code\ return\ \[\n\ \ \ \ \ \ \ \ \[uplevel\ 1\ \[list\ ::namespace\ which\ \$cmd\]\]\ \{*\}\$args\n\ \ \ \ \]\n\}\n======\n\nbut\ it's\ almost\ as\ easy\ to\ do\ both\ at\ the\ same\ time\n\n======\nproc\ untailcall\ \{cmd\ args\}\ \{\n\ \ \ \ return\ -code\ return\ \[\n\ \ \ \ \ \ \ \ uplevel\ 2\ \[list\ \[uplevel\ 1\ \[list\ ::namespace\ which\ \$cmd\]\]\]\ \$args\n\ \ \ \ \]\n\}\n======\n\nA\ word\ of\ warning\ here\ is\ that\ this\ will\ produce\ a\ very\ confusing\ error\ message\nif\ the\ command\ is\ undefined,\ as\ `\[namespace\ which\]`\ returns\ an\ empty\ string\nin\ that\ case.\n\nA\ third\ aspect\ is\ that\ of\ preserving\ `\[return\]`\ levels.\n\n======\nproc\ rtailcall\ args\ \{\n\ \ \ \ catch\ \$args\ result\ options\n\ \ \ \ dict\ incr\ options\ -level\ 2\n\ \ \ \ return\ -options\ \$options\ \$result\n\}\n======\n\nThis\ leaves\ some\ extra\ material\ in\ the\ \[errorInfo\],\ but\ one\ can\ probably\ live\nwith\ that.\ Combining\ the\ \"r\"\ and\ \"u\"\ aspects\ is\ straightforward,\ but\ will\ leave\neven\ more:\n\n======\nproc\ rutailcall\ args\ \{\n\ \ \ \ catch\ \{uplevel\ 2\ \$args\}\ result\ options\n\ \ \ \ dict\ incr\ options\ -level\ 2\n\ \ \ \ return\ -options\ \$options\ \$result\n\}\n======\n\nTo\ complete\ the\ set,\ one\ might\ just\ as\ well\ write\ down\ the\ combination\ of\ the\n\"r\"\ and\ \"n\"\ aspects\n\n======\nproc\ rntailcall\ \{cmd\ args\}\ \{\n\ \ \ \ catch\ \{\n\ \ \ \ \ \ \ \ \[uplevel\ 1\ \[list\ ::namespace\ which\ \$cmd\]\]\ \{*\}\$args\n\ \ \ \ \}\ result\ options\n\ \ \ \ dict\ incr\ options\ -level\ 2\n\ \ \ \ return\ -options\ \$options\ \$result\n\}\n======\n\nand\ of\ all\ three\n\n======\nproc\ rnutailcall\ \{cmd\ args\}\ \{\n\ \ \ \ catch\ \{\n\ \ \ \ \ \ \ \ uplevel\ 2\ \[list\ \[uplevel\ 1\ \[list\ ::namespace\ which\ \$cmd\]\]\]\ \$args\n\ \ \ \ \}\ result\ options\n\ \ \ \ dict\ incr\ options\ -level\ 2\n\ \ \ \ return\ -options\ \$options\ \$result\n\}\n======\n\nBut\ note:\ ''all\ of\ the\ above\ will\ fail\ if\ used\ for\ tail\ recursion'',\ as\ soon\ as\nthe\ loops\ get\ long\ enough.\n\n\n**\ Replacement\ for\ `\[uplevel\]`\ **\n\n\[AMG\]:\ `\[uplevel\]`\ has\ limitations\ with\ respect\ to\ \[bytecode\]\ compilation\nand\ interpretation\ of\ `\[return\]`.\ \ If\ `\[uplevel\]`'s\ level\ count\ is\ `1`,\ and\nif\ it's\ the\ last\ thing\ being\ done\ in\ the\ `\[proc\]`,\ these\ limitations\ can\ be\navoided\ by\ using\ `\[tailcall\]`\ instead.\ \ Note\ that\ `\[uplevel\]`\ takes\ a\nscript\ whereas\ `\[tailcall\]`\ takes\ a\ command.\ \ If\ you\ want\ to\ pass\ a\ script\nto\ `\[tailcall\]`,\ make\ it\ be\ the\ sole\ argument\ to\ `\[try\]`.\n\nSee\ \[http://wiki.tcl.tk/1507#pagetocc0434a60%|%Possible\ uplevel\ deficiencies%|%\].\nAlso\ see\ \[http://wiki.tcl.tk/1507#pagetocb7539876%|%When\ to\ use\ uplevel\]\ for\nmore\ on\ when\ to\ use\ or\ avoid\ `\[uplevel\]`.\ \ See\n\[http://wiki.tcl.tk/1017#pagetoc74fae1d9%|%eval\ vs\ bytecode\]\ for\ discussion\ and\nperformance\ numbers\ regarding\ \[bytecode\]\ compilation\ with\ `\[eval\]`,\n`\[uplevel\]`,\ `\[try\]`,\ and\ others.\n\n**\ When\ to\ apply\ `tailcall`\ optimization\ **\n\n\[HaO\]\ 2012-12-14:\ Is\ it\ a\ good\ idea\ to\ replace\ any\ code:\n\n======\nproc\ proc1\ \{arg1\ arg2\}\ \{\n\ \ \ \ #\ do\ something\ here\ which\ finds\ arg3\ and\ arg4\n\ \ \ \ return\ \[proc2\ \$arg3\ \$arg4\]\n\}\n======\n\nby\n\n======\nproc\ proc1\ \{arg1\ arg2\}\ \{\n\ \ \ \ #\ do\ something\ here\ which\ finds\ arg3\ and\ arg4\n\ \ \ \ tailcall\ proc2\ \$arg3\ \$arg4\n\}\n======\n\nIf\ proc2\ is\ for\ sure\ found\ in\ the\ caller\ namespace?\n\nIs\ this\ an\ intelligent\ optimization?\n\nI\ came\ to\ this\ idea,\ as\ the\ TI\ C\ compiler\ calls\ this\ \"tailcall\ optimization\".\n\n\[AMG\]:\ Yes,\ except\ in\ a\ highly\ unlikely\ situation\ where\ `proc2`\ needs\ `proc1`\ to\ be\ visible\ in\ the\ stack.\ \ Procedures\ really\ ought\ not\ to\ care\ who\ called\ them,\ but\ Tcl\ makes\ all\ sorts\ of\ things\ possible,\ including\ stupid\ things.\n\n\n\n**\ Misc\ **\n\n\[NEM\]:\ \ Many\ thanks\ to\ \[MS\]\ for\ his\ hard\ work\ making\ this\ a\ reality!\n\n<<categories>>\ Command\ |\ Concept\ |\ Control\ structure\ |\ Functional\ Programming regexp2} CALL {my render tailcall '''\[http://www.tcl.tk/man/tcl/TclCmd/tailcall.htm%|%tailcall\]''',\ a\ \[Tcl\ Commands%|%built-in\]\ \[Tcl\]\ command,\ executes\ a\ command\ in\ place\ of\ the\ current\ncommand.\n\n\n\n**\ Synopsis\ **\n\n\ \ \ \ :\ \ \ '''tailcall'''\ ''command''\ ?''arg''...?\n\n\n\n**\ See\ Also\ **\n\n\ \ \ \[Tail\ call\ optimization\]:\ \ \ \n\n\ \ \ \[TIP\]#\[http://tip.tcl.tk/327%|%327\]:\ \ \ \n\n\ \ \ \[wrapping\ commands\]:\ \ \ wrap\ commands\ by\ using\ `\[interp\ invokehidden\]`\ together\ with\ `tailcall`\n\n\n\n**\ Description\ **\n\n'''`tailcall`'''\ interprets\ its\ arguments\ as\ a\ command\ and\ executes\ the\ncommand,replacing\ the\ \[stack\ frame%|%execution\ frame\]\ of\ the\ command\ that\ninvoked\ `tailcall`.\ \ Unlike\ `\[uplevel\]`,\ it\ does\ not\ \[eval%|%evaluate\]\ its\narguments\ as\ a\ script,\ so\ \[double\ substitution\]\ does\ not\ occur.\n\nUnlike\ some\ other\ languages,\ `tailcall`\ is\ not\ limited\ to\ executing\ only\ its\ncaller,\ but\ can\ execute\ any\ command.\ \ The\ command\ to\ be\ executed\ is\ resolved\ in\nthe\ current\ context\ before\ `tailcall`\ replaces\ the\ context.\n\n`tailcall`\ is\ made\ possible\ by\ \[NRE\].\ \ It\ first\ became\ available\ as\n`\[::tcl::unsupported::tailcall\]`\ in\ the\ release\ of\ Tcl8.6a2.\n\nContrast\ the\ following\ two\ commands:\n\n======\ntailcall\ foo\ \[bar\]\ \$var\nreturn\ \[uplevel\ 1\ \[list\ foo\ \[bar\]\ \$var1\]\]\n======\n\nThere\ are\ a\ couple\ of\ differences:\n\n\ \ \ 1.\ '''foo'''\ is\ resolved\ in\ the\ ''current''\ context,\ not\ in\ the\ caller's\n\ \ \ 1.\ the\ stack\ frame\ is\ ''really''\ gone,\ not\ just\ ''virtually''.\ This\ has\ positive\ effects\ on\ memory,\ and\ a\ possibly\ confusing\ effect\ on\ stack\ traces.\n\n\nTo\ `tailcall`\ a\ script:\n\n======\ntailcall\ try\ \$script\n======\n\n----\n\n\[WHD\]:\ Let\ me\ see\ if\ I\ understand\ what\ this\ does.\n\n======\nproc\ fred\ \{\}\ \{\n\ \ \ \ george\n\}\n\nproc\ george\ \{\}\ \{\n\ \ \ \ \ tailcall\ harry\n\}\n======\n\nIf\ I\ call\ fred,\ it's\ almost\ as\ though\ fred\ called\ harry\ directly,\ instead\ of\ngeorge.\ \ Not\ so?\n\n\[MS\]:\ \ yup\ -\ all\ traces\ of\ george\ are\ gone\ from\ the\ program\ stack\ when\ harry\ is\ncalled.\ Now,\ if\ harry\ resolves\ to\ a\ different\ command\ in\ george's\ current\nnamespace\ than\ it\ would\ under\ fred's,\ the\ harry\ that\ is\ called\ is\ george's\ and\nnot\ fred's\ (no\ diff\ if\ the\ commands\ are\ FQ,\ of\ course).\n\nI\ think\ this\ does\ pretty\ much\ what\ delegation\ is\ supposed\ to\ do,\ right?\n\n----\n\n\[jima\]\ 2009-10-15:\ Perhaps\ this\ has\ been\ asked\ before\ or\ somewhere\ else...\n\nIs\ this\ an\ optimization\ that\ takes\ place\ at\ bytecode\ generation\ time?\n\nI\ mean,\ once\ fred\ knows\ that\ has\ to\ call\ harry\ directly\ the\ bytecodes\ generated\nwould\ be\ the\ ones\ equivalent\ to\ have\ said:\n\n======\nproc\ fred\ \{\}\ \{\n\ \ \ \ harry\n\}\n======\n\nI\ reckon\ I\ am\ not\ familiar\ with\ all\ the\ internals\ of\ Tcl\ but\ I\ find\ this\ would\nbe\ an\ interesting\ thing.\ Wouldn't\ this\ be\ a\ new\ way\ to\ have\ some\ sort\ of\nmacros?\n\n\[MS\]:\ \ Currently,\ `tailcall`\ is\ not\ bytecompiled.\ Everything\ happens\ at\nruntime.\ That\ extremely\ simple\ example\ could\ indeed\ be\ bytecoded\ in\ a\ minute,\nbut\ things\ get\ more\ involved\ as\ soon\ as\ `fred`\ has\ a\ bit\ more\ structure\ to\nit:\ arguments,\ local\ variables,\ namespace\ issues\ both\ for\ variable\ and\ command\nlookup,\ multiple\ exit\ points\ with\ different\ (or\ no)\ `tailcall`\ in\ them,\netc.\n\n\[jima\]:\ Thanks\ a\ lot\ Miguel\ for\ the\ answer.\ I\ see\ the\ point.\ I\ guess\ this\ is\nthe\ same\ with\ `\[uplevel\]\ 1`,\ isn't\ it?\n\n======\nproc\ fred\ \{\}\ \{\n\ \ \ \ uplevel\ 1\ \{\n\ \ \ \ \ \ \ \ #code\ here\n\ \ \ \ \}\n\}\n======\n\nWould\ it\ be\ interesting\ to\ define\ a\ case\ (like\ a\ contract)\ saying\ if\ your\ proc\nis\ simple\ enough\ then\ it\ gets\ bytecompiled\ and\ you\ get\ some\ benefits?\n\n\[MS\]:\ \ you\ do\ not\ mean\ \"bytecompiled\"\ but\ rather\ \"inlined\ into\ the\ caller\",\ as\nall\ `\[proc\]`\ bodies\ get\ bytecompiled.\ There\ are\ quite\ a\ few\ other\ issues\ with\ that,\nespecially\ to\ accomodate\ Tcl's\ dynamic\ nature.\ Changing\ one\ inlined\ proc\ would\ncause\ a\ spoiling\ of\ all\ bytecodes\ and\ recompilation\ of\ the\ world,\ at\ least\ with\nthe\ current\ approach\ to\ bytecode\ lifetime\ management.\n\n----\n\n\[AMG\]:\ Sounds\ a\ lot\ like\ `exec`\ in\ \[Unix\ shells\].\ \ See\ \[execline\]\ for\ more\ninformation\ on\ a\ noninteractive\ Unix\ shell\ where\ everything\ is\ done\ with\nexec/tailcall.\n\n\n\n----\n\n\[PYK\]\ 2015-12-06:\ \ \ Combine\ `tailcall`\ with\ an\ \[identity\ function%|%identity\]\ncommand\ to\ emulate\ `\[return\]`:\n\n\n======\nproc\ p1\ \{\}\ \{\n\ \ \ \ \ \ \ \ tailcall\ lindex\ \{Hello\ from\ p1\}\n\}\n======\n\n\n\n\n\n**\ Interaction\ with\ `\[try\]`\ **\n\n===none\n'''%'''\ proc\ foo\ \{\}\ \{puts\ \{I'm\ foo\}\}\n'''%'''\ proc\ bar\ \{\}\ \{puts\ \{I'm\ bar\}\;\ try\ \{tailcall\ foo\}\ finally\ \{puts\ exiting\}\}\n'''%'''\ foo\n''I'm\ foo''\n'''%'''\ bar\n''I'm\ bar''\n''exiting''\n''I'm\ foo''\n===\n31-03-2015\ \[HE\]\ I'm\ sure\ \;-)\ that\ I\ don't\ understood\ what\ happend\ there.\ Why\ \"exiting\"\ is\ printed\ before\ \"I'm\ foo\"\ when\ I\ call\ bar?\nIf\ I\ change\ bar\ to\n======\nproc\ bar\ \{\}\ \{puts\ \{I'm\ bar\}\;\ try\ \{puts\ tryBody\;\ tailcall\ foo\}\ finally\ \{puts\ exiting\}\;\ puts\ afterwards\}\n======\nand\ call\ it,\ I\ get:\n======none\nI'm\ bar\ntryBody\nexiting\nI'm\ foo\n======\nWhat\ I\ see\ is\ that\ tailcall\ replace\ the\ rest\ of\ proc\ even\ inside\ the\ body\ of\ try.\ \nBut\ then,\ why\ is\ the\ finally\ clause\ executed?\nAnd\ even,\ if\ we\ assume\ the\ finally\ clause\ has\ to\ be\ executed\ because\ it\ is\ documented\ always\ to\ be\ executed,\ \nthen\ there\ would\ be\ the\ question,\ why\ before\ the\ execution\ of\ the\ tailcall\ command?\n\n\[AMG\]:\ \[\[foo\]\]\ is\ invoked\ by\ replacing\ \[\[bar\]\]\ which\ implies\ the\ intervening\ \[\[\[try\]\]\]\ block\ must\ exit\ before\ \[\[foo\]\]\ can\ start.\n\n----\n\[wdb\]:\ Apparently,\ the\ `tailcall`\ closes\ one\ of\ the\ last\ gaps\ in\nTcl:\ Tail\ recursion\ as\ known\ in\ \[Scheme\].\n\n\n\n**\ Example:\ Cause\ Caller\ to\ Return\ **\n\n======\nproc\ one\ \{\}\ \{\n\ \ \ \ two\n\ \ \ \ return\ 8\n\}\n\nproc\ two\ \{\}\ \{\n\ \ \ \ tailcall\ return\ 5\n\}\n\none\ \;#\ ->\ 5\n======\n\n`one`\ returns\ `5`,\ not\ `8`,\ because\ by\ invoking\ two,\ which,\ through\ `\[tailcall\]`,\ is\ replaced\ by\ `\[return\]`.\n\n\n\n**\ Example:\ \ Factorial\ **\n\n\[NEM\]:\ As\ a\ test/demo\ of\ how\ to\ use\ this\ facility,\ here\ is\ a\ simple\ benchmark\nusing\ the\ factorial\ function:\n\n======\npackage\ require\ Tcl\ 8.6a1\nnamespace\ import\ ::tcl::mathop::*\ninterp\ alias\ \{\}\ tailcall\ \{\}\ tcl::unsupported::tailcall\n\n#\ Naive\ recursive\ factorial\ function\nproc\ fac\ n\ \{\n\ \ \ \ if\ \{\$n\ <=\ 1\}\ \{\n\ \ \ \ \ \ \ \ return\ 1\n\ \ \ \ \}\ else\ \{\n\ \ \ \ \ \ \ \ *\ \$n\ \[fac\ \[-\ \$n\ 1\]\]\n\ \ \ \ \}\n\}\n\n#\ Tail-recursive\ factorial\nproc\ fac-tr\ \{n\ \{k\ 1\}\}\ \{\n\ \ \ \ if\ \{\$n\ <=\ 1\}\ \{\n\ \ \ \ \ \ \ \ return\ \$k\n\ \ \ \ \}\ else\ \{\n\ \ \ \ \ \ \ \ tailcall\ fac-tr\ \[-\ \$n\ 1\]\ \[*\ \$n\ \$k\]\n\ \ \ \ \}\n\}\n\n#\ Iterative\ factorial\nproc\ fac-i\ n\ \{\n\ \ \ \ for\ \{set\ k\ 1\}\ \{\$n\ >\ 1\}\ \{incr\ n\ -1\}\ \{\n\ \ \ \ \ \ \ \ set\ k\ \[expr\ \{\$n*\$k\}\]\n\ \ \ \ \}\n\ \ \ \ return\ \$k\n\}\n\nproc\ test\ \{\}\ \{\n\ \ \ \ set\ fmt\ \{%-10s\ ..%-12.12s\ %s\}\n\ \ \ \ puts\ \[format\ \$fmt\ Implementation\ Result\ Time\]\n\ \ \ \ foreach\ n\ \{1\ 5\ 10\ 100\ 500\ 1000\ 2500\ 5000\ 10000\}\ \{\n\ \ \ \ \ \ \ \ puts\ \"\\nfac\ \$n:\"\n\ \ \ \ \ \ \ \ foreach\ impl\ \{fac\ fac-i\ fac-tr\}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ if\ \{\[catch\ \{\$impl\ \$n\}\ result\]\}\ \{\ \n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ set\ result\ n/a\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ set\ time\ n/a\n\ \ \ \ \ \ \ \ \ \ \ \ \}\ else\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ set\ time\ \[time\ \[list\ \$impl\ \$n\]\ 10\]\n\ \ \ \ \ \ \ \ \ \ \ \ \}\n\ \ \ \ \ \ \ \ \ \ \ \ puts\ \[format\ \$fmt\ \$impl\ \$result\ \$time\]\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \}\n\}\ntest\n======\n\nPutting\ this\ in\ a\ table,\ we\ get\ (timings\ taken\ on\ Linux\ box,\ 2.66GHz,\ 1GB\ RAM):\n\n%|\ N\ |\ `fac`\ Time\ |\ `fac-i`\ Time\ |\ `fac-tr`\ Time\ |%\n&|\ 1\ |\ 3.2\ |\ 3.0\ |\ 2.8\ |&\n&|\ 5\ |\ 10.1\ |\ 4.7\ |\ 19.4\ |&\n&|\ 10\ |\ 18.4\ |\ 6.4\ |\ 37.9\ |&\n&|\ 100\ |\ 345.5\ |\ 267.4\ |\ 717.8\ |&\n&|\ 500\ |\ 3133.9\ |\ 3715.6\ |\ 6182.5\ |&\n&|\ 1000\ |\ n/a\ |\ 13811.7\ |\ 19764.3\ |&\n&|\ 2500\ |\ n/a\ |\ 65121.1\ |\ 84556.5\ |&\n&|\ 5000\ |\ n/a\ |\ 241176.8\ |\ 288136.1\ |&\n&|\ 10000\ |\ n/a\ |\ 987057.8\ |\ 1643480.7\ |&\n\nAs\ we\ can\ see,\ the\ tail-recursive\ version\ is\ slightly\ slower\ than\ the\ iterative\nversion,\ and\ unlike\ the\ naive\ version,\ manages\ to\ not\ blow\ the\ stack.\n\n\n\n**\ Using\ Tailcall\ for\ Callbacks\ **\n**Using\ Tailcall\ for\ Callbacks**\n\[Napier\ /\ Dash\ Automation\]\ -\ 12-28-015\n\[Napier\ /\ Dash\ Automation\]\ 2015-12-28:\n\n======\nproc\ callback\ \{args\}\ \{tailcall\ namespace\ code\ \$args\}\n\nnamespace\ eval\ foo\ \{\nproc\ myProc\ var\ \{puts\ \$var\}\n\ \ \ \ \ proc\ myCall\ \{\}\ \{\ after\ 5000\ \[callback\ myProc\ \$::myVar\]\ \}\n\nafter\ 5000\ \[callback\ myProc\ \$myVar\]\n\n**\ Emulating\ `tailcall`\ **\n\n\[Lars\ H\]\ 2010-05-09:\ As\ of\ late,\ when\ writing\ an\ `\[uplevel\]`,\ I've\ sometimes\nfound\ myself\ thinking\ \"That\ would\ be\ slicker\ with\ `\[tailcall\]`,\ but\ I\ can't\nrely\ on\ 8.6\ features\ in\ this\ project\".\ Today\ it\ occurred\ to\ me\ that\ one\ can\nhowever\ use\ a\ `\[proc\]`\ to\ emulate\ the\ properties\ of\ `tailcall`\ that\ would\nbe\ needed\ in\ these\ cases,\ and\ thus\ provide\ a\ route\ for\ forward\ compatibility.\n\nThe\ main\ situation\ I've\ encountered\ is\ that\ of\ delegating\ to\ another\ command\nwhich\ may\ make\ use\ of\ `\[upvar\]`\ or\ `\[uplevel\]`.\ That's\ basically\ taken\ncare\ of\ by\n\n======\nproc\ utailcall\ args\ \{uplevel\ 2\ \$args\}\n======\n\nalthough\ it's\ safer\ to\ make\ it\n\n======\nproc\ utailcall\ args\ \{return\ -code\ return\ \[uplevel\ 2\ \$args\]\}\n======\n\nin\ case\ the\ \"terminate\ proc\ early\"\ aspect\ of\ `tailcall`\ is\ relied\ upon\;\ this\nis\ easy\ to\ do\ without\ thinking\ much\ about\ it.\n\nAnother\ aspect\ of\ `tailcall`\ is\ the\ name\ resolution\ of\ the\ called\ command.\nThis\ can\ be\ done\ as\ follows\n\n======\nproc\ ntailcall\ \{cmd\ args\}\ \{\n\ \ \ \ return\ -code\ return\ \[\n\ \ \ \ \ \ \ \ \[uplevel\ 1\ \[list\ ::namespace\ which\ \$cmd\]\]\ \{*\}\$args\n\ \ \ \ \]\n\}\n======\n\nbut\ it's\ almost\ as\ easy\ to\ do\ both\ at\ the\ same\ time\n\n======\nproc\ untailcall\ \{cmd\ args\}\ \{\n\ \ \ \ return\ -code\ return\ \[\n\ \ \ \ \ \ \ \ uplevel\ 2\ \[list\ \[uplevel\ 1\ \[list\ ::namespace\ which\ \$cmd\]\]\]\ \$args\n\ \ \ \ \]\n\}\n======\n\nA\ word\ of\ warning\ here\ is\ that\ this\ will\ produce\ a\ very\ confusing\ error\ message\nif\ the\ command\ is\ undefined,\ as\ `\[namespace\ which\]`\ returns\ an\ empty\ string\nin\ that\ case.\n\nA\ third\ aspect\ is\ that\ of\ preserving\ `\[return\]`\ levels.\n\n======\nproc\ rtailcall\ args\ \{\n\ \ \ \ catch\ \$args\ result\ options\n\ \ \ \ dict\ incr\ options\ -level\ 2\n\ \ \ \ return\ -options\ \$options\ \$result\n\}\n======\n\nThis\ leaves\ some\ extra\ material\ in\ the\ \[errorInfo\],\ but\ one\ can\ probably\ live\nwith\ that.\ Combining\ the\ \"r\"\ and\ \"u\"\ aspects\ is\ straightforward,\ but\ will\ leave\neven\ more:\n\n======\nproc\ rutailcall\ args\ \{\n\ \ \ \ catch\ \{uplevel\ 2\ \$args\}\ result\ options\n\ \ \ \ dict\ incr\ options\ -level\ 2\n\ \ \ \ return\ -options\ \$options\ \$result\n\}\n======\n\nTo\ complete\ the\ set,\ one\ might\ just\ as\ well\ write\ down\ the\ combination\ of\ the\n\"r\"\ and\ \"n\"\ aspects\n\n======\nproc\ rntailcall\ \{cmd\ args\}\ \{\n\ \ \ \ catch\ \{\n\ \ \ \ \ \ \ \ \[uplevel\ 1\ \[list\ ::namespace\ which\ \$cmd\]\]\ \{*\}\$args\n\ \ \ \ \}\ result\ options\n\ \ \ \ dict\ incr\ options\ -level\ 2\n\ \ \ \ return\ -options\ \$options\ \$result\n\}\n======\n\nand\ of\ all\ three\n\n======\nproc\ rnutailcall\ \{cmd\ args\}\ \{\n\ \ \ \ catch\ \{\n\ \ \ \ \ \ \ \ uplevel\ 2\ \[list\ \[uplevel\ 1\ \[list\ ::namespace\ which\ \$cmd\]\]\]\ \$args\n\ \ \ \ \}\ result\ options\n\ \ \ \ dict\ incr\ options\ -level\ 2\n\ \ \ \ return\ -options\ \$options\ \$result\n\}\n======\n\nBut\ note:\ ''all\ of\ the\ above\ will\ fail\ if\ used\ for\ tail\ recursion'',\ as\ soon\ as\nthe\ loops\ get\ long\ enough.\n\n\n**\ Replacement\ for\ `\[uplevel\]`\ **\n\n\[AMG\]:\ `\[uplevel\]`\ has\ limitations\ with\ respect\ to\ \[bytecode\]\ compilation\nand\ interpretation\ of\ `\[return\]`.\ \ If\ `\[uplevel\]`'s\ level\ count\ is\ `1`,\ and\nif\ it's\ the\ last\ thing\ being\ done\ in\ the\ `\[proc\]`,\ these\ limitations\ can\ be\navoided\ by\ using\ `\[tailcall\]`\ instead.\ \ Note\ that\ `\[uplevel\]`\ takes\ a\nscript\ whereas\ `\[tailcall\]`\ takes\ a\ command.\ \ If\ you\ want\ to\ pass\ a\ script\nto\ `\[tailcall\]`,\ make\ it\ be\ the\ sole\ argument\ to\ `\[try\]`.\n\nSee\ \[http://wiki.tcl.tk/1507#pagetocc0434a60%|%Possible\ uplevel\ deficiencies%|%\].\nAlso\ see\ \[http://wiki.tcl.tk/1507#pagetocb7539876%|%When\ to\ use\ uplevel\]\ for\nmore\ on\ when\ to\ use\ or\ avoid\ `\[uplevel\]`.\ \ See\n\[http://wiki.tcl.tk/1017#pagetoc74fae1d9%|%eval\ vs\ bytecode\]\ for\ discussion\ and\nperformance\ numbers\ regarding\ \[bytecode\]\ compilation\ with\ `\[eval\]`,\n`\[uplevel\]`,\ `\[try\]`,\ and\ others.\n\n**\ When\ to\ apply\ `tailcall`\ optimization\ **\n\n\[HaO\]\ 2012-12-14:\ Is\ it\ a\ good\ idea\ to\ replace\ any\ code:\n\n======\nproc\ proc1\ \{arg1\ arg2\}\ \{\n\ \ \ \ #\ do\ something\ here\ which\ finds\ arg3\ and\ arg4\n\ \ \ \ return\ \[proc2\ \$arg3\ \$arg4\]\n\}\n======\n\nby\n\n======\nproc\ proc1\ \{arg1\ arg2\}\ \{\n\ \ \ \ #\ do\ something\ here\ which\ finds\ arg3\ and\ arg4\n\ \ \ \ tailcall\ proc2\ \$arg3\ \$arg4\n\}\n======\n\nIf\ proc2\ is\ for\ sure\ found\ in\ the\ caller\ namespace?\n\nIs\ this\ an\ intelligent\ optimization?\n\nI\ came\ to\ this\ idea,\ as\ the\ TI\ C\ compiler\ calls\ this\ \"tailcall\ optimization\".\n\n\[AMG\]:\ Yes,\ except\ in\ a\ highly\ unlikely\ situation\ where\ `proc2`\ needs\ `proc1`\ to\ be\ visible\ in\ the\ stack.\ \ Procedures\ really\ ought\ not\ to\ care\ who\ called\ them,\ but\ Tcl\ makes\ all\ sorts\ of\ things\ possible,\ including\ stupid\ things.\n\n\n\n**\ Misc\ **\n\n\[NEM\]:\ \ Many\ thanks\ to\ \[MS\]\ for\ his\ hard\ work\ making\ this\ a\ reality!\n\n<<categories>>\ Command\ |\ Concept\ |\ Control\ structure\ |\ Functional\ Programming} CALL {my revision tailcall} CALL {::oo::Obj1878620 process revision/tailcall} CALL {::oo::Obj1878618 process}

-errorcode

NONE

-errorinfo

Unknow state transition: LINE -> END
    while executing
"error $msg"
    (class "::Wiki" method "render_wikit" line 6)
    invoked from within
"my render_$default_markup $N $C $mkup_rendering_engine"
    (class "::Wiki" method "render" line 8)
    invoked from within
"my render $name $C"
    (class "::Wiki" method "revision" line 31)
    invoked from within
"my revision $page"
    (class "::Wiki" method "process" line 56)
    invoked from within
"$server process [string trim $uri /]"

-errorline

4