Debugging Forth using a Test Harness - debugging

I would like to use a simple test harness to test my code during debugging using the same methodology as the Forth test harness developed by John Hayes.
The concept is to define a function, say my+ and then to define simple code snippets that will test the code when Tdebug is on.
Tdebug if T{ 1 1 my+ -> 2 }T else
Is it really as simple as including tester.f and changing {> to T{ and } to }T?
I plan to omit tester.f in the production release if size is an issue.
Edit:
debug if ... then does not work because it is outside compile...
Now I need help!
If debug is true tester.f works well.
If debug is false t{ and }t must work like ( ... ) comments. How do I code this?
0 constant debug
: t{
debug if
( as defined in tester.fr )
else
( what goes here? )
then
;
: }t
debug if
( as defined in tester.fr )
else
( and what goes here? )
then
;

The only way is to parse the input source stream up to }t. If t{ can be nested, it becomes a little trickier — see the reference implementation of [ELSE] word.
For reference, the production-mode definition of t{ word for simple (not nested) case in standard Forth:
: t{ ( "ccc }t" -- ) \ skip up to '}t'
begin
begin parse-name dup while S" }t" compare 0= until exit then 2drop
refill 0=
until
;
Although, I suggest to place tests into separate files and make conditional inclusion of such files ("spec" files). In such case you don't need to have another (production-mode) definition of t{ word at all.

I eventually did something similar to #ruvim by including tester.f when in debug mode and including notester.f when in production as follows:
\ notester.fs
( include either tester.fs or notester.fs )
\ adapted from longcomment.txt
false variable verbose
: t{ ( -- ) \ Long comment
begin
token \ Get next token
dup 0= if 2drop cr query token then \ If length of token is zero, end of
\ line is reached.
\ Fetch new line. Fetch new token.
s" }t" compare \ Search for }t
until
immediate 0-foldable
;
: testing ( -- ) \ Talking comment.
source verbose #
if dup >r type cr r> >in !
else >in ! drop [char] * emit
then
;
t{ 1 1 + -> 2 }t \ Usage sample
I find that having the tests as usage comments in the production file assists clarity.

Related

Error in Parsing the postscript to pdf

I have a postscript file when i try to convert it into pdf or open it with postscript it gives the following error
undefined in execform
I am trying to fix this error. But there is no solution i found. Kindly Help me understand the issue.
This is postscript file
OK so a few observations to start;
The file is 8 pages long, uses many forms, and the first form it uses has nested forms. This really isn't suitable as an example file, you are expecting other programmers to dig through a lot of extraneous cruft to help you out. When you post an example, please try and reduce it to just the minimum required to reproduce the problem.
Have you actually tried to debug this problem yourself ? If so what did you do ? (and why didn't you start by reducing the file complexity ?)
I don't want to be offensive, but this is the third rather naive posting you've made recently, do you have much experience of PostScript programming ? Has anyone offered you any training in the language ? It appears you are working on behalf of a commercial organisation, you should talk to your line manager and try and arrange some training if you haven't already been given some.
The PostScript program does not give the error you stated
undefined in execform
In fact the error is a Ghostscript-specific error message:
Error: /undefined in --.execform1--
So that's the .execform1 operator (note the leading '.' to indicate a Ghostscript internal operator). That's only important because firstly its important to accurately quote error messages, and secondly because, for someone familiar with Ghostscript, it tells you that the error occurs while executing the form PaintProc, not while executing the execform operator.
After considerably reducing of the complexity of the file, the problem is absolutely nothing to do with the use of Forms. The offending Form executes code like this:
2 RM
0.459396 w
[(\0\1\0\2)]435.529999 -791.02002 T
(That's the first occurrence, and its where the error occurs)
That executes the procedure named T which is defined as:
/T{neg _LY add /_y ed _LX add /_x ed/_BLSY _y _BLY sub D/_BLX _x D/_BLY _y D _x _y TT}bd
Obviously that's using a number of other functions defined in the prolog, but the important point is that it executes TT which is defined as :
/TT{/_y ed/_x ed/_SX _x _LX sub D/_SY _y _LY sub D/_LX _x D/_LY _y D _x _y m 0 _rm eq{ dup type/stringtype eq{show}{{ dup type /stringtype eq{show}{ 0 rmoveto}?}forall}?} if
1 _rm eq {gsave 0 _scs eq { _sr setgray}if 1 _scs eq { _sr _sg _sb setrgbcolor}if 2 _scs eq { _sr _sg _sb _sk setcmykcolor} if dup type/stringtype eq{true charpath }{{dup type /stringtype eq{true charpath } { 0 rmoveto}?}forall}? S grestore} if
2 _rm eq {gsave 0 _fcs eq { _fr setgray}if 1 _fcs eq { _fr _fg _fb setrgbcolor}if 2 _fcs eq { _fr _fg _fb _fk setcmykcolor} if dup type/stringtype eq{true charpath }{{dup type /stringtype eq{true charpath } { 0 rmoveto}?}
forall}? gsave fill grestore 0 _scs eq { _sr setgray}if 1 _scs eq { _sr _sg _sb setrgbcolor}if 2 _scs eq { _sr _sg _sb _sk setcmykcolor}if S grestore} if
Under the conditions holding at the time TT is executed (RM sets _rm to 2), we go through this piece of code:
gsave 0 _fcs eq
However, _fcs is initially undefined, and only defined when the /fcs function is executed. Your program never executes /fcs so _fcs is undefined, leading to the error.
Is there a reason why you are defining each page in a PostScript Form ? This is not optimal, if the interpreter actually supports Forms then you are using up VM for no useful purpose (since you only execute each Form once).
If its because the original PDF input uses PDF Form XObjects I would recommend that you don't try and reproduce those in PostScript. Reuse of Form XObjects in PDF is rather rare (it does happen but non-reuse is much more common). The loss of efficiency due to describing PostScript Forms for each PDF Form XObject for all the files where the form isn't reused exceeds the benefit for the rare cases where it would actually be valuable.

In VHDL is there a way of limiting the size of a string with a variable value from a process?

My goal is to write a string to a file where the size of the string will vary. At the moment I have made the string very large so that there is no overflow but is there a way to make it so that the size of the string is the exact number of characters I'm placing into it? I've tried something like the code below but it gives me an error unknown identifier "address count" I think it is because address count is a variable declared in a process and address count is constantly changing. Is there any way around this?
signal address_map :string (1 to address_count);
many thanks
leo
"My goal is to write a string to a file." Hence, lets just focus on that.
Step 1: reference the file IO packages (recommended to turn on VHDL-2008):
use std.textio.all ;
-- use ieee.std_logic_textio.all ; -- include if not using VHDL-2008
Step 2: Declare your file
file MyFile : TEXT open WRITE_MODE is "MyFile.txt";
Step 3: Create a buffer:
TestProc : process
variable WriteBuf : line ;
begin
write ... -- see step 4
writeline ... -- see step 5
Step 4: Use write to write into the buffer (in the process TestProc):
write(WriteBuf, string'("State = ") ) ; -- Any VHDL version
write(WriteBuf, StateType'image(State)) ;
swrite(WriteBuf, " at time = " ); -- VHDL-2008 simplification
write(WriteBuf, NOW, RIGHT, 12) ;
Step 5: Write the buffer to the file (in the process TestProc):
writeline(MyFile, WriteBuf) ;
Alternate Steps 3-5: Use built-in VHDL Write with to_string:
Write(MyFile, "State = " & to_string(State) &
", Data = " & to_hstring(Data) &
" at time " & to_string(NOW, 1 ns) ) ;
Alternate Steps 1-5: Use OSVVM (see http://osvvm.org) (requires VHDL-2008):
library osvvm ;
use osvvm.transcriptpkg.all ; -- all printing goes to same file
. . .
TestProc : process
begin
TranscriptOpen("./results/test1.txt") ;
Print("State = " & to_string(State) &
", Data = " & to_hstring(Data) &
" at time " & to_string(NOW, 1 ns) ) ;
One hard but flexible solution is to use dynamic allocation features of VHDL (copied from ADA).
You have to use an access of string (it is roughly like a "pointer to a string" in C)
type line is access string;
you event don't have to do it because line is already declared in std.textio package.
Ok, the problem next is that you can't use an access type for a signal, so you have to use a shared variable:
shared variable address_map: line;
And finally you have to allocate, read and write to this line:
--Example in a function/procedure/process:
--free a previously allocated string:
if address_map /= NULL then
deallocate(address_map);
end if;
--allocate a new string:
address_map:=new string (1 to address_count);
address_map(1 to 3):="xyz";
--we have here:
-- address_map(1)='y'
-- address_map(2 to 3)="yz"
-- address_map.all = "xyz"
Notice the use of new/deallocate (like malloc/free in C or free/delete in C++).
It is not easy to handle this kind of code, I recommend you to read the documentation of VHDL keywords "new", "deallocate" and "access" (easily found with your favorite search engine) or feel free to ask more questions.
You can also use the READ (read the whole line into a string) and WRITE (append a string to the line) functions from std.textio package.

Constraint Error warning using Enum in ADA

I'd like to know why constraint Errors warnings are prompted in Ada when enums are used as in the example below. As I've been using Enums I can replace them for a better implementation.
type Uart_Instance_Type is (COM1, COM2, COM3);
for Uart_Instance_Type use
( COM1 => 16#0001# ,
COM2 => 16#0002# ,
COM3 => 16#0003#
);
type UART_Register_Type is record
SR : Half_Word; -- USART Status register
Reserved_0 : Half_Word;
DR : Half_Word; -- USART Data register
Reserved_1 : Half_Word;
BRR : Half_Word; -- USART Baud rate register
Reserved_2 : Half_Word;
end record
with volatile;
for UART_Register_Type use record
SR at 0 range 0 .. 15;
Reserved_0 at 2 range 0 .. 15;
DR at 4 range 0 .. 15;
Reserved_1 at 6 range 0 .. 15;
BRR at 8 range 0 .. 15;
Reserved_2 at 10 range 0 .. 15;
end record;
type UART_Register_Access is access all UART_Register_Type;
UARTs: array (Uart_Instance_Type range COM1 .. COM3) of aliased UART_Register_Access;
The compiler prompt at the last line ("UARTs: ...) and shows:
warning: "Constraint Error" may call Last_Chance_Handler
Is there a better implementation to avoid these warnings when using Enums?
Thanks in advance! :)
I think you must be compiling for a restricted (Ravenscar?) runtime, which is why any exception will result in a call to Last_Chance_Handler.
I encountered a lot of irritating warnings like this, and eventually traced it to compiling with
-gnatwa (“turn on all info/warnings marked below with +”) which enables
-gnatw.x ("turn on warnings for non-local exception”).
You can suppress the warnings with -gnatw.X.
(For info, you can see the command line options by saying gnatmake -h (or arm-eabi-gnatmake -h). There are a lot.)

What's the ideal order of checks for early bailout when processing files with Perl?

Parsing a directory tree with hundreds of thousands of of files looking for valid (non-empty, readable) log files. What is the most efficient order of tests for early bail?
Here's an example I use as a file::find preprocessor stage and, being new to Perl, I wonder what tests are slowests / redundant / inefficiently ordered?
sub filter {
my $nicename = substr( $File::Find::dir, $_pathLength );
my #clean;
my $filecount = my $dircount = 0;
foreach (#_) {
next unless -R $_; # readable
next unless -f _ || -d _; # file or dir.
next if ( $_ =~ m/^\./ ); # ignore files/folders starting with a period
if ( -f _ ) { # regular file
next unless ( my $size = -s _ ); # does it have a size?
next unless ( $_ =~ m/([^.]+)$/ )[0] eq $_log_file_ext; # correct file extension?
next if exists( $_previousRun{ $_ . " ($size)" } ); # don't add files we've already processed
$filecount++;
} elsif ( -d _ ) { # dir
$dircount++;
}
push( #clean, $_ );
}
$_fileCount += $filecount;
$_dirCount += $dircount;
Utils::logit("'$nicename' contains $filecount new files and $dircount folders to explore.");
return #clean;
}
Any info you can provide on Perls internals and behaviours would be useful to me.
At the very end I run some specific checks for "regular file" and "directory". Are there other things I should check for and avoid adding to my clean list?
As a rough rule of thumb, 'going to disk' it the most expensive thing you'll be doing.
So when trying to optimise IO based:
First, discard anything you can based on name/location. (e.g. 'does filename contain a .')
Then discard based on file attributes - coalesce if you can into a single stat call, because then you're making a single IO.
And then do anything else.
I'm at least fairly sure that your -s -d -f etc. will be triggering stat() operations each time they go. (Which will probably get cached, so it doesn't hurt that much). But you do also test -f and -d twice - once to do the next unless and again to do the if
But you might find you can do a single stat and get most of the metadata you're interested in:
http://perldoc.perl.org/functions/stat.html
In the grand scheme of things though - I wouldn't worry about it too much. Your limiting factor will be disk IO, and the odd additional stat or regular expressions won't make much difference to the overall speed.

Keeping quotations as tuple members in Factor

I want to keep a quotation as a member of a tuple in Factor. But when I try to execute 'call' on it I get the error 'cannot apply call to a run-time computed value'. Note that marking the functions as 'inline' does nothing.
Sample code:
USING: accessors kernel ;
IN: stackoverflow
TUPLE: quottuple quot ;
C: <quottuple> quottuple
: call-quot ( quottuple -- result )
quot>> call ; inline
: main ( -- )
[ 1 ] <quottuple>
call-quot drop ;
MAIN: main
The answer is the 'call(' word. That word requires you to specify the stack effect of the quotation, but as a result the quotation doesn't need to be known at compile time.
USING: accessors kernel ;
IN: stackoverflow
TUPLE: quottuple quot ;
C: <quottuple> quottuple
: call-quot ( quottuple -- result )
quot>> call( -- result ) ;
: main ( -- )
[ 1 ] <quottuple>
call-quot drop ;
MAIN: main

Resources