← Dolaima← Docs indexFortran原文中文

Fortran

The scientific-computing style works here too.

How to run it on your phone

vml run examples/fortran/test/sysinfo.f90

Compiling takes a while (one to two minutes for C, a few seconds for scripting languages). Once the program is running, the gamepad is at the bottom of the screen - the D-pad and the four action buttons are all there. Tap the back arrow in the top-right corner to return to the Shell.

What to know before you write

Examples

FileWhat it shows
app/sokoban.f90Sokoban (two-array state plus movement rules plus level-complete check)
test/bench.f90Benchmark
test/sysinfo.f90Device information

Also in this folder: demo/demo_std.f90, math/main.f90, test/libs.f90, tty/demo_tty.f90, ui/demo_ui.f90

Pitfalls we hit on real devices


The rest of this page is taken straight from the VML source (third_party/vml/VMLPrepares/FortranCompiler/): the README covers what this front end supports and how to compile it, and the language reference covers the syntax itself. When upstream changes, regenerating this page brings it up to date.

Language reference

Fortran language compiler specification

Version: v1.0 | Date: 2026-07-06 | Revised by: Shenzhen Tanso Intelligent Technology Co., Ltd.

Metadata

AttributeValue
StandardFortran 90/95 subset
First released1957 (Fortran 90: 1991)
Completeness~98%
File extensions.f90, .f, .f95, .f03, .f08, .for, .ftn
Lines of code~1,590 lines of C#

Overview

Fortran (FORmula TRANslation) was the world's first high-level programming language, designed for scientific computing and numerical analysis. This compiler implements a subset of Fortran 90/95 and supports free-form source form.

Core characteristics:

Supported features

1. Data types
Type keywordInternal mappingDescription
integerinteger (i32)32-bit signed integer
realreal (float)32-bit IEEE 754 single-precision float
double precisionreal (float)Mapped to 32-bit float (VML has no native f64 hardware support; a soft-float library is required)
complexcomplexComplex type (syntax reserved, runtime support is limited)
logicallogical (i32)Logical value, stored internally as the integer 0/1
charactercharacterString type (address loaded through MOVE R0, label)

Note: The double keyword is recognized but mapped to real (single precision). doubleprecision (without a space) is also mapped to real. Full double-precision float support requires the VML_FLOAT64_SOFT macro to be enabled so the soft-float library is linked.

2. Program structure
program program_name
    ! declaration section
    integer :: x, y
    real :: pi = 3.14159

    ! executable section
    x = 10
    call mysub(x)

contains

    subroutine mysub(n)
        integer :: n
        print *, 'n = ', n
    end subroutine mysub

    function add(a, b) result(sum)
        integer :: a, b
        integer :: sum
        sum = a + b
    end function add

end program program_name

Supported top-level constructs:

Syntax notes:

3. Variable declarations
! basic declaration (the :: separator is optional)
integer :: i, j, k
real :: temperature
logical :: flag

! declaration with dimension (parses, but array operations are not implemented yet)
integer :: a(10), b(20)

! parameter keyword (recognized by the lexer/parser, no code generated)
parameter :: pi = 3.14159

Implementation details:

4. Implicit and explicit typing

The compiler recognizes an implicit none statement and skips it. By default, declaring implicit none at the top of a program is recommended in order to disable Fortran's implicit typing rules (which treat I-N initial letters as integer and the rest as real).

Note: The current compiler does not enforce explicit declarations — an undeclared variable is automatically allocated as a global data-segment variable when it is used. This differs from standard Fortran behavior.

5. Operators
PrecedenceOperatorMeaningDescription
Lowest.or.logical orshort-circuit evaluation
.and.logical andshort-circuit evaluation
== / .eq.equal toboth C style and Fortran style work
/= / .ne.not equal toboth C style and Fortran style work
< / .lt.less than
> / .gt.greater than
<= / .le.less than or equal
>= / .ge.greater than or equal
+addition
-subtraction
*multiplication
/division
Highest**exponentiationcurrently simplified to * (no native POW instruction)

Logical operators (only the .dot. form is supported):

Note: .eqv. and .neqv. are recognized by the Lexer as keywords, but no dedicated code generation has been implemented in the current CodeGenerator. Likewise, comparison operators support both the Fortran style (.eq., .ne., .lt., .gt., .le., .ge.) and the C style (==, /=, <, >, <=, >=).

6. Assignment
x = 42           ! correct: Fortran uses = rather than ==
flag = .true.    ! logical assignment
y = x ** 2 + 1   ! expression assignment

Assignment uses the = operator (not ==). == is the equality comparison operator.

7. Control flow
IF statements
if (x > 0) then
    print *, 'positive'
else if (x < 0) then
    print *, 'negative'
else
    print *, 'zero'
end if
DO WHILE loops
i = 1
do while (i <= 10)
    print *, i
    i = i + 1
end do
Counted DO loops
do i = 1, 10
    print *, i
end do

do j = 10, 1, -1     ! step = -1
    print *, j
end do
8. Subroutine and function calls
CALL statement (calling a subroutine)
call mysub(arg1, arg2)
call print_values(x, y, z)
Function calls (inside expressions)
result = add(a, b)            ! function call as an expression
x = square(y) + offset        ! nested inside an expression
9. Built-in functions (SYSCALL)

The Fortran compiler provides basic I/O through VML system calls:

print argument typeSYSCALLDescription
String literalSYSCALL 1Print a string (R0 = label address, MOVE semantics)
Integer/variableSYSCALL 5Print an integer (R0 = value)
SpacingSYSCALL 4Print a single character (space separator)
NewlineSYSCALL 4Print \n

Shared built-in runtime functions (provided by Lib/shared/builtins.vml): peek / poke / putchar / abs / min / max / random / sleep / alloc.

The stop [code] statement calls the exit SYSCALL (SYSCALL 3) with an optional exit code (0 by default).

10. Logical literals
LiteralInternal valueDescription
.true. / true1 (i32)both the Fortran style and the simplified form work
.false. / false0 (i32)both the Fortran style and the simplified form work

The lexer also accepts true/false (without the surrounding dots) as keywords, but standard Fortran should use .true. / .false..

11. Comments
! this is a line comment (supported in both free form and fixed form)
program main
    integer :: x   ! end-of-line comment
end program

Fixed-form compatibility:

* an asterisk in column 1 marks a comment line
C or c in column 1 marks a comment line
12. String literals
print *, 'Hello, World!'
print *, 'It''s Fortran'    ! two single quotes escape to one
13. Continuation lines

In free form, & continues a line:

x = a + b + &
    c + d

The lexer's handling of & and continuation-line behavior is dealt with by the preprocessing stage.

Expression precedence

From lowest to highest:

1. .or.                         (logical or)
2. .and.                        (logical and)
3. == /= < > <= >=             (comparison)
   .eq. .ne. .lt. .gt. .le. .ge.
4. + -                          (add/subtract)
5. * / **                       (multiply/divide/power)
6. - + .not.                    (unary minus/plus/logical not)
7. literals / variables / function calls / ( expr )

The parsing implementation matches:

ParseLogicalOr    → .or.
  ParseLogicalAnd  → .and.
    ParseComparison → == /= < > <= >=
      ParseAdditive  → + -
        ParseMultiplicative → * / **
          ParseUnary     → - + .not.
            ParsePrimary  → literals / variables / function calls / ( )

Preprocessing

The compiler integrates CompilerBase.Preprocessor, which supports the following:

Predefined macros
MacroValueDescription
__VML__1VML toolchain identifier
__VML_VERSION__"1.65.32"VML version number
__FORTRAN__1Fortran compiler identifier
__DATE__"Jun 01 2026"Compilation date (English format)
__TIME__"HH:mm:ss"Compilation time
Module import
use math_lib          ! import the module math_lib
Conditional compilation
#ifdef __VML__
    print *, 'VML compiler'
#endif

All standard C preprocessor directives are supported: #define, #ifdef, #ifndef, #if, #else, #elif, #endif, #include, #undef.

Limitations and unimplemented features

Keywords registered in the Lexer/Token but not implemented in the CodeGenerator
KeywordStatusDescription
module / use / onlysyntax skipped / module importuse is only used for library imports; module blocks are not supported
dimension / allocatablerecognized by the lexerArray dimension declarations are merely parsed and skipped
implicit / nonerecognized by the parser (NopNode)Parsed as a no-op; explicit declarations are not enforced
parameterrecognized by the lexerConstant declarations generate no code
intent / in / out / inoutrecognized by the lexerA parameter's intent attribute is ignored
write / readrecognized by the lexerOnly print *, is implemented (treated as write)
.eqv. / .neqv.recognized by the lexerCode generation is not implemented
complexrecognized by the lexerComplex arithmetic is not implemented
Core unsupported features
FeatureDescription
Array operationsDeclaration syntax is parsed and skipped; whole-array operations, array sections and WHERE/FORALL are not supported
Module systemmodule/end module blocks are not supported
Derived typestype/end type user-defined types are not supported
PointersThe pointer attribute is not supported
Interface blocksinterface/end interface are not supported
FORMAT statementsFormatted I/O is not supported; only print *, (list-directed output) is
READ/WRITEOnly print *, is available; read * is not supported
COMMON blocksCommon blocks are not supported; variables are allocated on the stack frame
ENTRYMultiple entry points are not supported
SAVEThe variable persistence attribute is not supported
DATADATA initialization statements are not supported
IMPLICIT rulesExplicit declarations (implicit none) are recommended but not enforced
Double precisiondouble precision is mapped to single-precision float
Exponentiation «/»**Simplified to multiplication, not real exponentiation
Negative DO stepThe loop condition <= behaves incorrectly for a negative step
Array parametersSubroutines/functions cannot accept arrays as parameters

Compiler architecture

source file (.f90/.f)
    │
    ▼
Lexer.cs ─────────── lexing (case insensitive)
    │   Keywords: 65 keywords + operators
    │   Comments: ! line comment, * C/c in column 1
    │   Strings: '...' and "..." ('' escape)
    │   Numbers: integer / real / scientific notation (E/D)  / kind (_4)
    ▼
Parser.cs ────────── recursive-descent parsing
    │   Statements: program/subroutine/function/if/do while/do for/call/print
    │   Expressions: 7 precedence levels (Pratt style)
    │   Declarations: type [::] name [, name]*
    ▼
ASTNode.cs ───────── abstract syntax tree
    │   ProgramNode / SubroutineNode / FunctionNode
    │   IfNode / DoWhileNode / ForNode
    │   CallNode / ReturnNode / StopNode / PrintNode
    │   AssignNode / BinaryNode / UnaryNode / FuncCallNode
    │   LiteralNode / VarNode / VarDeclNode
    ▼
CodeGenerator.cs ─── VML code generation
    │   Extends CodeGeneratorBase
    │   Stack frame management: R12 base + nextStackOffset
    │   Symbol table: Dictionary<string, int> (name → stack offset)
    │   Expressions: ExpressionManager three-operand form
    ▼
FortranCompiler.cs ─ compiler entry point
    │   Compile(string) → VmlProgram
    │   CompileFile(path) → VmlProgram (with preprocessing + library linking)
    │   Preprocessing: Preprocessor + predefined macros
    │   Library linking: use statements + builtin.vml

Calling convention

Library structure

Lib/fortran/
    builtin.vml          ← linked automatically by the compiler
    ├── .linked  "../shared/builtins.vml"       (peek/poke/putchar/abs/min/max/random/sleep/alloc)
    ├── .linked  "../shared/device.vml"          (device operations)
    ├── .linked  "../shared/sysinfo.vml"         (date/time/exit)
    ├── .linked  "../shared/softfloat.vml"       (VML_FLOAT32_SOFT)
    ├── .linked  "../shared/softdouble.vml"      (VML_FLOAT64_SOFT)
    ├── .linked  "../shared/softint64.vml"       (VML_INT64_SOFT)
    ├── .linked  "../shared/float.vml"           (basic floating point)
    └── .linked  "../shared/syscall.inc.vml"     (system call constants)

Minimal complete program example

program hello
    implicit none
    integer :: i

    do i = 1, 5
        print *, 'Hello Fortran!', i
    end do

contains

    function square(x) result(y)
        integer :: x
        integer :: y
        y = x * x
    end function square

end program hello

🆕 String encoding (v1.65.19)

This language compiler uses the VML string system indirectly through the shared library (Lib/shared/).

DirectiveWidthEncodingC type
.string8-bitUTF-8char*
.wstring16-bitUTF-16LEwchar_t*
.ustring32-bitUTF-32LEchar32_t*

MCU mode (default): strings are output as UTF-8 (.string) OS mode: the encoding can be determined through the VML_WSTRING macro

The shared library already provides wide-string conversion functions (wchar.h/uchar.h), which each language compiler can use as needed.

Compiler README

Fortran compiler

Path: VMLPrepares/FortranCompiler/ Completeness: ~98% | 🟢 production ready Standard library: Lib/fortran/

Features

Compilation modes

MCU mode (default --mode mcu)

MCU mode is tuned for microcontrollers and bare-metal environments.

Skipped (not supported by the MCU):

Kept:

OS mode (--mode os)

OS mode supports every language feature.

RAM levels

Usage

dotnet run --project VMLTool -- input.f90 -o output.vml

Tests