I am trying to use the flow_parser library, but I get the following error after running dune exec ./start.exe:
File "_none_", line 1:
Error: No implementations provided for the following modules:
Ppx_deriving_runtime referenced from /Users/macintosh/.opam/4.07.1/lib/flow_parser/parser_flow.cmxa(File_key)
Here's my dune file:
(executables
(names start)
(libraries core flow_parser)
(preprocess (pps ppx_jane ppx_deriving.show ppx_deriving.ord)))
Here's the start.ml:
let () =
let source = File_key.SourceFile("./fixtures/fib.js") in
let channel = open_in "./fixtures/fib.js" in
let lexbuf = Sedlexing.Utf8.from_channel channel in
let lex_env = Lex_env.new_lex_env (Some source) lexbuf ~enable_types_in_comments: false in
let (_, lex_result) = Lexer.token lex_env in
print_endline(Lex_result.debug_string_of_lex_result(lex_result));
Note that I could not use open Flow_parser - I get an unbounded module error. However, my editor (VSCode with the OCaml/ReasonML plugin) allows me to access the modules inside Flow_parser (e.g. File_key).
Related
I hope all is well. At this point, I plan on reading a file, and then writing it to another file. (The equivalent of cp in OCaml, before I go ahead and manipulate text.) Currently in my code, I am making using the extlib to read a file, and then output it. I am also using dune to build file as an executable file. My file looks something like the following:
(* example.ml file *)
let read_filename = "example_1.ts"
let filename = "example_2.ts"
let () =
let text read_filename =
let chan = open_in read_filename in
Std.input_list chan
let filename = filename in
let text = text in
Std.output_file ~filename ~text
(* normal exit: all channels are flushed and closed *)
When I build the file using dune build example.bc I receive the following error:
File "example.ml", line 11, characters 2-5:
Error: Syntax error
I am trying to figure out what I am doing wrong, but to no avail. Any help would be more than appreciated. Thank you.
When I have readed you code I remark these lines.
let filename = filename in
let text = text in
Why have you writting this line ? (* You could delete it safely *)
And then I have found your syntax error was a line above you have forgotten a in
(* example.ml file *)
let read_filename = "example_1.ts"
let filename = "example_2.ts"
let () =
let text read_filename =
let chan = open_in read_filename in
Std.input_list chan
in
Std.output_file ~filename ~text
(* normal exit: all channels are flushed and closed *)
The rule for each local definition you must have a in keyword
(* a local definition is a let inside a let expression *)
Here I have a file set.ml with a module called IntSet. How do I refer to the module IntSet inside the corresponding interface file set.mli?
module IntSet = struct
type t = int list;;
let empty = [];;
let rec is_member key = function
| [] -> false
| (x::xs) -> (
if x = key then true
else is_member key xs
);;
end;;
let join xs ys = xs # ys;;
Here is set.mli
val join : IntSet.t -> IntSet.t -> IntSet.t
If I try to compile it, I get an error claiming that the module IntSet is unbound.
% corebuild set.native
+ ocamlfind ocamlc -c -w A-4-33-40-41-42-43-34-44 -strict-sequence -g -bin-annot -short-paths -thread -package core -ppx 'ppx-jane -as-ppx' -o set.cmi set.mli
File "set.mli", line 1, characters 11-19:
Error: Unbound module IntSet
Command exited with code 2.
Hint: Recursive traversal of subdirectories was not enabled for this build,
as the working directory does not look like an ocamlbuild project (no
'_tags' or 'myocamlbuild.ml' file). If you have modules in subdirectories,
you should add the option "-r" or create an empty '_tags' file.
To enable recursive traversal for some subdirectories only, you can use the
following '_tags' file:
true: -traverse
<dir1> or <dir2>: traverse
Compilation unsuccessful after building 3 targets (1 cached) in 00:00:00.
How do I expose a module defined in set.ml so I can use it in definitions?
I changed set.mli to this, and the compiler seems happy:
module IntSet : sig type t end
val join : IntSet.t -> IntSet.t -> IntSet.t
There is probably more work to make things usable. There's no way to make a value of type IntSet.t, for example.
In ocaml toplevel, I can use "bitstring" package by typing the following commands:
#use "topfind";;
#camlp4o;;
#require "bitstring.syntax";;
let data = 0l;;
let bits = BITSTRING { data : 32 };;
However, if I create an OCaml script, e.g., foo.ml :
#!/usr/bin/env ocaml
#use "topfind";;
#camlp4o;;
#require "bitstring.syntax";;
let data = 0l;;
let bits = BITSTRING { data : 32 };;
And, if I run the OCaml script, I got a syntax error:
$ ./foo.ml
File "./foo.ml", line 8, characters 28-29: Error: Syntax error
What am I missing here? Why does the same code work with an interactive shell, but not with a script file?
I believe that's because script file is first parsed, and then the directives are executed, hence it cannot handle unknown (yet) syntax.
The easiest solution is to use ocamlscript :
#! /usr/bin/env ocamlscript
Ocaml.packs := [ "bitstring"; "bitstring.syntax" ]
--
let data = 0l;;
let bits = BITSTRING { data : 32 };;
I want to create a haskell interpreter that I can use from C++ on linux.
I have a file FFIInterpreter.hs which implements the interpreter in haskell and exports the functions via FFI to C++.
module FFIInterpreter where
import Language.Haskell.Interpreter
import Data.IORef
import Foreign.StablePtr
import Foreign.C.Types
import Foreign.C.String
import Control.Monad
import Foreign.Marshal.Alloc
type Session = Interpreter ()
type Context = StablePtr (IORef Session)
foreign export ccall createContext :: CString -> IO Context
createContext :: CString -> IO Context
createContext name = join ((liftM doCreateContext) (peekCString name))
where
doCreateContext :: ModuleName -> IO Context
doCreateContext name
= do let session = newModule name
_ <- runInterpreter session
liftIO $ newStablePtr =<< newIORef session
newModule :: ModuleName -> Session
newModule name = loadModules [name] >> setTopLevelModules [name]
foreign export ccall freeContext :: Context -> IO ()
freeContext :: Context -> IO ()
freeContext = freeStablePtr
foreign export ccall runExpr :: Context -> CString -> IO CString
runExpr :: Context -> CString -> IO CString
runExpr env input = join ((liftM newCString) (join (((liftM liftM) doRunExpr) env (peekCString input))))
where
doRunExpr :: Context -> String -> IO String
doRunExpr env input
= do env_value <- deRefStablePtr env
tcs_value <- readIORef env_value
result <- runInterpreter (tcs_value >> eval input)
return $ either show id result
foreign export ccall freeString :: CString -> IO ()
freeString :: CString -> IO ()
freeString = Foreign.Marshal.Alloc.free
When I compile the whole project with ghc, everything works fine. I use the following command:
ghc -no-hs-main FFIInterpreter.hs main.cpp -lstdc++
But the haskell module is only a small piece of the C++ project and I don't want the whole project to depend on ghc.
So I want to build a dynamic library with ghc and then link it to the project using g++.
$ ghc -shared -fPIC FFIInterpreter.hs module_init.c -lstdc++
[1 of 1] Compiling FFIInterpreter ( FFIInterpreter.hs, FFIInterpreter.o )
Linking a.out ...
/usr/bin/ld: /usr/lib/haskell-packages/ghc/lib/hint-0.3.3.2/ghc-7.0.3/libHShint-0.3.3.2.a(Interpreter.o): relocation R_X86_64_32S against `.data' can not be used when making a shared object; recompile with -fPIC
/usr/lib/haskell-packages/ghc/lib/hint-0.3.3.2/ghc-7.0.3/libHShint-0.3.3.2.a: could not read symbols: Bad value
collect2: ld gab 1 als Ende-Status zurück
So I added the -dynamic keyword, but that also doesn't work:
$ ghc -dynamic -shared -fPIC FFIInterpreter.hs librarymain.cpp -lstdc++
FFIInterpreter.hs:3:8:
Could not find module `Language.Haskell.Interpreter':
Perhaps you haven't installed the "dyn" libraries for package `hint-0.3.3.2'?
Use -v to see a list of the files searched for.
I searched my system for Interpreter.dyn_hi but didn't find it. Is there a way to get it?
I also tried to install hint manually, but this also doesn't deliver the Interpreter.dyn_hi file.
You have to install the library (and all it depends on) with the --enable-shared flag (using cabal-install) to get the .dyn_hi and .dyn_o files. You may consider setting that option in your ~/.cabal/config file.
Perhaps the easiest way is to uncomment the shared: XXX line in ~/.cabal/config, set the option to True and
cabal install --reinstall world
For safety, run that with the --dry-run option first to detect problems early. If the --dry-run output looks reasonable, go ahead and reinstall - it will take a while, though.
How can I emulate this Python idiom in OCaml?
if __name__=="__main__":
main()
See RosettaCode for examples in other programming languages.
There is no notion of main module in Ocaml. All the modules in a program are equal. So you can't directly translate this Python idiom.
The usual way in Ocaml is to have a separate file containing the call to main, as well as other stuff like command line parsing that only make sense in a standalone executable. Don't include that source file when linking your code as a library.
There is a way to get at the name of the module, but it's rather hackish, as it is intended for debugging only. It violates the usual assumption that you can rename a module without changing its behavior. If you rely on it, other programmers reading your code will curse you. This method is provided for entertainment purposes only and should not be used in real life.
let name_of_this_compilation_unit =
try assert false with Assert_failure (filename, _, _) -> filename
You can compare the name of the compilation unit with Sys.executable_name or Sys.argv.(0). Note that this is not really the same thing as the Python idiom, which does not rely on the toplevel script having a particular name.
$ ocamlc -o scriptedmain -linkall str.cma scriptedmain.ml
$ ./scriptedmain
Main: The meaning of life is 42
$ ocamlc -o test -linkall str.cma scriptedmain.ml test.ml
$ ./test
Test: The meaning of life is 42
scriptedmain.ml:
let meaning_of_life : int = 42
let main () = print_endline ("Main: The meaning of life is " ^ string_of_int meaning_of_life)
let _ =
let program = Sys.argv.(0)
and re = Str.regexp "scriptedmain" in
try let _ = Str.search_forward re program 0 in
main ()
with Not_found -> ()
test.ml:
let main () = print_endline ("Test: The meaning of life is " ^ string_of_int Scriptedmain.meaning_of_life)
let _ =
let program = Sys.argv.(0)
and re = Str.regexp "test" in
try let _ = Str.search_forward re program 0 in
main ()
with Not_found -> ()
Posted on RosettaCode.