How works return -code $value from the proc in TCL - return

I must use a proc Z, which returns something like "return -code 2" $something , but I can't understand how it's works.
proc X {} {
puts "X - in"
Y
puts "X - out"
}
proc Y {} {
puts "Y - in"
Z
puts "Y - out"
}
proc Z {} {
puts "Z - in"
return -code 2 "some value"
puts "Z - out"
}
X
Output is :
X - in
Y - in
Z - in
X - out
I can't change return in proc Z, but I also want that it continues his work in proc Y and puts "Y-out". Can i do it ?

The return command conceptually raises an exception (of type return, which corresponds to the TCL_RETURN result code in the Tcl C API) that is trapped by the procedure (strictly, by the procedure hull that does things like callframe management and argument marshalling) in which it runs to make that do something. In the case of a normal return, it simply makes the procedure return that value, but when the -code option is provided, it can direct the procedure to do something else; this is done after the callframe has been popped from the Tcl call stack.
Because 2 is the actual value of the TCL_RETURN result code, it means that it is telling the procedure hull (i.e., the overall Z procedure) to behave like it was a simple call to return, which is why puts "Y - out" isn't being executed; there's a return exception being processed as a result of the execution of Z. (FWIW, return -code 2 is pretty rare. return -code 1/return -code error is much more common, as it is a way of getting an error exception to be thrown, which is useful because stack traces are only built by error exceptions.)
You can override this processing using catch or try. It's a bit easier to get this right with try, since catch is a fairly broad-brush primitive. Try this:
proc Y {} {
puts "Y - in"
try {
Z
} on return {msg} {
puts "Z told us to return '$msg'"
}
puts "Y - out"
}
If you're just wanting to make a short piece of code work after the call but otherwise not interfere, try…finally is the right way:
proc Y {} {
puts "Y - in"
try {
Z
} finally {
puts "Y - out"
}
}
If you're using Tcl 8.5 (or before), you won't have try. Here's a version with catch:
proc Y {} {
puts "Y - in"
set code [catch {
Z
} msg]
if {$code == 2} {
puts "Z told us to return '$msg'"
}
puts "Y - out"
}
The problem with catch is that it is very easy to lose errors by accident.

Related

How to use Jenkins local defined variable in IF statement?

I have below code
def result = readFile('res.txt')
echo "${result}"
if ("${result}" > 5 )
{
echo "Yes"
} else {
echo "No"
}
}
It is printing NO but the answer in ${result} -> 11 which means it should print Yes. Can u pls help.
As noted in comments - you should cast the result to integer. Both result.toInteger() and Integer.parseInt(result) will work, although the first one is more straightforward and doesn't complain about extra white space (e.g. trailing endline character).
Besides, you don't need to mess with strange constructs like "${result}" because result is a normal variable, so your code may look like this:
def result = readFile('res.txt')
echo "${result}"
if (result.toInteger() > 5 ) {
echo "Yes"
} else {
echo "No"
}

How do I write busted unit tests for functions that return ok,err?

I have a Lua function that returns false followed by error message and want to test its behavior using the busted testing framework. Right now I am doing it a bit like this:
function safe_divide(a, b)
if b > 0 then -- buggy! should be b ~= 0
return a / b
else
return false, "division by zero"
end
end
describe("safe_divide", function()
it("can divide by positive numbers", function()
local ok, err = safe_divide(10.0, 5.0)
assert.truthy(ok)
assert.are.same(2.0, ok)
end)
it("errors when dividing by zero", function()
local ok, err = safe_divide(10.0, 0.0)
assert.not_truthy(ok)
assert.are.same("division by zero", err)
end)
it("can divide by negative numbers", function()
local ok, err = safe_divide(-10.0, -5.0)
assert.truthy(ok)
assert.are.same(2.0, ok)
end)
end)
There are two things that I don't like about my current approach:
Each test is 3 lines instead of a single clean line
When the 3rd test fails, busted just says that false is not a truthy value as expected, and never mentions the "divide by zero" error message.
Is there a way I can improve my test file to avoid these problems?
I think what I want to do is kind of similar to the has_error assertion in busted but that seems to be only for functions that actually raise exceptions, not for functions that return false followed by error message.
Busted makes use of luassert, that can be extended with your own assertions.
For instance, the following code uses a user-defined assertion answers that takes as first parameter a table of the expected result, and the effective function results as remaining parameters.
local assert = require "luassert"
local function safe_divide(a, b)
if b > 0 then -- buggy! should be b ~= 0
return a / b
else
return false, "division by zero"
end
end
local function answers(state, arguments)
local expected = arguments[1]
assert(type(expected) == "table")
for i = 2, #arguments do
if arguments[i] ~= expected[i-1] then
state.failure_message = "unexpected result " .. tostring (i-1) .. ": " .. tostring (arguments [i])
return false
end
end
return true
end
assert:register("assertion", "answers", answers)
describe("safe_divide", function()
it("can divide by positive numbers", function()
assert.answers({ 2.0 }, safe_divide(10.0, 5.0))
end)
it("errors when dividing by zero", function()
assert.answers({ false, "division by zero" }, safe_divide(10.0, 0.0))
end)
it("can divide by negative numbers", function()
assert.answers({ 2.0 }, safe_divide(-10.0, -5.0))
end)
end)
This code lacks correct formatting for the assertion message. You can look at the luaassert documentation, or at the predefined assertions. It contains a say module for translations of messages.

Print a table in pairs

I'm trying to use in pairs inside a function but it doesn't work, it just prints the first row (key). This is my code:
set = {1,2,3,4};
unset = {5,6,7,8};
function listen(ftype)
if (ftype == [[~]]) then
for num,str in pairs(set) do
return str;
end
end
if (ftype == [[$]]) then
for num,str in pairs(unset) do
return str;
end
end
end
print(listen([[~]])..[[ =:= ]]..listen([[$]]));
If I do something like this..
for num,str in pairs(unset) do
print(str);
end
It works like a charm. That’s exactly what I want but inside a function.
You can build your own iterator:
function double_pair(t1, t2)
local i = 0
return function() i = i + 1
return t1[i] and t1[i] .. " =:= " .. t2[i]
end
end
Then you can use it like this:
for str in double_pair(set, unset) do
print(str)
end
Output:
1 =:= 5
2 =:= 6
3 =:= 7
4 =:= 8
Note that you don't need semicolons to end your statement, unless the statements are in one line and you want to make them clear. And [[ =:= ]] is usually used to build long multi-line strings, normally we choose to use double quote " =:= " or single quote ' =:= '.
A function can't return multiple times. Putting an unconditional return inside a loop is nonsensical - it will never get to the second iteration of the loop.
You are essentially trying to return multiple values from the function. Lua supports that; you could, for instance, just return 1,2,3,4. For an unknown number of return values, you can build them up in a table and call unpack on it, like so:
function listen(ftype)
local result = {}
local num, str
if (ftype == [[~]]) then
for num,str in pairs(set) do
table.insert(result, str)
end
elseif (ftype == [[$]]) then
for num,str in pairs(unset) do
table.insert(result, str)
end
end
return unpack(result)
end
But since your results are already in a couple tables, it would be silly to reconstruct them that way. You can just unpack the originals:
function listen(ftype)
if (ftype == [[~]]) then
return unpack(set)
elseif (ftype == [[$]]) then
return unpack(unset)
end
end
Great. But when you put the function call into an expression like your print statement, it will only return the first value, which puts you back where you started.
So to print out your pairs, you can't avoid having to either:
1) do some iteration outside the function
or
2) do the actual printing inside the function
The cleanest solution is probably a custom iterator, as suggested by #YuHao.

How to create a "new mode" for vim (i.e., loop and get user input, then execute the associated actions)

I'm trying to create something of a "new mode" in vim. The details of the mode are unimportant, but there is one thing I need to be able to do.
I need to do something like the following pseudo-code:
get user input (movement keys like "j" or complex keys like "dd")
while user_input != <esc>
execute the user input
endwhile
In other words, I need a loop that will read what the user is doing, then perform the associated action.
I've already got the following code:
let char = nr2char(getchar())
while char =~ '^\w$'
execute "normal ". char
let char = nr2char(getchar())
endwhile
This works fine for user movements (j, k, etc.), but fails for more complex multi-character commands like dd.
Also, this is a small annoyance, but the cursor disappears during getchar(), meaning you effectively can't see the cursor (this is of less importance because of what I'm trying to do, but hopefully has a solution as well).
Does anyone have any idea how I can get multi-character actions to work?
I think you might be interested in submode.vim, if not to use it, to at least see how they've implemented this feature.
I usually redefine locally (:h map-<buffer>, for instance) the things this new mode is meant to change. And I also override <esc> to unregister those things from the mode.
This is the easier approach IMO.
Just for the record, for creating a new mode that accepts commands of multiple length you usually use something like a parse tree with keys and commands. Here is a simple version in vim:
let g:EvalTree = { 'root': {} }
function! s:AddKeyMapRecursive(root, keys, command) abort
if !has_key(a:root, a:keys[0])
let a:root[a:keys[0]] = { 'command': '', 'children': {} }
endif
if len(a:keys) == 1
let a:root[a:keys[0]].command = a:command
else
call s:AddKeyMapRecursive(a:root[a:keys[0]].children, a:keys[1 : ], a:command)
endif
endfunction
function! g:EvalTree.AddMap(keys, command) abort
call s:AddKeyMapRecursive(l:self.root, a:keys, a:command)
endfunction
function! s:GetNodeRecursive(root, keys) abort
if !has_key(a:root, a:keys[0])
return 0
endif
if len(a:keys) == 1
return a:root[a:keys[0]]
else
return s:GetNodeRecursive(a:root[a:keys[0]].children, a:keys[1 : ])
endif
endfunction
function! g:EvalTree.GetNode(keys) abort
return s:GetNodeRecursive(l:self.root, a:keys)
endfunction
You can insert in this tree like:
call g:EvalTree.AddMap('hw', ":echo 'hello world'<CR>")
call g:EvalTree.AddMap('DA', 'ggdG')
Later you can use this tree to eval things in the loop you mention. Although you will probably need a also a queue to do this. You can define one as:
let g:TextQueue = { 'text': '', 'index': 0 }
function! g:TextQueue.Push(c) abort
let l:self.text .= a:c
endfunction
function! g:TextQueue.Pop(...) abort
let l:self.index += get(a:, 1, 1)
endfunction
function! g:TextQueue.CheckFirst() abort
return l:self.text[l:self.index]
endfunction
function! g:TextQueue.Text() abort
return l:self.text[l:self.index : ]
endfunction
function! g:TextQueue.Empty() abort
return l:self.index >= strlen(l:self.text)
endfunction
function! g:TextQueue.ReInitialize() abort
let [l:self.text, l:self.index] = ['', 0]
endfunction
And using that queue and the tree make the evaluation loop. This is the part were I don't really know how to do it properly myself, but after trying a while a came to a functional (although ugly and very inefficient since eval some things much more than necessary) code that is this:
function! s:Execute(map) abort
execute 'normal! ' . a:map.command
redraw
call g:TextQueue.Pop(strlen(a:map.keys))
let [a:map.keys, a:map.command] = ['', '']
endfunction
function! s:LimitTimeHasElapsed(time) abort
return (a:time + 1 < localtime())
endfunction
function! g:EvalTree.Start() abort
let l:time = localtime()
let l:stored = { 'keys': '', 'command': '' }
while g:TextQueue.CheckFirst() !=# "\<Esc>"
let l:char_code = getchar(0)
if l:char_code
call g:TextQueue.Push(nr2char(l:char_code))
endif
if !g:TextQueue.Empty()
let l:possible_maps = g:EvalTree.GetNode(g:TextQueue.Text())
if type(l:possible_maps) != type({})
if !empty(l:stored.command)
call s:Execute(l:stored)
elseif g:TextQueue.CheckFirst() !=# "\<Esc>"
call g:TextQueue.Pop()
endif
let l:time = localtime()
continue
endif
if l:possible_maps.command !=# ''
let l:stored.keys = g:TextQueue.Text()
let l:stored.command = l:possible_maps.command
if l:possible_maps.children == {} || s:LimitTimeHasElapsed(l:time)
call s:Execute(l:stored)
let l:time = localtime()
endif
elseif s:LimitTimeHasElapsed(l:time)
let [l:stored.keys, l:stored.command] = ['', '']
call g:TextQueue.pop()
let l:time = localtime()
endif
else
call g:TextQueue.ReInitialize()
let l:time = localtime()
endif
sleep 20m
endwhile
endfunction
Now you simply have to define a several mappings. Ie:
call g:EvalTree.AddMap('hw', ":echo 'hello workd'\<CR>")
call g:EvalTree.AddMap('h', 'h')
call g:EvalTree.AddMap('l', 'l')
call g:EvalTree.AddMap('j', 'j')
call g:EvalTree.AddMap('k', 'k')
call g:EvalTree.AddMap('H', '0')
call g:EvalTree.AddMap('L', '$')
call g:EvalTree.AddMap('K', 'H')
call g:EvalTree.AddMap('J', 'L')
call g:EvalTree.AddMap('dd', 'dd')
call g:EvalTree.AddMap('Z', 'yap')
call g:EvalTree.AddMap('D', 'dap')
call g:EvalTree.AddMap('ab', ":echo 'hello'\<CR>")
call g:EvalTree.AddMap('abc', ":echo 'world'\<CR>")
call g:EvalTree.AddMap('abcd', ":echo 'hello world'\<CR>")
And finally, start the evaluation:
call g:EvalTree.Start()
You all may also be interested in watching my plugin 'EXtend.vim' and its ReadLine() function. It doesn't eval multi character commands but does a couple of things that are indeed pretty interesting, like emulating cursors and selections inside its submode.

PEG for Python style indentation

How would you write a Parsing Expression Grammar in any of the following Parser Generators (PEG.js, Citrus, Treetop) which can handle Python/Haskell/CoffeScript style indentation:
Examples of a not-yet-existing programming language:
square x =
x * x
cube x =
x * square x
fib n =
if n <= 1
0
else
fib(n - 2) + fib(n - 1) # some cheating allowed here with brackets
Update:
Don't try to write an interpreter for the examples above. I'm only interested in the indentation problem. Another example might be parsing the following:
foo
bar = 1
baz = 2
tap
zap = 3
# should yield (ruby style hashmap):
# {:foo => { :bar => 1, :baz => 2}, :tap => { :zap => 3 } }
Pure PEG cannot parse indentation.
But peg.js can.
I did a quick-and-dirty experiment (being inspired by Ira Baxter's comment about cheating) and wrote a simple tokenizer.
For a more complete solution (a complete parser) please see this question: Parse indentation level with PEG.js
/* Initializations */
{
function start(first, tail) {
var done = [first[1]];
for (var i = 0; i < tail.length; i++) {
done = done.concat(tail[i][1][0])
done.push(tail[i][1][1]);
}
return done;
}
var depths = [0];
function indent(s) {
var depth = s.length;
if (depth == depths[0]) return [];
if (depth > depths[0]) {
depths.unshift(depth);
return ["INDENT"];
}
var dents = [];
while (depth < depths[0]) {
depths.shift();
dents.push("DEDENT");
}
if (depth != depths[0]) dents.push("BADDENT");
return dents;
}
}
/* The real grammar */
start = first:line tail:(newline line)* newline? { return start(first, tail) }
line = depth:indent s:text { return [depth, s] }
indent = s:" "* { return indent(s) }
text = c:[^\n]* { return c.join("") }
newline = "\n" {}
depths is a stack of indentations. indent() gives back an array of indentation tokens and start() unwraps the array to make the parser behave somewhat like a stream.
peg.js produces for the text:
alpha
beta
gamma
delta
epsilon
zeta
eta
theta
iota
these results:
[
"alpha",
"INDENT",
"beta",
"gamma",
"INDENT",
"delta",
"DEDENT",
"DEDENT",
"epsilon",
"INDENT",
"zeta",
"DEDENT",
"BADDENT",
"eta",
"theta",
"INDENT",
"iota",
"DEDENT",
"",
""
]
This tokenizer even catches bad indents.
I think an indentation-sensitive language like that is context-sensitive. I believe PEG can only do context-free langauges.
Note that, while nalply's answer is certainly correct that PEG.js can do it via external state (ie the dreaded global variables), it can be a dangerous path to walk down (worse than the usual problems with global variables). Some rules can initially match (and then run their actions) but parent rules can fail thus causing the action run to be invalid. If external state is changed in such an action, you can end up with invalid state. This is super awful, and could lead to tremors, vomiting, and death. Some issues and solutions to this are in the comments here: https://github.com/dmajda/pegjs/issues/45
So what we are really doing here with indentation is creating something like a C-style blocks which often have their own lexical scope. If I were writing a compiler for a language like that I think I would try and have the lexer keep track of the indentation. Every time the indentation increases it could insert a '{' token. Likewise every time it decreases it could inset an '}' token. Then writing an expression grammar with explicit curly braces to represent lexical scope becomes more straight forward.
You can do this in Treetop by using semantic predicates. In this case you need a semantic predicate that detects closing a white-space indented block due to the occurrence of another line that has the same or lesser indentation. The predicate must count the indentation from the opening line, and return true (block closed) if the current line's indentation has finished at the same or shorter length. Because the closing condition is context-dependent, it must not be memoized.
Here's the example code I'm about to add to Treetop's documentation. Note that I've overridden Treetop's SyntaxNode inspect method to make it easier to visualise the result.
grammar IndentedBlocks
rule top
# Initialise the indent stack with a sentinel:
&{|s| #indents = [-1] }
nested_blocks
{
def inspect
nested_blocks.inspect
end
}
end
rule nested_blocks
(
# Do not try to extract this semantic predicate into a new rule.
# It will be memo-ized incorrectly because #indents.last will change.
!{|s|
# Peek at the following indentation:
save = index; i = _nt_indentation; index = save
# We're closing if the indentation is less or the same as our enclosing block's:
closing = i.text_value.length <= #indents.last
}
block
)*
{
def inspect
elements.map{|e| e.block.inspect}*"\n"
end
}
end
rule block
indented_line # The block's opening line
&{|s| # Push the indent level to the stack
level = s[0].indentation.text_value.length
#indents << level
true
}
nested_blocks # Parse any nested blocks
&{|s| # Pop the indent stack
# Note that under no circumstances should "nested_blocks" fail, or the stack will be mis-aligned
#indents.pop
true
}
{
def inspect
indented_line.inspect +
(nested_blocks.elements.size > 0 ? (
"\n{\n" +
nested_blocks.elements.map { |content|
content.block.inspect+"\n"
}*'' +
"}"
)
: "")
end
}
end
rule indented_line
indentation text:((!"\n" .)*) "\n"
{
def inspect
text.text_value
end
}
end
rule indentation
' '*
end
end
Here's a little test driver program so you can try it easily:
require 'polyglot'
require 'treetop'
require 'indented_blocks'
parser = IndentedBlocksParser.new
input = <<END
def foo
here is some indented text
here it's further indented
and here the same
but here it's further again
and some more like that
before going back to here
down again
back twice
and start from the beginning again
with only a small block this time
END
parse_tree = parser.parse input
p parse_tree
I know this is an old thread, but I just wanted to add some PEGjs code to the answers. This code will parse a piece of text and "nest" it into a sort of "AST-ish" structure. It only goes one deep and it looks ugly, furthermore it does not really use the return values to create the right structure but keeps an in-memory tree of your syntax and it will return that at the end. This might well become unwieldy and cause some performance issues, but at least it does what it's supposed to.
Note: Make sure you have tabs instead of spaces!
{
var indentStack = [],
rootScope = {
value: "PROGRAM",
values: [],
scopes: []
};
function addToRootScope(text) {
// Here we wiggle with the form and append the new
// scope to the rootScope.
if (!text) return;
if (indentStack.length === 0) {
rootScope.scopes.unshift({
text: text,
statements: []
});
}
else {
rootScope.scopes[0].statements.push(text);
}
}
}
/* Add some grammar */
start
= lines: (line EOL+)*
{
return rootScope;
}
line
= line: (samedent t:text { addToRootScope(t); }) &EOL
/ line: (indent t:text { addToRootScope(t); }) &EOL
/ line: (dedent t:text { addToRootScope(t); }) &EOL
/ line: [ \t]* &EOL
/ EOF
samedent
= i:[\t]* &{ return i.length === indentStack.length; }
{
console.log("s:", i.length, " level:", indentStack.length);
}
indent
= i:[\t]+ &{ return i.length > indentStack.length; }
{
indentStack.push("");
console.log("i:", i.length, " level:", indentStack.length);
}
dedent
= i:[\t]* &{ return i.length < indentStack.length; }
{
for (var j = 0; j < i.length + 1; j++) {
indentStack.pop();
}
console.log("d:", i.length + 1, " level:", indentStack.length);
}
text
= numbers: number+ { return numbers.join(""); }
/ txt: character+ { return txt.join(""); }
number
= $[0-9]
character
= $[ a-zA-Z->+]
__
= [ ]+
_
= [ ]*
EOF
= !.
EOL
= "\r\n"
/ "\n"
/ "\r"

Resources