How to execute Haskell code in the context of Main with `stack`? - bash

I'm looking to do something like this
$ stack eval 'functionDefinedInMain $ 1 + 1' > test1.txt
However, when I execute that, stderr tells me
<interactive>:1:1: Not in scope: ‘functionDefinedInMain’
I've also tried to pipe code into stack ghci, which gets me closer:
$ echo 'functionDefinedInMain $ 1+1' | stack ghci > test2.txt
Using main module: 1. Package `exp-proj' component exe:exp-proj with main-is file: /home/wizek/sandbox/exp-proj/exp-proj/src/Main.hs
Configuring GHCi with the following packages: exp-proj
$ cat test2.txt
GHCi, version 7.10.3: http://www.haskell.org/ghc/ :? for help
[1 of 5] Compiling Utils ( /home/wizek/sandbox/exp-proj/exp-proj/src/Utils.hs, interpreted )
[2 of 5] Compiling Vertex ( /home/wizek/sandbox/exp-proj/exp-proj/src/Vertex.hs, interpreted )
[3 of 5] Compiling Edge ( /home/wizek/sandbox/exp-proj/exp-proj/src/Edge.hs, interpreted )
[4 of 5] Compiling Lib ( /home/wizek/sandbox/exp-proj/exp-proj/src/Lib.hs, interpreted )
[5 of 5] Compiling Main ( /home/wizek/sandbox/exp-proj/exp-proj/src/Main.hs, interpreted )
Ok, modules loaded: Utils, Vertex, Edge, Lib, Main.
*Main Edge Lib Utils Vertex> 3
*Main Edge Lib Utils Vertex> Leaving GHCi.
As you can see, the output (which is just the number 3 in this example) file is polluted by GHCi.
I'd like the content of the file to be instead:
$ cat test2.txt
3
How can I either
load all my project modules with stack eval as specified in my .cabal file to execute code in context, or
suppress GHCi output to stdout? (I don't mind if GHCi puts messages on stderr)
$ stack --version
Version 1.0.2, Git revision fa09a980d8bb3df88b2a9193cd9bf84cc6c419b3 (3084 commits) x86_64
edit: Added unix and bash tags since it might be possible to achieve this by piping together different stack/GHCi commands even without explicit support from stack.

The -e flag in ghc -e expects a Haskell expression and has—by default—only access on Prelude. You need to use additional functions fully qualified:
stack eval 'Library.someFunc $ 1+1'
^^^^^^^^
However, this does only work in the following circumstances:
The module must be part of your library, not your executable.
The expression must be exported from the module.
If you're just trying to use Main.xxx, make sure that Main is a visible module in your library. This also concludes that you cannot use eval for executable only projects. However, this can lead to strange problems. For example, GHCi will try to import Main twice, once via the executable and once via the library.
Example
$ stack new exp-eval simple
$ cd exp-eval
$ cat addition >> exp-eval.cabal
$ stack eval 'Main.main'
Where addition has the following content:
library
hs-source-dirs: src
exposed-modules: Main
default-language: Haskell2010
build-depends: base >= 4.7 && < 5

I don't quite get what you want to do - do you want to execute the main - then use
$> stack runghc ./src/Main.hs > test.txt
or
$> stack build
$> stack exec -- modulename > test.txt
to invoke the compiled binary.
If you have a function that is exported in main it is easiest to use stack ghci and call the function from inside - if it produces a String you can then use
writeFile "test.txt" (myfunction parameter1 parameter2)
to get the desired result.
I have not used stack eval before but I guess you have to export your function in a library for that, I guess your cabal file says that you have only an export of an executable - to give you more info I would need your cabal file.

Related

How to print statement with line and stack trace in Haskell?

How do you make a print statement with a line number and stack trace in Haskell?
You might like to play with GHC.Stack in the latest release of GHC.
Either use this...
Haskell Print Debugger - http://hackage.haskell.org/package/print-debugger
Or use this...
Debug.Trace.traceStack - https://hackage.haskell.org/package/base-4.8.2.0/docs/Debug-Trace.html
The former can print a single line formatted. The latter can print multiple lines unformatted.
Debug.Trace.traceStack requires compiling with -frof and -fprof-auto and running with +RTS -xc
Debug.Trace.traceStack Example (from "What I Wish I Knew When Learning Haskell"):
http://dev.stephendiehl.com/hask/):
$ ghc -O0 -rtsopts=all -prof -auto-all --make stacktrace.hs
./stacktrace +RTS -xc
Haskell Print Debugger Example:
-- http://i.imgur.com/av57mTS.png
import Debug.Print.StackTraceDebug
main = debugTraceIO "This has a stack trace."
____________________________________________
This has a stack trace. in thread "1" :
at Main.call(Main.hs:5)
If you just need to find your print statements the first option is a better choice.
p.s. I am advertising my own package located here:
https://github.com/JohnReedLOL/HaskellPrintDebugger

Confusing debugging error in Fortran program

I've been sitting here for a while quite baffled as to why my debugger keeps displaying an error in my code when the program runs fine. There are three parts to a very simple program that is just reading in information from a file.
My code is broken into three Fortran files given below and compiled via
ifort -o test global.f90 read.f90 test.f90
global.f90:
module global
implicit none
integer(4), parameter :: jsz = 904
end module global
read.f90:
subroutine read(kp,q,wt,swt)
implicit none
integer(4) :: i, j
integer(4), intent(in) :: kp
real(8), intent(out) :: swt, q(kp,3), wt(kp)
swt = 0.0d0; q(:,:) = 0.0d0; wt(:) = 0.0d0
open(7,file='test.dat')
read(7,*) ! Skipping a line
do i = 1, kp
read(7,1000)(q(i,j),j=1,3), wt(i)
swt = swt + wt(i)
end do
close(7)
return
1000 format(3F10.6,1X,1F10.6)
end subroutine read
test.f90:
program test
use global
integer(4) :: i, j
real(8) :: tot, qq(jsz,3), wts(jsz)
call read(jsz,qq,wts,tot)
stop
end program test
The error I keep receiving is
Breakpoint 1, read (kp=904,
q=<error reading variable: Cannot access memory at address 0x69bb80>,
wt=..., swt=6.9531436082559572e-310) at read.f90:6
This error appears right when the subroutine of read is called. In other words, I'm adding a breakpoint at the read subroutine and running the code in gdb after the breakpoint is added. The program will continue to run as expected and give the correct outputs when I include write statements in the 'test' program. However, if I use the gdb print options I receive an error of 'Cannot access memory at address 0x69bb80' for array q only. All other arrays and variables can be displayed with no problems.
As I would like the read subroutine to be a stand alone subroutine and not necessarily use any global parameters, I have not used the global module and instead called the variable kp into the subroutine. I decided to test whether using the global module would help, and if I use jsz in place of kp, I do indeed remove the error. However, since this isn't my overall goal with the subroutine, I would hopefully like to figure out how to fix this without the use of the global module. (I also tried not using the global at all and setting the parameter variable of kp in the test.f90 program directly, but this also gives the error.)
Any insight on possible reasons for this error, or suggestions to try and fix the memory addressing issue would be greatly appreciated.
I think this is an issue specific to the ifort+gdb combination that is fixed with newer gdb versions. Here's a smaller example to reproduce the issue:
$ cat test.f90
subroutine bar(arg)
integer, intent(inout):: arg
print *, 'bar argument is', arg
arg = 42
end subroutine bar
program test
integer:: param
param = 3
call bar(param)
print *, 'post-bar param:', param
end program test
$ ifort -g -O0 -o test test.f90
$ gdb --quiet test
Reading symbols from /home/nrath/tmp/test...done.
(gdb) b 4
Breakpoint 1 at 0x402bd0: file test.f90, line 4.
(gdb) r
Starting program: /home/nrath/tmp/test
[Thread debugging using libthread_db enabled]
Breakpoint 1, bar (arg=#0x2aaa00000003) at test.f90:4
4 print *, 'bar argument is', arg
(gdb) p arg
$1 = (REF TO -> ( INTEGER(4) )) #0x2aaa00000003: <error reading variable>
(gdb) quit
$ gdb --version | head -1
GNU gdb (GDB) Red Hat Enterprise Linux (7.2-60.el6_4.1)
However, if you compile with gfortran instead of ifort, or if you use GDB 7.7.1, it works fine.
Did you add the INTERFACE statement to the end of your programme?
You need it when you call a function that is not contained in the programme.

LLDB equivalent of gdb "directory" command for specifying source search path?

Looking for the lldb equivalent of the gdb "directory" command to add search paths for finding missing source code (or possibly similar functionality within xcode)?
Thanks in advance!
The target.source-map setting allows you define a series of a => b path remappings in the debug session. It's not identical to the gdb dir command, which is a list of directories to search for source files by base name, but you can solve the same problems with source-map. Here's an example where I move a source file to a hidden directory after compiling:
% cd /tmp
% echo 'int main () { }' > a.c
% clang -g a.c
% mkdir hide
% mv a.c hide/
% xcrun lldb a.out
(lldb) settings set target.source-map /tmp /tmp/hide
(lldb) l -f a.c
1 int main () { }
(lldb) br se -n main
Breakpoint created: 1: name = 'main', locations = 1
(lldb) r
Process 21674 launched: '/private/tmp/a.out' (x86_64)
Process 21674 stopped
* thread #1: tid = 0x1f03, 0x0000000100000f49 a.out`main + 9 at a.c:1, stop reason = breakpoint 1.1
#0: 0x0000000100000f49 a.out`main + 9 at a.c:1
-> 1 int main () { }
(lldb)
For more information about this setting, type set list target.source-map in lldb. fwiw you might have discovered this in lldb by doing apropos path which will list all commands/settings that have the word path in the name/description. Seeing that there was a setting by this name, you'd do settings list to see the list of settings and find out that it's filed under target..
The problem with lldb not being able to find your source files may be caused by flawed compilation process - i just spent several hours in attempt to find a lldb command to set path to sources by force but ended up discovering that i performed both actual compiling and linking with identical set of flags (-Wall -Werror -Wextra -g) in my Makefile... So compiler worked without warning and error messages despite errors (or warning treated as errors) actually existed. Fixing them fixed lldb workflow. Maybe developers should consider adding some warning (for newbies like me) in case program wasn't able to find sources (they were located in the very same directory in src folder).

Compiling multiple Ocaml files

I am new to Ocaml and trying to write some small example application. I am using ocamlc version 3.11.2 under Linux Ubuntu 10.04. I want to compile two files:
a.ml
b.ml
File b.ml uses definitions from a.ml. As far as I understand, I can use ocamlc -c to perform compilation only. I can call ocamlc one final time when I have all the .cmo files to link them to an executable. Also, when compiling a file that uses definitions from another file, I have to tell the compiler in which .cmi file to find the external definitions.
So my idea was to use:
ocamlc -i -c a.ml > a.mli
ocamlc -c a.mli b.ml
ocamlc -o b a.cmo b.cmo
The first step works and produces files a.mli and a.cmo, but when running the second step I get
File "b.ml", line 1, characters 28-31:
Error: Unbound value foo
where foo is a function that is defined in a.ml and called in b.ml.
So my question is: how can I compile each source file separately and specify the interfaces to be imported on the command line? I have been looking in the documentation and as far as I can understand I have to specify the .mli files to be included, but I do not know how.
EDIT
Here some more details. File a.ml contains the definition
let foo = 5;;
File b.ml contains the expression
print_string (string_of_int foo) ^ "\n";;
The real example is bigger but with these files I already have the error I reported above.
EDIT 2
I have edited file b.ml and replaced foo with A.foo and this works (foo is visible in b.ml even though I have another compilation error which is not important for this question). I guess it is cleaner to write my own .mli files explicitly, as suggested by
It would be clearer if you showed the code that's not working. As Kristopher points out, though, the most likely problem is that you're not specifyig which module foo is in. You can specify the module explicitly, as A.foo. Or you can open A and just use the name foo.
For a small example it doesn't matter, but for a big project you should be careful not to use open too freely. You want the freedom to use good names in your modules, and if you open too many of them, the good names can conflict with each other.
First fix the unbound value issue, as explained by Jeffrey's answer.
This is a comment about the commands you're using.
Decomposing compilation in several steps is a good way to understand what's going on.
If you want to write your own a.mli, most likely to hide some values of the module A, then your command ocaml -i -c a.ml > a.mli is a good way to get a first version of the this file and then edit it. But if you're not touching a.mli, then you don't need to generate it: you can also directly enter
ocamlc -o foo a.ml b.ml
which will produce a.cmo, b.cmo and the exectuable foo.
(It will also generate a.cmi, which is the compiled version of a.mli, that you get by issuing ocamlc -c a.mli. Likewise it will also generate b.cmi).
Note that order matters: you need to provide a.ml before b.ml on the command line. This way, when compiling b.ml, the compiler has already seen a.ml and knows where to find the module A.
Some more comments:
You're right in your "As far as I understand" paragraph.
you don't really include a separate file, it's more like import in Python: the values of module A are available, but under the name A.foo. The contents of a.ml has not been copy-pasted into b.ml, rather, values of the module A, defined in a.ml and it's compiled version a.cmo have been accessed.
if you're using this module A in b.ml, you can pass any of the following on the command line before b.ml:
a.mli, which will get compiled into a.cmi
a.cmi if you've already compiled a.mli into a.cmi
a.ml or its compiled version a.cmo if you don't need to write your own a.mli, i.e. if the default interface of module A suits you. (This interface is simply every value of a.ml).

Fortran module variables not accessible in debuggers

I've compiled a Fortran code, which contains several modules, using both gfortran 4.4 and intel 11.1 and subsequently tried to debug it using both gdb and DDT. In all cases, I cannot see the values of any variables that are declared in modules. These global variables have values, as the code still runs correctly, but I can't see what the values are in my debuggers. Local variables are fine. I've had trouble finding a solution to this problem elsewhere online, so perhaps there is no straightforward solution, but it's going to be really difficult to debug my code if I can't see the values of any of my global variables.
With newer GDBs (7.2 if I recall correctly), debugging modules is simple. Take the following program:
module modname
integer :: var1 = 1 , var2 = 2
end module modname
use modname, only: newvar => var2
newvar = 7
end
You can now run:
$ gfortran -g -o mytest test.f90; gdb --quiet ./mytest
Reading symbols from /dev/shm/mytest...done.
(gdb) b 6
Breakpoint 1 at 0x4006a0: file test.f90, line 6.
(gdb) run
Starting program: /dev/shm/mytest
Breakpoint 1, MAIN__ () at test.f90:6
6 newvar = 7
(gdb) p newvar
$1 = 2
(gdb) p var1
No symbol "var1" in current context.
(gdb) p modname::var1
$2 = 1
(gdb) p modname::var2
$3 = 2
(gdb) n
7 end
(gdb) p modname::var2
$4 = 7
(gdb)
In gdb, try referencing the global variables with names like __modulename__variablename
You can check that this is the right mangling scheme using nm and grep to find one of your global variables in the symbols of your program.
If that doesn't work, make sure you're using a recent version of gdb.
Here's a thread on this issue: http://gcc.gnu.org/ml/fortran/2005-04/msg00064.html
I had the same issue (GNU gdb 7.9 running in parallel with MPI). What worked for me was the following:
p __modname_mod_var
That is: double underscore, the name of the module, underscore, mod, the name of the variable.
Compiling with -gstabs+ instead of -g may also fix some issues (but not the present one).

Resources