<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=edge"><![endif]--> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="generator" content="Asciidoctor 1.5.4"> <meta name="author" content="Hongbo Zhang"> <title>BuckleScript User Manual</title> <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700"> <style> /* Asciidoctor default stylesheet | MIT License | http://asciidoctor.org */ /* Remove comment around @import statement below when using as a custom stylesheet */ /*@import "https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700";*/ article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block} audio,canvas,video{display:inline-block} audio:not([controls]){display:none;height:0} [hidden],template{display:none} script{display:none!important} html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%} body{margin:0} a{background:transparent} a:focus{outline:thin dotted} a:active,a:hover{outline:0} h1{font-size:2em;margin:.67em 0} abbr[title]{border-bottom:1px dotted} b,strong{font-weight:bold} dfn{font-style:italic} hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0} mark{background:#ff0;color:#000} code,kbd,pre,samp{font-family:monospace;font-size:1em} pre{white-space:pre-wrap} q{quotes:"\201C" "\201D" "\2018" "\2019"} small{font-size:80%} sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline} sup{top:-.5em} sub{bottom:-.25em} img{border:0} svg:not(:root){overflow:hidden} figure{margin:0} fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em} legend{border:0;padding:0} button,input,select,textarea{font-family:inherit;font-size:100%;margin:0} button,input{line-height:normal} button,select{text-transform:none} button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer} button[disabled],html input[disabled]{cursor:default} input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0} input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box} input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none} button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0} textarea{overflow:auto;vertical-align:top} table{border-collapse:collapse;border-spacing:0} *,*:before,*:after{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box} html,body{font-size:100%} body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:"Noto Serif","DejaVu Serif",serif;font-weight:400;font-style:normal;line-height:1;position:relative;cursor:auto} a:hover{cursor:pointer} img,object,embed{max-width:100%;height:auto} object,embed{height:100%} img{-ms-interpolation-mode:bicubic} .left{float:left!important} .right{float:right!important} .text-left{text-align:left!important} .text-right{text-align:right!important} .text-center{text-align:center!important} .text-justify{text-align:justify!important} .hide{display:none} body{-webkit-font-smoothing:antialiased} img,object,svg{display:inline-block;vertical-align:middle} textarea{height:auto;min-height:50px} select{width:100%} .center{margin-left:auto;margin-right:auto} .spread{width:100%} p.lead,.paragraph.lead>p,#preamble>.sectionbody>.paragraph:first-of-type p{font-size:1.21875em;line-height:1.6} .subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em} div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0;direction:ltr} a{color:#2156a5;text-decoration:underline;line-height:inherit} a:hover,a:focus{color:#1d4b8f} a img{border:none} p{font-family:inherit;font-weight:400;font-size:1em;line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility} p aside{font-size:.875em;line-height:1.35;font-style:italic} h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:"Open Sans","DejaVu Sans",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em} h1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0} h1{font-size:2.125em} h2{font-size:1.6875em} h3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em} h4,h5{font-size:1.125em} h6{font-size:1em} hr{border:solid #ddddd8;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em;height:0} em,i{font-style:italic;line-height:inherit} strong,b{font-weight:bold;line-height:inherit} small{font-size:60%;line-height:inherit} code{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;color:rgba(0,0,0,.9)} ul,ol,dl{font-size:1em;line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit} ul,ol,ul.no-bullet,ol.no-bullet{margin-left:1.5em} ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0;font-size:1em} ul.square li ul,ul.circle li ul,ul.disc li ul{list-style:inherit} ul.square{list-style-type:square} ul.circle{list-style-type:circle} ul.disc{list-style-type:disc} ul.no-bullet{list-style:none} ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0} dl dt{margin-bottom:.3125em;font-weight:bold} dl dd{margin-bottom:1.25em} abbr,acronym{text-transform:uppercase;font-size:90%;color:rgba(0,0,0,.8);border-bottom:1px dotted #ddd;cursor:help} abbr{text-transform:none} blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd} blockquote cite{display:block;font-size:.9375em;color:rgba(0,0,0,.6)} blockquote cite:before{content:"\2014 \0020"} blockquote cite a,blockquote cite a:visited{color:rgba(0,0,0,.6)} blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)} @media only screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2} h1{font-size:2.75em} h2{font-size:2.3125em} h3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em} h4{font-size:1.4375em}} table{background:#fff;margin-bottom:1.25em;border:solid 1px #dedede} table thead,table tfoot{background:#f7f8f7;font-weight:bold} table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left} table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)} table tr.even,table tr.alt,table tr:nth-of-type(even){background:#f8f8f7} table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{display:table-cell;line-height:1.6} body{tab-size:4} h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em} h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400} .clearfix:before,.clearfix:after,.float-group:before,.float-group:after{content:" ";display:table} .clearfix:after,.float-group:after{clear:both} *:not(pre)>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background-color:#f7f7f8;-webkit-border-radius:4px;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed} pre,pre>code{line-height:1.45;color:rgba(0,0,0,.9);font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;text-rendering:optimizeSpeed} .keyseq{color:rgba(51,51,51,.8)} kbd{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background-color:#f7f7f7;border:1px solid #ccc;-webkit-border-radius:3px;border-radius:3px;-webkit-box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em white inset;box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em #fff inset;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap} .keyseq kbd:first-child{margin-left:0} .keyseq kbd:last-child{margin-right:0} .menuseq,.menu{color:rgba(0,0,0,.8)} b.button:before,b.button:after{position:relative;top:-1px;font-weight:400} b.button:before{content:"[";padding:0 3px 0 2px} b.button:after{content:"]";padding:0 2px 0 3px} p a>code:hover{color:rgba(0,0,0,.9)} #header,#content,#footnotes,#footer{width:100%;margin-left:auto;margin-right:auto;margin-top:0;margin-bottom:0;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em} #header:before,#header:after,#content:before,#content:after,#footnotes:before,#footnotes:after,#footer:before,#footer:after{content:" ";display:table} #header:after,#content:after,#footnotes:after,#footer:after{clear:both} #content{margin-top:1.25em} #content:before{content:none} #header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0} #header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #ddddd8} #header>h1:only-child,body.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #ddddd8;padding-bottom:8px} #header .details{border-bottom:1px solid #ddddd8;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:-ms-flexbox;display:-webkit-flex;display:flex;-ms-flex-flow:row wrap;-webkit-flex-flow:row wrap;flex-flow:row wrap} #header .details span:first-child{margin-left:-.125em} #header .details span.email a{color:rgba(0,0,0,.85)} #header .details br{display:none} #header .details br+span:before{content:"\00a0\2013\00a0"} #header .details br+span.author:before{content:"\00a0\22c5\00a0";color:rgba(0,0,0,.85)} #header .details br+span#revremark:before{content:"\00a0|\00a0"} #header #revnumber{text-transform:capitalize} #header #revnumber:after{content:"\00a0"} #content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #ddddd8;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem} #toc{border-bottom:1px solid #efefed;padding-bottom:.5em} #toc>ul{margin-left:.125em} #toc ul.sectlevel0>li>a{font-style:italic} #toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0} #toc ul{font-family:"Open Sans","DejaVu Sans",sans-serif;list-style-type:none} #toc li{line-height:1.3334;margin-top:.3334em} #toc a{text-decoration:none} #toc a:active{text-decoration:underline} #toctitle{color:#7a2518;font-size:1.2em} @media only screen and (min-width:768px){#toctitle{font-size:1.375em} body.toc2{padding-left:15em;padding-right:0} #toc.toc2{margin-top:0!important;background-color:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #efefed;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto} #toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em} #toc.toc2>ul{font-size:.9em;margin-bottom:0} #toc.toc2 ul ul{margin-left:0;padding-left:1em} #toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em} body.toc2.toc-right{padding-left:0;padding-right:15em} body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #efefed;left:auto;right:0}} @media only screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0} #toc.toc2{width:20em} #toc.toc2 #toctitle{font-size:1.375em} #toc.toc2>ul{font-size:.95em} #toc.toc2 ul ul{padding-left:1.25em} body.toc2.toc-right{padding-left:0;padding-right:20em}} #content #toc{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px} #content #toc>:first-child{margin-top:0} #content #toc>:last-child{margin-bottom:0} #footer{max-width:100%;background-color:rgba(0,0,0,.8);padding:1.25em} #footer-text{color:rgba(255,255,255,.8);line-height:1.44} .sect1{padding-bottom:.625em} @media only screen and (min-width:768px){.sect1{padding-bottom:1.25em}} .sect1+.sect1{border-top:1px solid #efefed} #content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400} #content h1>a.anchor:before,h2>a.anchor:before,h3>a.anchor:before,#toctitle>a.anchor:before,.sidebarblock>.content>.title>a.anchor:before,h4>a.anchor:before,h5>a.anchor:before,h6>a.anchor:before{content:"\00A7";font-size:.85em;display:block;padding-top:.1em} #content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible} #content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none} #content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221} .audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em} .admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:"Noto Serif","DejaVu Serif",serif;font-size:1rem;font-style:italic} table.tableblock>caption.title{white-space:nowrap;overflow:visible;max-width:0} .paragraph.lead>p,#preamble>.sectionbody>.paragraph:first-of-type p{color:rgba(0,0,0,.85)} table.tableblock #preamble>.sectionbody>.paragraph:first-of-type p{font-size:inherit} .admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%} .admonitionblock>table td.icon{text-align:center;width:80px} .admonitionblock>table td.icon img{max-width:none} .admonitionblock>table td.icon .title{font-weight:bold;font-family:"Open Sans","DejaVu Sans",sans-serif;text-transform:uppercase} .admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #ddddd8;color:rgba(0,0,0,.6)} .admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0} .exampleblock>.content{border-style:solid;border-width:1px;border-color:#e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;-webkit-border-radius:4px;border-radius:4px} .exampleblock>.content>:first-child{margin-top:0} .exampleblock>.content>:last-child{margin-bottom:0} .sidebarblock{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px} .sidebarblock>:first-child{margin-top:0} .sidebarblock>:last-child{margin-bottom:0} .sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center} .exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0} .literalblock pre,.listingblock pre:not(.highlight),.listingblock pre[class="highlight"],.listingblock pre[class^="highlight "],.listingblock pre.CodeRay,.listingblock pre.prettyprint{background:#f7f7f8} .sidebarblock .literalblock pre,.sidebarblock .listingblock pre:not(.highlight),.sidebarblock .listingblock pre[class="highlight"],.sidebarblock .listingblock pre[class^="highlight "],.sidebarblock .listingblock pre.CodeRay,.sidebarblock .listingblock pre.prettyprint{background:#f2f1f1} .literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{-webkit-border-radius:4px;border-radius:4px;word-wrap:break-word;padding:1em;font-size:.8125em} .literalblock pre.nowrap,.literalblock pre[class].nowrap,.listingblock pre.nowrap,.listingblock pre[class].nowrap{overflow-x:auto;white-space:pre;word-wrap:normal} @media only screen and (min-width:768px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:.90625em}} @media only screen and (min-width:1280px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:1em}} .literalblock.output pre{color:#f7f7f8;background-color:rgba(0,0,0,.9)} .listingblock pre.highlightjs{padding:0} .listingblock pre.highlightjs>code{padding:1em;-webkit-border-radius:4px;border-radius:4px} .listingblock pre.prettyprint{border-width:0} .listingblock>.content{position:relative} .listingblock code[data-lang]:before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:#999} .listingblock:hover code[data-lang]:before{display:block} .listingblock.terminal pre .command:before{content:attr(data-prompt);padding-right:.5em;color:#999} .listingblock.terminal pre .command:not([data-prompt]):before{content:"$"} table.pyhltable{border-collapse:separate;border:0;margin-bottom:0;background:none} table.pyhltable td{vertical-align:top;padding-top:0;padding-bottom:0;line-height:1.45} table.pyhltable td.code{padding-left:.75em;padding-right:0} pre.pygments .lineno,table.pyhltable td:not(.code){color:#999;padding-left:0;padding-right:.5em;border-right:1px solid #ddddd8} pre.pygments .lineno{display:inline-block;margin-right:.25em} table.pyhltable .linenodiv{background:none!important;padding-right:0!important} .quoteblock{margin:0 1em 1.25em 1.5em;display:table} .quoteblock>.title{margin-left:-1.5em;margin-bottom:.75em} .quoteblock blockquote,.quoteblock blockquote p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify} .quoteblock blockquote{margin:0;padding:0;border:0} .quoteblock blockquote:before{content:"\201c";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)} .quoteblock blockquote>.paragraph:last-child p{margin-bottom:0} .quoteblock .attribution{margin-top:.5em;margin-right:.5ex;text-align:right} .quoteblock .quoteblock{margin-left:0;margin-right:0;padding:.5em 0;border-left:3px solid rgba(0,0,0,.6)} .quoteblock .quoteblock blockquote{padding:0 0 0 .75em} .quoteblock .quoteblock blockquote:before{display:none} .verseblock{margin:0 1em 1.25em 1em} .verseblock pre{font-family:"Open Sans","DejaVu Sans",sans;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility} .verseblock pre strong{font-weight:400} .verseblock .attribution{margin-top:1.25rem;margin-left:.5ex} .quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic} .quoteblock .attribution br,.verseblock .attribution br{display:none} .quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)} .quoteblock.abstract{margin:0 0 1.25em 0;display:block} .quoteblock.abstract blockquote,.quoteblock.abstract blockquote p{text-align:left;word-spacing:0} .quoteblock.abstract blockquote:before,.quoteblock.abstract blockquote p:first-of-type:before{display:none} table.tableblock{max-width:100%;border-collapse:separate} table.tableblock td>.paragraph:last-child p>p:last-child,table.tableblock th>p:last-child,table.tableblock td>p:last-child{margin-bottom:0} table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede} table.grid-all th.tableblock,table.grid-all td.tableblock{border-width:0 1px 1px 0} table.grid-all tfoot>tr>th.tableblock,table.grid-all tfoot>tr>td.tableblock{border-width:1px 1px 0 0} table.grid-cols th.tableblock,table.grid-cols td.tableblock{border-width:0 1px 0 0} table.grid-all *>tr>.tableblock:last-child,table.grid-cols *>tr>.tableblock:last-child{border-right-width:0} table.grid-rows th.tableblock,table.grid-rows td.tableblock{border-width:0 0 1px 0} table.grid-all tbody>tr:last-child>th.tableblock,table.grid-all tbody>tr:last-child>td.tableblock,table.grid-all thead:last-child>tr>th.tableblock,table.grid-rows tbody>tr:last-child>th.tableblock,table.grid-rows tbody>tr:last-child>td.tableblock,table.grid-rows thead:last-child>tr>th.tableblock{border-bottom-width:0} table.grid-rows tfoot>tr>th.tableblock,table.grid-rows tfoot>tr>td.tableblock{border-width:1px 0 0 0} table.frame-all{border-width:1px} table.frame-sides{border-width:0 1px} table.frame-topbot{border-width:1px 0} th.halign-left,td.halign-left{text-align:left} th.halign-right,td.halign-right{text-align:right} th.halign-center,td.halign-center{text-align:center} th.valign-top,td.valign-top{vertical-align:top} th.valign-bottom,td.valign-bottom{vertical-align:bottom} th.valign-middle,td.valign-middle{vertical-align:middle} table thead th,table tfoot th{font-weight:bold} tbody tr th{display:table-cell;line-height:1.6;background:#f7f8f7} tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold} p.tableblock>code:only-child{background:none;padding:0} p.tableblock{font-size:1em} td>div.verse{white-space:pre} ol{margin-left:1.75em} ul li ol{margin-left:1.5em} dl dd{margin-left:1.125em} dl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0} ol>li p,ul>li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em} ul.unstyled,ol.unnumbered,ul.checklist,ul.none{list-style-type:none} ul.unstyled,ol.unnumbered,ul.checklist{margin-left:.625em} ul.checklist li>p:first-child>.fa-square-o:first-child,ul.checklist li>p:first-child>.fa-check-square-o:first-child{width:1em;font-size:.85em} ul.checklist li>p:first-child>input[type="checkbox"]:first-child{width:1em;position:relative;top:1px} ul.inline{margin:0 auto .625em auto;margin-left:-1.375em;margin-right:0;padding:0;list-style:none;overflow:hidden} ul.inline>li{list-style:none;float:left;margin-left:1.375em;display:block} ul.inline>li>*{display:block} .unstyled dl dt{font-weight:400;font-style:normal} ol.arabic{list-style-type:decimal} ol.decimal{list-style-type:decimal-leading-zero} ol.loweralpha{list-style-type:lower-alpha} ol.upperalpha{list-style-type:upper-alpha} ol.lowerroman{list-style-type:lower-roman} ol.upperroman{list-style-type:upper-roman} ol.lowergreek{list-style-type:lower-greek} .hdlist>table,.colist>table{border:0;background:none} .hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none} td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em} td.hdlist1{font-weight:bold;padding-bottom:1.25em} .literalblock+.colist,.listingblock+.colist{margin-top:-.5em} .colist>table tr>td:first-of-type{padding:0 .75em;line-height:1} .colist>table tr>td:last-of-type{padding:.25em 0} .thumb,.th{line-height:0;display:inline-block;border:solid 4px #fff;-webkit-box-shadow:0 0 0 1px #ddd;box-shadow:0 0 0 1px #ddd} .imageblock.left,.imageblock[style*="float: left"]{margin:.25em .625em 1.25em 0} .imageblock.right,.imageblock[style*="float: right"]{margin:.25em 0 1.25em .625em} .imageblock>.title{margin-bottom:0} .imageblock.thumb,.imageblock.th{border-width:6px} .imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em} .image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0} .image.left{margin-right:.625em} .image.right{margin-left:.625em} a.image{text-decoration:none;display:inline-block} a.image object{pointer-events:none} sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super} sup.footnote a,sup.footnoteref a{text-decoration:none} sup.footnote a:active,sup.footnoteref a:active{text-decoration:underline} #footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em} #footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em 0;border-width:1px 0 0 0} #footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;text-indent:-1.05em;margin-bottom:.2em} #footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none} #footnotes .footnote:last-of-type{margin-bottom:0} #content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0} .gist .file-data>table{border:0;background:#fff;width:100%;margin-bottom:0} .gist .file-data>table td.line-data{width:99%} div.unbreakable{page-break-inside:avoid} .big{font-size:larger} .small{font-size:smaller} .underline{text-decoration:underline} .overline{text-decoration:overline} .line-through{text-decoration:line-through} .aqua{color:#00bfbf} .aqua-background{background-color:#00fafa} .black{color:#000} .black-background{background-color:#000} .blue{color:#0000bf} .blue-background{background-color:#0000fa} .fuchsia{color:#bf00bf} .fuchsia-background{background-color:#fa00fa} .gray{color:#606060} .gray-background{background-color:#7d7d7d} .green{color:#006000} .green-background{background-color:#007d00} .lime{color:#00bf00} .lime-background{background-color:#00fa00} .maroon{color:#600000} .maroon-background{background-color:#7d0000} .navy{color:#000060} .navy-background{background-color:#00007d} .olive{color:#606000} .olive-background{background-color:#7d7d00} .purple{color:#600060} .purple-background{background-color:#7d007d} .red{color:#bf0000} .red-background{background-color:#fa0000} .silver{color:#909090} .silver-background{background-color:#bcbcbc} .teal{color:#006060} .teal-background{background-color:#007d7d} .white{color:#bfbfbf} .white-background{background-color:#fafafa} .yellow{color:#bfbf00} .yellow-background{background-color:#fafa00} span.icon>.fa{cursor:default} .admonitionblock td.icon [class^="fa icon-"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default} .admonitionblock td.icon .icon-note:before{content:"\f05a";color:#19407c} .admonitionblock td.icon .icon-tip:before{content:"\f0eb";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111} .admonitionblock td.icon .icon-warning:before{content:"\f071";color:#bf6900} .admonitionblock td.icon .icon-caution:before{content:"\f06d";color:#bf3400} .admonitionblock td.icon .icon-important:before{content:"\f06a";color:#bf0000} .conum[data-value]{display:inline-block;color:#fff!important;background-color:rgba(0,0,0,.8);-webkit-border-radius:100px;border-radius:100px;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:"Open Sans","DejaVu Sans",sans-serif;font-style:normal;font-weight:bold} .conum[data-value] *{color:#fff!important} .conum[data-value]+b{display:none} .conum[data-value]:after{content:attr(data-value)} pre .conum[data-value]{position:relative;top:-.125em} b.conum *{color:inherit!important} .conum:not([data-value]):empty{display:none} dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility} h1,h2,p,td.content,span.alt{letter-spacing:-.01em} p strong,td.content strong,div.footnote strong{letter-spacing:-.005em} p,blockquote,dt,td.content,span.alt{font-size:1.0625rem} p{margin-bottom:1.25rem} .sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em} .exampleblock>.content{background-color:#fffef7;border-color:#e0e0dc;-webkit-box-shadow:0 1px 4px #e0e0dc;box-shadow:0 1px 4px #e0e0dc} .print-only{display:none!important} @media print{@page{margin:1.25cm .75cm} *{-webkit-box-shadow:none!important;box-shadow:none!important;text-shadow:none!important} a{color:inherit!important;text-decoration:underline!important} a.bare,a[href^="#"],a[href^="mailto:"]{text-decoration:none!important} a[href^="http:"]:not(.bare):after,a[href^="https:"]:not(.bare):after{content:"(" attr(href) ")";display:inline-block;font-size:.875em;padding-left:.25em} abbr[title]:after{content:" (" attr(title) ")"} pre,blockquote,tr,img,object,svg{page-break-inside:avoid} thead{display:table-header-group} svg{max-width:100%} p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3} h2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid} #toc,.sidebarblock,.exampleblock>.content{background:none!important} #toc{border-bottom:1px solid #ddddd8!important;padding-bottom:0!important} .sect1{padding-bottom:0!important} .sect1+.sect1{border:0!important} #header>h1:first-child{margin-top:1.25rem} body.book #header{text-align:center} body.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em 0} body.book #header .details{border:0!important;display:block;padding:0!important} body.book #header .details span:first-child{margin-left:0!important} body.book #header .details br{display:block} body.book #header .details br+span:before{content:none!important} body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important} body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always} .listingblock code[data-lang]:before{display:block} #footer{background:none!important;padding:0 .9375em} #footer-text{color:rgba(0,0,0,.6)!important;font-size:.9em} .hide-on-print{display:none!important} .print-only{display:block!important} .hide-for-print{display:none!important} .show-for-print{display:inherit!important}} </style> <style> .listingblock .pygments .hll { background-color: #ffffcc } .listingblock .pygments { background: #f8f8f8; } .listingblock .pygments .tok-c { color: #408080; font-style: italic } /* Comment */ .listingblock .pygments .tok-err { border: 1px solid #FF0000 } /* Error */ .listingblock .pygments .tok-k { color: #008000; font-weight: bold } /* Keyword */ .listingblock .pygments .tok-o { color: #666666 } /* Operator */ .listingblock .pygments .tok-cm { color: #408080; font-style: italic } /* Comment.Multiline */ .listingblock .pygments .tok-cp { color: #BC7A00 } /* Comment.Preproc */ .listingblock .pygments .tok-c1 { color: #408080; font-style: italic } /* Comment.Single */ .listingblock .pygments .tok-cs { color: #408080; font-style: italic } /* Comment.Special */ .listingblock .pygments .tok-gd { color: #A00000 } /* Generic.Deleted */ .listingblock .pygments .tok-ge { font-style: italic } /* Generic.Emph */ .listingblock .pygments .tok-gr { color: #FF0000 } /* Generic.Error */ .listingblock .pygments .tok-gh { color: #000080; font-weight: bold } /* Generic.Heading */ .listingblock .pygments .tok-gi { color: #00A000 } /* Generic.Inserted */ .listingblock .pygments .tok-go { color: #888888 } /* Generic.Output */ .listingblock .pygments .tok-gp { color: #000080; font-weight: bold } /* Generic.Prompt */ .listingblock .pygments .tok-gs { font-weight: bold } /* Generic.Strong */ .listingblock .pygments .tok-gu { color: #800080; font-weight: bold } /* Generic.Subheading */ .listingblock .pygments .tok-gt { color: #0044DD } /* Generic.Traceback */ .listingblock .pygments .tok-kc { color: #008000; font-weight: bold } /* Keyword.Constant */ .listingblock .pygments .tok-kd { color: #008000; font-weight: bold } /* Keyword.Declaration */ .listingblock .pygments .tok-kn { color: #008000; font-weight: bold } /* Keyword.Namespace */ .listingblock .pygments .tok-kp { color: #008000 } /* Keyword.Pseudo */ .listingblock .pygments .tok-kr { color: #008000; font-weight: bold } /* Keyword.Reserved */ .listingblock .pygments .tok-kt { color: #B00040 } /* Keyword.Type */ .listingblock .pygments .tok-m { color: #666666 } /* Literal.Number */ .listingblock .pygments .tok-s { color: #BA2121 } /* Literal.String */ .listingblock .pygments .tok-na { color: #7D9029 } /* Name.Attribute */ .listingblock .pygments .tok-nb { color: #008000 } /* Name.Builtin */ .listingblock .pygments .tok-nc { color: #0000FF; font-weight: bold } /* Name.Class */ .listingblock .pygments .tok-no { color: #880000 } /* Name.Constant */ .listingblock .pygments .tok-nd { color: #AA22FF } /* Name.Decorator */ .listingblock .pygments .tok-ni { color: #999999; font-weight: bold } /* Name.Entity */ .listingblock .pygments .tok-ne { color: #D2413A; font-weight: bold } /* Name.Exception */ .listingblock .pygments .tok-nf { color: #0000FF } /* Name.Function */ .listingblock .pygments .tok-nl { color: #A0A000 } /* Name.Label */ .listingblock .pygments .tok-nn { color: #0000FF; font-weight: bold } /* Name.Namespace */ .listingblock .pygments .tok-nt { color: #008000; font-weight: bold } /* Name.Tag */ .listingblock .pygments .tok-nv { color: #19177C } /* Name.Variable */ .listingblock .pygments .tok-ow { color: #AA22FF; font-weight: bold } /* Operator.Word */ .listingblock .pygments .tok-w { color: #bbbbbb } /* Text.Whitespace */ .listingblock .pygments .tok-mb { color: #666666 } /* Literal.Number.Bin */ .listingblock .pygments .tok-mf { color: #666666 } /* Literal.Number.Float */ .listingblock .pygments .tok-mh { color: #666666 } /* Literal.Number.Hex */ .listingblock .pygments .tok-mi { color: #666666 } /* Literal.Number.Integer */ .listingblock .pygments .tok-mo { color: #666666 } /* Literal.Number.Oct */ .listingblock .pygments .tok-sb { color: #BA2121 } /* Literal.String.Backtick */ .listingblock .pygments .tok-sc { color: #BA2121 } /* Literal.String.Char */ .listingblock .pygments .tok-sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */ .listingblock .pygments .tok-s2 { color: #BA2121 } /* Literal.String.Double */ .listingblock .pygments .tok-se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */ .listingblock .pygments .tok-sh { color: #BA2121 } /* Literal.String.Heredoc */ .listingblock .pygments .tok-si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */ .listingblock .pygments .tok-sx { color: #008000 } /* Literal.String.Other */ .listingblock .pygments .tok-sr { color: #BB6688 } /* Literal.String.Regex */ .listingblock .pygments .tok-s1 { color: #BA2121 } /* Literal.String.Single */ .listingblock .pygments .tok-ss { color: #19177C } /* Literal.String.Symbol */ .listingblock .pygments .tok-bp { color: #008000 } /* Name.Builtin.Pseudo */ .listingblock .pygments .tok-vc { color: #19177C } /* Name.Variable.Class */ .listingblock .pygments .tok-vg { color: #19177C } /* Name.Variable.Global */ .listingblock .pygments .tok-vi { color: #19177C } /* Name.Variable.Instance */ .listingblock .pygments .tok-il { color: #666666 } /* Literal.Number.Integer.Long */ </style> </head> <body class="article toc2 toc-left"> <div id="header"> <h1><a href="https://github.com/bucklescript/bucklescript">BuckleScript</a> User Manual</h1> <div class="details"> <span id="author" class="author">Hongbo Zhang</span><br> <span id="revnumber">version 2.1.0</span> </div> <div id="toc" class="toc2"> <div id="toctitle">Table of Contents</div> <ul class="sectlevel1"> <li><a href="#_why_bucklescript">Why BuckleScript</a> <ul class="sectlevel2"> <li><a href="#_benefits_of_javascript_platform">Benefits of JavaScript platform</a></li> <li><a href="#_problems_of_javascript_how_bucklescript_solves_them">Problems of JavaScript && how BuckleScript solves them</a></li> </ul> </li> <li><a href="#_installation">Installation</a> <ul class="sectlevel2"> <li><a href="#_from_a_href_https_www_npmjs_com_package_bs_platform_npm_a_recommended_for_normal_users">From <a href="https://www.npmjs.com/package/bs-platform">npm</a> (recommended for normal users)</a></li> <li><a href="#_build_from_source_in_release_mode">Build from source in Release Mode</a></li> <li><a href="#_making_use_of_opam">Making use of OPAM</a></li> </ul> </li> <li><a href="#_get_started">Get Started</a> <ul class="sectlevel2"> <li><a href="#_using_existing_templates_since_1_7_4">Using existing templates (@since 1.7.4 )</a></li> <li><a href="#_first_example_by_hand_without_samples">First example by hand without samples</a></li> <li><a href="#_an_example_with_multiple_modules">An example with multiple modules</a></li> </ul> </li> <li><a href="#_built_in_npm_support">Built in NPM support</a> <ul class="sectlevel2"> <li><a href="#_build_an_ocaml_library_as_a_npm_package">Build an OCaml library as a npm package</a></li> <li><a href="#_to_use_ocaml_library_as_a_npm_package">To use OCaml library as a npm package</a></li> <li><a href="#_together">Together</a></li> <li><a href="#_examples">Examples</a></li> </ul> </li> <li><a href="#_js_calling_ocaml">JS Calling OCaml</a></li> <li><a href="#_bucklescript_annotations_for_unicode_and_js_ffi_support">BuckleScript annotations for Unicode and JS FFI support</a> <ul class="sectlevel2"> <li><a href="#_unicode_support_since_1_5_1">Unicode support (@since 1.5.1)</a> <ul class="sectlevel3"> <li><a href="#_unicode_support_with_string_interpolation_since_1_7_0">Unicode support with string interpolation (@since 1.7.0)</a></li> </ul> </li> <li><a href="#_ffi">FFI</a></li> <li><a href="#_binding_to_simple_js_functions_values">Binding to simple JS functions values</a> <ul class="sectlevel3"> <li><a href="#_binding_to_global_value_code_bs_val_code">Binding to global value: <code>bs.val</code></a></li> <li><a href="#_scoped_values_code_bs_scope_code_since_1_7_2">Scoped values: <code>bs.scope</code> (@since 1.7.2)</a></li> <li><a href="#_binding_to_javascript_constructor_code_bs_new_code">Binding to JavaScript constructor: <code>bs.new</code></a></li> <li><a href="#_binding_to_a_value_from_a_module_code_bs_module_code">Binding to a value from a module: <code>bs.module</code></a></li> <li><a href="#_binding_the_whole_module_as_a_value_or_function">Binding the whole module as a value or function</a></li> <li><a href="#_binding_to_method_code_bs_send_code_code_bs_send_pipe_code">Binding to method: <code>bs.send</code>, <code>bs.send.pipe</code></a></li> <li><a href="#_binding_to_dynamic_key_access_set_code_bs_set_index_code_code_bs_get_index_code">Binding to dynamic key access/set: <code>bs.set_index</code>, <code>bs.get_index</code></a></li> <li><a href="#_binding_to_getter_setter_code_bs_get_code_code_bs_set_code">Binding to Getter/Setter: <code>bs.get</code>, <code>bs.set</code></a></li> </ul> </li> <li><a href="#_splice_calling_convention_code_bs_splice_code">Splice calling convention: <code>bs.splice</code></a></li> <li><a href="#_special_types_on_external_declarations_code_bs_string_code_code_bs_int_code_code_bs_ignore_code_code_bs_as_code_code_bs_unwrap_code">Special types on external declarations: <code>bs.string</code>, <code>bs.int</code>, <code>bs.ignore</code>, <code>bs.as</code>, <code>bs.unwrap</code></a> <ul class="sectlevel3"> <li><a href="#_using_polymorphic_variant_to_model_enums_and_string_types">Using polymorphic variant to model enums and string types</a></li> <li><a href="#_using_polymorphic_variant_to_model_event_listener">Using polymorphic variant to model event listener</a></li> <li><a href="#_using_polymorphic_variant_to_model_arguments_of_multiple_possible_types_since_1_8_3">Using polymorphic variant to model arguments of multiple possible types (@since 1.8.3)</a></li> <li><a href="#_phantom_arguments_and_ad_hoc_polymorphism">Phantom Arguments and ad-hoc polymorphism</a></li> <li><a href="#_fixed_arguments">Fixed Arguments</a></li> <li><a href="#_fixed_arguments_with_arbitrary_json_literal_since_1_7_0">Fixed Arguments with arbitrary JSON literal (@since 1.7.0)</a></li> </ul> </li> <li><a href="#_binding_to_nodejs_special_variables_a_href_api_node_html_bs_node_a">Binding to NodeJS special variables: <a href="../api/Node.html">bs.node</a></a></li> <li><a href="#_binding_to_callbacks_higher_order_function">Binding to callbacks (higher-order function)</a> <ul class="sectlevel3"> <li><a href="#__code_bs_code_for_explicit_uncurried_callback"><code>[@bs]</code> for explicit uncurried callback</a></li> <li><a href="#__code_bs_uncurry_code_for_implicit_uncurried_callback_since_1_5_0"><code>[@bs.uncurry]</code> for implicit uncurried callback (@since 1.5.0)</a></li> <li><a href="#_uncurried_calling_convention_as_an_optimization">Uncurried calling convention as an optimization</a> <ul class="sectlevel4"> <li><a href="#_callback_optimization">Callback optimization</a></li> </ul> </li> <li><a href="#_bindings_to_code_this_code_based_callbacks_code_bs_this_code">Bindings to <code>this</code> based callbacks: <code>bs.this</code></a></li> </ul> </li> <li><a href="#_binding_to_js_objects">Binding to JS objects</a> <ul class="sectlevel3"> <li><a href="#_simple_object_type">Simple object type</a></li> <li><a href="#_complex_object_type">Complex object type</a></li> <li><a href="#_how_to_consume_js_property_and_methods">How to consume JS property and methods</a> <ul class="sectlevel4"> <li><a href="#_getter_setter_annotation_to_js_properties_simplified_since_1_9_2">getter/setter annotation to JS properties (simplified @since 1.9.2)</a></li> </ul> </li> <li><a href="#_create_js_objects_using_bs_obj">Create JS objects using bs.obj</a></li> <li><a href="#_create_js_objects_using_external">Create JS objects using external</a></li> <li><a href="#_create_js_objects_with_code_this_code_semantics">Create JS objects with <code>this</code> semantics</a> <ul class="sectlevel4"> <li><a href="#_method_chaining">Method chaining</a></li> </ul> </li> <li><a href="#_object_label_translation_convention">Object label translation convention</a></li> </ul> </li> <li><a href="#_return_value_checking_since_1_5_1">Return value checking (@since 1.5.1)</a></li> <li><a href="#_mapping_between_js_values_and_ocaml_values_since_2_1_0">Mapping between JS values and OCaml values (@since 2.1.0)</a> <ul class="sectlevel3"> <li><a href="#_mapping_js_int_enums_to_ocaml_enums_since_2_1_0">Mapping JS Int enums to OCaml enums (@since 2.1.0)</a></li> <li><a href="#_mapping_js_string_enums_to_ocaml_enums_since_2_1_0">Mapping JS string enums to OCaml enums (@since 2.1.0)</a></li> <li><a href="#_mapping_js_objects_to_ocaml_records_since_2_1_0">Mapping JS objects to OCaml records (@since 2.1.0)</a></li> </ul> </li> <li><a href="#_embedding_untyped_javascript_code">Embedding untyped Javascript code</a> <ul class="sectlevel3"> <li><a href="#_detect_global_variable_existence_code_bs_external_code_since_1_5_1">Detect global variable existence <code>bs.external</code> (@since 1.5.1)</a></li> <li><a href="#_embedding_arbitrary_js_code_as_an_expression">Embedding arbitrary JS code as an expression</a></li> <li><a href="#_embedding_raw_js_code_as_statements">Embedding raw JS code as statements</a></li> </ul> </li> <li><a href="#_debugger_support">Debugger support</a></li> <li><a href="#_regex_support">Regex support</a></li> <li><a href="#_examples_2">Examples</a> <ul class="sectlevel3"> <li><a href="#_a_simple_example_binding_to_mocha_unit_test_library">A simple example: binding to mocha unit test library</a></li> </ul> </li> </ul> </li> <li><a href="#_exception_handling_between_ocaml_and_js_since_1_7_0">Exception handling between OCaml and JS (@since 1.7.0)</a></li> <li><a href="#__code_bs_open_code_type_safe_external_data_source_handling_since_1_7_0"><code>bs.open</code>: Type safe external data-source handling (@@since 1.7.0)</a> <ul class="sectlevel2"> <li><a href="#_use_cases">Use cases</a></li> </ul> </li> <li><a href="#_js_module">Js module</a> <ul class="sectlevel2"> <li><a href="#_null_and_undefined">Null and Undefined</a></li> <li><a href="#_boolean">Boolean</a></li> </ul> </li> <li><a href="#_extended_compiler_options">Extended compiler options</a> <ul class="sectlevel2"> <li><a href="#__bs_main_single_directory_build">-bs-main (single directory build)</a></li> <li><a href="#__bs_files">-bs-files</a></li> <li><a href="#__bs_package_name">-bs-package-name</a></li> <li><a href="#__bs_packge_output">-bs-packge-output</a></li> <li><a href="#__bs_gen_tds">-bs-gen-tds</a></li> <li><a href="#__bs_no_warn_ffi_type">-bs-no-warn-ffi-type</a></li> <li><a href="#__bs_eval">-bs-eval</a></li> <li><a href="#__bs_no_builtin_ppx_ml_bs_no_builtin_ppx_mli">-bs-no-builtin-ppx-ml, -bs-no-builtin-ppx-mli</a></li> <li><a href="#__bs_no_version_header">-bs-no-version-header</a></li> </ul> </li> <li><a href="#_semantic_differences_from_other_backends">Semantic differences from other backends</a> <ul class="sectlevel2"> <li><a href="#_custom_data_type">Custom data type</a></li> <li><a href="#_physical_in_equality">Physical (in)equality</a></li> <li><a href="#_string_char_range">String char range</a></li> <li><a href="#_weak_map">Weak map</a></li> <li><a href="#_integers">Integers</a></li> <li><a href="#_printf_printf">Printf.printf</a></li> <li><a href="#_obj_module">Obj module</a></li> <li><a href="#_hashtbl_hash_algorithm">Hashtbl hash algorithm</a></li> <li><a href="#_marshall">Marshall</a></li> <li><a href="#_sys_argv_sys_max_array_length_sys_max_string_length">Sys.argv, Sys.max_array_length, Sys.max_string_length</a></li> <li><a href="#_unsupported_io_primitives">Unsupported IO primitives</a></li> </ul> </li> <li><a href="#_conditional_compilation_support_static_if">Conditional compilation support - static if</a> <ul class="sectlevel2"> <li><a href="#_concrete_syntax">Concrete syntax</a></li> <li><a href="#_typing_rules">Typing rules</a></li> <li><a href="#_examples_3">Examples</a></li> <li><a href="#_built_in_variables_and_custom_variables">Built in variables and custom variables</a></li> <li><a href="#_changes_to_command_line_options">Changes to command line options</a></li> </ul> </li> <li><a href="#_build_system_support">Build system support</a> <ul class="sectlevel2"> <li><a href="#_bucklescript_build_system_code_bsb_code">BuckleScript build system: <code>bsb</code></a> <ul class="sectlevel3"> <li><a href="#_build_with_other_bucklescript_dependencies">Build with other BuckleScript dependencies</a></li> <li><a href="#_mark_your_directory_as_dev_only">Mark your directory as dev only</a></li> </ul> </li> <li><a href="#_a_real_world_example_of_using_code_bsb_code">A real world example of using <code>bsb</code></a></li> <li><a href="#_namespace_support_since_1_9_0">namespace support (@since 1.9.0)</a></li> <li><a href="#_in_source_build_support_since_1_9_0">In source build support (@since 1.9.0)</a></li> <li><a href="#_build_using_make">Build using Make</a></li> <li><a href="#_customize_rules_generators_support_since_1_7_4">Customize rules (generators support, @since 1.7.4)</a></li> </ul> </li> <li><a href="#_faq">FAQ</a></li> <li><a href="#_high_level_compiler_workflow">High Level compiler workflow</a> <ul class="sectlevel2"> <li><a href="#_design_principles">Design Principles</a></li> <li><a href="#_soundness">Soundness</a></li> <li><a href="#_minimal_new_symbol_creation">Minimal new symbol creation</a></li> </ul> </li> <li><a href="#_runtime_representation">Runtime representation</a> <ul class="sectlevel2"> <li><a href="#_simple_ocaml_type">Simple OCaml type</a></li> </ul> </li> <li><a href="#_integration_with_reason">Integration with Reason</a></li> <li><a href="#_contributions">Contributions</a> <ul class="sectlevel2"> <li><a href="#_development_set_up">Development set-up</a></li> <li><a href="#_contributing_to_code_bsb_exe_code">Contributing to <code>bsb.exe</code></a></li> <li><a href="#_contributing_to_code_bsc_exe_code">Contributing to <code>bsc.exe</code></a></li> <li><a href="#_contributing_to_the_runtime">Contributing to the runtime</a></li> <li><a href="#_contributing_to_the_documentation">Contributing to the documentation</a></li> <li><a href="#_contributing_to_the_api_reference">Contributing to the API reference</a></li> </ul> </li> <li><a href="#_comparisons">Comparisons</a> <ul class="sectlevel2"> <li><a href="#_difference_from_a_href_https_github_com_ocsigen_js_of_ocaml_js_of_ocaml_a">Difference from <a href="https://github.com/ocsigen/js_of_ocaml">js_of_ocaml</a></a></li> </ul> </li> <li><a href="#_library_api_documentation">Appendix A: Library API documentation</a></li> <li><a href="#_changes">Appendix B: CHANGES</a> <ul class="sectlevel2"> <li><a href="#_1_3_2">1.3.2</a></li> <li><a href="#_1_2_1_dev">1.2.1 + dev</a></li> <li><a href="#_1_1_2">1.1.2</a></li> <li><a href="#_1_1_1">1.1.1</a></li> <li><a href="#_1_03">1.03</a></li> <li><a href="#_1_02">1.02</a></li> <li><a href="#_1_01">1.01</a></li> <li><a href="#_1_0">1.0</a></li> </ul> </li> </ul> </div> </div> <div id="content"> <div id="preamble"> <div class="sectionbody"> <input type="search" id="agolia-search" placeholder="Search docs..."> <!-- at the end of the HEAD --> <link rel="stylesheet" href="https://cdn.jsdelivr.net/docsearch.js/2/docsearch.min.css" /> <!-- at the end of the BODY --> <script type="text/javascript" src="https://cdn.jsdelivr.net/docsearch.js/2/docsearch.min.js"></script> <script type="text/javascript"> docsearch({ apiKey: '0fd97db83891aa20810559812d9e69ac', indexName: 'bucklescript', inputSelector: '#agolia-search', debug: false // Set debug to true if you want to inspect the dropdown }); </script> <div class="paragraph"> <p>BuckleScript is a backend for the <a href="https://ocaml.org/">OCaml</a> compiler which emits JavaScript. It works with both vanilla OCaml and <a href="https://github.com/facebook/Reason">Reason</a>, the whole compiler is compiled into JS (and ASM) so that you can play with it in the <a href="https://bucklescript.github.io/bucklescript-playground/">browser</a>.</p> </div> <div class="admonitionblock note"> <table> <tr> <td class="icon"> <div class="title">Note</div> </td> <td class="content"> <div class="paragraph"> <p>Documentation under <a href="https://bucklescript.github.io/bucklescript/Manual.html"><em>bucklescript.github.io</em></a> match the <a href="https://github.com/bucklescript/bucklescript">master branch</a>.</p> </div> <div class="paragraph"> <p>If you find errors or omissions in this document, please don’t hesitate to submit an issue, sources are <a href="https://github.com/bucklescript/bucklescript/tree/master/site/docsource">here</a>.</p> </div> </td> </tr> </table> </div> </div> </div> <div class="sect1"> <h2 id="_why_bucklescript"><a class="anchor" href="#_why_bucklescript"></a>Why BuckleScript</h2> <div class="sectionbody"> <div class="sect2"> <h3 id="_benefits_of_javascript_platform"><a class="anchor" href="#_benefits_of_javascript_platform"></a>Benefits of JavaScript platform</h3> <div class="paragraph"> <p>JavaScript is not just <em>the</em> browser language, it’s also the <em>only</em> existing cross platform language. It is truly everywhere: users don’t need to install binaries or use package managers to access software, just a link will work.</p> </div> <div class="paragraph"> <p>Another important factor is that the JavaScript VM is quite fast and keeps getting faster. The JavaScript platform is therefore increasingly capable of supporting large applications.</p> </div> </div> <div class="sect2"> <h3 id="_problems_of_javascript_how_bucklescript_solves_them"><a class="anchor" href="#_problems_of_javascript_how_bucklescript_solves_them"></a>Problems of JavaScript && how BuckleScript solves them</h3> <div class="paragraph"> <p>BuckleScript is mainly designed to solve the problems of <em>large scale</em> JavaScript programming:</p> </div> <div class="dlist"> <dl> <dt class="hdlist1">Type-safety</dt> <dd> <p>OCaml offers an industrial-strength state-of-the-art type system and provides very strong type inference (i.e. No verbose type annotation required compared with TypeScript), which proves <a href="http://programmers.stackexchange.com/questions/215482/what-are-the-safety-benefits-of-a-type-system">invaluable</a> in managing large projects. OCaml’s type system is not just for tooling, it is a <em>sound</em> type system which means it is guaranteed that there will be no runtime type errors after type checking.</p> </dd> <dt class="hdlist1">High quality dead code elimination</dt> <dd> <p>A large amount of web-development relies on inclusion of code dependencies by copying or referencing CDNs (the very thing that makes JavaScript highly accessible), but this also introduces a lot of <a href="https://en.wikipedia.org/wiki/Dead_code">dead code</a>. This impacts performance adversely when the JavaScript VM has to interpret code that will never be invoked. BuckleScript provides powerful dead-code elimination at all levels:</p> <div class="ulist"> <ul> <li> <p>Function and module level elimination is facilitated by the sophistication of the type-system of OCaml and <em>purity analysis</em>.</p> </li> <li> <p>At the global level BuckleScript generates code ready for dead-code elimination done by bundling tools such as the <a href="https://developers.google.com/closure/compiler/">Google closure-compiler</a>.</p> </li> </ul> </div> </dd> <dt class="hdlist1">Offline optimizations</dt> <dd> <p>JavaScript is a dynamic language, it takes a performance-hit for the VM to optimize code at runtime. While some JS engines circumvent the problem to some extent by <a href="http://v8project.blogspot.com/2015/07/code-caching.html">caching</a>, this is not available to all environments, and lack of a strong type system also limits the level of optimizations possible. Again, BuckleScript, using features of the OCaml type-system and compiler implementation is able to provide many optimizations during offline compilation, allowing the runtime code to be extremely fast.</p> </dd> <dt class="hdlist1">JS platform and Native platform</dt> <dd> <p>Run your programs on all platforms, but run your system <em>faster</em> under specific platforms. JavaScript is everywhere but it does not mean we have to run all apps in JS, under several platforms, for example, server side or iOS/Android native apps, when programs are written in OCaml, it can also be compiled to native code for <em>better and reliable performance</em>.</p> </dd> </dl> </div> <div class="paragraph"> <p>While a strong type-system helps in countering these problems, at the same time we hope to avoid some of the problems faced in using other offline <a href="https://github.com/jashkenas/coffeescript/wiki/list-of-languages-that-compile-to-js">transpilation systems</a>:</p> </div> <div class="dlist"> <dl> <dt class="hdlist1">Slow compilation</dt> <dd> <p>OCaml byte-code compilation is known to be fast (one or two orders of magnitude faster than other similar languages: <a href="http://www.scala-lang.org/">Scala</a> or <a href="https://www.haskell.org/">Haskell</a>), BuckleScript shares the same property and compiles even faster since it saves the link time. See the speeds at work in the <a href="https://bucklescript.github.io/bucklescript-playground/">playground</a>, the native backend is one order faster than the JS backend.</p> </dd> <dt class="hdlist1">Un-readable JS Code and hard to integrate with existing JS libraries</dt> <dd> <p>When compiling to JavaScript, many systems generate code, that while syntactically and semantically correct is not human-readable and very difficult to debug and profile. Our BuckleScript implementation and the multi-pass compilation strategy of OCaml, allows us to avoid <a href="https://en.wikipedia.org/wiki/Name_mangling">name-mangling</a>, and produce JavaScript code that is human-readable and easier to debug and maintain. More importantly, this makes integration with existing JS libraries <em>much easier</em>.</p> </dd> <dt class="hdlist1">Large JS output even for a simple program</dt> <dd> <p>In BuckleScript, a <code>Hello world</code> program generates <em>20 bytes</em> JS code instead of <em>50K bytes</em>. This is due to BuckleScript having an excellent integration with JS libs in that unlike most JS compilers, all BuckleScript’s runtime is written in OCaml itself so that these runtime libraries are only needed when user actually calls it.</p> </dd> <dt class="hdlist1">Loss of code-structure</dt> <dd> <p>Many systems generate JavaScript code that is essentially a <a href="https://en.wikipedia.org/wiki/Big_ball_of_mud">big ball of mud</a>. We try to keep the original structure of the code by mapping one OCaml module to one JS module.</p> </dd> </dl> </div> </div> </div> </div> <div class="sect1"> <h2 id="_installation"><a class="anchor" href="#_installation"></a>Installation</h2> <div class="sectionbody"> <div class="sect2"> <h3 id="_from_a_href_https_www_npmjs_com_package_bs_platform_npm_a_recommended_for_normal_users"><a class="anchor" href="#_from_a_href_https_www_npmjs_com_package_bs_platform_npm_a_recommended_for_normal_users"></a>From <a href="https://www.npmjs.com/package/bs-platform">npm</a> (recommended for normal users)</h3> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="sh">npm install -g bs-platform</code></pre> </div> </div> <div class="paragraph"> <p>It supports all platform including Windows</p> </div> </div> <div class="sect2"> <h3 id="_build_from_source_in_release_mode"><a class="anchor" href="#_build_from_source_in_release_mode"></a>Build from source in Release Mode</h3> <div class="paragraph"> <p>Note for dev mode, you are encouraged to work from <a href="https://github.com/BuckleScript/bucklescript/wiki/Contribute">there</a></p> </div> <div class="ulist"> <div class="title">Prerequisites</div> <ul> <li> <p>Standard C toolchain(gcc,Makefile)</p> </li> </ul> </div> <div class="listingblock"> <div class="title">Get source</div> <div class="content"> <pre class="pygments highlight"><code data-lang="sh">git clone https://github.com/bucklescript/bucklescript</code></pre> </div> </div> <div class="paragraph"> <p>The patched compiler is installed locally into your <code>$(pwd)/bin</code> directory. To start using it temporarily, check if <code>ocamlc.opt</code> and <code>ocamlopt.opt</code> exist in <code>$(pwd)/bin</code>, and temporarily add the location to your <code>$(PATH)</code> (e.g. <code>PATH=$(pwd)/bin:$PATH</code>).</p> </div> <div class="listingblock"> <div class="title">Build Vendored OCaml compiler</div> <div class="content"> <pre class="pygments highlight"><code data-lang="sh"><span class="tok-nb">cd </span>bucklescript/vendor/ocaml ./configure -prefix <span class="tok-sb">`</span><span class="tok-nb">pwd</span><span class="tok-sb">`</span> make world <span class="tok-o">&&</span> make install</code></pre> </div> </div> <div class="paragraph"> <div class="title">Build BuckleScript compiler and its toolchain</div> <p>The following directions assume you already have the correct version of <code>ocamlopt.opt</code> in your <code>$PATH</code>, having followed the process described in the previous section.</p> </div> <div class="paragraph"> <p>Change <code>cwd</code> to project root directory</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="sh"><span class="tok-nb">export </span><span class="tok-nv">BS_RELEASE_BUILD</span><span class="tok-o">=</span>1 make world <span class="tok-o">&&</span> install</code></pre> </div> </div> <div class="paragraph"> <p>At the end, you should have a binary called <code>bsc.exe</code> under <code>lib/</code> directory, which you can add to your <code>$PATH</code>.</p> </div> </div> <div class="sect2"> <h3 id="_making_use_of_opam"><a class="anchor" href="#_making_use_of_opam"></a>Making use of OPAM</h3> <div class="paragraph"> <p>When working with OCaml we also recommend using <a href="https://opam.ocaml.org">opam</a> package manager to install OCaml native toolchains, available <a href="https://opam.ocaml.org/doc/Install.html">here</a>. You will benefit from the existing OCaml ecosystem.</p> </div> <div class="paragraph"> <p>Once you have <code>opam</code> installed, ask <code>opam</code> to switch to using our version of the compiler:</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="sh">opam update opam switch 4.02.3+buckle-master <span class="tok-nb">eval</span> <span class="tok-sb">`</span>opam config env<span class="tok-sb">`</span></code></pre> </div> </div> <div class="paragraph"> <p>Note that using this approach, the user can also install other OCaml tools easily.</p> </div> </div> </div> </div> <div class="sect1"> <h2 id="_get_started"><a class="anchor" href="#_get_started"></a>Get Started</h2> <div class="sectionbody"> <div class="sect2"> <h3 id="_using_existing_templates_since_1_7_4"><a class="anchor" href="#_using_existing_templates_since_1_7_4"></a>Using existing templates (@since 1.7.4 )</h3> <div class="paragraph"> <p>BuckleScript provide some project templates, to help people get started on board as fast as possible.</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="sh">npm install -g bs-platform <span class="tok-o">&&</span> bsb -init hello <span class="tok-o">&&</span> <span class="tok-nb">cd </span>hello <span class="tok-o">&&</span> npm run build</code></pre> </div> </div> <div class="paragraph"> <p>First, it installs <code>bs-platform</code> globally, then we use the command line tool <code>bsb</code> to set up a sample project named <code>hello</code>, then we run the build.</p> </div> <div class="paragraph"> <p>The output project layout is similar as below</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="sh">hello>tree -d . . <span class="tok-p">|</span>---.vscode ├── lib │ ├── bs │ │ └── src │ └── js │ └── src ├── node_modules │ └── bs-platform -> ... └── src</code></pre> </div> </div> <div class="paragraph"> <p>To enter watch mode, you can run <code>npm run watch</code>, then you can edit <code>src/demo.ml</code> and see it compiled on the fly, and changes are updated on <code>lib/js/src/demo.js</code></p> </div> <div class="paragraph"> <p>If you happen to use VSCode as editor, we provide <code>.vscode/tasks.json</code> as well, type <code>Tasks>build</code>, it will enter watch mode, the great thing is that VSCode comes with a <code>Problems</code> panel which has a much nicer UI.</p> </div> <div class="paragraph"> <p>Currently there are not too many project templates, you can contribute more project templates here <a href="https://github.com/bucklescript/bucklescript/tree/master/jscomp/bsb/templates">here</a>,</p> </div> </div> <div class="sect2"> <h3 id="_first_example_by_hand_without_samples"><a class="anchor" href="#_first_example_by_hand_without_samples"></a>First example by hand without samples</h3> <div class="ulist"> <ul> <li> <p>Create a directory called <code>hello</code> and create <code>bsconfig.json</code> and <code>package.json</code> as below:</p> <div class="listingblock"> <div class="title">bsconfig.json</div> <div class="content"> <pre class="pygments highlight"><code data-lang="js"><span class="tok-p">{</span> <span class="tok-s2">"name"</span> <span class="tok-o">:</span> <span class="tok-s2">"hello"</span><span class="tok-p">,</span> <span class="tok-s2">"sources"</span> <span class="tok-o">:</span> <span class="tok-p">{</span> <span class="tok-s2">"dir"</span> <span class="tok-o">:</span> <span class="tok-s2">"src"</span><span class="tok-p">}</span> <span class="tok-p">}</span></code></pre> </div> </div> <div class="listingblock"> <div class="title">package.json</div> <div class="content"> <pre class="pygments highlight"><code data-lang="js"><span class="tok-p">{</span> <span class="tok-s2">"dependencies"</span><span class="tok-o">:</span> <span class="tok-p">{</span> <span class="tok-s2">"bs-platform"</span><span class="tok-o">:</span> <span class="tok-s2">"1.7.0"</span> <b class="conum">(1)</b> <span class="tok-p">},</span> <span class="tok-s2">"scripts"</span> <span class="tok-o">:</span> <span class="tok-p">{</span> <span class="tok-s2">"build"</span> <span class="tok-o">:</span> <span class="tok-s2">"bsb"</span><span class="tok-p">,</span> <span class="tok-s2">"watch"</span> <span class="tok-o">:</span> <span class="tok-s2">"bsb -w"</span> <b class="conum">(2)</b> <span class="tok-p">}</span> <span class="tok-p">}</span></code></pre> </div> </div> <div class="colist arabic"> <ol> <li> <p>Version should be updated accordingly</p> </li> <li> <p>Watch mode when developing</p> </li> </ol> </div> </li> <li> <p>Create <code>src/main_entry.ml</code> as below:</p> <div class="listingblock"> <div class="title">src/main_entry.ml</div> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">let</span> <span class="tok-bp">()</span> <span class="tok-o">=</span> <span class="tok-n">print_endline</span> <span class="tok-s2">"hello world"</span></code></pre> </div> </div> </li> <li> <p>Build the app</p> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="sh">npm run build</code></pre> </div> </div> </li> </ul> </div> <div class="paragraph"> <p>Now you should see a file called <code>lib/js/src/main_entry.js</code> generated as below:</p> </div> <div class="listingblock"> <div class="title">lib/js/src/main_entry.js</div> <div class="content"> <pre class="pygments highlight"><code data-lang="js"><span class="tok-c1">// GENERATED CODE BY BUCKLESCRIPT VERSION 1.0.1 , PLEASE EDIT WITH CARE</span> <span class="tok-s1">'use strict'</span><span class="tok-p">;</span> <span class="tok-nx">console</span><span class="tok-p">.</span><span class="tok-nx">log</span><span class="tok-p">(</span><span class="tok-s2">"hello world"</span><span class="tok-p">);</span> <span class="tok-cm">/* Not a pure module */</span> <b class="conum">(1)</b></code></pre> </div> </div> <div class="colist arabic"> <ol> <li> <p>The compiler detects this module is impure due to the side effect.</p> </li> </ol> </div> <div class="paragraph"> <p>User can also run <code>watch</code> mode to see changes instantly while editing.</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="sh">npm run watch</code></pre> </div> </div> <div class="admonitionblock tip"> <table> <tr> <td class="icon"> <div class="title">Tip</div> </td> <td class="content"> The working code is available <a href="https://github.com/bucklescript/bucklescript-addons/tree/master/examples/hello">here</a>: </td> </tr> </table> </div> </div> <div class="sect2"> <h3 id="_an_example_with_multiple_modules"><a class="anchor" href="#_an_example_with_multiple_modules"></a>An example with multiple modules</h3> <div class="paragraph"> <p>Now we want to create two modules, one file called <code>fib.ml</code> which exports <code>fib</code> function, the other module called <code>main_entry.ml</code> which will call <code>fib</code>.</p> </div> <div class="ulist"> <ul> <li> <p>Create a directory <code>fib</code> and create files <code>bsconfig.json</code> and <code>package.json</code></p> <div class="listingblock"> <div class="title">bsconfig.json</div> <div class="content"> <pre class="pygments highlight"><code data-lang="js"><span class="tok-p">{</span> <span class="tok-s2">"name"</span> <span class="tok-o">:</span> <span class="tok-s2">"helo"</span><span class="tok-p">,</span> <span class="tok-s2">"sources"</span> <span class="tok-o">:</span> <span class="tok-p">{</span> <span class="tok-s2">"dir"</span> <span class="tok-o">:</span> <span class="tok-s2">"src"</span><span class="tok-p">}</span> <span class="tok-p">}</span></code></pre> </div> </div> <div class="listingblock"> <div class="title">package.json</div> <div class="content"> <pre class="pygments highlight"><code data-lang="js"><span class="tok-p">{</span> <span class="tok-s2">"dependencies"</span><span class="tok-o">:</span> <span class="tok-p">{</span> <span class="tok-s2">"bs-platform"</span><span class="tok-o">:</span> <span class="tok-s2">"1.7.0"</span> <span class="tok-p">},</span> <span class="tok-s2">"scripts"</span> <span class="tok-o">:</span> <span class="tok-p">{</span> <span class="tok-s2">"build"</span> <span class="tok-o">:</span> <span class="tok-s2">"bsb"</span><span class="tok-p">,</span> <span class="tok-s2">"watch"</span> <span class="tok-o">:</span> <span class="tok-s2">"bsb -w"</span> <span class="tok-p">}</span> <span class="tok-p">}</span></code></pre> </div> </div> </li> <li> <p>Create file <code>src/fib.ml</code> and file <code>src/main_entry.ml</code></p> <div class="listingblock"> <div class="title">src/fib.ml</div> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">let</span> <span class="tok-n">fib</span> <span class="tok-n">n</span> <span class="tok-o">=</span> <span class="tok-k">let</span> <span class="tok-k">rec</span> <span class="tok-n">aux</span> <span class="tok-n">n</span> <span class="tok-n">a</span> <span class="tok-n">b</span> <span class="tok-o">=</span> <span class="tok-k">if</span> <span class="tok-n">n</span> <span class="tok-o">=</span> <span class="tok-mi">0</span> <span class="tok-k">then</span> <span class="tok-n">a</span> <span class="tok-k">else</span> <span class="tok-n">aux</span> <span class="tok-o">(</span><span class="tok-n">n</span> <span class="tok-o">-</span> <span class="tok-mi">1</span><span class="tok-o">)</span> <span class="tok-n">b</span> <span class="tok-o">(</span><span class="tok-n">a</span><span class="tok-o">+</span><span class="tok-n">b</span><span class="tok-o">)</span> <span class="tok-k">in</span> <span class="tok-n">aux</span> <span class="tok-n">n</span> <span class="tok-mi">1</span> <span class="tok-mi">1</span></code></pre> </div> </div> <div class="listingblock"> <div class="title">src/main_entry.ml</div> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">let</span> <span class="tok-bp">()</span> <span class="tok-o">=</span> <span class="tok-k">for</span> <span class="tok-n">i</span> <span class="tok-o">=</span> <span class="tok-mi">0</span> <span class="tok-k">to</span> <span class="tok-mi">10</span> <span class="tok-k">do</span> <span class="tok-nn">Js</span><span class="tok-p">.</span><span class="tok-n">log</span> <span class="tok-o">(</span><span class="tok-nn">Fib</span><span class="tok-p">.</span><span class="tok-n">fib</span> <span class="tok-n">i</span><span class="tok-o">)</span> <b class="conum">(1)</b> <span class="tok-k">done</span></code></pre> </div> </div> <div class="colist arabic"> <ol> <li> <p><a href="../api/Js.html"><code>Js</code></a> module is a built-in module shipped with BuckleScript</p> </li> </ol> </div> </li> <li> <p>Build the app</p> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="sh">npm install npm run build node lib/js/src/main_entry.js</code></pre> </div> </div> </li> </ul> </div> <div class="paragraph"> <p>If everything goes well, you should see the output as below:</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="sh">1 1 2 3 5 8 13 21 34 55 89</code></pre> </div> </div> </div> </div> </div> <div class="sect1"> <h2 id="_built_in_npm_support"><a class="anchor" href="#_built_in_npm_support"></a>Built in NPM support</h2> <div class="sectionbody"> <div class="sect2"> <h3 id="_build_an_ocaml_library_as_a_npm_package"><a class="anchor" href="#_build_an_ocaml_library_as_a_npm_package"></a>Build an OCaml library as a npm package</h3> <div class="paragraph"> <p>BuckleScript build system has built in support for NPM packages, please checkout the section about the bsb for NPM support.</p> </div> <div class="admonitionblock note"> <table> <tr> <td class="icon"> <div class="title">Note</div> </td> <td class="content"> <div class="paragraph"> <p>This section covers some basics of how NPM is supported internally, normal users are safe to skip this section.</p> </div> </td> </tr> </table> </div> <div class="paragraph"> <p>BuckleScript extends the OCaml compiler options with several flags to provide a better experience for NPM users.</p> </div> <div class="paragraph"> <p>In general, you are expected to see two kinds of build artifacts, the generated JS files and metadata which your OCaml dependencies rely on.</p> </div> <div class="paragraph"> <p>Since CommonJS has no namespaces, to allow JS files to live in different directories, we have a flag</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="sh">bsc.exe -bs-package-name <span class="tok-nv">$npm_package_name</span> -bs-package-output modulesystem:path/to/your/js/dir -c a.ml</code></pre> </div> </div> <div class="paragraph"> <p>By passing this flag, <code>bsc.exe</code> will store your <code>package_name</code> and relative path to <code>package.json</code> in <code>.cmj</code> files. It will also generate JS files in the directory you specified. You can, and are encouraged to, store JavaScript files in a hierarchical directory.</p> </div> <div class="paragraph"> <p>For the binary artifacts (Note that this is not necessary if you only want your libraries to be consumed by JS developers, and it has benefit since end users don’t need these binary data any more), the convention is to store all <code>*.cm</code> data in a <em>single</em> directory <code>package.json/lib/ocaml</code> and Javascript files in a <em>hierachical</em> directory like <code>package.json/lib/js</code></p> </div> </div> <div class="sect2"> <h3 id="_to_use_ocaml_library_as_a_npm_package"><a class="anchor" href="#_to_use_ocaml_library_as_a_npm_package"></a>To use OCaml library as a npm package</h3> <div class="paragraph"> <p>If you follow the layout convention above, using an OCaml package is pretty straightforward:</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="sh">bsc.exe -I path/to/ocaml/package/installed -c a.ml</code></pre> </div> </div> </div> <div class="sect2"> <h3 id="_together"><a class="anchor" href="#_together"></a>Together</h3> <div class="paragraph"> <p>Your command line would be like this:</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="sh">bsc.exe -I path/to/ocaml/package1/installed -I path/to/ocaml/package2/installed -bs-package-name <span class="tok-nv">$npm_package_name</span> -bs-package-output commonjs:path/to/lib/js/ -c a.ml</code></pre> </div> </div> </div> <div class="sect2"> <h3 id="_examples"><a class="anchor" href="#_examples"></a>Examples</h3> <div class="paragraph"> <p>Please visit <a href="https://github.com/bucklescript/bucklescript-addons" class="bare">https://github.com/bucklescript/bucklescript-addons</a> for more examples.</p> </div> </div> </div> </div> <div class="sect1"> <h2 id="_js_calling_ocaml"><a class="anchor" href="#_js_calling_ocaml"></a>JS Calling OCaml</h2> <div class="sectionbody"> <div class="paragraph"> <p>Since BuckleScript guarantees that all OCaml functions are exported as is, no extra work is required to expose OCaml functions to JavaScript.</p> </div> <div class="admonitionblock caution"> <table> <tr> <td class="icon"> <div class="title">Caution</div> </td> <td class="content"> <div class="ulist"> <ul> <li> <p><code>external</code> exports are not exported as JS functions, if you really want to export those external functions, please write <code>val</code> instead</p> </li> <li> <p><code>operators</code> are escaped, since Javascript does not support user defined operators. For example, instead of calling <code>Pervasives.(^)</code>, you have to call <code>Pervasives.$caret</code> from your JavaScript functions</p> </li> </ul> </div> </td> </tr> </table> </div> <div class="paragraph"> <p>If users want to consume some OCaml features only available in OCaml but not in JS, we recommend users to export it as functions.</p> </div> <div class="paragraph"> <p>For example, data constructors are not available in JS</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"> <span class="tok-k">type</span> <span class="tok-n">t</span> <span class="tok-o">=</span> <span class="tok-o">|</span> <span class="tok-nc">Cons</span> <span class="tok-k">of</span> <span class="tok-kt">int</span> <span class="tok-o">*</span> <span class="tok-n">t</span> <span class="tok-o">|</span> <span class="tok-nc">Nil</span></code></pre> </div> </div> <div class="paragraph"> <p>Currently, we recommend the user expose the constructor as a function so that it can be constructed from the JS side.</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">let</span> <span class="tok-n">cons</span> <span class="tok-n">x</span> <span class="tok-n">y</span> <span class="tok-o">=</span> <span class="tok-nc">Cons</span> <span class="tok-o">(</span><span class="tok-n">x</span><span class="tok-o">,</span><span class="tok-n">y</span><span class="tok-o">)</span> <span class="tok-k">let</span> <span class="tok-n">nil</span> <span class="tok-o">=</span> <span class="tok-nc">Nil</span></code></pre> </div> </div> <div class="admonitionblock note"> <table> <tr> <td class="icon"> <div class="title">Note</div> </td> <td class="content"> <div class="paragraph"> <p>In the future, we will derive these functions to automate this process.</p> </div> </td> </tr> </table> </div> </div> </div> <div class="sect1"> <h2 id="_bucklescript_annotations_for_unicode_and_js_ffi_support"><a class="anchor" href="#_bucklescript_annotations_for_unicode_and_js_ffi_support"></a>BuckleScript annotations for Unicode and JS FFI support</h2> <div class="sectionbody"> <div class="paragraph"> <p>To make OCaml work smoothly with JavaScript, we introduced several extensions to the OCaml language. These BuckleScript extensions facilitate the integration of native JavaScript code and improve the generated code.</p> </div> <div class="sect2"> <h3 id="_unicode_support_since_1_5_1"><a class="anchor" href="#_unicode_support_since_1_5_1"></a>Unicode support (@since 1.5.1)</h3> <div class="admonitionblock warning"> <table> <tr> <td class="icon"> <div class="title">Warning</div> </td> <td class="content"> <div class="paragraph"> <p>In this section, we assume the source is encoded using UTF8.</p> </div> </td> </tr> </table> </div> <div class="paragraph"> <p>In OCaml, string is an immutable byte sequence (like GoLang), so if the user types some Unicode</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-nn">Js</span><span class="tok-p">.</span><span class="tok-n">log</span> <span class="tok-s2">"ä½ å¥½"</span></code></pre> </div> </div> <div class="paragraph"> <p>It will be translated into</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="js"><span class="tok-nx">console</span><span class="tok-p">.</span><span class="tok-nx">log</span><span class="tok-p">(</span><span class="tok-s2">"\xe4\xbd\xa0\xe5\xa5\xbd"</span><span class="tok-p">);</span></code></pre> </div> </div> <div class="paragraph"> <p>Luckily, OCaml allows customized multiple-line string support, BuckleScript <strong>reserves</strong> the delimiter <code>js</code> and <code>j</code>.</p> </div> <div class="listingblock"> <div class="title">Input:</div> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-nn">Js</span><span class="tok-p">.</span><span class="tok-n">log</span> <span class="tok-o">{</span><span class="tok-n">js</span><span class="tok-o">|</span><span class="tok-err">ä½ å¥½ï¼Œ</span> <span class="tok-err">世界</span><span class="tok-o">|</span><span class="tok-n">js</span><span class="tok-o">}</span></code></pre> </div> </div> <div class="listingblock"> <div class="title">Output:</div> <div class="content"> <pre class="pygments highlight"><code data-lang="js"><span class="tok-nx">console</span><span class="tok-p">.</span><span class="tok-nx">log</span><span class="tok-p">(</span><span class="tok-s2">"ä½ å¥½ï¼Œ\n世界"</span><span class="tok-p">);</span></code></pre> </div> </div> <div class="paragraph"> <p>Inside the <code>js</code> delimiter, the escape convention is like JavaScript</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-nn">Js</span><span class="tok-p">.</span><span class="tok-n">log</span> <span class="tok-o">{</span><span class="tok-n">js</span><span class="tok-o">|</span><span class="tok-err">\</span><span class="tok-n">x3f</span><span class="tok-err">\</span><span class="tok-n">u003f</span><span class="tok-err">\</span><span class="tok-n">b</span><span class="tok-err">\</span><span class="tok-n">t</span><span class="tok-err">\</span><span class="tok-n">n</span><span class="tok-err">\</span><span class="tok-n">v</span><span class="tok-err">\</span><span class="tok-n">f</span><span class="tok-err">\</span><span class="tok-n">r</span><span class="tok-err">\</span><span class="tok-mi">0</span><span class="tok-s2">"'|js}</span></code></pre> </div> </div> <div class="listingblock"> <div class="title">Output:</div> <div class="content"> <pre class="pygments highlight"><code data-lang="js"><span class="tok-nx">console</span><span class="tok-p">.</span><span class="tok-nx">log</span><span class="tok-p">(</span><span class="tok-s2">"\x3f\u003f\b\t\n\v\f\r\0\"\'"</span><span class="tok-p">);</span></code></pre> </div> </div> <div class="sect3"> <h4 id="_unicode_support_with_string_interpolation_since_1_7_0"><a class="anchor" href="#_unicode_support_with_string_interpolation_since_1_7_0"></a>Unicode support with string interpolation (@since 1.7.0)</h4> <div class="paragraph"> <p>Like <code>{js||js}</code>, <code>{j||j}</code> not only allow unicode point, but also variable interpolation.</p> </div> <div class="paragraph"> <p>For example</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">let</span> <span class="tok-n">world</span> <span class="tok-o">=</span> <span class="tok-o">{</span><span class="tok-n">j</span><span class="tok-o">|</span><span class="tok-err">世界</span><span class="tok-o">|</span><span class="tok-n">j</span><span class="tok-o">}</span> <span class="tok-k">let</span> <span class="tok-n">hello_world</span> <span class="tok-o">=</span> <span class="tok-o">{</span><span class="tok-n">j</span><span class="tok-o">|</span><span class="tok-err">ä½ å¥½ï¼Œ</span><span class="tok-o">$</span><span class="tok-n">world</span><span class="tok-o">|</span><span class="tok-n">j</span><span class="tok-o">}</span></code></pre> </div> </div> <div class="paragraph"> <p>Users can parenthesize the interpreted variable as below:</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">let</span> <span class="tok-n">hello_world</span> <span class="tok-o">=</span> <span class="tok-o">{</span><span class="tok-n">j</span><span class="tok-o">|</span><span class="tok-err">ä½ å¥½ï¼Œ</span><span class="tok-o">$(</span><span class="tok-n">world</span><span class="tok-o">)|</span><span class="tok-n">j</span><span class="tok-o">}</span></code></pre> </div> </div> <div class="paragraph"> <p>Note the syntax of interpolated variable is intentionally designed to be simple. Its lexical convention is as below:</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="bnf">identifier := leading_identifier_char identifier_chars leading_identifier_char := 'a' .. 'z' | '_' identifier_chars := 'a' .. 'z' | 'A' .. 'Z' | '0' .. '9' | '_' | '\'</code></pre> </div> </div> </div> </div> <div class="sect2"> <h3 id="_ffi"><a class="anchor" href="#_ffi"></a>FFI</h3> <div class="paragraph"> <p>Like TypeScript, when building type-safe bindings from JS to OCaml, users have to write type declarations. In OCaml, unlike TypeScript, users do not need to create a separate <code>.d.ts</code> file, since the type declarations are an integral part of OCaml.</p> </div> <div class="paragraph"> <p>The FFI is divided into several components:</p> </div> <div class="ulist"> <ul> <li> <p>Binding to simple functions and values</p> </li> <li> <p>Binding to higher-order functions</p> </li> <li> <p>Binding to object literals</p> </li> <li> <p>Binding to classes</p> </li> <li> <p>Extensions to the language for debugger, regex, and embedding arbitrary JS code</p> </li> </ul> </div> </div> <div class="sect2"> <h3 id="_binding_to_simple_js_functions_values"><a class="anchor" href="#_binding_to_simple_js_functions_values"></a>Binding to simple JS functions values</h3> <div class="paragraph"> <p>This part is similar to <a href="http://caml.inria.fr/pub/docs/manual-ocaml-4.02/intfc.html">traditional FFI</a>, with syntax as described below:</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">external</span> <span class="tok-k">value</span><span class="tok-o">-</span><span class="tok-n">name</span> <span class="tok-o">:</span> <span class="tok-n">typexpr</span> <span class="tok-o">=</span> <span class="tok-k">external</span><span class="tok-o">-</span><span class="tok-n">declaration</span> <span class="tok-n">attributes</span> <span class="tok-k">external</span><span class="tok-o">-</span><span class="tok-n">declaration</span> <span class="tok-o">:=</span> <span class="tok-kt">string</span><span class="tok-o">-</span><span class="tok-n">literal</span></code></pre> </div> </div> <div class="paragraph"> <p>Users need to declare types for foreign functions (JS functions for BuckleScript or C functions for native compiler) and provide customized <code>attributes</code>.</p> </div> <div class="sect3"> <h4 id="_binding_to_global_value_code_bs_val_code"><a class="anchor" href="#_binding_to_global_value_code_bs_val_code"></a>Binding to global value: <code>bs.val</code></h4> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">external</span> <span class="tok-n">imul</span> <span class="tok-o">:</span> <span class="tok-kt">int</span> <span class="tok-o">-></span> <span class="tok-kt">int</span> <span class="tok-o">-></span> <span class="tok-kt">int</span> <span class="tok-o">=</span> <span class="tok-s2">"Math.imul"</span> <span class="tok-o">[@@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-k">val</span><span class="tok-o">]</span> <span class="tok-k">type</span> <span class="tok-n">dom</span> <span class="tok-c">(* Abstract type for the DOM *)</span> <span class="tok-k">external</span> <span class="tok-n">dom</span> <span class="tok-o">:</span> <span class="tok-n">dom</span> <span class="tok-o">=</span> <span class="tok-s2">"document"</span> <span class="tok-o">[@@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-k">val</span><span class="tok-o">]</span></code></pre> </div> </div> <div class="paragraph"> <p><code>bs.val</code> attribute is used to bind to a JavaScript value, it can be a function or plain value.</p> </div> <div class="admonitionblock note"> <table> <tr> <td class="icon"> <div class="title">Note</div> </td> <td class="content"> <div class="ulist"> <ul> <li> <p>If <code>external-declaration</code> is the same as <code>value-name</code>, the user can leave <code>external-declaration</code> empty. For example:</p> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">external</span> <span class="tok-n">document</span> <span class="tok-o">:</span> <span class="tok-n">dom</span> <span class="tok-o">=</span> <span class="tok-s2">""</span> <span class="tok-o">[@@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-k">val</span><span class="tok-o">]</span></code></pre> </div> </div> </li> <li> <p>If you want to make a single FFI for both C functions and JavaScript functions, you can give the JavaScript foreign function a different name:</p> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">external</span> <span class="tok-n">imul</span> <span class="tok-o">:</span> <span class="tok-kt">int</span> <span class="tok-o">-></span> <span class="tok-kt">int</span> <span class="tok-o">-></span> <span class="tok-kt">int</span> <span class="tok-o">=</span> <span class="tok-s2">"c_imul"</span> <span class="tok-o">[@@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-k">val</span> <span class="tok-s2">"Math.imul"</span><span class="tok-o">]</span></code></pre> </div> </div> </li> </ul> </div> </td> </tr> </table> </div> </div> <div class="sect3"> <h4 id="_scoped_values_code_bs_scope_code_since_1_7_2"><a class="anchor" href="#_scoped_values_code_bs_scope_code_since_1_7_2"></a>Scoped values: <code>bs.scope</code> (@since 1.7.2)</h4> <div class="paragraph"> <p>In JS library, it is quite common to use a name as namespace, for example, if the user want to write a binding to <code>vscode.commands.executeCommand</code>, assume <code>vscode</code> is a module name, the user needs to type <code>commands</code> properly before typing <code>executeCommand</code>, and in practice, it is rarely useful to call <code>vscode.commands</code> alone, for this reason, we introduce a convient sugar: <code>bs.scope</code></p> </div> <div class="listingblock"> <div class="title">Example</div> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">type</span> <span class="tok-n">param</span> <span class="tok-k">external</span> <span class="tok-n">executeCommands</span> <span class="tok-o">:</span> <span class="tok-kt">string</span> <span class="tok-o">-></span> <span class="tok-n">param</span> <span class="tok-kt">array</span> <span class="tok-o">-></span> <span class="tok-kt">unit</span> <span class="tok-o">=</span> <span class="tok-s2">""</span> <span class="tok-o">[@@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">scope</span> <span class="tok-s2">"commands"</span><span class="tok-o">]</span> <span class="tok-o">[@@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-k">module</span> <span class="tok-s2">"vscode"</span><span class="tok-o">][@@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">splice</span><span class="tok-o">]</span> <span class="tok-k">let</span> <span class="tok-n">f</span> <span class="tok-n">a</span> <span class="tok-n">b</span> <span class="tok-n">c</span> <span class="tok-o">=</span> <span class="tok-n">executeCommands</span> <span class="tok-s2">"hi"</span> <span class="tok-o">[|</span><span class="tok-n">a</span><span class="tok-o">;</span><span class="tok-n">b</span><span class="tok-o">;</span><span class="tok-n">c</span><span class="tok-o">|]</span></code></pre> </div> </div> <div class="listingblock"> <div class="title">Output:</div> <div class="content"> <pre class="pygments highlight"><code data-lang="js"><span class="tok-kd">var</span> <span class="tok-nx">Vscode</span> <span class="tok-o">=</span> <span class="tok-nx">require</span><span class="tok-p">(</span><span class="tok-s2">"vscode"</span><span class="tok-p">);</span> <span class="tok-kd">function</span> <span class="tok-nx">f</span><span class="tok-p">(</span><span class="tok-nx">a</span><span class="tok-p">,</span> <span class="tok-nx">b</span><span class="tok-p">,</span> <span class="tok-nx">c</span><span class="tok-p">)</span> <span class="tok-p">{</span> <span class="tok-nx">Vscode</span><span class="tok-p">.</span><span class="tok-nx">commands</span><span class="tok-p">.</span><span class="tok-nx">executeCommands</span><span class="tok-p">(</span><span class="tok-s2">"hi"</span><span class="tok-p">,</span> <span class="tok-nx">a</span><span class="tok-p">,</span> <span class="tok-nx">b</span><span class="tok-p">,</span> <span class="tok-nx">c</span><span class="tok-p">);</span> <span class="tok-k">return</span> <span class="tok-cm">/* () */</span><span class="tok-mi">0</span><span class="tok-p">;</span> <span class="tok-p">}</span></code></pre> </div> </div> <div class="paragraph"> <p>NOTE <code>bs.scope</code> can also be chained as below:</p> </div> <div class="listingblock"> <div class="title">Example</div> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">external</span> <span class="tok-n">makeBuffer</span> <span class="tok-o">:</span> <span class="tok-kt">int</span> <span class="tok-o">-></span> <span class="tok-n">buffer</span> <span class="tok-o">=</span> <span class="tok-s2">"Buffer"</span> <span class="tok-o">[@@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-k">new</span><span class="tok-o">]</span> <span class="tok-o">[@@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">scope</span> <span class="tok-s2">"global"</span><span class="tok-o">]</span> <span class="tok-k">external</span> <span class="tok-n">hi</span> <span class="tok-o">:</span> <span class="tok-kt">string</span> <span class="tok-o">=</span> <span class="tok-s2">""</span> <span class="tok-o">[@@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-k">module</span> <span class="tok-s2">"z"</span><span class="tok-o">]</span> <span class="tok-o">[@@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">scope</span> <span class="tok-s2">"a0"</span><span class="tok-o">,</span> <span class="tok-s2">"a1"</span><span class="tok-o">,</span> <span class="tok-s2">"a2"</span><span class="tok-o">]</span> <span class="tok-k">external</span> <span class="tok-n">ho</span> <span class="tok-o">:</span> <span class="tok-kt">string</span> <span class="tok-o">=</span> <span class="tok-s2">""</span> <span class="tok-o">[@@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-k">val</span><span class="tok-o">]</span> <span class="tok-o">[@@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">scope</span> <span class="tok-s2">"a0"</span><span class="tok-o">,</span><span class="tok-s2">"a1"</span><span class="tok-o">,</span><span class="tok-s2">"a2"</span><span class="tok-o">]</span> <span class="tok-k">external</span> <span class="tok-n">imul</span> <span class="tok-o">:</span> <span class="tok-kt">int</span> <span class="tok-o">-></span> <span class="tok-kt">int</span> <span class="tok-o">-></span> <span class="tok-kt">int</span> <span class="tok-o">=</span> <span class="tok-s2">""</span> <span class="tok-o">[@@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-k">val</span><span class="tok-o">]</span> <span class="tok-o">[@@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">scope</span> <span class="tok-s2">"Math"</span><span class="tok-o">]</span> <span class="tok-k">let</span> <span class="tok-n">f2</span> <span class="tok-bp">()</span> <span class="tok-o">=</span> <span class="tok-n">makeBuffer</span> <span class="tok-mi">20</span> <span class="tok-o">,</span> <span class="tok-n">hi</span> <span class="tok-o">,</span> <span class="tok-n">ho</span><span class="tok-o">,</span> <span class="tok-n">imul</span> <span class="tok-mi">1</span> <span class="tok-mi">2</span></code></pre> </div> </div> <div class="listingblock"> <div class="title">Output:</div> <div class="content"> <pre class="pygments highlight"><code data-lang="js"><span class="tok-kd">var</span> <span class="tok-nx">Z</span> <span class="tok-o">=</span> <span class="tok-nx">require</span><span class="tok-p">(</span><span class="tok-s2">"z"</span><span class="tok-p">);</span> <span class="tok-kd">function</span> <span class="tok-nx">f2</span><span class="tok-p">()</span> <span class="tok-p">{</span> <span class="tok-k">return</span> <span class="tok-cm">/* tuple */</span><span class="tok-p">[</span> <span class="tok-k">new</span> <span class="tok-p">(</span><span class="tok-nx">global</span><span class="tok-p">.</span><span class="tok-nx">Buffer</span><span class="tok-p">)(</span><span class="tok-mi">20</span><span class="tok-p">),</span> <span class="tok-nx">Z</span><span class="tok-p">.</span><span class="tok-nx">a0</span><span class="tok-p">.</span><span class="tok-nx">a1</span><span class="tok-p">.</span><span class="tok-nx">a2</span><span class="tok-p">.</span><span class="tok-nx">hi</span><span class="tok-p">,</span> <span class="tok-nx">a0</span><span class="tok-p">.</span><span class="tok-nx">a1</span><span class="tok-p">.</span><span class="tok-nx">a2</span><span class="tok-p">.</span><span class="tok-nx">ho</span><span class="tok-p">,</span> <span class="tok-nb">Math</span><span class="tok-p">.</span><span class="tok-nx">imul</span><span class="tok-p">(</span><span class="tok-mi">1</span><span class="tok-p">,</span> <span class="tok-mi">2</span><span class="tok-p">)</span> <span class="tok-p">];</span> <span class="tok-p">}</span></code></pre> </div> </div> </div> <div class="sect3"> <h4 id="_binding_to_javascript_constructor_code_bs_new_code"><a class="anchor" href="#_binding_to_javascript_constructor_code_bs_new_code"></a>Binding to JavaScript constructor: <code>bs.new</code></h4> <div class="paragraph"> <p><code>bs.new</code> is used to create a JavaScript object.</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">type</span> <span class="tok-n">t</span> <span class="tok-k">external</span> <span class="tok-n">create_date</span> <span class="tok-o">:</span> <span class="tok-kt">unit</span> <span class="tok-o">-></span> <span class="tok-n">t</span> <span class="tok-o">=</span> <span class="tok-s2">"Date"</span> <span class="tok-o">[@@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-k">new</span><span class="tok-o">]</span> <span class="tok-k">let</span> <span class="tok-n">date</span> <span class="tok-o">=</span> <span class="tok-n">create_date</span> <span class="tok-bp">()</span></code></pre> </div> </div> <div class="listingblock"> <div class="title">Output:</div> <div class="content"> <pre class="pygments highlight"><code data-lang="js"><span class="tok-kd">var</span> <span class="tok-nx">date</span> <span class="tok-o">=</span> <span class="tok-k">new</span> <span class="tok-nb">Date</span><span class="tok-p">();</span></code></pre> </div> </div> </div> <div class="sect3"> <h4 id="_binding_to_a_value_from_a_module_code_bs_module_code"><a class="anchor" href="#_binding_to_a_value_from_a_module_code_bs_module_code"></a>Binding to a value from a module: <code>bs.module</code></h4> <div class="listingblock"> <div class="title">Input:</div> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">external</span> <span class="tok-n">add</span> <span class="tok-o">:</span> <span class="tok-kt">int</span> <span class="tok-o">-></span> <span class="tok-kt">int</span> <span class="tok-o">-></span> <span class="tok-kt">int</span> <span class="tok-o">=</span> <span class="tok-s2">"add"</span> <span class="tok-o">[@@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-k">module</span> <span class="tok-s2">"x"</span><span class="tok-o">]</span> <span class="tok-k">external</span> <span class="tok-n">add2</span> <span class="tok-o">:</span> <span class="tok-kt">int</span> <span class="tok-o">-></span> <span class="tok-kt">int</span> <span class="tok-o">-></span> <span class="tok-kt">int</span> <span class="tok-o">=</span> <span class="tok-s2">"add2"</span><span class="tok-o">[@@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-k">module</span> <span class="tok-s2">"y"</span><span class="tok-o">,</span> <span class="tok-s2">"U"</span><span class="tok-o">]</span> <b class="conum">(1)</b> <span class="tok-k">let</span> <span class="tok-n">f</span> <span class="tok-o">=</span> <span class="tok-n">add</span> <span class="tok-mi">3</span> <span class="tok-mi">4</span> <span class="tok-k">let</span> <span class="tok-n">g</span> <span class="tok-o">=</span> <span class="tok-n">add2</span> <span class="tok-mi">3</span> <span class="tok-mi">4</span></code></pre> </div> </div> <div class="colist arabic"> <ol> <li> <p><code>"U"</code> will hint the compiler to generate a better name for the module, see output</p> </li> </ol> </div> <div class="listingblock"> <div class="title">Output:</div> <div class="content"> <pre class="pygments highlight"><code data-lang="js"><span class="tok-kd">var</span> <span class="tok-nx">U</span> <span class="tok-o">=</span> <span class="tok-nx">require</span><span class="tok-p">(</span><span class="tok-s2">"y"</span><span class="tok-p">);</span> <span class="tok-kd">var</span> <span class="tok-nx">X</span> <span class="tok-o">=</span> <span class="tok-nx">require</span><span class="tok-p">(</span><span class="tok-s2">"x"</span><span class="tok-p">);</span> <span class="tok-kd">var</span> <span class="tok-nx">f</span> <span class="tok-o">=</span> <span class="tok-nx">X</span><span class="tok-p">.</span><span class="tok-nx">add</span><span class="tok-p">(</span><span class="tok-mi">3</span><span class="tok-p">,</span> <span class="tok-mi">4</span><span class="tok-p">);</span> <span class="tok-kd">var</span> <span class="tok-nx">g</span> <span class="tok-o">=</span> <span class="tok-nx">U</span><span class="tok-p">.</span><span class="tok-nx">add2</span><span class="tok-p">(</span><span class="tok-mi">3</span><span class="tok-p">,</span> <span class="tok-mi">4</span><span class="tok-p">);</span></code></pre> </div> </div> <div class="admonitionblock note"> <table> <tr> <td class="icon"> <div class="title">Note</div> </td> <td class="content"> <div class="ulist"> <ul> <li> <p>if <code>external-declaration</code> is the same as <code>value-name</code>, it can be left empty, for example,</p> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">external</span> <span class="tok-n">add</span> <span class="tok-o">:</span> <span class="tok-kt">int</span> <span class="tok-o">-></span> <span class="tok-kt">int</span> <span class="tok-o">-></span> <span class="tok-kt">int</span> <span class="tok-o">=</span> <span class="tok-s2">""</span> <span class="tok-o">[@@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-k">module</span> <span class="tok-s2">"x"</span><span class="tok-o">]</span></code></pre> </div> </div> </li> </ul> </div> </td> </tr> </table> </div> </div> <div class="sect3"> <h4 id="_binding_the_whole_module_as_a_value_or_function"><a class="anchor" href="#_binding_the_whole_module_as_a_value_or_function"></a>Binding the whole module as a value or function</h4> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">type</span> <span class="tok-n">http</span> <span class="tok-k">external</span> <span class="tok-n">http</span> <span class="tok-o">:</span> <span class="tok-n">http</span> <span class="tok-o">=</span> <span class="tok-s2">"http"</span> <span class="tok-o">[@@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-k">module</span><span class="tok-o">]</span> <b class="conum">(1)</b></code></pre> </div> </div> <div class="colist arabic"> <ol> <li> <p><code>external-declaration</code> is the module name</p> </li> </ol> </div> <div class="admonitionblock note"> <table> <tr> <td class="icon"> <div class="title">Note</div> </td> <td class="content"> <div class="ulist"> <ul> <li> <p>if <code>external-declaration</code> is the same as <code>value-name</code>, it can be left empty, for example:</p> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">external</span> <span class="tok-n">http</span> <span class="tok-o">:</span> <span class="tok-n">http</span> <span class="tok-o">=</span> <span class="tok-s2">""</span> <span class="tok-o">[@@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-k">module</span><span class="tok-o">]</span></code></pre> </div> </div> </li> </ul> </div> </td> </tr> </table> </div> </div> <div class="sect3"> <h4 id="_binding_to_method_code_bs_send_code_code_bs_send_pipe_code"><a class="anchor" href="#_binding_to_method_code_bs_send_code_code_bs_send_pipe_code"></a>Binding to method: <code>bs.send</code>, <code>bs.send.pipe</code></h4> <div class="paragraph"> <p><code>bs.send</code> helps the user send a message to a JS object.</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">type</span> <span class="tok-n">id</span> <span class="tok-c">(** Abstract type for id object *)</span> <span class="tok-k">external</span> <span class="tok-n">get_by_id</span> <span class="tok-o">:</span> <span class="tok-n">dom</span> <span class="tok-o">-></span> <span class="tok-kt">string</span> <span class="tok-o">-></span> <span class="tok-n">id</span> <span class="tok-o">=</span> <span class="tok-s2">"getElementById"</span> <span class="tok-o">[@@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">send</span><span class="tok-o">]</span></code></pre> </div> </div> <div class="paragraph"> <p>The object is always the first argument and actual arguments follow.</p> </div> <div class="listingblock"> <div class="title">Input:</div> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-n">get_by_id</span> <span class="tok-n">dom</span> <span class="tok-s2">"xx"</span></code></pre> </div> </div> <div class="listingblock"> <div class="title">Output:</div> <div class="content"> <pre class="pygments highlight"><code data-lang="js"><span class="tok-nb">document</span><span class="tok-p">.</span><span class="tok-nx">getElementById</span><span class="tok-p">(</span><span class="tok-s2">"xx"</span><span class="tok-p">);</span></code></pre> </div> </div> <div class="paragraph"> <p><code>bs.send.pipe</code> is similar to <code>bs.send</code> except that the first argument, i.e, the object, is put in the position of last argument to help user write in a <em>chaining style</em>:</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">external</span> <span class="tok-n">map</span> <span class="tok-o">:</span> <span class="tok-o">(</span><span class="tok-k">'</span><span class="tok-n">a</span> <span class="tok-o">-></span> <span class="tok-k">'</span><span class="tok-n">b</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">])</span> <span class="tok-o">-></span> <span class="tok-k">'</span><span class="tok-n">b</span> <span class="tok-kt">array</span> <span class="tok-o">=</span> <span class="tok-s2">""</span> <span class="tok-o">[@@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">send</span><span class="tok-o">.</span><span class="tok-n">pipe</span><span class="tok-o">:</span> <span class="tok-k">'</span><span class="tok-n">a</span> <span class="tok-kt">array</span><span class="tok-o">]</span> <b class="conum">(1)</b> <span class="tok-k">external</span> <span class="tok-n">forEach</span><span class="tok-o">:</span> <span class="tok-o">(</span><span class="tok-k">'</span><span class="tok-n">a</span> <span class="tok-o">-></span> <span class="tok-kt">unit</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">])</span> <span class="tok-o">-></span> <span class="tok-k">'</span><span class="tok-n">a</span> <span class="tok-kt">array</span> <span class="tok-o">=</span> <span class="tok-s2">""</span> <span class="tok-o">[@@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">send</span><span class="tok-o">.</span><span class="tok-n">pipe</span><span class="tok-o">:</span> <span class="tok-k">'</span><span class="tok-n">a</span> <span class="tok-kt">array</span><span class="tok-o">]</span> <span class="tok-k">let</span> <span class="tok-n">test</span> <span class="tok-n">arr</span> <span class="tok-o">=</span> <span class="tok-n">arr</span> <span class="tok-o">|></span> <span class="tok-n">map</span> <span class="tok-o">(</span><span class="tok-k">fun</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">]</span> <span class="tok-n">x</span> <span class="tok-o">-></span> <span class="tok-n">x</span> <span class="tok-o">+</span> <span class="tok-mi">1</span><span class="tok-o">)</span> <span class="tok-o">|></span> <span class="tok-n">forEach</span> <span class="tok-o">(</span><span class="tok-k">fun</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">]</span> <span class="tok-n">x</span> <span class="tok-o">-></span> <span class="tok-nn">Js</span><span class="tok-p">.</span><span class="tok-n">log</span> <span class="tok-n">x</span><span class="tok-o">)</span></code></pre> </div> </div> <div class="colist arabic"> <ol> <li> <p>For the <code>[@bs]</code> attribute in the callback, see <a href="#_binding_to_callbacks_higher_order_function">Binding to callbacks (higher-order function)</a></p> </li> </ol> </div> <div class="admonitionblock note"> <table> <tr> <td class="icon"> <div class="title">Note</div> </td> <td class="content"> <div class="ulist"> <ul> <li> <p>if <code>external-declaration</code> is the same as <code>value-name</code>, it can be left empty, for example:</p> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">external</span> <span class="tok-n">getElementById</span> <span class="tok-o">:</span> <span class="tok-n">dom</span> <span class="tok-o">-></span> <span class="tok-kt">string</span> <span class="tok-o">-></span> <span class="tok-n">id</span> <span class="tok-o">=</span> <span class="tok-s2">""</span> <span class="tok-o">[@@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">send</span><span class="tok-o">]</span></code></pre> </div> </div> </li> </ul> </div> </td> </tr> </table> </div> </div> <div class="sect3"> <h4 id="_binding_to_dynamic_key_access_set_code_bs_set_index_code_code_bs_get_index_code"><a class="anchor" href="#_binding_to_dynamic_key_access_set_code_bs_set_index_code_code_bs_get_index_code"></a>Binding to dynamic key access/set: <code>bs.set_index</code>, <code>bs.get_index</code></h4> <div class="paragraph"> <p>This attribute allows dynamic access to a JavaScript property</p> </div> <div class="listingblock"> <div class="title">Input:</div> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">type</span> <span class="tok-n">t</span> <span class="tok-k">external</span> <span class="tok-n">create</span> <span class="tok-o">:</span> <span class="tok-kt">int</span> <span class="tok-o">-></span> <span class="tok-n">t</span> <span class="tok-o">=</span> <span class="tok-s2">"Int32Array"</span> <span class="tok-o">[@@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-k">new</span><span class="tok-o">]</span> <span class="tok-k">external</span> <span class="tok-n">get</span> <span class="tok-o">:</span> <span class="tok-n">t</span> <span class="tok-o">-></span> <span class="tok-kt">int</span> <span class="tok-o">-></span> <span class="tok-kt">int</span> <span class="tok-o">=</span> <span class="tok-s2">""</span> <span class="tok-o">[@@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">get_index</span><span class="tok-o">]</span> <span class="tok-k">external</span> <span class="tok-n">set</span> <span class="tok-o">:</span> <span class="tok-n">t</span> <span class="tok-o">-></span> <span class="tok-kt">int</span> <span class="tok-o">-></span> <span class="tok-kt">int</span> <span class="tok-o">-></span> <span class="tok-kt">unit</span> <span class="tok-o">=</span> <span class="tok-s2">""</span> <span class="tok-o">[@@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">set_index</span><span class="tok-o">]</span> <span class="tok-k">let</span> <span class="tok-o">_</span> <span class="tok-o">=</span> <span class="tok-k">let</span> <span class="tok-n">i32arr</span> <span class="tok-o">=</span> <span class="tok-o">(</span><span class="tok-n">create</span> <span class="tok-mi">3</span><span class="tok-o">)</span> <span class="tok-k">in</span> <span class="tok-n">set</span> <span class="tok-n">i32arr</span> <span class="tok-mi">0</span> <span class="tok-mi">42</span><span class="tok-o">;</span> <span class="tok-nn">Js</span><span class="tok-p">.</span><span class="tok-n">log</span> <span class="tok-o">(</span><span class="tok-n">get</span> <span class="tok-n">i32arr</span> <span class="tok-mi">0</span><span class="tok-o">)</span></code></pre> </div> </div> <div class="listingblock"> <div class="title">Output:</div> <div class="content"> <pre class="pygments highlight"><code data-lang="js"><span class="tok-kd">var</span> <span class="tok-nx">i32arr</span> <span class="tok-o">=</span> <span class="tok-k">new</span> <span class="tok-nx">Int32Array</span><span class="tok-p">(</span><span class="tok-mi">3</span><span class="tok-p">);</span> <span class="tok-nx">i32arr</span><span class="tok-p">[</span><span class="tok-mi">0</span><span class="tok-p">]</span> <span class="tok-o">=</span> <span class="tok-mi">42</span><span class="tok-p">;</span> <span class="tok-nx">console</span><span class="tok-p">.</span><span class="tok-nx">log</span><span class="tok-p">(</span><span class="tok-nx">i32arr</span><span class="tok-p">[</span><span class="tok-mi">0</span><span class="tok-p">]);</span></code></pre> </div> </div> </div> <div class="sect3"> <h4 id="_binding_to_getter_setter_code_bs_get_code_code_bs_set_code"><a class="anchor" href="#_binding_to_getter_setter_code_bs_get_code_code_bs_set_code"></a>Binding to Getter/Setter: <code>bs.get</code>, <code>bs.set</code></h4> <div class="paragraph"> <p>This attribute helps get and set the property of a JavaScript object.</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">type</span> <span class="tok-n">textarea</span> <span class="tok-k">external</span> <span class="tok-n">set_name</span> <span class="tok-o">:</span> <span class="tok-n">textarea</span> <span class="tok-o">-></span> <span class="tok-kt">string</span> <span class="tok-o">-></span> <span class="tok-kt">unit</span> <span class="tok-o">=</span> <span class="tok-s2">"name"</span> <span class="tok-o">[@@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">set</span><span class="tok-o">]</span> <span class="tok-k">external</span> <span class="tok-n">get_name</span> <span class="tok-o">:</span> <span class="tok-n">textarea</span> <span class="tok-o">-></span> <span class="tok-kt">string</span> <span class="tok-o">=</span> <span class="tok-s2">"name"</span> <span class="tok-o">[@@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">get</span><span class="tok-o">]</span></code></pre> </div> </div> </div> </div> <div class="sect2"> <h3 id="_splice_calling_convention_code_bs_splice_code"><a class="anchor" href="#_splice_calling_convention_code_bs_splice_code"></a>Splice calling convention: <code>bs.splice</code></h3> <div class="paragraph"> <p>In JS, it is quite common to have a function take variadic arguments. BuckleScript supports typing homogeneous variadic arguments. For example,</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">external</span> <span class="tok-n">join</span> <span class="tok-o">:</span> <span class="tok-kt">string</span> <span class="tok-kt">array</span> <span class="tok-o">-></span> <span class="tok-kt">string</span> <span class="tok-o">=</span> <span class="tok-s2">""</span> <span class="tok-o">[@@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-k">module</span> <span class="tok-s2">"path"</span><span class="tok-o">]</span> <span class="tok-o">[@@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">splice</span><span class="tok-o">]</span> <span class="tok-k">let</span> <span class="tok-n">v</span> <span class="tok-o">=</span> <span class="tok-n">join</span> <span class="tok-o">[|</span> <span class="tok-s2">"a"</span><span class="tok-o">;</span> <span class="tok-s2">"b"</span><span class="tok-o">|]</span></code></pre> </div> </div> <div class="listingblock"> <div class="title">Output:</div> <div class="content"> <pre class="pygments highlight"><code data-lang="js"><span class="tok-kd">var</span> <span class="tok-nx">Path</span> <span class="tok-o">=</span> <span class="tok-nx">require</span><span class="tok-p">(</span><span class="tok-s2">"path"</span><span class="tok-p">);</span> <span class="tok-kd">var</span> <span class="tok-nx">v</span> <span class="tok-o">=</span> <span class="tok-nx">Path</span><span class="tok-p">.</span><span class="tok-nx">join</span><span class="tok-p">(</span><span class="tok-s2">"a"</span><span class="tok-p">,</span><span class="tok-s2">"b"</span><span class="tok-p">);</span></code></pre> </div> </div> <div class="admonitionblock note"> <table> <tr> <td class="icon"> <div class="title">Note</div> </td> <td class="content"> <div class="paragraph"> <p>For the external call, if the <code>array</code> arguments is not a compile time array, the compiler will emit an error message.</p> </div> </td> </tr> </table> </div> </div> <div class="sect2"> <h3 id="_special_types_on_external_declarations_code_bs_string_code_code_bs_int_code_code_bs_ignore_code_code_bs_as_code_code_bs_unwrap_code"><a class="anchor" href="#_special_types_on_external_declarations_code_bs_string_code_code_bs_int_code_code_bs_ignore_code_code_bs_as_code_code_bs_unwrap_code"></a>Special types on external declarations: <code>bs.string</code>, <code>bs.int</code>, <code>bs.ignore</code>, <code>bs.as</code>, <code>bs.unwrap</code></h3> <div class="sect3"> <h4 id="_using_polymorphic_variant_to_model_enums_and_string_types"><a class="anchor" href="#_using_polymorphic_variant_to_model_enums_and_string_types"></a>Using polymorphic variant to model enums and string types</h4> <div class="paragraph"> <p>There are several patterns heavily used in existing JavaScript codebases, for example, the string type is used a lot. BuckleScript FFI allows the user to model string type in a safe way by using annotated polymorphic variant.</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">external</span> <span class="tok-n">readFileSync</span> <span class="tok-o">:</span> <span class="tok-n">name</span><span class="tok-o">:</span><span class="tok-kt">string</span> <span class="tok-o">-></span> <span class="tok-o">([</span> <span class="tok-o">`</span><span class="tok-n">utf8</span> <span class="tok-o">|</span> <span class="tok-o">`</span><span class="tok-n">my_name</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-k">as</span> <span class="tok-s2">"ascii"</span><span class="tok-o">]</span> <b class="conum">(1)</b> <span class="tok-o">]</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-kt">string</span><span class="tok-o">])</span> <span class="tok-o">-></span> <span class="tok-kt">string</span> <span class="tok-o">=</span> <span class="tok-s2">""</span> <span class="tok-o">[@@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-k">module</span> <span class="tok-s2">"fs"</span><span class="tok-o">]</span> <span class="tok-k">let</span> <span class="tok-o">_</span> <span class="tok-o">=</span> <span class="tok-n">readFileSync</span> <span class="tok-o">~</span><span class="tok-n">name</span><span class="tok-o">:</span><span class="tok-s2">"xx.txt"</span> <span class="tok-o">`</span><span class="tok-n">my_name</span></code></pre> </div> </div> <div class="colist arabic"> <ol> <li> <p>Here we intentionally made an example to show how to customize a name</p> </li> </ol> </div> <div class="listingblock"> <div class="title">Output:</div> <div class="content"> <pre class="pygments highlight"><code data-lang="js"><span class="tok-kd">var</span> <span class="tok-nx">Fs</span> <span class="tok-o">=</span> <span class="tok-nx">require</span><span class="tok-p">(</span><span class="tok-s2">"fs"</span><span class="tok-p">);</span> <span class="tok-nx">Fs</span><span class="tok-p">.</span><span class="tok-nx">readFileSync</span><span class="tok-p">(</span><span class="tok-s2">"xx.txt"</span><span class="tok-p">,</span> <span class="tok-s2">"ascii"</span><span class="tok-p">);</span></code></pre> </div> </div> <div class="paragraph"> <p>Polymorphic variants can also be used to model <em>enums</em>.</p> </div> <div class="listingblock"> <div class="title">Input:</div> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">external</span> <span class="tok-n">test_int_type</span> <span class="tok-o">:</span> <span class="tok-o">([</span> <span class="tok-o">`</span><span class="tok-n">on_closed</span> <span class="tok-o">|</span> <span class="tok-o">`</span><span class="tok-n">on_open</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-k">as</span> <span class="tok-mi">3</span><span class="tok-o">]</span> <b class="conum">(2)</b> <span class="tok-o">|</span> <span class="tok-o">`</span><span class="tok-n">in_bin</span> <b class="conum">(3)</b> <span class="tok-o">]</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-kt">int</span><span class="tok-o">])</span> <span class="tok-o">-></span> <span class="tok-kt">int</span> <span class="tok-o">=</span> <span class="tok-s2">""</span> <span class="tok-o">[@@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-k">val</span><span class="tok-o">]</span> <span class="tok-k">let</span> <span class="tok-o">_</span> <span class="tok-o">=</span> <span class="tok-n">test_int_type</span> <span class="tok-o">`</span><span class="tok-n">in_bin</span></code></pre> </div> </div> <div class="colist arabic"> <ol> <li> <p><em>`on_closed</em> will be encoded as 0</p> </li> <li> <p><em>`on_open</em> will be 3 due to the attribute <code>bs.as</code></p> </li> <li> <p><em>`in_bin</em> will be 4</p> </li> </ol> </div> <div class="listingblock"> <div class="title">Output:</div> <div class="content"> <pre class="pygments highlight"><code data-lang="js"><span class="tok-nx">test_int_type</span><span class="tok-p">(</span><span class="tok-mi">4</span><span class="tok-p">);</span></code></pre> </div> </div> </div> <div class="sect3"> <h4 id="_using_polymorphic_variant_to_model_event_listener"><a class="anchor" href="#_using_polymorphic_variant_to_model_event_listener"></a>Using polymorphic variant to model event listener</h4> <div class="paragraph"> <p>BuckleScript models this in a type-safe way by using annotated polymorphic variants.</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">type</span> <span class="tok-n">readline</span> <span class="tok-k">external</span> <span class="tok-n">on</span> <span class="tok-o">:</span> <span class="tok-o">(</span> <span class="tok-o">[</span> <span class="tok-o">`</span><span class="tok-n">close</span> <span class="tok-k">of</span> <span class="tok-kt">unit</span> <span class="tok-o">-></span> <span class="tok-kt">unit</span> <span class="tok-o">|</span> <span class="tok-o">`</span><span class="tok-n">line</span> <span class="tok-k">of</span> <span class="tok-kt">string</span> <span class="tok-o">-></span> <span class="tok-kt">unit</span> <span class="tok-o">]</span> <b class="conum">(1)</b> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-kt">string</span><span class="tok-o">])</span> <span class="tok-o">-></span> <span class="tok-n">readline</span> <span class="tok-o">=</span> <span class="tok-s2">""</span> <span class="tok-o">[@@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">send</span><span class="tok-o">.</span><span class="tok-n">pipe</span><span class="tok-o">:</span> <span class="tok-n">readline</span><span class="tok-o">]</span> <span class="tok-k">let</span> <span class="tok-n">register</span> <span class="tok-n">rl</span> <span class="tok-o">=</span> <span class="tok-n">rl</span> <span class="tok-o">|></span> <span class="tok-n">on</span> <span class="tok-o">(`</span><span class="tok-n">close</span> <span class="tok-o">(</span><span class="tok-k">fun</span> <span class="tok-n">event</span> <span class="tok-o">-></span> <span class="tok-bp">()</span> <span class="tok-o">))</span> <span class="tok-o">|></span> <span class="tok-n">on</span> <span class="tok-o">(`</span><span class="tok-n">line</span> <span class="tok-o">(</span><span class="tok-k">fun</span> <span class="tok-n">line</span> <span class="tok-o">-></span> <span class="tok-n">print_endline</span> <span class="tok-n">line</span><span class="tok-o">))</span></code></pre> </div> </div> <div class="colist arabic"> <ol> <li> <p>This is a very powerful typing: each event can have its own <em>different types</em>.</p> </li> </ol> </div> <div class="listingblock"> <div class="title">Output:</div> <div class="content"> <pre class="pygments highlight"><code data-lang="js"><span class="tok-kd">function</span> <span class="tok-nx">register</span><span class="tok-p">(</span><span class="tok-nx">rl</span><span class="tok-p">)</span> <span class="tok-p">{</span> <span class="tok-k">return</span> <span class="tok-nx">rl</span><span class="tok-p">.</span><span class="tok-nx">on</span><span class="tok-p">(</span><span class="tok-s2">"close"</span><span class="tok-p">,</span> <span class="tok-kd">function</span> <span class="tok-p">()</span> <span class="tok-p">{</span> <span class="tok-k">return</span> <span class="tok-cm">/* () */</span><span class="tok-mi">0</span><span class="tok-p">;</span> <span class="tok-p">})</span> <span class="tok-p">.</span><span class="tok-nx">on</span><span class="tok-p">(</span><span class="tok-s2">"line"</span><span class="tok-p">,</span> <span class="tok-kd">function</span> <span class="tok-p">(</span><span class="tok-nx">line</span><span class="tok-p">)</span> <span class="tok-p">{</span> <span class="tok-nx">console</span><span class="tok-p">.</span><span class="tok-nx">log</span><span class="tok-p">(</span><span class="tok-nx">line</span><span class="tok-p">);</span> <span class="tok-k">return</span> <span class="tok-cm">/* () */</span><span class="tok-mi">0</span><span class="tok-p">;</span> <span class="tok-p">});</span> <span class="tok-p">}</span></code></pre> </div> </div> </div> <div class="sect3"> <h4 id="_using_polymorphic_variant_to_model_arguments_of_multiple_possible_types_since_1_8_3"><a class="anchor" href="#_using_polymorphic_variant_to_model_arguments_of_multiple_possible_types_since_1_8_3"></a>Using polymorphic variant to model arguments of multiple possible types (@since 1.8.3)</h4> <div class="paragraph"> <p>Sometimes a JavaScript function will accept an argument that could have different types depending upon how it’s used.</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="js"><span class="tok-kd">function</span> <span class="tok-nx">padLeft</span><span class="tok-p">(</span><span class="tok-nx">string</span><span class="tok-p">,</span> <span class="tok-nx">padding</span><span class="tok-p">)</span> <span class="tok-p">{</span> <span class="tok-k">if</span> <span class="tok-p">(</span><span class="tok-k">typeof</span> <span class="tok-nx">padding</span> <span class="tok-o">===</span> <span class="tok-s2">"number"</span><span class="tok-p">)</span> <span class="tok-p">{</span> <span class="tok-k">return</span> <span class="tok-nb">Array</span><span class="tok-p">(</span><span class="tok-nx">padding</span> <span class="tok-o">+</span> <span class="tok-mi">1</span><span class="tok-p">).</span><span class="tok-nx">join</span><span class="tok-p">(</span><span class="tok-s2">" "</span><span class="tok-p">)</span> <span class="tok-o">+</span> <span class="tok-nx">value</span><span class="tok-p">;</span> <span class="tok-p">}</span> <span class="tok-k">if</span> <span class="tok-p">(</span><span class="tok-k">typeof</span> <span class="tok-nx">padding</span> <span class="tok-o">===</span> <span class="tok-s2">"string"</span><span class="tok-p">)</span> <span class="tok-p">{</span> <span class="tok-k">return</span> <span class="tok-nx">padding</span> <span class="tok-o">+</span> <span class="tok-nx">value</span><span class="tok-p">;</span> <span class="tok-p">}</span> <span class="tok-k">throw</span> <span class="tok-k">new</span> <span class="tok-nb">Error</span><span class="tok-p">(</span><span class="tok-err">`</span><span class="tok-nx">Expected</span> <span class="tok-nx">string</span> <span class="tok-nx">or</span> <span class="tok-nx">number</span><span class="tok-p">,</span> <span class="tok-nx">got</span> <span class="tok-s1">'${padding}'</span><span class="tok-p">.</span><span class="tok-err">`</span><span class="tok-p">);</span> <span class="tok-p">}</span></code></pre> </div> </div> <div class="paragraph"> <p>You can model such a function in BuckleScript using <code>[@bs.unwrap]</code>.</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">external</span> <span class="tok-n">padLeft</span> <span class="tok-o">:</span> <span class="tok-kt">string</span> <span class="tok-o">-></span> <span class="tok-o">([</span> <span class="tok-o">`</span><span class="tok-nc">String</span> <span class="tok-k">of</span> <span class="tok-kt">string</span> <span class="tok-o">|</span> <span class="tok-o">`</span><span class="tok-nc">Int</span> <span class="tok-k">of</span> <span class="tok-kt">int</span> <span class="tok-o">]</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">unwrap</span><span class="tok-o">])</span> <span class="tok-o">-></span> <span class="tok-kt">string</span> <span class="tok-o">=</span> <span class="tok-s2">""</span> <span class="tok-o">[@@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-k">val</span><span class="tok-o">]</span></code></pre> </div> </div> <div class="paragraph"> <p>Polymorphic variants with <code>[@bs.unwrap]</code> will "unwrap" the variant at the call site so that the JavaScript function is called with the underlying value.</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">let</span> <span class="tok-o">_</span> <span class="tok-o">=</span> <span class="tok-n">padLeft</span> <span class="tok-s2">"Hello World"</span> <span class="tok-o">(`</span><span class="tok-nc">Int</span> <span class="tok-mi">4</span><span class="tok-o">)</span> <span class="tok-k">let</span> <span class="tok-o">_</span> <span class="tok-o">=</span> <span class="tok-n">padLeft</span> <span class="tok-s2">"Hello World"</span> <span class="tok-o">(`</span><span class="tok-nc">String</span> <span class="tok-s2">"bs: "</span><span class="tok-o">)</span></code></pre> </div> </div> <div class="paragraph"> <p>Output:</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="js"><span class="tok-nx">padLeft</span><span class="tok-p">(</span><span class="tok-s2">"Hello World"</span><span class="tok-p">,</span> <span class="tok-mi">4</span><span class="tok-p">);</span> <span class="tok-nx">padLeft</span><span class="tok-p">(</span><span class="tok-s2">"Hello World"</span><span class="tok-p">,</span> <span class="tok-s2">"bs: "</span><span class="tok-p">);</span></code></pre> </div> </div> <div class="admonitionblock warning"> <table> <tr> <td class="icon"> <div class="title">Warning</div> </td> <td class="content"> <div class="ulist"> <ul> <li> <p>These <code>[@bs.string]</code>, <code>[@bs.int]</code>, and <code>[@bs.unwrap]</code> annotations will only have effect in <code>external</code> declarations.</p> </li> <li> <p>The runtime encoding of using polymorphic variant is internal to the compiler.</p> </li> <li> <p>With these annotations mentioned above, BuckleScript will automatically transform the internal encoding to the designated encoding for FFI. BuckleScript will try to do such conversion at compile time if it can, otherwise, it will do such conversion in the runtime, but it should be always correct.</p> </li> </ul> </div> </td> </tr> </table> </div> </div> <div class="sect3"> <h4 id="_phantom_arguments_and_ad_hoc_polymorphism"><a class="anchor" href="#_phantom_arguments_and_ad_hoc_polymorphism"></a>Phantom Arguments and ad-hoc polymorphism</h4> <div class="paragraph"> <p><code>bs.ignore</code> allows arguments to be erased after passing to JS functional call, the side effect will still be recorded.</p> </div> <div class="paragraph"> <p>For example,</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">external</span> <span class="tok-n">add</span> <span class="tok-o">:</span> <span class="tok-o">(</span><span class="tok-kt">int</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">ignore</span><span class="tok-o">])</span> <span class="tok-o">-></span> <span class="tok-kt">int</span> <span class="tok-o">-></span> <span class="tok-kt">int</span> <span class="tok-o">-></span> <span class="tok-kt">int</span> <span class="tok-o">=</span> <span class="tok-s2">""</span> <span class="tok-o">[@@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-k">val</span><span class="tok-o">]</span> <span class="tok-k">let</span> <span class="tok-n">v</span> <span class="tok-o">=</span> <span class="tok-n">add</span> <span class="tok-mi">0</span> <span class="tok-mi">1</span> <span class="tok-mi">2</span> <b class="conum">(1)</b></code></pre> </div> </div> <div class="colist arabic"> <ol> <li> <p>the first argument will be erased</p> </li> </ol> </div> <div class="listingblock"> <div class="title">Output:</div> <div class="content"> <pre class="pygments highlight"><code data-lang="javascript"><span class="tok-kd">var</span> <span class="tok-nx">v</span> <span class="tok-o">=</span> <span class="tok-nx">add</span> <span class="tok-p">(</span><span class="tok-mi">1</span><span class="tok-p">,</span><span class="tok-mi">2</span><span class="tok-p">);</span></code></pre> </div> </div> <div class="paragraph"> <p>This is very useful to combine GADT:</p> </div> <div class="listingblock"> <div class="title">Input</div> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">type</span> <span class="tok-o">_</span> <span class="tok-n">kind</span> <span class="tok-o">=</span> <span class="tok-o">|</span> <span class="tok-nc">Float</span> <span class="tok-o">:</span> <span class="tok-kt">float</span> <span class="tok-n">kind</span> <span class="tok-o">|</span> <span class="tok-nc">String</span> <span class="tok-o">:</span> <span class="tok-kt">string</span> <span class="tok-n">kind</span> <span class="tok-k">external</span> <span class="tok-n">add</span> <span class="tok-o">:</span> <span class="tok-o">(</span><span class="tok-k">'</span><span class="tok-n">a</span> <span class="tok-n">kind</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">ignore</span><span class="tok-o">])</span> <span class="tok-o">-></span> <span class="tok-k">'</span><span class="tok-n">a</span> <span class="tok-o">-></span> <span class="tok-k">'</span><span class="tok-n">a</span> <span class="tok-o">-></span> <span class="tok-k">'</span><span class="tok-n">a</span> <span class="tok-o">=</span> <span class="tok-s2">""</span> <span class="tok-o">[@@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-k">val</span><span class="tok-o">]</span> <span class="tok-k">let</span> <span class="tok-bp">()</span> <span class="tok-o">=</span> <span class="tok-nn">Js</span><span class="tok-p">.</span><span class="tok-n">log</span> <span class="tok-o">(</span><span class="tok-n">add</span> <span class="tok-nc">Float</span> <span class="tok-mi">3</span><span class="tok-o">.</span><span class="tok-mi">0</span> <span class="tok-mi">2</span><span class="tok-o">.</span><span class="tok-mi">0</span><span class="tok-o">);</span> <span class="tok-nn">Js</span><span class="tok-p">.</span><span class="tok-n">log</span> <span class="tok-o">(</span><span class="tok-n">add</span> <span class="tok-nc">String</span> <span class="tok-s2">"x"</span> <span class="tok-s2">"y"</span><span class="tok-o">);</span></code></pre> </div> </div> <div class="listingblock"> <div class="title">Output</div> <div class="content"> <pre class="pygments highlight"><code data-lang="js"><span class="tok-nx">console</span><span class="tok-p">.</span><span class="tok-nx">log</span><span class="tok-p">(</span><span class="tok-nx">add</span><span class="tok-p">(</span><span class="tok-mf">3.0</span><span class="tok-p">,</span> <span class="tok-mf">2.0</span><span class="tok-p">));</span> <span class="tok-nx">console</span><span class="tok-p">.</span><span class="tok-nx">log</span><span class="tok-p">(</span><span class="tok-nx">add</span><span class="tok-p">(</span><span class="tok-s2">"x"</span><span class="tok-p">,</span> <span class="tok-s2">"y"</span><span class="tok-p">));</span></code></pre> </div> </div> <div class="paragraph"> <p>User can also have a payload for the GADT:</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">let</span> <span class="tok-n">string_of_kind</span> <span class="tok-o">(</span><span class="tok-k">type</span> <span class="tok-n">t</span><span class="tok-o">)</span> <span class="tok-o">(</span><span class="tok-n">kind</span> <span class="tok-o">:</span> <span class="tok-n">t</span> <span class="tok-n">kind</span><span class="tok-o">)</span> <span class="tok-o">=</span> <span class="tok-k">match</span> <span class="tok-n">kind</span> <span class="tok-k">with</span> <span class="tok-o">|</span> <span class="tok-nc">Float</span> <span class="tok-o">-></span> <span class="tok-s2">"float"</span> <span class="tok-o">|</span> <span class="tok-nc">String</span> <span class="tok-o">-></span> <span class="tok-s2">"string"</span> <span class="tok-k">external</span> <span class="tok-n">add_dyn</span> <span class="tok-o">:</span> <span class="tok-o">(</span><span class="tok-k">'</span><span class="tok-n">a</span> <span class="tok-n">kind</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">ignore</span><span class="tok-o">])</span> <span class="tok-o">-></span> <span class="tok-kt">string</span> <span class="tok-o">-></span> <span class="tok-k">'</span><span class="tok-n">a</span> <span class="tok-o">-></span> <span class="tok-k">'</span><span class="tok-n">a</span> <span class="tok-o">-></span> <span class="tok-k">'</span><span class="tok-n">a</span> <span class="tok-o">=</span> <span class="tok-s2">""</span> <span class="tok-o">[@@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-k">val</span><span class="tok-o">]</span> <span class="tok-k">let</span> <span class="tok-n">add2</span> <span class="tok-n">k</span> <span class="tok-n">x</span> <span class="tok-n">y</span> <span class="tok-o">=</span> <span class="tok-n">add_dyn</span> <span class="tok-n">k</span> <span class="tok-o">(</span><span class="tok-n">string_of_kind</span> <span class="tok-n">k</span><span class="tok-o">)</span> <span class="tok-n">x</span> <span class="tok-n">y</span></code></pre> </div> </div> <div class="admonitionblock note"> <table> <tr> <td class="icon"> <div class="title">Note</div> </td> <td class="content"> <div class="paragraph"> <p>Using a GADT as a <code>[@bs.ignore]</code> argument as described to achieve a single polymorphic argument can now also be accomplished with <code>[@bs.unwrap]</code> above. The GADT + <code>[@bs.ignore]</code> approach is slightly more flexible and is always guaranteed to have no runtime overhead, where <code>[@bs.unwrap]</code> could incur slight runtime overhead in some cases but could be a more intuitive API for end users.</p> </div> </td> </tr> </table> </div> </div> <div class="sect3"> <h4 id="_fixed_arguments"><a class="anchor" href="#_fixed_arguments"></a>Fixed Arguments</h4> <div class="paragraph"> <p>Contrary to the Phantom arguments, <code>_ [@bs.as]</code> is introduced to attach constant data.</p> </div> <div class="paragraph"> <p>For example:</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">external</span> <span class="tok-n">process_on_exit</span> <span class="tok-o">:</span> <span class="tok-o">(_</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-k">as</span> <span class="tok-s2">"exit"</span><span class="tok-o">])</span> <span class="tok-o">-></span> <span class="tok-o">(</span><span class="tok-kt">int</span> <span class="tok-o">-></span> <span class="tok-kt">unit</span><span class="tok-o">)</span> <span class="tok-o">-></span> <span class="tok-kt">unit</span> <span class="tok-o">=</span> <span class="tok-s2">"process.on"</span> <span class="tok-o">[@@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-k">val</span><span class="tok-o">]</span> <span class="tok-k">let</span> <span class="tok-bp">()</span> <span class="tok-o">=</span> <span class="tok-n">process_on_exit</span> <span class="tok-o">(</span><span class="tok-k">fun</span> <span class="tok-n">exit_code</span> <span class="tok-o">-></span> <span class="tok-nn">Js</span><span class="tok-p">.</span><span class="tok-n">log</span><span class="tok-o">(</span> <span class="tok-s2">"error code: "</span> <span class="tok-o">^</span> <span class="tok-n">string_of_int</span> <span class="tok-n">exit_code</span> <span class="tok-o">))</span></code></pre> </div> </div> <div class="listingblock"> <div class="title">Output:</div> <div class="content"> <pre class="pygments highlight"><code data-lang="js"><span class="tok-nx">process</span><span class="tok-p">.</span><span class="tok-nx">on</span><span class="tok-p">(</span><span class="tok-s2">"exit"</span><span class="tok-p">,</span> <span class="tok-kd">function</span> <span class="tok-p">(</span><span class="tok-nx">exit_code</span><span class="tok-p">)</span> <span class="tok-p">{</span> <span class="tok-nx">console</span><span class="tok-p">.</span><span class="tok-nx">log</span><span class="tok-p">(</span><span class="tok-s2">"error code: "</span> <span class="tok-o">+</span> <span class="tok-nx">exit_code</span><span class="tok-p">);</span> <span class="tok-k">return</span> <span class="tok-cm">/* () */</span><span class="tok-mi">0</span><span class="tok-p">;</span> <span class="tok-p">});</span></code></pre> </div> </div> <div class="paragraph"> <p>It can also be used in combination with other attributes, for example:</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">type</span> <span class="tok-n">process</span> <span class="tok-k">external</span> <span class="tok-n">on_exit</span> <span class="tok-o">:</span> <span class="tok-o">(_</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-k">as</span> <span class="tok-s2">"exit"</span><span class="tok-o">])</span> <span class="tok-o">-></span> <span class="tok-o">(</span><span class="tok-kt">int</span> <span class="tok-o">-></span> <span class="tok-kt">unit</span><span class="tok-o">)</span> <span class="tok-o">-></span> <span class="tok-n">process</span> <span class="tok-o">=</span> <span class="tok-s2">"on"</span> <span class="tok-o">[@@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">send</span><span class="tok-o">.</span><span class="tok-n">pipe</span><span class="tok-o">:</span> <span class="tok-n">process</span><span class="tok-o">]</span> <span class="tok-k">let</span> <span class="tok-n">register</span> <span class="tok-o">(</span><span class="tok-n">p</span> <span class="tok-o">:</span> <span class="tok-n">process</span><span class="tok-o">)</span> <span class="tok-o">=</span> <span class="tok-n">p</span> <span class="tok-o">|></span> <span class="tok-n">on_exit</span> <span class="tok-o">(</span><span class="tok-k">fun</span> <span class="tok-n">i</span> <span class="tok-o">-></span> <span class="tok-nn">Js</span><span class="tok-p">.</span><span class="tok-n">log</span> <span class="tok-n">i</span><span class="tok-o">)</span></code></pre> </div> </div> <div class="listingblock"> <div class="title">Output:</div> <div class="content"> <pre class="pygments highlight"><code data-lang="js"><span class="tok-kd">function</span> <span class="tok-nx">register</span><span class="tok-p">(</span><span class="tok-nx">p</span><span class="tok-p">)</span> <span class="tok-p">{</span> <span class="tok-k">return</span> <span class="tok-nx">p</span><span class="tok-p">.</span><span class="tok-nx">on</span><span class="tok-p">(</span><span class="tok-s2">"exit"</span><span class="tok-p">,</span> <span class="tok-p">(</span><span class="tok-kd">function</span> <span class="tok-p">(</span><span class="tok-nx">i</span><span class="tok-p">)</span> <span class="tok-p">{</span> <span class="tok-nx">console</span><span class="tok-p">.</span><span class="tok-nx">log</span><span class="tok-p">(</span><span class="tok-nx">i</span><span class="tok-p">);</span> <span class="tok-k">return</span> <span class="tok-cm">/* () */</span><span class="tok-mi">0</span><span class="tok-p">;</span> <span class="tok-p">}));</span> <span class="tok-p">}</span></code></pre> </div> </div> <div class="listingblock"> <div class="title">Input:</div> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">external</span> <span class="tok-n">io_config</span> <span class="tok-o">:</span> <span class="tok-n">stdio</span><span class="tok-o">:(_</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-k">as</span> <span class="tok-s2">"inherit"</span><span class="tok-o">])</span> <span class="tok-o">-></span> <span class="tok-n">cwd</span><span class="tok-o">:</span><span class="tok-kt">string</span> <span class="tok-o">-></span> <span class="tok-kt">unit</span> <span class="tok-o">-></span> <span class="tok-o">_</span> <span class="tok-o">=</span> <span class="tok-s2">""</span> <span class="tok-o">[@@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">obj</span><span class="tok-o">]</span> <span class="tok-k">let</span> <span class="tok-n">config</span> <span class="tok-o">=</span> <span class="tok-n">io_config</span> <span class="tok-o">~</span><span class="tok-n">cwd</span><span class="tok-o">:</span><span class="tok-s2">"."</span> <span class="tok-bp">()</span></code></pre> </div> </div> <div class="listingblock"> <div class="title">Output:</div> <div class="content"> <pre class="pygments highlight"><code data-lang="js"><span class="tok-kd">var</span> <span class="tok-nx">config</span> <span class="tok-o">=</span> <span class="tok-p">{</span> <span class="tok-nx">stdio</span><span class="tok-o">:</span> <span class="tok-s2">"inherit"</span><span class="tok-p">,</span> <span class="tok-nx">cwd</span><span class="tok-o">:</span> <span class="tok-s2">"."</span> <span class="tok-p">};</span></code></pre> </div> </div> </div> <div class="sect3"> <h4 id="_fixed_arguments_with_arbitrary_json_literal_since_1_7_0"><a class="anchor" href="#_fixed_arguments_with_arbitrary_json_literal_since_1_7_0"></a>Fixed Arguments with arbitrary JSON literal (@since 1.7.0)</h4> <div class="paragraph"> <p>So the payload can be more flexiblie with JSON literal support</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">type</span> <span class="tok-n">t</span> <span class="tok-k">external</span> <span class="tok-n">x</span><span class="tok-o">:</span> <span class="tok-n">t</span> <span class="tok-o">=</span> <span class="tok-s2">""</span> <span class="tok-o">[@@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-k">val</span><span class="tok-o">]</span> <span class="tok-k">external</span> <span class="tok-n">on_exit_slice5</span> <span class="tok-o">:</span> <span class="tok-kt">int</span> <span class="tok-o">-></span> <span class="tok-o">(_</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-k">as</span> <span class="tok-mi">3</span><span class="tok-o">])</span> <span class="tok-o">-></span> <span class="tok-o">(_</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-k">as</span> <span class="tok-o">{</span><span class="tok-n">json</span><span class="tok-o">|</span><span class="tok-bp">true</span><span class="tok-o">|</span><span class="tok-n">json</span><span class="tok-o">}])</span> <span class="tok-o">-></span> <span class="tok-o">(_</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-k">as</span> <span class="tok-o">{</span><span class="tok-n">json</span><span class="tok-o">|</span><span class="tok-bp">false</span><span class="tok-o">|</span><span class="tok-n">json</span><span class="tok-o">}])</span> <span class="tok-o">-></span> <span class="tok-o">(_</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-k">as</span> <span class="tok-o">{</span><span class="tok-n">json</span><span class="tok-o">|</span><span class="tok-s2">"ä½ å¥½"</span><span class="tok-o">|</span><span class="tok-n">json</span><span class="tok-o">}])</span> <span class="tok-o">-></span> <span class="tok-o">(_</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-k">as</span> <span class="tok-o">{</span><span class="tok-n">json</span><span class="tok-o">|</span> <span class="tok-o">[</span><span class="tok-s2">"ä½ å¥½"</span><span class="tok-o">,</span><span class="tok-mi">1</span><span class="tok-o">,</span><span class="tok-mi">2</span><span class="tok-o">,</span><span class="tok-mi">3</span><span class="tok-o">]</span> <span class="tok-o">|</span><span class="tok-n">json</span><span class="tok-o">}])</span> <span class="tok-o">-></span> <span class="tok-o">(_</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-k">as</span> <span class="tok-o">{</span><span class="tok-n">json</span><span class="tok-o">|</span> <span class="tok-o">[{</span> <span class="tok-s2">"arr"</span> <span class="tok-o">:</span> <span class="tok-o">[</span><span class="tok-s2">"ä½ å¥½"</span><span class="tok-o">,</span><span class="tok-mi">1</span><span class="tok-o">,</span><span class="tok-mi">2</span><span class="tok-o">,</span><span class="tok-mi">3</span><span class="tok-o">],</span> <span class="tok-s2">"encoding"</span> <span class="tok-o">:</span> <span class="tok-s2">"utf8"</span><span class="tok-o">}]</span> <span class="tok-o">|</span><span class="tok-n">json</span><span class="tok-o">}])</span> <span class="tok-o">-></span> <span class="tok-o">(_</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-k">as</span> <span class="tok-o">{</span><span class="tok-n">json</span><span class="tok-o">|</span> <span class="tok-o">[{</span> <span class="tok-s2">"arr"</span> <span class="tok-o">:</span> <span class="tok-o">[</span><span class="tok-s2">"ä½ å¥½"</span><span class="tok-o">,</span><span class="tok-mi">1</span><span class="tok-o">,</span><span class="tok-mi">2</span><span class="tok-o">,</span><span class="tok-mi">3</span><span class="tok-o">],</span> <span class="tok-s2">"encoding"</span> <span class="tok-o">:</span> <span class="tok-s2">"utf8"</span><span class="tok-o">}]</span> <span class="tok-o">|</span><span class="tok-n">json</span><span class="tok-o">}])</span> <span class="tok-o">-></span> <span class="tok-o">(_</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-k">as</span> <span class="tok-s2">"xxx"</span><span class="tok-o">])</span> <span class="tok-o">-></span> <span class="tok-o">([`</span><span class="tok-n">a</span><span class="tok-o">|`</span><span class="tok-n">b</span><span class="tok-o">|`</span><span class="tok-n">c</span><span class="tok-o">]</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-kt">int</span><span class="tok-o">])</span> <span class="tok-o">-></span> <span class="tok-o">(_</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-k">as</span> <span class="tok-s2">"yyy"</span><span class="tok-o">])</span> <span class="tok-o">-></span> <span class="tok-o">([`</span><span class="tok-n">a</span><span class="tok-o">|`</span><span class="tok-n">b</span><span class="tok-o">|`</span><span class="tok-n">c</span><span class="tok-o">]</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-kt">string</span><span class="tok-o">])</span> <span class="tok-o">-></span> <span class="tok-kt">int</span> <span class="tok-kt">array</span> <span class="tok-o">-></span> <span class="tok-kt">unit</span> <span class="tok-o">=</span> <span class="tok-s2">"xx"</span> <span class="tok-o">[@@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">send</span><span class="tok-o">.</span><span class="tok-n">pipe</span><span class="tok-o">:</span> <span class="tok-n">t</span><span class="tok-o">]</span> <span class="tok-o">[@@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">splice</span><span class="tok-o">]</span> <span class="tok-k">let</span> <span class="tok-o">_</span> <span class="tok-o">=</span> <span class="tok-n">x</span> <span class="tok-o">|></span> <span class="tok-n">on_exit_slice5</span> <span class="tok-o">__</span><span class="tok-n">LINE__</span> <span class="tok-o">`</span><span class="tok-n">a</span> <span class="tok-o">`</span><span class="tok-n">b</span> <span class="tok-o">[|</span><span class="tok-mi">1</span><span class="tok-o">;</span><span class="tok-mi">2</span><span class="tok-o">;</span><span class="tok-mi">3</span><span class="tok-o">;</span><span class="tok-mi">4</span><span class="tok-o">;</span><span class="tok-mi">5</span><span class="tok-o">|]</span></code></pre> </div> </div> <div class="listingblock"> <div class="title">Output:</div> <div class="content"> <pre class="pygments highlight"><code data-lang="js"><span class="tok-nx">x</span><span class="tok-p">.</span><span class="tok-nx">xx</span><span class="tok-p">(</span><span class="tok-mi">114</span><span class="tok-p">,</span> <span class="tok-mi">3</span><span class="tok-p">,</span> <span class="tok-kc">true</span><span class="tok-p">,</span> <span class="tok-kc">false</span><span class="tok-p">,</span> <span class="tok-p">(</span><span class="tok-s2">"ä½ å¥½"</span><span class="tok-p">),</span> <span class="tok-p">(</span> <span class="tok-p">[</span><span class="tok-s2">"ä½ å¥½"</span><span class="tok-p">,</span><span class="tok-mi">1</span><span class="tok-p">,</span><span class="tok-mi">2</span><span class="tok-p">,</span><span class="tok-mi">3</span><span class="tok-p">]</span> <span class="tok-p">),</span> <span class="tok-p">(</span> <span class="tok-p">[{</span> <span class="tok-s2">"arr"</span> <span class="tok-o">:</span> <span class="tok-p">[</span><span class="tok-s2">"ä½ å¥½"</span><span class="tok-p">,</span><span class="tok-mi">1</span><span class="tok-p">,</span><span class="tok-mi">2</span><span class="tok-p">,</span><span class="tok-mi">3</span><span class="tok-p">],</span> <span class="tok-s2">"encoding"</span> <span class="tok-o">:</span> <span class="tok-s2">"utf8"</span><span class="tok-p">}]</span> <span class="tok-p">),</span> <span class="tok-p">(</span> <span class="tok-p">[{</span> <span class="tok-s2">"arr"</span> <span class="tok-o">:</span> <span class="tok-p">[</span><span class="tok-s2">"ä½ å¥½"</span><span class="tok-p">,</span><span class="tok-mi">1</span><span class="tok-p">,</span><span class="tok-mi">2</span><span class="tok-p">,</span><span class="tok-mi">3</span><span class="tok-p">],</span> <span class="tok-s2">"encoding"</span> <span class="tok-o">:</span> <span class="tok-s2">"utf8"</span><span class="tok-p">}]</span> <span class="tok-p">),</span> <span class="tok-s2">"xxx"</span><span class="tok-p">,</span> <span class="tok-mi">0</span><span class="tok-p">,</span> <span class="tok-s2">"yyy"</span><span class="tok-p">,</span> <span class="tok-s2">"b"</span><span class="tok-p">,</span> <span class="tok-mi">1</span><span class="tok-p">,</span> <span class="tok-mi">2</span><span class="tok-p">,</span> <span class="tok-mi">3</span><span class="tok-p">,</span> <span class="tok-mi">4</span><span class="tok-p">,</span> <span class="tok-mi">5</span><span class="tok-p">)</span></code></pre> </div> </div> </div> </div> <div class="sect2"> <h3 id="_binding_to_nodejs_special_variables_a_href_api_node_html_bs_node_a"><a class="anchor" href="#_binding_to_nodejs_special_variables_a_href_api_node_html_bs_node_a"></a>Binding to NodeJS special variables: <a href="../api/Node.html">bs.node</a></h3> <div class="paragraph"> <p>NodeJS has several file local variables: <code><em>dirname</code>, <code></em>filename</code>, <code>_module</code>, and <code>require</code>. Their semantics are more like macros instead of functions.</p> </div> <div class="paragraph"> <p>BuckleScript provides built-in macro support for these variables:</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">let</span> <span class="tok-n">dirname</span> <span class="tok-o">:</span> <span class="tok-kt">string</span> <span class="tok-n">option</span> <span class="tok-o">=</span> <span class="tok-o">[%</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">node</span> <span class="tok-o">__</span><span class="tok-n">dirname</span><span class="tok-o">]</span> <span class="tok-k">let</span> <span class="tok-n">filename</span> <span class="tok-o">:</span> <span class="tok-kt">string</span> <span class="tok-n">option</span> <span class="tok-o">=</span> <span class="tok-o">[%</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">node</span> <span class="tok-o">__</span><span class="tok-n">filename</span><span class="tok-o">]</span> <span class="tok-k">let</span> <span class="tok-o">_</span><span class="tok-n">module</span> <span class="tok-o">:</span> <span class="tok-nn">Node</span><span class="tok-p">.</span><span class="tok-n">node_module</span> <span class="tok-n">option</span> <span class="tok-o">=</span> <span class="tok-o">[%</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">node</span> <span class="tok-o">_</span><span class="tok-n">module</span><span class="tok-o">]</span> <span class="tok-k">let</span> <span class="tok-n">require</span> <span class="tok-o">:</span> <span class="tok-nn">Node</span><span class="tok-p">.</span><span class="tok-n">node_require</span> <span class="tok-n">option</span> <span class="tok-o">=</span> <span class="tok-o">[%</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">node</span> <span class="tok-n">require</span><span class="tok-o">]</span></code></pre> </div> </div> </div> <div class="sect2"> <h3 id="_binding_to_callbacks_higher_order_function"><a class="anchor" href="#_binding_to_callbacks_higher_order_function"></a>Binding to callbacks (higher-order function)</h3> <div class="paragraph"> <p>Higher order functions are functions where the callback can be another function. For example, suppose JS has a map function as below:</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="js"><span class="tok-kd">function</span> <span class="tok-nx">map</span> <span class="tok-p">(</span><span class="tok-nx">a</span><span class="tok-p">,</span> <span class="tok-nx">b</span><span class="tok-p">,</span> <span class="tok-nx">f</span><span class="tok-p">){</span> <span class="tok-kd">var</span> <span class="tok-nx">i</span> <span class="tok-o">=</span> <span class="tok-nb">Math</span><span class="tok-p">.</span><span class="tok-nx">min</span><span class="tok-p">(</span><span class="tok-nx">a</span><span class="tok-p">.</span><span class="tok-nx">length</span><span class="tok-p">,</span> <span class="tok-nx">b</span><span class="tok-p">.</span><span class="tok-nx">length</span><span class="tok-p">);</span> <span class="tok-kd">var</span> <span class="tok-nx">c</span> <span class="tok-o">=</span> <span class="tok-k">new</span> <span class="tok-nb">Array</span><span class="tok-p">(</span><span class="tok-nx">i</span><span class="tok-p">);</span> <span class="tok-k">for</span><span class="tok-p">(</span><span class="tok-kd">var</span> <span class="tok-nx">j</span> <span class="tok-o">=</span> <span class="tok-mi">0</span><span class="tok-p">;</span> <span class="tok-nx">j</span> <span class="tok-o"><</span> <span class="tok-nx">i</span><span class="tok-p">;</span> <span class="tok-o">++</span><span class="tok-nx">j</span><span class="tok-p">){</span> <span class="tok-nx">c</span><span class="tok-p">[</span><span class="tok-nx">j</span><span class="tok-p">]</span> <span class="tok-o">=</span> <span class="tok-nx">f</span><span class="tok-p">(</span><span class="tok-nx">a</span><span class="tok-p">[</span><span class="tok-nx">i</span><span class="tok-p">],</span><span class="tok-nx">b</span><span class="tok-p">[</span><span class="tok-nx">i</span><span class="tok-p">])</span> <span class="tok-p">}</span> <span class="tok-k">return</span> <span class="tok-nx">c</span> <span class="tok-p">;</span> <span class="tok-p">}</span></code></pre> </div> </div> <div class="paragraph"> <p>A <strong>naive</strong> external type declaration would be as below:</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">external</span> <span class="tok-n">map</span> <span class="tok-o">:</span> <span class="tok-k">'</span><span class="tok-n">a</span> <span class="tok-kt">array</span> <span class="tok-o">-></span> <span class="tok-k">'</span><span class="tok-n">b</span> <span class="tok-kt">array</span> <span class="tok-o">-></span> <span class="tok-o">(</span><span class="tok-k">'</span><span class="tok-n">a</span> <span class="tok-o">-></span> <span class="tok-k">'</span><span class="tok-n">b</span> <span class="tok-o">-></span> <span class="tok-k">'</span><span class="tok-n">c</span><span class="tok-o">)</span> <span class="tok-o">-></span> <span class="tok-k">'</span><span class="tok-n">c</span> <span class="tok-kt">array</span> <span class="tok-o">=</span> <span class="tok-s2">""</span> <span class="tok-o">[@@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-k">val</span><span class="tok-o">]</span></code></pre> </div> </div> <div class="paragraph"> <p>Unfortunately, this is not completely correct. The issue is by reading the type <code>'a → 'b → 'c</code>, it can be in several cases:</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">let</span> <span class="tok-n">f</span> <span class="tok-n">x</span> <span class="tok-n">y</span> <span class="tok-o">=</span> <span class="tok-n">x</span> <span class="tok-o">+</span> <span class="tok-n">y</span></code></pre> </div> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">let</span> <span class="tok-n">g</span> <span class="tok-n">x</span> <span class="tok-o">=</span> <span class="tok-k">let</span> <span class="tok-n">z</span> <span class="tok-o">=</span> <span class="tok-n">x</span> <span class="tok-o">+</span> <span class="tok-mi">1</span> <span class="tok-k">in</span> <span class="tok-k">fun</span> <span class="tok-n">y</span> <span class="tok-o">-></span> <span class="tok-n">x</span> <span class="tok-o">+</span> <span class="tok-n">z</span></code></pre> </div> </div> <div class="paragraph"> <p>In OCaml they all have the same type; however, <code>f</code> and <code>g</code> may be compiled into functions with different arities.</p> </div> <div class="paragraph"> <p>A naive compilation will compile <code>f</code> as below:</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">let</span> <span class="tok-n">f</span> <span class="tok-o">=</span> <span class="tok-k">fun</span> <span class="tok-n">x</span> <span class="tok-o">-></span> <span class="tok-k">fun</span> <span class="tok-n">y</span> <span class="tok-o">-></span> <span class="tok-n">x</span> <span class="tok-o">+</span> <span class="tok-n">y</span></code></pre> </div> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="js"><span class="tok-kd">function</span> <span class="tok-nx">f</span><span class="tok-p">(</span><span class="tok-nx">x</span><span class="tok-p">){</span> <span class="tok-k">return</span> <span class="tok-kd">function</span> <span class="tok-p">(</span><span class="tok-nx">y</span><span class="tok-p">){</span> <span class="tok-k">return</span> <span class="tok-nx">x</span> <span class="tok-o">+</span> <span class="tok-nx">y</span><span class="tok-p">;</span> <span class="tok-p">}</span> <span class="tok-p">}</span> <span class="tok-kd">function</span> <span class="tok-nx">g</span><span class="tok-p">(</span><span class="tok-nx">x</span><span class="tok-p">){</span> <span class="tok-kd">var</span> <span class="tok-nx">z</span> <span class="tok-o">=</span> <span class="tok-nx">x</span> <span class="tok-o">+</span> <span class="tok-mi">1</span> <span class="tok-p">;</span> <span class="tok-k">return</span> <span class="tok-kd">function</span> <span class="tok-p">(</span><span class="tok-nx">y</span><span class="tok-p">){</span> <span class="tok-k">return</span> <span class="tok-nx">x</span> <span class="tok-o">+</span> <span class="tok-nx">z</span> <span class="tok-p">;</span> <span class="tok-p">}</span> <span class="tok-p">}</span></code></pre> </div> </div> <div class="paragraph"> <p>Its arity will be <em>consistent</em> but is <em>1</em> (returning another function); however, we expect <em>its arity to be 2</em>.</p> </div> <div class="paragraph"> <p>Bucklescript uses a more complex compilation strategy, compiling <code>f</code> as</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="js"><span class="tok-kd">function</span> <span class="tok-nx">f</span><span class="tok-p">(</span><span class="tok-nx">x</span><span class="tok-p">,</span><span class="tok-nx">y</span><span class="tok-p">){</span> <span class="tok-k">return</span> <span class="tok-nx">x</span> <span class="tok-o">+</span> <span class="tok-nx">y</span> <span class="tok-p">;</span> <span class="tok-p">}</span></code></pre> </div> </div> <div class="paragraph"> <p>No matter which strategy we use, existing typing rules <strong>cannot guarantee a function of type <code>'a → 'b → 'c</code> will have arity 2.</strong></p> </div> <div class="sect3"> <h4 id="__code_bs_code_for_explicit_uncurried_callback"><a class="anchor" href="#__code_bs_code_for_explicit_uncurried_callback"></a><code>[@bs]</code> for explicit uncurried callback</h4> <div class="paragraph"> <p>To solve this problem introduced by OCaml’s curried calling convention, we support a special attribute <code>[@bs]</code> at the type level.</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">external</span> <span class="tok-n">map</span> <span class="tok-o">:</span> <span class="tok-k">'</span><span class="tok-n">a</span> <span class="tok-kt">array</span> <span class="tok-o">-></span> <span class="tok-k">'</span><span class="tok-n">b</span> <span class="tok-kt">array</span> <span class="tok-o">-></span> <span class="tok-o">(</span><span class="tok-k">'</span><span class="tok-n">a</span> <span class="tok-o">-></span> <span class="tok-k">'</span><span class="tok-n">b</span> <span class="tok-o">-></span> <span class="tok-k">'</span><span class="tok-n">c</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">])</span> <span class="tok-o">-></span> <span class="tok-k">'</span><span class="tok-n">c</span> <span class="tok-kt">array</span> <span class="tok-o">=</span> <span class="tok-s2">"map"</span> <span class="tok-o">[@@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-k">val</span><span class="tok-o">]</span></code></pre> </div> </div> <div class="paragraph"> <p>Here <code>('a → 'b → 'c [@bs])</code> will <em>always be of arity 2</em>, in general, <code>'a0 → 'a1 …​ 'aN → 'b0 [@bs]</code> is the same as <code>'a0 → 'a1 …​ 'aN → 'b0</code> except the former’s arity is guaranteed to be <code>N</code> while the latter is unknown.</p> </div> <div class="paragraph"> <p>To produce a function of type <code>'a0 → .. 'aN → 'b0 [@bs]</code>, as follows:</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">let</span> <span class="tok-n">f</span> <span class="tok-o">:</span> <span class="tok-k">'</span><span class="tok-n">a0</span> <span class="tok-o">-></span> <span class="tok-k">'</span><span class="tok-n">a1</span> <span class="tok-o">-></span> <span class="tok-o">..</span> <span class="tok-k">'</span><span class="tok-n">b0</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">]</span> <span class="tok-o">=</span> <span class="tok-k">fun</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">]</span> <span class="tok-n">a0</span> <span class="tok-n">a1</span> <span class="tok-o">..</span> <span class="tok-n">aN</span> <span class="tok-o">-></span> <span class="tok-n">b0</span> <span class="tok-k">let</span> <span class="tok-n">b</span> <span class="tok-o">:</span> <span class="tok-k">'</span><span class="tok-n">b0</span> <span class="tok-o">=</span> <span class="tok-n">f</span> <span class="tok-n">a0</span> <span class="tok-n">a1</span> <span class="tok-n">a2</span> <span class="tok-o">..</span> <span class="tok-n">aN</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">]</span></code></pre> </div> </div> <div class="paragraph"> <p>A special case for arity of 0:</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">let</span> <span class="tok-n">f</span> <span class="tok-o">:</span> <span class="tok-kt">unit</span> <span class="tok-o">-></span> <span class="tok-k">'</span><span class="tok-n">b0</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">]</span> <span class="tok-o">=</span> <span class="tok-k">fun</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">]</span> <span class="tok-bp">()</span> <span class="tok-o">-></span> <span class="tok-n">b0</span> <span class="tok-k">let</span> <span class="tok-n">b</span> <span class="tok-o">:</span> <span class="tok-k">'</span><span class="tok-n">b0</span> <span class="tok-o">=</span> <span class="tok-n">f</span> <span class="tok-bp">()</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">]</span></code></pre> </div> </div> <div class="paragraph"> <p>Note that this extension to the OCaml language is <em>sound</em>. If you add an attribute in one place but miss it in other place, the type checker will complain.</p> </div> <div class="paragraph"> <p>Another more complex example:</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">type</span> <span class="tok-k">'</span><span class="tok-n">a</span> <span class="tok-n">return</span> <span class="tok-o">=</span> <span class="tok-kt">int</span> <span class="tok-o">-></span> <span class="tok-k">'</span><span class="tok-n">a</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">]</span> <span class="tok-k">type</span> <span class="tok-k">'</span><span class="tok-n">a</span> <span class="tok-n">u0</span> <span class="tok-o">=</span> <span class="tok-kt">int</span> <span class="tok-o">-></span> <span class="tok-kt">string</span> <span class="tok-o">-></span> <span class="tok-k">'</span><span class="tok-n">a</span> <span class="tok-n">return</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">]</span> <b class="conum">(1)</b> <span class="tok-k">type</span> <span class="tok-k">'</span><span class="tok-n">a</span> <span class="tok-n">u1</span> <span class="tok-o">=</span> <span class="tok-kt">int</span> <span class="tok-o">-></span> <span class="tok-kt">string</span> <span class="tok-o">-></span> <span class="tok-kt">int</span> <span class="tok-o">-></span> <span class="tok-k">'</span><span class="tok-n">a</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">]</span> <b class="conum">(2)</b> <span class="tok-k">type</span> <span class="tok-k">'</span><span class="tok-n">a</span> <span class="tok-n">u2</span> <span class="tok-o">=</span> <span class="tok-kt">int</span> <span class="tok-o">-></span> <span class="tok-kt">string</span> <span class="tok-o">-></span> <span class="tok-o">(</span><span class="tok-kt">int</span> <span class="tok-o">-></span> <span class="tok-k">'</span><span class="tok-n">a</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">])</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">]</span> <b class="conum">(3)</b></code></pre> </div> </div> <div class="colist arabic"> <ol> <li> <p><code>u0</code> has arity of 2, return a function with arity 1</p> </li> <li> <p><code>u1</code> has arity of 3</p> </li> <li> <p><code>u2</code> has arity of 2, return a function with arity 1</p> </li> </ol> </div> </div> <div class="sect3"> <h4 id="__code_bs_uncurry_code_for_implicit_uncurried_callback_since_1_5_0"><a class="anchor" href="#__code_bs_uncurry_code_for_implicit_uncurried_callback_since_1_5_0"></a><code>[@bs.uncurry]</code> for implicit uncurried callback (@since 1.5.0)</h4> <div class="paragraph"> <p>Note the <code>[@bs]</code> annotation already solved the problem completely, but it has a drawback that it requires users to write <code>[@bs]</code> both in definition site and call site.</p> </div> <div class="paragraph"> <p>For example:</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">external</span> <span class="tok-n">map</span> <span class="tok-o">:</span> <span class="tok-k">'</span><span class="tok-n">a</span> <span class="tok-kt">array</span> <span class="tok-o">-></span> <span class="tok-o">(</span><span class="tok-k">'</span><span class="tok-n">a</span> <span class="tok-o">-></span> <span class="tok-k">'</span><span class="tok-n">b</span><span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">])</span> <span class="tok-o">-></span> <span class="tok-k">'</span><span class="tok-n">b</span> <span class="tok-kt">array</span> <span class="tok-o">=</span> <span class="tok-s2">""</span> <span class="tok-o">[@@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">send</span><span class="tok-o">]</span> <b class="conum">(1)</b> <span class="tok-n">map</span> <span class="tok-o">[|</span><span class="tok-mi">1</span><span class="tok-o">;</span><span class="tok-mi">2</span><span class="tok-o">;</span><span class="tok-mi">3</span><span class="tok-o">|]</span> <span class="tok-o">(</span><span class="tok-k">fun</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">]</span> <span class="tok-n">x</span> <span class="tok-o">-></span> <span class="tok-n">x</span> <span class="tok-o">+</span> <span class="tok-mi">1</span><span class="tok-o">)</span> <b class="conum">(2)</b></code></pre> </div> </div> <div class="colist arabic"> <ol> <li> <p><code>[@bs]</code> annotation in definition site</p> </li> <li> <p><code>[@bs]</code> annotation in call site</p> </li> </ol> </div> <div class="paragraph"> <p>This is less convenient for end users, so we introduce another implicit annotation <code>[@bs.uncurry]</code> so that the compiler will automatically wrap the curried callback (from OCaml side) to JS uncurried callback. In this way, the <code>[@bs.uncurry]</code> annotation is defined only once.</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">external</span> <span class="tok-n">map</span> <span class="tok-o">:</span> <span class="tok-k">'</span><span class="tok-n">a</span> <span class="tok-kt">array</span> <span class="tok-o">-></span> <span class="tok-o">(</span><span class="tok-k">'</span><span class="tok-n">a</span> <span class="tok-o">-></span> <span class="tok-k">'</span><span class="tok-n">b</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">uncurry</span><span class="tok-o">])</span> <span class="tok-o">-></span> <span class="tok-k">'</span><span class="tok-n">b</span> <span class="tok-kt">array</span> <span class="tok-o">=</span> <span class="tok-s2">""</span> <span class="tok-o">[@@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">send</span><span class="tok-o">]</span> <b class="conum">(1)</b> <span class="tok-n">map</span> <span class="tok-o">[|</span><span class="tok-mi">1</span><span class="tok-o">;</span><span class="tok-mi">2</span><span class="tok-o">;</span><span class="tok-mi">3</span><span class="tok-o">|]</span> <span class="tok-o">(</span><span class="tok-k">fun</span> <span class="tok-n">x</span> <span class="tok-o">-></span> <span class="tok-n">x</span><span class="tok-o">+</span> <span class="tok-mi">1</span><span class="tok-o">)</span> <b class="conum">(2)</b></code></pre> </div> </div> <div class="colist arabic"> <ol> <li> <p><code>[@bs.uncurry]</code> annotation in definition site</p> </li> <li> <p>Idiomatic OCaml code</p> </li> </ol> </div> <div class="admonitionblock note"> <table> <tr> <td class="icon"> <div class="title">Note</div> </td> <td class="content"> <div class="paragraph"> <p>In general, <code>bs.uncurry</code> is recommended, and compiler will do lots of optimizations to resolve the <code>curry</code> to <code>uncurry</code> calling convention at compile time. However, there are some cases the compiler optimizer could not do it, in that case, it will be converted runtime.</p> </div> <div class="paragraph"> <p>This means <code>[@bs]</code> are completely static behavior (no any runtime cost), while <code>[@bs.uncurry]</code> is more convenient for end users but in some very rare cases it might be slower than <code>[@bs]</code></p> </div> </td> </tr> </table> </div> </div> <div class="sect3"> <h4 id="_uncurried_calling_convention_as_an_optimization"><a class="anchor" href="#_uncurried_calling_convention_as_an_optimization"></a>Uncurried calling convention as an optimization</h4> <div class="paragraph"> <div class="title">Background:</div> <p>As we discussed before, we can compile any OCaml function as arity 1 to support OCaml’s curried calling convention.</p> </div> <div class="paragraph"> <p>This model is simple and easy to implement, but the native compilation is very slow and expensive for all functions.</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">let</span> <span class="tok-n">f</span> <span class="tok-n">x</span> <span class="tok-n">y</span> <span class="tok-n">z</span> <span class="tok-o">=</span> <span class="tok-n">x</span> <span class="tok-o">+</span> <span class="tok-n">y</span> <span class="tok-o">+</span> <span class="tok-n">z</span> <span class="tok-k">let</span> <span class="tok-n">a</span> <span class="tok-o">=</span> <span class="tok-n">f</span> <span class="tok-mi">1</span> <span class="tok-mi">2</span> <span class="tok-mi">3</span> <span class="tok-k">let</span> <span class="tok-n">b</span> <span class="tok-o">=</span> <span class="tok-n">f</span> <span class="tok-mi">1</span> <span class="tok-mi">2</span></code></pre> </div> </div> <div class="paragraph"> <p>can be compiled as</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="js"><span class="tok-kd">function</span> <span class="tok-nx">f</span><span class="tok-p">(</span><span class="tok-nx">x</span><span class="tok-p">){</span> <span class="tok-k">return</span> <span class="tok-kd">function</span> <span class="tok-p">(</span><span class="tok-nx">y</span><span class="tok-p">){</span> <span class="tok-k">return</span> <span class="tok-kd">function</span> <span class="tok-p">(</span><span class="tok-nx">z</span><span class="tok-p">){</span> <span class="tok-k">return</span> <span class="tok-nx">x</span> <span class="tok-o">+</span> <span class="tok-nx">y</span> <span class="tok-o">+</span> <span class="tok-nx">z</span> <span class="tok-p">}</span> <span class="tok-p">}</span> <span class="tok-p">}</span> <span class="tok-kd">var</span> <span class="tok-nx">a</span> <span class="tok-o">=</span> <span class="tok-nx">f</span> <span class="tok-p">(</span><span class="tok-mi">1</span><span class="tok-p">)</span> <span class="tok-p">(</span><span class="tok-mi">2</span><span class="tok-p">)</span> <span class="tok-p">(</span><span class="tok-mi">3</span><span class="tok-p">)</span> <span class="tok-kd">var</span> <span class="tok-nx">b</span> <span class="tok-o">=</span> <span class="tok-nx">f</span> <span class="tok-p">(</span><span class="tok-mi">1</span><span class="tok-p">)</span> <span class="tok-p">(</span><span class="tok-mi">2</span><span class="tok-p">)</span></code></pre> </div> </div> <div class="paragraph"> <p>But as you can see, this is <em>highly inefficient</em>, since the compiler already <em>saw the source definition</em> of <code>f</code>, it can be optimized as below:</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="js"><span class="tok-kd">function</span> <span class="tok-nx">f</span><span class="tok-p">(</span><span class="tok-nx">x</span><span class="tok-p">,</span><span class="tok-nx">y</span><span class="tok-p">,</span><span class="tok-nx">z</span><span class="tok-p">)</span> <span class="tok-p">{</span><span class="tok-k">return</span> <span class="tok-nx">x</span> <span class="tok-o">+</span> <span class="tok-nx">y</span> <span class="tok-o">+</span> <span class="tok-nx">z</span><span class="tok-p">}</span> <span class="tok-kd">var</span> <span class="tok-nx">a</span> <span class="tok-o">=</span> <span class="tok-nx">f</span><span class="tok-p">(</span><span class="tok-mi">1</span><span class="tok-p">,</span><span class="tok-mi">2</span><span class="tok-p">,</span><span class="tok-mi">3</span><span class="tok-p">)</span> <span class="tok-kd">var</span> <span class="tok-nx">b</span> <span class="tok-o">=</span> <span class="tok-kd">function</span><span class="tok-p">(</span><span class="tok-nx">z</span><span class="tok-p">){</span><span class="tok-k">return</span> <span class="tok-nx">f</span><span class="tok-p">(</span><span class="tok-mi">1</span><span class="tok-p">,</span><span class="tok-mi">2</span><span class="tok-p">,</span><span class="tok-nx">z</span><span class="tok-p">)}</span></code></pre> </div> </div> <div class="paragraph"> <p>BuckleScript does this optimization in the cross module level and tries to infer the arity as much as it can.</p> </div> <div class="sect4"> <h5 id="_callback_optimization"><a class="anchor" href="#_callback_optimization"></a>Callback optimization</h5> <div class="paragraph"> <p>However, such optimization will not work with <em>higher-order</em> functions, i.e, callbacks.</p> </div> <div class="paragraph"> <p>For example,</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">let</span> <span class="tok-n">app</span> <span class="tok-n">f</span> <span class="tok-n">x</span> <span class="tok-o">=</span> <span class="tok-n">f</span> <span class="tok-n">x</span></code></pre> </div> </div> <div class="paragraph"> <p>Since the arity of <code>f</code> is unknown, the compiler can not do any optimization (unless <code>app</code> gets inlined), so we have to generate code as below:</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="js"><span class="tok-kd">function</span> <span class="tok-nx">app</span><span class="tok-p">(</span><span class="tok-nx">f</span><span class="tok-p">,</span><span class="tok-nx">x</span><span class="tok-p">){</span> <span class="tok-k">return</span> <span class="tok-nx">Curry</span><span class="tok-p">.</span><span class="tok-nx">_1</span><span class="tok-p">(</span><span class="tok-nx">f</span><span class="tok-p">,</span><span class="tok-nx">x</span><span class="tok-p">);</span> <span class="tok-p">}</span></code></pre> </div> </div> <div class="paragraph"> <p><code>Curry._1</code> is a function to dynamically support the curried calling convention.</p> </div> <div class="paragraph"> <p>Since we support the uncurried calling convention, you can write <code>app</code> as below</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">let</span> <span class="tok-n">app</span> <span class="tok-n">f</span> <span class="tok-n">x</span> <span class="tok-o">=</span> <span class="tok-n">f</span> <span class="tok-n">x</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">]</span></code></pre> </div> </div> <div class="paragraph"> <p>Now the type system will infer <code>app</code> as type <code>('a →'b [@bs]) → 'a</code> and compile <code>app</code> as</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="js"><span class="tok-kd">function</span> <span class="tok-nx">app</span><span class="tok-p">(</span><span class="tok-nx">f</span><span class="tok-p">,</span><span class="tok-nx">x</span><span class="tok-p">){</span> <span class="tok-k">return</span> <span class="tok-nx">f</span><span class="tok-p">(</span><span class="tok-nx">x</span><span class="tok-p">)</span> <span class="tok-p">}</span></code></pre> </div> </div> <div class="admonitionblock note"> <table> <tr> <td class="icon"> <div class="title">Note</div> </td> <td class="content"> <div class="paragraph"> <p>In OCaml the compiler internally uncurries every function declared as <code>external</code> and guarantees that it is always fully applied. Therefore, for <code>external</code> first-order FFI, its outermost function does not need the <code>[@bs]</code> annotation.</p> </div> </td> </tr> </table> </div> </div> </div> <div class="sect3"> <h4 id="_bindings_to_code_this_code_based_callbacks_code_bs_this_code"><a class="anchor" href="#_bindings_to_code_this_code_based_callbacks_code_bs_this_code"></a>Bindings to <code>this</code> based callbacks: <code>bs.this</code></h4> <div class="paragraph"> <p>Many JS libraries have callbacks which rely on <code>this</code> (the source), for example:</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="js"><span class="tok-nx">x</span><span class="tok-p">.</span><span class="tok-nx">onload</span> <span class="tok-o">=</span> <span class="tok-kd">function</span><span class="tok-p">(</span><span class="tok-nx">v</span><span class="tok-p">){</span> <span class="tok-nx">console</span><span class="tok-p">.</span><span class="tok-nx">log</span><span class="tok-p">(</span><span class="tok-k">this</span><span class="tok-p">.</span><span class="tok-nx">response</span> <span class="tok-o">+</span> <span class="tok-nx">v</span> <span class="tok-p">)</span> <span class="tok-p">}</span></code></pre> </div> </div> <div class="paragraph"> <p>Here, <code>this</code> would be the same as <code>x</code> (actually depends on how <code>onload</code> is called). It is clear that it is not correct to declare <code>x.onload</code> of type <code>unit → unit [@bs]</code>. Instead, we introduced a special attribute <code>bs.this</code> allowing us to type <code>x</code> as below:</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">type</span> <span class="tok-n">x</span> <span class="tok-k">external</span> <span class="tok-n">x</span><span class="tok-o">:</span> <span class="tok-n">x</span> <span class="tok-o">=</span> <span class="tok-s2">""</span> <span class="tok-o">[@@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-k">val</span><span class="tok-o">]</span> <span class="tok-k">external</span> <span class="tok-n">set_onload</span> <span class="tok-o">:</span> <span class="tok-n">x</span> <span class="tok-o">-></span> <span class="tok-o">(</span><span class="tok-n">x</span> <span class="tok-o">-></span> <span class="tok-kt">int</span> <span class="tok-o">-></span> <span class="tok-kt">unit</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">this</span><span class="tok-o">])</span> <span class="tok-o">-></span> <span class="tok-kt">unit</span> <span class="tok-o">=</span> <span class="tok-s2">"onload"</span> <span class="tok-o">[@@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">set</span><span class="tok-o">]</span> <span class="tok-k">external</span> <span class="tok-n">resp</span> <span class="tok-o">:</span> <span class="tok-n">x</span> <span class="tok-o">-></span> <span class="tok-kt">int</span> <span class="tok-o">=</span> <span class="tok-s2">"response"</span> <span class="tok-o">[@@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">get</span><span class="tok-o">]</span> <span class="tok-k">let</span> <span class="tok-o">_</span> <span class="tok-o">=</span> <span class="tok-n">set_onload</span> <span class="tok-n">x</span> <span class="tok-k">begin</span> <span class="tok-k">fun</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">this</span><span class="tok-o">]</span> <span class="tok-n">o</span> <span class="tok-n">v</span> <span class="tok-o">-></span> <span class="tok-nn">Js</span><span class="tok-p">.</span><span class="tok-n">log</span><span class="tok-o">(</span><span class="tok-n">resp</span> <span class="tok-n">o</span> <span class="tok-o">+</span> <span class="tok-n">v</span> <span class="tok-o">)</span> <span class="tok-k">end</span></code></pre> </div> </div> <div class="listingblock"> <div class="title">Output:</div> <div class="content"> <pre class="pygments highlight"><code data-lang="js"><span class="tok-nx">x</span><span class="tok-p">.</span><span class="tok-nx">onload</span> <span class="tok-o">=</span> <span class="tok-p">(</span><span class="tok-kd">function</span> <span class="tok-p">(</span><span class="tok-nx">v</span><span class="tok-p">)</span> <span class="tok-p">{</span> <span class="tok-kd">var</span> <span class="tok-nx">o</span> <span class="tok-o">=</span> <span class="tok-k">this</span> <span class="tok-p">;</span> <b class="conum">(1)</b> <span class="tok-nx">console</span><span class="tok-p">.</span><span class="tok-nx">log</span><span class="tok-p">(</span><span class="tok-nx">o</span><span class="tok-p">.</span><span class="tok-nx">response</span> <span class="tok-o">+</span> <span class="tok-nx">v</span> <span class="tok-o">|</span> <span class="tok-mi">0</span><span class="tok-p">);</span> <span class="tok-k">return</span> <span class="tok-cm">/* () */</span><span class="tok-mi">0</span><span class="tok-p">;</span> <span class="tok-p">});</span></code></pre> </div> </div> <div class="colist arabic"> <ol> <li> <p>The first argument is automatically bound to <code>this</code></p> </li> </ol> </div> <div class="paragraph"> <p><code>bs.this</code> is the same as <code>bs</code> : except that its first parameter is reserved for <code>this</code> and for arity of 0, there is no need for a redundant <code>unit</code> type:</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">let</span> <span class="tok-n">f</span> <span class="tok-o">:</span> <span class="tok-k">'</span><span class="tok-n">obj</span> <span class="tok-o">-></span> <span class="tok-k">'</span><span class="tok-n">b</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">this</span><span class="tok-o">]</span> <span class="tok-o">=</span> <span class="tok-k">fun</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">this</span><span class="tok-o">]</span> <span class="tok-n">obj</span> <span class="tok-o">-></span> <span class="tok-o">....</span> <span class="tok-k">let</span> <span class="tok-n">f1</span> <span class="tok-o">:</span> <span class="tok-k">'</span><span class="tok-n">obj</span> <span class="tok-o">-></span> <span class="tok-k">'</span><span class="tok-n">a0</span> <span class="tok-o">-></span> <span class="tok-k">'</span><span class="tok-n">b</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">this</span><span class="tok-o">]</span> <span class="tok-o">=</span> <span class="tok-k">fun</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">this</span><span class="tok-o">]</span> <span class="tok-n">obj</span> <span class="tok-n">a</span> <span class="tok-o">-></span> <span class="tok-o">...</span></code></pre> </div> </div> <div class="admonitionblock note"> <table> <tr> <td class="icon"> <div class="title">Note</div> </td> <td class="content"> <div class="paragraph"> <p>There is no way to consume a function of type <code>'obj → 'a0 .. → 'aN → 'b0 [@bs.this]</code> on the OCaml side. This is an intentional design choice, we <strong>don’t encourage</strong> people to write code in this style.</p> </div> <div class="paragraph"> <p>This was introduced mainly to be consumed by existing JS libraries. User can also type <code>x</code> as a JS class too (see later)</p> </div> </td> </tr> </table> </div> </div> </div> <div class="sect2"> <h3 id="_binding_to_js_objects"><a class="anchor" href="#_binding_to_js_objects"></a>Binding to JS objects</h3> <div class="paragraph"> <div class="title">Convention:</div> <p>All JS objects of type <code>'a</code> are lifted to type <code>'a Js.t</code> to avoid conflict with OCaml’s native object system (we support both OCaml’s native object system and FFI to JS’s objects), <code>##</code> is used in JS’s object method dispatch and field access, while <code>#</code> is used in OCaml’s object method dispatch.</p> </div> <div class="paragraph"> <div class="title">Typing JavaScript objects:</div> <p>OCaml supports object oriented style natively and provides structural type system. OCaml’s object system has different runtime semantics from JS object, but they share the same type system, all JS objects of type <code>'a</code> are typed as <code>'a Js.t</code></p> </div> <div class="paragraph"> <p>OCaml provides two kinds of syntaxes to model structural typing: <code>< p1 : t1 ></code> style and <code>class type</code> style. They are mostly the same except that the latter is more feature rich (supporting inheritance) but more verbose.</p> </div> <div class="sect3"> <h4 id="_simple_object_type"><a class="anchor" href="#_simple_object_type"></a>Simple object type</h4> <div class="paragraph"> <p>Suppose we have a JS file <code>demo.js</code> which exports two properties: <code>height</code> and <code>width</code>:</p> </div> <div class="listingblock"> <div class="title">demo.js</div> <div class="content"> <pre class="pygments highlight"><code data-lang="js"><span class="tok-nx">exports</span><span class="tok-p">.</span><span class="tok-nx">height</span> <span class="tok-o">=</span> <span class="tok-mi">3</span> <span class="tok-nx">exports</span><span class="tok-p">.</span><span class="tok-nx">width</span> <span class="tok-o">=</span> <span class="tok-mi">3</span></code></pre> </div> </div> <div class="paragraph"> <p>There are different ways to writing binding to module <code>demo</code>, here we use OCaml objects to model module <code>demo</code></p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">external</span> <span class="tok-n">demo</span> <span class="tok-o">:</span> <span class="tok-o"><</span> <span class="tok-n">height</span> <span class="tok-o">:</span> <span class="tok-kt">int</span> <span class="tok-o">;</span> <span class="tok-n">width</span> <span class="tok-o">:</span> <span class="tok-kt">int</span> <span class="tok-o">></span> <span class="tok-nn">Js</span><span class="tok-p">.</span><span class="tok-n">t</span> <span class="tok-o">=</span> <span class="tok-s2">""</span> <span class="tok-o">[@@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-k">module</span><span class="tok-o">]</span></code></pre> </div> </div> <div class="paragraph"> <p>There are two kinds of types on the method name:</p> </div> <div class="ulist"> <ul> <li> <p>normal type</p> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-o"><</span> <span class="tok-n">label</span> <span class="tok-o">:</span> <span class="tok-kt">int</span> <span class="tok-o">></span> <span class="tok-o"><</span> <span class="tok-n">label</span> <span class="tok-o">:</span> <span class="tok-kt">int</span> <span class="tok-o">-></span> <span class="tok-kt">int</span> <span class="tok-o">></span> <span class="tok-o"><</span> <span class="tok-n">label</span> <span class="tok-o">:</span> <span class="tok-kt">int</span> <span class="tok-o">-></span> <span class="tok-kt">int</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">]></span> <span class="tok-o"><</span> <span class="tok-n">label</span> <span class="tok-o">:</span> <span class="tok-kt">int</span> <span class="tok-o">-></span> <span class="tok-kt">int</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">this</span><span class="tok-o">]></span></code></pre> </div> </div> </li> <li> <p>method</p> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-o"><</span> <span class="tok-n">label</span> <span class="tok-o">:</span> <span class="tok-kt">int</span> <span class="tok-o">-></span> <span class="tok-kt">int</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">meth</span><span class="tok-o">]</span> <span class="tok-o">></span></code></pre> </div> </div> </li> </ul> </div> <div class="paragraph"> <p>The difference is that for <code>method</code>, the type system will force users to fulfill its arguments all at the same time, since its semantics depends on <code>this</code> in JavaScript.</p> </div> <div class="paragraph"> <p>For example:</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">let</span> <span class="tok-n">test</span> <span class="tok-n">f</span> <span class="tok-o">=</span> <span class="tok-n">f</span><span class="tok-o">##</span><span class="tok-n">hi</span> <span class="tok-mi">1</span> <b class="conum">(1)</b> <span class="tok-k">let</span> <span class="tok-n">test2</span> <span class="tok-n">f</span> <span class="tok-o">=</span> <span class="tok-k">let</span> <span class="tok-n">u</span> <span class="tok-o">=</span> <span class="tok-n">f</span><span class="tok-o">##</span><span class="tok-n">hi</span> <span class="tok-k">in</span> <span class="tok-n">u</span> <span class="tok-mi">1</span> <span class="tok-k">let</span> <span class="tok-n">test3</span> <span class="tok-n">f</span> <span class="tok-o">=</span> <span class="tok-k">let</span> <span class="tok-n">u</span> <span class="tok-o">=</span> <span class="tok-n">f</span><span class="tok-o">##</span><span class="tok-n">hi</span> <span class="tok-k">in</span> <span class="tok-n">u</span> <span class="tok-mi">1</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">]</span></code></pre> </div> </div> <div class="colist arabic"> <ol> <li> <p><code>##</code> is JS object property/method dispatch</p> </li> </ol> </div> <div class="paragraph"> <p>The compiler would infer types differently</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">val</span> <span class="tok-n">test</span> <span class="tok-o">:</span> <span class="tok-o"><</span> <span class="tok-n">hi</span> <span class="tok-o">:</span> <span class="tok-kt">int</span> <span class="tok-o">-></span> <span class="tok-k">'</span><span class="tok-n">a</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">meth</span><span class="tok-o">];</span> <span class="tok-o">..</span> <span class="tok-o">></span> <span class="tok-o">-></span> <span class="tok-k">'</span><span class="tok-n">a</span> <b class="conum">(1)</b> <span class="tok-k">val</span> <span class="tok-n">test2</span> <span class="tok-o">:</span> <span class="tok-o"><</span> <span class="tok-n">hi</span> <span class="tok-o">:</span> <span class="tok-kt">int</span> <span class="tok-o">-></span> <span class="tok-k">'</span><span class="tok-n">a</span> <span class="tok-o">;</span> <span class="tok-o">..</span> <span class="tok-o">></span> <span class="tok-o">-></span> <span class="tok-k">'</span><span class="tok-n">a</span> <span class="tok-k">val</span> <span class="tok-n">test3</span> <span class="tok-o">:</span> <span class="tok-o"><</span> <span class="tok-n">hi</span> <span class="tok-o">:</span> <span class="tok-kt">int</span> <span class="tok-o">-></span> <span class="tok-k">'</span><span class="tok-n">a</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">];</span> <span class="tok-o">..</span> <span class="tok-o">></span></code></pre> </div> </div> <div class="colist arabic"> <ol> <li> <p><code>..</code> is a row variable, which means the object can contain more methods.</p> </li> </ol> </div> </div> <div class="sect3"> <h4 id="_complex_object_type"><a class="anchor" href="#_complex_object_type"></a>Complex object type</h4> <div class="paragraph"> <p>Below is an example:</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">class</span> <span class="tok-k">type</span> <span class="tok-o">_</span><span class="tok-n">rect</span> <span class="tok-o">=</span> <span class="tok-k">object</span> <span class="tok-k">method</span> <span class="tok-n">height</span> <span class="tok-o">:</span> <span class="tok-kt">int</span> <span class="tok-o">[@@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">set</span><span class="tok-o">]</span> <span class="tok-k">method</span> <span class="tok-n">width</span> <span class="tok-o">:</span> <span class="tok-kt">int</span> <span class="tok-o">[@@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">set</span><span class="tok-o">]</span> <span class="tok-k">method</span> <span class="tok-n">draw</span> <span class="tok-o">:</span> <span class="tok-kt">unit</span> <span class="tok-o">-></span> <span class="tok-kt">unit</span> <span class="tok-k">end</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">]</span> <b class="conum">(1)</b> <span class="tok-k">type</span> <span class="tok-n">rect</span> <span class="tok-o">=</span> <span class="tok-o">_</span><span class="tok-n">rect</span> <span class="tok-nn">Js</span><span class="tok-p">.</span><span class="tok-n">t</span></code></pre> </div> </div> <div class="colist arabic"> <ol> <li> <p><code>class type</code> annotated with <code>[@bs]</code> is treated as a JS class type, it needs to be lifted to <code>Js.t</code> too.</p> </li> </ol> </div> <div class="paragraph"> <p>For JS classes, methods with arrow types are treated as real methods (automatically annotated with <code>[@bs.meth]</code>) while methods with non-arrow types are treated as properties. Adding <code>[@@bs.set]</code> to those methods will make them mutable, which enables you to set them using <code>#=</code> later. Dropping the <code>[@@bs.set]</code> attribute makes the method/property immutable.</p> </div> <div class="paragraph"> <p>So the type <code>rect</code> is the same as below:</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">type</span> <span class="tok-n">rect</span> <span class="tok-o">=</span> <span class="tok-o"><</span> <span class="tok-n">height</span> <span class="tok-o">:</span> <span class="tok-kt">int</span> <span class="tok-o">;</span> <span class="tok-n">width</span> <span class="tok-o">:</span> <span class="tok-kt">int</span> <span class="tok-o">;</span> <span class="tok-n">draw</span> <span class="tok-o">:</span> <span class="tok-kt">unit</span> <span class="tok-o">-></span> <span class="tok-kt">unit</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">meth</span><span class="tok-o">]</span> <span class="tok-o">></span> <span class="tok-nn">Js</span><span class="tok-p">.</span><span class="tok-n">t</span></code></pre> </div> </div> </div> <div class="sect3"> <h4 id="_how_to_consume_js_property_and_methods"><a class="anchor" href="#_how_to_consume_js_property_and_methods"></a>How to consume JS property and methods</h4> <div class="paragraph"> <p>As we said: <code>##</code> is used in both object method dispatch and field access.</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-n">f</span><span class="tok-o">##</span><span class="tok-n">property</span> <b class="conum">(1)</b> <span class="tok-n">f</span><span class="tok-o">##</span><span class="tok-n">property</span> <span class="tok-o">#=</span> <span class="tok-n">v</span> <span class="tok-n">f</span><span class="tok-o">##</span><span class="tok-n">js_method</span> <span class="tok-n">args0</span> <span class="tok-n">args1</span> <span class="tok-n">args2</span> <b class="conum">(2)</b></code></pre> </div> </div> <div class="colist arabic"> <ol> <li> <p>property get should not come with any argument as we discussed above, which will be checked by the compiler.</p> </li> <li> <p>Here <code>method</code> is of arity 3.</p> </li> </ol> </div> <div class="admonitionblock note"> <table> <tr> <td class="icon"> <div class="title">Note</div> </td> <td class="content"> <div class="paragraph"> <p>All JS method application is uncurried, JS’s <strong>method is not a function</strong>, this invariant can be guaranteed by OCaml’s type checker, a classic example shown below:</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="js"><span class="tok-nx">console</span><span class="tok-p">.</span><span class="tok-nx">log</span><span class="tok-p">(</span><span class="tok-s1">'fine'</span><span class="tok-p">)</span> <span class="tok-kd">var</span> <span class="tok-nx">log</span> <span class="tok-o">=</span> <span class="tok-nx">console</span><span class="tok-p">.</span><span class="tok-nx">log</span><span class="tok-p">;</span> <span class="tok-nx">log</span><span class="tok-p">(</span><span class="tok-s1">'fine'</span><span class="tok-p">)</span> <b class="conum">(1)</b></code></pre> </div> </div> <div class="colist arabic"> <ol> <li> <p>May cause exception, implementation dependent, <code>console.log</code> may depend on <code>this</code></p> </li> </ol> </div> </td> </tr> </table> </div> <div class="paragraph"> <p>In BuckleScript</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">let</span> <span class="tok-n">fn</span> <span class="tok-o">=</span> <span class="tok-n">f0</span><span class="tok-o">##</span><span class="tok-n">f</span> <span class="tok-k">in</span> <span class="tok-k">let</span> <span class="tok-n">a</span> <span class="tok-o">=</span> <span class="tok-n">fn</span> <span class="tok-mi">1</span> <span class="tok-mi">2</span> <span class="tok-c">(* f##field a b would think `field` as a method *)</span></code></pre> </div> </div> <div class="paragraph"> <p>is different from</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">let</span> <span class="tok-n">b</span> <span class="tok-o">=</span> <span class="tok-n">f1</span><span class="tok-o">##</span><span class="tok-n">f</span> <span class="tok-mi">1</span> <span class="tok-mi">2</span></code></pre> </div> </div> <div class="paragraph"> <p>The compiler will infer as below:</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">val</span> <span class="tok-n">f0</span> <span class="tok-o">:</span> <span class="tok-o"><</span> <span class="tok-n">f</span> <span class="tok-o">:</span> <span class="tok-kt">int</span> <span class="tok-o">-></span> <span class="tok-kt">int</span> <span class="tok-o">-></span> <span class="tok-kt">int</span> <span class="tok-o">></span> <span class="tok-nn">Js</span><span class="tok-p">.</span><span class="tok-n">t</span> <span class="tok-k">val</span> <span class="tok-n">f1</span> <span class="tok-o">:</span> <span class="tok-o"><</span> <span class="tok-n">f</span> <span class="tok-o">:</span> <span class="tok-kt">int</span> <span class="tok-o">-></span> <span class="tok-kt">int</span> <span class="tok-o">-></span> <span class="tok-kt">int</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">meth</span><span class="tok-o">]</span> <span class="tok-o">></span> <span class="tok-nn">Js</span><span class="tok-p">.</span><span class="tok-n">t</span></code></pre> </div> </div> <div class="paragraph"> <p>If we type <code>console</code> properly in OCaml, user could only write</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-n">console</span><span class="tok-o">##</span><span class="tok-n">log</span> <span class="tok-s2">"fine"</span> <span class="tok-k">let</span> <span class="tok-n">u</span> <span class="tok-o">=</span> <span class="tok-n">console</span><span class="tok-o">##</span><span class="tok-n">log</span> <span class="tok-k">let</span> <span class="tok-bp">()</span> <span class="tok-o">=</span> <span class="tok-n">u</span> <span class="tok-s2">"fine"</span> <b class="conum">(1)</b></code></pre> </div> </div> <div class="colist arabic"> <ol> <li> <p>OCaml compiler will complain</p> </li> </ol> </div> <div class="admonitionblock note"> <table> <tr> <td class="icon"> <div class="title">Note</div> </td> <td class="content"> <div class="paragraph"> <p>If a user were to make such a mistake, the type checker would complain by saying it expected <code>Js.method</code> but saw a function instead, so it is still sound and type safe.</p> </div> </td> </tr> </table> </div> <div class="sect4"> <h5 id="_getter_setter_annotation_to_js_properties_simplified_since_1_9_2"><a class="anchor" href="#_getter_setter_annotation_to_js_properties_simplified_since_1_9_2"></a>getter/setter annotation to JS properties (simplified @since 1.9.2)</h5> <div class="paragraph"> <p>Since OCaml’s object system does not have getters/setters, we introduced two attributes <code>bs.get</code> and <code>bs.set</code> to help inform BuckleScript to compile them as property getters/setters.</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">type</span> <span class="tok-n">y</span> <span class="tok-o">=</span> <span class="tok-o"><</span> <span class="tok-n">height</span> <span class="tok-o">:</span> <span class="tok-kt">int</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">set</span> <span class="tok-n">no_get</span><span class="tok-o">]</span> <b class="conum">(1)</b> <span class="tok-o">></span> <span class="tok-nn">Js</span><span class="tok-p">.</span><span class="tok-n">t</span> <span class="tok-k">type</span> <span class="tok-n">y0</span> <span class="tok-o">=</span> <span class="tok-o"><</span> <span class="tok-n">height</span> <span class="tok-o">:</span> <span class="tok-kt">int</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">set</span><span class="tok-o">]</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">get</span> <span class="tok-n">null</span><span class="tok-o">]</span> <b class="conum">(2)</b> <span class="tok-o">></span> <span class="tok-nn">Js</span><span class="tok-p">.</span><span class="tok-n">t</span> <span class="tok-k">type</span> <span class="tok-n">y1</span> <span class="tok-o">=</span> <span class="tok-o"><</span> <span class="tok-n">height</span> <span class="tok-o">:</span> <span class="tok-kt">int</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">set</span><span class="tok-o">]</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">get</span> <span class="tok-n">undefined</span><span class="tok-o">]</span> <b class="conum">(3)</b> <span class="tok-o">></span> <span class="tok-nn">Js</span><span class="tok-p">.</span><span class="tok-n">t</span> <span class="tok-k">type</span> <span class="tok-n">y2</span> <span class="tok-o">=</span> <span class="tok-o"><</span> <span class="tok-n">height</span> <span class="tok-o">:</span> <span class="tok-kt">int</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">set</span><span class="tok-o">]</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">get</span> <span class="tok-n">nullable</span> <span class="tok-o">]</span> <b class="conum">(4)</b> <span class="tok-o">></span> <span class="tok-nn">Js</span><span class="tok-p">.</span><span class="tok-n">t</span> <span class="tok-k">type</span> <span class="tok-n">y3</span> <span class="tok-o">=</span> <span class="tok-o"><</span> <span class="tok-n">height</span> <span class="tok-o">:</span> <span class="tok-kt">int</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">get</span> <span class="tok-n">nullable</span><span class="tok-o">]</span> <b class="conum">(5)</b> <span class="tok-o">></span> <span class="tok-nn">Js</span><span class="tok-p">.</span><span class="tok-n">t</span></code></pre> </div> </div> <div class="colist arabic"> <ol> <li> <p><code>height</code> is setter only</p> </li> <li> <p>getter return <code>int Js.null</code></p> </li> <li> <p>getter return <code>int Js.undefined</code></p> </li> <li> <p>getter return <code>int Js.nullable</code></p> </li> <li> <p>getter only, return <code>int Js.nullable</code></p> </li> </ol> </div> <div class="admonitionblock note"> <table> <tr> <td class="icon"> <div class="title">Note</div> </td> <td class="content"> Getter/Setter also applies to class type label </td> </tr> </table> </div> </div> </div> <div class="sect3"> <h4 id="_create_js_objects_using_bs_obj"><a class="anchor" href="#_create_js_objects_using_bs_obj"></a>Create JS objects using bs.obj</h4> <div class="paragraph"> <p>Not only can we create bindings to JS objects, but also we can create JS objects in a type safe way on the OCaml side:</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">let</span> <span class="tok-n">u</span> <span class="tok-o">=</span> <span class="tok-o">[%</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">obj</span> <span class="tok-o">{</span> <span class="tok-n">x</span> <span class="tok-o">=</span> <span class="tok-o">{</span> <span class="tok-n">y</span> <span class="tok-o">=</span> <span class="tok-o">{</span> <span class="tok-n">z</span> <span class="tok-o">=</span> <span class="tok-mi">3</span><span class="tok-o">}}}</span> <span class="tok-o">]</span> <b class="conum">(1)</b></code></pre> </div> </div> <div class="colist arabic"> <ol> <li> <p><code>bs.obj</code> extension is used to mark <code>{}</code> as JS objects</p> </li> </ol> </div> <div class="listingblock"> <div class="title">Output:</div> <div class="content"> <pre class="pygments highlight"><code data-lang="js"><span class="tok-kd">var</span> <span class="tok-nx">u</span> <span class="tok-o">=</span> <span class="tok-p">{</span> <span class="tok-nx">x</span> <span class="tok-o">:</span> <span class="tok-p">{</span> <span class="tok-nx">y</span> <span class="tok-o">:</span> <span class="tok-p">{</span> <span class="tok-nx">z</span> <span class="tok-o">:</span> <span class="tok-mi">3</span> <span class="tok-p">}}}}</span></code></pre> </div> </div> <div class="paragraph"> <p>The compiler would infer <code>u</code> as type:</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">val</span> <span class="tok-n">u</span> <span class="tok-o">:</span> <span class="tok-o"><</span> <span class="tok-n">x</span> <span class="tok-o">:</span> <span class="tok-o"><</span> <span class="tok-n">y</span> <span class="tok-o">:</span> <span class="tok-o"><</span> <span class="tok-n">z</span> <span class="tok-o">:</span> <span class="tok-kt">int</span> <span class="tok-o">></span> <span class="tok-nn">Js</span><span class="tok-p">.</span><span class="tok-n">t</span> <span class="tok-o">></span> <span class="tok-nn">Js</span><span class="tok-p">.</span><span class="tok-n">t</span> <span class="tok-o">></span> <span class="tok-nn">Js</span><span class="tok-p">.</span><span class="tok-n">t</span></code></pre> </div> </div> <div class="paragraph"> <p>To make it more symmetric, extension <code>bs.obj</code> can also be applied into the type level, so you can write:</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">val</span> <span class="tok-n">u</span> <span class="tok-o">:</span> <span class="tok-o">[%</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">obj</span><span class="tok-o">:</span> <span class="tok-o"><</span> <span class="tok-n">x</span> <span class="tok-o">:</span> <span class="tok-o"><</span> <span class="tok-n">y</span> <span class="tok-o">:</span> <span class="tok-o"><</span> <span class="tok-n">z</span> <span class="tok-o">:</span> <span class="tok-kt">int</span> <span class="tok-o">></span> <span class="tok-o">></span> <span class="tok-o">></span> <span class="tok-o">]</span></code></pre> </div> </div> <div class="paragraph"> <p>Users can also write expression and types together as below:</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">let</span> <span class="tok-n">u</span> <span class="tok-o">=</span> <span class="tok-o">[%</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">obj</span> <span class="tok-o">(</span> <span class="tok-o">{</span> <span class="tok-n">x</span> <span class="tok-o">=</span> <span class="tok-o">{</span> <span class="tok-n">y</span> <span class="tok-o">=</span> <span class="tok-o">{</span> <span class="tok-n">z</span> <span class="tok-o">=</span> <span class="tok-mi">3</span> <span class="tok-o">}}}</span> <span class="tok-o">:</span> <span class="tok-o"><</span> <span class="tok-n">x</span> <span class="tok-o">:</span> <span class="tok-o"><</span> <span class="tok-n">y</span> <span class="tok-o">:</span> <span class="tok-o"><</span> <span class="tok-n">z</span> <span class="tok-o">:</span> <span class="tok-kt">int</span> <span class="tok-o">></span> <span class="tok-o">></span> <span class="tok-o">></span> <span class="tok-o">]</span></code></pre> </div> </div> <div class="paragraph"> <p>Objects in a collection also works:</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">let</span> <span class="tok-n">xs</span> <span class="tok-o">=</span> <span class="tok-o">[%</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">obj</span> <span class="tok-o">[|</span> <span class="tok-o">{</span> <span class="tok-n">x</span> <span class="tok-o">=</span> <span class="tok-mi">3</span> <span class="tok-o">}</span> <span class="tok-o">;</span> <span class="tok-o">{</span> <span class="tok-n">x</span> <span class="tok-o">=</span> <span class="tok-mi">3</span> <span class="tok-o">}</span> <span class="tok-o">|]</span> <span class="tok-o">:</span> <span class="tok-o"><</span> <span class="tok-n">x</span> <span class="tok-o">:</span> <span class="tok-kt">int</span> <span class="tok-o">></span> <span class="tok-kt">array</span> <span class="tok-o">]</span> <span class="tok-k">let</span> <span class="tok-n">ys</span> <span class="tok-o">=</span> <span class="tok-o">[%</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">obj</span> <span class="tok-o">[|</span> <span class="tok-o">{</span> <span class="tok-n">x</span> <span class="tok-o">=</span> <span class="tok-mi">3</span> <span class="tok-o">}</span> <span class="tok-o">;</span> <span class="tok-o">{</span> <span class="tok-n">x</span> <span class="tok-o">=</span> <span class="tok-mi">4</span> <span class="tok-o">}</span> <span class="tok-o">|]</span> <span class="tok-o">]</span></code></pre> </div> </div> <div class="listingblock"> <div class="title">Output:</div> <div class="content"> <pre class="pygments highlight"><code data-lang="js"><span class="tok-kd">var</span> <span class="tok-nx">xs</span> <span class="tok-o">=</span> <span class="tok-p">[</span> <span class="tok-p">{</span> <span class="tok-nx">x</span> <span class="tok-o">:</span> <span class="tok-mi">3</span> <span class="tok-p">}</span> <span class="tok-p">,</span> <span class="tok-p">{</span> <span class="tok-nx">x</span> <span class="tok-o">:</span> <span class="tok-mi">3</span> <span class="tok-p">}</span> <span class="tok-p">]</span> <span class="tok-kd">var</span> <span class="tok-nx">ys</span> <span class="tok-o">=</span> <span class="tok-p">[</span> <span class="tok-p">{</span> <span class="tok-nx">x</span> <span class="tok-o">:</span> <span class="tok-mi">3</span> <span class="tok-p">}</span> <span class="tok-p">,</span> <span class="tok-p">{</span> <span class="tok-nx">x</span> <span class="tok-o">:</span> <span class="tok-mi">4</span> <span class="tok-p">}</span> <span class="tok-p">]</span></code></pre> </div> </div> </div> <div class="sect3"> <h4 id="_create_js_objects_using_external"><a class="anchor" href="#_create_js_objects_using_external"></a>Create JS objects using external</h4> <div class="paragraph"> <p><code>bs.obj</code> can also be used as an attribute in external declarations, as below:</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">external</span> <span class="tok-n">make_config</span> <span class="tok-o">:</span> <span class="tok-n">hi</span><span class="tok-o">:</span><span class="tok-kt">int</span> <span class="tok-o">-></span> <span class="tok-n">lo</span><span class="tok-o">:</span><span class="tok-kt">int</span> <span class="tok-o">-></span> <span class="tok-kt">unit</span> <span class="tok-o">-></span> <span class="tok-n">t</span> <span class="tok-o">=</span> <span class="tok-s2">""</span> <span class="tok-o">[@@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">obj</span><span class="tok-o">]</span> <span class="tok-k">let</span> <span class="tok-n">v</span> <span class="tok-o">=</span> <span class="tok-n">make_config</span> <span class="tok-o">~</span><span class="tok-n">hi</span><span class="tok-o">:</span><span class="tok-mi">2</span> <span class="tok-o">~</span><span class="tok-n">lo</span><span class="tok-o">:</span><span class="tok-mi">3</span></code></pre> </div> </div> <div class="listingblock"> <div class="title">Output:</div> <div class="content"> <pre class="pygments highlight"><code data-lang="js"><span class="tok-kd">var</span> <span class="tok-nx">v</span> <span class="tok-o">=</span> <span class="tok-p">{</span> <span class="tok-nx">hi</span> <span class="tok-o">:</span> <span class="tok-mi">2</span> <span class="tok-p">,</span> <span class="tok-nx">lo</span> <span class="tok-o">:</span> <span class="tok-mi">3</span> <span class="tok-p">}</span></code></pre> </div> </div> <div class="paragraph"> <p>Option argument is also supported:</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">external</span> <span class="tok-n">make_config</span> <span class="tok-o">:</span> <span class="tok-n">hi</span><span class="tok-o">:</span><span class="tok-kt">int</span> <span class="tok-o">-></span> <span class="tok-o">?</span><span class="tok-n">lo</span><span class="tok-o">:</span><span class="tok-kt">int</span> <span class="tok-o">-></span> <span class="tok-kt">unit</span> <span class="tok-o">-></span> <span class="tok-n">t</span> <span class="tok-o">=</span> <span class="tok-s2">""</span> <span class="tok-o">[@@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">obj</span><span class="tok-o">]</span> <b class="conum">(1)</b> <span class="tok-k">let</span> <span class="tok-n">u</span> <span class="tok-o">=</span> <span class="tok-n">make_config</span> <span class="tok-o">~</span><span class="tok-n">hi</span><span class="tok-o">:</span><span class="tok-mi">3</span> <span class="tok-bp">()</span> <span class="tok-k">let</span> <span class="tok-n">v</span> <span class="tok-o">=</span> <span class="tok-n">make_config</span> <span class="tok-o">~</span><span class="tok-n">lo</span><span class="tok-o">:</span><span class="tok-mi">2</span> <span class="tok-o">~</span><span class="tok-n">hi</span><span class="tok-o">:</span><span class="tok-mi">3</span> <span class="tok-bp">()</span></code></pre> </div> </div> <div class="colist arabic"> <ol> <li> <p>In OCaml, the order of label does not matter, and the evaluation order of arguments is undefined. Since the order does not matter, to make sure the compiler realize all the arguments are fulfilled (including optional arguments), it is common to have a <code>unit</code> type before the result.</p> </li> </ol> </div> <div class="listingblock"> <div class="title">Output:</div> <div class="content"> <pre class="pygments highlight"><code data-lang="js"><span class="tok-kd">var</span> <span class="tok-nx">u</span> <span class="tok-o">=</span> <span class="tok-p">{</span><span class="tok-nx">hi</span> <span class="tok-o">:</span> <span class="tok-mi">3</span><span class="tok-p">}</span> <span class="tok-kd">var</span> <span class="tok-nx">v</span> <span class="tok-o">=</span> <span class="tok-p">{</span><span class="tok-nx">hi</span> <span class="tok-o">:</span> <span class="tok-mi">3</span> <span class="tok-p">,</span> <span class="tok-nx">lo</span><span class="tok-o">:</span> <span class="tok-mi">2</span><span class="tok-p">}</span></code></pre> </div> </div> <div class="paragraph"> <p>Now, we can write JS style code in OCaml too (in a type safe way):</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">let</span> <span class="tok-n">u</span> <span class="tok-o">=</span> <span class="tok-o">[%</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">obj</span> <span class="tok-o">{</span> <span class="tok-n">x</span> <span class="tok-o">=</span> <span class="tok-o">{</span> <span class="tok-n">y</span> <span class="tok-o">=</span> <span class="tok-o">{</span> <span class="tok-n">z</span> <span class="tok-o">=</span> <span class="tok-mi">3</span> <span class="tok-o">}</span> <span class="tok-o">};</span> <span class="tok-n">fn</span> <span class="tok-o">=</span> <span class="tok-k">fun</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">]</span> <span class="tok-n">u</span> <span class="tok-n">v</span> <span class="tok-o">-></span> <span class="tok-n">u</span> <span class="tok-o">+</span> <span class="tok-n">v</span> <b class="conum">(1)</b> <span class="tok-o">}</span> <span class="tok-o">]</span> <span class="tok-k">let</span> <span class="tok-n">h</span> <span class="tok-o">=</span> <span class="tok-n">u</span><span class="tok-o">##</span><span class="tok-n">x</span><span class="tok-o">##</span><span class="tok-n">y</span><span class="tok-o">##</span><span class="tok-n">z</span> <span class="tok-k">let</span> <span class="tok-n">a</span> <span class="tok-o">=</span> <span class="tok-n">u</span><span class="tok-o">##</span><span class="tok-n">fn</span> <span class="tok-k">let</span> <span class="tok-n">b</span> <span class="tok-o">=</span> <span class="tok-n">a</span> <span class="tok-mi">1</span> <span class="tok-mi">2</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">]</span></code></pre> </div> </div> <div class="colist arabic"> <ol> <li> <p><code>fn</code> property is not method, it does not rely on <code>this</code>. We will show how to create JS method in OCaml later.</p> </li> </ol> </div> <div class="listingblock"> <div class="title">Output:</div> <div class="content"> <pre class="pygments highlight"><code data-lang="js"><span class="tok-kd">var</span> <span class="tok-nx">u</span> <span class="tok-o">=</span> <span class="tok-p">{</span> <span class="tok-nx">x</span> <span class="tok-o">:</span> <span class="tok-p">{</span> <span class="tok-nx">y</span> <span class="tok-o">:</span> <span class="tok-p">{</span> <span class="tok-nx">z</span> <span class="tok-o">:</span> <span class="tok-mi">3</span> <span class="tok-p">}</span> <span class="tok-p">},</span> <span class="tok-nx">fn</span> <span class="tok-o">:</span> <span class="tok-kd">function</span> <span class="tok-p">(</span><span class="tok-nx">u</span><span class="tok-p">,</span> <span class="tok-nx">v</span><span class="tok-p">)</span> <span class="tok-p">{</span><span class="tok-k">return</span> <span class="tok-nx">u</span> <span class="tok-o">+</span> <span class="tok-nx">v</span><span class="tok-p">}}</span> <span class="tok-kd">var</span> <span class="tok-nx">h</span> <span class="tok-o">=</span> <span class="tok-nx">u</span><span class="tok-p">.</span><span class="tok-nx">x</span><span class="tok-p">.</span><span class="tok-nx">y</span><span class="tok-p">.</span><span class="tok-nx">z</span> <span class="tok-kd">var</span> <span class="tok-nx">a</span> <span class="tok-o">=</span> <span class="tok-nx">u</span><span class="tok-p">.</span><span class="tok-nx">fn</span> <span class="tok-kd">var</span> <span class="tok-nx">b</span> <span class="tok-o">=</span> <span class="tok-nx">a</span><span class="tok-p">(</span><span class="tok-mi">1</span><span class="tok-p">,</span><span class="tok-mi">2</span><span class="tok-p">)</span></code></pre> </div> </div> <div class="admonitionblock note"> <table> <tr> <td class="icon"> <div class="title">Note</div> </td> <td class="content"> <div class="paragraph"> <p>When the field is an uncurried function, a short-hand syntax <code>#@</code> is available:</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">let</span> <span class="tok-n">b</span> <span class="tok-n">x</span> <span class="tok-n">y</span> <span class="tok-n">h</span> <span class="tok-o">=</span> <span class="tok-n">h</span><span class="tok-o">#@</span><span class="tok-n">fn</span> <span class="tok-n">x</span> <span class="tok-n">y</span></code></pre> </div> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="js"><span class="tok-kd">function</span> <span class="tok-nx">b</span> <span class="tok-p">(</span><span class="tok-nx">x</span><span class="tok-p">,</span><span class="tok-nx">y</span><span class="tok-p">,</span><span class="tok-nx">h</span><span class="tok-p">){</span> <span class="tok-k">return</span> <span class="tok-nx">h</span><span class="tok-p">.</span><span class="tok-nx">fn</span><span class="tok-p">(</span><span class="tok-nx">x</span><span class="tok-p">,</span><span class="tok-nx">y</span><span class="tok-p">)</span> <span class="tok-p">}</span></code></pre> </div> </div> <div class="paragraph"> <p>The compiler will infer the type of <code>b</code> as</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">val</span> <span class="tok-n">b</span> <span class="tok-o">:</span> <span class="tok-k">'</span><span class="tok-n">a</span> <span class="tok-o">-></span> <span class="tok-k">'</span><span class="tok-n">b</span> <span class="tok-o">-></span> <span class="tok-o"><</span> <span class="tok-n">fn</span> <span class="tok-o">:</span> <span class="tok-k">'</span><span class="tok-n">a</span> <span class="tok-o">-></span> <span class="tok-k">'</span><span class="tok-n">b</span> <span class="tok-o">-></span> <span class="tok-k">'</span><span class="tok-n">c</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">]</span> <span class="tok-o">></span> <span class="tok-nn">Js</span><span class="tok-p">.</span><span class="tok-n">t</span> <span class="tok-o">-></span> <span class="tok-k">'</span><span class="tok-n">c</span></code></pre> </div> </div> </td> </tr> </table> </div> </div> <div class="sect3"> <h4 id="_create_js_objects_with_code_this_code_semantics"><a class="anchor" href="#_create_js_objects_with_code_this_code_semantics"></a>Create JS objects with <code>this</code> semantics</h4> <div class="paragraph"> <p>The objects created above can not use <code>this</code> in the method, this is supported in BuckleScript too.</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">let</span> <span class="tok-n">v2</span> <span class="tok-o">=</span> <span class="tok-k">let</span> <span class="tok-n">x</span> <span class="tok-o">=</span> <span class="tok-mi">3</span><span class="tok-o">.</span> <span class="tok-k">in</span> <span class="tok-k">object</span> <span class="tok-o">(</span><span class="tok-n">self</span><span class="tok-o">)</span> <b class="conum">(1)</b> <span class="tok-k">method</span> <span class="tok-n">hi</span> <span class="tok-n">x</span> <span class="tok-n">y</span> <span class="tok-o">=</span> <span class="tok-n">self</span><span class="tok-o">##</span><span class="tok-n">say</span> <span class="tok-n">x</span> <span class="tok-o">+.</span> <span class="tok-n">y</span> <span class="tok-k">method</span> <span class="tok-n">say</span> <span class="tok-n">x</span> <span class="tok-o">=</span> <span class="tok-n">x</span> <span class="tok-o">*.</span> <span class="tok-n">self</span><span class="tok-o">##</span><span class="tok-n">x</span> <span class="tok-bp">()</span> <span class="tok-k">method</span> <span class="tok-n">x</span> <span class="tok-bp">()</span> <span class="tok-o">=</span> <span class="tok-n">x</span> <span class="tok-k">end</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">]</span> <b class="conum">(2)</b></code></pre> </div> </div> <div class="colist arabic"> <ol> <li> <p><code>self</code> is bound to <code>this</code> in generated JS code</p> </li> <li> <p><code>[@bs]</code> marks <code>object .. end</code> as a JS object</p> </li> </ol> </div> <div class="listingblock"> <div class="title">Output:</div> <div class="content"> <pre class="pygments highlight"><code data-lang="js"><span class="tok-kd">var</span> <span class="tok-nx">v2</span> <span class="tok-o">=</span> <span class="tok-p">{</span> <span class="tok-nx">hi</span><span class="tok-o">:</span> <span class="tok-kd">function</span> <span class="tok-p">(</span><span class="tok-nx">x</span><span class="tok-p">,</span> <span class="tok-nx">y</span><span class="tok-p">)</span> <span class="tok-p">{</span> <span class="tok-kd">var</span> <span class="tok-nx">self</span> <span class="tok-o">=</span> <span class="tok-k">this</span> <span class="tok-p">;</span> <span class="tok-k">return</span> <span class="tok-nx">self</span><span class="tok-p">.</span><span class="tok-nx">say</span><span class="tok-p">(</span><span class="tok-nx">x</span><span class="tok-p">)</span> <span class="tok-o">+</span> <span class="tok-nx">y</span><span class="tok-p">;</span> <span class="tok-p">},</span> <span class="tok-nx">say</span><span class="tok-o">:</span> <span class="tok-kd">function</span> <span class="tok-p">(</span><span class="tok-nx">x</span><span class="tok-p">)</span> <span class="tok-p">{</span> <span class="tok-kd">var</span> <span class="tok-nx">self</span> <span class="tok-o">=</span> <span class="tok-k">this</span> <span class="tok-p">;</span> <span class="tok-k">return</span> <span class="tok-nx">x</span> <span class="tok-o">*</span> <span class="tok-nx">self</span><span class="tok-p">.</span><span class="tok-nx">x</span><span class="tok-p">();</span> <span class="tok-p">},</span> <span class="tok-nx">x</span><span class="tok-o">:</span> <span class="tok-kd">function</span> <span class="tok-p">()</span> <span class="tok-p">{</span> <span class="tok-k">return</span> <span class="tok-mi">3</span><span class="tok-p">;</span> <span class="tok-p">}</span> <span class="tok-p">};</span></code></pre> </div> </div> <div class="paragraph"> <p>Compiler infers the type of <code>v2</code> as below:</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">val</span> <span class="tok-n">v2</span> <span class="tok-o">:</span> <span class="tok-o"><</span> <span class="tok-n">hi</span> <span class="tok-o">:</span> <span class="tok-kt">float</span> <span class="tok-o">-></span> <span class="tok-kt">float</span> <span class="tok-o">-></span> <span class="tok-kt">float</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">meth</span><span class="tok-o">];</span> <span class="tok-n">say</span> <span class="tok-o">:</span> <span class="tok-kt">float</span> <span class="tok-o">-></span> <span class="tok-kt">float</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">meth</span><span class="tok-o">];</span> <span class="tok-n">x</span> <span class="tok-o">:</span> <span class="tok-kt">unit</span> <span class="tok-o">-></span> <span class="tok-kt">float</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">meth</span><span class="tok-o">]</span> <span class="tok-o">></span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">]</span></code></pre> </div> </div> <div class="paragraph"> <p>Below is another example to consume a JS object :</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">let</span> <span class="tok-n">f</span> <span class="tok-o">(</span><span class="tok-n">u</span> <span class="tok-o">:</span> <span class="tok-n">rect</span><span class="tok-o">)</span> <span class="tok-o">=</span> <span class="tok-c">(* the type annotation is un-necessary,</span> <span class="tok-c"> but it gives better error message</span> <span class="tok-c"> *)</span> <span class="tok-nn">Js</span><span class="tok-p">.</span><span class="tok-n">log</span> <span class="tok-n">u</span><span class="tok-o">##</span><span class="tok-n">height</span><span class="tok-o">;</span> <span class="tok-nn">Js</span><span class="tok-p">.</span><span class="tok-n">log</span> <span class="tok-n">u</span><span class="tok-o">##</span><span class="tok-n">width</span><span class="tok-o">;</span> <span class="tok-n">u</span><span class="tok-o">##</span><span class="tok-n">width</span> <span class="tok-o">#=</span> <span class="tok-mi">30</span><span class="tok-o">;</span> <span class="tok-n">u</span><span class="tok-o">##</span><span class="tok-n">height</span> <span class="tok-o">#=</span> <span class="tok-mi">30</span><span class="tok-o">;</span> <span class="tok-n">u</span><span class="tok-o">##</span><span class="tok-n">draw</span> <span class="tok-bp">()</span></code></pre> </div> </div> <div class="listingblock"> <div class="title">Output:</div> <div class="content"> <pre class="pygments highlight"><code data-lang="js"><span class="tok-kd">function</span> <span class="tok-nx">f</span><span class="tok-p">(</span><span class="tok-nx">u</span><span class="tok-p">){</span> <span class="tok-nx">console</span><span class="tok-p">.</span><span class="tok-nx">log</span><span class="tok-p">(</span><span class="tok-nx">u</span><span class="tok-p">.</span><span class="tok-nx">height</span><span class="tok-p">);</span> <span class="tok-nx">console</span><span class="tok-p">.</span><span class="tok-nx">log</span><span class="tok-p">(</span><span class="tok-nx">u</span><span class="tok-p">.</span><span class="tok-nx">width</span><span class="tok-p">);</span> <span class="tok-nx">u</span><span class="tok-p">.</span><span class="tok-nx">width</span> <span class="tok-o">=</span> <span class="tok-mi">30</span><span class="tok-p">;</span> <span class="tok-nx">u</span><span class="tok-p">.</span><span class="tok-nx">height</span> <span class="tok-o">=</span> <span class="tok-mi">30</span><span class="tok-p">;</span> <span class="tok-k">return</span> <span class="tok-nx">u</span><span class="tok-p">.</span><span class="tok-nx">draw</span><span class="tok-p">()</span> <span class="tok-p">}</span></code></pre> </div> </div> <div class="sect4"> <h5 id="_method_chaining"><a class="anchor" href="#_method_chaining"></a>Method chaining</h5> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-n">f</span> <span class="tok-o">##(</span><span class="tok-n">meth0</span> <span class="tok-bp">()</span><span class="tok-o">)</span> <span class="tok-o">##(</span><span class="tok-n">meth1</span> <span class="tok-n">a</span><span class="tok-o">)</span> <span class="tok-o">##(</span><span class="tok-n">meth2</span> <span class="tok-n">a</span> <span class="tok-n">b</span><span class="tok-o">)</span></code></pre> </div> </div> </div> </div> <div class="sect3"> <h4 id="_object_label_translation_convention"><a class="anchor" href="#_object_label_translation_convention"></a>Object label translation convention</h4> <div class="paragraph"> <p>There are two cases, where we might want to do name mangling for a JS object method name.</p> </div> <div class="paragraph"> <p>First, in OCaml, some names are keywords, so we want to add an underscore to avoid a syntax error.</p> </div> <div class="listingblock"> <div class="title">Key-word method:</div> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-n">f</span><span class="tok-o">##_</span><span class="tok-n">open</span> <span class="tok-n">f</span><span class="tok-o">##_</span><span class="tok-n">MAX_LENGTH</span></code></pre> </div> </div> <div class="listingblock"> <div class="title">OUTPUT:</div> <div class="content"> <pre class="pygments highlight"><code data-lang="js"><span class="tok-nx">f</span><span class="tok-p">.</span><span class="tok-nx">open</span> <span class="tok-nx">f</span><span class="tok-p">.</span><span class="tok-nx">MAX_LENGTH</span></code></pre> </div> </div> <div class="paragraph"> <p>Second, it is common to have several types for a single method. To model this ad-hoc polymorphism, we introduced a small convention when translating object labels, which is <em>occasionally</em> useful as below</p> </div> <div class="listingblock"> <div class="title">Ad-hoc polymorphism</div> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-n">f</span><span class="tok-o">##</span><span class="tok-n">draw__cat</span> <span class="tok-o">(</span><span class="tok-n">x</span><span class="tok-o">,</span><span class="tok-n">y</span><span class="tok-o">)</span> <span class="tok-n">f</span><span class="tok-o">##</span><span class="tok-n">draw__dog</span> <span class="tok-o">(</span><span class="tok-n">x</span><span class="tok-o">,</span><span class="tok-n">y</span><span class="tok-o">)</span></code></pre> </div> </div> <div class="listingblock"> <div class="title">OUTPUT:</div> <div class="content"> <pre class="pygments highlight"><code data-lang="js"><span class="tok-nx">f</span><span class="tok-p">.</span><span class="tok-nx">draw</span><span class="tok-p">(</span><span class="tok-nx">x</span><span class="tok-p">,</span><span class="tok-nx">y</span><span class="tok-p">)</span> <span class="tok-c1">// f.draw in JS can accept different types</span> <span class="tok-nx">f</span><span class="tok-p">.</span><span class="tok-nx">draw</span><span class="tok-p">(</span><span class="tok-nx">x</span><span class="tok-p">,</span><span class="tok-nx">y</span><span class="tok-p">)</span></code></pre> </div> </div> <div class="admonitionblock note"> <table> <tr> <td class="icon"> <div class="title">Note</div> </td> <td class="content"> <div class="title">Rules</div> <div class="olist arabic"> <ol class="arabic"> <li> <p>If <code>__[rest]</code> appears in the label, index from the right to left.</p> <div class="ulist"> <ul> <li> <p>If index = 0, nothing mangled</p> </li> <li> <p>If index > 0, <code>__[rest]</code> is dropped</p> </li> </ul> </div> </li> <li> <p>Else if <code>_</code> is the first char</p> <div class="ulist"> <ul> <li> <p>If the following char is not 'a' .. 'z', drop the first '_'</p> </li> <li> <p>Else if the rest happens to be a keyword, drop the first '_'</p> </li> <li> <p>Else, nothing mangled</p> </li> </ul> </div> </li> </ol> </div> </td> </tr> </table> </div> </div> </div> <div class="sect2"> <h3 id="_return_value_checking_since_1_5_1"><a class="anchor" href="#_return_value_checking_since_1_5_1"></a>Return value checking (@since 1.5.1)</h3> <div class="paragraph"> <p>In general, the FFI code is error prone, and potentially will leak in <code>undefined</code> or <code>null</code> values.</p> </div> <div class="paragraph"> <p>So we introduced auto coercion for return values to gain two benefits:</p> </div> <div class="olist arabic"> <ol class="arabic"> <li> <p>More safety for FFI code without performance cost (explained later).</p> </li> <li> <p>More idiomatic OCaml code for users to consume the FFI.</p> </li> </ol> </div> <div class="paragraph"> <p>Below is a contrived core example:</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">type</span> <span class="tok-n">element</span> <span class="tok-k">type</span> <span class="tok-n">dom</span> <span class="tok-k">external</span> <span class="tok-n">getElementById</span> <span class="tok-o">:</span> <span class="tok-kt">string</span> <span class="tok-o">-></span> <span class="tok-n">element</span> <span class="tok-n">option</span> <span class="tok-o">=</span> <span class="tok-s2">""</span> <span class="tok-o">[@@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">send</span><span class="tok-o">.</span><span class="tok-n">pipe</span><span class="tok-o">:</span><span class="tok-n">dom</span><span class="tok-o">]</span> <span class="tok-o">[@@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">return</span> <span class="tok-n">nullable</span><span class="tok-o">]</span> <b class="conum">(1)</b> <span class="tok-k">let</span> <span class="tok-n">test</span> <span class="tok-n">dom</span> <span class="tok-o">=</span> <span class="tok-k">let</span> <span class="tok-n">elem</span> <span class="tok-o">=</span> <span class="tok-n">dom</span> <span class="tok-o">|></span> <span class="tok-n">getElementById</span> <span class="tok-s2">"haha"</span> <span class="tok-k">in</span> <span class="tok-k">match</span> <span class="tok-n">elem</span> <span class="tok-k">with</span> <span class="tok-o">|</span> <span class="tok-nc">None</span> <span class="tok-o">-></span> <span class="tok-mi">1</span> <span class="tok-o">|</span> <span class="tok-nc">Some</span> <span class="tok-n">ui</span> <span class="tok-o">-></span> <span class="tok-nn">Js</span><span class="tok-p">.</span><span class="tok-n">log</span> <span class="tok-n">ui</span> <span class="tok-o">;</span> <span class="tok-mi">2</span></code></pre> </div> </div> <div class="colist arabic"> <ol> <li> <p><code>nullable</code> attribute will automatically convert null and undefined to <code>option</code></p> </li> </ol> </div> <div class="listingblock"> <div class="title">Output:</div> <div class="content"> <pre class="pygments highlight"><code data-lang="js"><span class="tok-kd">function</span> <span class="tok-nx">test</span><span class="tok-p">(</span><span class="tok-nx">dom</span><span class="tok-p">)</span> <span class="tok-p">{</span> <span class="tok-kd">var</span> <span class="tok-nx">elem</span> <span class="tok-o">=</span> <span class="tok-nx">dom</span><span class="tok-p">.</span><span class="tok-nx">getElementById</span><span class="tok-p">(</span><span class="tok-s2">"haha"</span><span class="tok-p">);</span> <span class="tok-k">if</span> <span class="tok-p">(</span><span class="tok-nx">elem</span> <span class="tok-o">==</span> <span class="tok-kc">null</span><span class="tok-p">)</span> <span class="tok-p">{</span> <span class="tok-k">return</span> <span class="tok-mi">1</span><span class="tok-p">;</span> <span class="tok-p">}</span> <span class="tok-k">else</span> <span class="tok-p">{</span> <span class="tok-nx">console</span><span class="tok-p">.</span><span class="tok-nx">log</span><span class="tok-p">(</span><span class="tok-nx">elem</span><span class="tok-p">);</span> <span class="tok-k">return</span> <span class="tok-mi">2</span><span class="tok-p">;</span> <span class="tok-p">}</span> <span class="tok-p">}</span></code></pre> </div> </div> <div class="paragraph"> <p>Currently 4 directives are supported: <code>null_to_opt</code>, <code>undefined_to_opt</code>, <code>nullable</code>(introduced in @1.9.0) and <code>identity</code>. <code>null_undefined_to_opt</code> works the same as <code>nullable</code>, but it is deprecated, <code>nullable</code> is encouraged</p> </div> <div class="admonitionblock note"> <table> <tr> <td class="icon"> <div class="title">Note</div> </td> <td class="content"> <div class="paragraph"> <p><code>null_to_opt</code>, <code>undefined_to_opt</code> and <code>nullable</code> will <strong>semantically</strong> convert a nullable value to <code>option</code> which is a boxed value, but the compiler will do smart optimizations to <strong>remove such boxing overhead</strong> when the returned value is destructed in the same routine.</p> </div> <div class="paragraph"> <p>The three directives above require users to write literally <code>_ option</code>. It is in theory not necessary, but it is required to reduce user errors.</p> </div> <div class="paragraph"> <p>When the return type is <code>unit</code>: the compiler will append its return value with an OCaml <code>unit</code> literal to make sure it does return <code>unit</code>. Its main purpose is to make the user consume FFI in idiomatic OCaml code, the cost is <strong>very very small</strong> and the compiler will do smart optimizations to remove it when the returned value is not used (mostly likely).</p> </div> <div class="paragraph"> <p>When the return type is <code>bool</code>, the compiler will coerce its return value from JS boolean to OCaml boolean. The cost is also <strong>very small</strong> and compiler will remove such coercion when it is not needed. Note even if your external FFI does return OCaml <code>bool</code> or <code>unit</code>, such implicit coercion will <strong>cause no harm</strong>.</p> </div> <div class="paragraph"> <p><code>identity</code> will make sure that compiler will do nothing about the returned value. It is rarely used, but introduced here for debugging purpose.</p> </div> </td> </tr> </table> </div> </div> <div class="sect2"> <h3 id="_mapping_between_js_values_and_ocaml_values_since_2_1_0"><a class="anchor" href="#_mapping_between_js_values_and_ocaml_values_since_2_1_0"></a>Mapping between JS values and OCaml values (@since 2.1.0)</h3> <div class="paragraph"> <p>BuckleScript already maps basic OCaml primitive types into JS primitive types, however, there are some cases where such direct mapping is technically challenging, we automate such process by providing a function to convert back and forth between idiomatic JS values and idiomatic OCaml values, the generated code is optimized for both performance and code size.</p> </div> <div class="sect3"> <h4 id="_mapping_js_int_enums_to_ocaml_enums_since_2_1_0"><a class="anchor" href="#_mapping_js_int_enums_to_ocaml_enums_since_2_1_0"></a>Mapping JS Int enums to OCaml enums (@since 2.1.0)</h4> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">type</span> <span class="tok-n">t</span> <span class="tok-o">=</span> <span class="tok-o">|</span> <span class="tok-nc">A0</span> <span class="tok-o">|</span> <span class="tok-nc">A1</span> <span class="tok-o">|</span> <span class="tok-nc">A2</span> <span class="tok-o">|</span> <span class="tok-nc">A3</span> <span class="tok-o">|</span> <span class="tok-nc">A4</span> <span class="tok-o">[@@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">deriving</span> <span class="tok-n">jsConverter</span><span class="tok-o">]</span></code></pre> </div> </div> <div class="paragraph"> <p>This will derive two functions</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">val</span> <span class="tok-n">tToJs</span> <span class="tok-o">:</span> <span class="tok-n">t</span> <span class="tok-o">-></span> <span class="tok-kt">int</span> <span class="tok-k">val</span> <span class="tok-n">tFromJs</span> <span class="tok-o">:</span> <span class="tok-kt">int</span> <span class="tok-o">-></span> <span class="tok-n">t</span> <span class="tok-n">option</span></code></pre> </div> </div> <div class="paragraph"> <p>Note here by default <code>Ai</code> is mapped into <code>i</code>, but we can customie it as follows:</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">type</span> <span class="tok-n">t</span> <span class="tok-o">=</span> <span class="tok-o">|</span> <span class="tok-nc">A0</span> <span class="tok-o">|</span> <span class="tok-nc">A1</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-k">as</span> <span class="tok-mi">3</span><span class="tok-o">]</span> <span class="tok-o">|</span> <span class="tok-nc">A2</span> <span class="tok-o">|</span> <span class="tok-nc">A3</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-k">as</span> <span class="tok-mi">7</span><span class="tok-o">]</span> <span class="tok-o">|</span> <span class="tok-nc">A4</span> <span class="tok-o">[@@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">deriving</span> <span class="tok-n">jsConverter</span><span class="tok-o">]</span></code></pre> </div> </div> <div class="paragraph"> <p>In this case, <code>A0</code> is 0, <code>A1</code> is 3, <code>A2</code> is 4, <code>A3</code> is 7, <code>A4</code> is 8.</p> </div> <div class="paragraph"> <p>Note the above derived js type is transparent: <code>int</code>, if we want to provide more type safety, we can annotate it as below:</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">type</span> <span class="tok-n">t</span> <span class="tok-o">=</span> <span class="tok-o">|</span> <span class="tok-nc">A0</span> <span class="tok-o">|</span> <span class="tok-nc">A1</span> <span class="tok-o">|</span> <span class="tok-nc">A2</span> <span class="tok-o">|</span> <span class="tok-nc">A3</span> <span class="tok-o">|</span> <span class="tok-nc">A4</span> <span class="tok-o">[@@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">deriving</span> <span class="tok-o">{</span><span class="tok-n">jsConverter</span> <span class="tok-o">=</span> <span class="tok-n">newType</span><span class="tok-o">}</span> <span class="tok-o">]</span></code></pre> </div> </div> <div class="paragraph"> <p>In this case, it would generate two functions of such type, note <code>newType</code> means a new type declaration (by default to be abstract) is created:</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">val</span> <span class="tok-n">tToJs</span> <span class="tok-o">:</span> <span class="tok-n">t</span> <span class="tok-o">-></span> <span class="tok-n">abs_t</span> <span class="tok-k">val</span> <span class="tok-n">tFromJs</span> <span class="tok-o">:</span> <span class="tok-n">abs_t</span> <span class="tok-o">-></span> <span class="tok-n">t</span></code></pre> </div> </div> <div class="paragraph"> <p>Note the derived type is slightly different, since <code>abs_t</code> is abstrac type, we assume it is well structured value, so it should always return value of type <code>t</code> instead of <code>t option</code>.</p> </div> <div class="paragraph"> <p>The <code>bs.deriving</code> also applies to the signature file, so that users don’t have to write generate functions manually</p> </div> </div> <div class="sect3"> <h4 id="_mapping_js_string_enums_to_ocaml_enums_since_2_1_0"><a class="anchor" href="#_mapping_js_string_enums_to_ocaml_enums_since_2_1_0"></a>Mapping JS string enums to OCaml enums (@since 2.1.0)</h4> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">type</span> <span class="tok-n">t</span> <span class="tok-o">=</span> <span class="tok-o">[</span> <span class="tok-o">|</span> <span class="tok-o">`</span><span class="tok-nc">A0</span> <span class="tok-o">|</span> <span class="tok-o">`</span><span class="tok-nc">A1</span> <span class="tok-o">|</span> <span class="tok-o">`</span><span class="tok-nc">A2</span> <span class="tok-o">|</span> <span class="tok-o">`</span><span class="tok-nc">A3</span> <span class="tok-o">|</span> <span class="tok-o">`</span><span class="tok-nc">A4</span> <span class="tok-o">]</span> <span class="tok-o">[@@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">deriving</span> <span class="tok-n">jsConverter</span><span class="tok-o">]</span></code></pre> </div> </div> <div class="paragraph"> <p>This will derive two functions</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">val</span> <span class="tok-n">tToJs</span> <span class="tok-o">:</span> <span class="tok-n">t</span> <span class="tok-o">-></span> <span class="tok-kt">string</span> <span class="tok-k">val</span> <span class="tok-n">tFromJs</span> <span class="tok-o">:</span> <span class="tok-kt">string</span> <span class="tok-o">-></span> <span class="tok-n">t</span> <span class="tok-n">option</span></code></pre> </div> </div> <div class="paragraph"> <p>Note here by default <code>Ai</code> is mapped into <code>"Ai"</code>, but we can customie it as follows:</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">type</span> <span class="tok-n">t</span> <span class="tok-o">=</span> <span class="tok-o">[</span> <span class="tok-o">|</span> <span class="tok-o">`</span><span class="tok-nc">A0</span> <span class="tok-o">|</span> <span class="tok-o">`</span><span class="tok-nc">A1</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-k">as</span> <span class="tok-s2">"c"</span><span class="tok-o">]</span> <span class="tok-o">|</span> <span class="tok-o">`</span><span class="tok-nc">A2</span> <span class="tok-o">|</span> <span class="tok-o">`</span><span class="tok-nc">A3</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-k">as</span> <span class="tok-s2">"d"</span><span class="tok-o">]</span> <span class="tok-o">|</span> <span class="tok-o">`</span><span class="tok-nc">A4</span> <span class="tok-o">]</span> <span class="tok-o">[@@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">deriving</span> <span class="tok-n">jsConverter</span><span class="tok-o">]</span></code></pre> </div> </div> <div class="paragraph"> <p>Note the above derived js type is transparent: <code>string</code>, if we want to provide more type safety, we can annotate it as below:</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">type</span> <span class="tok-n">t</span> <span class="tok-o">=</span> <span class="tok-o">[</span> <span class="tok-o">|</span> <span class="tok-o">`</span><span class="tok-nc">A0</span> <span class="tok-o">|</span> <span class="tok-o">`</span><span class="tok-nc">A1</span> <span class="tok-o">|</span> <span class="tok-o">`</span><span class="tok-nc">A2</span> <span class="tok-o">|</span> <span class="tok-o">`</span><span class="tok-nc">A3</span> <span class="tok-o">|</span> <span class="tok-o">`</span><span class="tok-nc">A4</span> <span class="tok-o">]</span> <span class="tok-o">[@@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">deriving</span> <span class="tok-o">{</span><span class="tok-n">jsConverter</span> <span class="tok-o">=</span> <span class="tok-n">newType</span><span class="tok-o">}</span> <span class="tok-o">]</span></code></pre> </div> </div> <div class="paragraph"> <p>In this case, it would generate two functions of such type:</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">val</span> <span class="tok-n">tToJs</span> <span class="tok-o">:</span> <span class="tok-n">t</span> <span class="tok-o">-></span> <span class="tok-n">abs_t</span> <span class="tok-k">val</span> <span class="tok-n">tFromJs</span> <span class="tok-o">:</span> <span class="tok-n">abs_t</span> <span class="tok-o">-></span> <span class="tok-n">t</span></code></pre> </div> </div> <div class="paragraph"> <p>Note the derived type is slightly different, since <code>abs_t</code> is abstrac type, we assume it is well structured value, so it should always return value of type <code>t</code> instead of type <code>t option</code>.</p> </div> <div class="paragraph"> <p>The <code>bs.deriving</code> also applies to the signature file, so that users don’t have to write generate functions manually</p> </div> </div> <div class="sect3"> <h4 id="_mapping_js_objects_to_ocaml_records_since_2_1_0"><a class="anchor" href="#_mapping_js_objects_to_ocaml_records_since_2_1_0"></a>Mapping JS objects to OCaml records (@since 2.1.0)</h4> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">type</span> <span class="tok-n">t</span> <span class="tok-o">=</span> <span class="tok-o">{</span> <span class="tok-n">x</span> <span class="tok-o">:</span> <span class="tok-kt">int</span> <span class="tok-o">;</span> <span class="tok-n">y</span> <span class="tok-o">:</span> <span class="tok-kt">int</span> <span class="tok-o">}</span> <span class="tok-o">[@@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">deriving</span> <span class="tok-n">jsConverter</span><span class="tok-o">]</span></code></pre> </div> </div> <div class="paragraph"> <p>This will derive two functions:</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">val</span> <span class="tok-n">tToJs</span> <span class="tok-o">:</span> <span class="tok-n">t</span> <span class="tok-o">-></span> <span class="tok-o"><</span><span class="tok-n">x</span> <span class="tok-o">:</span> <span class="tok-kt">int</span> <span class="tok-o">;</span> <span class="tok-n">y</span> <span class="tok-o">:</span> <span class="tok-kt">int</span> <span class="tok-o">></span> <span class="tok-nn">Js</span><span class="tok-p">.</span><span class="tok-n">t</span> <span class="tok-k">val</span> <span class="tok-n">tFromJs</span> <span class="tok-o">:</span> <span class="tok-o"><</span> <span class="tok-n">x</span><span class="tok-o">;</span> <span class="tok-kt">int</span> <span class="tok-o">;</span> <span class="tok-n">y</span> <span class="tok-o">:</span> <span class="tok-kt">int</span> <span class="tok-o">;</span> <span class="tok-o">..</span> <span class="tok-o">></span> <span class="tok-nn">Js</span><span class="tok-p">.</span><span class="tok-n">t</span> <span class="tok-o">-></span> <span class="tok-n">t</span></code></pre> </div> </div> <div class="paragraph"> <p>Note that the input of <code>tFromJs</code> is open type so that it is more permissive.</p> </div> <div class="paragraph"> <p>Note the above derived js type is transparent, if we want to provide more type safety, we can annotate it as below:</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">type</span> <span class="tok-n">t</span> <span class="tok-o">=</span> <span class="tok-o">{</span> <span class="tok-n">x</span> <span class="tok-o">:</span> <span class="tok-kt">int</span> <span class="tok-o">;</span> <span class="tok-n">y</span> <span class="tok-o">:</span> <span class="tok-kt">int</span> <span class="tok-o">}</span> <span class="tok-o">[@@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">deriving</span> <span class="tok-o">{</span><span class="tok-n">jsConverter</span><span class="tok-o">=</span> <span class="tok-n">newType</span><span class="tok-o">}]</span></code></pre> </div> </div> <div class="paragraph"> <p>This will derive two functions:</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">val</span> <span class="tok-n">tToJs</span> <span class="tok-o">:</span> <span class="tok-n">t</span> <span class="tok-o">-></span> <span class="tok-n">abs_t</span> <span class="tok-k">val</span> <span class="tok-n">tFromJs</span> <span class="tok-o">:</span> <span class="tok-n">abs_t</span> <span class="tok-o">-></span> <span class="tok-n">t</span></code></pre> </div> </div> </div> </div> <div class="sect2"> <h3 id="_embedding_untyped_javascript_code"><a class="anchor" href="#_embedding_untyped_javascript_code"></a>Embedding untyped Javascript code</h3> <div class="admonitionblock warning"> <table> <tr> <td class="icon"> <div class="title">Warning</div> </td> <td class="content"> <div class="paragraph"> <p>This is not encouraged. The user should minimize and localize use cases of embedding raw JavaScript code, however, sometimes it’s necessary to get the job done.</p> </div> </td> </tr> </table> </div> <div class="sect3"> <h4 id="_detect_global_variable_existence_code_bs_external_code_since_1_5_1"><a class="anchor" href="#_detect_global_variable_existence_code_bs_external_code_since_1_5_1"></a>Detect global variable existence <code>bs.external</code> (@since 1.5.1)</h4> <div class="paragraph"> <p>Before we dive into embedding arbitrary JS code, a quite common use case of embedding untyped JS code is detect a global variable (feature detection), Bucklescript provides a relatively type safe approach for such use case: <code>bs.external</code> (or <code>external</code>), <code>[%bs.external a_single_identifier]</code> is a value of <code>_ option</code> type, see examples below</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">let</span> <span class="tok-n">test</span> <span class="tok-bp">()</span> <span class="tok-o">=</span> <span class="tok-k">match</span> <span class="tok-o">[%</span><span class="tok-k">external</span> <span class="tok-o">__</span><span class="tok-n">DEV__</span><span class="tok-o">]</span> <span class="tok-k">with</span> <span class="tok-o">|</span> <span class="tok-nc">Some</span> <span class="tok-o">_</span> <span class="tok-o">-></span> <span class="tok-nn">Js</span><span class="tok-p">.</span><span class="tok-n">log</span> <span class="tok-s2">"dev mode"</span> <span class="tok-o">|</span> <span class="tok-nc">None</span> <span class="tok-o">-></span> <span class="tok-nn">Js</span><span class="tok-p">.</span><span class="tok-n">log</span> <span class="tok-s2">"production mode"</span></code></pre> </div> </div> <div class="listingblock"> <div class="title">Output:</div> <div class="content"> <pre class="pygments highlight"><code data-lang="js"><span class="tok-kd">function</span> <span class="tok-nx">test</span><span class="tok-p">()</span> <span class="tok-p">{</span> <span class="tok-kd">var</span> <span class="tok-nx">match</span> <span class="tok-o">=</span> <span class="tok-k">typeof</span> <span class="tok-p">(</span><span class="tok-nx">__DEV__</span><span class="tok-p">)</span> <span class="tok-o">===</span> <span class="tok-s2">"undefined"</span> <span class="tok-o">?</span> <span class="tok-kc">undefined</span> <span class="tok-o">:</span> <span class="tok-p">(</span><span class="tok-nx">__DEV__</span><span class="tok-p">);</span> <span class="tok-k">if</span> <span class="tok-p">(</span><span class="tok-nx">match</span> <span class="tok-o">!==</span> <span class="tok-kc">undefined</span><span class="tok-p">)</span> <span class="tok-p">{</span> <span class="tok-nx">console</span><span class="tok-p">.</span><span class="tok-nx">log</span><span class="tok-p">(</span><span class="tok-s2">"dev mode"</span><span class="tok-p">);</span> <span class="tok-k">return</span> <span class="tok-cm">/* () */</span><span class="tok-mi">0</span><span class="tok-p">;</span> <span class="tok-p">}</span> <span class="tok-k">else</span> <span class="tok-p">{</span> <span class="tok-nx">console</span><span class="tok-p">.</span><span class="tok-nx">log</span><span class="tok-p">(</span><span class="tok-s2">"production mode"</span><span class="tok-p">);</span> <span class="tok-k">return</span> <span class="tok-cm">/* () */</span><span class="tok-mi">0</span><span class="tok-p">;</span> <span class="tok-p">}</span> <span class="tok-p">}</span></code></pre> </div> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">let</span> <span class="tok-n">test2</span> <span class="tok-bp">()</span> <span class="tok-o">=</span> <span class="tok-k">match</span> <span class="tok-o">[%</span><span class="tok-k">external</span> <span class="tok-o">__</span><span class="tok-n">filename</span><span class="tok-o">]</span> <span class="tok-k">with</span> <span class="tok-o">|</span> <span class="tok-nc">Some</span> <span class="tok-n">f</span> <span class="tok-o">-></span> <span class="tok-nn">Js</span><span class="tok-p">.</span><span class="tok-n">log</span> <span class="tok-n">f</span> <span class="tok-o">|</span> <span class="tok-nc">None</span> <span class="tok-o">-></span> <span class="tok-nn">Js</span><span class="tok-p">.</span><span class="tok-n">log</span> <span class="tok-s2">"non node environment"</span></code></pre> </div> </div> <div class="listingblock"> <div class="title">Output:</div> <div class="content"> <pre class="pygments highlight"><code data-lang="js"><span class="tok-kd">function</span> <span class="tok-nx">test2</span><span class="tok-p">()</span> <span class="tok-p">{</span> <span class="tok-kd">var</span> <span class="tok-nx">match</span> <span class="tok-o">=</span> <span class="tok-k">typeof</span> <span class="tok-p">(</span><span class="tok-nx">__filename</span><span class="tok-p">)</span> <span class="tok-o">===</span> <span class="tok-s2">"undefined"</span> <span class="tok-o">?</span> <span class="tok-kc">undefined</span> <span class="tok-o">:</span> <span class="tok-p">(</span><span class="tok-nx">__filename</span><span class="tok-p">);</span> <span class="tok-k">if</span> <span class="tok-p">(</span><span class="tok-nx">match</span> <span class="tok-o">!==</span> <span class="tok-kc">undefined</span><span class="tok-p">)</span> <span class="tok-p">{</span> <span class="tok-nx">console</span><span class="tok-p">.</span><span class="tok-nx">log</span><span class="tok-p">(</span><span class="tok-nx">match</span><span class="tok-p">);</span> <span class="tok-k">return</span> <span class="tok-cm">/* () */</span><span class="tok-mi">0</span><span class="tok-p">;</span> <span class="tok-p">}</span> <span class="tok-k">else</span> <span class="tok-p">{</span> <span class="tok-nx">console</span><span class="tok-p">.</span><span class="tok-nx">log</span><span class="tok-p">(</span><span class="tok-s2">"non node environment"</span><span class="tok-p">);</span> <span class="tok-k">return</span> <span class="tok-cm">/* () */</span><span class="tok-mi">0</span><span class="tok-p">;</span> <span class="tok-p">}</span> <span class="tok-p">}</span></code></pre> </div> </div> </div> <div class="sect3"> <h4 id="_embedding_arbitrary_js_code_as_an_expression"><a class="anchor" href="#_embedding_arbitrary_js_code_as_an_expression"></a>Embedding arbitrary JS code as an expression</h4> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">let</span> <span class="tok-n">keys</span> <span class="tok-o">:</span> <span class="tok-n">t</span> <span class="tok-o">-></span> <span class="tok-kt">string</span> <span class="tok-kt">array</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">]</span> <span class="tok-o">=</span> <span class="tok-o">[%</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">raw</span> <span class="tok-s2">"Object.keys"</span> <span class="tok-o">]</span> <span class="tok-k">let</span> <span class="tok-n">unsafe_lt</span> <span class="tok-o">:</span> <span class="tok-k">'</span><span class="tok-n">a</span> <span class="tok-o">-></span> <span class="tok-k">'</span><span class="tok-n">a</span> <span class="tok-o">-></span> <span class="tok-nn">Js</span><span class="tok-p">.</span><span class="tok-n">boolean</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">]</span> <span class="tok-o">=</span> <span class="tok-o">[%</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">raw</span><span class="tok-o">{|</span><span class="tok-k">function</span><span class="tok-o">(</span><span class="tok-n">x</span><span class="tok-o">,</span><span class="tok-n">y</span><span class="tok-o">){</span><span class="tok-n">return</span> <span class="tok-n">x</span> <span class="tok-o"><</span> <span class="tok-n">y</span><span class="tok-o">}|}]</span></code></pre> </div> </div> <div class="paragraph"> <p>We highly recommend writing type annotations for such unsafe code. It is unsafe to refer to external OCaml symbols in raw JS code.</p> </div> </div> <div class="sect3"> <h4 id="_embedding_raw_js_code_as_statements"><a class="anchor" href="#_embedding_raw_js_code_as_statements"></a>Embedding raw JS code as statements</h4> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="js"><span class="tok-p">[</span><span class="tok-o">%%</span><span class="tok-nx">bs</span><span class="tok-p">.</span><span class="tok-nx">raw</span><span class="tok-p">{</span><span class="tok-o">|</span> <span class="tok-nx">console</span><span class="tok-p">.</span><span class="tok-nx">log</span> <span class="tok-p">(</span><span class="tok-s2">"hey"</span><span class="tok-p">);</span> <span class="tok-o">|</span><span class="tok-p">}]</span></code></pre> </div> </div> <div class="paragraph"> <p>Other examples:</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">let</span> <span class="tok-n">x</span> <span class="tok-o">:</span> <span class="tok-kt">string</span> <span class="tok-o">=</span> <span class="tok-o">[%</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">raw</span><span class="tok-o">{|</span><span class="tok-s2">"</span><span class="tok-se">\x01\x02</span><span class="tok-s2">"</span><span class="tok-o">|}]</span></code></pre> </div> </div> <div class="paragraph"> <p>It will be compiled into:</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="js"><span class="tok-kd">var</span> <span class="tok-nx">x</span> <span class="tok-o">=</span> <span class="tok-s2">"\x01\x02"</span></code></pre> </div> </div> <div class="paragraph"> <p>Polyfill of <code>Math.imul</code></p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"> <span class="tok-o">[%%</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">raw</span><span class="tok-o">{|</span> <span class="tok-o">//</span> <span class="tok-nn">Math</span><span class="tok-p">.</span><span class="tok-n">imul</span> <span class="tok-n">polyfill</span> <span class="tok-k">if</span> <span class="tok-o">(!</span><span class="tok-nn">Math</span><span class="tok-p">.</span><span class="tok-n">imul</span><span class="tok-o">){</span> <span class="tok-nn">Math</span><span class="tok-p">.</span><span class="tok-n">imul</span> <span class="tok-o">=</span> <span class="tok-k">function</span> <span class="tok-o">(..)</span> <span class="tok-o">{..}</span> <span class="tok-o">}</span> <span class="tok-o">|}]</span></code></pre> </div> </div> <div class="admonitionblock warning"> <table> <tr> <td class="icon"> <div class="title">Warning</div> </td> <td class="content"> <div class="ulist"> <ul> <li> <p>So far we don’t perform any sanity checks in the quoted text (syntax checking is a long-term goal).</p> </li> <li> <p>Users should not refer to symbols in OCaml code. It is not guaranteed that the order is correct.</p> </li> </ul> </div> </td> </tr> </table> </div> </div> </div> <div class="sect2"> <h3 id="_debugger_support"><a class="anchor" href="#_debugger_support"></a>Debugger support</h3> <div class="paragraph"> <p>We introduced the extension <code>bs.debugger</code>, for example:</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"> <span class="tok-k">let</span> <span class="tok-n">f</span> <span class="tok-n">x</span> <span class="tok-n">y</span> <span class="tok-o">=</span> <span class="tok-o">[%</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">debugger</span><span class="tok-o">];</span> <span class="tok-n">x</span> <span class="tok-o">+</span> <span class="tok-n">y</span></code></pre> </div> </div> <div class="paragraph"> <p>which will be compiled into:</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="js"> <span class="tok-kd">function</span> <span class="tok-nx">f</span> <span class="tok-p">(</span><span class="tok-nx">x</span><span class="tok-p">,</span><span class="tok-nx">y</span><span class="tok-p">)</span> <span class="tok-p">{</span> <span class="tok-kr">debugger</span><span class="tok-p">;</span> <span class="tok-c1">// JavaScript developer tools will set an breakpoint and stop here</span> <span class="tok-nx">x</span> <span class="tok-o">+</span> <span class="tok-nx">y</span><span class="tok-p">;</span> <span class="tok-p">}</span></code></pre> </div> </div> </div> <div class="sect2"> <h3 id="_regex_support"><a class="anchor" href="#_regex_support"></a>Regex support</h3> <div class="paragraph"> <p>We introduced <code>bs.re</code> for Javascript regex expressions:</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">let</span> <span class="tok-n">f</span> <span class="tok-o">=</span> <span class="tok-o">[%</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">re</span> <span class="tok-s2">"/b/g"</span><span class="tok-o">]</span></code></pre> </div> </div> <div class="paragraph"> <p>The compiler will infer <code>f</code> has type <code>Js.Re.t</code> and generate code as below:</p> </div> <div class="listingblock"> <div class="content"> <pre>var f = /b/g</pre> </div> </div> <div class="admonitionblock note"> <table> <tr> <td class="icon"> <div class="title">Note</div> </td> <td class="content"> <code>Js.Re.t</code> can be accessed and manipulated using the functions available in the <a href="../api/Js.Re.html"><code>Js.Re</code></a> module. </td> </tr> </table> </div> </div> <div class="sect2"> <h3 id="_examples_2"><a class="anchor" href="#_examples_2"></a>Examples</h3> <div class="paragraph"> <p>Below is a simple example for the <a href="https://mochajs.org/">mocha</a> library. For more examples, please visit <a href="https://github.com/bucklescript/bucklescript-addons" class="bare">https://github.com/bucklescript/bucklescript-addons</a></p> </div> <div class="sect3"> <h4 id="_a_simple_example_binding_to_mocha_unit_test_library"><a class="anchor" href="#_a_simple_example_binding_to_mocha_unit_test_library"></a>A simple example: binding to mocha unit test library</h4> <div class="paragraph"> <p>This is an example showing how to provide bindings to the <a href="https://mochajs.org/">mochajs</a> unit test framework.</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">external</span> <span class="tok-n">describe</span> <span class="tok-o">:</span> <span class="tok-kt">string</span> <span class="tok-o">-></span> <span class="tok-o">(</span><span class="tok-kt">unit</span> <span class="tok-o">-></span> <span class="tok-kt">unit</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">])</span> <span class="tok-o">-></span> <span class="tok-kt">unit</span> <span class="tok-o">=</span> <span class="tok-s2">""</span> <span class="tok-o">[@@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-k">val</span><span class="tok-o">]</span> <span class="tok-k">external</span> <span class="tok-n">it</span> <span class="tok-o">:</span> <span class="tok-kt">string</span> <span class="tok-o">-></span> <span class="tok-o">(</span><span class="tok-kt">unit</span> <span class="tok-o">-></span> <span class="tok-kt">unit</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">])</span> <span class="tok-o">-></span> <span class="tok-kt">unit</span> <span class="tok-o">=</span> <span class="tok-s2">""</span> <span class="tok-o">[@@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-k">val</span><span class="tok-o">]</span></code></pre> </div> </div> <div class="paragraph"> <p>Since, <code>mochajs</code> is a test framework, we also need some assertion tests. We can also describe the bindings to <code>assert.deepEqual</code> from the nodejs <code>assert</code> library:</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">external</span> <span class="tok-n">eq</span> <span class="tok-o">:</span> <span class="tok-k">'</span><span class="tok-n">a</span> <span class="tok-o">-></span> <span class="tok-k">'</span><span class="tok-n">a</span> <span class="tok-o">-></span> <span class="tok-kt">unit</span> <span class="tok-o">=</span> <span class="tok-s2">"deepEqual"</span> <span class="tok-o">[@@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-k">module</span> <span class="tok-s2">"assert"</span><span class="tok-o">]</span></code></pre> </div> </div> <div class="paragraph"> <p>On top of this we can write normal OCaml functions, for example:</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">let</span> <span class="tok-n">assert_equal</span> <span class="tok-o">=</span> <span class="tok-n">eq</span> <span class="tok-k">let</span> <span class="tok-n">from_suites</span> <span class="tok-n">name</span> <span class="tok-n">suite</span> <span class="tok-o">=</span> <span class="tok-n">describe</span> <span class="tok-n">name</span> <span class="tok-o">(</span><span class="tok-k">fun</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">]</span> <span class="tok-bp">()</span> <span class="tok-o">-></span> <span class="tok-nn">List</span><span class="tok-p">.</span><span class="tok-n">iter</span> <span class="tok-o">(</span><span class="tok-k">fun</span> <span class="tok-o">(</span><span class="tok-n">name</span><span class="tok-o">,</span> <span class="tok-n">code</span><span class="tok-o">)</span> <span class="tok-o">-></span> <span class="tok-n">it</span> <span class="tok-n">name</span> <span class="tok-n">code</span><span class="tok-o">)</span> <span class="tok-n">suite</span> <span class="tok-o">)</span></code></pre> </div> </div> <div class="paragraph"> <p>The compiler would generate code as below:</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="js"> <span class="tok-kd">var</span> <span class="tok-nx">Assert</span> <span class="tok-o">=</span> <span class="tok-nx">require</span><span class="tok-p">(</span><span class="tok-s2">"assert"</span><span class="tok-p">);</span> <span class="tok-kd">var</span> <span class="tok-nx">List</span> <span class="tok-o">=</span> <span class="tok-nx">require</span><span class="tok-p">(</span><span class="tok-s2">"bs-platform/lib/js/list"</span><span class="tok-p">);</span> <span class="tok-kd">function</span> <span class="tok-nx">assert_equal</span><span class="tok-p">(</span><span class="tok-nx">prim</span><span class="tok-p">,</span> <span class="tok-nx">prim$1</span><span class="tok-p">)</span> <span class="tok-p">{</span> <span class="tok-k">return</span> <span class="tok-nx">Assert</span><span class="tok-p">.</span><span class="tok-nx">deepEqual</span><span class="tok-p">(</span><span class="tok-nx">prim</span><span class="tok-p">,</span> <span class="tok-nx">prim$1</span><span class="tok-p">);</span> <span class="tok-p">}</span> <span class="tok-kd">function</span> <span class="tok-nx">from_suites</span><span class="tok-p">(</span><span class="tok-nx">name</span><span class="tok-p">,</span> <span class="tok-nx">suite</span><span class="tok-p">)</span> <span class="tok-p">{</span> <span class="tok-k">return</span> <span class="tok-nx">describe</span><span class="tok-p">(</span><span class="tok-nx">name</span><span class="tok-p">,</span> <span class="tok-kd">function</span> <span class="tok-p">()</span> <span class="tok-p">{</span> <span class="tok-k">return</span> <span class="tok-nx">List</span><span class="tok-p">.</span><span class="tok-nx">iter</span><span class="tok-p">(</span><span class="tok-kd">function</span> <span class="tok-p">(</span><span class="tok-nx">param</span><span class="tok-p">)</span> <span class="tok-p">{</span> <span class="tok-k">return</span> <span class="tok-nx">it</span><span class="tok-p">(</span><span class="tok-nx">param</span><span class="tok-p">[</span><span class="tok-mi">0</span><span class="tok-p">],</span> <span class="tok-nx">param</span><span class="tok-p">[</span><span class="tok-mi">1</span><span class="tok-p">]);</span> <span class="tok-p">},</span> <span class="tok-nx">suite</span><span class="tok-p">);</span> <span class="tok-p">});</span> <span class="tok-p">}</span></code></pre> </div> </div> </div> </div> </div> </div> <div class="sect1"> <h2 id="_exception_handling_between_ocaml_and_js_since_1_7_0"><a class="anchor" href="#_exception_handling_between_ocaml_and_js_since_1_7_0"></a>Exception handling between OCaml and JS (@since 1.7.0)</h2> <div class="sectionbody"> <div class="paragraph"> <p>In the JS world, exception could be any data, while an OCaml exception is a structured data format and supports pattern matching. Catching an OCaml exception on JS side is therefore a no-op.</p> </div> <div class="paragraph"> <p>JS exceptions can be raised from OCaml by using the <code>JS.Exn.raise*</code> functions, and can be caught as an OCaml exception of the type <code>Js.Exn.Error</code> with the JS exception as it’s paylaod typed as <code>Js.Exn.t</code>. The JS Exception can then either be manipulated with the accessor functions in <code>Js.Exn</code>, or casted to a more appropriate type.</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">let</span> <span class="tok-bp">()</span> <span class="tok-o">=</span> <span class="tok-k">try</span> <span class="tok-nn">Js</span><span class="tok-p">.</span><span class="tok-nn">Exn</span><span class="tok-p">.</span><span class="tok-n">raiseError</span> <span class="tok-s2">"oops!"</span> <span class="tok-k">with</span> <span class="tok-o">|</span> <span class="tok-nn">Js</span><span class="tok-p">.</span><span class="tok-nn">Exn</span><span class="tok-p">.</span><span class="tok-nc">Error</span> <span class="tok-n">e</span> <span class="tok-o">-></span> <span class="tok-k">match</span> <span class="tok-nn">Js</span><span class="tok-p">.</span><span class="tok-nn">Exn</span><span class="tok-p">.</span><span class="tok-n">message</span> <span class="tok-n">e</span> <span class="tok-k">with</span> <span class="tok-o">|</span> <span class="tok-nc">Some</span> <span class="tok-n">message</span> <span class="tok-o">-></span> <span class="tok-nn">Js</span><span class="tok-p">.</span><span class="tok-n">log</span> <span class="tok-o">{</span><span class="tok-n">j</span><span class="tok-o">|</span><span class="tok-nc">Error</span><span class="tok-o">:</span> <span class="tok-o">$</span><span class="tok-n">message</span><span class="tok-o">|</span><span class="tok-n">j</span><span class="tok-o">}</span> <span class="tok-o">|</span> <span class="tok-nc">None</span> <span class="tok-o">-></span> <span class="tok-nn">Js</span><span class="tok-p">.</span><span class="tok-n">log</span> <span class="tok-s2">"An unknown error occurred"</span></code></pre> </div> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">let</span> <span class="tok-n">maybeParsed</span> <span class="tok-o">=</span> <span class="tok-k">match</span> <span class="tok-nn">Js</span><span class="tok-p">.</span><span class="tok-nn">Json</span><span class="tok-p">.</span><span class="tok-n">parseExn</span> <span class="tok-o">{|</span> <span class="tok-o">{</span><span class="tok-s2">"x"</span> <span class="tok-o">}|}</span> <span class="tok-k">with</span> <span class="tok-o">|</span> <span class="tok-k">value</span> <span class="tok-o">-></span> <span class="tok-nc">Some</span> <span class="tok-k">value</span> <span class="tok-o">|</span> <span class="tok-k">exception</span> <span class="tok-nn">Js</span><span class="tok-p">.</span><span class="tok-nn">Exn</span><span class="tok-p">.</span><span class="tok-nc">Error</span> <span class="tok-n">e</span> <span class="tok-o">-></span> <span class="tok-nn">Js</span><span class="tok-p">.</span><span class="tok-n">log</span> <span class="tok-o">(</span><span class="tok-nn">Js</span><span class="tok-p">.</span><span class="tok-nn">Exn</span><span class="tok-p">.</span><span class="tok-n">message</span> <span class="tok-n">e</span><span class="tok-o">);</span> <span class="tok-nc">None</span></code></pre> </div> </div> <div class="paragraph"> <p>Please consult the <a href="../api/Js.Exn.html"><code>Js.Exn</code> API reference</a> for more details</p> </div> </div> </div> <div class="sect1"> <h2 id="__code_bs_open_code_type_safe_external_data_source_handling_since_1_7_0"><a class="anchor" href="#__code_bs_open_code_type_safe_external_data_source_handling_since_1_7_0"></a><code>bs.open</code>: Type safe external data-source handling (@@since 1.7.0)</h2> <div class="sectionbody"> <div class="paragraph"> <p>There are some cases, the data-source could either come from JS land or OCaml land, it is very hard to give precise type information. For example, for an external promise whose creation could come from JS API, its failed value caused by <code>Promise.reject</code> could be in any shape.</p> </div> <div class="paragraph"> <p>BuckleScript provides a solution to filter out OCaml structured exception data from the mixed data source, it preserves the type safety while allow users to deal with mixed source.</p> </div> <div class="paragraph"> <p>It makes use of OCaml’s extensible variant, so that users can mix values of type <code>exn</code> with JS data-source</p> </div> <div class="listingblock"> <div class="title">Example</div> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">let</span> <span class="tok-n">handleData</span> <span class="tok-o">=</span> <span class="tok-k">function</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-k">open</span><span class="tok-o">]</span> <span class="tok-o">|</span> <span class="tok-nc">Invalid_argument</span> <span class="tok-o">_</span> <span class="tok-o">-></span> <span class="tok-mi">0</span> <span class="tok-o">|</span> <span class="tok-nc">Not_found</span> <span class="tok-o">-></span> <span class="tok-mi">1</span> <span class="tok-o">|</span> <span class="tok-nc">Sys_error</span> <span class="tok-o">_</span> <span class="tok-o">-></span> <span class="tok-mi">2</span> <span class="tok-k">val</span> <span class="tok-n">handleData</span> <span class="tok-o">:</span> <span class="tok-k">'</span><span class="tok-n">a</span> <span class="tok-o">-></span> <span class="tok-kt">int</span> <span class="tok-n">option</span> <b class="conum">(1)</b></code></pre> </div> </div> <div class="colist arabic"> <ol> <li> <p>For any input source, as long as it matches the exception pattern (nested pattern match supported), the matched value is returned, otherwise return <code>None</code>.</p> </li> </ol> </div> <div class="sect2"> <h3 id="_use_cases"><a class="anchor" href="#_use_cases"></a>Use cases</h3> <div class="paragraph"> <p>Take promise for example:</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">let</span> <span class="tok-n">v</span> <span class="tok-o">=</span> <span class="tok-nn">Js</span><span class="tok-p">.</span><span class="tok-nn">Promise</span><span class="tok-p">.</span><span class="tok-n">reject</span> <span class="tok-nc">Not_found</span> <span class="tok-k">let</span> <span class="tok-n">handlePromiseFailure</span> <span class="tok-o">=</span> <span class="tok-k">function</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-k">open</span><span class="tok-o">]</span> <span class="tok-o">|</span> <span class="tok-nc">Not_found</span> <span class="tok-o">-></span> <span class="tok-nn">Js</span><span class="tok-p">.</span><span class="tok-n">log</span> <span class="tok-s2">"Not found"</span><span class="tok-o">;</span> <span class="tok-o">(</span><span class="tok-nn">Js</span><span class="tok-p">.</span><span class="tok-nn">Promise</span><span class="tok-p">.</span><span class="tok-n">resolve</span> <span class="tok-bp">()</span><span class="tok-o">)</span> <span class="tok-k">let</span> <span class="tok-bp">()</span> <span class="tok-o">=</span> <span class="tok-n">v</span> <span class="tok-o">|></span> <span class="tok-nn">Js</span><span class="tok-p">.</span><span class="tok-nn">Promise</span><span class="tok-p">.</span><span class="tok-n">catch</span> <span class="tok-o">(</span><span class="tok-k">fun</span> <span class="tok-n">error</span> <span class="tok-o">-></span> <span class="tok-k">match</span> <span class="tok-n">handlePromiseFailure</span> <span class="tok-n">error</span> <span class="tok-k">with</span> <span class="tok-o">|</span> <span class="tok-nc">Some</span> <span class="tok-n">x</span> <span class="tok-o">-></span> <span class="tok-n">x</span> <span class="tok-o">|</span> <span class="tok-nc">None</span> <span class="tok-o">-></span> <span class="tok-k">raise</span> <span class="tok-nc">UnhandledPromise</span> <span class="tok-o">)</span></code></pre> </div> </div> </div> </div> </div> <div class="sect1"> <h2 id="_js_module"><a class="anchor" href="#_js_module"></a>Js module</h2> <div class="sectionbody"> <div class="paragraph"> <p><a href="https://bucklescript.github.io/bucklescript/api/Js.html">API reference</a></p> </div> <div class="paragraph"> <p>Js module is shipped with BuckleScript, both the namespace <code>Js</code> and <code>Node</code> are preserved.</p> </div> <div class="sect2"> <h3 id="_null_and_undefined"><a class="anchor" href="#_null_and_undefined"></a>Null and Undefined</h3> <div class="paragraph"> <p>BuckleScript does not deal with <code>null</code> and <code>undefined</code> on the language level. Instead they are defined on the library level, represented by <code>Js.Null.empty</code> and <code>Js.Undefined.empty</code> (and <code>Js.Null_undefined.empty</code>) types. But due to this being Ocaml and all, we can’t just pass these values off as if it was any type we’d like it to be, so in order to actually use them we need to lift the type we want to use them with. For this purpose BuckleScript defines the type <code>'a Js.null</code>, <code>'a Js.undefined' and ’a Js.null_undefined</code> (for values that can be both <code>null</code>, <code>undefined</code> and <code>'a</code>). As well as the corresponding modules <code>Js.Null</code>, <code>Js.Undefined</code> and <code>Js.Null_undefined</code> for working with these types.</p> </div> <div class="paragraph"> <p>Here’s an example showing <code>Js.Null</code> used directly:</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">external</span> <span class="tok-n">get_prop_name_maybe</span> <span class="tok-o">:</span> <span class="tok-kt">unit</span> <span class="tok-o">-></span> <span class="tok-kt">string</span> <span class="tok-nn">Js</span><span class="tok-p">.</span><span class="tok-n">null</span> <span class="tok-o">=</span> <span class="tok-s2">""</span> <span class="tok-o">[@@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-k">val</span><span class="tok-o">]</span> <span class="tok-k">external</span> <span class="tok-n">set_or_unset_prop</span> <span class="tok-o">:</span> <span class="tok-kt">string</span> <span class="tok-o">-></span> <span class="tok-kt">int</span> <span class="tok-nn">Js</span><span class="tok-p">.</span><span class="tok-n">null</span> <span class="tok-o">-></span> <span class="tok-kt">unit</span> <span class="tok-o">=</span> <span class="tok-s2">""</span> <span class="tok-o">[@@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-k">val</span><span class="tok-o">]</span> <span class="tok-c">(* unset property if fond *)</span> <span class="tok-k">let</span> <span class="tok-n">s</span> <span class="tok-o">=</span> <span class="tok-n">get_prop_name_maybe</span> <span class="tok-bp">()</span> <span class="tok-k">let</span> <span class="tok-o">_</span> <span class="tok-o">=</span> <span class="tok-nn">Js</span><span class="tok-p">.</span><span class="tok-nn">Null</span><span class="tok-p">.</span><span class="tok-n">iter</span> <span class="tok-n">s</span> <span class="tok-o">((</span><span class="tok-k">fun</span> <span class="tok-n">name</span> <span class="tok-o">-></span> <span class="tok-n">set_or_unset_prop</span> <span class="tok-n">name</span> <span class="tok-nn">Js</span><span class="tok-p">.</span><span class="tok-nn">Null</span><span class="tok-p">.</span><span class="tok-n">empty</span><span class="tok-o">)</span> <span class="tok-o">[@</span><span class="tok-n">bs</span><span class="tok-o">])</span> <span class="tok-c">(* set some other property *)</span> <span class="tok-k">let</span> <span class="tok-o">_</span> <span class="tok-o">=</span> <span class="tok-n">set_or_unset_prop</span> <span class="tok-s2">"some_other_property"</span> <span class="tok-o">(</span><span class="tok-nn">Js</span><span class="tok-p">.</span><span class="tok-nn">Null</span><span class="tok-p">.</span><span class="tok-n">return</span> <span class="tok-s2">""</span><span class="tok-o">)</span></code></pre> </div> </div> <div class="paragraph"> <p>You might also want to map these types to <code>option</code> for a friendlier and more idiomatic API, if the distinction between <code>null</code> and <code>undefined</code> isn’t important to maintain:</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">external</span> <span class="tok-n">try_some_thing</span> <span class="tok-o">:</span> <span class="tok-kt">string</span> <span class="tok-nn">Js</span><span class="tok-p">.</span><span class="tok-n">null</span> <span class="tok-o">-></span> <span class="tok-kt">int</span> <span class="tok-nn">Js</span><span class="tok-p">.</span><span class="tok-n">null</span> <span class="tok-o">=</span> <span class="tok-o">...</span> <span class="tok-k">let</span> <span class="tok-n">try_some_thing_maybe</span> <span class="tok-o">(</span><span class="tok-n">v</span> <span class="tok-o">:</span> <span class="tok-kt">string</span> <span class="tok-n">option</span><span class="tok-o">)</span> <span class="tok-o">:</span> <span class="tok-kt">int</span> <span class="tok-n">option</span> <span class="tok-o">=</span> <span class="tok-nn">Js</span><span class="tok-p">.</span><span class="tok-nn">Null</span><span class="tok-p">.</span><span class="tok-n">to_opt</span> <span class="tok-o">(</span><span class="tok-n">try_some_thing</span> <span class="tok-o">(</span><span class="tok-nn">Js</span><span class="tok-p">.</span><span class="tok-nn">Null</span><span class="tok-p">.</span><span class="tok-n">from_opt</span> <span class="tok-n">v</span><span class="tok-o">))</span></code></pre> </div> </div> </div> <div class="sect2"> <h3 id="_boolean"><a class="anchor" href="#_boolean"></a>Boolean</h3> <div class="paragraph"> <p>"Native" <code>bool</code> is for Bob-ish reasons not represented as <code>true</code> and <code>false</code> literals in JavaScript. For interop you therefore need to use the <code>Js.boolean</code> and its <code>Js.true_</code> and <code>Js.false_</code> values. There are also convenience functions for coercing to and from <code>bool</code>: <code>Js.to_bool</code> and <code>Js.Boolean.to_js_boolean</code>.</p> </div> </div> </div> </div> <div class="sect1"> <h2 id="_extended_compiler_options"><a class="anchor" href="#_extended_compiler_options"></a>Extended compiler options</h2> <div class="sectionbody"> <div class="exampleblock"> <div class="content"> <div class="paragraph"> <p>This section is only for people who want roll their own build system instead of using the recommended build system: <a href="#_bucklescript_build_system_code_bsb_code">BuckleScript build system: <code>bsb</code></a>, in general, it is safe to skip this section. It also adds some tips for people who debug the compiler.</p> </div> </div> </div> <div class="paragraph"> <p>BuckleScript inherits the command line arguments of the <a href="http://caml.inria.fr/pub/docs/manual-ocaml/comp.html">OCaml compiler</a>. It also adds several flags:</p> </div> <div class="sect2"> <h3 id="__bs_main_single_directory_build"><a class="anchor" href="#__bs_main_single_directory_build"></a>-bs-main (single directory build)</h3> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="sh">bsc.exe -bs-main Main</code></pre> </div> </div> <div class="paragraph"> <p><code>bsc.exe</code> will build module <code>Main</code> and all its dependencies and when it finishes, it will run <code>node main.js</code>.</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="sh">bsc.exe -c -bs-main Main</code></pre> </div> </div> <div class="paragraph"> <p>The same as above, but will not run <code>node</code>.</p> </div> </div> <div class="sect2"> <h3 id="__bs_files"><a class="anchor" href="#__bs_files"></a>-bs-files</h3> <div class="paragraph"> <p>So that you can do</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="sh">bsc.exe -c -bs-files *.ml *.mli</code></pre> </div> </div> <div class="paragraph"> <p>the compiler will sort the order of input files before starting compilation.</p> </div> <div class="paragraph"> <p>BuckleScript supports two compilation modes: script mode and package mode. In package mode, you have to provide <code>package.json</code> on top and set the options <code>-bs-package-name</code>, <code>-bs-package-output</code>. In script mode, such flags are not needed.</p> </div> </div> <div class="sect2"> <h3 id="__bs_package_name"><a class="anchor" href="#__bs_package_name"></a>-bs-package-name</h3> <div class="paragraph"> <p>The project name of your project. The user is suggested to make it consistent with the <code>name</code> field in <code>package.json</code></p> </div> </div> <div class="sect2"> <h3 id="__bs_packge_output"><a class="anchor" href="#__bs_packge_output"></a>-bs-packge-output</h3> <div class="paragraph"> <p>The format is <code>module_system:oupt/path/relative/to/package.json</code> Currently supported module systesms are: <code>commonjs</code>, <code>amdjs</code> and <code>es6</code>.</p> </div> <div class="paragraph"> <p>For example, when you want to use the <code>es6</code> module system, you can do things like this:</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="bash">bsc.exe -bs-package-name your_package -bs-package-output es6:lib/es6 -c xx.ml</code></pre> </div> </div> <div class="admonitionblock note"> <table> <tr> <td class="icon"> <div class="title">Note</div> </td> <td class="content"> The user can supply multiple <code>-bs-package-output</code> at the same time. </td> </tr> </table> </div> <div class="paragraph"> <p>For example:</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="bash">bsc.exe -bs-package-name name -bs-package-output commonjs:lib/js -bs-package-output amdjs:lib/amdjs -c x.ml</code></pre> </div> </div> <div class="paragraph"> <p>It will generate <code>x.js</code> in <code>lib/js</code> as a commonjs module, <code>lib/amdjs</code> as an amdjs module at the same time.</p> </div> <div class="paragraph"> <p>You would then need a bundler for the different module systems: <code>webpack</code> supports <code>commonjs</code> and <code>amdjs</code> while <code>google closure compiler</code> supports all.</p> </div> </div> <div class="sect2"> <h3 id="__bs_gen_tds"><a class="anchor" href="#__bs_gen_tds"></a>-bs-gen-tds</h3> <div class="paragraph"> <p>Trigger the generation of TypeScript <code>.d.ts</code> files. <code>bsc.exe</code> has the ability to also emit <code>.d.ts</code> for better interaction with TypeScript. This is still experimental.</p> </div> <div class="paragraph"> <p>For more options, please see the documentation of <code>bsc.exe -help</code>.</p> </div> </div> <div class="sect2"> <h3 id="__bs_no_warn_ffi_type"><a class="anchor" href="#__bs_no_warn_ffi_type"></a>-bs-no-warn-ffi-type</h3> <div class="paragraph"> <p>Turn off warnings on FFI type declarations.</p> </div> </div> <div class="sect2"> <h3 id="__bs_eval"><a class="anchor" href="#__bs_eval"></a>-bs-eval</h3> <div class="listingblock"> <div class="title">Example</div> <div class="content"> <pre class="pygments highlight"><code data-lang="sh">bsc.exe -dparsetree -drawlambda -bs-eval <span class="tok-s1">'Js.log "hello"'</span></code></pre> </div> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-o">[</span> <b class="conum">(1)</b> <span class="tok-n">structure_item</span> <span class="tok-o">(//</span><span class="tok-n">toplevel</span><span class="tok-o">//[</span><span class="tok-mi">1</span><span class="tok-o">,</span><span class="tok-mi">0</span><span class="tok-o">+</span><span class="tok-mi">0</span><span class="tok-o">]..[</span><span class="tok-mi">1</span><span class="tok-o">,</span><span class="tok-mi">0</span><span class="tok-o">+</span><span class="tok-mi">14</span><span class="tok-o">])</span> <span class="tok-nc">Pstr_eval</span> <span class="tok-n">expression</span> <span class="tok-o">(//</span><span class="tok-n">toplevel</span><span class="tok-o">//[</span><span class="tok-mi">1</span><span class="tok-o">,</span><span class="tok-mi">0</span><span class="tok-o">+</span><span class="tok-mi">0</span><span class="tok-o">]..[</span><span class="tok-mi">1</span><span class="tok-o">,</span><span class="tok-mi">0</span><span class="tok-o">+</span><span class="tok-mi">14</span><span class="tok-o">])</span> <span class="tok-nc">Pexp_apply</span> <span class="tok-n">expression</span> <span class="tok-o">(//</span><span class="tok-n">toplevel</span><span class="tok-o">//[</span><span class="tok-mi">1</span><span class="tok-o">,</span><span class="tok-mi">0</span><span class="tok-o">+</span><span class="tok-mi">0</span><span class="tok-o">]..[</span><span class="tok-mi">1</span><span class="tok-o">,</span><span class="tok-mi">0</span><span class="tok-o">+</span><span class="tok-mi">6</span><span class="tok-o">])</span> <span class="tok-nc">Pexp_ident</span> <span class="tok-s2">"Js.log"</span> <span class="tok-o">(//</span><span class="tok-n">toplevel</span><span class="tok-o">//[</span><span class="tok-mi">1</span><span class="tok-o">,</span><span class="tok-mi">0</span><span class="tok-o">+</span><span class="tok-mi">0</span><span class="tok-o">]..[</span><span class="tok-mi">1</span><span class="tok-o">,</span><span class="tok-mi">0</span><span class="tok-o">+</span><span class="tok-mi">6</span><span class="tok-o">])</span> <span class="tok-o">[</span> <span class="tok-o"><</span><span class="tok-n">label</span><span class="tok-o">></span> <span class="tok-s2">""</span> <span class="tok-n">expression</span> <span class="tok-o">(//</span><span class="tok-n">toplevel</span><span class="tok-o">//[</span><span class="tok-mi">1</span><span class="tok-o">,</span><span class="tok-mi">0</span><span class="tok-o">+</span><span class="tok-mi">7</span><span class="tok-o">]..[</span><span class="tok-mi">1</span><span class="tok-o">,</span><span class="tok-mi">0</span><span class="tok-o">+</span><span class="tok-mi">14</span><span class="tok-o">])</span> <span class="tok-nc">Pexp_constant</span> <span class="tok-nc">Const_string</span><span class="tok-o">(</span><span class="tok-s2">"hello"</span><span class="tok-o">,</span><span class="tok-nc">None</span><span class="tok-o">)</span> <span class="tok-o">]</span> <span class="tok-o">]</span> <b class="conum">(2)</b> <span class="tok-o">(</span><span class="tok-n">setglobal</span> <span class="tok-nc">Bs_internal_eval</span><span class="tok-o">!</span> <span class="tok-o">(</span><span class="tok-n">seq</span> <span class="tok-o">(</span><span class="tok-n">js_dump</span> <span class="tok-s2">"hello"</span><span class="tok-o">)</span> <span class="tok-o">(</span><span class="tok-n">makeblock</span> <span class="tok-mi">0</span><span class="tok-o">)))</span> <span class="tok-o">//</span> <span class="tok-nc">Generated</span> <span class="tok-n">by</span> <span class="tok-nc">BUCKLESCRIPT</span> <span class="tok-nc">VERSION</span> <span class="tok-mi">1</span><span class="tok-o">.</span><span class="tok-mi">0</span><span class="tok-o">.</span><span class="tok-mi">2</span> <span class="tok-o">,</span> <span class="tok-nc">PLEASE</span> <span class="tok-nc">EDIT</span> <span class="tok-nc">WITH</span> <span class="tok-nc">CARE</span> <span class="tok-k">'</span><span class="tok-n">use</span> <span class="tok-n">strict'</span><span class="tok-o">;</span> <span class="tok-n">console</span><span class="tok-o">.</span><span class="tok-n">log</span><span class="tok-o">(</span><span class="tok-s2">"hello"</span><span class="tok-o">);</span> <span class="tok-o">/*</span> <span class="tok-nc">Not</span> <span class="tok-n">a</span> <span class="tok-n">pure</span> <span class="tok-k">module</span> <span class="tok-o">*/</span></code></pre> </div> </div> <div class="colist arabic"> <ol> <li> <p>Output by flag -dparsetree</p> </li> <li> <p>Output by flag -drawlambda</p> </li> </ol> </div> <div class="paragraph"> <p>For this flag, it will not create any intermediate file, which is useful for learning or troubleshooting.</p> </div> </div> <div class="sect2"> <h3 id="__bs_no_builtin_ppx_ml_bs_no_builtin_ppx_mli"><a class="anchor" href="#__bs_no_builtin_ppx_ml_bs_no_builtin_ppx_mli"></a>-bs-no-builtin-ppx-ml, -bs-no-builtin-ppx-mli</h3> <div class="paragraph"> <p>If the user doesn’t use any bs specific annotations, the user can explicitly turn it off. Another use case is that users can use <code>-ppx</code> explicitly as below:</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-n">bsc</span><span class="tok-o">.</span><span class="tok-n">exe</span> <span class="tok-o">-</span><span class="tok-n">c</span> <span class="tok-o">-</span><span class="tok-n">ppx</span> <span class="tok-n">bsppx</span><span class="tok-o">.</span><span class="tok-n">exe</span> <span class="tok-o">-</span><span class="tok-n">bs</span><span class="tok-o">-</span><span class="tok-n">no</span><span class="tok-o">-</span><span class="tok-n">builtin</span><span class="tok-o">-</span><span class="tok-n">ppx</span><span class="tok-o">-</span><span class="tok-n">ml</span> <span class="tok-n">c</span><span class="tok-o">.</span><span class="tok-n">ml</span></code></pre> </div> </div> </div> <div class="sect2"> <h3 id="__bs_no_version_header"><a class="anchor" href="#__bs_no_version_header"></a>-bs-no-version-header</h3> <div class="paragraph"> <p>Don’t print version header.</p> </div> </div> </div> </div> <div class="sect1"> <h2 id="_semantic_differences_from_other_backends"><a class="anchor" href="#_semantic_differences_from_other_backends"></a>Semantic differences from other backends</h2> <div class="sectionbody"> <div class="paragraph"> <p>This is particularly important when porting an existing OCaml application to JavaScript.</p> </div> <div class="sect2"> <h3 id="_custom_data_type"><a class="anchor" href="#_custom_data_type"></a>Custom data type</h3> <div class="paragraph"> <p>In OCaml, the C FFI allows the user to define a custom data type and customize <code>caml_compare</code>, <code>caml_hash</code> behavior, etc. This is not available in our backend (since we have no C FFI).</p> </div> </div> <div class="sect2"> <h3 id="_physical_in_equality"><a class="anchor" href="#_physical_in_equality"></a>Physical (in)equality</h3> <div class="paragraph"> <p>In general, users should only use physical equality as an optimization technique, but not rely on its correctness, since it is tightly coupled with the runtime.</p> </div> </div> <div class="sect2"> <h3 id="_string_char_range"><a class="anchor" href="#_string_char_range"></a>String char range</h3> <div class="paragraph"> <p>Currently, BuckleScript assumes that the char range is <code>0-255</code>. The user should be careful when they pass a JavaScript string to the OCaml side. Note that we are working on a solution for this problem.</p> </div> </div> <div class="sect2"> <h3 id="_weak_map"><a class="anchor" href="#_weak_map"></a>Weak map</h3> <div class="paragraph"> <p>OCaml’s weak map is not available in BuckleScript. The weak pointer is replaced by a strict pointer.</p> </div> </div> <div class="sect2"> <h3 id="_integers"><a class="anchor" href="#_integers"></a>Integers</h3> <div class="paragraph"> <p>OCaml has <code>int</code>, <code>int32</code>, <code>nativeint</code> and <code>int64</code> types. - Both <code>int32</code> and <code>int64</code> in BuckleScript have the exact same semantics as OCaml. - <code>int</code> in BuckleScript is the same as <code>int32</code> while in OCaml it’s platform dependent. - <code>nativeint</code> is treated as JavaScript float, except for division. For example, <code>Nativeint.div a b</code> will be translated into <code>a /b | 0</code>.</p> </div> <div class="admonitionblock warning"> <table> <tr> <td class="icon"> <div class="title">Warning</div> </td> <td class="content"> <div class="paragraph"> <p><code>Nativeint.shift_right_logical x 0</code> is different from <code>Int32.shift_right_local x 0</code>. The former is literally translated into <code>x >>> 0</code> (translated into an unsigned int), while the latter is <code>x | 0</code>.</p> </div> </td> </tr> </table> </div> </div> <div class="sect2"> <h3 id="_printf_printf"><a class="anchor" href="#_printf_printf"></a>Printf.printf</h3> <div class="paragraph"> <p>The <code>Printf.print</code> implementation in BuckleScript requires a newline (<code>\n</code>) to trigger the printing. This behavior is not consistent with the buffered behavior of native OCaml. The only potential problem we foresee is that if the program terminates with no newline character, the text will never be printed.</p> </div> </div> <div class="sect2"> <h3 id="_obj_module"><a class="anchor" href="#_obj_module"></a>Obj module</h3> <div class="paragraph"> <p>We do our best to mimic the native compiler, but we have no guarantee and there are differences.</p> </div> </div> <div class="sect2"> <h3 id="_hashtbl_hash_algorithm"><a class="anchor" href="#_hashtbl_hash_algorithm"></a>Hashtbl hash algorithm</h3> <div class="paragraph"> <p>BuckleScript uses the same algorithm as native OCaml but the output is different due to the runtime representation of int/int64/int32 and float.</p> </div> </div> <div class="sect2"> <h3 id="_marshall"><a class="anchor" href="#_marshall"></a>Marshall</h3> <div class="paragraph"> <p>Marshall module is not supported yet.</p> </div> </div> <div class="sect2"> <h3 id="_sys_argv_sys_max_array_length_sys_max_string_length"><a class="anchor" href="#_sys_argv_sys_max_array_length_sys_max_string_length"></a>Sys.argv, Sys.max_array_length, Sys.max_string_length</h3> <div class="paragraph"> <p>Command line arguments are always empty. This might be fixed in the near future. <code>Sys.max_array_length</code> and <code>Sys.max_string_length</code> will be the same as <code>max_int</code>, but it might be respected.</p> </div> </div> <div class="sect2"> <h3 id="_unsupported_io_primitives"><a class="anchor" href="#_unsupported_io_primitives"></a>Unsupported IO primitives</h3> <div class="paragraph"> <p>Because of the JavaScript environment limitation, <code>Pervasives.stdin</code> is not supported but both <code>Pervasives.stdout</code> and <code>Pervasives.stderr</code> are.</p> </div> </div> </div> </div> <div class="sect1"> <h2 id="_conditional_compilation_support_static_if"><a class="anchor" href="#_conditional_compilation_support_static_if"></a>Conditional compilation support - static if</h2> <div class="sectionbody"> <div class="paragraph"> <p>It is quite common that people want to write code that works with different versions of compilers and libraries.</p> </div> <div class="paragraph"> <p>People used to use preprocessors like <a href="http://tigcc.ticalc.org/doc/cpp.html">C preprocessor</a> for the C family languages. In the OCaml community there are several preprocessors: <a href="https://github.com/mjambon/cppo">cppo</a>, <a href="https://github.com/OCamlPro/typerex-build/tree/master/tools/ocp-pp">ocp-pp</a>, camlp4 IFDEF macros, <a href="https://github.com/diml/optcomp">optcomp</a> and <a href="https://github.com/janestreet/ppx_optcomp">ppx optcomp</a>.</p> </div> <div class="paragraph"> <p>Instead of using a preprocessor, BuckleScript adds language level static if compilation to the language. It is less powerful than other preprocessors since it only supports static if (no <code>#define</code>, <code>#undefine</code>, <code>#include</code>) but there are several advantages.</p> </div> <div class="ulist"> <ul> <li> <p>It’s very small (only around 500 LOC) and highly efficient. There is no added pass, allowing everything to be done in a <strong>single pass</strong>. It is easy to rebuild the pre-processor in a stand alone file, with no dependencies on compiler libs to back-port it to old OCaml compilers.</p> </li> <li> <p>It’s purely functional and type safe, easy to work with IDEs like Merlin.</p> </li> </ul> </div> <div class="sect2"> <h3 id="_concrete_syntax"><a class="anchor" href="#_concrete_syntax"></a>Concrete syntax</h3> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="bnf">static-if | HASH-IF-BOL conditional-expression THEN <b class="conum">(1)</b> tokens (HASH-ELIF-BOL conditional-expression THEN) * (ELSE-BOL tokens)? HASH-END-BOL conditional-expression | conditional-expression && conditional-expression | conditional-expression || conditional-expression | atom-predicate atom-predicate | atom operator atom | defined UIDENT | undefined UIDENT operator | (= | < | > | <= | >= | =~ ) atom | UIDENT | INT | STRING | FLOAT</code></pre> </div> </div> <div class="colist arabic"> <ol> <li> <p>IF-BOL means <code>#IF</code> should be in the beginning of a line</p> </li> </ol> </div> </div> <div class="sect2"> <h3 id="_typing_rules"><a class="anchor" href="#_typing_rules"></a>Typing rules</h3> <div class="ulist"> <ul> <li> <p>type of INT is <code>int</code></p> </li> <li> <p>type of STRING is <code>string</code></p> </li> <li> <p>type of FLOAT is <code>float</code></p> </li> <li> <p>value of UIDENT comes from either built-in values (with documented types) or an environment variable, if it is literally <code>true</code>, <code>false</code> then it is <code>bool</code>, else if it is parsable by <code>int_of_string</code> then it is of type int, else if it is parsable by <code>float_of_string</code> then it is float, otherwise it would be string</p> </li> <li> <p>In <code>lhs operator rhs</code>, <code>lhs</code> and <code>rhs</code> are always the same type and return boolean. <code>=~</code> is a semantic version operator which requires both sides to be string.</p> </li> </ul> </div> <div class="paragraph"> <p>Evaluation rules are obvious. <code>=~</code> respect semantic version, for example, the underlying engine</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-n">semver</span> <span class="tok-nn">Location</span><span class="tok-p">.</span><span class="tok-n">none</span> <span class="tok-s2">"1.2.3"</span> <span class="tok-s2">"~1.3.0"</span> <span class="tok-o">=</span> <span class="tok-bp">false</span><span class="tok-o">;;</span> <span class="tok-n">semver</span> <span class="tok-nn">Location</span><span class="tok-p">.</span><span class="tok-n">none</span> <span class="tok-s2">"1.2.3"</span> <span class="tok-s2">"^1.3.0"</span> <span class="tok-o">=</span> <span class="tok-bp">true</span> <span class="tok-o">;;</span> <span class="tok-n">semver</span> <span class="tok-nn">Location</span><span class="tok-p">.</span><span class="tok-n">none</span> <span class="tok-s2">"1.2.3"</span> <span class="tok-s2">">1.3.0"</span> <span class="tok-o">=</span> <span class="tok-bp">false</span> <span class="tok-o">;;</span> <span class="tok-n">semver</span> <span class="tok-nn">Location</span><span class="tok-p">.</span><span class="tok-n">none</span> <span class="tok-s2">"1.2.3"</span> <span class="tok-s2">">=1.3.0"</span> <span class="tok-o">=</span> <span class="tok-bp">false</span> <span class="tok-o">;;</span> <span class="tok-n">semver</span> <span class="tok-nn">Location</span><span class="tok-p">.</span><span class="tok-n">none</span> <span class="tok-s2">"1.2.3"</span> <span class="tok-s2">"<1.3.0"</span> <span class="tok-o">=</span> <span class="tok-bp">true</span> <span class="tok-o">;;</span> <span class="tok-n">semver</span> <span class="tok-nn">Location</span><span class="tok-p">.</span><span class="tok-n">none</span> <span class="tok-s2">"1.2.3"</span> <span class="tok-s2">"<=1.3.0"</span> <span class="tok-o">=</span> <span class="tok-bp">true</span> <span class="tok-o">;;</span> <span class="tok-n">semver</span> <span class="tok-nn">Location</span><span class="tok-p">.</span><span class="tok-n">none</span> <span class="tok-s2">"1.2.3"</span> <span class="tok-s2">"1.2.3"</span> <span class="tok-o">=</span> <span class="tok-bp">true</span><span class="tok-o">;;</span></code></pre> </div> </div> </div> <div class="sect2"> <h3 id="_examples_3"><a class="anchor" href="#_examples_3"></a>Examples</h3> <div class="listingblock"> <div class="title">lwt_unix.mli</div> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">type</span> <span class="tok-n">open_flag</span> <span class="tok-o">=</span> <span class="tok-nn">Unix</span><span class="tok-p">.</span><span class="tok-n">open_flag</span> <span class="tok-o">=</span> <span class="tok-o">|</span> <span class="tok-nc">O_RDONLY</span> <span class="tok-o">|</span> <span class="tok-nc">O_WRONLY</span> <span class="tok-o">|</span> <span class="tok-nc">O_RDWR</span> <span class="tok-o">|</span> <span class="tok-nc">O_NONBLOCK</span> <span class="tok-o">|</span> <span class="tok-nc">O_APPEND</span> <span class="tok-o">|</span> <span class="tok-nc">O_CREAT</span> <span class="tok-o">|</span> <span class="tok-nc">O_TRUNC</span> <span class="tok-o">|</span> <span class="tok-nc">O_EXCL</span> <span class="tok-o">|</span> <span class="tok-nc">O_NOCTTY</span> <span class="tok-o">|</span> <span class="tok-nc">O_DSYNC</span> <span class="tok-o">|</span> <span class="tok-nc">O_SYNC</span> <span class="tok-o">|</span> <span class="tok-nc">O_RSYNC</span> <span class="tok-o">#</span><span class="tok-k">if</span> <span class="tok-nc">OCAML_VERSION</span> <span class="tok-o">=~</span> <span class="tok-s2">">=3.13"</span> <span class="tok-k">then</span> <span class="tok-o">|</span> <span class="tok-nc">O_SHARE_DELETE</span> <span class="tok-o">#</span><span class="tok-k">end</span> <span class="tok-o">#</span><span class="tok-k">if</span> <span class="tok-nc">OCAML_VERSION</span> <span class="tok-o">=~</span> <span class="tok-s2">">=4.01"</span> <span class="tok-k">then</span> <span class="tok-o">|</span> <span class="tok-nc">O_CLOEXEC</span> <span class="tok-o">#</span><span class="tok-k">end</span></code></pre> </div> </div> </div> <div class="sect2"> <h3 id="_built_in_variables_and_custom_variables"><a class="anchor" href="#_built_in_variables_and_custom_variables"></a>Built in variables and custom variables</h3> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="sh">ocamlscript>bsc.exe -bs-D <span class="tok-nv">CUSTOM_A</span><span class="tok-o">=</span><span class="tok-s2">"ghsigh"</span> -bs-list-conditionals OCAML_PATCH <span class="tok-s2">"BS"</span> BS_VERSION <span class="tok-s2">"1.2.1"</span> OS_TYPE <span class="tok-s2">"Unix"</span> BS <span class="tok-nb">true</span> CUSTOM_A <span class="tok-s2">"ghsigh"</span> WORD_SIZE 64 OCAML_VERSION <span class="tok-s2">"4.02.3+BS"</span> BIG_ENDIAN <span class="tok-nb">false</span></code></pre> </div> </div> </div> <div class="sect2"> <h3 id="_changes_to_command_line_options"><a class="anchor" href="#_changes_to_command_line_options"></a>Changes to command line options</h3> <div class="paragraph"> <p>For BuckleScript users, nothing needs to be done (it is baked in the language level). For non BuckleScript users, we provide an external pre-processor, so it will work with other OCaml compilers too. Note that the <a href="https://github.com/bucklescript/bucklescript/blob/master/jscomp/bin/bspp.ml">bspp.ml</a> is a stand alone file, so that it even works without compilation.</p> </div> <div class="listingblock"> <div class="title">Example</div> <div class="content"> <pre class="pygments highlight"><code data-lang="sh">bsc.exe -c lwt_unix.mli ocamlc -pp <span class="tok-s1">'bspp.exe'</span> -c lwt_unix.mli ocamlc -pp <span class="tok-s1">'ocaml -w -a bspp.ml'</span> -c lwt_unix.mli</code></pre> </div> </div> <div class="admonitionblock warning"> <table> <tr> <td class="icon"> <div class="title">Warning</div> </td> <td class="content"> <div class="paragraph"> <p>This is a very small extension to the OCaml language, it is backward compatible with OCaml language with such exceptions.</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">let</span> <span class="tok-n">f</span> <span class="tok-n">x</span> <span class="tok-o">=</span> <span class="tok-n">x</span> <span class="tok-o">#</span><span class="tok-n">elif</span> <b class="conum">(1)</b></code></pre> </div> </div> <div class="colist arabic"> <ol> <li> <p><code>#elif</code> at the beginning of a line is interpreted as static if, there is no issue with <code>#if</code> or <code>#end</code>, since they are already keywords.</p> </li> </ol> </div> </td> </tr> </table> </div> </div> </div> </div> <div class="sect1"> <h2 id="_build_system_support"><a class="anchor" href="#_build_system_support"></a>Build system support</h2> <div class="sectionbody"> <div class="paragraph"> <p>The BuckleScript compilation model is similar to OCaml native compiler. If <code>b.ml</code> depends on <code>a.ml</code>, you have to compile <code>a.ml</code> <strong>and</strong> <code>a.mli</code> first.</p> </div> <div class="admonitionblock note"> <table> <tr> <td class="icon"> <div class="title">Note</div> </td> <td class="content"> <div class="paragraph"> <p>The technical reason is that BuckleScript will generate intermediate files with the extension <code>.cmj</code> which are later used for cross module inlining, arity inference and other information.</p> </div> </td> </tr> </table> </div> <div class="sect2"> <h3 id="_bucklescript_build_system_code_bsb_code"><a class="anchor" href="#_bucklescript_build_system_code_bsb_code"></a>BuckleScript build system: <code>bsb</code></h3> <div class="paragraph"> <p>BuckleScript provides a native build tool on top of Google’s <a href="https://github.com/ninja-build/ninja/releases">ninja-build</a>. It is designed for a fast feedback loop (typically 100ms feedback loop) and works cross platform.</p> </div> <div class="paragraph"> <p><code>bsb</code> is a schema based build tool. The schema is <a href="http://bucklescript.github.io/bucklescript/docson/#build-schema.json">available</a>. It is strongly recommended to <strong>check out the <a href="http://bucklescript.github.io/bucklescript/docson/#build-schema.json">schema</a></strong> after you finish reading the tutorials below.</p> </div> <div class="paragraph"> <p>If your editor supports JSON schema validation and auto-completion like <a href="https://code.visualstudio.com/docs/languages/json">VSCode</a>, below is a configuration to help you get auto-completion and validation for free:</p> </div> <div class="listingblock"> <div class="title">settings.json</div> <div class="content"> <pre class="pygments highlight"><code data-lang="js"><span class="tok-p">{</span> <span class="tok-s2">"json.schemas"</span><span class="tok-o">:</span> <span class="tok-p">[</span> <span class="tok-p">{</span> <span class="tok-s2">"fileMatch"</span><span class="tok-o">:</span> <span class="tok-p">[</span> <span class="tok-s2">"bsconfig.json"</span> <span class="tok-p">],</span> <span class="tok-s2">"url"</span> <span class="tok-o">:</span> <span class="tok-s2">"file:///path/to/bucklescript/docs/docson/build-schema.json"</span> <b class="conum">(1)</b> <span class="tok-p">}</span> <span class="tok-p">],</span> <span class="tok-c1">// ....</span> <span class="tok-p">}</span></code></pre> </div> </div> <div class="paragraph"> <p>The build system is installed as <code>bsb.exe</code> in <code>bs-platform/bin/bsb.exe</code>. Due to a known issue in npm, we create a JS wrapper (which is accessible in <code>.bin</code> too) so the user can call either <code>bsb</code> (slightly higher latency but symlinked into <code>.bin</code>) or <code>bsb.exe</code></p> </div> <div class="paragraph"> <p>Here is a <strong>minimal</strong> configuration:</p> </div> <div class="listingblock"> <div class="title">bsconfig.json</div> <div class="content"> <pre class="pygments highlight"><code data-lang="js"><span class="tok-p">{</span> <span class="tok-s2">"name"</span><span class="tok-o">:</span> <span class="tok-s2">"test"</span><span class="tok-p">,</span> <span class="tok-c1">// package name, required </span><b class="conum">(1)</b> <span class="tok-s2">"sources"</span><span class="tok-o">:</span> <span class="tok-s2">"src"</span> <b class="conum">(2)</b> <span class="tok-p">}</span></code></pre> </div> </div> <div class="colist arabic"> <ol> <li> <p>It is an extension to JSON with comment support</p> </li> <li> <p>Here we did not list files, so all <code>.ml</code>, <code>.mli</code>, <code>.re</code>, <code>.rei</code> will be considered as source files</p> </li> </ol> </div> <div class="paragraph"> <p>The entry point is <code>bsb</code>. It will check if there is already <code>build.ninja</code> in the build directory, and if not or it needs to be regenerated it will generate the file <code>build.ninja</code> and delegate the hard work to <code>ninja</code>.</p> </div> <div class="paragraph"> <p>The directory layout (after building) would be</p> </div> <div class="listingblock"> <div class="content"> <pre>. ├── lib │ ├── bs │ │ ├── src │ │ └── test │ ├── js │ │ ├── src │ │ └── test │ ├── amdjs <b class="conum">(1)</b> │ │ ├── src │ │ └── test │ ├── es6 <b class="conum">(2)</b> │ │ ├── src │ │ └── test │ └── ocaml ├── scripts ├── src └── test</pre> </div> </div> <div class="colist arabic"> <ol> <li> <p>Will generate AMDJS modules if flags are turned on</p> </li> <li> <p>Will generate ES6 modules if flags are turned on</p> </li> </ol> </div> <div class="paragraph"> <p>We wrap <code>bsb.exe</code> as <code>bsb</code> so that it will work across different platforms.</p> </div> <div class="listingblock"> <div class="title">Watch mode</div> <div class="content"> <pre class="pygments highlight"><code data-lang="sh">bsb <b class="conum">(1)</b> bsb -w <b class="conum">(2)</b></code></pre> </div> </div> <div class="colist arabic"> <ol> <li> <p>Do the plain build</p> </li> <li> <p>Do the plain build and watch</p> </li> </ol> </div> <div class="sect3"> <h4 id="_build_with_other_bucklescript_dependencies"><a class="anchor" href="#_build_with_other_bucklescript_dependencies"></a>Build with other BuckleScript dependencies</h4> <div class="paragraph"> <p>List your dependency in <code>bs-dependencies</code> and install it via <code>npm install</code> as below:</p> </div> <div class="listingblock"> <div class="title">bsconfig.json</div> <div class="content"> <pre class="pygments highlight"><code data-lang="js"><span class="tok-p">{</span> <span class="tok-s2">"name"</span><span class="tok-o">:</span> <span class="tok-s2">"bs-string"</span><span class="tok-p">,</span> <span class="tok-s2">"version"</span><span class="tok-o">:</span> <span class="tok-s2">"0.1.3"</span><span class="tok-p">,</span> <span class="tok-s2">"bs-dependencies"</span><span class="tok-o">:</span> <span class="tok-p">[</span> <span class="tok-s2">"bs-mocha"</span> <b class="conum">(1)</b> <span class="tok-p">],</span> <span class="tok-s2">"sources"</span><span class="tok-o">:</span> <span class="tok-p">[</span> <span class="tok-p">..</span> <span class="tok-p">.</span> <span class="tok-p">],</span> <span class="tok-s2">"generate-merlin"</span> <span class="tok-o">:</span> <span class="tok-kc">false</span> <b class="conum">(2)</b> <span class="tok-p">}</span></code></pre> </div> </div> <div class="colist arabic"> <ol> <li> <p>Yet another BuckleScript dependency</p> </li> <li> <p>If true (default) bsb will generate merlin file for you</p> </li> </ol> </div> <div class="listingblock"> <div class="title">package.json</div> <div class="content"> <pre class="pygments highlight"><code data-lang="js"><span class="tok-p">{</span> <span class="tok-s2">"dependencies"</span><span class="tok-o">:</span> <span class="tok-p">{</span> <span class="tok-s2">"bs-mocha"</span><span class="tok-o">:</span> <span class="tok-s2">"0.1.5"</span> <span class="tok-p">},</span> <span class="tok-p">...</span> <span class="tok-p">}</span></code></pre> </div> </div> <div class="paragraph"> <p>After your <code>npm install</code>,</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="sh">bsb -clean-world <b class="conum">(1)</b> bsb -make-world <b class="conum">(2)</b> bsb -w <b class="conum">(3)</b></code></pre> </div> </div> <div class="colist arabic"> <ol> <li> <p>Clean the binary artifact of current build and your dependency</p> </li> <li> <p>Build dependencies and lib itself</p> </li> <li> <p>Start watching the project and whenever your changes are made, <code>bsb</code> will rebuild incrementally</p> </li> </ol> </div> <div class="paragraph"> <p>You can also streamline the three commands as below:</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="sh">bsb -clean-world -make-world -w</code></pre> </div> </div> </div> <div class="sect3"> <h4 id="_mark_your_directory_as_dev_only"><a class="anchor" href="#_mark_your_directory_as_dev_only"></a>Mark your directory as dev only</h4> <div class="paragraph"> <p>Note sometimes, you have directories which are just tests that you don’t need your dependency to build. In that case you can mark it as dev only:</p> </div> <div class="listingblock"> <div class="title">bsconfig.json</div> <div class="content"> <pre class="pygments highlight"><code data-lang="js"><span class="tok-p">{</span> <span class="tok-s2">"sources"</span> <span class="tok-o">:</span> <span class="tok-p">{</span> <span class="tok-s2">"dir"</span> <span class="tok-o">:</span> <span class="tok-s2">"test"</span><span class="tok-p">,</span> <span class="tok-s2">"type"</span> <span class="tok-o">:</span> <span class="tok-s2">"dev"</span> <b class="conum">(1)</b> <span class="tok-p">}</span> <span class="tok-p">}</span></code></pre> </div> </div> <div class="colist arabic"> <ol> <li> <p>directory <code>test</code> is in dev mode, it will not be built when used as a dependency</p> </li> </ol> </div> </div> </div> <div class="sect2"> <h3 id="_a_real_world_example_of_using_code_bsb_code"><a class="anchor" href="#_a_real_world_example_of_using_code_bsb_code"></a>A real world example of using <code>bsb</code></h3> <div class="paragraph"> <p>Below is a json configuration for the <a href="https://github.com/OvermindDL1/bucklescript-tea">bucklescript-tea</a>: the Elm artchitecture in BuckleScript</p> </div> <div class="listingblock"> <div class="title">bsconfig.json</div> <div class="content"> <pre class="pygments highlight"><code data-lang="js"><span class="tok-p">{</span> <span class="tok-s2">"name"</span><span class="tok-o">:</span> <span class="tok-s2">"bucklescript-tea"</span><span class="tok-p">,</span> <span class="tok-s2">"version"</span><span class="tok-o">:</span> <span class="tok-s2">"0.1.3"</span><span class="tok-p">,</span> <span class="tok-s2">"sources"</span><span class="tok-o">:</span> <span class="tok-p">[</span> <span class="tok-s2">"src"</span><span class="tok-p">,</span> <b class="conum">(1)</b> <span class="tok-p">{</span> <span class="tok-s2">"dir"</span><span class="tok-o">:</span> <span class="tok-s2">"test"</span><span class="tok-p">,</span> <span class="tok-s2">"type"</span><span class="tok-o">:</span> <span class="tok-s2">"dev"</span> <b class="conum">(2)</b> <span class="tok-p">}</span> <span class="tok-p">]</span> <span class="tok-p">}</span></code></pre> </div> </div> <div class="colist arabic"> <ol> <li> <p>Source directory, by default it will export all units of this directory to users.</p> </li> <li> <p>Dev directory, which will only be useful for developers of this project.</p> </li> </ol> </div> <div class="listingblock"> <div class="title">package.json</div> <div class="content"> <pre class="pygments highlight"><code data-lang="js"><span class="tok-p">{</span> <span class="tok-s2">"name"</span><span class="tok-o">:</span> <span class="tok-s2">"bucklescript-tea"</span><span class="tok-p">,</span> <span class="tok-s2">"version"</span><span class="tok-o">:</span> <span class="tok-s2">"0.1.3"</span><span class="tok-p">,</span> <span class="tok-s2">"description"</span><span class="tok-o">:</span> <span class="tok-s2">"TEA for Bucklescript"</span><span class="tok-p">,</span> <span class="tok-s2">"scripts"</span><span class="tok-o">:</span> <span class="tok-p">{</span> <span class="tok-s2">"build"</span><span class="tok-o">:</span> <span class="tok-s2">"bsb"</span><span class="tok-p">,</span> <span class="tok-s2">"watch"</span><span class="tok-o">:</span> <span class="tok-s2">"bsb -w"</span><span class="tok-p">,</span> <span class="tok-s2">"test"</span><span class="tok-o">:</span> <span class="tok-s2">"echo \"Error: no test specified\" && exit 1"</span> <span class="tok-p">},</span> <span class="tok-s2">"peerDependencies"</span><span class="tok-o">:</span> <span class="tok-p">{</span> <span class="tok-s2">"bs-platform"</span><span class="tok-o">:</span> <span class="tok-s2">"^1.7.0"</span> <b class="conum">(1)</b> <span class="tok-p">}</span> <span class="tok-p">}</span></code></pre> </div> </div> <div class="colist arabic"> <ol> <li> <p>Here we list <code>bs-platform</code> as a peer dependency so that different repos shares the same compiler.</p> </li> </ol> </div> <div class="paragraph"> <p>Now, if we have a repo <a href="https://github.com/bobzhang/bucklescript-have-tea">bucklescript-have-tea</a> which depends on <code>bucklescript-tea</code>, its configurations are as below:</p> </div> <div class="listingblock"> <div class="title">bsconfig.json</div> <div class="content"> <pre class="pygments highlight"><code data-lang="js"><span class="tok-p">{</span> <span class="tok-s2">"name"</span> <span class="tok-o">:</span> <span class="tok-s2">"bucklescript-have-tea"</span><span class="tok-p">,</span> <span class="tok-s2">"sources"</span> <span class="tok-o">:</span> <span class="tok-s2">"src"</span><span class="tok-p">,</span> <span class="tok-s2">"bs-dependencies"</span><span class="tok-o">:</span> <span class="tok-p">[</span> <span class="tok-s2">"bucklescript-tea"</span> <span class="tok-p">]</span> <span class="tok-p">}</span></code></pre> </div> </div> <div class="listingblock"> <div class="title">package.json</div> <div class="content"> <pre class="pygments highlight"><code data-lang="js"><span class="tok-p">{</span> <span class="tok-s2">"name"</span> <span class="tok-o">:</span> <span class="tok-s2">"bucklescript-have-tea"</span><span class="tok-p">,</span> <span class="tok-s2">"version"</span> <span class="tok-o">:</span> <span class="tok-s2">"0.1.0"</span><span class="tok-p">,</span> <span class="tok-s2">"dependencies"</span> <span class="tok-o">:</span> <span class="tok-p">{</span> <span class="tok-s2">"bucklescript-tea"</span> <span class="tok-o">:</span> <span class="tok-s2">"^0.1.2"</span> <span class="tok-p">},</span> <b class="conum">(1)</b> <span class="tok-s2">"peerDependencies"</span> <span class="tok-o">:</span> <span class="tok-p">{</span> <span class="tok-s2">"bs-platform"</span> <span class="tok-o">:</span> <span class="tok-s2">"^1.7.0"</span> <span class="tok-p">}</span> <b class="conum">(2)</b> <span class="tok-p">}</span></code></pre> </div> </div> <div class="colist arabic"> <ol> <li> <p>List <code>bucklescript-tea</code> as dependency</p> </li> <li> <p>List <code>bs-platform</code> as peer dependency</p> </li> </ol> </div> <div class="paragraph"> <p>Suppose you are in <code>bucklescript-have-tea</code> top directory,</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="sh">npm install <b class="conum">(1)</b> npm install bs-platform <b class="conum">(2)</b> ./node_modules/.bin/bsb -clean-world -make-world -w <b class="conum">(3)</b></code></pre> </div> </div> <div class="colist arabic"> <ol> <li> <p>Install the dependencies</p> </li> <li> <p>Install peer dependencies</p> </li> <li> <p>On Windows, it would be <code>.\node_modules\.bin\bsb -clean-world -make-world -w</code></p> </li> </ol> </div> <div class="paragraph"> <p>You can also change the <code>package-specs</code> to have another module format, for example, tweak your <code>bsconfig.json</code>:</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="js"><span class="tok-p">{</span> <span class="tok-p">...</span> <span class="tok-p">,</span> <span class="tok-s2">"package-specs"</span> <span class="tok-o">:</span> <span class="tok-p">[</span><span class="tok-s2">"amdjs"</span><span class="tok-p">,</span> <span class="tok-s2">"commonjs"</span><span class="tok-p">],</span> <span class="tok-p">...</span> <span class="tok-p">}</span></code></pre> </div> </div> <div class="paragraph"> <p>Rerun the command</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="sh">bsb -clean-world -make-world</code></pre> </div> </div> <div class="paragraph"> <p>You will get both <code>commonjs</code> and <code>amdjs</code> support. In the end, we suggest you <a href="http://bucklescript.github.io/bucklescript/docson/#build-schema.json">check out the schema</a> and enjoy the build!</p> </div> </div> <div class="sect2"> <h3 id="_namespace_support_since_1_9_0"><a class="anchor" href="#_namespace_support_since_1_9_0"></a>namespace support (@since 1.9.0)</h3> <div class="paragraph"> <p>OCaml treats file names as modules, so that users can only have unique file names in a project, BuckleScript solves the problem by scoping all modules by package.</p> </div> <div class="paragraph"> <p>Below is the <code>bsconfig.json</code> for <code>liba</code>, <code>libb</code> (they share the same configuration in this example)</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="js"><span class="tok-p">{</span> <span class="tok-s2">"name"</span><span class="tok-o">:</span> <span class="tok-s2">"liba"</span><span class="tok-p">,</span> <span class="tok-s2">"version"</span><span class="tok-o">:</span> <span class="tok-s2">"0.1.0"</span><span class="tok-p">,</span> <span class="tok-s2">"sources"</span><span class="tok-o">:</span> <span class="tok-s2">"src"</span><span class="tok-p">,</span> <span class="tok-s2">"namespace"</span><span class="tok-o">:</span> <span class="tok-kc">true</span> <span class="tok-p">}</span></code></pre> </div> </div> <div class="paragraph"> <p>Now you have a library to use them</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="js"><span class="tok-p">{</span> <span class="tok-s2">"name"</span><span class="tok-o">:</span> <span class="tok-s2">"namespace"</span><span class="tok-p">,</span> <span class="tok-s2">"version"</span><span class="tok-o">:</span> <span class="tok-s2">"0.1.0"</span><span class="tok-p">,</span> <span class="tok-s2">"sources"</span><span class="tok-o">:</span> <span class="tok-s2">"src"</span><span class="tok-p">,</span> <span class="tok-s2">"bs-dependencies"</span><span class="tok-o">:</span> <span class="tok-p">[</span> <span class="tok-s2">"liba"</span><span class="tok-p">,</span> <span class="tok-s2">"libb"</span> <span class="tok-p">]</span> <span class="tok-p">}</span></code></pre> </div> </div> <div class="paragraph"> <p>Since <code>liba</code> and <code>libb</code> are configured using namespace, to use them in source code, it would be like</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">let</span> <span class="tok-n">v</span> <span class="tok-o">=</span> <span class="tok-o">(</span><span class="tok-nn">Liba</span><span class="tok-p">.</span><span class="tok-nn">Demo</span><span class="tok-p">.</span><span class="tok-n">v</span> <span class="tok-o">+</span> <span class="tok-nn">Libb</span><span class="tok-p">.</span><span class="tok-nn">Demo</span><span class="tok-p">.</span><span class="tok-n">v</span><span class="tok-o">)</span></code></pre> </div> </div> <div class="admonitionblock note"> <table> <tr> <td class="icon"> <div class="title">Note</div> </td> <td class="content"> <div class="paragraph"> <p>In the same package, everything works the same whether it uses namespace or not, it only affects people who use your library</p> </div> </td> </tr> </table> </div> </div> <div class="sect2"> <h3 id="_in_source_build_support_since_1_9_0"><a class="anchor" href="#_in_source_build_support_since_1_9_0"></a>In source build support (@since 1.9.0)</h3> <div class="paragraph"> <p>When user has an existing JS project, it makes sense to output the JS file in the same directory as vanilla JS, so the schema added a key called <code>in-source</code> so that the JS file is generated next to ML file.</p> </div> <div class="paragraph"> <p>Example:</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="json"><span class="tok-p">{</span> <span class="tok-err">...</span> <span class="tok-nt">"package-specs"</span> <span class="tok-p">:</span> <span class="tok-p">[{</span> <span class="tok-nt">"module"</span><span class="tok-p">:</span> <span class="tok-s2">"commonjs"</span><span class="tok-p">,</span> <span class="tok-nt">"in-source"</span><span class="tok-p">:</span> <span class="tok-kc">true</span> <span class="tok-p">}]</span> <span class="tok-p">}</span></code></pre> </div> </div> </div> <div class="sect2"> <h3 id="_build_using_make"><a class="anchor" href="#_build_using_make"></a>Build using Make</h3> <div class="admonitionblock warning"> <table> <tr> <td class="icon"> <div class="title">Warning</div> </td> <td class="content"> <div class="paragraph"> <p><code>bsb</code> is the officially recommended build system. This section is included here only for people who are <em>curious</em> about how the build works.</p> </div> </td> </tr> </table> </div> <div class="paragraph"> <p>BuckleScript distribution has <code>bsdep.exe</code> which has the same interface as <code>ocamldep</code></p> </div> <div class="paragraph"> <p>Here is a simple Makefile to get started:</p> </div> <div class="listingblock"> <div class="title">Makefile</div> <div class="content"> <pre class="pygments highlight"><code data-lang="make"><span class="tok-nv">OCAMLC</span><span class="tok-o">=</span>bsc.exe <b class="conum">(1)</b> <span class="tok-nv">OCAMLDEP</span><span class="tok-o">=</span>bsdep.exe <b class="conum">(2)</b> <span class="tok-nv">SOURCE_LIST</span> <span class="tok-o">:=</span> src_a src_b <span class="tok-nv">SOURCE_MLI</span> <span class="tok-o">=</span> <span class="tok-k">$(</span>addsuffix .mli, <span class="tok-k">$(</span>SOURCE_LIST<span class="tok-k">))</span> <span class="tok-nv">SOURCE_ML</span> <span class="tok-o">=</span> <span class="tok-k">$(</span>addsuffix .ml, <span class="tok-k">$(</span>SOURCE_LIST<span class="tok-k">))</span> <span class="tok-nv">TARGETS</span> <span class="tok-o">:=</span> <span class="tok-k">$(</span>addsuffix .cmj, <span class="tok-k">$(</span>SOURCE_LIST<span class="tok-k">))</span> <span class="tok-nv">INCLUDES</span><span class="tok-o">=</span> <span class="tok-nf">all</span><span class="tok-o">:</span> <span class="tok-k">$(</span><span class="tok-nv">TARGETS</span><span class="tok-k">)</span> <span class="tok-nf">.mli</span><span class="tok-o">:</span>.<span class="tok-n">cmi</span> <span class="tok-k">$(</span>OCAMLC<span class="tok-k">)</span> <span class="tok-k">$(</span>INCLUDES<span class="tok-k">)</span> <span class="tok-k">$(</span>COMPFLAGS<span class="tok-k">)</span> -c <span class="tok-nv">$<</span> <span class="tok-nf">.ml</span><span class="tok-o">:</span>.<span class="tok-n">cmj</span>: <span class="tok-k">$(</span>OCAMLC<span class="tok-k">)</span> <span class="tok-k">$(</span>INCLUDES<span class="tok-k">)</span> <span class="tok-k">$(</span>COMPFLAGS<span class="tok-k">)</span> -c <span class="tok-nv">$<</span> <span class="tok-cp">-include .depend</span> <span class="tok-nf">depend</span><span class="tok-o">:</span> <span class="tok-k">$(</span>OCAMLDEP<span class="tok-k">)</span> <span class="tok-k">$(</span>INCLUDES<span class="tok-k">)</span> <span class="tok-k">$(</span>SOURCE_ML<span class="tok-k">)</span> <span class="tok-k">$(</span>SOURCE_MLI<span class="tok-k">)</span> > .depend</code></pre> </div> </div> <div class="colist arabic"> <ol> <li> <p>bsc.exe is the BuckleScript compiler</p> </li> <li> <p>ocamldep executable is part of the OCaml compiler installation</p> </li> </ol> </div> <div class="paragraph"> <p>In theory, people need run <code>make depend && make all</code>. <code>make depend</code> will calculate dependencies while <code>make all</code> will do the job.</p> </div> <div class="paragraph"> <p>However in practice, people used to a file watch service, such as <a href="https://facebook.github.io/watchman/">watchman</a> for example, will need the JSON configuration:</p> </div> <div class="listingblock"> <div class="title">build.json</div> <div class="content"> <pre class="pygments highlight"><code data-lang="json"><span class="tok-p">[</span> <span class="tok-s2">"trigger"</span><span class="tok-p">,</span> <span class="tok-s2">"."</span><span class="tok-p">,</span> <span class="tok-p">{</span> <span class="tok-nt">"name"</span><span class="tok-p">:</span> <span class="tok-s2">"build"</span><span class="tok-p">,</span> <span class="tok-nt">"expression"</span><span class="tok-p">:</span> <span class="tok-p">[</span><span class="tok-s2">"pcre"</span><span class="tok-p">,</span> <span class="tok-s2">"(\\.(ml|mll|mly|mli|sh|sh)$|Makefile)"</span><span class="tok-p">],</span> <b class="conum">(1)</b> <span class="tok-nt">"command"</span><span class="tok-p">:</span> <span class="tok-p">[</span><span class="tok-s2">"./build.sh"</span><span class="tok-p">],</span> <span class="tok-nt">"append_files"</span> <span class="tok-p">:</span> <span class="tok-kc">true</span> <span class="tok-p">}</span> <span class="tok-p">]</span></code></pre> </div> </div> <div class="colist arabic"> <ol> <li> <p>whenever such files are changed, it will trigger the <code>command</code> field to be run</p> </li> </ol> </div> <div class="listingblock"> <div class="title">build.sh</div> <div class="content"> <pre class="pygments highlight"><code data-lang="sh">make -r -j8 all <b class="conum">(1)</b> make depend <b class="conum">(2)</b></code></pre> </div> </div> <div class="colist arabic"> <ol> <li> <p>build</p> </li> <li> <p>update the dependency</p> </li> </ol> </div> <div class="paragraph"> <p>Now in your working directory, type <code>watchman -j < build.json</code> and enjoy the lightning build speed.</p> </div> </div> <div class="sect2"> <h3 id="_customize_rules_generators_support_since_1_7_4"><a class="anchor" href="#_customize_rules_generators_support_since_1_7_4"></a>Customize rules (generators support, @since 1.7.4)</h3> <div class="paragraph"> <p>It is quite common for programmers to use some preprocessors to generate some boilerplate code during developement.</p> </div> <div class="paragraph"> <p>Note preprocessors can be classified in two categories: one is system-dependent which must be delayed until running on the target machines and the other is system-independent (such as lex, yacc, m4, re2c, etc.) which could be executed anytime.</p> </div> <div class="paragraph"> <p>BuckleScript has built in support for conditional compilation for the second category. Since it is system-independent, we ask users to always generate such code and check it in before shipping, which would cut the dependencies for end users.</p> </div> <div class="paragraph"> <p>A typical example would be like this</p> </div> <div class="listingblock"> <div class="title">Bsb using ocamlyacc</div> <div class="content"> <pre class="pygments highlight"><code data-lang="js"><span class="tok-p">{</span> <span class="tok-s2">"generators"</span> <span class="tok-o">:</span> <span class="tok-p">[</span> <span class="tok-p">{</span> <span class="tok-s2">"name"</span> <span class="tok-o">:</span> <span class="tok-s2">"ocamlyacc"</span> <span class="tok-p">,</span> <span class="tok-s2">"command"</span> <span class="tok-o">:</span> <span class="tok-s2">"ocamlyacc $in"</span> <span class="tok-p">}</span> <span class="tok-p">],</span> <span class="tok-p">...,</span> <span class="tok-s2">"sources"</span> <span class="tok-o">:</span> <span class="tok-p">{</span> <span class="tok-s2">"dir"</span> <span class="tok-o">:</span> <span class="tok-s2">"src"</span><span class="tok-p">,</span> <span class="tok-s2">"generators"</span> <span class="tok-o">:</span> <span class="tok-p">[</span> <span class="tok-p">{</span> <span class="tok-s2">"name"</span> <span class="tok-o">:</span> <span class="tok-s2">"ocamlyacc"</span><span class="tok-p">,</span> <span class="tok-s2">"edge"</span> <span class="tok-o">:</span> <span class="tok-p">[</span><span class="tok-s2">"test.ml"</span><span class="tok-p">,</span> <span class="tok-s2">"test.mli"</span><span class="tok-p">,</span> <span class="tok-s2">":"</span><span class="tok-p">,</span> <span class="tok-s2">"test.mly"</span><span class="tok-p">]</span> <span class="tok-p">}</span> <span class="tok-p">]</span> <span class="tok-p">}</span> <span class="tok-p">}</span></code></pre> </div> </div> <div class="paragraph"> <p>Note <code>ocamlyacc</code> will generate <code>test.ml</code> and <code>test.mli</code> in the same directory with <code>test.mly</code>. The developer should check in the generated file since then users would not need run <code>ocamlyacc</code> again. This would apply to <code>menhir</code> as well.</p> </div> <div class="paragraph"> <p>When a developer is working on their current project, <code>bsb</code> will track the dependencies between <code>test.ml</code> and <code>test.mly</code> properly. When released as a package, <code>bsb</code> will cut such a dependency, so that users will only need the generated <code>test.ml</code>. To help test such behavior, developers can set it manually:</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="js"><span class="tok-p">{</span> <span class="tok-p">...,</span> <span class="tok-s2">"cut-generators"</span> <span class="tok-o">:</span> <span class="tok-kc">true</span> <span class="tok-p">}</span></code></pre> </div> </div> <div class="paragraph"> <p>With this setting <code>bsb</code> will not regenerate <code>test.ml</code> whenever <code>test.mly</code> changes.</p> </div> </div> </div> </div> <div class="sect1"> <h2 id="_faq"><a class="anchor" href="#_faq"></a>FAQ</h2> <div class="sectionbody"> <div class="qlist qanda"> <ol> <li> <p><em>How does IO work in the browser?</em></p> <p>In general, it is very hard to simulate IO in the browser, we recommend users write bindings to NodeJS directly for server side, or use <code>Js.log</code> in client side, see discussions in <a href="https://github.com/bucklescript/bucklescript/issues/748">#748</a></p> </li> <li> <p><em>The compiler does not build?</em></p> <p> In production mode, the compiler is a single file in <code>jscomp/bin/compiler.ml</code>. If it is not compiling, make sure you have the right OCaml compiler version. Currently the OCaml compiler is a submodule of BuckleScript. Make sure the exact commit hash matches (we only update the compiler occasionally).</p> </li> <li> <p><em>Which version of JavaScript syntax does BuckleScript target?</em></p> <p>BuckleScript targets <strong>ES5</strong>.</p> </li> <li> <p><em>Does BuckleScript work with merlin?</em></p> <p>Yes, you need edit your <code>.merlin</code> file:</p> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code>B node_modules/bs-platform/lib/ocaml S node_modules/bs-platform/lib/ocaml FLG -ppx node_modules/bs-platform/bin/bsppx.exe</code></pre> </div> </div> <div class="paragraph"> <p>Note there is a <a href="https://github.com/the-lambda-church/merlin/issues/568">upstream fix</a> in Merlin, make sure your merlin is updated.</p> </div> </li> <li> <p><em>What polyfills does BuckleScript need?</em></p> <div class="ulist"> <ul> <li> <p><em>Math.imul</em>: This polyfill is needed for <code>int32</code> multiplication. BuckleScript provides this by default (when feature detection returns false), no action is required from the user.</p> </li> <li> <p><em>TypedArray</em>: The TypedArray polyfill is not provided by BuckleScript and it’s the responsibility of the user to bundle the desired polyfill implementation with the BuckleScript generated code.</p> <div class="literalblock"> <div class="content"> <pre>The following functions from OCaml stdlib require the TypedArray polyfill:</pre> </div> </div> <div class="ulist"> <ul> <li> <p>Int64.float_of_bits</p> </li> <li> <p>Int64.bits_of_float</p> </li> <li> <p>Int32.float_of_bits</p> </li> <li> <p>Int32.bits_of_float</p> <div class="admonitionblock warning"> <table> <tr> <td class="icon"> <div class="title">Warning</div> </td> <td class="content"> <div class="paragraph"> <p>For the current BuckleScript version, if the user does not bundle the TypedArray polyfill, the JavaScript engine does not support it and user used functions mentioned above, the code will fail at runtime.</p> </div> </td> </tr> </table> </div> </li> </ul> </div> </li> </ul> </div> </li> <li> <p><em>Uncurried functions cannot be polymorphic?</em></p> <p>E.g. if you try to do this at toplevel:</p> </li> </ol> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code>let id : ('a -> 'a [@bs]) = ((fun v -> v) [@bs])</code></pre> </div> </div> <div class="paragraph"> <p>You’ll get this dreaded error message</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code>Error: The type of this expression, ([ `Arity_1 of '_a ], '_a) Js.fn, contains type variables that cannot be generalized</code></pre> </div> </div> <div class="paragraph"> <p>The issue here isn’t that the function is polymorphic. You can use (and probably have used) polymorphic uncurried functions without any problem as inline callbacks. But you can’t export them. The issue here is the combination of using the uncurried calling convention, polymorphism and exporting (by default). It’s an unfortunate limitation partly due to how OCaml’s type system incorporates side-effects, and partly due to how BuckleScript handles uncurrying. The simplest solution is in most cases to just not export it, by adding an interface to the module. Alternatively, if you really, really need to export it, you can do so in its curried form, and then wrap it in an uncurried lambda at the call site. E.g.:</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code>lat _ = map (fun v -> id v [@bs])</code></pre> </div> </div> </div> </div> <div class="sect1"> <h2 id="_high_level_compiler_workflow"><a class="anchor" href="#_high_level_compiler_workflow"></a>High Level compiler workflow</h2> <div class="sectionbody"> <div class="paragraph"> <p>The high level architecture is illustrated below:</p> </div> <div class="listingblock"> <div class="content"> <pre>Source Language | | (Reuse OCaml Parser) v Surface Syntax Tree | | (built in Syntax tree transformation) v Surface Syntax Tree | | (Reuse OCaml Type checker) v Typedtree | | (Reuse OCaml pattern match compiler and erase types) | (Patches to pass more information down to Lambda ) | OCaml Lambda IR | | v Buckle Lambda IR ------------------+ | ^ | | | 6 Lambda Passes (lam_* files) | | Optimization/inlining/dead code elimination | \ | | \ --------------------------+ | | Self tail call elimination | Constant folding + propagation V JS IR (J.ml) ---------------------+ | ^ | | | 6 JS Passes (js_* files) | | Optimization/inlining/dead code elimination | \ | | \ -------------------------+ | | Smart printer includes scope analysis | V Javascript Code</pre> </div> </div> <div class="sect2"> <h3 id="_design_principles"><a class="anchor" href="#_design_principles"></a>Design Principles</h3> <div class="paragraph"> <p>The current design of BuckleScript follows several high level principles. While those principles might change in the future, they are enforced today and can explain certain technical limitations BuckleScript has.</p> </div> <div class="paragraph"> <p><strong>Lambda Representation</strong></p> </div> <div class="paragraph"> <p>As pictured in the diagram above, BuckleScript is primarily based on the Lambda representation of the OCaml compiler. While this representation is quite rich, some information is lost from the upstream representation. The patch to the OCaml compiler tries to enrich this representation in a non-intrusive way (see next section).</p> </div> <div class="paragraph"> <p><strong>Minimal Patch to the OCaml compiler</strong></p> </div> <div class="paragraph"> <p>BuckleScript requires patches to the OCaml compiler. One of the main reasons is to enrich the Lambda representation so that the generated code is as nice as possible. A design goal is to keep those patches minimal and useful for the OCaml compiler in general so that they can later be integrated.</p> </div> <div class="admonitionblock note"> <table> <tr> <td class="icon"> <div class="title">Note</div> </td> <td class="content"> <div class="paragraph"> <p>A common question is to wonder why BuckleScript transpiles an OCaml record value to a JavaScript array while a more intuitive representation would be a JavaScript object. This technical decision is a direct consequence of the above 2 design principles: the Lambda layer assumes in a lot of places that a record value is an array and such modification would be too large of a change to OCaml compiler.</p> </div> </td> </tr> </table> </div> </div> <div class="sect2"> <h3 id="_soundness"><a class="anchor" href="#_soundness"></a>Soundness</h3> <div class="paragraph"> <p>BuckleScript preserves the soundness of the OCaml language. Assuming the FFI is correctly implemented, the type safety is preserved.</p> </div> </div> <div class="sect2"> <h3 id="_minimal_new_symbol_creation"><a class="anchor" href="#_minimal_new_symbol_creation"></a>Minimal new symbol creation</h3> <div class="paragraph"> <p>In order to make the JavaScript generated code as close as possible to the original OCaml core we thrive to introduce as few new symbols as possible.</p> </div> </div> </div> </div> <div class="sect1"> <h2 id="_runtime_representation"><a class="anchor" href="#_runtime_representation"></a>Runtime representation</h2> <div class="sectionbody"> <div class="paragraph"> <p>Below is a description of how OCaml values are encoded in JavaScript, the <strong>internal</strong> description means <strong>users should not rely on its actual encoding (and it is subject to change)</strong>. We recommend that you write setter/getter functions to manipulate safely OCaml values from JavaScript.</p> </div> <div class="paragraph"> <p>For example, users should not rely on how OCaml <code>list</code> is encoded in JavaScript; instead, the OCaml stdlib provides three functions: <code>List.cons</code>, <code>List.hd</code> and <code>List.tl</code>. JavaScript code should only rely on those three functions.</p> </div> <div class="sect2"> <h3 id="_simple_ocaml_type"><a class="anchor" href="#_simple_ocaml_type"></a>Simple OCaml type</h3> <table class="tableblock frame-all grid-all spread"> <colgroup> <col style="width: 50%;"> <col style="width: 50%;"> </colgroup> <thead> <tr> <th class="tableblock halign-left valign-top">ocaml type</th> <th class="tableblock halign-left valign-top">JavaScript type</th> </tr> </thead> <tbody> <tr> <td class="tableblock halign-left valign-top"><p class="tableblock">int</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">number</p></td> </tr> <tr> <td class="tableblock halign-left valign-top"><p class="tableblock">nativeint</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">number</p></td> </tr> <tr> <td class="tableblock halign-left valign-top"><p class="tableblock">int32</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">number</p></td> </tr> <tr> <td class="tableblock halign-left valign-top"><p class="tableblock">float</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">number</p></td> </tr> <tr> <td class="tableblock halign-left valign-top"><p class="tableblock">bool</p></td> <td class="tableblock halign-left valign-top"><div><div class="paragraph"> <p>number</p> </div> <div class="ulist"> <ul> <li> <p>true → 1</p> </li> <li> <p>false → 0</p> </li> </ul> </div></div></td> </tr> <tr> <td class="tableblock halign-left valign-top"><p class="tableblock">int64</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">Array of size two numbers <code>[hi,lo]</code>. <code>hi</code> is signed while <code>lo</code> is unsigned</p></td> </tr> <tr> <td class="tableblock halign-left valign-top"><p class="tableblock">char</p></td> <td class="tableblock halign-left valign-top"><div><div class="paragraph"> <p>number</p> </div> <div class="paragraph"> <p>for example:</p> </div> <div class="ulist"> <ul> <li> <p>'a' → <code>97</code></p> </li> </ul> </div></div></td> </tr> <tr> <td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td> </tr> <tr> <td class="tableblock halign-left valign-top"><p class="tableblock">bytes</p></td> <td class="tableblock halign-left valign-top"><div><div class="paragraph"> <p>number array</p> </div> <div class="admonitionblock note"> <table> <tr> <td class="icon"> <div class="title">Note</div> </td> <td class="content"> We might encode it as buffer in NodeJS. </td> </tr> </table> </div></div></td> </tr> <tr> <td class="tableblock halign-left valign-top"><p class="tableblock">'a array</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">Array</p></td> </tr> <tr> <td class="tableblock halign-left valign-top"><p class="tableblock">record</p></td> <td class="tableblock halign-left valign-top"><div><div class="paragraph"> <p>Array <strong>internal</strong></p> </div> <div class="paragraph"> <p>For instance:</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">type</span> <span class="tok-n">t</span> <span class="tok-o">=</span> <span class="tok-o">{</span> <span class="tok-n">x</span> <span class="tok-o">:</span> <span class="tok-kt">int</span><span class="tok-o">;</span> <span class="tok-n">y</span> <span class="tok-o">:</span> <span class="tok-kt">int</span> <span class="tok-o">}</span> <span class="tok-k">let</span> <span class="tok-n">v</span> <span class="tok-o">=</span> <span class="tok-o">{</span><span class="tok-n">x</span> <span class="tok-o">=</span> <span class="tok-mi">1</span><span class="tok-o">;</span> <span class="tok-n">y</span> <span class="tok-o">=</span> <span class="tok-mi">2</span><span class="tok-o">}</span></code></pre> </div> </div> <div class="paragraph"> <p>Output:</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="js"><span class="tok-kd">var</span> <span class="tok-nx">v</span> <span class="tok-o">=</span> <span class="tok-p">[</span><span class="tok-mi">1</span><span class="tok-p">,</span><span class="tok-mi">2</span><span class="tok-p">]</span></code></pre> </div> </div></div></td> </tr> <tr> <td class="tableblock halign-left valign-top"><p class="tableblock">tuple</p></td> <td class="tableblock halign-left valign-top"><div><div class="paragraph"> <p>Array</p> </div> <div class="paragraph"> <p>For example:</p> </div> <div class="ulist"> <ul> <li> <p>(3,4) → [3,4]</p> </li> </ul> </div></div></td> </tr> <tr> <td class="tableblock halign-left valign-top"><p class="tableblock"><code>’a option</code></p></td> <td class="tableblock halign-left valign-top"><div><div class="paragraph"> <p><strong>internal</strong></p> </div> <div class="paragraph"> <p>For example:</p> </div> <div class="ulist"> <ul> <li> <p><code>None</code> → <code>0</code></p> </li> <li> <p><code>Some a</code> → <code>[a]</code></p> </li> </ul> </div></div></td> </tr> <tr> <td class="tableblock halign-left valign-top"><p class="tableblock">list</p></td> <td class="tableblock halign-left valign-top"><div><div class="paragraph"> <p><strong>internal</strong></p> </div> <div class="paragraph"> <p>For example:</p> </div> <div class="ulist"> <ul> <li> <p><code>[]</code> → <code>0</code></p> </li> <li> <p><code>x::y</code> → <code>[x,y]</code></p> </li> <li> <p><code>1::2::[3]</code> → <code>[ 1, [ 2, [ 3, 0 ] ] ]</code></p> </li> </ul> </div></div></td> </tr> <tr> <td class="tableblock halign-left valign-top"><p class="tableblock">Variant</p></td> <td class="tableblock halign-left valign-top"><div><div class="paragraph"> <p><strong>internal</strong> (subject to change)</p> </div> <div class="paragraph"> <p>Simple Variants: (Variants with only one non-nullary constructor)</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">type</span> <span class="tok-n">tree</span> <span class="tok-o">=</span> <span class="tok-o">|</span> <span class="tok-nc">Leaf</span> <span class="tok-o">|</span> <span class="tok-nc">Node</span> <span class="tok-k">of</span> <span class="tok-kt">int</span> <span class="tok-o">*</span> <span class="tok-n">tree</span> <span class="tok-o">*</span> <span class="tok-n">tree</span> <span class="tok-c">(* Leaf --> 0 *)</span> <span class="tok-c">(* Node(a,b,c) --> [a,b,c]*)</span></code></pre> </div> </div> <div class="paragraph"> <p>Complex Variants: (Variants with more than one non-nullary constructor)</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">type</span> <span class="tok-n">u</span> <span class="tok-o">=</span> <span class="tok-o">|</span> <span class="tok-nc">A</span> <span class="tok-k">of</span> <span class="tok-kt">string</span> <span class="tok-o">|</span> <span class="tok-nc">B</span> <span class="tok-k">of</span> <span class="tok-kt">int</span> <span class="tok-c">(* A a --> [a].tag=0 -- tag 0 assignment is optional *)</span> <span class="tok-c">(* B b --> [b].tag=1 *)</span></code></pre> </div> </div></div></td> </tr> <tr> <td class="tableblock halign-left valign-top"><p class="tableblock">Polymorphic variant</p></td> <td class="tableblock halign-left valign-top"><div><div class="paragraph"> <p><strong>internal</strong></p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-o">`</span><span class="tok-n">a</span> <span class="tok-c">(* 97 *)</span> <span class="tok-o">`</span><span class="tok-n">a</span> <span class="tok-mi">1</span> <span class="tok-mi">2</span> <span class="tok-c">(* [97, [1,2] ]*)</span></code></pre> </div> </div></div></td> </tr> <tr> <td class="tableblock halign-left valign-top"><p class="tableblock">exception</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>internal</strong></p></td> </tr> <tr> <td class="tableblock halign-left valign-top"><p class="tableblock">extension</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>internal</strong></p></td> </tr> <tr> <td class="tableblock halign-left valign-top"><p class="tableblock">object</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>internal</strong></p></td> </tr> <tr> <td class="tableblock halign-left valign-top"><p class="tableblock"><code>Js.boolean</code></p></td> <td class="tableblock halign-left valign-top"><div><div class="paragraph"> <p>boolean</p> </div> <div class="paragraph"> <p>For example:</p> </div> <div class="ulist"> <ul> <li> <p>Js.true_ → true</p> </li> <li> <p>Js.false_ → false</p> </li> </ul> </div> <div class="listingblock"> <div class="title">Js module</div> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">type</span> <span class="tok-n">boolean</span> <span class="tok-k">val</span> <span class="tok-n">to_bool</span><span class="tok-o">:</span> <span class="tok-n">boolean</span> <span class="tok-o">-></span> <span class="tok-kt">bool</span></code></pre> </div> </div> <div class="listingblock"> <div class="title"><a href="../api/Js.Boolean.html">Js.Boolean</a> module</div> <div class="content"> <pre>val to_js_boolean: bool -> Js.boolean</pre> </div> </div></div></td> </tr> <tr> <td class="tableblock halign-left valign-top"><p class="tableblock"><code>'a Js.Null.t</code></p></td> <td class="tableblock halign-left valign-top"><div><div class="paragraph"> <p>Either <code>'a</code> or <code>null</code>. <code>Js.Null.empty</code> represents <code>null</code> too.</p> </div> <div class="listingblock"> <div class="title"><a href="../api/Js.Null.html">Js.Null</a> module</div> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">val</span> <span class="tok-n">to_opt</span> <span class="tok-o">:</span> <span class="tok-k">'</span><span class="tok-n">a</span> <span class="tok-n">t</span> <span class="tok-o">-></span> <span class="tok-k">'</span><span class="tok-n">a</span> <span class="tok-n">option</span> <span class="tok-k">val</span> <span class="tok-n">from_opt</span> <span class="tok-o">:</span> <span class="tok-k">'</span><span class="tok-n">a</span> <span class="tok-n">option</span> <span class="tok-o">-></span> <span class="tok-k">'</span><span class="tok-n">a</span> <span class="tok-n">t</span> <span class="tok-k">val</span> <span class="tok-n">return</span> <span class="tok-o">:</span> <span class="tok-k">'</span><span class="tok-n">a</span> <span class="tok-o">-></span> <span class="tok-k">'</span><span class="tok-n">a</span> <span class="tok-n">t</span> <span class="tok-k">val</span> <span class="tok-n">test</span> <span class="tok-o">:</span> <span class="tok-k">'</span><span class="tok-n">a</span> <span class="tok-n">t</span> <span class="tok-o">-></span> <span class="tok-kt">bool</span></code></pre> </div> </div></div></td> </tr> <tr> <td class="tableblock halign-left valign-top"><p class="tableblock"><code>'a Js.Undefined.t</code></p></td> <td class="tableblock halign-left valign-top"><div><div class="paragraph"> <p>Either <code>'a</code> or <code>undefined</code>. Same operations as <code>'a Js.Null.t</code>. <code>Js.Undefined.empty</code> represents <code>undefined</code> too.</p> </div></div></td> </tr> <tr> <td class="tableblock halign-left valign-top"><p class="tableblock"><code>'a Js.Null_undefined.t</code></p></td> <td class="tableblock halign-left valign-top"><div><div class="paragraph"> <p>Either <code>'a</code>, <code>null</code> or <code>undefined</code>. Same operations as <code>'a Js.Null.t</code>.</p> </div> <div class="paragraph"> <p><code>Js.Null_undefined.undefined</code> represents <code>undefined</code>, <code>Js.Null_undefined.null</code> represents <code>null</code>.</p> </div> <div class="paragraph"> <p>This module’s null tests check for both <code>null</code> and <code>undefined</code>; if you know the value’s only ever going to be <code>null</code> and not undefined, use <code>Js.Null</code> instead. Likewise for <code>Js.Undefined</code>.</p> </div></div></td> </tr> </tbody> </table> <div class="admonitionblock note"> <table> <tr> <td class="icon"> <div class="title">Note</div> </td> <td class="content"> <code>Js.to_opt</code> is optimized when the <code>option</code> is not escaped </td> </tr> </table> </div> <div class="admonitionblock note"> <table> <tr> <td class="icon"> <div class="title">Note</div> </td> <td class="content"> In the future, we will have a <em>debug</em> mode, in which the corresponding js encoding will be instrumented with more information </td> </tr> </table> </div> <div class="paragraph"> <p>As we clarified before, the internal representation should not be relied upon. We are working to provide a ppx extension as below:</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">type</span> <span class="tok-n">t</span> <span class="tok-o">=</span> <span class="tok-o">|</span> <span class="tok-nc">A</span> <span class="tok-o">|</span> <span class="tok-nc">B</span> <span class="tok-k">of</span> <span class="tok-kt">int</span> <span class="tok-o">*</span> <span class="tok-kt">int</span> <span class="tok-o">|</span> <span class="tok-nc">C</span> <span class="tok-k">of</span> <span class="tok-kt">int</span> <span class="tok-o">*</span> <span class="tok-kt">int</span> <span class="tok-o">|</span> <span class="tok-nc">D</span> <span class="tok-o">[@@</span><span class="tok-n">bs</span><span class="tok-o">.</span><span class="tok-n">deriving</span><span class="tok-o">{</span><span class="tok-n">export</span><span class="tok-o">}]</span></code></pre> </div> </div> <div class="paragraph"> <p>So that it will a automatically provide <code>constructing</code> and <code>destructing</code> functions:</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">val</span> <span class="tok-n">a</span> <span class="tok-o">:</span> <span class="tok-n">t</span> <span class="tok-k">val</span> <span class="tok-n">b</span> <span class="tok-o">:</span> <span class="tok-kt">int</span> <span class="tok-o">-></span> <span class="tok-kt">int</span> <span class="tok-o">-></span> <span class="tok-n">t</span> <span class="tok-k">val</span> <span class="tok-n">c</span> <span class="tok-o">:</span> <span class="tok-kt">int</span> <span class="tok-o">-></span> <span class="tok-kt">int</span> <span class="tok-o">-></span> <span class="tok-n">t</span> <span class="tok-k">val</span> <span class="tok-n">d</span> <span class="tok-o">:</span> <span class="tok-kt">int</span> <span class="tok-k">val</span> <span class="tok-n">a_of_t</span> <span class="tok-o">:</span> <span class="tok-n">t</span> <span class="tok-o">-></span> <span class="tok-kt">bool</span> <span class="tok-k">val</span> <span class="tok-n">d_of_t</span> <span class="tok-o">:</span> <span class="tok-n">t</span> <span class="tok-o">-></span> <span class="tok-kt">bool</span> <span class="tok-k">val</span> <span class="tok-n">b_of_t</span> <span class="tok-o">:</span> <span class="tok-n">t</span> <span class="tok-o">-></span> <span class="tok-o">(</span><span class="tok-kt">int</span> <span class="tok-o">*</span> <span class="tok-kt">int</span> <span class="tok-o">)</span> <span class="tok-nn">Js</span><span class="tok-p">.</span><span class="tok-nn">Null</span><span class="tok-p">.</span><span class="tok-n">t</span> <span class="tok-k">val</span> <span class="tok-n">c_of_t</span> <span class="tok-o">:</span> <span class="tok-n">t</span> <span class="tok-o">-></span> <span class="tok-o">(</span><span class="tok-kt">int</span> <span class="tok-o">*</span> <span class="tok-kt">int</span> <span class="tok-o">)</span> <span class="tok-nn">Js</span><span class="tok-p">.</span><span class="tok-nn">Null</span><span class="tok-p">.</span><span class="tok-n">t</span></code></pre> </div> </div> </div> </div> </div> <div class="sect1"> <h2 id="_integration_with_reason"><a class="anchor" href="#_integration_with_reason"></a>Integration with Reason</h2> <div class="sectionbody"> <div class="paragraph"> <p>You can play with Reason using the playground <a href="https://bucklescript.github.io/bucklescript/reason-demo">Facebook Reason</a></p> </div> <div class="admonitionblock note"> <table> <tr> <td class="icon"> <div class="title">Note</div> </td> <td class="content"> <div class="title">The playgrounds are only for demos and might not be the latest</div> <div class="paragraph"> <p>You should always use the command line as your production tool.</p> </div> </td> </tr> </table> </div> <div class="paragraph"> <p>There is a stand alone example <a href="https://github.com/bucklescript/bucklescript-addons/blob/master/examples/reason-demo/package.json">here</a>.</p> </div> </div> </div> <div class="sect1"> <h2 id="_contributions"><a class="anchor" href="#_contributions"></a>Contributions</h2> <div class="sectionbody"> <div class="paragraph"> <p>First, thanks for your interest in contributing! There are plenty of ways to make contributions, like blogging, sharing your experience, open sourcing your libraries using BuckleScript. They are all deeply appreciated.</p> </div> <div class="paragraph"> <p>This section will focus on how to contribute to this repo.</p> </div> <div class="sect2"> <h3 id="_development_set_up"><a class="anchor" href="#_development_set_up"></a>Development set-up</h3> <div class="ulist"> <ul> <li> <p>Having <a href="https://opam.ocaml.org/">opam</a> installed</p> <div class="literalblock"> <div class="content"> <pre>opam switch 4.02.3+buckle-master # use our OCaml compiler opam install camlp4 <1></pre> </div> </div> <div class="paragraph"> <p><code>Camlp4</code> is used to generate OCaml code for processing large AST. (<code>j.ml</code> file), if you don’t change <code>j.ml</code> (most likely you won’t), so you probably don’t need it</p> </div> </li> <li> <p>Having <a href="https://nodejs.org/">NodeJS</a> installed</p> </li> <li> <p>Having Make installed</p> </li> <li> <p>OS: Mac/Linux (Note BuckleScript works on Windows, but the dev mode is not tested)</p> </li> </ul> </div> <div class="paragraph"> <p><strong>Below assume that you are working in <code>jscomp</code> directory, and that you’ve followed instructions from <a href="#Minimal dependencies">[Minimal dependencies]</a> to build OCaml.</strong></p> </div> </div> <div class="sect2"> <h3 id="_contributing_to_code_bsb_exe_code"><a class="anchor" href="#_contributing_to_code_bsb_exe_code"></a>Contributing to <code>bsb.exe</code></h3> <div class="paragraph"> <p>The build target is</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="sh">make -C bin bsb.exe</code></pre> </div> </div> <div class="paragraph"> <p>So whenever you change files relevant to the build tool <code>bsb.exe</code>, try it and do some test. If it works, send a pull request!</p> </div> <div class="paragraph"> <p>Note that for most binaries in BuckleScript, we also have a <strong>release mode</strong>, which will pack all relevant files into a single file. This is important, since it will cut all our dev-dependencies, so the user does not need install those tools.</p> </div> <div class="paragraph"> <p>You can verify it by typing</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="sh">make snapshotml <span class="tok-c"># see the diffs in jscomp/bin</span></code></pre> </div> </div> <div class="paragraph"> <p>But please <strong>don’t commit</strong> those changes in PR, it will cause painful merge conflicts.</p> </div> </div> <div class="sect2"> <h3 id="_contributing_to_code_bsc_exe_code"><a class="anchor" href="#_contributing_to_code_bsc_exe_code"></a>Contributing to <code>bsc.exe</code></h3> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="sh">make -C bin bsc.exe <span class="tok-c"># build the compiler in dev mode</span></code></pre> </div> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="sh">make libs <span class="tok-c"># build all libs using the dev compiler</span></code></pre> </div> </div> <div class="paragraph"> <p>There is also a snapshot mode,</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="sh">make snapshotml</code></pre> </div> </div> <div class="paragraph"> <p>This will actually snapshot your changes into a single ml file and used in npm distribution. But please <strong>don’t commit</strong> those changes in PR, it will cause painful merge conflicts.</p> </div> </div> <div class="sect2"> <h3 id="_contributing_to_the_runtime"><a class="anchor" href="#_contributing_to_the_runtime"></a>Contributing to the runtime</h3> <div class="paragraph"> <p>BuckleScript runtime implementation is currently a mix of OCaml and JavaScript. (<code>jscomp/runtime</code> directory). The JavaScript code is defined in the <code>.ml</code> file using the <code>bs.raw</code> syntax extension.</p> </div> <div class="paragraph"> <p>The goal is to implement the runtime <strong>purely in OCaml</strong> and you can help contribute.</p> </div> <div class="paragraph"> <p>Each new PR should include appropriate testing.</p> </div> <div class="paragraph"> <p>Currently all tests are in <code>jscomp/test</code> directory and you should either add a new test file or modify an existing test which covers the part of the compiler you modified.</p> </div> <div class="ulist"> <ul> <li> <p>Add the filename in <code>jscomp/test/test.mllib</code></p> </li> <li> <p>Add a suite test</p> </li> </ul> </div> <div class="paragraph"> <p>The specification is in <code>jscomp/test/mt.ml</code></p> </div> <div class="paragraph"> <p>For example some simple tests would be like:</p> </div> <div class="listingblock"> <div class="content"> <pre class="pygments highlight"><code data-lang="ocaml"><span class="tok-k">let</span> <span class="tok-n">suites</span> <span class="tok-o">:</span> <span class="tok-o">_</span> <span class="tok-nn">Mt</span><span class="tok-p">.</span><span class="tok-n">pair_suites</span> <span class="tok-o">=</span> <span class="tok-o">[</span><span class="tok-s2">"hey"</span><span class="tok-o">,</span> <span class="tok-o">(</span><span class="tok-k">fun</span> <span class="tok-o">_</span> <span class="tok-o">-></span> <span class="tok-nc">Eq</span><span class="tok-o">(</span><span class="tok-bp">true</span><span class="tok-o">,</span> <span class="tok-mi">3</span> <span class="tok-o">></span> <span class="tok-mi">2</span><span class="tok-o">));</span> <span class="tok-s2">"hi"</span><span class="tok-o">,</span> <span class="tok-o">(</span><span class="tok-k">fun</span> <span class="tok-o">_</span> <span class="tok-o">-></span> <span class="tok-nc">Neq</span><span class="tok-o">(</span><span class="tok-mi">2</span><span class="tok-o">,</span><span class="tok-mi">3</span><span class="tok-o">));</span> <span class="tok-s2">"hello"</span><span class="tok-o">,</span> <span class="tok-o">(</span><span class="tok-k">fun</span> <span class="tok-o">_</span> <span class="tok-o">-></span> <span class="tok-nc">Approx</span><span class="tok-o">(</span><span class="tok-mi">3</span><span class="tok-o">.</span><span class="tok-mi">0</span><span class="tok-o">,</span> <span class="tok-mi">3</span><span class="tok-o">.</span><span class="tok-mi">0</span><span class="tok-o">));</span> <span class="tok-s2">"throw"</span><span class="tok-o">,</span> <span class="tok-o">(</span><span class="tok-k">fun</span> <span class="tok-o">_</span> <span class="tok-o">-></span> <span class="tok-nc">ThrowAny</span><span class="tok-o">(</span><span class="tok-k">fun</span> <span class="tok-o">_</span> <span class="tok-o">-></span> <span class="tok-k">raise</span> <span class="tok-mi">3</span><span class="tok-o">))</span> <span class="tok-o">]</span> <span class="tok-k">let</span> <span class="tok-bp">()</span> <span class="tok-o">=</span> <span class="tok-nn">Mt</span><span class="tok-p">.</span><span class="tok-n">from_pair_suites</span> <span class="tok-o">__</span><span class="tok-n">FILE__</span> <span class="tok-n">suites</span></code></pre> </div> </div> <div class="ulist"> <ul> <li> <p>Run the tests</p> </li> </ul> </div> <div class="paragraph"> <p>Suppose you have mocha installed, if not, try <code>npm install mocha</code></p> </div> <div class="paragraph"> <p><code>mocha -R list jscomp/test/your_test_file.js</code></p> </div> <div class="paragraph"> <p>To build libs, tests and run all tests:</p> </div> <div class="paragraph"> <p><code>make libs && make -C test all && npm test</code></p> </div> <div class="ulist"> <ul> <li> <p>See the coverage</p> </li> </ul> </div> <div class="paragraph"> <p><code>npm run cover</code></p> </div> </div> <div class="sect2"> <h3 id="_contributing_to_the_documentation"><a class="anchor" href="#_contributing_to_the_documentation"></a>Contributing to the documentation</h3> <div class="paragraph"> <p>You’ll need <a href="http://asciidoctor.org/">Asciidoctor</a> installed and on your <code>PATH</code>. Go into <code>site/docsource/</code>, modify the section you want, and run <code>build.sh</code>. You can check the <code>build.compile</code> file for debug output.</p> </div> </div> <div class="sect2"> <h3 id="_contributing_to_the_api_reference"><a class="anchor" href="#_contributing_to_the_api_reference"></a>Contributing to the API reference</h3> <div class="paragraph"> <p>The API reference is generated from doc comments in the source code. <a href="https://github.com/bucklescript/bucklescript/blob/99650/jscomp/others/js_re.mli#L146-L161">Here</a>'s a good example</p> </div> <div class="paragraph"> <p>Some tips and guidelines:</p> </div> <div class="ulist"> <ul> <li> <p>The first sentence or line should be a very short summary. This is used in indexes and by tools like merlin.</p> </li> <li> <p>Ideally, every function should have <strong>at least one</strong> <code>@example</code></p> </li> <li> <p>Cross-reference another definition with <code>{! identifier}</code>. But use them sparingly, they’re a bit verbose (currently, at least).</p> </li> <li> <p>Wrap non-cross-referenced identifiers and other code in <code>[ …​ ]</code></p> </li> <li> <p>Escape <code>{</code>, <code>}</code>, <code>[</code>, <code>]</code> and <code>@</code> using <code>\</code></p> </li> <li> <p>It’s possible to use <code>{%html …​}</code> to generate custom html, but use this very, very sparingly.</p> </li> <li> <p>A number of "documentation tags" are provided that would be nice to use, but unfortunately they’re often not supported for `external`s. Which is of course most of the API.</p> </li> <li> <p><code>@param</code> usually doesn’t work. Use <code>{b <param>} …​</code> instead</p> </li> <li> <p><code>@returns</code> usually doesn’t work. Use <code>{b returns} …​</code> instead.</p> </li> <li> <p>Always use <code>@deprecated</code> when applicable.</p> </li> <li> <p>Always use <code>@raise</code> when applicable.</p> </li> <li> <p>Always provide a <code>@see</code> tag pointing to MDN for more information when available.</p> </li> </ul> </div> <div class="paragraph"> <p>See <a href="http://caml.inria.fr/pub/docs/manual-ocaml/ocamldoc.html#sec333">Ocamldoc documentation</a> for a lot more details.</p> </div> <div class="paragraph"> <p>To generate the html, run <code>make docs</code> in <code>jscomp/</code>.</p> </div> <div class="paragraph"> <p>Html generation uses a custom generator located in <code>odoc_gen/</code> and custom styles located in <code>docs/api_static</code>.</p> </div> </div> </div> </div> <div class="sect1"> <h2 id="_comparisons"><a class="anchor" href="#_comparisons"></a>Comparisons</h2> <div class="sectionbody"> <div class="sect2"> <h3 id="_difference_from_a_href_https_github_com_ocsigen_js_of_ocaml_js_of_ocaml_a"><a class="anchor" href="#_difference_from_a_href_https_github_com_ocsigen_js_of_ocaml_js_of_ocaml_a"></a>Difference from <a href="https://github.com/ocsigen/js_of_ocaml">js_of_ocaml</a></h3> <div class="paragraph"> <p>Js_of_ocaml is a popular compiler which compiles OCaml’s bytecode into JavaScript. It is the inspiration for this project, and has already been under development for several years and is ready for production. In comparison, BuckleScript, while moving fast, is still a very young project. BuckleScript’s motivation, like <code>js_of_ocaml</code>, is to unify the ubiquity of the JavaScript platform and the truly sophisticated type system of OCaml, however, there are some areas where we view things differently from <code>js_of_ocaml</code>. We describe below, some of these differences, and also refer readers to some of the original informal <a href="https://github.com/ocsigen/js_of_ocaml/issues/338">discussions</a>.</p> </div> <div class="ulist"> <ul> <li> <p>Js_of_ocaml takes low-level bytecode from OCaml compiler, BuckleScript takes the high-level rawlambda representation from OCaml compiler</p> </li> <li> <p>Js_of_ocaml focuses more on existing OCaml ecosystem(opam) while BuckleScript’s major goal is to target npm</p> </li> <li> <p>Js_of_ocaml and BuckleScript have slightly different runtime encoding in several places, for example, BuckleScript encodes OCaml Array as JS Array while js_of_ocaml requires its index 0 to be of value 0.</p> </li> </ul> </div> <div class="paragraph"> <p>Both projects are improving quickly, so this can change in the future!</p> </div> </div> </div> </div> <div class="sect1"> <h2 id="_library_api_documentation"><a class="anchor" href="#_library_api_documentation"></a>Appendix A: Library API documentation</h2> <div class="sectionbody"> <div class="paragraph"> <p>There is a small library that comes with <code>bs-platform</code>, its documentation is <a href="http://bucklescript.github.io/bucklescript/api/">here</a>.</p> </div> </div> </div> <div class="sect1"> <h2 id="_changes"><a class="anchor" href="#_changes"></a>Appendix B: CHANGES</h2> <div class="sectionbody"> <div class="sect2"> <h3 id="_1_3_2"><a class="anchor" href="#_1_3_2"></a>1.3.2</h3> <div class="ulist"> <ul> <li> <p>Features</p> <div class="ulist"> <ul> <li> <p>Significantly improve <code>bsb</code> experience (TODO: install instruction)</p> </li> </ul> </div> </li> </ul> </div> </div> <div class="sect2"> <h3 id="_1_2_1_dev"><a class="anchor" href="#_1_2_1_dev"></a>1.2.1 + dev</h3> <div class="ulist"> <ul> <li> <p>Features</p> <div class="ulist"> <ul> <li> <p>add <code>-bs-assume-no-mli</code>, <code>-bs-no-implicit-include</code> <a href="https://github.com/bucklescript/bucklescript/issues/861">#861</a> it’s for deterministic build</p> </li> <li> <p>add <code>-bs-D</code> <code>-bs-list-conditionals</code> flags <a href="https://github.com/bucklescript/bucklescript/issues/851">#851</a></p> </li> <li> <p>add <code>-bs-syntax-only</code></p> </li> <li> <p>add <code>-bs-binary-ast</code> <a href="https://github.com/bucklescript/bucklescript/issues/854">#854</a></p> </li> </ul> </div> </li> </ul> </div> </div> <div class="sect2"> <h3 id="_1_1_2"><a class="anchor" href="#_1_1_2"></a>1.1.2</h3> <div class="ulist"> <ul> <li> <p>Fixes</p> <div class="ulist"> <ul> <li> <p>Bug fix with opam issues <a href="https://github.com/bucklescript/bucklescript/issues/831">#831</a></p> </li> </ul> </div> </li> <li> <p>Features</p> <div class="ulist"> <ul> <li> <p>Provide bspp.exe for official compiler</p> </li> </ul> </div> </li> </ul> </div> </div> <div class="sect2"> <h3 id="_1_1_1"><a class="anchor" href="#_1_1_1"></a>1.1.1</h3> <div class="ulist"> <ul> <li> <p>Features</p> <div class="ulist"> <ul> <li> <p>Add bsdep.exe <a href="https://github.com/bucklescript/bucklescript/issues/822">#822</a></p> </li> <li> <p>Conditional compilation support <a href="https://github.com/bucklescript/bucklescript/issues/820">#820</a></p> </li> <li> <p>Relax syntactic restrictions for all extension point <a href="https://github.com/bucklescript/bucklescript/issues/793">#793</a> so that <code>bs.obj</code>, <code>obj</code>, <code>bs.raw</code>, <code>raw</code>, etc will both work. Note that all attributes will still be qualified</p> </li> <li> <p>Suport bs.splice in bs.new <a href="https://github.com/bucklescript/bucklescript/issues/793">#793</a></p> </li> <li> <p>Complete `bs.splice ` support and documentation <a href="https://github.com/bucklescript/bucklescript/issues/798">#798</a></p> </li> </ul> </div> </li> </ul> </div> </div> <div class="sect2"> <h3 id="_1_03"><a class="anchor" href="#_1_03"></a>1.03</h3> <div class="ulist"> <ul> <li> <p>Features</p> <div class="ulist"> <ul> <li> <p>Add an option <code>-bs-no-warn-unused-bs-attribute</code> <a href="https://github.com/bucklescript/bucklescript/issues/787">#787</a></p> </li> </ul> </div> </li> <li> <p>Incompatible changes (due to proper Windows support):</p> <div class="ulist"> <ul> <li> <p><code>bsc</code>, <code>bspack</code> and <code>bsppx</code> are renamed into <code>bsc.exe</code>, <code>bspack.exe</code> and <code>bsppx.exe</code></p> </li> <li> <p>no symlink from .bin any more.</p> </li> </ul> </div> <div class="listingblock"> <div class="title">Old symlinks</div> <div class="content"> <pre class="pygments highlight"><code> tmp>ls -al node_modules/.bin/ total 96 drwxr-xr-x 14 hzhang295 staff 476 Sep 20 17:26 . drwxr-xr-x 4 hzhang295 staff 136 Sep 20 17:27 .. lrwxr-xr-x 1 hzhang295 staff 22 Sep 20 17:26 bsc -> ../bs-platform/bin/bsc lrwxr-xr-x 1 hzhang295 staff 25 Sep 20 17:26 bspack -> ../bs-platform/bin/bspack lrwxr-xr-x 1 hzhang295 staff 24 Sep 20 17:26 bsppx -> ../bs-platform/bin/bsppx</code></pre> </div> </div> <div class="paragraph"> <p>Now these symlinks are removed, you have to refer to <code>bs-platform/bin/bsc.exe</code></p> </div> </li> </ul> </div> </div> <div class="sect2"> <h3 id="_1_02"><a class="anchor" href="#_1_02"></a>1.02</h3> <div class="ulist"> <ul> <li> <p>Bug fixes and enhancement</p> <div class="ulist"> <ul> <li> <p>Fix Bytes.blit when src==dst <a href="https://github.com/bucklescript/bucklescript/issues/743">#743</a></p> </li> </ul> </div> </li> <li> <p>Features</p> <div class="ulist"> <ul> <li> <p>Add an option <code>-bs-no-warn-ffi-type</code> <a href="https://github.com/bucklescript/bucklescript/issues/783">#783</a> By default, <code>bsc.exe</code> will warn when it detect some ocaml datatype is passed from/to external FFi</p> </li> <li> <p>Add an option <code>-bs-eval</code> <a href="https://github.com/bucklescript/bucklescript/issues/784">784</a></p> </li> </ul> </div> </li> </ul> </div> </div> <div class="sect2"> <h3 id="_1_01"><a class="anchor" href="#_1_01"></a>1.01</h3> <div class="ulist"> <ul> <li> <p>FFI</p> <div class="ulist"> <ul> <li> <p>support fields and mutable fields in JS object creation and private method <a href="https://github.com/bucklescript/bucklescript/issues/694">#694</a></p> </li> <li> <p>Introduce phantom arguments (<code>bs.ignore</code>) for ad-hoc polymorphism <a href="https://github.com/bucklescript/bucklescript/issues/686">#686</a></p> </li> </ul> </div> </li> <li> <p>Bug fixes and enhancement</p> <div class="ulist"> <ul> <li> <p>Enforce <code>#=</code> always return unit <a href="https://github.com/bucklescript/bucklescript/issues/718">#718</a> for better error messages</p> </li> </ul> </div> </li> </ul> </div> </div> <div class="sect2"> <h3 id="_1_0"><a class="anchor" href="#_1_0"></a>1.0</h3> <div class="paragraph"> <p>Initial release</p> </div> </div> </div> </div> </div> <div id="footer"> <div id="footer-text"> Version 2.1.0<br> </div> </div> </body> </html>