Getting started

The following post assumes the reader is already familiar with OCaml. If you are not familiar with OCaml, we sugget you to get started here: OCaml tutorial. Learning OCaml would help you become a better programmer :-)

Installation

Requirements

make world

If you have ocamlfind installed, it will install a META file will be installed to the corresponding place, otherwise no META file installed

What it installed?

It installed three exectuables: fan.byte, fan.native, fane.byte into the path: ocamlc -where/bin. All the library files are installed into :sub:`ocamlc -where/fan.

FAst.cmi and FAstN.cmi two signature files are installed to the path of standard library.

Please read META for more details.

fan.byte, fan.native have exactly the same functionality, they are stand-alone without linking any external libraries (no compiler-libs linked, no dynlink).

fane.byte links the whole byte-code compiler and toplevel, it provides eval functionality, which we will talk about later.

What language does Fan speak?

Fan speaks OCaml natively, with a few addons.

There are some minor differences between Fan’s concrete syntax and OCaml though, the major differences is that Fan is more strict than OCaml.

Note

difference from OCaml syntax

  1. Parens are necessary for tuples

    (* incorrect *)
    a,b
    (* correct *)
    (a,b)
    
    (*incorrect *)
    let a,b = f in body
    (* correct *)
    let (a,b) = f in body
    
  2. Parens or begin end necessary for semis

    (* incorrect *)
    print_endline "a";
    print_endline "b"
    
    (* correct *)
    (print_endline "a";
    print_endline "b")
    (* correct *)
    begin
     print_endline "a";
     print_endline "b"
    end
    
  3. First vertical bar is necessary for algebraic data type, pattern match.

    (* incorrect *)
    type u = A | B
    let f = function
         A -> "a"
       | B -> "b"
    let f =
      match c with
        A -> "a"
      | B -> "b"
    
    (* correct *)
    type u = | A | B
    
    let f = function | A -> "a" | B -> "b"
    let f = match c with | A -> "a" | B -> "b"
    
  4. $ is a reserved operator, please don’t take it as a function.

Note

added syntax

It mainly introduce two syntaxes, we call them delimited domain specific languages(DDSL).

  1. compile time quotation

    #{:quot| |}
    

    Such quotation is purely compile time control language, it’s a general view of such directives:

    #load "xx.cmo";;
    #use "xx.ml" ;;
    

    It can be used to interact with the Fan compiler, the user can register different compile time quotation language to make the whole file self-explainable, this helps simplify the build system a lot.

    For example, there is a built-in control language

    #{:control|
    default "exp"; (* set the default quotation *)
    require "ulex"; (* require the feature *)
    import "Tutorial"; (* import the language namespace *)
    filter "serialize"; (* apply the filter serialize to the whole file *)
    |}
    

    Another language eval, could eval all legal ocaml code at compile-time.

    #eval{
    let v = 3 let b = 3
    }
    

    This would help test the syntax extension on-the-fly.

    Attention: all the compile time DDSL should be put in the beginning, this is intentional, to work better with IDE.

  2. Rewrite DDSL.

    The syntax is the same with compile-time DDSL except without hash sign, one sample is as follows:

    %exp{ 3}
    

    It can appear in most places (detail later)