Error processing request

Parameters

CONTENT_LENGTH0
REQUEST_METHODGET
REQUEST_URI/revision/uplevel?V=75
QUERY_STRINGV=75
CONTENT_TYPE
DOCUMENT_URI/revision/uplevel
DOCUMENT_ROOT/var/www/nikit/nikit/nginx/../docroot
SCGI1
SERVER_PROTOCOLHTTP/1.1
HTTPSon
REMOTE_ADDR172.70.135.64
REMOTE_PORT53382
SERVER_PORT4443
SERVER_NAMEwiki.tcl-lang.org
HTTP_HOSTwiki.tcl-lang.org
HTTP_CONNECTIONKeep-Alive
HTTP_ACCEPT_ENCODINGgzip, br
HTTP_X_FORWARDED_FOR44.192.75.131
HTTP_CF_RAY86bb8a90aca481b2-IAD
HTTP_X_FORWARDED_PROTOhttps
HTTP_CF_VISITOR{"scheme":"https"}
HTTP_ACCEPT*/*
HTTP_USER_AGENTclaudebot
HTTP_CF_CONNECTING_IP44.192.75.131
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 uplevel uplevel\ -\ Execute\ a\ script\ in\ a\ different\ stack\ frame\n\nhttp://www.purl.org/tcl/home/man/tcl8.5/TclCmd/uplevel.htm\ \n\n\n\nAll\ of\ the\ ''arg''\ arguments\ are\ concatenated\ as\ if\ they\ had\ been\ passed\ to\ '''\[concat\]'''\;\ the\ result\ is\ then\ evaluated\ in\ the\ variable\ context\ indicated\ by\ ''level''.\ '''Uplevel'''\ returns\ the\ result\ of\ that\ evaluation.\n\nIf\ ''level''\ is\ an\ integer\ then\ it\ gives\ a\ distance\ (up\ the\ procedure\ calling\ stack)\ to\ move\ before\ executing\ the\ command.\ If\ ''level''\ consists\ of\ #\ followed\ by\ a\ number\ then\ the\ number\ gives\ an\ absolute\ level\ number.\ If\ ''level''\ is\ omitted\ then\ it\ defaults\ to\ '''1'''.\ Level\ cannot\ be\ defaulted\ if\ the\ first\ ''command''\ argument\ starts\ with\ a\ digit\ or\ #.\n**\ Description\ **\n\[AMG\]:\ The\ last\ sentence\ of\ the\ previous\ paragraph\ bears\ repeating.\ \ For\ safety's\ sake,\ ''always''\ give\ the\ level\ explicitly,\ even\ though\ it's\ 1.\ \ This\ is\ because\ there\ are\ many\ situations\ where\ \[\[uplevel\]\]'s\ script\ argument\ comes\ from\ elsewhere,\ for\ instance\ when\ creating\ \[new\ control\ structures\]\ (a\ major\ use\ for\ \[\[uplevel\]\]).\ \ In\ those\ situations,\ the\ script\ argument\ could\ legitimately\ begin\ with\ a\ digit\ or\ a\ #\ mark,\ such\ as\ when\ it\ starts\ with\ a\ comment.\n'''`uplevel`'''\ concatenates\ the\ ''arg''\ arguments,\ in\ the\ same\ manner\ as\n<<discussion>>\n\n\[AMG\]:\ Executing\ a\ script\ in\ a\ different\ stack\ frame\ means\ only\ that\ the\ script\ is\ given\ local\ access\ to\ that\ stack\ frame's\ variables,\ plus\ the\ attendant\ change\ to\ \[\[\[info\ level\]\]\].\ \ It\ does\ not\ \"make\ the\ caller\ do\ something.\"\ \ I\ know\ of\ only\ one\ circumstance\ where\ this\ distinction\ matters,\ but\ it's\ critical.\ \ `uplevel\ \[return\]`\ is\ the\ same\ as\ `return`\ with\ no\ uplevel\;\ uplevel\ cannot\ be\ used\ to\ terminate\ the\ caller.\ \ (Instead\ use\ return's\ -level\ option.)\n\[PYK\]\ 2016-05-04:\ \ There's\ another\ effect\ to\ passing\ only\ one\ argument\ to\n----\n**When\ to\ use\ \[\[uplevel\]\]**\n\n\[AMG\]:\ \[\[uplevel\]\]\ provides\ access\ to\ another\ stack\ frame's\ local\ variables.\ \ In\ most\ cases,\ \[\[\[upvar\]\]\]\ is\ preferred\ over\ \[\[uplevel\]\]:\ it's\ simpler\ and\ it\ doesn't\ interfere\ with\ \[bytecode\]\ compilation.\ \ However,\ if\ the\ script\ to\ be\ executed\ comes\ from\ elsewhere\ (e.g.\ it\ was\ passed\ as\ an\ argument),\ \[\[uplevel\]\]\ is\ required.\n\n\nHarald\ Kirsch\ wrote\ in\ c.l.t:\n\[AMG\]:\ Executing\ a\ script\ in\ a\ different\ \[level\]\ means\ only\ that\ the\ script\ is\ given\ local\ access\ to\ that\ level's\ variables,\ plus\ the\ attendant\ change\ to\ `\[info\ level\]`.\ \ It\ does\ not\ \"make\ the\ caller\ do\ something.\"\ \ I\ know\ of\ only\ one\ circumstance\ where\ this\ distinction\ matters,\ but\ it's\ critical:\ \ `uplevel\ \[return\]`\ is\ the\ same\ as\ `return`\ with\ no\ `uplevel`\;\ uplevel\ cannot\ be\ used\ to\ terminate\ the\ caller.\ \ (Instead\ use\ return's\ -level\ option.)\n''Question:\ Is\ it\ possible\ to\ have\ \[\[macro\]\]\ as\ a\ counterpart\ to\ \[proc\]\ such\ that\ \[\[macro\]\]\ defines\ a\ \"function\"\ which\ is\ evaluated\ in\ the\ caller's\ stack\ context,\ i.e.,\ which\ does\ not\ create\ its\ own\ stack\ context?''\n\nSo\ how's\ this:\n======\n\ proc\ macro\ \{name\ body\}\ \{\n\ \ \ \ \ \ \ \ proc\ \$name\ \{\}\ \[list\ uplevel\ 1\ \$body\]\n\ \ \ \ \ \ \ \ set\ name\ \;#\ not\ needed,\ but\ maybe\ helpful\n\ \}\ \;#\ RS\n\ 0\ %\ macro\ now\ \{incr\ i\;\ incr\ j\}\n\ now\n\ 0\ %\ set\ j\ 10\;\ set\ i\ 1\n\ 1\n\ 0\ %\ now\n\ 11\n\nAs\ a\ variation,\ you\ might\ also\ have\ the\ body\ executed\ in\ global\ scope,\ if\ you\ want\ to\ avoid\ \[global\]\ commands\ (not\ recommended\ normally,\ since\ the\ variables\ you\ use\ are\ not\ cleaned\ up):\n\n\ proc\ Sub\ \{name\ body\}\ \{\n\ \ \ \ proc\ \$name\ \{\}\ \[list\ uplevel\ #0\ \$body\]\n\ \}\n\ %\ Sub\ nenv\ \{array\ size\ env\}\n\ %\ nenv\n\ 44\n\n\n\[DGP\]\ Note\ that\ \[\[macro\]\]\ will\ not\ be\ able\ to\ handle\ a\ ''body''\ that\ includes\ a\ \[return\]\ command,\ due\ to\ some\ fundamental\ limitations\ in\ Tcl\ itself.\ See\ tcllib::\[control\]\ documentation\ for\ some\ more\ details.\n\[AMG\]:\ `uplevel\ 0\ \$script`\ is\ the\ same\ as\ `eval\ \$script`.\n\[Tcl\ chatroom\]\ transcript:\n\n'''suchenwi''':\ I'm\ not\ sure\ what\ you\ mean\ with\ \"will\ not\ be\ able\ to\ handle\ a\ body\ that\ includes\ a\ return\ command.\"\ If\ there\ is\ one,\ it\ will\ cause\ the\ caller\ to\ return,\ I'd\ think.\ And\ that's\ like\ \"#define\ BYE\ return\;\"\ in\ C\ -\ expected\ behavior\ for\ a\ macro.\ \n\n'''dgp''':\ No,\ it\ won't.\ Try\ it.\ \n**\ Possible\ `uplevel`\ deficiencies\ **\n'''suchenwi''':\ But\ Harald\ Kirsch\ already\ followed\ up,\ he\ wants\ ''macro''\ to\ take\ arguments\ and\ have\ local\ variables.\ This\ is\ tricky\ indeed\ -\ you\ can't\ do\ a\ \"downlevel\"....\ \n\[AMG\]:\ Here's\ a\ nice,\ simple\ \[C\]-style\ ''do\ ...\ while''\ loop\ implemented\ using\ `uplevel`.\ \ Other\ implementations\ are\ available\ on\ the\ \[New\ Control\ Structures\]\ page.\n'''dgp''':\ Important\ to\ remember\ that\ '''uplevel'''\ adjusts\ only\ the\ command\ and\ variable\ substitution\ context.\ It\ can't\ really\ do\ anything\ to\ the\ calling\ stack.\ \n======\n'''suchenwi''':\ Ah\ -\ I\ see.\ Tried\ \"macro\ foo\ \{incr\ i\;\ incr\ j\;return\;puts\ \"oops\"\}\".\ \n\n'''dgp''':\ That\ doesn't\ test\ what\ needs\ testing.\n\n'''suchenwi''':\ '''foo'''\ itself\ returns\ (the\ oops\ won't\ come),\ but\ does\ not\ terminate\ its\ caller.\ One\ would\ have\ to\ do\n\n\ set\ body\ \[string\ map\ \{return\ \{return\ -code\ return\}\}\ \$body\]\ \;-)\ \n\n'''dgp''':\n\n\ macro\ mreturn\ return\ \n\ proc\ test\ \{\}\ \{puts\ a\;\ mreturn\;\ puts\ b\}\ \n\ test\ \n\n'''suchenwi''':\n\ \n\ proc\ macro\ \{name\ body\}\ \{\n\ \ \ \ proc\ \$name\ \{\}\ \[list\ uplevel\ 1\ \[string\ map\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ return\ \{return\ -code\ return\}\n\ \ \ \ \}\ \$body\]\]\}\ \n\n'''dgp''':\ Yes,\ that\ string\ map\ will\ handle\ more\ cases,\ but\ can't\ achieve\ \[\[return\ -code\ error\]\],\ etc.\ One\ way\ to\ fix\ this\ limitation\ would\ be\ to\ add\ a\ new\ status\ code\ to\ Tcl\ that\ caused\ the\ result\ to\ be\ evaluated\ in\ the\ caller's\ context\ by\ the\ caller.\n\n\ return\ -code\ eval\ \{set\ var\ val\}\ \n\nThen\ you\ would\ just\ map\ all\ \[\[return\ \$arg\ \$arg\ ...\]\]\ to\ ''return\ -code\ eval\ \{return\ \$arg\ \$arg\ ...\}''\ .\ Not\ completely\ sure\ what\ cans\ of\ worms\ get\ opened\ by\ that\ new\ feature\ though.\ Of\ course,\ with\ that\ status\ code\ available,\ \[\[macro\]\]\ would\ be\ much\ easier\ to\ write\ too.\n\n'''kennykb''':\ I\ like\ \[\[return\ -code\ eval\]\]\ --\ except\ for\ deciding\ whether\ Tcl_EvalObj\ and\ its\ friends\ should\ interpret\ it\ or\ return\ it\ to\ the\ C\ caller.\ \n\n'''rmax''':\ Hi\ Kevin.\ I\ think\ \[\[return\ -code\ eval\]\]\ would\ also\ help\ \[\[do\]\]\ to\ become\ complete\ for\ all\ possible\ cases.\n\n'''kennykb''':\ Yes,\ dgp's\ comments\ make\ it\ obvious\ that\ it\ could\ do\ return\ -code\ eval\ \{\ return\ -code\ eval\ \{\ return\ -code\ whatever\ \{...\ \}\}\}\ to\ break\ out\ of\ multiple\ scopes.\n\n'''dgp''':\ I\ still\ would\ not\ recommend\ that\ though.\ Just\ as\ it\ should\ always\ be\ \[\[uplevel\ 1\ ...\]\].\ \n\n'''kennykb''':\ Don:\ I\ wouldn't\ ''recommend''\ it\ either,\ but\ a\ certain\ depth\ of\ nesting\ is\ needed\ for\ \[\[control::do\]\]\ to\ handle\ \[\[return\ -code\]\]\ within\ the\ loop\ body,\ right?\ \n\n'''rmax''':\ You\ won't\ of\ course\ create\ nested\ \[\[return\ -code\ eval\]\]\ constructs\ yourself,\ but\ they\ could\ emerge\ from\ nested\ \[\[do\]\]\ loops\ or\ macro\ calls.\ \n\n'''dgp''':\ I\ think\ \[catch\]\ needs\ extending\ too.\ \n\n\ catch\ \{return\ -code\ error\ foo\}\ msg\ -->\ 2\ \n\ set\ msg\ -->\ foo\ \n\nBut\ where\ is\ the\ '1'?\ \nAdd\ another\ argument\ to\ \[catch\]\ to\ get\ the\ '1'.\ \n\n'''kennykb''':\ Yes,\ also\ need\ a\ place\ to\ stash\ the\ -errorcode\ and\ -errorInfo\ options\ to\ \[\[return\]\].\n\n'''dgp''':\ I\ think\ you\ can\ just\ grab\ them\ from\ ::errorInfo\ and\ ::errorCode\ directly.\ \n\n'''dgp''':\ ...\ but\ yes,\ status\ code\ '1'\ needs\ special\ handling,\ as\ always,\ to\ deal\ with\ ::errorInfo\ and\ ::errorCode.\ \nFor\ the\ rest,\ set\ code\ \{catch\ \$body\ msg\}\ \n\ if\ \{\$code\ ==\ 2\}\ \{\ \n\ #\ We\ caught\ a\ return\ \n\nD'oh!\ Make\ that\ \n\n\ set\ code\ \{catch\ \$body\ msg\ returncode\}\n\nthen...\ \n\n\ return\ -code\ eval\ \[list\ return\ -code\ \$returncode\ \$msg\]\ \n\ \}\ \n\n'''dgp''':\ Ah!\ I\ think\ I\ see\ what\ you\ were\ getting\ at!\ \n\n'''kennykb''':\ Hmmmm,\ it\ occurs\ to\ me\ that\ \[\[return\ -code\ eval\]\]\ subsumes\ all\ the\ others.\ \n\n'''dgp''':\ If\ \$body\ itself\ contains\ \[\[return\ -code\ eval\ \$script\]\].\ \n\n'''kennykb''':\ return\ -code\ error\ -errorcode\ code\ -errorinfo\ into\ message\ =>\ return\ -code\ eval\ \[\[list\ error\ message\ info\ code\]\]\n\ \nreturn\ -code\ break\ =>\ return\ -code\ eval\ break\ \n\n'''kennykb''':\ ...\ and\ the\ same\ for\ continue\ and\ return.\ \n\n'''suchenwi''':\ Looks\ like\ it\ would\ actually\ make\ the\ language\ smaller....\n\n'''dgp''':\ ...except\ maybe\ for\ the\ differences\ in\ ::errorInfo\ construction.\ \n\n'''kennykb''':\ We'd\ have\ to\ keep\ the\ other\ syntax\ on\ return\ for\ back\ compatibility,\ but\ I\ think\ it\ could\ simplify\ the\ mechanism.\ Oh,\ yeah,\ ::errorInfo\ construction.\ OK,\ make\ it\ return\ -code\ eval\ \[\[list\ error\ \$message\ \[\[doTheRightThingWith\ \$info\]\]\ \$code\]\].\ \n\n'''suchenwi''':\ ..and\ if\ eval\ is\ the\ last\ remaining\ value\ for\ -code,\ one\ could\ shorten\ that\ to\ -eval...\ \n\n'''kennykb''':\ Hmm,\ need\ a\ new\ command\ for\ those\ crazy\ enough\ to\ do\ \[\[return\ -code\ 6\]\].\ \n\n'''dgp''':\ How\ about\ \"-code\ ok\"\ ?\ I\ guess\ that's\ the\ default\ case\ where\ no\ eval\ script\ is\ done.\ \nNote:\ that's\ different\ from\ eval\ of\ an\ empty\ script.\ \n\nWhy\ a\ new\ command?\ \n\n'''kennykb''':\ I\ suppose\ if\ you\ wanted\ to\ be\ obsessive\ about\ it,\ you\ could\ say\ return\ -code\ ok\ \$value\ ->\ return\ -code\ eval\ \[\[list\ identity\ \$value\]\]\ where\ identity\ is\ a\ command\ that\ returns\ its\ arg,\ but\ I\ wouldn't\ go\ that\ far,\ myself.\ \n\n'''dgp''':\ We\ still\ need\ \[\[return\ -code\ 6\]\]\ if\ we\ want\ ability\ to\ create\ new\ status\ codes\ at\ the\ script\ level.\ \n\n'''rmax''':\ Isn't\ this\ possible\ to\ handle\ completely\ on\ the\ \[catch\]\ side?\ Doing\ it\ on\ the\ \[return\]\ side\ involves\ string\ operations\ on\ scripts,\ which\ hurts\ performance.\ \n\n'''dgp''':\ proc\ niftyNewBreak\ \{\}\ \{return\ -code\ 6\}\ \n\n'''kennykb''':\ proc\ niftyNewBreak\ \{\}\ \{\ return\ -code\ eval\ \{::tcl::raiseException\ 6\ \}\}\ ?\ 8^)\ \n\n'''rmax''':\ ...\ and\ there\ is\ the\ danger\ of\ substituting\ a\ \"return\"\ that\ isn't\ really\ a\ \[return\].\ \n\n'''dgp''':\ Ah,\ I\ see.\ \n\n'''kennykb''':\ Where\ are\ we\ doing\ string\ operations\ on\ scripts?\ \n\n'''dgp''':\ No\ substitution.\ catch\ and\ re-raise.\ \n\n'''rmax''':\ The\ implementation\ of\ \[\[do\]\]\ would\ have\ to\ substitute\ \"return\ -code\ ...\"\ by\ \"return\ -code\ eval\ \{return\ -code\ ...\}\"\ or\ am\ I\ wrong?\ \n\n'''kennykb''':\ Reinhard:\ Ah,\ but\ there's\ no\ string\ processing\ there.\ The\ new\ command\ is\ a\ pure\ list.\ \n\n'''dgp''':\ \[\[do\]\]\ includes\ the\ line:\ \n\n\ set\ code\ \[\[catch\ \{\ uplevel\ 1\ \$body\ \}\ result\]\]\n\nChange\ to:\ \n\n\ set\ code\ \[catch\ \{\ uplevel\ 1\ \$body\ \}\ result\ returnCode\]\ \n\nAdd\ a\ case\ to\ the\ \[switch\]\n\n\ 2\ \{return\ -code\ eval\ \[list\ return\ -code\ \$returnCode\ \$result\]\}\ \n\n'''kennykb''':\ Yes..\ and\ note\ that\ the\ thing\ to\ be\ 'eval'ed\ is\ a\ pure\ list.\ \n\n'''dgp''':\ The\ use\ of\ \[eval\]\ might\ prevent\ bytecode,\ so\ that's\ a\ performance\ issue,\ but\ there\ should\ be\ no\ need\ to\ reparse\ the\ strings.\ \n\n'''rmax''':\ wouldn't\ \"2\ \{return\ -code\ \$returnCode\ \$result\}\"\nbe\ sufficient?\ \n\n'''dgp''':\ No.\ The\ idea\ is\ that\ the\ \[return\]\ in\ \$body\ should\ act\ as\ if\ it\ was\ evaluated\ in\ the\ caller.\ Hmmm.\ so\ far\ have\ taken\ care\ of\ the\ first\ pass\ through\ \[\[do\]\].\ Remaining\ passes\ are\ handled\ by\ an\ \[\[uplevel\ 1\ \{while\ ...\}\]\]\ That\ probably\ needs\ similar\ handling.\ Yes.\ Same\ changes\ there.\ \n\n'''rmax''':\ I\ still\ think\ it\ would\ be\ sufficient\ for\ \[\[do\]\]\ to\ be\ able\ to\ catch\ and\ pass\ on\ the\ -code\ argument\ to\ return.\ \n\n'''kennykb''':\ Gentleb\[\[e\]\]ings,\ I\ think\ we're\ excising\ one\ of\ the\ language's\ major\ warts\ here.\ \n\n'''rmax''':\ Can\ you\ give\ an\ example\ of\ usage\ for\ \[\[do\]\]\ where\ that\ wouldn't\ be\ enough?\ \n\n*\ clock\ :\ 1011891602\ :\ Jan\ 24,2002\ Thursday\ 5pm\ GMT\ \n\n'''kennykb''':\ What\ if\ the\ body\ of\ the\ \[\[do\]\]\ contains\ \[\[return\ -code\ eval\]\]\ ?\ \n\n'''dgp''':\ I\ think\ that\ case\ is\ handled\ above.\ \n\n'''rmax''':\ do\ will\ pass\ on\ \[\[return\ -code\ eval\]\].\ \n\n'''dgp''':\ rmax:\ you\ don't\ want\ to\ return\ from\ \[\[do\]\],\ you\ want\ to\ return\ from\ the\ caller\ of\ \[\[do\]\].\ \n\n'''rmax''':\ Yes:\ \n\n\ do\ \{\ \n\ \ \ \ return\ -code\ return\ \n\ \}\ \n\ inside\ do:\ \n\ set\ code\ \[catch\ \{\ uplevel\ 1\ \$body\ \}\ result\ retCode\]\ \n\ ...\ \n\ 2\ \{\ return\ -code\ \[list\ return\ \$retCode\]\ \$result\ \}\ \n\nWhat\ about\ that?\n\n'''dgp''':\ That\ will\ return\ from\ the\ caller\ of\ \[\[do\]\]\ when\ what\ is\ intended\ is\ to\ return\ from\ the\ caller\ of\ the\ caller\ of\ \[\[do\]\].\n\ \n*\ rmax\ is\ totally\ confused\ now...\ has\ to\ try\ some\ things...\ \n\n'''kennykb''':\ That's\ yet\ another\ new\ syntax\ for\ \[return\].\ How\ is\ that\ preferable\ to\ \"return\ -code\ eval\ \[\[list\ return\ -code\ \$retCode\ \$result\]\]\"\ ?\ \n\n'''dgp''':\ Oh.\ I\ mis-read\ part\ of\ that\ last\ one.\ Given\ what\ we've\ described,\ that\ should\ be\ an\ error:\ \n\n'''rmax''':\ it\ is\ a\ bit\ shorter,\ and\ I\ haven't\ thought\ much\ about\ it...\ \n\n'''dgp''':\ unknown\ code:\ \"return\ 2\"\ \n\n'''kennykb''':\ Since\ we\ need\ \[\[return\ -code\ eval\]\]\ anyway\ --\ in\ order\ to\ implement\ \[\[macro\]\],\ I'm\ reluctant\ to\ invent\ still\ more\ syntax\ just\ to\ make\ \[\[do\]\]\ a\ tiny\ bit\ shorter.\ \n\n'''rmax''':\ Yep,\ Don.\ It\ implied\ another\ proposal\ of\ changing\ the\ syntax\ of\ \[return\].\ OK,\ Kevin,\ you\ win.\ \n\ \n'''dgp''':\ The\ numeric\ code\ for\ eval\ should\ be\ -1.\ \n\n'''kennykb''':\ Why\ -1?\ \n\n'''dgp''':\ #define\ TCL_EVAL\ -1\ \n\n'''dgp''':\ It's\ an\ interesting\ status\ code\ in\ that\ it\ is\ completely\ internal.\ No\ command\ will\ actually\ return\ it,\ it\ will\ return\ the\ result\ of\ eval'ing\ the\ result\ instead.\ \[\[return\ -code\ \$integer\]\]\ has\ been\ documented\ to\ allow\ any\ postive\ integer.\ -1\ won't\ interfere\ with\ previous\ extended\ status\ codes.\ \n\n'''kennykb''':\ OK,\ we\ have\ a\ compatibility\ issue\ with\ C\ code\ that\ calls\ commandProc's\ directly.\ (There\ are\ examples\ doing\ stuff\ like\ that\ in\ Brent's\ book,\ IIRC.)\ \n\n'''dgp''':\ hmmmm...\ take\ that\ back.\ I\ guess\ \"positive\"\ isn't\ in\ the\ docs\ after\ all.\ Are\ there\ any\ example\ doing\ that\ with\ *ObjCmd's?\ \n\n'''kennykb''':\ I\ don't\ think\ we\ have\ too\ much\ of\ a\ problem\ as\ long\ as\ we\ avoid\ whatever\ code\ \[exp_continue\]\ uses.\ \n\n'''dgp''':\ Any\ existing\ code\ is\ calling\ existing\ command\ procedures.\ None\ of\ which\ return\ the\ status\ code\ TCL_EVAL,\ so\ is\ there\ really\ a\ problem?\ \n\n'''bbh''':\ exp_continue\ seems\ to\ be\ -101\ \n\n'''kennykb''':\ Don:\ Doesn't\ Brent's\ code\ have\ a\ Tcl_GetCommandInfo\ so\ that\ it's\ actually\ calling\ a\ user-supplied\ command\ proc?\ \n\n'''dgp''':\ Anyhow\ look\ for\ a\ section\ \"Bypassing\ Tcl_Eval\".\ His\ code\ doesn't\ handle\ any\ extended\ return\ codes,\ so\ there's\ no\ new\ problem\ here.\ His\ routine\ is\ called\ Tcl_Invoke.\ Tcl_Invoke(\"break\",\ NULL)\;\ would\ cause\ problems\ now.\ \n\n'''*\ suchenwi\ has\ to\ stop\ mirroring\ this\ debate\ on\ http://wiki.tcl.tk/1507\ -\ real\ work\ calling...'''\n\n----\n\[TIP\]\ #90\ \[http://www.tcl.tk/cgi-bin/tct/tip/90.html\]\ is\ a\ formalized\ follow-up\ of\ the\ above\ discussion.\n...and\ is\ now\ incorporated\ in\ Tcl\ 8.5\ development.\n\n17\ October\ 2002:\ \[returneval\]\ provides\ a\ Tcl-only\ implementation\ of\ something\ very\ similar\ to\ the\ above\ \[\[return\ -code\ eval\]\].\n\n\[RHS\]\ TIP\ 90\ doesn't\ cover\ the\ ''-code\ eval''\ idea,\ does\ it?\ I\ read\ through\ it\ and\ it\ didn't\ seem\ to.\n\n\[Lars\ H\]:\ No,\ but\ ''-code\ eval''\ was\ considered\ as\ an\ alternative\ solution.\ Maybe\ it's\ not\ in\ the\ TIP\ itself,\ but\ in\ some\ of\ the\ surrounding\ discussion,\ however\ a\ good\ deal\ of\ thought\ was\ put\ into\ it.\n\n----\n\[AMG\]:\ `\[\[uplevel\ 0\ \$script\]\]`\ is\ the\ same\ as\ `\[\[\[eval\]\ \$script\]\]`.\n\n----\n**Possible\ \[\[uplevel\]\]\ deficiencies**\n\n\[AMG\]:\ Here's\ a\ nice,\ simple\ C-style\ ''do\ ...\ while''\ loop\ implemented\ using\ \[\[uplevel\]\].\ \ Other\ implementations\ are\ available\ on\ the\ \[New\ Control\ Structures\]\ page.\n\nproc\ do\ \{body\ while\ condition\}\ \{\n\ \ \ \ if\ \{\$while\ ne\ \{while\}\}\ \{\n\ \ \ \ if\ \{\$while\ ne\ \"while\"\}\ \{\n\ \ \ \ \}\n\ \ \ \ uplevel\ 1\ \$body\n\ \ \ \ uplevel\ 1\ \[list\ while\ \$condition\ \$body\]\n\}\n======\n\nI'm\ curious\ about\ the\ \[bytecode\]\ compilation\ properties\ of\ this\ \[control\ structure\].\ \ I\ don't\ think\ `\$condition`\ and\ `\$body`\ ever\ get\ compiled.\ \ Right?\ \ If\ so,\ is\ there\ any\ way\ to\ fix\ this?\ \ Putting\ the\ code\ to\ be\ executed\ into\ a\ randomly\ named\ \[proc\]\ would\ enable\ bytecode\ compilation,\ but\ running\ the\ code\ in\ a\ new\ level\ defeats\ the\ whole\ purpose\ of\ uplevel!\nI'm\ curious\ about\ the\ \[bytecode\]\ compilation\ properties\ of\ this\ \[control\ structure\].\ \ I\ don't\ think\ \$condition\ and\ \$body\ ever\ get\ compiled.\ \ Right?\ \ If\ so,\ is\ there\ any\ way\ to\ fix\ this?\ \ Putting\ the\ code\ to\ be\ executed\ into\ a\ randomly\ named\ \[proc\]\ would\ enable\ bytecode\ compilation,\ but\ running\ the\ code\ in\ a\ new\ stack\ frame\ defeats\ the\ whole\ purpose\ of\ uplevel!\nSo,\ does\ there\ exist\ a\ \[Tcl_Obj\]\ type\ for\ bytecode-compiled\ script\ snippets\ which\ are\ '''not'''\ given\ their\ own\ level?\nSo,\ does\ there\ exist\ a\ \[Tcl_Obj\]\ type\ for\ bytecode-compiled\ script\ snippets\ which\ are\ '''not'''\ given\ their\ own\ stack\ frame?\nI\ have\ another\ question.\ \ Can\ `\[do\]`\ be\ enhanced\ such\ that\ `\[return\]`\ inside\ the\ `\[do\]`\ body\ (or\ condition!)\ will\ cause\ `\[do\]`'s\ caller\ to\ return?\ \ Incrementing\ the\ `-level`\ option\ of\ `\[return\]`\ works,\ but\ this\ is\ not\ a\ change\ to\ `\[do\]`,\ it\ is\ a\ change\ to\ the\ arguments\ of\ `\[do\]`.\nI\ have\ another\ question.\ \ Can\ '''\[\[do\]\]'''\ be\ enhanced\ such\ that\ \[\[\[return\]\]\]\ inside\ the\ \[\[do\]\]\ body\ (or\ condition!)\ will\ cause\ \[\[do\]\]'s\ caller\ to\ return?\ \ Incrementing\ return's\ -level\ option\ works,\ but\ this\ is\ not\ a\ change\ to\ \[\[do\]\],\ it\ is\ a\ change\ to\ \[\[do\]\]'s\ arguments.\n======\nproc\ test1\ \{\}\ \{\n\ \ \ \ do\ \{return\ success\}\ while\ \{1\}\n\ \ \ \ return\ failure\n\}\nproc\ test2\ \{\}\ \{\n\ \ \ \ do\ \{return\ -level\ 2\ success\}\ while\ \{1\}\n\ \ \ \ return\ failure\n\}\ntest1\ \;#\ returns\ failure\ntest2\ \;#\ returns\ success\n======\n\n\[AMG\]:\ These\ are\ still\ burning\ questions...\ \ Anyone\ have\ answers?\n\n\[steveb\]\ Here\ is\ how\ I\ do\ this\ with\ Tcl8.5+\ and\ Jim\ Tcl.\ Needs\ some\ small\ tweaks\ if\ you\ want\ to\ support\ break\ and\ continue\ properly.\n\nproc\ do\ \{body\ while\ condition\}\ \{\n\ \ \ \ if\ \{\$while\ ne\ \{while\}\}\ \{\n\ \ \ \ if\ \{\$while\ ne\ \"while\"\}\ \{\n\ \ \ \ \}\n\ \ \ \ set\ rc\ \[catch\ \{\n\ \ \ \ \ \ \ \ uplevel\ 1\ \$body\n\ \ \ \ \ \ \ \ uplevel\ 1\ \[list\ while\ \$condition\ \$body\]\n\ \ \ \ \}\ msg\ opts\]\n\ \ \ \ if\ \{\$rc\}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ dict\ incr\ opts\ -level\n\ \ \ \ \}\n\ \ \ \ return\ \{*\}\$opts\ \$msg\n\}\n======\n\n\[DKF\]:\ With\ 8.6\ (specifically,\ \[tailcall\])\ you\ can\ do\ this:\n\nproc\ do\ \{body\ while\ condition\}\ \{\n\ \ \ \ if\ \{\$while\ ne\ \{while\}\}\ \{\n\ \ \ \ if\ \{\$while\ ne\ \"while\"\}\ \{\n\ \ \ \ \}\n\ \ \ \ tailcall\ while\ 1\ \$body\\n\[list\ if\ \$condition\ \{\}\ else\ break\]\n\}\n======\n\n\[AMG\]:\ Neat!\ \ These\ both\ work\ as-is\ in\ Tcl,\ and\ they\ pass\ the\ test1/test2\ test\ case\ I\ posted\ above.\ \ My\ remaining\ question\ is:\ how\ can\ I\ ensure\ that\ the\ code\ is\ \[bytecode\]d?\ \ With\ DKF's\ approach\ it\ might\ happen,\ but\ the\ bytecodes\ will\ be\ regenerated\ each\ time\ \[\[do\]\]\ is\ called.\n<<discussion>>\n\n\n**See\ also**\n2002-10-17:\ \ \[returneval\]\ provides\ a\ Tcl-only\ implementation\ of\ something\ very\ similar\ to\ the\ above\ `return\ -code\ eval`.\n\ \ \ *\ \[namespace\]\n\ \ \ *\ \[upvar\]\n\ \ \ *\ \[tailcall\]\n\[RHS\]:\ TIP\ 90\ doesn't\ cover\ the\ `-code\ eval`\ idea,\ does\ it?\ I\ read\ through\ it\ and\ it\ didn't\ seem\ to.\n<<categories>>\ Tcl\ syntax\ help\ |\ Arts\ and\ crafts\ of\ Tcl-Tk\ programming\ |\ Command\ |\ Introspection\ |\ Control\ Structure regexp2} CALL {my render uplevel uplevel\ -\ Execute\ a\ script\ in\ a\ different\ stack\ frame\n\nhttp://www.purl.org/tcl/home/man/tcl8.5/TclCmd/uplevel.htm\ \n\n\n\nAll\ of\ the\ ''arg''\ arguments\ are\ concatenated\ as\ if\ they\ had\ been\ passed\ to\ '''\[concat\]'''\;\ the\ result\ is\ then\ evaluated\ in\ the\ variable\ context\ indicated\ by\ ''level''.\ '''Uplevel'''\ returns\ the\ result\ of\ that\ evaluation.\n\nIf\ ''level''\ is\ an\ integer\ then\ it\ gives\ a\ distance\ (up\ the\ procedure\ calling\ stack)\ to\ move\ before\ executing\ the\ command.\ If\ ''level''\ consists\ of\ #\ followed\ by\ a\ number\ then\ the\ number\ gives\ an\ absolute\ level\ number.\ If\ ''level''\ is\ omitted\ then\ it\ defaults\ to\ '''1'''.\ Level\ cannot\ be\ defaulted\ if\ the\ first\ ''command''\ argument\ starts\ with\ a\ digit\ or\ #.\n**\ Description\ **\n\[AMG\]:\ The\ last\ sentence\ of\ the\ previous\ paragraph\ bears\ repeating.\ \ For\ safety's\ sake,\ ''always''\ give\ the\ level\ explicitly,\ even\ though\ it's\ 1.\ \ This\ is\ because\ there\ are\ many\ situations\ where\ \[\[uplevel\]\]'s\ script\ argument\ comes\ from\ elsewhere,\ for\ instance\ when\ creating\ \[new\ control\ structures\]\ (a\ major\ use\ for\ \[\[uplevel\]\]).\ \ In\ those\ situations,\ the\ script\ argument\ could\ legitimately\ begin\ with\ a\ digit\ or\ a\ #\ mark,\ such\ as\ when\ it\ starts\ with\ a\ comment.\n'''`uplevel`'''\ concatenates\ the\ ''arg''\ arguments,\ in\ the\ same\ manner\ as\n<<discussion>>\n\n\[AMG\]:\ Executing\ a\ script\ in\ a\ different\ stack\ frame\ means\ only\ that\ the\ script\ is\ given\ local\ access\ to\ that\ stack\ frame's\ variables,\ plus\ the\ attendant\ change\ to\ \[\[\[info\ level\]\]\].\ \ It\ does\ not\ \"make\ the\ caller\ do\ something.\"\ \ I\ know\ of\ only\ one\ circumstance\ where\ this\ distinction\ matters,\ but\ it's\ critical.\ \ `uplevel\ \[return\]`\ is\ the\ same\ as\ `return`\ with\ no\ uplevel\;\ uplevel\ cannot\ be\ used\ to\ terminate\ the\ caller.\ \ (Instead\ use\ return's\ -level\ option.)\n\[PYK\]\ 2016-05-04:\ \ There's\ another\ effect\ to\ passing\ only\ one\ argument\ to\n----\n**When\ to\ use\ \[\[uplevel\]\]**\n\n\[AMG\]:\ \[\[uplevel\]\]\ provides\ access\ to\ another\ stack\ frame's\ local\ variables.\ \ In\ most\ cases,\ \[\[\[upvar\]\]\]\ is\ preferred\ over\ \[\[uplevel\]\]:\ it's\ simpler\ and\ it\ doesn't\ interfere\ with\ \[bytecode\]\ compilation.\ \ However,\ if\ the\ script\ to\ be\ executed\ comes\ from\ elsewhere\ (e.g.\ it\ was\ passed\ as\ an\ argument),\ \[\[uplevel\]\]\ is\ required.\n\n\nHarald\ Kirsch\ wrote\ in\ c.l.t:\n\[AMG\]:\ Executing\ a\ script\ in\ a\ different\ \[level\]\ means\ only\ that\ the\ script\ is\ given\ local\ access\ to\ that\ level's\ variables,\ plus\ the\ attendant\ change\ to\ `\[info\ level\]`.\ \ It\ does\ not\ \"make\ the\ caller\ do\ something.\"\ \ I\ know\ of\ only\ one\ circumstance\ where\ this\ distinction\ matters,\ but\ it's\ critical:\ \ `uplevel\ \[return\]`\ is\ the\ same\ as\ `return`\ with\ no\ `uplevel`\;\ uplevel\ cannot\ be\ used\ to\ terminate\ the\ caller.\ \ (Instead\ use\ return's\ -level\ option.)\n''Question:\ Is\ it\ possible\ to\ have\ \[\[macro\]\]\ as\ a\ counterpart\ to\ \[proc\]\ such\ that\ \[\[macro\]\]\ defines\ a\ \"function\"\ which\ is\ evaluated\ in\ the\ caller's\ stack\ context,\ i.e.,\ which\ does\ not\ create\ its\ own\ stack\ context?''\n\nSo\ how's\ this:\n======\n\ proc\ macro\ \{name\ body\}\ \{\n\ \ \ \ \ \ \ \ proc\ \$name\ \{\}\ \[list\ uplevel\ 1\ \$body\]\n\ \ \ \ \ \ \ \ set\ name\ \;#\ not\ needed,\ but\ maybe\ helpful\n\ \}\ \;#\ RS\n\ 0\ %\ macro\ now\ \{incr\ i\;\ incr\ j\}\n\ now\n\ 0\ %\ set\ j\ 10\;\ set\ i\ 1\n\ 1\n\ 0\ %\ now\n\ 11\n\nAs\ a\ variation,\ you\ might\ also\ have\ the\ body\ executed\ in\ global\ scope,\ if\ you\ want\ to\ avoid\ \[global\]\ commands\ (not\ recommended\ normally,\ since\ the\ variables\ you\ use\ are\ not\ cleaned\ up):\n\n\ proc\ Sub\ \{name\ body\}\ \{\n\ \ \ \ proc\ \$name\ \{\}\ \[list\ uplevel\ #0\ \$body\]\n\ \}\n\ %\ Sub\ nenv\ \{array\ size\ env\}\n\ %\ nenv\n\ 44\n\n\n\[DGP\]\ Note\ that\ \[\[macro\]\]\ will\ not\ be\ able\ to\ handle\ a\ ''body''\ that\ includes\ a\ \[return\]\ command,\ due\ to\ some\ fundamental\ limitations\ in\ Tcl\ itself.\ See\ tcllib::\[control\]\ documentation\ for\ some\ more\ details.\n\[AMG\]:\ `uplevel\ 0\ \$script`\ is\ the\ same\ as\ `eval\ \$script`.\n\[Tcl\ chatroom\]\ transcript:\n\n'''suchenwi''':\ I'm\ not\ sure\ what\ you\ mean\ with\ \"will\ not\ be\ able\ to\ handle\ a\ body\ that\ includes\ a\ return\ command.\"\ If\ there\ is\ one,\ it\ will\ cause\ the\ caller\ to\ return,\ I'd\ think.\ And\ that's\ like\ \"#define\ BYE\ return\;\"\ in\ C\ -\ expected\ behavior\ for\ a\ macro.\ \n\n'''dgp''':\ No,\ it\ won't.\ Try\ it.\ \n**\ Possible\ `uplevel`\ deficiencies\ **\n'''suchenwi''':\ But\ Harald\ Kirsch\ already\ followed\ up,\ he\ wants\ ''macro''\ to\ take\ arguments\ and\ have\ local\ variables.\ This\ is\ tricky\ indeed\ -\ you\ can't\ do\ a\ \"downlevel\"....\ \n\[AMG\]:\ Here's\ a\ nice,\ simple\ \[C\]-style\ ''do\ ...\ while''\ loop\ implemented\ using\ `uplevel`.\ \ Other\ implementations\ are\ available\ on\ the\ \[New\ Control\ Structures\]\ page.\n'''dgp''':\ Important\ to\ remember\ that\ '''uplevel'''\ adjusts\ only\ the\ command\ and\ variable\ substitution\ context.\ It\ can't\ really\ do\ anything\ to\ the\ calling\ stack.\ \n======\n'''suchenwi''':\ Ah\ -\ I\ see.\ Tried\ \"macro\ foo\ \{incr\ i\;\ incr\ j\;return\;puts\ \"oops\"\}\".\ \n\n'''dgp''':\ That\ doesn't\ test\ what\ needs\ testing.\n\n'''suchenwi''':\ '''foo'''\ itself\ returns\ (the\ oops\ won't\ come),\ but\ does\ not\ terminate\ its\ caller.\ One\ would\ have\ to\ do\n\n\ set\ body\ \[string\ map\ \{return\ \{return\ -code\ return\}\}\ \$body\]\ \;-)\ \n\n'''dgp''':\n\n\ macro\ mreturn\ return\ \n\ proc\ test\ \{\}\ \{puts\ a\;\ mreturn\;\ puts\ b\}\ \n\ test\ \n\n'''suchenwi''':\n\ \n\ proc\ macro\ \{name\ body\}\ \{\n\ \ \ \ proc\ \$name\ \{\}\ \[list\ uplevel\ 1\ \[string\ map\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ \ return\ \{return\ -code\ return\}\n\ \ \ \ \}\ \$body\]\]\}\ \n\n'''dgp''':\ Yes,\ that\ string\ map\ will\ handle\ more\ cases,\ but\ can't\ achieve\ \[\[return\ -code\ error\]\],\ etc.\ One\ way\ to\ fix\ this\ limitation\ would\ be\ to\ add\ a\ new\ status\ code\ to\ Tcl\ that\ caused\ the\ result\ to\ be\ evaluated\ in\ the\ caller's\ context\ by\ the\ caller.\n\n\ return\ -code\ eval\ \{set\ var\ val\}\ \n\nThen\ you\ would\ just\ map\ all\ \[\[return\ \$arg\ \$arg\ ...\]\]\ to\ ''return\ -code\ eval\ \{return\ \$arg\ \$arg\ ...\}''\ .\ Not\ completely\ sure\ what\ cans\ of\ worms\ get\ opened\ by\ that\ new\ feature\ though.\ Of\ course,\ with\ that\ status\ code\ available,\ \[\[macro\]\]\ would\ be\ much\ easier\ to\ write\ too.\n\n'''kennykb''':\ I\ like\ \[\[return\ -code\ eval\]\]\ --\ except\ for\ deciding\ whether\ Tcl_EvalObj\ and\ its\ friends\ should\ interpret\ it\ or\ return\ it\ to\ the\ C\ caller.\ \n\n'''rmax''':\ Hi\ Kevin.\ I\ think\ \[\[return\ -code\ eval\]\]\ would\ also\ help\ \[\[do\]\]\ to\ become\ complete\ for\ all\ possible\ cases.\n\n'''kennykb''':\ Yes,\ dgp's\ comments\ make\ it\ obvious\ that\ it\ could\ do\ return\ -code\ eval\ \{\ return\ -code\ eval\ \{\ return\ -code\ whatever\ \{...\ \}\}\}\ to\ break\ out\ of\ multiple\ scopes.\n\n'''dgp''':\ I\ still\ would\ not\ recommend\ that\ though.\ Just\ as\ it\ should\ always\ be\ \[\[uplevel\ 1\ ...\]\].\ \n\n'''kennykb''':\ Don:\ I\ wouldn't\ ''recommend''\ it\ either,\ but\ a\ certain\ depth\ of\ nesting\ is\ needed\ for\ \[\[control::do\]\]\ to\ handle\ \[\[return\ -code\]\]\ within\ the\ loop\ body,\ right?\ \n\n'''rmax''':\ You\ won't\ of\ course\ create\ nested\ \[\[return\ -code\ eval\]\]\ constructs\ yourself,\ but\ they\ could\ emerge\ from\ nested\ \[\[do\]\]\ loops\ or\ macro\ calls.\ \n\n'''dgp''':\ I\ think\ \[catch\]\ needs\ extending\ too.\ \n\n\ catch\ \{return\ -code\ error\ foo\}\ msg\ -->\ 2\ \n\ set\ msg\ -->\ foo\ \n\nBut\ where\ is\ the\ '1'?\ \nAdd\ another\ argument\ to\ \[catch\]\ to\ get\ the\ '1'.\ \n\n'''kennykb''':\ Yes,\ also\ need\ a\ place\ to\ stash\ the\ -errorcode\ and\ -errorInfo\ options\ to\ \[\[return\]\].\n\n'''dgp''':\ I\ think\ you\ can\ just\ grab\ them\ from\ ::errorInfo\ and\ ::errorCode\ directly.\ \n\n'''dgp''':\ ...\ but\ yes,\ status\ code\ '1'\ needs\ special\ handling,\ as\ always,\ to\ deal\ with\ ::errorInfo\ and\ ::errorCode.\ \nFor\ the\ rest,\ set\ code\ \{catch\ \$body\ msg\}\ \n\ if\ \{\$code\ ==\ 2\}\ \{\ \n\ #\ We\ caught\ a\ return\ \n\nD'oh!\ Make\ that\ \n\n\ set\ code\ \{catch\ \$body\ msg\ returncode\}\n\nthen...\ \n\n\ return\ -code\ eval\ \[list\ return\ -code\ \$returncode\ \$msg\]\ \n\ \}\ \n\n'''dgp''':\ Ah!\ I\ think\ I\ see\ what\ you\ were\ getting\ at!\ \n\n'''kennykb''':\ Hmmmm,\ it\ occurs\ to\ me\ that\ \[\[return\ -code\ eval\]\]\ subsumes\ all\ the\ others.\ \n\n'''dgp''':\ If\ \$body\ itself\ contains\ \[\[return\ -code\ eval\ \$script\]\].\ \n\n'''kennykb''':\ return\ -code\ error\ -errorcode\ code\ -errorinfo\ into\ message\ =>\ return\ -code\ eval\ \[\[list\ error\ message\ info\ code\]\]\n\ \nreturn\ -code\ break\ =>\ return\ -code\ eval\ break\ \n\n'''kennykb''':\ ...\ and\ the\ same\ for\ continue\ and\ return.\ \n\n'''suchenwi''':\ Looks\ like\ it\ would\ actually\ make\ the\ language\ smaller....\n\n'''dgp''':\ ...except\ maybe\ for\ the\ differences\ in\ ::errorInfo\ construction.\ \n\n'''kennykb''':\ We'd\ have\ to\ keep\ the\ other\ syntax\ on\ return\ for\ back\ compatibility,\ but\ I\ think\ it\ could\ simplify\ the\ mechanism.\ Oh,\ yeah,\ ::errorInfo\ construction.\ OK,\ make\ it\ return\ -code\ eval\ \[\[list\ error\ \$message\ \[\[doTheRightThingWith\ \$info\]\]\ \$code\]\].\ \n\n'''suchenwi''':\ ..and\ if\ eval\ is\ the\ last\ remaining\ value\ for\ -code,\ one\ could\ shorten\ that\ to\ -eval...\ \n\n'''kennykb''':\ Hmm,\ need\ a\ new\ command\ for\ those\ crazy\ enough\ to\ do\ \[\[return\ -code\ 6\]\].\ \n\n'''dgp''':\ How\ about\ \"-code\ ok\"\ ?\ I\ guess\ that's\ the\ default\ case\ where\ no\ eval\ script\ is\ done.\ \nNote:\ that's\ different\ from\ eval\ of\ an\ empty\ script.\ \n\nWhy\ a\ new\ command?\ \n\n'''kennykb''':\ I\ suppose\ if\ you\ wanted\ to\ be\ obsessive\ about\ it,\ you\ could\ say\ return\ -code\ ok\ \$value\ ->\ return\ -code\ eval\ \[\[list\ identity\ \$value\]\]\ where\ identity\ is\ a\ command\ that\ returns\ its\ arg,\ but\ I\ wouldn't\ go\ that\ far,\ myself.\ \n\n'''dgp''':\ We\ still\ need\ \[\[return\ -code\ 6\]\]\ if\ we\ want\ ability\ to\ create\ new\ status\ codes\ at\ the\ script\ level.\ \n\n'''rmax''':\ Isn't\ this\ possible\ to\ handle\ completely\ on\ the\ \[catch\]\ side?\ Doing\ it\ on\ the\ \[return\]\ side\ involves\ string\ operations\ on\ scripts,\ which\ hurts\ performance.\ \n\n'''dgp''':\ proc\ niftyNewBreak\ \{\}\ \{return\ -code\ 6\}\ \n\n'''kennykb''':\ proc\ niftyNewBreak\ \{\}\ \{\ return\ -code\ eval\ \{::tcl::raiseException\ 6\ \}\}\ ?\ 8^)\ \n\n'''rmax''':\ ...\ and\ there\ is\ the\ danger\ of\ substituting\ a\ \"return\"\ that\ isn't\ really\ a\ \[return\].\ \n\n'''dgp''':\ Ah,\ I\ see.\ \n\n'''kennykb''':\ Where\ are\ we\ doing\ string\ operations\ on\ scripts?\ \n\n'''dgp''':\ No\ substitution.\ catch\ and\ re-raise.\ \n\n'''rmax''':\ The\ implementation\ of\ \[\[do\]\]\ would\ have\ to\ substitute\ \"return\ -code\ ...\"\ by\ \"return\ -code\ eval\ \{return\ -code\ ...\}\"\ or\ am\ I\ wrong?\ \n\n'''kennykb''':\ Reinhard:\ Ah,\ but\ there's\ no\ string\ processing\ there.\ The\ new\ command\ is\ a\ pure\ list.\ \n\n'''dgp''':\ \[\[do\]\]\ includes\ the\ line:\ \n\n\ set\ code\ \[\[catch\ \{\ uplevel\ 1\ \$body\ \}\ result\]\]\n\nChange\ to:\ \n\n\ set\ code\ \[catch\ \{\ uplevel\ 1\ \$body\ \}\ result\ returnCode\]\ \n\nAdd\ a\ case\ to\ the\ \[switch\]\n\n\ 2\ \{return\ -code\ eval\ \[list\ return\ -code\ \$returnCode\ \$result\]\}\ \n\n'''kennykb''':\ Yes..\ and\ note\ that\ the\ thing\ to\ be\ 'eval'ed\ is\ a\ pure\ list.\ \n\n'''dgp''':\ The\ use\ of\ \[eval\]\ might\ prevent\ bytecode,\ so\ that's\ a\ performance\ issue,\ but\ there\ should\ be\ no\ need\ to\ reparse\ the\ strings.\ \n\n'''rmax''':\ wouldn't\ \"2\ \{return\ -code\ \$returnCode\ \$result\}\"\nbe\ sufficient?\ \n\n'''dgp''':\ No.\ The\ idea\ is\ that\ the\ \[return\]\ in\ \$body\ should\ act\ as\ if\ it\ was\ evaluated\ in\ the\ caller.\ Hmmm.\ so\ far\ have\ taken\ care\ of\ the\ first\ pass\ through\ \[\[do\]\].\ Remaining\ passes\ are\ handled\ by\ an\ \[\[uplevel\ 1\ \{while\ ...\}\]\]\ That\ probably\ needs\ similar\ handling.\ Yes.\ Same\ changes\ there.\ \n\n'''rmax''':\ I\ still\ think\ it\ would\ be\ sufficient\ for\ \[\[do\]\]\ to\ be\ able\ to\ catch\ and\ pass\ on\ the\ -code\ argument\ to\ return.\ \n\n'''kennykb''':\ Gentleb\[\[e\]\]ings,\ I\ think\ we're\ excising\ one\ of\ the\ language's\ major\ warts\ here.\ \n\n'''rmax''':\ Can\ you\ give\ an\ example\ of\ usage\ for\ \[\[do\]\]\ where\ that\ wouldn't\ be\ enough?\ \n\n*\ clock\ :\ 1011891602\ :\ Jan\ 24,2002\ Thursday\ 5pm\ GMT\ \n\n'''kennykb''':\ What\ if\ the\ body\ of\ the\ \[\[do\]\]\ contains\ \[\[return\ -code\ eval\]\]\ ?\ \n\n'''dgp''':\ I\ think\ that\ case\ is\ handled\ above.\ \n\n'''rmax''':\ do\ will\ pass\ on\ \[\[return\ -code\ eval\]\].\ \n\n'''dgp''':\ rmax:\ you\ don't\ want\ to\ return\ from\ \[\[do\]\],\ you\ want\ to\ return\ from\ the\ caller\ of\ \[\[do\]\].\ \n\n'''rmax''':\ Yes:\ \n\n\ do\ \{\ \n\ \ \ \ return\ -code\ return\ \n\ \}\ \n\ inside\ do:\ \n\ set\ code\ \[catch\ \{\ uplevel\ 1\ \$body\ \}\ result\ retCode\]\ \n\ ...\ \n\ 2\ \{\ return\ -code\ \[list\ return\ \$retCode\]\ \$result\ \}\ \n\nWhat\ about\ that?\n\n'''dgp''':\ That\ will\ return\ from\ the\ caller\ of\ \[\[do\]\]\ when\ what\ is\ intended\ is\ to\ return\ from\ the\ caller\ of\ the\ caller\ of\ \[\[do\]\].\n\ \n*\ rmax\ is\ totally\ confused\ now...\ has\ to\ try\ some\ things...\ \n\n'''kennykb''':\ That's\ yet\ another\ new\ syntax\ for\ \[return\].\ How\ is\ that\ preferable\ to\ \"return\ -code\ eval\ \[\[list\ return\ -code\ \$retCode\ \$result\]\]\"\ ?\ \n\n'''dgp''':\ Oh.\ I\ mis-read\ part\ of\ that\ last\ one.\ Given\ what\ we've\ described,\ that\ should\ be\ an\ error:\ \n\n'''rmax''':\ it\ is\ a\ bit\ shorter,\ and\ I\ haven't\ thought\ much\ about\ it...\ \n\n'''dgp''':\ unknown\ code:\ \"return\ 2\"\ \n\n'''kennykb''':\ Since\ we\ need\ \[\[return\ -code\ eval\]\]\ anyway\ --\ in\ order\ to\ implement\ \[\[macro\]\],\ I'm\ reluctant\ to\ invent\ still\ more\ syntax\ just\ to\ make\ \[\[do\]\]\ a\ tiny\ bit\ shorter.\ \n\n'''rmax''':\ Yep,\ Don.\ It\ implied\ another\ proposal\ of\ changing\ the\ syntax\ of\ \[return\].\ OK,\ Kevin,\ you\ win.\ \n\ \n'''dgp''':\ The\ numeric\ code\ for\ eval\ should\ be\ -1.\ \n\n'''kennykb''':\ Why\ -1?\ \n\n'''dgp''':\ #define\ TCL_EVAL\ -1\ \n\n'''dgp''':\ It's\ an\ interesting\ status\ code\ in\ that\ it\ is\ completely\ internal.\ No\ command\ will\ actually\ return\ it,\ it\ will\ return\ the\ result\ of\ eval'ing\ the\ result\ instead.\ \[\[return\ -code\ \$integer\]\]\ has\ been\ documented\ to\ allow\ any\ postive\ integer.\ -1\ won't\ interfere\ with\ previous\ extended\ status\ codes.\ \n\n'''kennykb''':\ OK,\ we\ have\ a\ compatibility\ issue\ with\ C\ code\ that\ calls\ commandProc's\ directly.\ (There\ are\ examples\ doing\ stuff\ like\ that\ in\ Brent's\ book,\ IIRC.)\ \n\n'''dgp''':\ hmmmm...\ take\ that\ back.\ I\ guess\ \"positive\"\ isn't\ in\ the\ docs\ after\ all.\ Are\ there\ any\ example\ doing\ that\ with\ *ObjCmd's?\ \n\n'''kennykb''':\ I\ don't\ think\ we\ have\ too\ much\ of\ a\ problem\ as\ long\ as\ we\ avoid\ whatever\ code\ \[exp_continue\]\ uses.\ \n\n'''dgp''':\ Any\ existing\ code\ is\ calling\ existing\ command\ procedures.\ None\ of\ which\ return\ the\ status\ code\ TCL_EVAL,\ so\ is\ there\ really\ a\ problem?\ \n\n'''bbh''':\ exp_continue\ seems\ to\ be\ -101\ \n\n'''kennykb''':\ Don:\ Doesn't\ Brent's\ code\ have\ a\ Tcl_GetCommandInfo\ so\ that\ it's\ actually\ calling\ a\ user-supplied\ command\ proc?\ \n\n'''dgp''':\ Anyhow\ look\ for\ a\ section\ \"Bypassing\ Tcl_Eval\".\ His\ code\ doesn't\ handle\ any\ extended\ return\ codes,\ so\ there's\ no\ new\ problem\ here.\ His\ routine\ is\ called\ Tcl_Invoke.\ Tcl_Invoke(\"break\",\ NULL)\;\ would\ cause\ problems\ now.\ \n\n'''*\ suchenwi\ has\ to\ stop\ mirroring\ this\ debate\ on\ http://wiki.tcl.tk/1507\ -\ real\ work\ calling...'''\n\n----\n\[TIP\]\ #90\ \[http://www.tcl.tk/cgi-bin/tct/tip/90.html\]\ is\ a\ formalized\ follow-up\ of\ the\ above\ discussion.\n...and\ is\ now\ incorporated\ in\ Tcl\ 8.5\ development.\n\n17\ October\ 2002:\ \[returneval\]\ provides\ a\ Tcl-only\ implementation\ of\ something\ very\ similar\ to\ the\ above\ \[\[return\ -code\ eval\]\].\n\n\[RHS\]\ TIP\ 90\ doesn't\ cover\ the\ ''-code\ eval''\ idea,\ does\ it?\ I\ read\ through\ it\ and\ it\ didn't\ seem\ to.\n\n\[Lars\ H\]:\ No,\ but\ ''-code\ eval''\ was\ considered\ as\ an\ alternative\ solution.\ Maybe\ it's\ not\ in\ the\ TIP\ itself,\ but\ in\ some\ of\ the\ surrounding\ discussion,\ however\ a\ good\ deal\ of\ thought\ was\ put\ into\ it.\n\n----\n\[AMG\]:\ `\[\[uplevel\ 0\ \$script\]\]`\ is\ the\ same\ as\ `\[\[\[eval\]\ \$script\]\]`.\n\n----\n**Possible\ \[\[uplevel\]\]\ deficiencies**\n\n\[AMG\]:\ Here's\ a\ nice,\ simple\ C-style\ ''do\ ...\ while''\ loop\ implemented\ using\ \[\[uplevel\]\].\ \ Other\ implementations\ are\ available\ on\ the\ \[New\ Control\ Structures\]\ page.\n\nproc\ do\ \{body\ while\ condition\}\ \{\n\ \ \ \ if\ \{\$while\ ne\ \{while\}\}\ \{\n\ \ \ \ if\ \{\$while\ ne\ \"while\"\}\ \{\n\ \ \ \ \}\n\ \ \ \ uplevel\ 1\ \$body\n\ \ \ \ uplevel\ 1\ \[list\ while\ \$condition\ \$body\]\n\}\n======\n\nI'm\ curious\ about\ the\ \[bytecode\]\ compilation\ properties\ of\ this\ \[control\ structure\].\ \ I\ don't\ think\ `\$condition`\ and\ `\$body`\ ever\ get\ compiled.\ \ Right?\ \ If\ so,\ is\ there\ any\ way\ to\ fix\ this?\ \ Putting\ the\ code\ to\ be\ executed\ into\ a\ randomly\ named\ \[proc\]\ would\ enable\ bytecode\ compilation,\ but\ running\ the\ code\ in\ a\ new\ level\ defeats\ the\ whole\ purpose\ of\ uplevel!\nI'm\ curious\ about\ the\ \[bytecode\]\ compilation\ properties\ of\ this\ \[control\ structure\].\ \ I\ don't\ think\ \$condition\ and\ \$body\ ever\ get\ compiled.\ \ Right?\ \ If\ so,\ is\ there\ any\ way\ to\ fix\ this?\ \ Putting\ the\ code\ to\ be\ executed\ into\ a\ randomly\ named\ \[proc\]\ would\ enable\ bytecode\ compilation,\ but\ running\ the\ code\ in\ a\ new\ stack\ frame\ defeats\ the\ whole\ purpose\ of\ uplevel!\nSo,\ does\ there\ exist\ a\ \[Tcl_Obj\]\ type\ for\ bytecode-compiled\ script\ snippets\ which\ are\ '''not'''\ given\ their\ own\ level?\nSo,\ does\ there\ exist\ a\ \[Tcl_Obj\]\ type\ for\ bytecode-compiled\ script\ snippets\ which\ are\ '''not'''\ given\ their\ own\ stack\ frame?\nI\ have\ another\ question.\ \ Can\ `\[do\]`\ be\ enhanced\ such\ that\ `\[return\]`\ inside\ the\ `\[do\]`\ body\ (or\ condition!)\ will\ cause\ `\[do\]`'s\ caller\ to\ return?\ \ Incrementing\ the\ `-level`\ option\ of\ `\[return\]`\ works,\ but\ this\ is\ not\ a\ change\ to\ `\[do\]`,\ it\ is\ a\ change\ to\ the\ arguments\ of\ `\[do\]`.\nI\ have\ another\ question.\ \ Can\ '''\[\[do\]\]'''\ be\ enhanced\ such\ that\ \[\[\[return\]\]\]\ inside\ the\ \[\[do\]\]\ body\ (or\ condition!)\ will\ cause\ \[\[do\]\]'s\ caller\ to\ return?\ \ Incrementing\ return's\ -level\ option\ works,\ but\ this\ is\ not\ a\ change\ to\ \[\[do\]\],\ it\ is\ a\ change\ to\ \[\[do\]\]'s\ arguments.\n======\nproc\ test1\ \{\}\ \{\n\ \ \ \ do\ \{return\ success\}\ while\ \{1\}\n\ \ \ \ return\ failure\n\}\nproc\ test2\ \{\}\ \{\n\ \ \ \ do\ \{return\ -level\ 2\ success\}\ while\ \{1\}\n\ \ \ \ return\ failure\n\}\ntest1\ \;#\ returns\ failure\ntest2\ \;#\ returns\ success\n======\n\n\[AMG\]:\ These\ are\ still\ burning\ questions...\ \ Anyone\ have\ answers?\n\n\[steveb\]\ Here\ is\ how\ I\ do\ this\ with\ Tcl8.5+\ and\ Jim\ Tcl.\ Needs\ some\ small\ tweaks\ if\ you\ want\ to\ support\ break\ and\ continue\ properly.\n\nproc\ do\ \{body\ while\ condition\}\ \{\n\ \ \ \ if\ \{\$while\ ne\ \{while\}\}\ \{\n\ \ \ \ if\ \{\$while\ ne\ \"while\"\}\ \{\n\ \ \ \ \}\n\ \ \ \ set\ rc\ \[catch\ \{\n\ \ \ \ \ \ \ \ uplevel\ 1\ \$body\n\ \ \ \ \ \ \ \ uplevel\ 1\ \[list\ while\ \$condition\ \$body\]\n\ \ \ \ \}\ msg\ opts\]\n\ \ \ \ if\ \{\$rc\}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ dict\ incr\ opts\ -level\n\ \ \ \ \}\n\ \ \ \ return\ \{*\}\$opts\ \$msg\n\}\n======\n\n\[DKF\]:\ With\ 8.6\ (specifically,\ \[tailcall\])\ you\ can\ do\ this:\n\nproc\ do\ \{body\ while\ condition\}\ \{\n\ \ \ \ if\ \{\$while\ ne\ \{while\}\}\ \{\n\ \ \ \ if\ \{\$while\ ne\ \"while\"\}\ \{\n\ \ \ \ \}\n\ \ \ \ tailcall\ while\ 1\ \$body\\n\[list\ if\ \$condition\ \{\}\ else\ break\]\n\}\n======\n\n\[AMG\]:\ Neat!\ \ These\ both\ work\ as-is\ in\ Tcl,\ and\ they\ pass\ the\ test1/test2\ test\ case\ I\ posted\ above.\ \ My\ remaining\ question\ is:\ how\ can\ I\ ensure\ that\ the\ code\ is\ \[bytecode\]d?\ \ With\ DKF's\ approach\ it\ might\ happen,\ but\ the\ bytecodes\ will\ be\ regenerated\ each\ time\ \[\[do\]\]\ is\ called.\n<<discussion>>\n\n\n**See\ also**\n2002-10-17:\ \ \[returneval\]\ provides\ a\ Tcl-only\ implementation\ of\ something\ very\ similar\ to\ the\ above\ `return\ -code\ eval`.\n\ \ \ *\ \[namespace\]\n\ \ \ *\ \[upvar\]\n\ \ \ *\ \[tailcall\]\n\[RHS\]:\ TIP\ 90\ doesn't\ cover\ the\ `-code\ eval`\ idea,\ does\ it?\ I\ read\ through\ it\ and\ it\ didn't\ seem\ to.\n<<categories>>\ Tcl\ syntax\ help\ |\ Arts\ and\ crafts\ of\ Tcl-Tk\ programming\ |\ Command\ |\ Introspection\ |\ Control\ Structure} CALL {my revision uplevel} CALL {::oo::Obj1150216 process revision/uplevel} CALL {::oo::Obj1150214 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