You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Type: Tree-walking Fortran 90/95/2003 interpreter | Upstream:ofort by Beliavsky (MIT) | Location:CodeBench/ofort/*.c (app target) · fortran/offlinai_fortran.c (package amalgamation) · public C API in codebench_fortran.h | App Store safe
A self-contained Fortran interpreter that lexes, parses, and executes Fortran code at runtime. Supports free-form source, modules, allocatable arrays up to 7 dimensions, 45+ intrinsic functions, and formatted I/O. Case-insensitive as per the Fortran standard. No JIT, no compilation, no external tools needed.
Source & license. The interpreter core is ofort by Beliavsky, MIT-licensed (see CodeBench/ofort/LICENSE). ofort was extracted from CodeBench's original Fortran interpreter and matured upstream, then adopted back into the app — so the C source under CodeBench/ofort/ (notably ofort.c) is the single definition of the ofort_* symbols that codebench_fortran.h declares. FortranRuntime.swift is the thin Swift bridge that runs it on a large-stack worker thread. (This is the interpreter for user-run.f90/.f95 files; it is distinct from the Flang runtime stubs in fortran-runtime.md that let scipy's compiled Fortran load.)
Edits .f90 / .f95 / .f03 / .f / .for files in the shared Monaco-powered editor with Fortran syntax highlighting and auto-save (debounced ~600 ms; also flushed on run, tab switch, view disappear, and app backgrounding).
Quick Start
PROGRAM hello
IMPLICIT NONEINTEGER:: i, n
REAL:: sum, average
REAL, DIMENSION(10) ::data
n =10
sum =0.0DO i =1, n
data(i) =REAL(i) *1.5
sum = sum +data(i)
END DO
average = sum /REAL(n)
WRITE(*, '(A, F8.2)') 'Average: ', average
WRITE(*, '(A, I0)') 'Count: ', n
END PROGRAM hello
Program Structure
Basic Program Units
PROGRAM main_program
IMPLICIT NONE
! declarations
! executable statements
END PROGRAM main_program
SUBROUTINEmy_sub(arg1, arg2)
IMPLICIT NONEINTEGER, INTENT(IN) :: arg1
REAL, INTENT(OUT) :: arg2
arg2 =REAL(arg1) *2.0ENDSUBROUTINE my_subFUNCTIONmy_func(x) RESULT(y)
IMPLICIT NONEREAL, INTENT(IN) :: x
REAL:: y
y = x * x +1.0ENDFUNCTION my_func
Modules
MODULE constants
IMPLICIT NONEREAL, PARAMETER:: PI =3.14159265358979REAL, PARAMETER:: E =2.71828182845905REAL, PARAMETER:: G =9.80665
END MODULE constants
MODULE geometry
USE constants
IMPLICIT NONECONTAINSFUNCTIONcircle_area(r) RESULT(area)
REAL, INTENT(IN) :: r
REAL:: area
area = PI * r * r
ENDFUNCTIONcircle_areaFUNCTIONsphere_volume(r) RESULT(vol)
REAL, INTENT(IN) :: r
REAL:: vol
vol = (4.0/3.0) * PI * r * r * r
ENDFUNCTIONsphere_volume
END MODULE geometry
PROGRAM main
USE geometry
IMPLICIT NONEWRITE(*, *) 'Circle area (r=5): ', circle_area(5.0)
WRITE(*, *) 'Sphere volume (r=3): ', sphere_volume(3.0)
END PROGRAM main
Data Types
Type
Declaration
Description
INTEGER
INTEGER :: n = 42
Integer (64-bit)
REAL
REAL :: x = 3.14
Single-precision float (stored as double internally)
REAL, ALLOCATABLE ::data(:)
REAL, ALLOCATABLE :: grid(:,:)
INTEGER:: n
n =100
ALLOCATE(data(n))
ALLOCATE(grid(n, n))
DO i =1, n
data(i) =REAL(i)
END DO
! Check allocation status
IF (ALLOCATED(data)) THENWRITE(*, *) 'data is allocated, size =', SIZE(data)
END IF
DEALLOCATE(data)
DEALLOCATE(grid)
Array Operations (Whole-Array)
REAL:: a(5) = [1.0, 2.0, 3.0, 4.0, 5.0]
REAL:: b(5) = [5.0, 4.0, 3.0, 2.0, 1.0]
REAL:: c(5)
! Element-wise operations
c = a + b ! [6, 6, 6, 6, 6]c = a * b ! [5, 8, 9, 8, 5]c = a ** 2 ! [1, 4, 9, 16, 25]
! Array sections
c(1:3) = a(3:5) ! Slice assignmentc(::2) = 0.0 ! Stride: every other element
! WHERE construct
WHERE (a > 3.0)
c = a
ELSEWHERE
c =0.0END WHERE
! Counted DODO i =1, 10WRITE(*, *) i
END DO
! DO with step
DO i =10, 1, -1WRITE(*, *) i
END DO
! DO with step of 2DO i =0, 20, 2WRITE(*, *) i
END DO
! DOWHILE
n =1DOWHILE (n <=100)
n = n *2END DO
! Infinite DO with EXIT
DOREAD(*, *) x
IF (x < 0) EXIT
WRITE(*, *) SQRT(x)
END DO
! Named DO with CYCLE
outer: DO i =1, 10
inner: DO j =1, 10IF (MOD(j, 3) == 0) CYCLE inner
IF (i * j > 50) EXIT outer
WRITE(*, *) i, j
END DO inner
END DO outer
SELECT CASE
SELECT CASE (grade)
CASE ('A')
WRITE(*, *) 'Excellent'
CASE ('B', 'C')
WRITE(*, *) 'Good'
CASE ('D')
WRITE(*, *) 'Below average'
CASE ('F')
WRITE(*, *) 'Fail'
CASE DEFAULT
WRITE(*, *) 'Invalid grade'
END SELECT
! Integer ranges
SELECT CASE (score)
CASE (90:100)
grade ='A'
CASE (80:89)
grade ='B'
CASE (70:79)
grade ='C'
CASE (:69)
grade ='F'
END SELECT
Subroutines & Functions
Subroutines
SUBROUTINEswap(a, b)
IMPLICIT NONEINTEGER, INTENT(INOUT) :: a, b
INTEGER:: temp
temp = a
a = b
b = temp
ENDSUBROUTINE swap
! Call with CALL keyword
CALL swap(x, y)
Functions
! With RESULT clause
FUNCTIONfactorial(n) RESULT(fact)
IMPLICIT NONEINTEGER, INTENT(IN) :: n
INTEGER:: fact
INTEGER:: i
fact =1DO i =2, n
fact = fact * i
END DOENDFUNCTION factorial
! Recursive functions
RECURSIVEFUNCTIONfib(n) RESULT(f)
IMPLICIT NONEINTEGER, INTENT(IN) :: n
INTEGER:: f
IF (n <=1) THEN
f = n
ELSE
f = fib(n -1) + fib(n -2)
END IFENDFUNCTION fib
Internal Subprograms (CONTAINS)
PROGRAM main
IMPLICIT NONEWRITE(*, *) double(21)
CONTAINSFUNCTIONdouble(x) RESULT(y)
INTEGER, INTENT(IN) :: x
INTEGER:: y
y = x *2ENDFUNCTIONdoubleEND PROGRAM main
I/O -- WRITE, PRINT, and Format Descriptors
Free-Format Output
WRITE(*, *) 'Hello, World!'WRITE(*, *) 'x =', x, 'y =', y
PRINT*, 'Sum =', a + b
Fortran is fully case-insensitive. All of these are equivalent:
PROGRAM example ! uppercase
program example ! lowercase
Program Example ! mixed case
pRoGrAm eXaMpLe ! any combination
Keywords, variable names, function names, and intrinsic functions are all case-insensitive.
Derived Types (Structs)
TYPE :: Person
CHARACTER(LEN=50) :: name
INTEGER:: age
REAL:: height
END TYPE Person
TYPE(Person) :: p1, p2
p1%name ='Alice'
p1%age =30
p1%height =1.65
! Constructor syntax
p2 = Person('Bob', 25, 1.80)
WRITE(*, '(A, A, A, I0)') 'Name: ', TRIM(p1%name), ', Age: ', p1%age
Nested Types
TYPE :: Vector2D
REAL:: x, y
END TYPE Vector2D
TYPE :: Particle
TYPE(Vector2D) :: position
TYPE(Vector2D) :: velocity
REAL:: mass
END TYPE Particle
TYPE(Particle) :: p
p%position%x =1.0
p%position%y =2.0
p%velocity = Vector2D(3.0, 4.0)
p%mass =1.5
Example: Matrix Operations
PROGRAM matrix_ops
IMPLICIT NONEINTEGER, PARAMETER:: N =3REAL:: A(N, N), B(N, N), C(N, N)
INTEGER:: i, j
! Initialize
DO i =1, N
DO j =1, N
A(i, j) =REAL(i + j)
B(i, j) =REAL(i * j)
END DOEND DO
! Matrix multiply using intrinsic
C =MATMUL(A, B)
! Print result
DO i =1, N
WRITE(*, '(3F8.2)') (C(i, j), j =1, N)
END DO
! Other operations
WRITE(*, '(A, F8.2)') 'Trace: ', SUM([(A(i,i), i=1,N)])
WRITE(*, '(A, F8.2)') 'Frobenius norm: ', SQRT(SUM(A**2))
WRITE(*, '(A, F8.2)') 'Max element: ', MAXVAL(A)
WRITE(*, '(A, 2I3)') 'Max location: ', MAXLOC(A)
END PROGRAM matrix_ops