#BabelOfCode 2024
Week 4
Language: FORTRAN

Confidence level: High

PREV WEEK: https://mastodon.social/@mcc/113867584791780280
NEXT WEEK: https://mastodon.social/@mcc/113975448813565537
RULES: https://mastodon.social/@mcc/113676228091546556

I was very excited about doing TCL this week, but I told myself the first time I get a two-dimensional array problem I'd go FORTRAN, so I guess this week is FORTRAN.

A friend of mine who did AOC2024 in December noted the early challenges this year were *very* easy. Today's definitely is. I wonder if part 2 will have any depth.

I went into this thinking: C is basically cleaned up FORTRAN, right? I know C? This should be easy, right? Right off the bat I find there will be a lot of difficulties entirely not of the kind I'm used to in programming. After a brief adventure with accidentally naming my file .f and not .f90 causing horrific and baffling errors, I run a hello world off the Internet. There's a space before the printout. Hm, how do I turn that off?

https://stackoverflow.com/a/31236043

Oh my fuck, *what*?

How to get rid of unwanted spacing in Fortran's print output?

It may look like a trivial issue, but I couldn't find any answer through googling. I have this little program : Program Test_spacing_print Integer:: N Real:: A,B N=4; A=1.0; B=100.0 prin...

Stack Overflow

I get frustrated with C all the time for being fundamentally a 70s language. It may be I'm about to learn the pain of using a *50s language*.

(Alternately, I hear modern FORTRAN has all kinds of fancy niceties like operator overloading and might not resemble traditional FORTRAN all that much. But then I have the problem if I pick up a random tutorial it's hard to guess which *decade's* standard it's teaching me from, or if it's the GNU extension, if the GNU extension is that different, etc.)

Just learned FORTRAN has an aint() function

Don't that just beat all

I am getting a weird floaty feeling from FORTRAN. I do not at any point really understand what I'm doing, but I am having little to no problems having any one particular thing. I keep doing google searches and getting which I do not understand the syntax of ( `write(error_unit, *) "String to write"`— wait, what? but which work. I do not know if I'd be able to get anywhere with this language if I didn't have either a more experienced programmer or Google+Stack Overfow.

Here is my current program. At the moment, all it does is take a command line argument (a path) and attempt to open the specified file. I build it with `gfortran src/puzzle.f90 -std=f2023 -o program`

https://github.com/mcclure/aoc2024/blob/822e460f81b944c21ca675303b868c45b22a4c2b/04-01-wordsearch/src/puzzle.f90

I'm having two problems, one serious, one unserious.

The unserious problem: I want to abort if the # of arguments is bad. If I do "error stop", it prints a backtrace, which I didn't ask for. If I do "call abort", gfortran fails to link ("undefined reference to 'abort_').

aoc2024/04-01-wordsearch/src/puzzle.f90 at 822e460f81b944c21ca675303b868c45b22a4c2b · mcclure/aoc2024

Advent of Code 2024 challenge (laid-back/"babel" version) - mcclure/aoc2024

GitHub

Here's my serious FORTRAN problem (code link in previous post):

The recommended GET_COMMAND_ARGUMENT function seems to assume you know the length of the argument ahead of time. Obviously, I don't.

https://gcc.gnu.org/onlinedocs/gfortran/GET_005fCOMMAND_005fARGUMENT.html

It allows me to pass in an `allocatable` string, but I believe it is leaving that string of length 0 if I do not ALLOCATE() it, and the fetched string is ''. Is there a way to get the length of a command-line argument before GET-ing it?

I see GET_COMMAND, but that's… awkward

GET_COMMAND_ARGUMENT (The GNU Fortran Compiler)

GET_COMMAND_ARGUMENT (The GNU Fortran Compiler)

…hm. I am concerned.

According to the FORTRAN working group

https://wg5-fortran.org/N2201-N2250/N2212.pdf

As of the 2023 standard, an un-allocated deferred-length variable may have its length set by calling intrinsic procedures; they give GET_COMMAND as an example specifically, and StackOverflow users assert GET_COMMAND_ARGUMENT is also included.

I don't get this behavior. My argument is being input as ''.

Do you think this means my code (linked above) is wrong, or that gfortran -std=f2023 is nonconformant?

Oh my hell lol, I sincerely believe I have found a bug (standard nonconformance) in GNU FORTRAN 14.2.0 and I have a repro case

https://github.com/mcclure/aoc2024/blob/b31be91adb5a0721f97e2ba8f145da4f36129753/04-01-wordsearch/src/puzzle.f90

Am I going to have to figure out how to report a bug on GNU. Geez. Is this going to be like the bureaucracy planet scene in Jupiter Rising

aoc2024/04-01-wordsearch/src/puzzle.f90 at b31be91adb5a0721f97e2ba8f145da4f36129753 · mcclure/aoc2024

Advent of Code 2024 challenge (laid-back/"babel" version) - mcclure/aoc2024

GitHub

Now that I have successfully figured out how to read an argument from the command line without knowing its length ahead of time, I am stuck on figuring out how to read a line of text from a file without knowing its length ahead of time. Apparently not an expected FORTRAN use case. I think the trick I was using before will not work, or at least, I *think*

read(10,"(a)",size=line_length,advance='NO') line_in

should read a line without advancing the filehandle and save the size. But it saves 0.

This is the second time in the longform challenge I have found myself having to implement fscanf() [the other time was Forth]. Both languages do predate C, but I was hoping both would have, at some point in the last 55 years, realized "oh… people want to be able to input line-delimited text files" and added such a feature.

Incidentally, I am very comfortable usually with reading language specifications, but I got hold of a copy of the FORTRAN 2008 spec and… this is one of the least friendly language specifications I've ever seen, when reading it to try to determine how a program should be written.

(Trivia: When the image on the right says something like "the value must be YES or NO" what they mean is "the value must be 'YES' or 'NO'.)

FORTRAN 2008 spec 9.1:
"A file is composed of either a sequence of file storage units (9.3.5) or a sequence of records… A file composed of file storage
13 units is called a stream file."

The definition of "file storage units" (9.3.5):
"A file storage unit is the basic unit of storage in a stream file or an unformatted record file."

The linked definition of "Stream file" (1.3.139)
A file composed of a sequence of le storage units (9.1)

YOU ASSHOLES, THIS DEFINITION IS CIRCULAR!

Like okay I understand what you are trying to do here is not commit to a particular byte length because you want to support 7-bit bytes, 8-bit bytes, and possibly UTF-16 characters or something, but YOU COULD HAVE *SAID SO* INSTEAD OF MAKING A LOOP OF 3 DEFINITIONS LINKING TO EACH OTHER

git discovery: you cannot check a file you do not have permissions to into a repository.

problem: my repo contains a directory of test files. this directory contains a second directory of "invalid" tests, i.e., tests that the program is *expected* to fail on (and if it doesn't fail cleanly that's an error). one of the "invalid" tests is a file the program doesn't have read permissions to.

I cannot check my "file with no read permissions" test case into the repository :(

Since automatic deferred length initialization is not working as the spec seems to require, I decided to just read the file in line by line.

This was much harder than I expected! The GNU docs do not well describe READ/WRITE, but do well describe the standard library functions. So I wrote around FGETC(), but then it turned out this is a GNU extension (or possibly was in FORTRAN 77 but not future FORTRANS?) so I had to rewrite to use normal READ in "Stream mode"… not in the GNU docs * _ *

(1/2)

I wound up slowly picking my way through the 2008 language spec, as previously mentioned not super readable. But I got it to work:

https://github.com/mcclure/aoc2024/blob/a8835dcd8ad0162268ef16708f9a7cd8b6d45958/04-01-wordsearch/src/puzzle.f90

Annoyed I had to spend all this time just doing file management, I decided to do the file management REALLY WELL. It's got unique error messages for different types of file handling errors and everything!

Now if only I could make gfortran suppress that darn `error stop` backtrace..

(2/2)

aoc2024/04-01-wordsearch/src/puzzle.f90 at a8835dcd8ad0162268ef16708f9a7cd8b6d45958 · mcclure/aoc2024

Advent of Code 2024 challenge (laid-back/"babel" version) - mcclure/aoc2024

GitHub
By the way, check out this vaguely hilarious section from the FORTRAN 2008 spec, where they state in the *most noncommital terms possible* that a byte is *probably* 8 bits (they don't say "byte"; they don't like the word "byte"; the word "byte" appears exactly twice in the 621-page spec, both times in the C interoperability section) then have this long additional note falling all over themselves to apologize for the hubris of suggesting that a byte is probably 8 bits.

A reply I got on a previous post in this thread suggested that the reason the FORTRAN spec is so strict about using the word "file storage unit" instead of the normal terminology "byte" is that FORTRAN is from 1957 and literally predates the world at large adopting the vocabulary "byte" for the minimum addressable storage in a filesystem. Well, geez. That might really be it.

(Also note FORTRAN's commitment to line numbers is so great that even the English text of the spec has line numbers.)

@mcc If I'm understanding Wikipedia right, the first usage of the word "byte" was in 1956, literally just a year before. Knuth puts the year that byte standardized around being exactly eight bits as being as late as 1975... it's breaking my brain to think about.
@xgranade another really funny thing you'll find if you look carefully at wikipedia is that FORTRAN was designed in 1957, but the first FORTRAN program was not successfully compiled until 1958.
@mcc That makes way, way too much sense.
@xgranade It was of course, like, the second compiler. Ever. (Actually, although my memory is ALGOL beats FORTRAN as first compiled language, if it turns out the ALGOL team took longer to get to hello world on *implementing* the compiler then it might be once you work out the timelines you could argue ALGOL was the first compiled language but FORTRAN was the first compiler… I haven't done that math :P)
@mcc As much fun as I make of FORTRAN, and I do, it's really impressive that the second compiled language ever is still usable today, even if only just.
@xgranade Frankly, although some of the pain points are in *very* awkward places, I'm finding this a *lot* more usable than I was expecting. This is not the constant start and stop I had with Forth.
@mcc Maybe it's improved since I last used it, then... I kept having weird segfaults when using functions that didn't happen when rewriting as subroutines. I eventually figured out what was happening, but the compiler did *not* help with that. At all.
@xgranade You may have been writing more complex code than I yet have. I am still on attempting to load the contents of a file into a two-dimensional array.

@xgranade @mcc One of those wild bits of trivia about C++ is that there are parts of the spec that don't assume a byte is 8 bits, because it's old enough to have cared about targets where that isn't true.

I want to say it's around C++, like, 20? Where they introduced some modifiers on string literals to let you be explicit about the encoding, because otherwise encoding is an implementation detail and that means your strings might get jammed into 7-bit representations on some compilation targets.

@mark @mcc I mean, I've worked on embedded systems with 18-bit integer representations, so it makes a lot of sense.

Just still wild to think about, somehow.

@xgranade @mcc ... unless you're under NDA, I must know more. 😄
@mark @mcc It's all in https://arxiv.org/abs/2206.12950, but the rough version was that it was a really cool prototype where 18 bits was what folks could eke out.
Advancing Hybrid Quantum-Classical Computation with Real-Time Execution

The use of mid-circuit measurement and qubit reset within quantum programs has been introduced recently and several applications demonstrated that perform conditional branching based on these measurements. In this work, we go a step further and describe a next-generation implementation of classical computation embedded within quantum programs that enables the real-time calculation and adjustment of program variables based on the mid-circuit state of measured qubits. A full-featured Quantum Intermediate Representation (QIR) model is used to describe the quantum circuit including its embedded classical computation. This integrated approach eliminates the need to evaluate and store a potentially prohibitive volume of classical data within the quantum program in order to explore multiple solution paths. It enables a new type of quantum algorithm that requires fewer round-trips between an external classical driver program and the execution of the quantum program, significantly reducing computational latency, as much of the classical computation can be performed during the coherence time of quantum program execution. We review practical challenges to implementing this approach along with developments underway to address these challenges. An implementation of this novel and powerful quantum programming pattern, a random walk phase estimation algorithm, is demonstrated on a physical quantum computer with an analysis of its benefits and feasibility as compared to existing quantum computing methods.

arXiv.org
@mark @xgranade I once heard someone claim that the reason C++ took so long to standardize that, and so long to remove trigraphs, was IBM was still trying to support a very small number of SERIOUSLY old mainframe installations
@mcc @mark @xgranade For C DSPs were one of the big holdouts with unusual byte sizes AIUI - the users didn’t really care about data not represented as a word so no point implementing the hardware to handle that efficiently.
@xgranade @mcc 8-bit bytes were introduced with the 360 in 1964. Obviously it took some time for it to catch on universally after that, so 70's seems like a reasonable guess.

@mcc apparently the term "byte" was coined in 1956, so. yeah that's entirely plausible

on the other hand you are reading the specification for fortran 2008, which was approved in 2010, not the original fortran specification drafted in 1954

we knew what bytes are in 2008

@00dani sometimes organizational momentum is hard to reverse
@mcc @00dani I can believe that in a programming language spec there are so many places that reference a term like that that changing it would be a bunch of work.
@mcc yeah, i create them on demand
@whitequark i actually have an idiom for test scripts in this repo, so i guess i could make a test script that generates the expected no-access test in the directory that git idiomatically ignores. but i think i'll just leave the one copy in the no-git scratch directory. This is the AOC project so I probably won't check this out elsewhere.
@mcc git can't even represent permissions other than "readable file", "executable file" and "directory"
@jcoglan this may be the first time I've ever spoken this sentence about git, but: That sounds like a reasonable design decision.
@jcoglan
It also supports 'symlink', which is a load of fun if you're trying to share with people running Windows.
@mcc
@wouter ah yes, one of my projects has a symlink to a parent directory in it in order to avoid a build step to copy some files into the scope of some framework, and, this is not a good idea
@wouter the unix filesystem is a tree which is actually a cyclic directed graph, good fun

@mcc we'd ship a (small) filesystem image.

not sure what to do about windows...

@mcc a) drag, and b) nice negative test case!, and c) I have a folder "testing" in my repo that is .gitignored. I'd programattically touch the file and then change it's permissions and then test against that.

I was just musing about a similar problem: I need some tests that my code manipulates a git repo successfully. Can't put .git folders in a subfolder, git shits its pants.

https://mastodon.social/@GeePawHill/113920786190776103

@mcc It's wild to me that FORTRAN predates the near-universal adoption of the byte as an atomic unit of storage.

@xgranade @mcc have you read the Common Lisp spec? 😀

To be fair, the spec is very good, but they are also very explicity not giving any special significance to 8-bit bytes. And this is in paid of the spec being written decades after 8-bit bytes being standard.

https://www.lispworks.com/documentation/HyperSpec/Body/f_ldb.htm#ldb

CLHS: Accessor LDB

@loke That predates CL by many years ... LDB comes from MACLISP, and LDB / DPB date back to PDP-10 ... where a byte was just "bunch of bits".

@xgranade @mcc

@mcc Aw yeah as someone with extensive experience in Old FORTRANs it's always been like that.

Just be glad they stopped the slash-through-the-letter-O thing. It's so unimportant and yet so annoying, since everyone else who used a slashthrough used it for zero. And that includes Amateur Radio, so I don't know _what_ FORTRAN was thinking.

@mcc Oof. Couldn't we represent this in something more human-readable? Like XML and XSLT?
@mcc oh! I met a guy at POPL who is trying to bring some ideas from this century to FORTRAN, if not bring the FORTRAN spec itself into this century. it seems like one hell of a standards committee
@mcc I'm fairly sure I've implemented readline in fortran at least twice in my career. :(
@mcc Nah, most GNU projects use debbugs, so you probably just send an email.
@ieure Ah good. And I won't need to sign up for the mailing list to send the email?
@mcc Almost definitely not.

@mcc how do you mean ". ? the shell won't let you enter it.
You'd have to quote it as '".' Using the example proggy from the manual for GET_COMMAND_ARGUMENT gives you then

$ ./a.out 333 '".'
./a.out
333
".

@dimpase The argument is a nonempty sequence of characters, but is being read in as the empty string. I say '' in my post because I don't know how else to represent a string of zero length in text.
@mcc Fortranically speaking, every NULL and empty string (wat? without a terminating character, or with?) are sins, committed by C-minded ppl...
@dimpase I am aware of nothing to suggest a zero-length string is something FORTRAN considers invalid.

@mcc in old fortrans an empty string still had length 1.
Something like

CHARACTER FOO[1]

can hold a zero-length string.

Fortran 77;
----
There are no null (zero-length) character-string variables. A one-byte character string assigned a null constant has the length zero.
---

I'd be surprised if this has changed.

@mcc In even-older versions of FORTRAN, you preallocate the maximum possible length of any such character array (yes character array) of any such value. If you wanted to be less wasteful about it you made a buffer character array at some stupid size and use that repeatedly as a safe buffer, then you could get the length of the string received from the very long buffer character array and copy it safely into a small string.
@moira Okay, but I am using FORTRAN 2023. Is there a less-silly way to do it, given FORTRAN 2023?

@mcc holy gods there's a 2023

I would hope so, but since I don't know it, I'm handing you an older-FORTRAN best practice you can use if you can't a better method.

@mcc I rarely use this, but the way I've done it in the past is to allocate the argv character to a sensible buffer size, initialise it to " ", and use trim() on it when using it, which will strip the unused part of the buffer.

Example:

character(len=4096) :: arg
arg = " "
call get_command_argument(1, arg)
call my_code(trim(arg))

@mcc IMHO GET_COMMAND_ARGUMENT assumes you know the maximal length of the argument (wearing my old Fortranista hat, feels very Fortranic). I don't know how it's padded, or truncated, if the length is too big. If it's too small, it gets truncated.