Pharo: how to make Cmd+d ("do it") execute the whole multi-line statement by default instead of just the current line - smalltalk

Suppose I have a multi-line statement like this:
1 to: 5 do: [:i|
Transcript show: i.
Transcript cr].
Currently, when I put a text cursor on some line (without selecting anything) and press Cmd+d, Pharo tries to execute the current line. But it would be more convenient for me if by default (when nothing is selected) Pharo would execute the current statement (i.e. all this three-line statement), not just the current line. Because this is a much more frequent case ("I want to execute the whole statement") than "I want to execute this particular line inside a statement" (which in most cases just doesn't make sense syntactically, as 1st and 3rd lines here). And in these rear occasions (when I need to execute a line inside a statement) I would pre-select this line manually.
How can I achieve this?

To answer your question: Take a look at the text component. It has some method for evaluate-selection-and-do. And if nothing is selected, it tries to select the current line.
You may change this implementation to find the top most statement "scope".
It could be possible if you work with the code AST instead of the text. I worked once with this, to make it smarter for code expressions inside of comments.(that didn't work for all situations because the context for getting the method AST isn't always the same for this text component,in different tools (browser/workspace/and other))

Here is the idea for an algorithm. You will need to improve and complete it.
Define a class ExpressionFinder for finding the proper expression in your text.
In my sketch this class has the following ivars
string:
the complete string in your pane (playground/transcript/whatever)
compiler:
the compiler used by your pane to evaluate text
lines: the collection of associations pos->line, where pos is the position of the line inside string
index: current index to the lines collection used by the algorithm
interval: the output interval if any, otherwise nil
Assume you are given the string, the compiler and the current position of the cursor on string. Do the following:
string: aString position: anInteger compiler: aCompiler
string := aString.
compiler := aCompiler.
self computeLines.
index := lines findLast: [:assoc | assoc key <= anInteger]
Here is how you compute the collection of lines:
computeLines
| reader |
lines := OrderedCollection new.
reader := string readStream.
[reader atEnd]
whileFalse: [lines add: reader position + 1 -> reader nextLine]
With all of this you have everything you need to find the appropriate fragment. Here is a simple idea (which you should improve):
Start at the current line index and find the fragment by adding a line at a time. If found, end. If not, decrease the index and try again from the line above.
Here is the code
find
| i |
i := index.
[
i <= 0 ifTrue: [^self].
assoc := lines at: i.
self findFrom: assoc key]
whileFalse: [i := i - 1]
where
findFrom: start
| i end success |
i := index.
[| assoc fragment |
assoc := lines at: i + 1 ifAbsent: [string size + 1 -> nil].
end := assoc key - 1.
fragment := string copyFrom: start to: end.
success := self canCompile: fragment.
success not and: [end < string size]]
whileTrue: [i := i + 1].
success ifTrue: [interval := start to: end].
^success
The code for canCompile: fragment is dialect-dependent, on the lines of
canCompile: fragment
^(compiler compileExpression: fragment) notNil
If your compiler signals CompilationErrors, you will need to put a handler in canCompile: to avoid them. Also you might take advantage of such errors. For instance, if the compilation error refers to an undeclared variable, you know that you will not find its definition in the lines below, so you should exit the loop in findFrom: so to try with the line above and so on.

Related

How to read elements from a line in VHDL?

I'm trying to use VHDL to read from a file that can have different formats. I know you're supposed to use the following two lines of code to read a line at a time, the read individual elements in that line.
readline(file, aline);
read(aline, element);
However my question is what will read(aline, element) return into element? What will it return if the line is empty? What will it return if I've used it let's say 5 times and my line only has 4 characters?
The reason I want to know is that if I am reading a file with an arbitrary number of spaces between valid data, how do I parse this valid data?
The file contains ASCII characters separated by arbitrary amounts of white space (any number of spaces, tabs, or new lines). If the line starts with a # that line is a comment and should be ignored.
Outside of these comments, the first part of the file contains characters that are only letters or numbers in combinations of variable size. In other words this:
123 ABC 12ABB3
However, the majority of the file (after a certain number of read words) will be purely numbers of arbitrary length, separated by an arbitrary amount of white space. In other words, the second part of the file is this:
255 0 2245 625 430
2222 33 111111
and I must be able to parse these numbers (and interpret them as such) individually.
As mentioned in the comments, all the read procedures in std.textio and ieee.std_logic_textio skip over leading spaces apart from the character and string versions (because a space is as much a character as any other).
You can test whether a line variable (the buffer) is empty like this:
if L'length > 0 then
where L is your line variable. There is also a set of overloaded read procedures with an extra status output:
procedure read (L : inout LINE;
VALUE: out <type> ;
GOOD : out BOOLEAN);
The extra output - GOOD - is true if the read was successful and false if it wasn't. The advantage of these if that the read is unsuccessful, the simulation does not stop (as it does with the regular procedures). Also, with the versions in std.textio, if the read is unsuccessful, the read is non-destructive (ie whatever you were trying to read remains in the buffer). This is not the case with the versions in ieee.std_logic_textio, however.
If you really do not know what format you are trying to read, you could read the entire line into a string, like this:
variable S : string(1 to <some big number>);
...
readline(F, L);
assert L'length < S'length; -- make sure S is big enough
S := (others => ' '); -- make sure that the previous line is overwritten
if L'length > 0 then
read(L, S(1 to L'length);
end if;
The line L is now in the string S. You can then write some code to parse it. You may find the type attribute 'value useful. This converts a string to some type, eg
variable I : integer;
...
I := integer'value(S(12 to 14));
would set integer I to the value contained in elements 12 to 14 of string S.
Another approach, as suggested by user1155120 below, is to peek at the values in the buffer, eg
if L'length > 0 then -- check that the L isn't empty, otherwise the next line blows up
if L.all(1) = '#' then
-- the first character of the line is a '#' so the line must be a comment

Printing Expected Token Type XXX when a parsing error occurs

I would like to be able to print this error message using Ragel
=> Parsing error found at position line:col, Integer expected instead.
Is that possible with Ragel?
Best regards
I haven't gotten too far into error handling in Ragel just yet, but I would expect that if you use the error action embedding operators as specified in section 3.2.3 of the Ragel 6.9 Guide, that would override the default message.
You can get the line number by incrementing a counter at each newline, and get the column by taking the current position and subtracting the position of the previous newline, something like this:
newline = '\n' %{ ++lineCounter; linePosition = p; }
action ErrorHandler {
column = p - linePosition + 1;
// Print error message here using lineCounter and column
}
main := (allsortsofstuff | newline)* <>err(ErrorHandler);
Of course, the above may require a bit of tweaking based on exactly what you're doing, but at least it's a starting point.

Cannot print subsequent rows of array to file

I'm trying to write a rudimentary bit of code to print a 50*50 array called 'arr'. Unfortunately it so far only prints the first row of the array, although the formatting for that row is correct. I've attached the code below and was wondering if anyone could point out where I was going wrong? Thank you!
program testing
implicit none
integer :: i, j
integer, dimension (1:50, 1:50) :: arr
arr = 1
do i=1,50
open(unit=6, file= "array.txt", action="write")
write(6, '(2500I3)') (arr(i,j), j=1,50)
close(6)
end do
end program testing
Your open statement is inside loop (along with a matching close statement). That means for every row of the array, you open the file. That's probably not what you meant to do.
The default position specifier for an OPEN statement if there is no POSITION specifier is 'ASIS'. For a file that already exists (your case after the first iteration, and perhaps even for the first iteration) that means that the position is unspecified. Your processor probably takes that to be the start of the file. That means that each iteration of the loop you simply overwrite the first record, over and over again.
If you must open the file each iteration, then use the POSITION='APPEND' specifier to position the file at the end when the open statement is executed. Otherwise, move the open and close statements out of the loop.
(The way that the default of 'ASIS' behaves means that you should always specify the initial position of a file via a POSITION specifier when executing an OPEN statement for an existing "on disk" file.)
IanH's answer is correct. Your program can be fixed as follows. Note that output units should be parameterized and not set to 6 and that arrays and array sections can be written as shown.
program testing
implicit none
integer :: i
integer, dimension (1:50, 1:50) :: arr
integer, parameter :: outu = 20 ! better to parameterize unit and
! not to use the number 6, which most compilers
! use for standard output
arr = 1
open(unit=outu, file= "array.txt", action="write")
do i=1,50
write(outu, '(2500I3)') arr(i,:) ! can write array section without implied do loop
end do
close(outu)
end program testing

How to print multiple outputs in Smalltalk

|X Y A B C D|
Y:= 7.
X:= 6.
(X = Y)
ifTrue: [X := 0]
ifFalse:[X := 1].
B:=2.
C:=5.
D:=1.
A:= (B squared)*(C-D).
"print both A and X to screen here"
Simple enough little smalltalk example. I'm just curious how I can get this to print X and A as outputs? is there any way to do it w/o having to perform a 'print it' on the top 6 lines and a seperate 'print it' on the bottom 5 lines? if it could print out on just a 'do it' or a single 'print it' please let me know!
You should define what is "printing" and what is X and A.
If "printing" is a result of the "print it" action, then you are talking in general about returning X and A, as "print it" prints the return result of the selected code. This way you have to think about an object which will represent X and A. For this object you can define a printString method or printOn: and get the result printed. Or you can cheat a bit and return a point by doing X#A.
If you are talking about actually printing the thing somewhere then you have to tell more about where do you want to do it. You can print it in Transcript or similar, but there you have to explicitly send a message to the Transcript with what you want to be printed.
Now if you want to use this for "debugging/testing" reasons, it can be easier to go with "inspect it". In your code you can send inspect messages to the objects that you want to look at, and during the execution inspectors will open showing this objects.
Also I encourage you to follow conventions and make your variable names start with lowercase letter.
Smalltalk has no equivalent of print() or println() or the like, since most Smalltalk environments live in a window environment. There are ways to write output to stdout or std error, but this is very dialect specific.
One of the places that somehow replaces stdout in most dialects is a place/stream/window called Transcript, in most dialects this is the window that launches first when your start the IDE.
To write something there you simple do:
Transcript show: 'A=', A asString, ' ; X=', X asString.
(please note that in Smalltalk, Strings and Collections are concatenated with a comma)
You can also write a newLine by sending the message cr to the Transcript like so:
Transcript cr.
Does this answer your question?
A hint for further learning/investigation: Transcript is just a Variable that holds a Stream object. show: is a message that writes some String onto that Stream. asString is a method that returns a String representation of an object.

PostScript mark token

In PostScript if you have
[4 5 6]
you have the following tokens:
mark integer integer integer mark
The stack goes like this:
| mark |
| mark | integer |
| mark | integer | integer |
| mark | integer | integer | integer |
| array |
Now my question:
Is the ]-mark operator a literal object or an executable object?
Am I correct that the [-mark is a literal object (just data) and that the ]-mark is an executable object (because you always need to create an array when you see this ]-mark operator) ?
PostScript Language Reference Manual section 3.3.2 gives me:
The [ and ] operators, when executed, produce a literal array object with the en-closed objects as elements. Likewise, << and >> (LanguageLevel 2) produce a
literal dictionary object.
That is not clear for me if both [ ] operators are executable or only the ] operator.
Summary.
All of these special tokens, [, ], <<, >>, come out of the scanner as executable names. [ and << are defined to yield a marktype object (so they are not operators per se, but they are executable names defined in systemdict where all the operators live). ] and >> are defined as procedures or operators which are executed just like any other procedure or operator. These use the counttomark operator to find the opening bracket. But all of these tokens are treated specially by the scanner, which recognizes them without surrounding whitespace since they are part of its delimiter set.
Details.
It all depends on when you look at it. Let's trace through what the interpreter does with these tokens. I'm going to illustrate this with a string, but it works just the same with a file.
So if you have an input string
([4 5 6]) cvx exec
cvx makes a literal object executable. The program stream is a file object also labeled executable. exec pushes an object on the Execution Stack, where it is encountered by the interpreter on the next iteration of the inner interpreter processing loop. When executing the program stream, the executable file object is topmost on the Execution Stack.
The interpreter uses token to call the scanner. The scanner skips initial whitespace, then reads all non-whitespace characters up to the next delimiter, then attempts to interpret the string as a number, and failing that it becomes an executable name. The brackets are part of the set of delimiters, and so are termed 'self-delimiting'. So the scanner reads the one bracket character, stops reading because it's a delimiter, discovers it cannot be a number, so it yields an executable name.
Top of Exec Stack | Operand Stack
(4 5 6]) [ |
Next, the interpreter loop executes anything executable (unless it's an array). Executing a token means loading it from the dictionary, and then executing the definition if it's executable. [ is defined as a -mark- object, same as the name mark is defined. It's not technically an operator or a procedure, it's just a definition. Automatic loading happens because the name comes out of the scanner with the executable flag set.
(4 5 6]) | -mark-
The scanner then yields 4, 5, and 6 which are numbers and get pushed straight to the operand stack. 6 is delimited by the ] which is pushed back on the stream.
(]) | -mark- 4 5 6
The interpreter doesn't execute the numbers since they are not executable, but it would be just the same if it did. The action for executing a number is simply to push it on the stack.
Then, finally the scanner encounters the right bracket ]. And that's where the magic happens. Self-delimited, it doesn't need to be followed by any whitespace. The scanner yields the executable name ] and the interpreter executes it by loading and it finds ...
{ counttomark array astore exch pop }
Or maybe an actual operator that does this. But, yeah. counttomark yields the number of elements. array creates an array of that size. astore fills an array with elements from the stack. And exch pop to discard that pesky mark once and for all.
For dictionaries, << is exactly the same as [. It drops a mark. Then you line up some key-value pairs, and >> is procedure that does something to effect of ...
{ counttomark dup dict begin 2 idiv { def } repeat pop currentdict end }
Make a dictionary. Define all the pairs. Pop the mark. Yield the dictionary. This version of the procedure tries to create a fast dictionary by making it double-sized. Move the 2 idiv to before dup to make a small dictionary.
So, to get philosophical, counttomark is the operator you're using. And it requires a special object-type that isn't used for anything else, the marktype object, -mark-. The rest is just syntactical sugar to let you access this stack-counting ability to create linear data-structures.
Appendix
Here's a procedure that models the interpreter loop reading from currentfile.
{currentfile token not {exit} if dup type /arraytype ne {exec} if }loop
exec is responsible for loading (and further executing) any executable names. You can see from this that token really is the name of the scanner; and that procedures (arrays) directly encountered by the interpreter loop are not executed (type /arraytype ne {exec} if).
Using token on strings lets you do really cool stuff, however. For example, you can dynamically construct procedure bodies with substituted names. This is very much like a lisp macro.
/makeadder { % n . { n add }
1 dict begin
/n exch def
({//n add}) token % () {n add} true
pop exch pop % {n add}
end
} def
token reads the entire procedure from the string, substituting the immediately-evaluated name //n with its currently defined value. Notice here that the scanner reads an executable array all at once, effectively executing [ ... ] cvx internally before returning (In certain interpreters, like my own xpost, this allows you to bypass the stack-size limits to build an array, because the array is built in separate memory. But Level 2 garbage collection makes this largely irrelevant).
There is also the bind operator which modifies a procedure by replacing operator names with the operator objects themselves. These tricks help you to factor-out name lookups in speed-critical procedures (like inner loops).
Both [ and ] are executable tokens. [ produces a mark object, ] creates an array of objects to the last mark