barry(1)

πŸ“¦ version 4.7.23, in nixpkgs unstable

πŸ’… barry(1) β€” MLKit, a compiler for Standard ML 🧚

okay so bestie, welcome to barry β€” the fullblown Standard ML compiler from MLKit. yes, "fullblown" is the actual technical term here and honestly it ate. let's get into it ✨


🌸 NAME 🌸

barry β€” A fullblown Standard ML compiler. that's it. that's the whole vibe. no cap.


πŸ¦‹ SYNOPSIS πŸ¦‹

barry [OPTION]... [file.sml | file.sig | file.mlb]

All possible options are listed below. like, all of them, we're not hiding anything from you πŸ’–


πŸŽ€ DEFAULTS πŸŽ€

here's the starter pack β€” every single default the compiler ships with, exactly as it ships it, so you know what you're walking into πŸ‘‘

  • --SML_LIB You_did_not_set_path_to_install_dir β€” yeah, that's literally the default value, and yes it is a whole callout 😭 set this fr fr
  • -aopt on
  • -verbose off
  • -c off
  • -timings off
  • -cfold on
  • --contract on
  • -cross_opt off
  • -debug off
  • --debug_linking off
  • --debug_man_enrich off
  • -dufa on
  • --eliminate_explicit_records on
  • --fix_floating on
  • -basislib on
  • --inline_functors off
  • -ltdce on
  • --log_to_file off
  • -max_inl_sz 200
  • -max_spec_sz 200
  • --messages on
  • --minimize_fixs on
  • --namebase dummyBase
  • -opt on
  • -o run
  • -j 1
  • --pretty_depth 5
  • --pretty_string_size 80
  • -Pceb off
  • --print_excon_name off
  • -Peb off
  • --print_lvar_name off
  • -Pole off
  • -Ppeast off
  • -Ptypestamps off
  • -Ptypes off
  • -quot off
  • --raggedRight on
  • -scratch off
  • -sig off
  • --safeLinkTimeElimination off
  • --specialize_recursive_functions on
  • -stats_opt off
  • --type_check_lambda on
  • --unbox_funargs off
  • -uncurry off
  • -w 100
lowkey obsessed with how --SML_LIB's default value is just the compiler gently yelling at you. iconic behaviour honestly πŸ’€

🌈 DESCRIPTION 🌈

so when you invoke barry, it compiles the sources you handed it into an executable file called run, and it does that by running through a whole series of translation phases β€” like a makeover montage but for your code πŸ’…βœ¨

the various options let you control:

  • the printing of intermediate forms πŸ‘€
  • which optimizations get performed ⚑

and here's a cute detail: if your source files are organised in ML Basis Files (that's files with the extension .mlb), the compiler will memoize symbol table information and object code in the dedicated MLB directories located relative to the source files. so it remembers stuff for you. main character energy fr fr πŸŽ€

if you invoke barry without any source files at all, it starts an interactive REPL instead. type :help; inside the REPL to learn more about how to use it β€” go on, it's right there 🫢

and if you wanna learn more about programming with MLKit, the MLKit web page is literally sitting there waiting for you at

http://melsman.github.io/mlkit

⭐ STANDARDS ⭐

the MLKit implements Standard ML (Revised 1997) and has almost full support for the Standard ML Basis Library (version of 2002). almost full, bestie β€” not fully full, so don't come for me πŸ™ˆ

see the MLKit home page for a detailed overview of the support for the Standard ML Basis Library. it's all documented, i promise πŸ’œ


πŸ“ EXAMPLES πŸ“

for examples, consult the MLKit manual "Programming with Regions in the MLKit", which is available from the MLKit home page. yes, the regions one. go read it, it's giving essential reading πŸ“šβœ¨


πŸ’… OPTIONS πŸŽ€

okay bestie, this is the part where barry really shows off. there are so many flags. grab a snack. every single one is here, no cap. πŸ“

  • --SML_LIB S β€” points at the installation directory for the MLKit standard library. for normal everyday vibes you do not touch this. but like, if you're feeling adventurous and wanna use the MLKit with an altered runtime system, you can update this setting and the system will try to link to a runtime system found in the specified install directory. ✨
  • --aggressive_opt, -aopt β€” turns on aggressive optimisations, including aggressive inlining. πŸš€ heads up though: these optimisations are not guaranteed to be region safe. and turning off garbage collection automatically turns off this option. so like, it's giving bold. use responsibly.
  • --chat, -verbose β€” print a message for each compilation step in the compiler. it's the compiler narrating its life to you. πŸ—£οΈ
  • --compile_only, -c β€” compile only, bestie. suppresses generation of the executable. 😌
  • --compiler_timings, -timings β€” show compiler timings for each compilation phase. perfect for when you need to know exactly which phase is being slow. ⏱️
  • --constant_folding, -cfold β€” enable constant folding optimisations. little constants get folded. iconic. πŸŽ€
  • --contract β€” Contract is responsible for inlining, specialization, elimination of dead code, and much else (Lambda Expression Optimiser). it's the main character of the optimiser tbh. πŸ‘‘
  • --cross_module_opt, -cross_opt β€” enable cross-module optimisation, including inlining of small functions and specialisation of small recursive functions. which optimisations get performed across modules is controlled by individual optimisation flags. 🌈
  • --debug_compiler, -debug β€” print intermediate forms of a program during compilation. peek behind the curtain fr. πŸ¦‹
  • --debug_linking β€” debug linking of target code by showing which object files are linked together. so you can see exactly who's linking with who. messy but useful. πŸ’€
  • --debug_man_enrich β€” show information about why a program unit need be recompiled. a program unit (or a functor body) is recompiled if either (a) the program unit is modified, or (b) information about an identifier for which the program unit depends upon has changed. like a little detective for your rebuilds. πŸ”
  • --drop_unused_funargs, -dufa β€” drop function arguments that are unused. bye bestie, you weren't doing anything anyway. πŸ‘‹
  • --eliminate_explicit_records β€” eliminate bindings of explicit records only used for selections. it transforms:
let r = (e1,...,en) in ... #i r .. #j r ...

into:

let x1=e1 in ... let xn=en in ... xi .. xj ...

(Lambda Expression Optimiser). it's giving glow-up. ✨

  • --fix_floating β€” float fix-bindings into immediate let-bindings when possible, to help tail-calls not be captured in let-region bindings. 🎈
  • --help β€” print extended help information and exit. the classic. 🫢
  • --help S β€” print help information about an option and exit. just for one option, like a spotlight. πŸ”¦
  • --import_basislib, -basislib β€” import Basis Library automatically in your projects. if you wish to make use of the Standard ML Basis Library in your projects, this option should be turned on, unless you wish to import the Basis Library manually in your projects. honestly just leave it on unless you're built different. πŸ’…
  • --inline_functors β€” inline functors during static interpretation instead of generating separate target code blocks for functor bodies and arguments. with the flag enabled, performance may increase with the cost of larger (re)compilation times. the flag may be controlled in mlb-files using mlb-annotations. trade-off queen. βš–οΈ
  • --inline_names S β€” names of functions that should always be inlined if possible, no matter the setting of the flag --maximum_inline_size. they're VIPs, they get in. 🎟️
  • --link_code S β€” link-files to be linked together to form an executable. πŸ”—
  • --link_time_dead_code_elimination, -ltdce β€” link time dead code elimination. dead code gets got at link time. πŸ’€
  • --load_basis_files S, -load S β€” basis files to be loaded before compilation proper. πŸ“š
  • --log_to_file β€” log to files instead of stdout. keeping the receipts in a file. πŸ“
  • --man β€” print man-page and exit. hi, you're reading the result of this rn. 😭
  • --maximum_inline_size N, -max_inl_sz N β€” functions smaller than this size (counted in abstract syntax tree nodes) are inlined, even if they are used more than once. functions that are used only once are always inlined. a function declared in one program unit may be inlined when applied in another program unit, provided the function is sufficiently closed (refers only to exported identifiers) and provided the option --cross_opt is enabled. πŸ“
  • --maximum_specialise_size N, -max_spec_sz N β€” function-parameterised functions smaller than this size (counted in abstract syntax tree nodes) are specialised if all applications of the function within its own body are applied to its formal function argument, even if they are used more than once. functions that are used only once are specialised no matter their size. a function declared in one program unit may be specialised when applied in another program unit, provided the function is sufficiently closed (refers only to exported identifiers) and provided the option --cross_opt is enabled. see also the option --specialize_recursive_functions. 🌟
  • --messages β€” print messages about reading source files and generating target files. πŸ—¨οΈ
  • --minimize_fixs β€” minimize fix constructs (Lambda Expression Optimiser). πŸͺ„
  • --mlb_path_maps S, -mlb-path-map S β€” ML Basis path map files to be used. πŸ—ΊοΈ
  • --namebase S β€” name base to enforce unique names when compiling mlb-files. everyone gets a unique name, no duplicates allowed. 🏷️
  • --no_aggressive_opt, -no_aopt β€” opposite of --aggressive_opt, -aopt. πŸ™…
  • --no_constant_folding, -no_cfold β€” opposite of --constant_folding, -cfold. πŸ™…
  • --no_contract β€” opposite of --contract. πŸ™…
  • --no_cross_module_opt, -no_cross_opt β€” opposite of --cross_module_opt, -cross_opt. πŸ™…
  • --no_drop_unused_funargs, -no_dufa β€” opposite of --drop_unused_funargs, -dufa. πŸ™…
  • --no_eliminate_explicit_records β€” opposite of --eliminate_explicit_records. πŸ™…
  • --no_fix_floating β€” opposite of --fix_floating. πŸ™…
  • --no_import_basislib, -no_basislib β€” opposite of --import_basislib, -basislib. πŸ™…
  • --no_link_time_dead_code_elimination, -no_ltdce β€” opposite of --link_time_dead_code_elimination, -ltdce. πŸ™…
  • --no_messages β€” opposite of --messages. πŸ™…
  • --no_minimize_fixs β€” opposite of --minimize_fixs. πŸ™…
  • --no_optimiser, -no_opt β€” opposite of --optimiser, -opt. πŸ™…
  • --no_raggedRight β€” opposite of --raggedRight. πŸ™…
  • --no_specialize_recursive_functions β€” opposite of --specialize_recursive_functions. πŸ™…
  • --no_type_check_lambda β€” opposite of --type_check_lambda. πŸ™…
  • --no_unbox_funargs β€” opposite of --unbox_funargs. πŸ™…
  • --no_uncurrying, -no_uncurry β€” opposite of --uncurrying, -uncurry. πŸ™…
  • --optimiser, -opt β€” enable optimisation of intermediate language code (Lambda Expressions). which optimisations are performed is controlled by individual flags. the optimisations include function inlining, function specialisation, fix-minimization, unboxing of function arguments, and elimination of unnecessary record constructions. the whole package, honestly. 🎁
  • --output S, -o S β€” the name of the executable file generated by the Kit. name your child. πŸ‘Ά
  • --parallel_compilation N, -j N β€” the maximum number of parallel processes used for compilation. multitasking icon. ⚑
  • --pretty_depth N β€” this flag controls the pretty-printing depth of values printed in the REPL. the value must be an integer larger than zero. ✨
  • --pretty_string_size N β€” this flag controls the pretty-printing size of strings printed in the REPL. the value must be an integer larger than zero. ✨
  • --print_closed_export_bases, -Pceb β€” controls printing of closed export bases. πŸ–¨οΈ
  • --print_excon_name β€” print underlying unique name when printing excons. πŸ–¨οΈ
  • --print_export_bases, -Peb β€” controls printing of export bases. πŸ–¨οΈ
  • --print_lvar_name β€” print underlying unique name when printing lvars. πŸ–¨οΈ
  • --print_opt_lambda_expression, -Pole β€” print Lambda Expression after optimisation. πŸ–¨οΈ
  • --print_post_elab_ast, -Ppeast β€” print ast after elaboration. πŸ–¨οΈ
  • --print_type_name_stamps, -Ptypestamps β€” print type name stamps and their attributes in types and expressions. πŸ–¨οΈ
  • --print_types, -Ptypes β€” print types when printing intermediate forms. for Lambda Expressions, ordinary ML types are printed, whereas for Region Expressions, region types are printed. πŸ–¨οΈ
  • --quotation, -quot β€” enable support for quotations and anti-quotations. when enabled, the datatype
datatype 'a frag = QUOTE of string
                 | ANTIQUOTE 'a

is available in the initial environment. moreover, values of this datatype may be constructed using the quotation/antiquotation syntax:

val s = "world"
val a : string frag list = `hello ^s - goodbye`

literally so cute. πŸŽ€

  • --raggedRight β€” use ragged right margin in pretty-printing of expressions and types. πŸ“
  • --recompile_basislib, -scratch β€” recompile basis library from scratch. this option is useful together with other options that control code generation. clean slate energy. 🧼
  • --report_file_sig, -sig β€” report signatures for each file read. πŸ“„
  • --safeLinkTimeElimination β€” treat this module as a library in the sense that the code can be eliminated if it is not used, even if the code has side effects. ⚠️ yeah, even with side effects. read that again.
  • --specialize_recursive_functions β€” specialise recursive functions. use the option maximum_specialise_size to control which functions are specialised. if this flag is on, functions that are applied only once are specialised, no matter the setting of --maximum_inline_size... wait, no bestie, it's --maximum_specialise_size β€” (Lambda Expression Optimiser). πŸ”
ok tiny correction for clarity: the original says functions applied only once are specialised no matter the setting of --maximum_specialise_size. (Lambda Expression Optimiser).
  • --statistics_after_optimisation, -stats_opt β€” report optimisation statistics after optimisation of Lambda Expression. numbers go brrr. πŸ“Š
  • --type_check_lambda β€” type check lambda expression prior to performing region inference. type checking is very fast and for normal use you should not disable this option. type checking intermediate forms is very powerful for eliminating bugs in the compiler. πŸ›πŸ”¨
  • --unbox_funargs β€” unbox arguments to fix-bound functions, for which the argument 'a' is used only in contexts '#i a'. all call sites are transformed to match the new function (Lambda Expression Optimiser). πŸ“¦
  • --uncurrying, -uncurry β€” enable uncurrying of curried functions. the uncurried function takes its arguments unboxed in registers or on the stack. for partial applications and non-application uses of the function, appropriate eta-expansions are applied. πŸŒ€
  • --version, -v, -V β€” print version information and exit. 🏷️
  • --width N, -w N β€” column width used when pretty printing intermediate code. πŸ“

🚦 EXIT STATUS 🚦

exits with status 0 on success and -1 on failure. that's it, that's the whole vibe check. βœ…βŒ


🌱 ENVIRONMENT 🌱

a library install directory must be provided in an environment variable SML_LIB, as a path-definition in the user's personal path-map ~/.barry/mlb-path-map, or in a system wide path-map /nix/store/sfp5bfgah1f35wd1r96xrvhzx6nir1r6-mlkit-4.7.23/etc/barry/mlb-path-map. like, pick a lane, but pick one. 🫢

🌸 FILES 🌸

Okay bestie, so here's where barry actually looks for its config β€” pay attention, this part matters πŸ’…

  • /nix/store/sfp5bfgah1f35wd1r96xrvhzx6nir1r6-mlkit-4.7.23/etc/barry/mlb-path-map β€” the system-wide config of where libraries and runtime system locations live πŸ—ΊοΈ (yes, that is a very long Nix store path and no, you cannot shorten it, that's not me being dramatic, that's just Nix being Nix 😭)
  • ~/.barry/mlb-path-map β€” your own personal config of library and runtime system locations, because your setup can absolutely differ from the system one and that's valid 🫢
Ngl, if barry is looking in the wrong place for something, these two files are the first thing you check. The user one is yours to vibe with, the system one is the system's.

πŸ‘‘ CREDITS πŸ‘‘

Give it up for the icons who actually built this thing, fr fr πŸ’–

The MLKit (version 2 and beyond) was developed by Lars Birkedal</>, Martin Elsman</>, Niels Hallenberg</>, Tommy H. Olesen</>, Mads Tofte</>, and Carsten Varming</>. Absolute legends, no cap 🫑

The following people also contributed with bug-fixes and improvements β€” and honestly, bug-fixers are the main characters we don't talk about enough: Peter Bertelsen</>, Vesa Karvonen</>, Ken Friis Larsen</>, Henning Niss</>, Peter Sestoft</>, and Troels Henriksen</>. Slay πŸ’…

And for MLKit version 1 specifically, Nick Rothwell</> and David N. Turner</> took part in the development. OGs, genuinely 🌈


πŸ”₯ SEE ALSO πŸ”₯

If you want the deep lore on regions, go read the MLKit manual called β€œProgramming with Regions in the MLKit” β€” it's available straight from the MLKit home page:

http://melsman.github.io/mlkit

That manual is where you get an in-depth introduction to programming with regions in the MLKit, iykyk ✨

And the home page is also lowkey a whole vibe β€” it gives you an overview of which parts of the Standard ML Basis Library the MLKit implements, plus download and installation instructions. So like, everything you need in one place πŸ¦‹

If you're sitting there wondering "does MLKit even implement this piece of the Basis Library?", bestie, the home page literally answers that. Go look πŸ‘€

πŸ’– And that's the whole page, bestie! You made it to the end β€” proud of you πŸ₯Ή This was barry(1) from version v4.7.23. Go forth, compile things, and remember: check your paths. Always check your paths πŸ’…βœ¨πŸŽ€

πŸ“¦ where this page comes from