I somehow cannot compile (neither run) my Ada code in GPS. I get an error:
cannot generate code for file random.ads (package spec)
gprbuild: *** compilation phase failed
The random.ads file looks like this:
with Ada.Numerics.Float_Random;
use Ada.Numerics.Float_Random;
package random is
protected randomOut is
procedure Inicializal;
entry Parcel(
randomout: out Positive;
from: in Positive;
to: in Positive := 1
);
private
G: Generator;
Inicializalt: Boolean := False;
end randomOut;
task print is
entry write(what: in String);
end print;
end random;
The .gpr file looks as follows:
project Default is
package Compiler is
for Default_Switches ("ada") use ("-g", "-O2");
end Compiler;
for Main use ("hunting.adb");
end Default;
What does this mean? How can I fix it? Thank you!
You can't generate code for a package specification.
This is normal and expected.
You can compile the package body, random.adb, and generate code for it - but there's usually no need.
Just compile your main program, (or your test harness if you're unit testing) and let the compiler find all its dependencies.
(If it can't, either you haven't written them yet, or it's looking in the wrong place. If you need help with that, add relevant info to the question).
The problem is caused by
task print is
entry write(what: in String);
end print;
As any task is specified as a body, the compiler had trouble deciding: it had a body, that has to be compiled, in a spec file, which does not. Moving the task to the .adb file solved the issue.
Related
I'm using Julia to autograde students' work. I have all of their files Student1.jl, Student2.jl, etc. as separate modules Student1, Student2, etc in a directory that is part of LOAD_PATH. What I want to be able to do works completely fine in the REPL, but fails in a file.
macro Student(number)
return Meta.parse("Main.Student$number")
end
using Student1
#Student(1).call_function(inputs)
works completely fine in the REPL. However, since I'm running this in a script, I need to be able to include the modules with more metaprogramming that is currently not working. I would have thought that the exact same script above would have worked in a file Autograder.jl by calling
#eval(using Student1)
#Student(1).call_function(inputs)
in a module Autograder. But I get either an UndefVarError: Student1 not defined or LoadError: cannot replace module Student1 during compilation depending on how I tweak things.
Is there something small in Julia metaprogramming I'm missing here to make this autograding system work out? Thanks for any advice.
The code just as you have written works for me on julia versions 1.1.0, 1.3.1, 1.5.1, 1.6.0 and 1.7.0. By that I mean, if I add an inputs variable and put your first code block in a file Autograder.jl and run JULIA_LOAD_PATH="modules:$JULIA_LOAD_PATH" julia Autograder.jl with the student modules in the modules directory I get the output of the call_function function in the Student1 module.
However if Autograder.jl actually contains a module then the Student$number module is not required into Main and your macro needs to be modified accordingly:
module Autograder
macro Student(number)
return Meta.parse("Student$number") # or "Autograder.Student$number"
end
inputs = []
#eval(using Student1)
#Student(1).call_function(inputs)
end
Personally I wouldn't use a macro to accomplish this, here is one possible alternative:
student(id) = Base.require(Main, Symbol("Student$(id)"))
let student_module = student(1)
student_module.call_function(inputs)
end
or without modifying the LOAD_PATH:
student(id) = include("modules/Student$(id).jl")
let student_module = student(1)
student_module.call_function(inputs)
end
I would like to know how in the Julia language, I can determine if a file.jl is run as script, such as in the call:
bash$ julia file.jl
It must only in this case start a function main, for example. Thus I could use include('file.jl'), without actually executing the function.
To be specific, I am looking for something similar answered already in a python question:
def main():
# does something
if __name__ == '__main__':
main()
Edit:
To be more specific, the method Base.isinteractive (see here) is not solving the problem, when using include('file.jl') from within a non-interactive (e.g. script) environment.
The global constant PROGRAM_FILE contains the script name passed to Julia from the command line (it does not change when include is called).
On the other hand #__FILE__ macro gives you a name of the file where it is present.
For instance if you have a files:
a.jl
println(PROGRAM_FILE)
println(#__FILE__)
include("b.jl")
b.jl
println(PROGRAM_FILE)
println(#__FILE__)
You have the following behavior:
$ julia a.jl
a.jl
D:\a.jl
a.jl
D:\b.jl
$ julia b.jl
b.jl
D:\b.jl
In summary:
PROGRAM_FILE tells you what is the file name that Julia was started with;
#__FILE__ tells you in what file actually the macro was called.
tl;dr version:
if !isdefined(:__init__) || Base.function_module(__init__) != MyModule
main()
end
Explanation:
There seems to be some confusion. Python and Julia work very differently in terms of their "modules" (even though the two use the same term, in principle they are different).
In python, a source file is either a module or a script, depending on how you chose to "load" / "run" it: the boilerplate exists to detect the environment in which the source code was run, by querying the __name__ of the embedding module at the time of execution. E.g. if you have a file called mymodule.py, it you import it normally, then within the module definition the variable __name__ automatically gets set to the value mymodule; but if you ran it as a standalone script (effectively "dumping" the code into the "main" module), the __name__ variable is that of the global scope, namely __main__. This difference gives you the ability to detect how a python file was ran, so you could act slightly differently in each case, and this is exactly what the boilerplate does.
In julia, however, a module is defined explicitly as code. Running a file that contains a module declaration will load that module regardless of whether you did using or include; however in the former case, the module will not be reloaded if it's already on the workspace, whereas in the latter case it's as if you "redefined" it.
Modules can have initialisation code via the special __init__() function, whose job is to only run the first time a module is loaded (e.g. when imported via a using statement). So one thing you could do is have a standalone script, which you could either include directly to run as a standalone script, or include it within the scope of a module definition, and have it detect the presence of module-specific variables such that it behaves differently in each case. But it would still have to be a standalone file, separate from the main module definition.
If you want the module to do stuff, that the standalone script shouldn't, this is easy: you just have something like this:
module MyModule
__init__() = # do module specific initialisation stuff here
include("MyModule_Implementation.jl")
end
If you want the reverse situation, you need a way to detect whether you're running inside the module or not. You could do this, e.g. by detecting the presence of a suitable __init__() function, belonging to that particular module. For example:
### in file "MyModule.jl"
module MyModule
export fun1, fun2;
__init__() = print("Initialising module ...");
include("MyModuleImplementation.jl");
end
### in file "MyModuleImplementation.jl"
fun1(a,b) = a + b;
fun2(a,b) = a * b;
main() = print("Demo of fun1 and fun2. \n" *
" fun1(1,2) = $(fun1(1,2)) \n" *
" fun2(1,2) = $(fun2(1,2)) \n");
if !isdefined(:__init__) || Base.function_module(__init__) != MyModule
main()
end
If MyModule is loaded as a module, the main function in MyModuleImplementation.jl will not run.
If you run MyModuleImplementation.jl as a standalone script, the main function will run.
So this is a way to achieve something close to the effect you want; but it's very different to saying running a module-defining file as either a module or a standalone script; I don't think you can simply "strip" the module instruction from the code and run the module's "contents" in such a manner in julia.
The answer is available at the official Julia docs FAQ. I am copy/pasting it here because this question comes up as the first hit on some search engines. It would be nice if people found the answer on the first-hit site.
How do I check if the current file is being run as the main script?
When a file is run as the main script using julia file.jl one might want to activate extra functionality like command line argument handling. A way to determine that a file is run in this fashion is to check if abspath(PROGRAM_FILE) == #__FILE__ is true.
I have an ada program that has a main procedure, now I want to add another procedure but I got an error saying "end of file expected, file can have only one compilation unit". I did some looking an I think it is because you can only have 1 procedure per file. Do I have to create another file and put the procedure alone in that? If so how would I compile both the codes and run it? Can someone show me how I would be able to compile both and run the whole file together.
As the compiler says, you can only have one compilation unit per file. A main program is compilation unit, which is a procedure.
If you want one program to run two procedures which both are compilation units, when you can do it like this:
with One_Procedure,
Another_Procedure;
procedure Sequential is
begin
One_Procedure;
Another_Procedure;
end Sequential;
If you want to run the two procedures in parallel do it like this:
with One_Procedure,
Another_Procedure;
procedure Parallel is
task One;
task Another;
task body One is
begin
One_Procedure;
end One;
task body Another is
begin
Another_Procedure;
end Another;
begin
null;
end Parallel;
The procedures may of course also be declared in the declarative region of the main program or in some packages.
Both recent GNATs and GPRbuild have options for indicating which units of a file you want compiled: that's -gnateINNN for gcc, and -eInn for gprbuild, as documented here.
Another option is to become familiar with gnatchop for extracting compilation units from files, and with -m for minimal recompilation; the latter prevents having to compile the world only because of running gnatchop when an edit has not "semantically" touched all compilation units in a file. GNAT then ignores time stamps. I sometimes run commands like
gnatchop -r -w -c allofit.ada && gnatmake -Ptest -m someunit.adb
where someunit.adb is generated for compilation unit Someunit (a procedure, a package) contained in file allofit.ada.
You can have 1 main procedure but several procedures within main procedure.
procedure main is
...text...
procedure sub1 () is
begin
...text...
end sub1;
procedure sub2 () is
begin
...text...
end sub2;
...text...
end main;
I'm trying to get a couple of tasks to be able to call each other, but I don't seem very good with this limited with thing..
I have a spec sctrain-trains.ads
limited with SCTrain.Stations;
with SCTrain.Travellers, SCTrain.Tracks, Ada.Strings.Unbounded;
use SCTrain.Travellers, SCTrain.Tracks, Ada.Strings.Unbounded;
package SCTrain.Trains is
type my_station_access_t is access all Stations.Station;
task type Train is
entry Start(leaving: my_station_access_t; arriving: my_station_access_t);
end Train;
end SCTrain.Trains;
and its .adb
with SCTrain.Stations;
use SCTrain.Stations;
package body SCTrain.Trains is
task body Train is
destination: my_station_access_t;
begin
accept Start(leaving: my_station_access_t; arriving: my_station_access_t) do
destination := arriving;
end Start;
destination.Gogo(1);
end Train;
end SCTrain.Trains;
I found in the documents I've been reading that withing the "circular" package in the body would allow smooth executions, but apparently I still have an invalid prefix in selected component "destination" because dereference must not be of an incomplete type (RM 3.10.1), and those errors stay there even without the with and use in the package body.
I'm sure I'm missing something, possibly something very basic, and I'd really love to know what that is. The problem I'm trying to solve is that the Train needs a signal from the Station to be allowed to leave and still able to communicate its arrival time afterwards.
I'm using the latest GNAT-GPL.
Thank you very much.
edit: adding Station's code
limited with SCTrain.Trains;
with Ada.Calendar, Ada.Strings.Unbounded, Ada.Text_IO;
use Ada.Calendar, Ada.Strings.Unbounded, Ada.Text_IO;
package SCTrain.Stations is
task type Station is
entry Gogo(name_d : Integer := 0);
end Station;
end SCTrain.Stations;
and the body:
with SCTrain.Trains;
use SCTrain.Trains;
package body SCTrain.Stations is
task body Station is
name : Integer;
begin
accept Gogo (name_d : Integer := 0) do
name := name_d;
Put_Line("Station " & Integer'Image(name) & " is alive");
end Gogo;
end Station;
end SCTrain.Stations;
Use limited with in one direction only, and a normal with in the other.
Replace the declaration of destination by
destination: access Stations.Station;
or replace the offending line by
destination.all.Gogo(1);
I don't know whether this is a compiler bug or proper behaviour; it looks suspicious!
Later: I posted a still-more-cut-down example on comp.lang.ada and one of the resident experts agrees that it's a bug; I'll report it to AdaCore.
I have defined the macros of all my verilog files in one verilog file, say FabScalarParam.v
and I compile the FabScalarParam.v first in the system.do file then compile other verilog files.
But when I run "do system.do" to compile the design, it shows me the errors like this,
# ** Error: I:/programming/EDK/project_4/pcores/instruction_side_v1_00_a/hdl/verilog/StallUnit.v(6): (vlog-2163) Macro `MAX_STALL_CYCLES_LOG is undefined.
It says that some macros are not defined. Is there any method to choose the FabScalarParam.v as global file in compile list in modelsim? Due to the large number of macros, I cannot specify all the macros using the method: compile --> compile options --> verilog & system verilog --> other verilog options --> Macros.
I use modelsim 6.5, xilinx edk 12.4
This has to do with compile order. Compiler directives, which included macros are processed linearly by the compiler. See IEEE1364-2001 section 19 or IEEE1800-2009 section 22 for more detail. Make sure the macro file is the first file to that is compiled.
Manually adding the `include also works, however your compiler may give macro redefined warnings. It is recommend to encapsulate the macro definitions in a `ifdef/`ifndef. Doing so resolve the macro defined warnings. If multiple files refer to same `include then encapsulation of the macros may also improve compiler performance. See the following example.
macros.vh:
`ifndef macros_vh
// NOTE: for Verilog 1995 `ifndef is not supported use `ifdef macros_vh `else
`define macros_vh
/**************
* your macros *
* `define ... *
***************/
`endif
Then in your verilog files (*.v / *.sv)
`include "macro.vh"
/*************
* your code *
*************/
I cannot find anything useful on Internet to set global file in the compile list in modelsim. So, I just manually add `include ... in each file to solve the problem. Though it is stupid, It works fine.
If someone knows how to set the global file in the compile list in modelsim, please update it. :-) Thanks.
I had the same problem when I compiled my project with script.
At last, I figure out you can't compile your macro and verilog files in different scope.
EX:
vlog -work work macro.v
vlog -work work project.v
You have to:
vlog -work work macro.v project.v
Compiling them in one vlog command can solve the problem.
You can compile a verilog file and define the precompiler macro that will be applied for this file by adding the following option to vlog:
+define+<macro_name>[=<macro_text>]
which Same as compiler directive: `define macro_name macro_text
for example:
vlog +define+macro_name -work work project.v
This is my work around without adding `include in every files needing macros
vlog -mfcu -y <path/to/source/files> +libext+.v+.sv <source file 1> <source file 2> <... source file N>
-mfcu let vlog treats all source files in one command line as one compilation unit. If macro are defined in <source file 1>, they are visible to all following source files after it.