← 都来码← 文档索引Fortran原文English

Fortran

科学计算那套写法在这里也能用。

在手机上怎么跑

vml run examples/fortran/test/sysinfo.f90

编译要等一会儿(C 那种要一两分钟,脚本类语言几秒)。程序跑起来后屏幕底部就是手柄,方向键 + 四个动作键都在;点右上角返回可以回到命令行。

写法要点

示例

文件演示什么
app/sokoban.f90推箱子(双数组状态 + 移动规则 + 过关判定)
test/bench.f90跑分
test/sysinfo.f90设备信息

同目录还有:demo/demo_std.f90、math/main.f90、test/libs.f90、tty/demo_tty.f90、ui/demo_ui.f90

实测踩过的坑


下面的内容是从 VML 源码里直接带的(third_party/vml/VMLPrepares/FortranCompiler/): README 讲这个前端支持什么、怎么编;语言规范 讲语法本身。上游一改,这里重新生成就是最新的。

语言规范

Fortran 语言编译器规范说明

版本:v1.0 | 日期:2026-07-06 | 修订者:深圳市探索智能科技有限公司

元数据

属性值
标准Fortran 90/95 子集
首次发布1957 年 (Fortran 90: 1991 年)
完成度~98%
文件扩展名.f90, .f, .f95, .f03, .f08, .for, .ftn
代码行数~1,590 行 C#

概述

Fortran(FORmula TRANslation)是世界上第一个高级编程语言,专为科学计算和数值分析设计。本编译器实现 Fortran 90/95 的子集,支持自由列格式(free-form source form)。

核心特性:

支持的特性

1. 数据类型
类型关键字内部映射说明
integerinteger (i32)32 位有符号整数
realreal (float)32 位 IEEE 754 单精度浮点
double precisionreal (float)映射为 32 位浮点(VML 无原生 f64 硬件支持,需软浮点库)
complexcomplex复数类型(语法保留,运行时支持有限)
logicallogical (i32)逻辑值,内部以整数 0/1 存储
charactercharacter字符串类型(通过 MOVE R0, label 加载地址)

注意: double 关键字被识别但映射为 real(单精度)。doubleprecision(无空格)同样映射为 real。完整的双精度浮点支持需要启用 VML_FLOAT64_SOFT 宏以链接软浮点库。

2. 程序结构
program program_name
    ! 声明部分
    integer :: x, y
    real :: pi = 3.14159

    ! 执行部分
    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

支持的顶层结构:

语法要点:

3. 变量声明
! 基本声明(:: 分隔符可选)
integer :: i, j, k
real :: temperature
logical :: flag

! 带 dimension 的声明(语法解析通过,但数组操作尚未实现)
integer :: a(10), b(20)

! parameter 关键字(词法/语法识别,未生成代码)
parameter :: pi = 3.14159

实现细节:

4. 隐式与显式类型

编译器识别 implicit none 语句并跳过。默认情况下,建议在程序开头声明 implicit none 以禁用 Fortran 的隐式类型规则(以首字母 I-N 判断 integer,其余为 real)。

注意:当前编译器不强制显式声明——未声明的变量在使用时自动分配全局数据段变量。这与标准 Fortran 行为不同。

5. 运算符
优先级运算符含义说明
最低.or.逻辑或短路求值
.and.逻辑与短路求值
== / .eq.等于C 风格和 Fortran 风格均可
/= / .ne.不等于C 风格和 Fortran 风格均可
< / .lt.小于
> / .gt.大于
<= / .le.小于等于
>= / .ge.大于等于
+加法
-减法
*乘法
/除法
最高**幂运算当前简化为 *(无原生 POW 指令)

逻辑运算符(仅支持 .dot. 格式):

注意: .eqv. 和 .neqv. 被 Lexer 识别为关键字,但在目前的 CodeGenerator 中尚未实现专门的代码生成。同样,比较运算符同时支持 Fortran 风格(.eq., .ne., .lt., .gt., .le., .ge.)和 C 风格(==, /=, <, >, <=, >=)。

6. 赋值
x = 42           ! 正确:Fortran 用 = 而非 ==
flag = .true.    ! 逻辑赋值
y = x ** 2 + 1   ! 表达式赋值

赋值使用 = 运算符(不是 ==)。== 是相等比较运算符。

7. 控制流
IF 语句
if (x > 0) then
    print *, 'positive'
else if (x < 0) then
    print *, 'negative'
else
    print *, 'zero'
end if
DO WHILE 循环
i = 1
do while (i <= 10)
    print *, i
    i = i + 1
end do
计数 DO 循环
do i = 1, 10
    print *, i
end do

do j = 10, 1, -1     ! step = -1
    print *, j
end do
8. 子程序与函数调用
CALL 语句(调用子例程)
call mysub(arg1, arg2)
call print_values(x, y, z)
函数调用(表达式内)
result = add(a, b)            ! 函数调用作为表达式
x = square(y) + offset        ! 嵌套在表达式中
9. 内置函数(SYSCALL)

Fortran 编译器通过 VML 系统调用提供基本 I/O:

print 参数类型SYSCALL说明
字符串字面量SYSCALL 1打印字符串(R0 = 标签地址,MOVE 语义)
整数/变量SYSCALL 5打印整数(R0 = 值)
间隔空格SYSCALL 4打印单个字符(空格分隔)
换行SYSCALL 4打印 \n

共享的内置运行时函数(通过 Lib/shared/builtins.vml 提供):peek / poke / putchar / abs / min / max / random / sleep / alloc。

stop [code] 语句调用 exit SYSCALL(SYSCALL 3),可选退出码(默认 0)。

10. 逻辑字面量
字面量内部值说明
.true. / true1 (i32)Fortran 风格和简化形式均可
.false. / false0 (i32)Fortran 风格和简化形式均可

词法器同时接受 true/false(无前后点号)作为关键字,但标准 Fortran 应使用 .true. / .false.。

11. 注释
! 这是行注释(自由格式和固定格式均支持)
program main
    integer :: x   ! 行尾注释
end program

固定格式兼容:

* 星号在第 1 列视为注释行
C 或 c 在第 1 列视为注释行
12. 字符串字面量
print *, 'Hello, World!'
print *, 'It''s Fortran'    ! 两个单引号转义为一个
13. 续行

自由格式中,& 用于续行:

x = a + b + &
    c + d

词法器解析 & 以及续行行为由预处理阶段处理。

表达式优先级

从低到高:

1. .or.                         (逻辑或)
2. .and.                        (逻辑与)
3. == /= < > <= >=             (比较)
   .eq. .ne. .lt. .gt. .le. .ge.
4. + -                          (加减)
5. * / **                       (乘除幂)
6. - + .not.                    (一元负/正/逻辑非)
7. 字面量 / 变量 / 函数调用 / ( expr )

解析实现对应:

ParseLogicalOr    → .or.
  ParseLogicalAnd  → .and.
    ParseComparison → == /= < > <= >=
      ParseAdditive  → + -
        ParseMultiplicative → * / **
          ParseUnary     → - + .not.
            ParsePrimary  → 字面量 / 变量 / 函数调用 / ( )

预处理

编译器集成了 CompilerBase.Preprocessor,支持以下功能:

预定义宏
宏值说明
__VML__1VML 工具链标识
__VML_VERSION__"1.65.32"VML 版本号
__FORTRAN__1Fortran 编译器标识
__DATE__"Jun 01 2026"编译日期(英文格式)
__TIME__"HH:mm:ss"编译时间
模块导入
use math_lib          ! 导入模块 math_lib
条件编译
#ifdef __VML__
    print *, 'VML compiler'
#endif

标准 C 预处理器指令均支持:#define, #ifdef, #ifndef, #if, #else, #elif, #endif, #include, #undef。

限制与未实现特性

已在 Lexer/Token 中注册但未在 CodeGenerator 中实现的关键字
关键字状态说明
module / use / only语法跳过/模块导入use 仅用于库导入,module 块不支持
dimension / allocatable词法识别数组维度声明仅被解析跳过
implicit / none语法识别(NopNode)解析为 no-op,不强制执行显式声明
parameter词法识别常量声明未生成代码
intent / in / out / inout词法识别参数的 intent 属性被忽略
write / read词法识别仅 print *, 被实现(视为 write)
.eqv. / .neqv.词法识别代码生成未实现
complex词法识别复数运算未实现
核心不支持特性
特性说明
数组操作声明语法被解析跳过,不支持整体数组运算、数组切片、WHERE/FORALL
模块系统module/end module 块不支持
派生类型type/end type 自定义类型不支持
指针pointer 属性不支持
接口块interface/end interface 不支持
FORMAT 语句格式化 I/O 不支持,仅 print *,(列表定向输出)
READ/WRITE仅 print *, 可用;read * 不支持
COMMON 块公共块不支持,使用栈帧分配变量
ENTRY多入口点不支持
SAVE变量持久性属性不支持
DATADATA 初始化语句不支持
IMPLICIT 规则显式声明(implicit none)被建议但未强制执行
双精度double precision 映射为单精度 float
幂运算 «/»**简化为乘法,不是真正的幂运算
DO 负向步长循环条件 <= 对负向步长行为不正确
数组参数子程序/函数不能接受数组作为参数

编译器架构

源文件 (.f90/.f)
    │
    ▼
Lexer.cs ─────────── 词法分析(大小写不敏感)
    │   Keywords: 65 个关键字 + 运算符
    │   注释: ! 行注释, * C/c 在列1
    │   字符串: '...' 和 "..." ('' 转义)
    │   数字: 整数 / 实数 / 科学计数法 (E/D)  / 种类 (_4)
    ▼
Parser.cs ────────── 递归下降语法分析
    │   语句: program/subroutine/function/if/do while/do for/call/print
    │   表达式: 7 层优先级 (Pratt 风格)
    │   声明: type [::] name [, name]*
    ▼
ASTNode.cs ───────── 抽象语法树
    │   ProgramNode / SubroutineNode / FunctionNode
    │   IfNode / DoWhileNode / ForNode
    │   CallNode / ReturnNode / StopNode / PrintNode
    │   AssignNode / BinaryNode / UnaryNode / FuncCallNode
    │   LiteralNode / VarNode / VarDeclNode
    ▼
CodeGenerator.cs ─── VML 代码生成
    │   继承 CodeGeneratorBase
    │   栈帧管理: R12 基址 + nextStackOffset
    │   符号表: Dictionary<string, int> (名称 → 栈偏移)
    │   表达式: ExpressionManager 三操作数
    ▼
FortranCompiler.cs ─ 编译器入口
    │   Compile(string) → VmlProgram
    │   CompileFile(path) → VmlProgram (含预处理 + 库链接)
    │   预处理: Preprocessor + 预定义宏
    │   库链接: use 语句 + builtin.vml

调用约定

库结构

Lib/fortran/
    builtin.vml          ← 编译器自动链接
    ├── .linked  "../shared/builtins.vml"       (peek/poke/putchar/abs/min/max/random/sleep/alloc)
    ├── .linked  "../shared/device.vml"          (设备操作)
    ├── .linked  "../shared/sysinfo.vml"         (日期/时间/退出)
    ├── .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"           (基础浮点)
    └── .linked  "../shared/syscall.inc.vml"     (系统调用常量)

最小完整程序示例

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

🆕 字符串编码 (v1.65.19)

该语言编译器通过共享库 (Lib/shared/) 间接使用 VML 字符串体系。

伪指令宽度编码C 类型
.string8-bitUTF-8char*
.wstring16-bitUTF-16LEwchar_t*
.ustring32-bitUTF-32LEchar32_t*

MCU 模式 (默认): 字符串输出为 UTF-8 (.string) OS 模式: 可通过 VML_WSTRING 宏判断编码

共享库已提供宽字符串转换函数 (wchar.h/uchar.h),各语言编译器可按需使用。

编译器 README

Fortran 编译器

路径: VMLPrepares/FortranCompiler/ 完成度: ~98% | 🟢 生产可用 标准库: Lib/fortran/

功能

编译模式

MCU 模式(默认 --mode mcu)

MCU 模式针对单片机/裸机环境优化。

跳过(MCU 不支持):

保留:

OS 模式(--mode os)

OS 模式支持全部语言特性。

RAM 级别

使用

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

测试