How to print file location of calling function in OCaml? - ocaml

I'm trying to make a custom assert function with greater functionality, except the problem is the assert exception points to inside the custom assert function, which isn't useful for the end user when they're trying to figure out which assertion failed.
Here's what I have so far:
let assert_eq (exp: 'a) (exp2: 'a) =
assert (exp = exp2)

OCaml doesn't have an interface for a function to determine details of its call site. The reason it's possible for the built-in assert mechanism is just that: it's a built-in mechanism, not an ordinary function call.
There is a way to determine the current function, filename, line number, and module. In the documentation for Stdlib (in a section named Debugging) you'll find __FUNCTION_, __FILE__, __LINE__, and __MODULE__. There are a few more similar names that capture various combinations. The documentation for Stdlib is here: https://v2.ocaml.org/releases/4.14/api/Stdlib.html
To create an assert function that can access these values from the call site I'm pretty sure you'll need to create a syntax extension that passes them along. The currently favored mechanism for doing this is PPX. The best general description I could find of PPX is here: https://ocaml-ppx.github.io/ppxlib/ppxlib/manual.html#what-is-ppx
In sum, I'd say this is a project that requires advanced features of OCaml.

Related

how to search for OCaml functions by name and type

In Haskell, there are two main ways to look up information on functions.
Sites like Hoogle and Stackage. These sites provide two main types of searching:
Searching for the name of a function. For example, here is a search on Hoogle for a function called catMaybes.
This search returns the type of the catMaybes function, as well as the package and module it is defined in.
The major use-case for this type of search is when you see a function used somewhere and you want to know its type and what package it is defined in.
Searching for the type of a function. For example, here is a search on Hoogle for a function of type [Maybe a] -> [a].
This search returns multiple functions that have a similar type, the first of which is catMaybes. It also returns the package and module catMaybes is defined in.
The major use-case for this type of search occurs when you are writing code. You know the type of the function you need, and you're wondering if it is already defined somewhere. For example, you have a list of Maybes, and you want to return a list with all the Nothings removed. You know the function is going to have the type [Maybe a] -> [a].
Directly from ghci. In ghci, it is easy to get information about a function with the :info command, as long as the function is already in your environment.
For example, here is a ghci session showing how to get info about the catMaybes function. Note how you must import the Data.Maybes module first:
> import Data.Maybe
> :info catMaybes
catMaybes :: [Maybe a] -> [a] -- Defined in ‘Data.Maybe’
>
:info shows both the type of the catMaybes and where it is defined.
In OCaml, what sites/tools can be used to search for functions by name or type?
For example, I'm reading through Real World OCaml. I came across some code using the |> function. I wondered if there was a function <| for composing the opposite way. However, I don't know of any way of searching for a function called <|. Also, I don't know of any way of figuring out where |> is defined.
Based on the linked code above, I guess the |> would either have to be in Pervasives or somewhere in Jane Street's Core, but it would be nice to have a tool that gave the exact location.
awesome-ocaml has a section on dev tools that should be helpful.
ocamloscope (github) is sort of an Hoogle for OCaml. Search by name works well. Search by type is less good.
For local search by name, ocp-browser provides a convenient TUI.
In your editor, merlin and ocp-index can do lookup-to-definition and lookup-documentation.
There is a WIP public instance of odig here with a lot (but not all) packages. You can use odig locally too, as stated in another answer.
P.S. The function you are looking for is ##, and it's in the standard library.
The ocp-index package provides a basic facility for searching API functions, e.g.,
$ ocp-index locate '|>'
/home/ivg/.opam/devel/build/ocaml/stdlib/pervasives.ml:39:0
The ocp-browser is a beautiful interface to this utility.
They are all integrated with Emacs (and other popular text editors). Speaking of text editors and IDE, Merlin is a killer feature without which I can't imagine OCaml coding anymore. It is capable of jumping directly to the definition, extracting documentation and incremental typechecking.
Speaking of web-based search, there was an argot document generator that has an API search engine featuring type search, full-text search, and regular expressions. A project is somewhat abandoned and doesn't work with the latest OCaml.
We forked it, update to the latest OCaml, fixed a few bugs, and enhanced the unification procedure to get a better type search. The result can be found here.
One of the main features is a search by type manifest, that ignores such irrelevant things as parameter ordering in functions, field names, differences between record names and tuples (e.g., string * int is the same as {name : string; age : int}) and aliasing. For example, in our project there are quite a few aliases, e.g., type bil = stmt list = Stmt.t list = Stmt.t Core_kernel.Std.list = .... You can choose any name when you search (using type manifest), as the algorithm will correctly unify all aliases.
odig may be helpful. once installed, you can browse by package and by function.

Expressive assertion failure messages in C++

Unit test frameworks generally provide very nice assertion failure messages (I'm using gtest) describing expected and actual values to a particular test. Furthermore, you know the origin of the function call because you're testing the interface of the class.
In contrast, assert, when used as a sanity check in the implementation provides some, but more cryptic information. For example, the one I'm working on now . .
Assertion failed: (latency > std::chrono::milliseconds(0)), function setLatency, file /path/to/my.cpp line 71
So I know which assertion failed, but I have no idea what the values were that caused it to fail, and more importantly, I don't know the problematic function from which setLatency was called.
A simple solution normally would be drop to the debugger, but I cannot do this in this instance. Is it possible to get a more descriptive assertion message from within the implementation of a class? How can I do this? I don't mind using a 3rd party lib if necessary.
A common solution for this problem is to create an assert macro. For an example see this question. The final form of their macro in that answer was the following:
#define dbgassert(EX,...) \
(void)((EX) || (realdbgassert (#EX, __FILE__, __LINE__, ## __VA_ARGS__),0))
In your case, the realdbgassert would be a function that prints any relevant information to stderr or other output console, and then calls the assert function itself. Depending on how much information you want, you could also do a stack dump, or log any other relevant information that will help you identify the issue. However, it can be as simple as passing a printf-esque format string, and relevant parameter value(s).
Note that if you compiler doesn't support variadic macros, you can create macros that take a specific number of parameters instead. This is slightly more cumbersome, but an option if your compiler lacks the support, eg:
#define dbgassert0(EX) \ ...
#define dbgassert1(EX,p0) \ ...
#define dbgassert2(EX,p0,p1) \ ...
I am not sure if this is what you are looking for, but you can append any message you like to the "Assertion failed:.." message by doing something like this:
assert(1==1 && "This is always true");
assert(1==0 && "This always fails");
Of course you can modify the string to contain values or more information.

camlp4 syntax extension, parser error

I created a syntax extension that allow the definition of a type as
type.yjson type_name {
/* type_declaration */
}
to be able to build a record value directly from a json file.
The syntax extension insert a module and the function necessary to do so.
Until here, no problem. The syntax extension do exactly what I wanted.
I start having some issue if I want to use "yjson" at some other place in my code (i.e:function parameter).
Here what I tried:
EXTEND Gram
str_item:
[
[ KEYWORD "type"; KEYWORD "."; "yjson"; tdl_raw = type_declaration ->
Here the error I get when I use "yjson" as a function parameter
[fun_binding] expected after [ipatt] (in [let_binding])
I don't really understand what happen here. It doesn't seems like the rule have been match, so why do I get a parse error ?
I do not perfectly understand the P4's mechanism around this, but [ [ "blahblah" -> ... makes blahblah as a new keyword of the language, so you can no longer use blahblah as a function argument.
To see this, try preprocess your pa_*.ml by camlp4of and see how "blahblah" is expanded to Gram.Skeyword "blahblah". It seems that this Skeyword _ is passed to Structure.using via Insert.insert of P4 and the string is registered as a new keyword.
To keep yjson usable as a normal variable, use id = LIDENT instead of "yjson" in your rule, then check id's content is "yjson" or not in your action.
If I can make a slightly off-topic remark, I think it's wrong to design a custom syntax for type-directed code generation, when there already exist two different syntaxes (one for type_conv and one for deriving), one of which (type-conv) is becoming a de facto standard.
type foo = {
...
} with json
If you pick a syntax for this, you should use this one unless you have very good reasons not to. In fact, type-conv itself is a helper utility to let you write your own type-directed code generators, so you may as well use type-conv directly for what you're trying to do.
(You probably know about Martin Jambon's Atdgen, which made a conscious choice not to use Camlp4; there is ongoing work by Alain Frisch to support annotations directly in the OCaml syntax, but that's not yet ready for consumption.)

the reasons of errors in ML code

The below code is just a kind of prototype. What I want to know is why it fails to compile.
fun test(list) =
let
fun inner(list) =
let
val from = #1(hd(list))
in
if null(tl(list)) = false then innerinner(tl(list),from)
else false
end
fun innerinner(list,from) =
if #2(hd(list)) = from then true
else if null(list) = false then innerinner(tl(list),from)
else false
in
inner(list)
end;
The error messages are:
test.txt:7.34-7.44 Error: unbound variable or constructor: innerinner
test.txt:3.2-9.6 Error: unresolved flex record
(can't tell what fields there are besides #1)
test.txt:10.2-13.13 Error: unresolved flex record
(can't tell what fields there are besides #2)
uncaught exception Error
raised at: ../compiler/Toplevel/interact/evalloop.sml:66.19-66.27
....
I am a kind beginner of ML programming. Could anyone teach me what is wrong?
You have quite a few things going on here. If we first look at the errors you are getting.
unbound variable or constructor: innerinner
In sml you can't "use" stuff before it has been declared. It is easily fixed in your case by
swapping the function declarations around, and thus declaring innerinner before inner.
If you ever end up in a case where you want to for example declare two mutually recursive
functions, then this is not an option. In this case you would have to use the keyword and.
unresolved flex record
This is a bit more complicated. It is a type error and has something to do with the fact
that tuples are represented as records internally (I would recommend you go read about
it). Thus when you don't supply enough information, the type system will complain.
I think this QA explains it quite good. In summary, you can't have unbounded tuples
and thus you need to make it clear to the type system how many elements it contains. This
could be done by explicitly type annotating the function declaration.
However in general you ought to use pattern matching instead, as often as feasible.
In general you should always use pattern matching rather than tuple selectors (#1, #2, ...), or list selectors (hd or tl). You just saw why tuple selectors can be "bad" but using list selectors without testing whether or not the list is empty first will give you runtime errors (exceptions).
Putting in such test cases in your code will "blow it up" and make it messy to read. But if you use pattern matching instead you will have some nice clear cut cases in your function definition.
Also often you will tend to writer less code (in my opinion).
Btw, you don't need to put parentheses around single arguments to functions, such as you main definition of the test function.
All in all your function could look something like this:
fun test list =
let
fun innerinner ((x1, x2)::xs,from) =
if x1 = from then true
else innerinner(xs,from)
| innerinner ([], from) = false
fun inner ((x1, x2)::xs) = innerinner(xs,x1)
| inner [] = false
in
inner(list)
end

Linux g++ Embedding Prolog Logic Engine Within C++

I have some logic in a C++ program that is not only insanely complex, it requires multiple solutions for which Prolog is ideal. It's sort of like a firewall config script, checking input for actions, but sometimes more that one action is required.
What I want is something like this:
class PrologEngine
{
LoadLogic(const char* filename) throw PrologException; // Load a file of prolog rules, predicates facts etc in textual format. Must be callable multiple times to load AND COMPILE (for speed) prolog rule files.
std::vector<std::string> Evaluate(const char* predicate_in_string_form = "execute(input, Result)") throw PrologException; Returns a vector of matching predicates in text form.
};
It needs no ability to call back into C++.
AMI Prolog seems to get it, but it's not available on Linux. I'm trying to use SWI-Prolog and can only find 2 examples and and incredibly byzantine API (my opinion)
Can anyone point me to an example that is close to what I'm looking for?
There is A C++ interface to SWI-Prolog, that's high level.
I'm fighting with it, here an example of bridging to OpenGL:
PREDICATE(glEvalCoord1d, 1) {
double u = A1;
glEvalCoord1d( u );
return TRUE;
}
This clean code hides many 'bizantinism', using implicit type conversion and some macro. The interface is well tought and bidirectional: to call Prolog from C++ there are PlCall ('run' a query, similar to Evaluate you expose in the answer) or a more structured PlQuery, for multiple results...
If you don't need to link to openGl, or can wait to ear about the answer that hopefully I'll get from SWI-Prolog mailing list, you should evaluate it.
If you don't mind rewriting the prolog code for use in a native c++ header only library, I'd look into the castor library:
http://www.mpprogramming.com/cpp/