816 search results for ""
-
The Compiler Frontend: Parsing and Type Checking
Syntax Errors
The syntax error points to the line and character number of the first token that couldn't be parsed. In the broken example, the module keyword isn't a valid token at that point in parsing, so t
Runtime & Compiler -
The Compiler Frontend: Parsing and Type Checking
Generating Documentation from Interfaces
You can also use odoc to generate complete snapshots of your project via integration with dune, as described in "Generating Documentation" . You should now have HTML files inside the html/ d
Runtime & Compiler -
The Compiler Frontend: Parsing and Type Checking
Preprocessing with ppx
There are two primary forms of extension points in OCaml: attributes and extension nodes . Let's first run through some examples of what they look like, and then see how to use them in your ow
Runtime & Compiler -
The Compiler Frontend: Parsing and Type Checking
Extension Attributes
Finally, an attribute can also be attached to an individual expression. In the next example, the @warn_on_literal_pattern attribute indicates that the argument to the type constructor should
Runtime & Compiler -
The Compiler Frontend: Parsing and Type Checking
Commonly Used Extension Attributes
This allows you to take advantage of a community of syntax augmentation. There are also a number of builtin attributes in the core OCaml compiler. Some are performance oriented and give directiv
Runtime & Compiler -
The Compiler Frontend: Parsing and Type Checking
Extension Nodes
We've already seen extension nodes in use via the Core syntax extensions earlier in the book, where they act as syntactic sugar for error handling ( let%bind ), for command-line parsing ( let%map
Runtime & Compiler -
The Compiler Frontend: Parsing and Type Checking
Static Type Checking
Subtyping in OCaml objects is always an explicit operation (via the :> operator). This means that it doesn't complicate the core type inference engine and can be tested as a separate concern. T
Runtime & Compiler -
The Compiler Frontend: Parsing and Type Checking
Displaying Inferred Types from the Compiler
<div class="note"> \noindent then, when you try to build, you'll get this error: \noindent and this as your mli : The compiler makes sure that your ml and mli files have compatible
Runtime & Compiler -
The Compiler Frontend: Parsing and Type Checking
Which Comes First: The ml or the mli?
</div> Signature files provide a place to write succinct documentation and to abstract internal details that shouldn't be exported. Maintaining separate signature files also speeds up incrementa
Runtime & Compiler -
The Compiler Frontend: Parsing and Type Checking
Type Inference
OCaml does have some language extensions that strain the limits of principal type inference, but by and large, most programs you write will never require annotations (although they sometimes hel
Runtime & Compiler -
The Compiler Frontend: Parsing and Type Checking
Adding Type Annotations to Find Errors
This error points directly to the correct line number that contains the typo. Once you fix the problem, you can remove the manual annotations if you prefer more succinct code. You can also leave
Runtime & Compiler -
The Compiler Frontend: Parsing and Type Checking
Enforcing Principal Typing
If compiling in principal mode works, it is guaranteed that the program will pass type checking in non-principal mode, too. Bear in mind that the cmi files generated in principal mode differ fr
Runtime & Compiler -
The Compiler Frontend: Parsing and Type Checking
Modules and Separate Compilation
This section discusses how the compiler implements them in more detail. Modules are essential for larger projects that consist of many source files (also known as compilation units ). It's impra
Runtime & Compiler -
The Compiler Frontend: Parsing and Type Checking
The Mapping Between Files and Modules
These two files produce essentially the same result as the following code. and a corresponding signature file: Create a file called alice.ml with the following contents: Individual compi
Runtime & Compiler -
The Compiler Frontend: Parsing and Type Checking
Defining a Module Search Path
<div class="note"> By default, only the current directory and the OCaml standard library will be searched for cmi files. The Stdlib module from the standard library will also be opened by d
Runtime & Compiler -
The Compiler Frontend: Parsing and Type Checking
Inspecting Compilation Units with ocamlobjinfo
</div> This hash check is very conservative, but ensures that separate compilation remains type-safe all the way up to the final link phase. Your build system should ensure that you never see th
Runtime & Compiler -
The Compiler Frontend: Parsing and Type Checking
Wrapping Libraries with Module Aliases
If you want to disable this behavior of dune and deliberately include multiple toplevel modules, you can add (wrapped false) to your libraries stanza. However, this is discouraged in general du
Runtime & Compiler -
The Compiler Frontend: Parsing and Type Checking
Shorter Module Paths in Type Errors
You'll need to choose for yourself if you prefer short paths or the default behavior in your own projects, and pass the -short-paths flag to the compiler if you need The utop enhanced toplev
Runtime & Compiler -
The Compiler Frontend: Parsing and Type Checking
The Typed Syntax Tree
The cmt files are particularly useful for IDE tools to match up OCaml source code at a specific location to the inferred or external types. For example, the merlin and ocaml-lsp-server opam
Runtime & Compiler -
The Compiler Frontend: Parsing and Type Checking
Examining the Typed Syntax Tree Directly
You'll rarely need to look at this raw output from the compiler unless you're building IDE tools, or are hacking on extensions to the core compiler itself. However, it's useful to know that this
Runtime & Compiler -
The Compiler Backend: Bytecode and Native code
The Compiler Backend: Bytecode and Native code
The Untyped Lambda Form
The lambda form is the key stage that discards the OCaml type information and maps the source code to the runtime memory model described in Memory Representation Of Values . This stage also pe
Runtime & CompilerThe Compiler Backend: Bytecode and Native code
Pattern Matching Optimization
The paper describes the backtracking algorithm used in classical pattern matching compilation, and also several OCaml-specific optimizations, such as the use of exhaustiveness information and con
Runtime & CompilerThe Compiler Backend: Bytecode and Native code
Benchmarking Pattern Matching
The lambda form is primarily a stepping stone to the bytecode executable format that we'll cover next. It's often easier to look at the textual output from this stage than to wade through the nat
Runtime & CompilerThe Compiler Backend: Bytecode and Native code
Generating Portable Bytecode
<div class="note"> There are around 140 instructions in total, but most are just minor variants of commonly encountered operations (e.g., function application at a specific arity). You can find
Runtime & CompilerThe Compiler Backend: Bytecode and Native code
Where Did the Bytecode Instruction Set Come From?
</div> Understanding the reasoning behind the different implementations of the bytecode interpreter and the native compiler is a very useful exercise for any budding language hacker. This paper
Runtime & CompilerThe Compiler Backend: Bytecode and Native code
Compiling and Linking Bytecode
The bytecode files are then linked together with the OCaml standard library to produce an executable program. The order in which .cmo arguments are presented on the command line defines the ord
Runtime & CompilerThe Compiler Backend: Bytecode and Native code
Executing Bytecode
Dune can build a self-contained bytecode executable if you specify the byte_complete mode in the executable rule. For example, this dune file will generate a prog.bc.exe target: The custom
Runtime & CompilerThe Compiler Backend: Bytecode and Native code
Embedding OCaml Bytecode in C
Embedding OCaml code like this lets you write OCaml that interfaces with any environment that works with a C compiler. You can even cross back from the C code into OCaml by using the Callback m
Runtime & CompilerThe Compiler Backend: Bytecode and Native code
Compiling Fast Native Code
Collections of .cmx and .o files can also be linked into a .cmxa archive by passing the -a flag to the compiler. However, unlike the bytecode version, you must keep the individual cmx fi
Runtime & CompilerThe Compiler Backend: Bytecode and Native code
Inspecting Assembly Output
The assembly code is highly architecture-specific, so the following discussion assumes an Intel or AMD 64-bit platform. We've generated the example code using -inline 20 and -nodynlink since
Runtime & CompilerThe Compiler Backend: Bytecode and Native code
The Impact of Polymorphic Comparison
OCaml on x86_64 architectures caches the location of the minor heap in the %r15 register since it's so frequently referenced in OCaml functions. The minor heap pointer can also be changed by the
Runtime & CompilerThe Compiler Backend: Bytecode and Native code
Benchmarking Polymorphic Comparison
<div class="note"> We see that the polymorphic comparison is close to 10 times slower! These results shouldn't be taken too seriously, as this is a very narrow test that, like all such microben
Runtime & CompilerThe Compiler Backend: Bytecode and Native code
Accessing Stdlib Modules from Within Core
</div> In the benchmark above comparing polymorphic and monomorphic comparison, you may have noticed that we prepended the comparison functions with Stdlib . This is because the Core module ex
Runtime & CompilerThe Compiler Backend: Bytecode and Native code
Debugging Native Code Binaries
Extra debugging information is inserted into the output assembly when the library is compiled in debug mode. These include the CFI stubs you will have noticed in the profiling output earlier ( .c
Runtime & CompilerThe Compiler Backend: Bytecode and Native code
Understanding Name Mangling
Anonymous functions are hard to predict without inspecting intermediate compiler output. If you need to debug them, it's usually easier to modify the source code to let-bind the anonymous functio
Runtime & CompilerThe Compiler Backend: Bytecode and Native code
Interactive Breakpoints with the GNU Debugger
One very useful feature of OCaml native code is that C and OCaml share the same stack. This means that GDB backtraces can give you a combined view of what's going on in your program and runtime
Runtime & CompilerThe Compiler Backend: Bytecode and Native code
Profiling Native Code
Note that many other tools that operate on native binaries, such as Valgrind, will work just fine with OCaml as long as the program is linked with the -g flag to embed debugging symbols. GNU g
Runtime & CompilerThe Compiler Backend: Bytecode and Native code
Gprof
Getting precise information out of gprof requires passing the -p flag to the native code compiler when compiling and linking the binary. This generates extra code that records profile infor
Runtime & CompilerThe Compiler Backend: Bytecode and Native code
Perf
<div class="note"> Perf has a growing collection of other commands that let you archive these runs and compare them against each other. You can read more on the home page . This trace broadly
Runtime & CompilerThe Compiler Backend: Bytecode and Native code
Using the Frame Pointer to Get More Accurate Traces
</div> Using the frame pointer changes the OCaml calling convention, but opam takes care of recompiling all your libraries with the new interface. OCaml thus makes the frame pointer an option
Runtime & CompilerThe Compiler Backend: Bytecode and Native code
Embedding Native Code in C
<div class="note"> The embed_native.o is a standalone object file that has no further references to OCaml code beyond the runtime library, just as with the bytecode runtime. Do remember that
Runtime & CompilerThe Compiler Backend: Bytecode and Native code
Activating the Debug Runtime
</div> To use the debug library, just link your program with the -runtime-variant d flag: Despite your best efforts, it is easy to introduce a bug into some components, such as C bindings, t
Runtime & CompilerThe Compiler Backend: Bytecode and Native code
Summarizing the File Extensions
.o are compiled native object files of the module implementation. .cmx contains extra information for linking and cross-module optimization of the object file. .cmxa and .a are libraries of c
Runtime & CompilerFormatting and Wrapping Text
Formatting and Wrapping Text
Principles
boxes : a box is a logical pretty-printing unit, which defines a behaviour of the pretty-printing engine to display the material inside the box. break hints : a break hint is a directive to the p
TutorialsFormatting and Wrapping Text
Boxes
within a “h” box: within a “v” box: within a “hv” box: If there is enough room to print the box on the line: But "---b---b---" that cannot fit on the line is written within a
TutorialsFormatting and Wrapping Text
Printing Spaces
Generally speaking, a printing routine using "format", should not directly output white spaces: the routine should use break hints instead. (For instance print_space () that is a convenient a
TutorialsFormatting and Wrapping Text
Indentation of New Lines
when defining the box : when you open a box, you can fix the indentation added to each new line opened within that box. For instance: open_hovbox 1 opens a “hov” box with new lines indent
TutorialsFormatting and Wrapping Text
Refinement on “hov” Boxes
Tutorials