# LFortran User Guide

## About LFortran

LFortran's goal is an implementation of the latest Fortran standard (currently F2018) with
some added extensions.  It works on Linux, macOS, most BSDs and on Windows.

The LFortran compiler consists of the following components:

* The LFortran compiler itself.
* A runtime library supporting language elements and intrinsic functions.
* Several module definitions which define the external environment and
  supply particular details about the computer running the program.
* The capability to read additional module definitions which define
  the interfaces to external libraries such as OpenMPI.
* Generation of executable code with the LLVM compiler infrastructure.
* Generation of C, C++, WebAssembly or Julia code.
* Interactive usage via LLVM JIT
* Source file formatting (`lfortran fmt`).

## Standards

The LFortran compiler is currently in the alpha stage and is actively under development. It is designed to support the following Fortran standards and modes:

Supported Standards:

* ISO Fortran 2023 (`--std=f23`): Partial support for the latest Fortran 2023 features. Use this option to enable conformance to Fortran 2023 where supported.
* Legacy Mode (`--std=legacy`): Allows compilation of older Fortran codebases that use non-standard or deprecated syntax.
* LFortran Mode (`--std=lf`): Default mode focusing on modern Fortran features, including experimental extensions beyond the current standards.

## Extensions

The extensions are currently in development and are planned to include:

* Global Scope (statements outside of a program block).
* Interactive Fortran (in alpha).
* Jupyter integration.
* Support for GPUs and other accelerators.
* Type inference (`:=` operator and `--infer` mode).

### Type Inference with `:=`

**Experimental, subject to change.**

The `:=` operator declares a new variable whose type is inferred from the
right-hand side. It is closely inspired by Go's short variable declaration
(`:=`), where it is the dominant way to declare local variables. The
rationale is the same: when the right-hand side already communicates the
type, repeating it on the left is redundant noise. `:=` makes declarations
visible at a glance without requiring the programmer to spell out types
that the compiler can deduce.

`:=` is not standard Fortran syntax. It is an LFortran-specific extension,
and the compiler emits a warning on each use to make this clear. The
`--infer` flag suppresses the warning.

```fortran
x := 42              ! integer
y := 3.14d0          ! real(8)
z := (1.0d0, 2.0d0)  ! complex(8)
vals := [1, 2, 3]    ! integer, dimension(3)
p := point_t(0.0, 0.0)  ! type(point_t)
```

#### Rules

`:=` always declares a new variable. It never assigns to an existing one.

```fortran
x := 5
x = 10     ! ok: plain assignment to existing variable
x := 10    ! error: x is already declared in this scope
```

```fortran
integer :: x
x := 5     ! error: x is already declared
```

Inner blocks may shadow outer variables:

```fortran
x := 5
block
    x := "hello"   ! ok: new x in inner scope
end block
! outer x is still integer 5
```

Supported right-hand sides: integer, real, complex, logical, character
scalars; fixed-size arrays when dimensions are compile-time constants;
derived types via structure constructors or typed expressions.
The inferred kind matches the expression (`3.14d0` produces `real(8)`).

#### Guidance

Use `:=` when the type is evident from the right-hand side:

```fortran
cfg := load_config("input.nml")
origin := point_t(0.0, 0.0)
coeffs := [1.0d0, 0.5d0, 0.25d0]
```

Use explicit declarations when the type matters for clarity or safety:

```fortran
real(dp) :: result
result = compute(data)    ! reader sees the type; catches signature changes

integer :: i, n           ! simple counters are clearer with explicit types
```

#### `--infer` mode

`--infer` enables a second, more permissive form of inference: the first
plain `=` to an undeclared name declares it, like a scripting language.
This is intended for interactive and notebook use.

| Feature | Syntax | Declares | Intended for |
|---------|--------|----------|--------------|
| `:=` | `x := expr` | Always | Production code |
| `--infer` | `x = expr` | On first use | Interactive / notebooks |

`:=` works independently of `--infer`. When both are active, either form
declares, but `:=` makes the intent explicit.

## Interactive Compiler

LFortran supports an interactive mode; just run the `lfortran` command
to start it.

## Invoking LFortran

The LFortran compiler supports numerous command-line flags to select
compilation options, output options, link options and so on.

### Compiler information

* `--print-targets`, Print the registered CPU targets
* `--version`, Show the current version

### Source code format

* `--fixed-form`, Parse the file assuming Fortran 66 format (6 spaces)
* `--fixed-form-infer`, Use heuristics to infer if a file is in fixed form

### Source code processing

* `--cpp`, Enable C preprocessing
* `-E`, Preprocess only; do not compile, assemble or link

### Other inputs

* `-D <macro>=<value>` Define a macro (or 1 if <value> omitted)
* `-I <value>`, Include path for `include` statements
* `-L <value>`, Library path for shared libraries
* `-l <value>`, Link library naming a linkable shared library

### Compiler feature selections

* `--fast`, Best performance (disable strict standard compliance)
* `--implicit-argument-casting`, Allow implicit argument casting
* `--implicit-interface`, Allow implicit interface
* `--implicit-typing`, Allow implicit typing
* `--openmp`, Enable OpenMP
* `--print-leading-space`, Print leading white space if format is unspecified
* `--realloc-lhs-arrays`, Reallocate left hand side automatically for arrays
* `--disable-realloc-lhs-arrays`, Disables reallocating left hand side automatically for arrays
* `--target <value>`, Generate code for the given target
* `--backend` flag is used to specify the target backend for code generation in LFortran. The supported backends are:
  
  - `llvm`: The most advanced and default backend, used for generating LLVM IR or machine code through LLVM.
  - `wasm`: For generating `Webassembly` via our custom `wasm` backend.
  - `c`: For generating C code.
  - `cpp`: For generating C++ code (requires the Kokkos library).
  - `x86`: For generating x86 machine code directly (without LLVM).
  - `fortran`: For generating Fortran code.
  - `julia`: For generating Julia code.

### Compiler text outputs

* `--error-format <value>`, Control how errors are produced (human, short)
* `--no-error-banner`, Turn off error banner
* `--no-warnings`, Turn off all warnings
* `-S`, Emit assembly, do not assemble or link
* `--time-report`, Show compilation time report
* `-v`, Be more verbose

### Compiler binary outputs

* `-c`, Compile and assemble, do not link
* `--separate-compilation`, Generate object code into .o files
* `-J <value>`, Where to save mod files
* `-o <value>`, Specify the file to place the compiler's output into
* `--static`, Create a static executable

### Compiler debugging

A number of command-line options select various text outputs useful
for debugging the compiler.  See `lfortran --help` for a list.

## Examples

The following commands and code demonstrate basic operation of the compiler.

```
lfortran helloworld.f90
Hello World!

lfortran -o hw helloworld.f90
./hw
Hello World!

cat helloworld.f90
program hello_world
    implicit none
    write (*, *) 'Hello World!'
end program hello_world

```

Here is a simple example with a module:

```
lfortran -c varray.f90
lfortran usev.f90
 sum is    7.20000000e+01

cat varray.f90
module varray
    integer :: nsize
end module varray

cat usev.f90
program usev
    use varray
    real, allocatable, dimension(:) :: A
    integer :: i
    nsize = 8
    allocate(A(nsize))
    do i = 1, nsize
        A(i) = 2.0*i
    end do
    print *, " sum is ", (A(1)+A(nsize))*nsize/2.0
    deallocate(A)
end program usev

```


The compile command for the module requires `-c` to avoid automatic running
of the code.


## Formatting Fortran source files

The `lfortran` compiler will automatically format source files with the `fmt`
option.  You can select auto-indent for modules, and in-place update of
the Fortran source file with the `-i` option (use with caution!).

```
lfortran fmt varray.f90
module varray
integer :: nsize
real, allocatable, dimension(:) :: A
end module varray
```

Or add spaces and indentation as follows:

```
lfortran fmt --spaces 4 --indent-unit varray.f90
module varray
    integer :: nsize
    real, allocatable, dimension(:) :: A
end module varray
```

## Selecting the C Compiler

By default LFortran uses the `clang` compiler.  On some systems
the compiler has a version number or spelling difference.  The compiler
can be changed with the `LFORTRAN_CC` symbol:

```
unset LFORTRAN_CC
lfortran hw.f90
Hello World!

export LFORTRAN_CC=gcc
lfortran hw.f90
Hello World!

export LFORTRAN_CC=clang-14
lfortran hw.f90
sh: clang-14: not found
...(further error messages)...
```

## Differences from other compilers

GNU, Intel and LLVM Fortran use "standard" Fortran carriage control where the
first character of each output line controls a conceptual "line printer".  A
space " " means
single-space, a zero "0" means double-space and one "1" means form-feed
before printing.  This is obsolete and LFortran omits this unless
`--print-leading-space` is selected at compile-time.

There is currently no way to specify detailed compiler options to
Clang such as `-O3` or `-flto` (optimization and link-time optimization).

GNU extension declarations `real*8 xvalue` are accepted but deprecated. This
was never standard-conforming Fortran; it is an old IBM extension that predates Fortran-77.


