# Fortran calculator/interpreter

**URL:** <https://fortran-lang.discourse.group/t/fortran-calculator-interpreter/9644>\
**Category:** Uncategorized\
**Created:** [April 28, 2025, 9:46pm UTC](https://fortran-lang.discourse.group/t/fortran-calculator-interpreter/9644 "2025-04-28T21:46:09Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![Beliavsky](https://avatars.discourse-cdn.com/v4/letter/b/ba8739/32.png) [@Beliavsky](https://fortran-lang.discourse.group/u/Beliavsky)\
**Post date:** [April 28, 2025, 9:46pm UTC](https://fortran-lang.discourse.group/t/fortran-calculator-interpreter/9644/1 "2025-04-28T21:46:09Z")

</div>

> **[GitHub - Beliavsky/Calc: Interpreter in Fortran that can handle scalars and...](https://github.com/Beliavsky/Calc)**
>
> Interpreter in Fortran that can handle scalars and 1D arrays, with access to intrinsics and statistical functions and plotting with gnuplot

I made a calculator/Interpreter in Fortran that works with scalars and 1D arrays of reals. It has a bit of the functionality of NumPy or R. You can define variables and evaluate expressions involving them. There are no loops or conditionals. There are whole array operations, array sections, vector subscripts, uniform and normal RNG, descriptive statistics, sorting, relational operators, and functions for correlation and covariance. ChatGPT o3 is helpful in writing a parser. One can use it to look up values for special functions, for example

```auto
x = grid(5, 0.1, 0.1)
[.100000 .200000 .300000 .400000 .500000]

bessel_j0(x)
[.997502 .990025 .977626 .960398 .938470]

```

To simulate the probability that a standard normal deviate exceeds 2 one writes

```auto
x = rnorm(10^6)
      size mean sd min max first last
   1000000 -0.0002 1.0001 -4.6193 4.9802 -0.8247 -0.0022

mean(x > 2)
0.022749

```

The last line works since logical variables are treated as 1s and 0s (not standard Fortran).

I don’t know how easily the calculator can be extended to handle 2D arrays. ([M\_matrix](https://github.com/urbanjost/M_matrix) of @urbanjost does.) By toggling a parameter `mutable` you can allow or disallow variables to be changed once set. It’s mostly a fun project, but it is nice to quickly define functions for an interpreted language in a few lines of Fortran. It compiles with either gfortran or ifx.

---

<div class="post-metadata">

**Author:** ![certik](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/certik/32/4_2.png) [@certik](https://fortran-lang.discourse.group/u/certik)\
**Post date:** [April 28, 2025, 9:53pm UTC](https://fortran-lang.discourse.group/t/fortran-calculator-interpreter/9644/2 "2025-04-28T21:53:19Z")

</div>

So kind of like the original Matlab, that was also written in Fortran.

---

<div class="post-metadata">

**Author:** ![gardhor](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/gardhor/32/88_2.png) [@gardhor](https://fortran-lang.discourse.group/u/gardhor)\
**Post date:** [April 29, 2025, 1:54pm UTC](https://fortran-lang.discourse.group/t/fortran-calculator-interpreter/9644/3 "2025-04-29T13:54:10Z")

</div>

Great work!  
To be more Fortran like, is it possible to have also the exponentiation as \*\*?

---

<div class="post-metadata">

**Author:** ![Beliavsky](https://avatars.discourse-cdn.com/v4/letter/b/ba8739/32.png) [@Beliavsky](https://fortran-lang.discourse.group/u/Beliavsky)\
**Post date:** [April 29, 2025, 3:50pm UTC](https://fortran-lang.discourse.group/t/fortran-calculator-interpreter/9644/4 "2025-04-29T15:50:09Z")

</div>

I want to keep ^ for exponentiation and am not sure that \*\* should also do the same thing. Maybe Fortran used \*\* historically because ^ was not universally available. In the main program there is now code

```fortran
     line = replace(line, "**", "^")
     call eval_print(trim(line))

```

so that \*\* is replaced by ^ before the code is processed. Now you get

```auto
> 2**5

> 2^5
32
> sqrt(3 **2 + 4** 2)

> sqrt(3^2 + 4^2)
5

```

---

<div class="post-metadata">

**Author:** ![aledinola](https://avatars.discourse-cdn.com/v4/letter/a/3ec8ea/32.png) [@aledinola](https://fortran-lang.discourse.group/u/aledinola)\
**Post date:** [April 29, 2025, 7:24pm UTC](https://fortran-lang.discourse.group/t/fortran-calculator-interpreter/9644/5 "2025-04-29T19:24:58Z")

</div>

Very interesting! Incidentally, I saw that you coded the function `cumsum` in one of the project modules

```fortran
function cumsum(x) result(y)
! return the cumulative sum of x
real(kind=dp), intent(in) :: x(:)
real(kind=dp) :: y(size(x))
integer :: i, n
n = size(x)
if (n < 1) return
y(1) = x(1)
do i=2,n
   y(i) = y(i-1) + x(i)
end do
end function cumsum

```

I copied it and tested it, but for large arrays it gives a stack overflow. I prefer not using the compilation flag `heap-arrays0` (it might degrade performance?) so I made the function result as allocatable and it works without errors.

I wonder if it is a good practice to declare function results as allocatable to avoid stack overflow. Are there better alternatives (besides heap arrays flag)? Generally, I always try to avoid “automatic arrays” (not sure if this term is correct) in functions and subroutines because sooner or later my code crash

```fortran
function cumsum(x) result(y)
! return the cumulative sum of x
real(kind=dp), intent(in) :: x(:)
real(kind=dp), allocatable :: y(:)
integer :: i, n

n = size(x)
allocate(y(n))

if (n < 1) return
y(1) = x(1)
do i=2,n
   y(i) = y(i-1) + x(i)
end do
end function cumsum

```

---

<div class="post-metadata">

**Author:** ![RonShepard](https://avatars.discourse-cdn.com/v4/letter/r/a3d4f5/32.png) [@RonShepard](https://fortran-lang.discourse.group/u/RonShepard)\
**Post date:** [April 30, 2025, 1:08am UTC](https://fortran-lang.discourse.group/t/fortran-calculator-interpreter/9644/6 "2025-04-30T01:08:12Z")

</div>

> [@aledinola](#):
>
> I wonder if it is a good practice to declare function results as allocatable to avoid stack overflow.

The programmer should have a way to tell the compiler to first try stack allocation, and then if that fails to fall back to heap allocation for automatic arrays. That way, the program only does the extra overhead when necessary. However, I don’t know of any compilers that work that way. I don’t know why.

---

<div class="post-metadata">

**Author:** ![davidpfister](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/davidpfister/32/3949_2.png) [@davidpfister](https://fortran-lang.discourse.group/u/davidpfister)\
**Post date:** [April 30, 2025, 7:00am UTC](https://fortran-lang.discourse.group/t/fortran-calculator-interpreter/9644/7 "2025-04-30T07:00:09Z")

</div>

Nice!  
The advantage of `^` over ` **` is that it keeps the parser simple and clean since you can proceed one character at a time. `** ` requires adding some extra logic to check the i+1 character and take care of exceptions (e.g. make sure the i+1 index does not exceed the string length, etc.).

The substitution method is also what is used in [feq-parse](https://github.com/FluidNumerics/feq-parse/blob/d196662c9e8d9d7d99a9be27fe3d04bba483d479/src/FEQParse.f90#L180) and [evaluate.f](https://github.com/davidpfister/evaluate.f/blob/6db7c8b6322af257436ddfc6761554a03be9f1f8/src/evaluate.f90#L651).

If you want to extend the calculator to matrices you can also have a look at what @fluidnumerics_joe did in [feq-parse](https://github.com/FluidNumerics/feq-parse). He handles up to 4 dimensions. If all the functions are elemental this is ‘just’ about creating a dedicated stack for 2D arrays. There is also some support to add user defined functions that could be fun to play with.

---

<div class="post-metadata">

**Author:** ![gardhor](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/gardhor/32/88_2.png) [@gardhor](https://fortran-lang.discourse.group/u/gardhor)\
**Post date:** [May 1, 2025, 8:39am UTC](https://fortran-lang.discourse.group/t/fortran-calculator-interpreter/9644/8 "2025-05-01T08:39:17Z")

</div>

This great thanks!

---

<div class="post-metadata">

**Author:** ![Beliavsky](https://avatars.discourse-cdn.com/v4/letter/b/ba8739/32.png) [@Beliavsky](https://fortran-lang.discourse.group/u/Beliavsky)\
**Post date:** [May 2, 2025, 2:24am UTC](https://fortran-lang.discourse.group/t/fortran-calculator-interpreter/9644/9 "2025-05-02T02:24:45Z")

</div>

I changed `cumsum` to use an allocatable result. I also added the `merge`, `pack`, and `count` intrinsic functions, added `print_compiler_version` and `print_compiler_info` functions that call the `compiler_version` and `compiler_option` intrinsics, added a `time_code` toggle in the main program that times each line of code, and fixed some bugs.

---

<div class="post-metadata">

**Author:** ![Beliavsky](https://avatars.discourse-cdn.com/v4/letter/b/ba8739/32.png) [@Beliavsky](https://fortran-lang.discourse.group/u/Beliavsky)\
**Post date:** [May 2, 2025, 3:42pm UTC](https://fortran-lang.discourse.group/t/fortran-calculator-interpreter/9644/10 "2025-05-02T15:42:37Z")

</div>

I want to extend the interpreter to read data from a file, assuming each line has a single value. Some possible syntax is

`x < "file.txt"`

which is concise, but which overloads `<`, which already means less than. Other syntax is

`x = read("file.txt")` or

`read ("file.txt") x, y`

where the last line is close to Fortran syntax and says to read variables x and y from columns 1 and 2 of file.txt. A natural complement would be

`write ("file.txt") x, y`

Currently one can just type a variable name to print it, but a `print` statement would allow syntax such as

print “x, y =”, x, y

Suggestions are welcome.

---

<div class="post-metadata">

**Author:** ![waleedmebane](https://avatars.discourse-cdn.com/v4/letter/w/58956e/32.png) [@waleedmebane](https://fortran-lang.discourse.group/u/waleedmebane)\
**Post date:** [May 2, 2025, 5:33pm UTC](https://fortran-lang.discourse.group/t/fortran-calculator-interpreter/9644/11 "2025-05-02T17:33:13Z")

</div>

You might have meant fortran compiler and not compilers in general, but at least one Ada compiler does something similar with a heap-allocated “secondary stack”: [https://nytpu.com/gemlog/2024-12-27-2](https://nytpu.com/gemlog/2024-12-27-2). And I previously read [this](https://en.m.wikipedia.org/wiki/Stack-based_memory_allocation) on Wikipedia under the heading “System Interface”:

> A safer version of `alloca` called `_malloca` , which allocates on the heap if the allocation size is too large, and reports stack overflow errors, exists on Microsoft Windows. It requires the use of `_freea` . gnulib provides an equivalent interface, albeit instead of throwing an SEH exception on overflow, it delegates to `malloc` when an overlarge size is detected.

Seems like something like that could be used to implement what you suggested (though maybe only on GNU and Windows).

---

<div class="post-metadata">

**Author:** ![certik](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/certik/32/4_2.png) [@certik](https://fortran-lang.discourse.group/u/certik)\
**Post date:** [May 2, 2025, 9:05pm UTC](https://fortran-lang.discourse.group/t/fortran-calculator-interpreter/9644/12 "2025-05-02T21:05:25Z")

</div>

I think most compilers allocate on a heap using some heap allocator, but I also like the secondary stack (per thread) better. I think you only need to manage it in functions that can allocate on it. So it should be more performing than a heap.

---

<div class="post-metadata">

**Author:** ![RonShepard](https://avatars.discourse-cdn.com/v4/letter/r/a3d4f5/32.png) [@RonShepard](https://fortran-lang.discourse.group/u/RonShepard)\
**Post date:** [May 3, 2025, 12:29am UTC](https://fortran-lang.discourse.group/t/fortran-calculator-interpreter/9644/13 "2025-05-03T00:29:18Z")

</div>

> [@waleedmebane](#):
>
> […] at least one Ada compiler does something similar with a heap-allocated “secondary stack” […]

That approach should work also for fortran. The main advantage of stack storage is its simplicity, which results in its efficiency, over more general heap storage. It should make little difference in efficiency if it is a stack managed by the OS or a stack managed by the compiler. Of course, heap allocations cannot be eliminated entirely, as push/pop stack allocation only satisfies a subset of memory allocation requirements within the language (candidates are things like local automatic arrays, local allocatable arrays, allocatable function results, and temporary arrays needed during expression evaluation).

---

<div class="post-metadata">

**Author:** ![Beliavsky](https://avatars.discourse-cdn.com/v4/letter/b/ba8739/32.png) [@Beliavsky](https://fortran-lang.discourse.group/u/Beliavsky)\
**Post date:** [May 4, 2025, 2:49pm UTC](https://fortran-lang.discourse.group/t/fortran-calculator-interpreter/9644/14 "2025-05-04T14:49:37Z")

</div>

I added plotting with gnuplot (but if you substitute your own module `plot_mod` with the same subroutine signatures, other plotting tools can be used). An example is

```auto
x = arange(1000)/100;
plot(x,bessel_j0(x))

```

 ![bessel_j0](https://global.discourse-cdn.com/free1/uploads/fortran_lang/original/2X/b/b41e99c4a3e68b9a3bfa36401633559572442fbb.png)

There are one-line if statements and do loops with `cycle` and `exit`, so one can write

```fortran
do i=1,10
   x = rnorm()
   if (x < 0) cycle
   [x sqrt(x)]
end do

```

Sometimes you just want to repeat a line several times and do not need a loop variable. The interpreter treats `*n` at the beginning of a line as an instruction to execute the line n times, so

```fortran
a = 3
x = 1
*5 x = (x + a/x)/2 ! Newton's method for square root

```

gives

```auto
> 3
> 1
> 2
1.750000
1.732143
1.732051
1.732051

```

and

```auto
*3 rnorm(10^6) ! simulate 3 sets of a million normal deviates

```

gives

```auto
      size mean sd skew kurt min max first last
   1000000 -0.0003 0.9995 -0.0024 0.0009 -5.9611 5.0877 0.8383 1.8332
      size mean sd skew kurt min max first last
   1000000 0.0008 1.0000 0.0006 0.0018 -4.6125 4.7730 0.3212 0.6562
      size mean sd skew kurt min max first last
   1000000 -0.0008 0.9993 -0.0005 -0.0017 -4.8507 5.3175 -0.7557 1.4073

```

---

<div class="post-metadata">

**Author:** ![Beliavsky](https://avatars.discourse-cdn.com/v4/letter/b/ba8739/32.png) [@Beliavsky](https://fortran-lang.discourse.group/u/Beliavsky)\
**Post date:** [February 1, 2026, 5:12pm UTC](https://fortran-lang.discourse.group/t/fortran-calculator-interpreter/9644/15 "2026-02-01T17:12:17Z")

</div>

Access to OpenAI Codex inspired me to add some features to the interpreter. The main one is the addition of a transpiler in Python that takes the code you send to the interpreter and translates it to a Fortran main program, calling the same procedures the interpreter does. For example,

```fortran
a = 3.0
b = 1.0
! Newton method for square root
*5 b = (b + a/b)/2
b
! simulate from an AR(1) process and print the autocorrelations
const n = 10^3
x = arsim(n, [0.9])
acf(x,5)
plot(x)

```

is translated to

```fortran
program session
  use kind_mod, only: dp
  use stats_mod, only: acf, arsim
  use plot_mod, only: plot
  implicit none
  integer :: rep1
  integer, parameter :: n = 10**3
  real(kind=dp) :: a, b
  real(kind=dp), allocatable :: x(:)

   a = 3.0_dp
   b = 1.0_dp
   ! Newton method for square root
   do rep1 = 1, 5
      b = (b + a/b)/2
   end do
   print *, b
   ! simulate from an AR(1) process and print the autocorrelations
   x = arsim(n, [0.9_dp])
   print *, acf(x,5)
   call plot(x)
end program session

```
