"cannot generate code for file random.ads" when running a .adb program - gps

I have some troubles with running a program in Ada. I have the three following project files (I use GPS) :
Types.ads
package types is
subtype T_valeurind is Integer range 2..14;
type T_couleur is (s, h, c, d);
type t_carte is record
valeur : T_valeurind;
couleur : T_couleur;
end record;
type T_jeu is array (1..7) of t_carte;
function trans(val: Character) return T_valeurind;
end types;
Trans.adb
with types;
use types;
WITH Text_Io , Ada.Integer_Text_Io;
USE Text_Io , Ada.Integer_Text_Io;
function trans(val : Character)
return T_valeurind is
ret: Integer;
begin
case val is
when '3' => ret:=3;
when '4' => ret:=4;
when '5' => ret:=5;
when '6' => ret:=6;
when '7' => ret:=7;
when '8' => ret:=8;
when '9' => ret:=9;
when 'T' => ret:=10;
when 'J' => ret:=11;
when 'Q' => ret:=12;
when 'K' => ret:=13;
when 'A' => ret:=14;
when others => null;
end case;
return ret;
end trans;
Test.adb
WITH Text_Io , Ada.Integer_Text_Io;
USE Text_Io , Ada.Integer_Text_Io;
with types;
use types;
procedure test is
begin
put(T_valeurind'Image(trans('c')));
end test;
I'm just trying to execute test.adb just to check if my function "trans" works well. When I build the files in GPS, everything works just fine. But when I want to run them, I have the following message, and no execution :
cannot generate code for file types.ads (package spec)
gprbuild: *** compilation phase failed
[2018-12-02 02:01:39] process exited with status 4, 100% (2/2), elapsed time: 01.65s
But what is perturbing is that the first time I tried running the code, it worked. Without changing anything, it stopped working.
I don't know what to do. I've seen that this message just tells me that .ads file is not compilable, but what I try to compile and run is an .adb file, so I don't get it..
Do you have an idea why it doesn't work ?
Thank you all in advance !

First, those aren't project files, which would have type .gpr; they're Ada source files in your project.
Your types.ads promises function trans, which means it needs a package body in types.adb,
package body types is
function trans(val : Character)
return T_valeurind is
ret: Integer;
begin
case val is
when '3' => ret:=3;
when '4' => ret:=4;
when '5' => ret:=5;
when '6' => ret:=6;
when '7' => ret:=7;
when '8' => ret:=8;
when '9' => ret:=9;
when 'T' => ret:=10;
when 'J' => ret:=11;
when 'Q' => ret:=12;
when 'K' => ret:=13;
when 'A' => ret:=14;
when others => null;
end case;
return ret;
end trans;
end types;
(Hmm. If you pass in an invalid character, you'll return uninitialised data, and as like as not get a Constraint_Error; T_valeurind includes the value 2, shouldn’t you cover it?)
Your trans.adb specifies a library-level function instead.
When I build the files in GPS, everything works just fine. But when I want to run them, I have the following message, and no execution :
If a package spec (types.ads) requires a body (types.adb) and you don't provide it, the compiler will produce the message you report when you try to compile it. If you try to just compile test.adb it will be OK. If you try to build test.adb it will try to compile the package Types and will fail, regardless of whether you're trying to Build or Build & Run.
I have no idea how this could have worked first time!

It looks like you forgot to include your function Trans in the context of the test program. And if it isn't in the context, you can't use it.
Try to add:
with Trans;
To the context clause of procedure Test.

Your whole problem could have been avoided in the first place using powerful Ada enums capabilities (and some bad inputs handling strategy, like exceptions). Your trans procedure would be useless.
If you are interested in the order relation of your enum values, you can also use the Ada's 'First* (first enum literal), 'Last (last enum literal), 'Pos (position inside the enum), 'Succ (next enum literal), 'Pred (previous enum literal).
If you perform memory mapping for your variables, you could use 'Valid to check if the variable has a valid value and save the need of exception catch for constraint errors.
See example below:
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Exceptions; use Ada.Exceptions;
procedure Hello is
-- miwing chars and literal values in enum
-- note that jack is 'J' and not the single source code character J
type My_Awesome_Enum is ('1', '2', '3', 'J', Q, K, Ace);
for My_Awesome_Enum use
('1' => -1,
'2' => 2,
'3' => 3,
-- ...
'J' => 11,
Q => 12,
K => 13,
Ace => 14);
temp : Integer;
prev : My_Awesome_Enum;
succ : My_Awesome_Enum;
temp2 : My_Awesome_Enum;
begin
-- ------------------------------------------
-- Ada enum power
declare
begin
for value in My_Awesome_Enum loop
temp := My_Awesome_Enum'Enum_Rep(value);
Put_Line("Enum litteral value: " & value'Image & " - memory representation: " & Integer'Image(temp));
if value /= My_Awesome_Enum'First then
prev := My_Awesome_Enum'Pred(value);
Put_Line("Previous: " & prev'Image);
else
Put_Line("No previous");
end if;
if value /= My_Awesome_Enum'Last then
succ := My_Awesome_Enum'Succ(value);
Put_Line("Next: " & succ'Image);
else
Put_Line("No next");
end if;
Put_Line("");
end loop;
end;
-- ------------------------------------------
-- conversion from some input source
Put_Line("");
declare
strInput : String := "Unknown user value";
begin
Put_Line("Handling of user input: " & strInput);
temp2 := My_Awesome_Enum'Value (strInput);
exception
when E: others =>
Put_Line("Exception catched: " & Exception_Information (E));
Put_Line("Setting value to Ace instead");
temp2 := Ace;
end;
Put_Line("tmp2 value: " & temp2'Image & " - memory representation: " & Integer'Image(My_Awesome_Enum'Enum_Rep(temp2)));
-- ------------------------------------------
-- mmemory mapping
Put_Line("");
declare
my_int : Integer := -3;
mapped_Enum : My_Awesome_Enum;
for mapped_Enum'Address use my_int'Address;
last_enum : My_Awesome_Enum := (My_Awesome_Enum'Last);
stop_condition : Integer := (last_enum'Enum_Rep) + 2;
begin
while (my_int < stop_condition) loop
if mapped_Enum'Valid then
Put_Line("Enum with value: " & my_int'Image & " is valid.");
else
Put_Line("Memory mapping would result in invalid enum for value: " & my_int'Image);
end if;
my_int := my_int + 1;
end loop;
end;
end Hello;
This give sthe following output (https://www.tutorialspoint.com/compile_ada_online.php, with GNATMAKE v7.1.1):
Build:
$gnatmake -o hello *.adb
gcc -c hello.adb
gnatbind -x hello.ali
gnatlink hello.ali -o hello
Execute:
Enum litteral value: '1' - memory representation: -1
No previous
Next: '2'
Enum litteral value: '2' - memory representation: 2
Previous: '1'
Next: '3'
Enum litteral value: '3' - memory representation: 3
Previous: '2'
Next: 'J'
Enum litteral value: 'J' - memory representation: 11
Previous: '3'
Next: Q
Enum litteral value: Q - memory representation: 12
Previous: J
Next: K
Enum litteral value: K - memory representation: 13
Previous: Q
Next: ACE
Enum litteral value: ACE - memory representation: 14
Previous: K
No next
Handling of user input: Unknown user value
Exception catched: raised CONSTRAINT_ERROR : bad input for 'Value: "Unknown user value"
Setting value to Ace instead
tmp2 value: ACE - memory representation: 14
Memory mapping would result in invalid enum for value: -3
Memory mapping would result in invalid enum for value: -2
Enum with value: -1 is valid.
Memory mapping would result in invalid enum for value: 0
Memory mapping would result in invalid enum for value: 1
Enum with value: 2 is valid.
Enum with value: 3 is valid.
Memory mapping would result in invalid enum for value: 4
Memory mapping would result in invalid enum for value: 5
Memory mapping would result in invalid enum for value: 6
Memory mapping would result in invalid enum for value: 7
Memory mapping would result in invalid enum for value: 8
Memory mapping would result in invalid enum for value: 9
Memory mapping would result in invalid enum for value: 10
Enum with value: 11 is valid.
Enum with value: 12 is valid.
Enum with value: 13 is valid.
Enum with value: 14 is valid.
Memory mapping would result in invalid enum for value: 15

Related

dataframe-go: How to filter using < > operators?

I'm trying to do a simple filter in dataframe-go. I adapted from the Github example and tried to use a simple > operator in the Filter Function, but the compiler gave invalid operation: vals["day"] > 4 (operator > not defined on interface) error (see my code below)
Ok, so I changed the type to map[string]int64 but then, it gave the error: cannot convert func literal (type func(map[string]int64, int, int) (dataframe.FilterAction, error)) to type dataframe.FilterDataFrameFn.
I'm very familiar with R DataFrame/Table and Pandas but dataframe-go's API is rather convoluted. The only web resource I found is this but the author also stated he couldn't understand the filter API.
Any help is appreciated, thanks!
s1 := dataframe.NewSeriesInt64("day", nil, 1, 2, 3, 4, 5, 6, 7, 8)
s2 := dataframe.NewSeriesFloat64("sales", nil, 50.3, 23.4, 56.2, nil, nil, 84.2, 72, 89)
df := dataframe.NewDataFrame(s1, s2)
// Try filtering
filterFn := dataframe.FilterDataFrameFn(
func(vals map[string]int64, row, nRows int) (dataframe.FilterAction, error) {
//func(vals map[interface{}]interface{}, row, nRows int) (dataframe.FilterAction, error) {
if vals["day"] > 4 { // <= This is where I changed things
return dataframe.KEEP, nil
}
return dataframe.DROP, nil
})
ctx := context.Background()
dt_filtered, _ := dataframe.Filter(ctx, df, filterFn)
fmt.Print(dt_filtered)
You have to pass a function with the required signature, so vals must be a map[interface{}]interface{}. This is required because Go is not an interpreted language, and the code calling that function you passed as an argument has no compile-time knowledge of the function passed in.
Since your values are interface{}s, you have to convert them to the correct type to operate with them:
if ivalue, ok:=vals["day"].(int64); ok { // Check if the value is int64, and go ahead if so
if ivalue > 4 {
return dataframe.KEEP, nil
}
}

Pascal | Initializing variables

The following syntax examples are incorrect ways to initialize a variable in pascal:
var current: string = '1.6';
Error message: Column 21: Semicolon (;) expected.
var current: string;
current = '1.6';
Error message: Column 1: Duplicate identifier 'current'.
Correct syntax to initialize a variable in Pascal:
var current: string;
begin
current := '1.6';
end
Source:
https://www.freepascal.org/docs-html/current/ref/refse25.html#x56-740004.5
I haven't codified in Pascal for a long time, but the assignation of a variable uses the := operator (assigment operator), = operator is for comparisitions. Otherwise you need to add the main program block, like this:
Var
current: string;
Begin
current := '1.6';
End.
I hope can be useful for you.
More info here: https://www.freepascal.org/docs-html/ref/refse101.html
It's been a very long time since I wrote Pascal, but IIRC, the assignment operator is := (aka the walrus sign). = is the equality test operator.
Try this:
var current: string;
current := '1.6';

How to define a single byte variable in go lang

I am a newbie to golang and want to find a way to define a single byte variable.
It's a demo program in Effective Go reference.
package main
import (
"fmt"
)
func unhex(c byte) byte{
switch {
case '0' <= c && c <= '9':
return c - '0'
case 'a' <= c && c <= 'f':
return c - 'a' + 10
case 'A' <= c && c <= 'F':
return c - 'A' + 10
}
return 0
}
func main(){
// It works fine here, as I wrap things with array.
c := []byte{'A'}
fmt.Println(unhex(c[0]))
//c := byte{'A'} **Error** invalid type for composite literal: byte
//fmt.Println(unhex(c))
}
As you see I can wrap a byte with array, things goes fine, but How can I define a single byte without using array? thanks.
In your example, this would work, using the conversion syntax T(x):
c := byte('A')
Conversions are expressions of the form T(x) where T is a type and x is an expression that can be converted to type T.
See this playground example.
cb := byte('A')
fmt.Println(unhex(cb))
Output:
10
If you don't want to use the := syntax, you can still use a var statement, which lets you explicitly specify the type. e.g:
var c byte = 'A'

How to retrieve Y/N from user in Ada

I wrote a program that will determine whether some imaginary school would have a snow day or not. I have the program working correctly I'm just having an issue.
Basically what I want is for the True/False to be Y/N. And later when I print SnowDay --tells whether there's a snow day. Then it will print either "Yes" or "No" instead of "True" or "False"
SofieAssignment : Boolean;
SnowDay : Boolean;
.
.
Put(Item => "Does Sophie have a big assignment due in class, True/False? ");
Get(Item => SophieAssignment);
.
.
Put(Item => "Should we have a snow day today? " & Boolean'Image (SnowDay));
Assuming I understand what you're trying to do:
(1) If you want the user to enter Y or N for SophieAssignment, there are a couple possibilities:
You can input a string and analyze the string yourself.
Put(Item => "Does Sophie have a big assignment due in class, True/False? ");
declare
Answer : String := Get_Line; -- Get_Line is in Ada.Text_IO
begin
if Answer = "Y" or else Answer = "y" or else Answer = "Yes" or else
Answer = "yes" then
SophieAssignment := True;
elsif Answer = "N" or else Answer = "n" or else Answer = "No" or else
Answer = "no" then
SophieAssignment := False;
else
-- whatever you want to do for an invalid entry
end if;
end;
(This could be improved, but I'm just trying to cover the fundamental approach.) Another possibility is to define your own enumeration that has the values Y and N:
type Yes_No is (N, Y);
package Yes_No_IO is new Enumeration_IO (Yes_No); -- Enumeration_IO is in Ada.Text_IO
Answer : Yes_No;
Put(Item => "Does Sophie have a big assignment due in class, True/False? ");
Yes_No_IO.Get(Item => Answer);
SophieAssignment := (Answer = Y);
Get here will set Answer to either Y or N if the user enters the enumeration name (in either case); it will raise Data_Error if something else is entered. I'd prefer the first method if you want better control over how input is handled. For the second, if the user enters "Y Z", Get will return the Y, and the Z is left in the input stream waiting for the next input operation. Also, the first method allows for multiple possible answers better than the second, although you could make it work with an enumeration like
type Yes_No is (N, No, Y, Yes);
(2) To output "Yes" or "No" based on a Boolean, you can use a function as in Keith's answer, or you can set up an array:
type Const_String_Acc is access constant String;
Yes_No_Image : constant array (Boolean) of Const_String_Acc :=
(False => new String' ("No"),
True => new String' ("Yes"));
Put(Item => "Should we have a snow day today? " & Yes_No_Image (SnowDay).all);
To print a Boolean value as "Yes" or "No", just write a function:
function Boolean_Image(B: Boolean) return String is
begin
if B then
return "Yes";
else
return "No";
end if;
end Boolean_Image;
and use it in place of Boolean'Image.
To read a value from the user as Y or y for True, or as N or n for False, just read a Character value and test it to determine which Boolean value to set. Think about how you want to respond if the character the user enters is not any of Y, y, N, or n. You can use Get_Immediate to read a single character without waiting for a newline on input.
type Snow_Day_Type is new Boolean;
function Yes return Snow_Day_Type is (Snow_Day_Type'(True));
function No return Snow_Day_Type is (Snow_Day_Type'(False));

VHDL - init std_logic_vector array from HEX file

I have simple "RAM" implemented as:
type memory_array is array(31 downto 0) of std_logic_vector(7 downto 0);
signal ram : memory_array;
I would like to init it's content from HEX file. I wonder about reading the file like:
ram_init: process
file file_ptr : text;
variable line_text : string(1 to 14);
variable line_num : line;
variable lines_read : integer := 0;
variable char : character;
variable tmp_hexnum : string(1 to 2);
begin
file_open(file_ptr,"../RAM.HEX",READ_MODE);
while (not endfile(file_ptr)) loop
readline (file_ptr,line_num);
READ (line_num,line_text);
if (lines_read < 32) then
tmp_hexnum := line_text(10 to 11);
-- ram(lines_read) <= tmp_hexnum;
lines_read := lines_read + 1;
wait for 10 ns;
end if;
end loop;
file_close(file_ptr);
wait;
end process;
The problem is (if this code above would works, which I don't even know), how to convert the tmp_hexnum string to std_logic_vector.
Please have patience with me, VHDL beginner.
The first mistake is to use a process : if you attempt to synthesise the design, the process won't do anything until the design is built and running; which is far too late to read a file!
Instead, wrap the init code in a function, and use that to initialise the memory
signal ram : memory_array := my_ram_init(filename => "../RAM.HEX");
This will work in simulation, and many synthesis tools will infer a RAM and initialise it correctly. If you declared a constant instead of a signal, this would create a ROM instead of a RAM.
Anyway the function looks a bit like
function my_ram_init(filename : string) return memory_array is
variable temp : memory_array;
-- other variables
begin
file_open(...);
-- you have a good handle on the function body
file_close(...);
return temp;
end function;
leaving you with the original problem :
temp(lines_read) <= to_slv(tmp_hexnum);
writing the to_slv function. There ought to be a standard library of these, but for some reason there isn't a universally accepted one. So, here's a start...
function to_slv (tmp_hexnum : string) return std_logic_vector is
variable temp : std_logic_vector(7 downto 0);
variable digit : natural;
begin
for i in tmp_hexnum'range loop
case tmp_hexnum(i) is
when '0' to '9' =>
digit := Character'pos(tmp_hexnum(i)) - Character'pos('0');
when 'A' to 'F' =>
digit := Character'pos(tmp_hexnum(i)) - Character'pos('A') + 10;
when 'a' to 'f' =>
digit := Character'pos(tmp_hexnum(i)) - Character'pos('a') + 10;
when others => digit := 0;
end case;
temp(i*4+3 downto i*4) := std_logic_vector(to_unsigned(digit));
end loop;
return temp;
end function;
Converting a string of variable length to std_logic_vector with length as 4 *
length of string, can be done with the function below:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
...
-- Convert string to std_logic_vector, assuming characters in '0' to '9',
-- 'A' to 'F', or 'a' to 'f'.
function str_to_slv(str : string) return std_logic_vector is
alias str_norm : string(1 to str'length) is str;
variable char_v : character;
variable val_of_char_v : natural;
variable res_v : std_logic_vector(4 * str'length - 1 downto 0);
begin
for str_norm_idx in str_norm'range loop
char_v := str_norm(str_norm_idx);
case char_v is
when '0' to '9' => val_of_char_v := character'pos(char_v) - character'pos('0');
when 'A' to 'F' => val_of_char_v := character'pos(char_v) - character'pos('A') + 10;
when 'a' to 'f' => val_of_char_v := character'pos(char_v) - character'pos('a') + 10;
when others => report "str_to_slv: Invalid characters for convert" severity ERROR;
end case;
res_v(res_v'left - 4 * str_norm_idx + 4 downto res_v'left - 4 * str_norm_idx + 1) :=
std_logic_vector(to_unsigned(val_of_char_v, 4));
end loop;
return res_v;
end function;
Your (both) answers helped me a lot. But it seems not working.
function ram_init(filename : string) return memory_array is
variable temp : memory_array;
file file_ptr : text;
variable line_line : line;
variable line_text : string(1 to 14);
variable tmp_hexnum : string(1 to 2);
variable lines_read : integer := 0;
begin
file_open(file_ptr,filename,READ_MODE);
while (lines_read < 32 and not endfile(file_ptr)) loop
readline (file_ptr,line_line);
read (line_line,line_text);
tmp_hexnum := line_text(10 to 11);
temp(lines_read) := hex_to_bin(tmp_hexnum);
lines_read := lines_read + 1;
end loop;
file_close(file_ptr);
return temp;
end function;
signal ram : memory_array := ram_init(filename=>"../RAM.HEX");
If I set tmp_hexnum to e.g. "0A", it's OK, but reading from file do not fill the RAM.
Can you please check the file part for me, too?