Eiffel: how do I get the type of a particular operand of a procedure - introspection

As I can see into the debugger it's possible to get the operands, and name of procedure, is there a way to get it?
PROCEDURE=>operands returns a detachable that seems return the operands only when they have been setted into the agent
Do I have pass through any REFLECTOR class because the PROCEDURE class doesn't have this function and in this case why?
Seems that estudio has access to informations as ROUTINE client don't have, why is he a privileged one? is he cheating?

The following code demonstrates how to retrieve information about open argument types of a routine object:
p: ROUTINE -- Routine object.
t: TYPE [detachable ANY] -- Current open argument type.
do
p := agent (i: INTEGER; s: STRING)
do
end
across
1 |..| p.open_count as i
loop
t := p.generating_type.generic_parameter_type (1).generic_parameter_type (i.item)
io.put_string (t.name)
io.put_new_line
end
For me, the code above prints
INTEGER_32
!STRING_8
Comments:
p.open_count gives the total number of open arguments.
p.generating_type retrieves the type of the routine object.
p.generating_type.generic_parameter_type (1) retrieves the type of the open arguments tuple object.
The final call to generating_type retrieves the type of the open argument with index i.item.

Related

VBA: How to pass For Loop iterator to sub? [duplicate]

I've just had an irritating 30 minutes on a "compiler error" in VBA (Access 2003) caused by my use of parenthesis around the arguments I'm passing to a Sub I defined.
I've been searching to find a decent article/tutorial/instruction as to when parenthesis are necessary/appropriate/inappropriate/forbidden, but can't find any clear guidelines.
There is perfect logic to the Parentheses Rule in VB(A), and it goes like this.
If a procedure (function or sub) is called with arguments, and the call is on a line with other statements or keywords, the arguments must be enclosed in parentheses. This to distinguish the arguments belonging to the procedure call from the rest of the line. So:
1: If CheckConditions(A, B, C) = DONT_PROCEED Then Exit Sub
is a valid line; the call to CheckConditions needs the parentheses to indicate what other bits of the line are its arguments. Conversely, this would produce a syntax error:
2: If CheckConditions A, B, C = DONT_PROCEED Then Exit Sub
Because it is impossible to parse.
With a procedure call as the only statement on the line, parentheses aren't needed because it is clear that the arguments belong to the procedure call:
3: SaveNewValues Value1, Value2, Value3
While this results in a syntax error (for sound reasons discussed below):
4: SaveNewValues(Value1, Value2, Value3)
To avoid confusion about parentheses or no parentheses (in fact, to avoid the Parentheses Rule entirely), it is always a good idea to use the Call keyword for calls like these; that ensures that the procedure call is not the only statement on the line, thus requiring parentheses:
5: Call SaveNewValues(Value1, Value2, Value3)
So if you get in the habit of preceding self-contained procedure calls with the Call keyword, you can forget the Parentheses Rule, because you can then always enclose your arguments in parentheses.
The matter is confused by the additional role parentheses play in VB(A) (and many other languages): they also indicate evaluation precedence for expressions. If you use parentheses in any other context but to enclose procedure call arguments, VB(A) will attempt to evaluate the expression in the parentheses to a resulting simple value.
Thus, in example 4, where parentheses are illegal for enclosing the arguments, VB(A) will instead attempt to evaluate the expression in the parentheses. Since (Value1, Value 2, Value3) is not an expression that can be evaluated, a syntax error ensues.
This also explains why calls with a variable passed ByRef act as if called ByVal if the argument is enclosed in parentheses. In the example above, where function p is called with ByRef parameter a, there is a big difference between these two calls to p:
6: p a
And
7: p(a)
As discussed above, 6 is the correct syntax: the call is alone on its line, so parentheses should not be used to enclose the arguments.
In 7, the argument is enclosed in parentheses anyway, prompting VB(A) to evaluate the enclosed expression to a simple value. Which of course is the very definition of passing ByVal. The parentheses ensure that instead of a pointer to a, the value of a is passed, and a is left unmodified.
This also explains why the parentheses rule doesn't always seem to hold sway. Clearest example is a MsgBox call:
8: MsgBox "Hello World!"
And
9: MsgBox ("Hello World!")
Are both correct, even though the parentheses rule dictates that 9 should be wrong. It is, of course, but all that happens is that VB(A) evaluates the expression in the parentheses. And the string literal evaluates to the exact same string literal, so that the actual call made is 8. In other words: calls to single-argument procedures with constant or string literal arguments have the identical result with or without parentheses. (This is why even my MsgBox calls are preceded by the Call keyword.)
Finally, this explains odd Type Mismatch errors and weird behavior when passing Object arguments. Let's say your application has a HighlightContent procedure that takes a TextBox as argument (and, you'll never guess, highlights it contents). You call this to select all text in the textbox. You can call this procedure in three syntactically correct ways:
10: HighlightContent txtName
11: HighlightContent (txtName)
12: Call HighlightContent(txtName)
Let's say your user has entered "John" in the textbox and your application calls HighlightContent. What will happen, which call will work?
10 and 12 are correct; the name John will be highlighted in the textbox. But 11 is syntactically correct, but will result in a compile or runtime error. Why? Because the parentheses are out of place. That will prompt VB(A) to attempt an evaluation of the expression in the parentheses. And the result of the evaluation of an object will most often be the value of its default property; .Text, in this case. So calling the procedure like 11 will not pass the TextBox object to the procedure, but a string value "John". Resulting in a Type Mismatch.
From Here:
Using the VBScript Call Statement to Call a Subroutine
The use of Call statement is optional when you wish to call a subroutine. The purpose of the Call statement when used with a Sub is to allow you to enclose the argument list in parentheses. However, if a subroutine does not pass any arguments, then you still should not use parentheses when calling a Sub using the Call statement.
Call MySubroutine
If a subroutine has arguments, you must use parentheses when using the Call statement. If there is more than one argument, you must separate the arguments with commas.
Call MySubroutine(intUsageFee, intTimeInHours, "DevGuru")
Calling the Function
There are two possible ways to call a function. You may either call the function directly, by name only, or you may call it by using the VBScript Call statement.
Calling a Function by Name
When calling a function directly by name and when there is no assignment to a returned value, all of the following are legal syntax:
MyFunction
MyFunction()
MyFunction intUsageFee, intTimeInHours, "DevGuru"
If you want a returned value, you can assign the function to a variable. Note that if there is one or more arguments, you must use the parentheses.
returnval = MyFunction
returnval = MyFunction()
returnval = MyFunction(intUsageFee, intTimeInHours, "DevGuru")
I just found some weird behavior calling a function with / without parentheses. Google took me here.
sub test()
dim a as double
a = 1#
p(a) 'this won't change a's value
Debug.Print a '1
p a ' this is expected behavior
Debug.Print a '2
Call p(a) 'this is also valid
Debug.Print a '3
end sub
Function p(a as Double) 'default is byref
a = a + 1
end function
My conclusion is that you have to use either Call or omitting the parentheses when calling a function with only one parameter, otherwise the parameter isn't passed by reference (it's still get called, as I checked already).
I just spent 10 minutes figuring out an "types incompatible" exception while calling a Sub which takes 1 argument via
CallMe(argument)
As it turns out, this is invalid, googling lead me here and finally
Call CallMe(argument)
or
CallMe argument
did the trick. So you must not use the brackets when calling a sub without the call-statement which only takes 1 argument.
When you use
Call MySub you should use parentheses around parameters, but if you omit Call, you don't need parentheses.
1 - By default, do not use parentheses when calling procedures or functions:
MsgBox "Hello World"
2 - If you are calling a function, and are interested in its result, then you must enclose its arguments with parentheses:
Dim s As String
Dim l As Long
s = "Hello World"
l = Len(s)
3 - If you want to use the call keyword with a procedure, then you must enclose the arguments with parentheses (e.g. when you want to assign the result in a variable or to use the function in an expression):
Call MsgBox("Hello World")
4 - If you want to force a ByRef argument (the default) to be passed ByVal, then enclose the ByRef argument with parentheses:
Sub Test
Dim text As String
text = "Hello World"
ChangeArgument((text))
MsgBox text
End Sub
Sub ChangeArgument(ByRef s As String)
s = "Changed"
End Sub
This displays "Hello World"
Well this was asked long ago but I just faced this problem and I found this question which I feel hasn't been fully answered yet. Hope I shed some light over this issue so that it serves for newcomers.
As I have seen previous answers mainly focus on the fact that whenever you use the "Call" statement you must enclose the arguments within parenthesis. Although this is true 1 it is definitely not the main source triggering this "strange" syntax errors.
The key point has been briefly noted by Cristopher. I'll just reference the documentation and further explain a little.
Ref Docs 2
So the main point is that the parenthesis determine whether you are interested in the return value of the function/sub/method/statement you are calling or not, that is, whether it must be returned to store it on a variable or not.
Having said that one may run into several problems
Calling with parenthesis a procedure that doesn't return a value 3.
Sub no_value_return(x as Integer)
Dim dummy as Integer
dummy = x
End Sub
'Error
no_value_return(1)
'No error
no_value_return 1
Calling with parenthesis a procedure that returns a value but not assigning it to a variable
Function value_return(ByVal x as Integer)
Dim value_return as Integer
value_return = x*2
End Function
'Error:
value_return(1)
'No error
Dim result as Integer
result = value_return(1)
Some additional examples
'Error - No value returned since no parenthesis were specified
Dim result as Integer
result = value_return 1
'No error - Special case
Dim result as Variant
result = value_return 1
'The reason for this is that variant is the only data type that accepts
'the special value "Empty"
'No error - You can perfectly ignore the returned value even if it exists
value_return 1
1 https://learn.microsoft.com/en-us/office/vba/language/concepts/getting-started/calling-sub-and-function-procedures
2 https://learn.microsoft.com/en-us/office/vba/language/concepts/getting-started/using-parentheses-in-code
3 Note this isn't aplicable for function procedures or built-in functions since those must always return a value
I use another logic to differ when to use brackets or not. If you function doesn't return a value (void type in C-liked languages), you don't need the parentheses. And it is always true for subs because returning value is the main difference between sub and function. Otherwise you have to use parentheses.

Reading class method definition - what is Callable?

I am relatively new to python, and I started to read the docs when using packages, but I'm having a hard time understanding some of it:
post_to_main_thread(self: open3d.cpu.pybind.visualization.gui.Application, arg0: open3d::visualization::gui::Window, arg1: Callable[[], None]) → None
the only thing here that I don't understand is the arg1 with that callable, and I can't find an explanation on it at the web.
Interesting question!
So post_to_main_thread() is a method that takes 3 arguments (inputs/variables) and returns None.
Because it's a method (a function associated with a class, not just a standalone function) the first argument, self, refers to the instance of the class that the function is part of.
The other two arguments are passed within the function parentheses, as expected with a standalone function. So a call might look like this:
instance_name = open3d.visualization.gui.Application(...)
instance_name.post_to_main_thread(arg1, arg2)
arg1 should be of type open3d::visualization::gui::Window. This is an instance of the class open3d.visualization.gui.Window().
arg2 should be of type Callable(). This describes a number of built-ins that you can find details about in the documentation. To quote:
The subscription syntax must always be used with exactly two values: the argument list and the return type. The argument list must be a list of types or an ellipsis; the return type must be a single type.
So in this case the type should be Callable[[], None], which means this should be a function that takes no input and returns None. Carrying on from our previous example, you'd pass this as an argument like so:
def my_callable:
print('Hello, World!')
return
instance_name.post_to_main_thread(arg1, my_callable)
Does that clear things up?

Binary Search algorithm random array

I don't understand why the recursive function always gives me zero result, even if I put values inside the array.
it seems that size (a) == 0
recursive function binarySearch_R (a, value) result (bsresult)
real, intent(in) :: a(6), value
integer :: bsresult, mid
mid = size(a)/2 + 1
if (size(a) == 0) then
bsresult = 0 ! not found
else if (a(mid) > value) then
bsresult= binarySearch_R(a(:mid-1), value)
else if (a(mid) < value) then
bsresult = binarySearch_R(a(mid+1:), value)
if (bsresult /= 0) then
bsresult = mid + bsresult
end if
else
bsresult = mid ! SUCCESS!!
end if
end function binarySearch_R
program hji
read*, a
read*, value
print*, binarySearch_R
end program hji
Chapter 1: The dangers of implicit typing
The first thing I strongly recommend you do is to include the line
implicit none
after the program line. This will suppress implicit typing, and the resulting errors will give you some useful insight into what is happening.
If you did that, you'd get an error message:
$ gfortran -o binsearch binsearch.f90
binsearch.f90:23:12:
read*, a
1
Error: Symbol ‘a’ at (1) has no IMPLICIT type
binsearch.f90:27:25:
print*,binarySearch_R
1
Error: Symbol ‘binarysearch_r’ at (1) has no IMPLICIT type
binsearch.f90:24:16:
read*, value
1
Error: Symbol ‘value’ at (1) has no IMPLICIT type
It doesn't matter that a, value, and binarySearch_R were defined in the function. As the function is not part of the program block, the program doesn't know what these are.
With implicit typing active, it simply assumed that all three are simple real variables. (The type depends on the first letter of the variable name, i through n are integer, everything else is real)
Because this implicit typing can so easily hide coding errors, it's strongly, strongly suggested to always switch it off.
Which also means that we have to declare the variables a and value in the program:
program hji
implicit none
real :: a(6), value
...
end program hji
Chapter 2: How to introduce a function to the program?
So how does the program get access to the function? There are four ways:
The best way: Use a module
module mod_binsearch
implicit none
contains
recursive function binarySearch_R (a, value) result (bsresult)
...
end function binarySearch_R
end module mod_binsearch
program hji
use mod_binsearch
implicit none
real :: a(6), value
...
end program hji
Note that the use statement has to be before the implicit none.
This method leaves the function separate, but callable.
It automatically checks that the parameters (that's something we'll be coming to in a bit) are correct.
Have the function contained in the program.
Between the final line of code of the program and the end program statement, add the keyword contains, followed by the function code (everything from recursive function ... to end function ...).
This is the quick-and-dirty method. You have to be careful with this method as the function will automatically have access to the program's variables unless there's a new variable with that name declared inside the function.
The convoluted way: Interfaces
Create an interface block in the declaration section of your program's source code,
and repeat the interface information in there.
This still allows the compiler to check whether the function is invoked correctly, but it's up to you to ensure that this interface block is correct and matches the actual implementation.
The really, really ugly way: Declare it like a variable, invoke it like a function.
Please don't do that.
Chapter 3: Calling a function
When you call a function, you have to use the parentheses and give it all the parameters that it expects. In your case, you need to type
print *, binarySearch_r(a, value)
Chapter 4: Dynamic arrays as dummy parameters
In the successive recursive calls to the function, the array gets smaller and smaller.
But the dummy parameter is always the same size (6). Not only will this interfere with your algorithm, but this can also lead to dangerously undefined memory access.
Fortunately, specially for intent(in) dummy parameters, you can use dynamic arrays:
recursive function binarySearch_R(a, value)
real, intent(in) :: a(:), value
The single colon tells the compiler to expect a one-dimensional array, but not the length of it. Since you're already using size(a), it should automatically work.
Too long for a comment, but not an answer (and to any Fortran experts reading this, yes, there are one or two places where I gloss over some details because I think they are unimportant at this stage) ...
The way the code is written does not allow the compiler to help you. As far as the compiler is concerned there is no connection between the function and the program. As far as the program is concerned a is, because you haven't told the compiler otherwise, assumed to be a real scalar value. The a in the program is not the same thing as the a in the function - there is no connection between the function and the program.
The same is true for value.
The same is true for binarysearch_r - and if you don't believe this delete the function definition from the source code and recompile the program.
So, what must you do to fix the code ?
First step: modify your source code so that it looks like this:
program hji
... program code goes here ...
contains
recursive function binarySearch_R (a, value) result (bsresult)
... function code goes here ...
end function binarySearch_R
end program hji
This first step allows the compiler to see the connection between the program and the function.
Second step: insert the line implicit none immediately after the line program hji. This second step allows the compiler to spot any errors you make with the types (real or integer, etc) and ranks (scalar, array, etc) of the variables you declare.
Third step: recompile and start dealing with the errors the compiler identifies. One of them will be that you do not pass the arguments to the function so the line
print*, binarySearch_R
in the program will have to change to
print*, binarySearch_R(a, value)

VBA Calling function with / without Parenthesis [duplicate]

I am getting the 800A0414 error in lines 7 and 12 of this script:
Module Module1
Dim p
Sub Main()
CreateObject("Wscript.Shell").Run("program.bat", 0, True)
p = Process.GetProcessesByName("program")
If p.Count > 0 Then
WScript.Sleep(300000)
Else
CreateObject("Wscript.Shell").Run("program clean up.bat", 0, True)
End If
End Sub
Private Function WScript() As Object
Throw New NotImplementedException
End Function
End Module
I am trying to run a batch script, that starts a process, then wait until the process terminates, then run another batch script. I also do not want any command boxes being shown. If their is a easier way please let me know.
Thanks for your help
When you enclose a procedure's argument list in parentheses, you must use the Call keyword:
Call CreateObject("WScript.Shell").Run("program.bat", 0, True)
If you omit the Call keyword, you must also drop parentheses:
CreateObject("WScript.Shell").Run "program.bat", 0, True
To complete what's been said before:
When Call keyword is used to call a procedure (i.e. sub or function) the arguments must be enclosed in parentheses, except when the procedure has no arguments in which case the parentheses are optional. For example all the statements:
Call test()
Call test
Call test(1,2)
are valid, but not this one:
Call test 1
When calling a procedure without using the Call keyword, the parentheses can only be used when either the procedure has zero or one argument or the procedure has a return value (i.e. is a function) and its value is used in the same statement. For example all the statements:
test()
test(1)
test(1,2)
a = test
a = test(1,2)
a = test(test(1,2),2)
are valid, except the third one which has more than one argument. In case it's not clear, the inner call of "test" in the last statement is valid because its return value is used as an argument to another call.
Note that whenever parentheses is used in this text, it is meant to imply the possible comma-separated values as well.
Seems to me this is a VB.NET, not VBScript code.
You have Shell function in VB.NET (and other methods).
Anyway, Run returns any error code returned by the program, and if you
store that result in a variable, you can use parentheses in this case.
Dim lResult As Long
lResult = CreateObject("Wscript.Shell").Run("program.bat", 0, True)
The rest was answered by #Helen.

Set the value of an object from inside a method in Io

I'm trying to set the value of an object from inside a method. Here's an example:
myObject := list(1,2,3,4,5)
myObject drop := method(
self := list()
)
myObject drop
myObject println //returns original object
What am I doing wrong?
What you've done is create a new slot inside the method and named it self. Which means it goes away when the method returns. In Io self isn't a keyword, there are no keywords, and thus it doesn't have special meaning.
What you're looking for is to use a method that modifies self. Since List is written in C, you'd have to interface directly with something written in C, or with something that interfaces with something written in C, to clear the contents of the list. Consider:
myObject drop := method(
self empty
)
What's going on here is List has a method named empty which removes all items and returns the now empty object. It talks to a primitive List method called removeAll to accomplish this.
This is a bit cut and dry though. In the general case, in other circumstances, you may want to save the item you want to return BEFORE you remove it from the collection. i.e.,
myCollection drop := method(
result := self at(42)
self removeAllTheThings
result
)
Since not every type of collection that could exist, would have a removeAll or empty method built in.

Resources