OCaml compilation with corebuild - ocaml

I currently have a project (Go to Python compiler) with the following files
ast.ml
parser.mly
lex.mll
weeder.ml
prettyPrint.ml
main.ml
Here are the dependencies:
parser: ast
lexer: parser, Core, Lexing
weeder: ast
prettyPrint: ast
main: ast, lex, parser, weeder, prettyPrint
I try to compile doing the following which should work according to the documentation I read:
$ menhir parser.mly
> Warning: you are using the standard library and/or the %inline keyword. We
recommend switching on --infer in order to avoid obscure type error messages.
$ ocamllex lex.mll
> 209 states, 11422 transitions, table size 46942 bytes
$ ocamlbuild -no-hygiene main.native
> File "parser.mli", line 77, characters 56-59:
Error: Unbound type constructor ast
Command exited with code 2.
Compilation unsuccessful after building 6 targets (2 cached) in 00:00:00.
ast.ml contains a list of type declarations in which I have a
type ast = ...
I spent a few hours now reading doc for ocamlfind, corebuild and ocamlopt and nothing. At some point it compiled by what seemed like a mere coincidence and never worked again. I'm open to using any tool.
Here is what is in parser.mly
%{
open Ast
exception ParserError of string
let rec deOptionTypeInList tupleList =
match tupleList with
| [] -> []
| (a, Some t)::tl -> (a, t)::(deOptionTypeInList tl)
| _ -> raise (ParserError "no type given in type declaration")
%}
[ ... long list of tokens ... ]
%type <ast> prog (* that seems to be the problem *)
%type <string> packDec
%type <dec> dec
%type <dec> subDec
[...]
%start prog
[ ... rules ... ]
And here is the line, the very last, that is refereed to in the error message.
val prog: (Lexing.lexbuf -> token) -> Lexing.lexbuf -> (ast)

The open Ast construct will not be exported to the .mli file where the type of symbols are mentioned. Try using
%type <Ast.ast>
Edit: also, your build commands are weird. You should not call ocamllex and menhir manually, and consequently not need -no-hygiene. Remove all generated files and just do
ocamlbuild -use-menhir main.byte

Related

Unbound value "string_of_sexp"

It works quite well in utop with #require "ppx_jane" but
I added (preprocess (pps ppx_jane)) in my dune file which looks like this:
(library
(preprocess (pps ppx_jane))
(name raftml)
(modules raft rpc types)
(libraries
core
core_unix
proto
grpc
grpc-lwt
ocaml-protoc
lwt
lwt.unix
h2
h2-lwt-unix
domainslib
yojson
ppx_jane
ppx_sexp_conv
ppx_deriving_yojson
ppx_deriving
ppx_deriving_yojson.runtime))
And my types are like this:
type log = {
mutable command: string;
mutable term: int32;
mutable index: int32
} [##deriving sexp]
I call sexp_of_log in my code like this:
let persist () = Out_channel.write_all "file_name" ~data:(Sexp.to_string (sexp_of_log { command = "hello"; term = (10l); index = (24l); }))
And there's an error when I run dune build: Unbound value "string_of_sexp"
I solved this by adding:
open Sexplib.Std
At the top of the file that has the record types deriving sexp.

How to use jbuild and ppx_driver with ppx_deriving

I am trying to use jbuilder together with ppx_deriving (ppx_deriving_yojson specifically) but got stuck for well over an hour now. My current approach is a jbuild file, containing the following:
(jbuild_version 1)
(executables
((names (my-binary))
(libraries
(ppx_deriving
ppx_deriving_yojson
cohttp
yojson))
(preprocess (pps (ppx_deriving_yojson ppx_driver.runner)))))
But that results in
Command [5] exited with code 1:
$ (cd _build/default && ../.ppx/default/ppx_deriving_yojson+ppx_driver.runner/ppx.exe --dump-ast -o src/my_file.pp.ml --impl src/my_file.ml)
File "src/my_file.ml", line 16, characters 5-13:
Error: Attribute `deriving' was not used
Running the generated ppx_driver in _build/.ppx/default/ppx_deriving_yojson+ppx_driver.runner/ppx.exe manually with -print-transformations gives empty output, so I am obviously missing something.
The code builds fine with topkg by just including ppx_deriving and ppx_deriving_yojson as dependencies.
As of more recent versions of ppx_deriving_yojson this should be possible.
Code:
type t = {x: int; y: int} [##deriving to_yojson]
let () = print_endline (Yojson.Safe.to_string (to_yojson {x= 1; y= 2}))
And a sample jbuild file:
(jbuild_version 1)
(executables
((names (main))
(preprocess (pps (ppx_deriving_yojson)))
(libraries (ppx_deriving_yojson.runtime))))
(install
((section bin)
(files ((main.exe as main)))))

Installing RLdev tools on Linux

When installing Haeleth's RLdev I got the error:
$ ./configure && omake
........
File "pa_matches.ml", line 24, characters 2-6:
Parse error: Deprecated syntax, the grammar module is expected
Error while running external preprocessor
Command line: camlp4 pa_o.cmo pa_op.cmo pa_extend.cmo q_MLast.cmo pr_dump.cmo 'pa_matches.ml' > /home/.../tmp/ocamlpp4e8738
*** omake error:
File rlc/OMakefile: lines 26:4-27:88
command terminated with code 2: ocamlc -c -pp 'camlp4 pa_o.cmo pa_op.cmo pa_extend.cmo q_MLast.cmo pr_dump.cmo' -I /usr/lib/ocaml/camlp4 gramlib.cma pa_matches.ml -o pa_matches.cmo
File pa_matches.ml contains only following code:
Line 22: open Pcaml
Line 23: EXTEND
Line 24: expr: LEVEL "expr1"
Line 25: [[ v = expr; "matches"; p = patt -> <:expr< match $v$ with [ $p$ -> True | _ -> False ] >> ]];
Line 26: END
In the INSTALL file specified OCaml version 3.09 but 4.01 installed.
OCaml 3.09 is incompatible to OCaml 4.01. This especially applies to camlp4. With OCaml 3.10 a new, backward incompatible version of camlp4 was introduced.
That's probably the reason, why pa_matches.ml doesn't compile. It uses the old camlp4.

Module case name confusion

I made the mistake of updating software and now I can't run any OUnit tests.
I think I've managed to boil the problem down to a simple REPL session.
$ ocaml -I /opt/local/lib/ocaml/site-lib/oUnit
OCaml version 4.01.0
# Ounit.assert_equal;;
Error: Wrong file naming: /opt/local/lib/ocaml/site-lib/oUnit/ounit.cmi
contains the compiled interface for
Ounit when OUnit was expected
# OUnit.assert_equal;;
Error: Reference to undefined global `OUnit'
Any ideas what I'm doing wrong?
I'm running this on a Mac laptop which has the default case-insensitive/case-preserving file-system, but dinking with the case of the include path doesn't help.
My larger problem manifests thus:
ocamlbuild \
-libs \
nums,str,unix,oUnit,graph \
-cflags \
-g,-w,+a-4,-warn-error,+a-4,-I,/opt/local/lib/ocaml/site-lib/oUnit,-I,/opt/local/lib/ocaml/site-lib/ocamlgraph \
-lflags \
-g,-I,/opt/local/lib/ocaml/site-lib/oUnit,-I,/opt/local/lib/ocaml/site-lib/ocamlgraph \
./AllTests.native
Error: No implementations provided for the following modules:
OUnitCore referenced from /opt/local/lib/ocaml/site-lib/oUnit/oUnit.cmxa(OUnit2),
/opt/local/lib/ocaml/site-lib/oUnit/oUnit.cmxa(OUnit)
OUnitLoggerStd referenced from /opt/local/lib/ocaml/site-lib/oUnit/oUnit.cmxa(OUnit)
OUnitUtils referenced from /opt/local/lib/ocaml/site-lib/oUnit/oUnit.cmxa(OUnit2),
/opt/local/lib/ocaml/site-lib/oUnit/oUnit.cmxa(OUnit)
OUnitConf referenced from /opt/local/lib/ocaml/site-lib/oUnit/oUnit.cmxa(OUnit2),
/opt/local/lib/ocaml/site-lib/oUnit/oUnit.cmxa(OUnit)
OUnitAssert referenced from /opt/local/lib/ocaml/site-lib/oUnit/oUnit.cmxa(OUnit2),
/opt/local/lib/ocaml/site-lib/oUnit/oUnit.cmxa(OUnit)
OUnitBracket referenced from /opt/local/lib/ocaml/site-lib/oUnit/oUnit.cmxa(OUnit2),
/opt/local/lib/ocaml/site-lib/oUnit/oUnit.cmxa(OUnit)
OUnitTest referenced from /opt/local/lib/ocaml/site-lib/oUnit/oUnit.cmxa(OUnit2),
/opt/local/lib/ocaml/site-lib/oUnit/oUnit.cmxa(OUnit)
OUnitRunner referenced from /opt/local/lib/ocaml/site-lib/oUnit/oUnit.cmxa(OUnit)
OUnitChooser referenced from /opt/local/lib/ocaml/site-lib/oUnit/oUnit.cmxa(OUnit)
OUnitLogger referenced from /opt/local/lib/ocaml/site-lib/oUnit/oUnit.cmxa(OUnit2),
/opt/local/lib/ocaml/site-lib/oUnit/oUnit.cmxa(OUnit)
OUnitTestData referenced from /opt/local/lib/ocaml/site-lib/oUnit/oUnit.cmxa(OUnit2)
Command exited with code 2.
Compilation unsuccessful after building 646 targets (645 cached) in 00:00:02.
Your first error is probably because your OS does not distinguish cases in filenames but OCaml does:
$ ocamlobjinfo `ocamlfind query oUnit`/oUnit.cmi
File /mnt/home/jun/.opam/system/lib/oUnit/oUnit.cmi
Unit name: OUnit
Interfaces imported:
cb146e345f0b34fc8ad4b5afe69d1f20 OUnit
...
You can see that the module is called "OUnit" not "Ounit".
The second error is clearly because the library is not loaded into the REPL yet. The REPL's knows the existence of the function, but has no code loaded. It is accessible if you load the library and those on which it depends:
ocaml -I `ocamlfind query oUnit` unix.cma oUnitAdvanced.cma oUnit.cma
OCaml version 4.01.0
# OUnit.assert_equal;;
- : ?cmp:('a -> 'a -> bool) ->
?printer:('a -> string) ->
?pp_diff:(Format.formatter -> 'a * 'a -> unit) ->
?msg:string -> 'a -> 'a -> unit
= <fun>
I solved the problem by changing my ocamlbuild invocation to use -use-ocamlfind which seems to work around all the path confusion.
I also uninstalled all OCaml modules and instead installed OPAM and then installed OUnit and others via OPAM, and re-logged in so that my environment is pristine.
The build command that works for me now is
ocamlbuild \
-use-ocamlfind \
-libs graph \
-pkgs str,unix,ounit \
-cflags -g,-w,+a-4,-warn-error,+a-4,-I,/opt/local/lib/ocaml/site-lib/ocamlgraph \
-lflags -g,-I,/opt/local/lib/ocaml/site-lib/ocamlgraph \
./AllTests.native
which is generated by my updated build script
(* Usage: ocaml make.ml [<ModuleToBuild>.{byte,native}] *)
#load "unix.cma";;
let args = match Array.to_list Sys.argv with
| [] -> failwith "no program on argv"
| _::[] -> ["AllTests.byte"]
| _::argv -> argv
let library_paths = [
(* TODO: Figure out why `opam install ocamlgraph` fails *)
"-I"; "/opt/local/lib/ocaml/site-lib/ocamlgraph";
]
(* If the -p flag is first in the argument list, then replace it
with a host of flags that enable profiling via ocamlprof. *)
let args, c_opt_flags, l_opt_flags =
match args with
| "-p"::rest ->
(* Treat the targets as debug and profile targets. *)
"-tags"::"debug,profile"
(* Use profiling versions of the compilers which instrument
various flow control constructs with entry counters. *)
::"-ocamlc"::"ocamlcp"
::"-ocamlopt"::"ocamloptp"
::rest,
(* Instrument all available points. *)
["-P"; "a"],
(* Link with a wrapper that dumps profiling data if program
exits noramlly. *)
["-p"]
| _ -> args, [], []
let standard_flags = [
"-use-ocamlfind";
(* TODO: Figure out why `opam install ocamlgraph` fails *)
"-libs"; "graph";
"-pkgs"; "str,unix,ounit"; (* TODO: graph *)
"-cflags"; (String.concat "," (
[
"-g";
"-w"; "+a-4";
"-warn-error"; "+a-4";
]
# c_opt_flags
# library_paths));
"-lflags"; (String.concat "," (
[
"-g";
]
# l_opt_flags
# library_paths));
]
let build_command = "ocamlbuild"
let argv = build_command::(standard_flags # args)
let _ = begin
Printf.printf "%s\n" (String.concat " \\\n\t" argv);
flush stdout;
Unix.execvp build_command (Array.of_list argv);
end;;

Can't find namespace for method(16:method)-while client using SOAP::Lite

When I run my perl script (version: 5.6.1), I got below error:
Can't find namespace for method(16:method)
my code was:
my $ws_url = '$url';
my $ws_uri = '$uri';
my $ws_xmlns = '$xmlns';
my $soap = SOAP::Lite
-> uri($ws_uri)
-> on_action( sub { join '/s/', $ws_uri, $_[1] } )
-> proxy($ws_url);
my $method = SOAP::Data->name('Add')
->attr({xmlns => $ws_xmlns});
my #params = ( SOAP::Data->name(addParam => $myParam));
$response = $soap->call($method => #params);
then I read documentation in link:
http://docs.activestate.com/activeperl/5.8/lib/SOAP/Lite.html, which says:
Be warned, that though you have more control using this method, you should
specify namespace attribute for method explicitely, even if you made uri()
call earlier. So, if you have to have namespace on method element, instead of:
print SOAP::Lite
-> new(....)
-> uri('mynamespace') # will be ignored
-> call(SOAP::Data->name('method') => #parameters)
-> result;
do
print SOAP::Lite
-> new(....)
-> call(SOAP::Data->name('method')->attr({xmlns => 'mynamespace'})
=> #parameters)
-> result;
……….
……….
Moreover, it'll become fatal error if you try to call it with prefixed name:
print SOAP::Lite
-> new(....)
-> uri('mynamespace') # will be ignored
-> call(SOAP::Data->name('a:method') => #parameters)
-> result;
gives you:
Can't find namespace for method (a:method)
because nothing is associated with prefix 'a'.
So, I tried change my code to:
my $soap = SOAP::Lite
-> on_action( sub { join '/s/', $ws_uri, $_[1] } )
-> proxy($ws_url);
my #params = ( SOAP::Data->name(addParam => $myParam));
my $response = $soap->call(SOAP::Data->name('Add')->attr({xmlns => $ws_xmlns}) => #params)
->result;
and it still did not work..
any advice?
thanks ahead!
SOAP::Lite uses Scalar::Util. Scalar::Util has XS (ie, compiled C, non-pure-Perl) code in it.
The Perl version you are running with is 5.6.1.
The documentation link you provided points to an ActiveState library for Perl version 5.8.0. I'm going to assume that the version of SOAP::Lite you installed was compiled for use with 5.8.0, since that's the documentation version you cited.
Perl version 5.8.0 is not binary compatible with Perl 5.6.1. Modules compiled for 5.6.1 that contain XS will not run under 5.8.0. Modules compiled for 5.8.0 that contain XS code will not run under 5.6.1. In your case, it's not the module SOAP::Lite that contains the XS code, but one of its dependencies: Scalar::Util.
When you installed SOAP::Lite from the ActiveState repository for 5.8.0, PPM updated all of the module's dependencies, including Scalar::Util. In so doing, it installed a version of Scalar::Util that is not binary compatible with Perl 5.6.1.
The error you're experiencing is sufficiently wonky to support this theory, in the absence of a better one. Seems like the easiest way out of the mess would be to upgrade Perl, as well as your installed modules, and hope it doesn't break something else. ;)