Salta al contenuto principale


#BabelOfCode 2024
Week 4
Language: FORTRAN

Confidence level: High

PREV WEEK: mastodon.social/@mcc/113867584…
NEXT WEEK: mastodon.social/@mcc/113975448…
RULES: mastodon.social/@mcc/113676228…

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.


#BabelOfCode 2024
Week 3
Language: x86_64 assembly [AMD64] (macroassembler: GNU as/gas)

PREV WEEK: mastodon.social/@mcc/113783248…
NEXT WEEK: mastodon.social/@mcc/113906616…
RULES: mastodon.social/@mcc/113676228…

I planned ASM for today and when I saw the challenge *almost* bounced to TCL, because I *don't* wanna write a parser in ASM. But the language here is exceedingly regular, so probs a state machine is enough.

Successfully ran this hello world cs.lmu.edu/~ray/notes/gasexamp… which I think should be all I need to start


Questa voce è stata modificata (8 mesi fa)

Giuseppe Aceto reshared this.

in reply to mcc

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?

stackoverflow.com/a/31236043

Oh my fuck, *what*?

Questa voce è stata modificata (9 mesi fa)
in reply to mcc

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.)

Oblomov reshared this.

in reply to mcc

Jumping into Fortran is quite an interesting experience. I became one of 6 core developers of a Fortran physics simulation code at CERN back in 2017 until I left in 2020. We converted a lot of the code to Fortran 2003. It's not a bad language once you learn the quirks, and it's relatively easy to interface with C. (I mean, most things are.)
in reply to Veronica Olsen 🏳️‍🌈🇳🇴🌻

@veronica Where would you recommend starting to ensure I'm learning FORTRAN 2003 or FORTRAN 2023 and not something ancient and unnecessarily inconvenient?

Does anyone use GNU FORTRAN (ie, asking if they use -std=gnu, not asking if they use gfortran) in industry?

in reply to mcc

We supported GNU, Intel and the Nagfor compilers. Honestly, my best resource was the Intel Fortran forums, which are not public. I had a university Intel account though.

I also have a draft copy of one of the Fortran standards that I used for reference. It is quite tricky to find good resources online unfortunately.

in reply to mcc

@veronica One of the best books to get started is "Modern Fortran explained" by Metcalf et al.
in reply to mcc

Just learned FORTRAN has an aint() function

Don't that just beat all

Questa voce è stata modificata (9 mesi fa)

Oblomov reshared this.

in reply to mcc

does it have a y'all function? Because if so, I'm switching immediately

mcc reshared this.

in reply to Foone🏳️‍⚧️

@foone pretty sure no

I assume that the "y'all" keyword would be a standin for every variable in scope. So you say

y'all += 4

and it adds 4 to all variables.

It might be possible to implement this in userspace in Python.

reshared this

in reply to mcc

@darkling @foone this suggests you could type y'all() and it would be the code equivalent of selecting everything on your desktop and pressing enter
in reply to mcc

@foone @darkling In some parts of Arkansas and elsewhere, “you ‘uns” is used instead of “y’all.” I assume “you ‘uns” would operate on all variables currently equal to 1.
in reply to mcc

I wonder what blessyourheart() would do. Surely something that looks good to the initiated, but is scarring to those who understand. @foone
Questa voce è stata modificata (9 mesi fa)
in reply to mcc

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.
in reply to mcc

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`

github.com/mcclure/aoc2024/blo…

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_').

in reply to mcc

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.

gcc.gnu.org/onlinedocs/gfortra…

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

in reply to 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.
Questa voce è stata modificata (9 mesi fa)
in reply to Spo0000opybirb

@moira Okay, but I am using FORTRAN 2023. Is there a less-silly way to do it, given FORTRAN 2023?
in reply to 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.

Questa voce è stata modificata (9 mesi fa)
in reply to 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))

Questa voce è stata modificata (9 mesi fa)
in reply to mcc

Can you call twice, first to get LENGTH, second to get VALUE after having made the allocation?
in reply to Ken Milmore

@kbm0 Thank you, this was what I needed. I did not understand LENGTH was an out argument.
in reply to 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.
in reply to mcc

…hm. I am concerned.

According to the FORTRAN working group

wg5-fortran.org/N2201-N2250/N2…

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?

in reply to 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
".

in reply to Dima Pasechnik 🇺🇦 🇳🇱

@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.
in reply to mcc

Fortranically speaking, every NULL and empty string (wat? without a terminating character, or with?) are sins, committed by C-minded ppl...
in reply to 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.

Questa voce è stata modificata (9 mesi fa)
in reply to mcc

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

github.com/mcclure/aoc2024/blo…

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

in reply to mcc

Nah, most GNU projects use debbugs, so you probably just send an email.
in reply to PunnO)))

@ieure Ah good. And I won't need to sign up for the mailing list to send the email?
in reply to mcc

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.

in reply to mcc

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.
Questa voce è stata modificata (8 mesi fa)
in reply to mcc

I'm fairly sure I've implemented readline in fortran at least twice in my career. 🙁
in reply to mcc

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'.)

Oblomov reshared this.

in reply to 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.

Questa voce è stata modificata (9 mesi fa)
in reply to Spo0000opybirb

@moira I've been trying to source "Letter O Considered Harmful" for years now. It seems it only exists in paper form, in some old Fortran Work Group archive, somewhere in the UK.
in reply to Efexor Zolpidem

@capeta @moira I agree that the letter O is harmful but DON'T USE THE SLASH TO INDICATE O INSTEAD OF 0 WHAT WERE YOU THINKING JOHN
in reply to mcc

itym JØHN

sfairesphobic bastard

Questa voce è stata modificata (9 mesi fa)
in reply to mcc

Oof. Couldn't we represent this in something more human-readable? Like XML and XSLT?
in reply to 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
in reply to mcc

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!

in reply to mcc

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
in reply to mcc

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

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 🙁

Questa voce è stata modificata (9 mesi fa)

Oblomov reshared this.

in reply to ✧✦Catherine✦✧

@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.
in reply to mcc

git can't even represent permissions other than "readable file", "executable file" and "directory"
in reply to jcoglan

@jcoglan this may be the first time I've ever spoken this sentence about git, but: That sounds like a reasonable design decision.
in reply to mcc

we'd ship a (small) filesystem image.

not sure what to do about windows...

in reply to 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.

mastodon.social/@GeePawHill/11…

Questa voce è stata modificata (9 mesi fa)
in reply to mcc

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)

in reply to mcc

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

github.com/mcclure/aoc2024/blo…

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)

in reply to mcc

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.

Oblomov reshared this.

in reply to mcc

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.)

Oblomov reshared this.

in reply to 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.
in reply to Cassandra is only carbon now

@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.
in reply to Cassandra is only carbon now

@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 😛)
in reply to 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.
in reply to Cassandra is only carbon now

@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.
in reply to 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.
in reply to Cassandra is only carbon now

@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.
in reply to mcc

Was for homework in a numerical relativity class, and for writing higher-order Runge–Kutta integrators.
in reply to Cassandra is only carbon now

@xgranade 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.

in reply to Mark T. Tomczak

@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
in reply to 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.
in reply to 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

reshared this

in reply to 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.
in reply to mcc

@00dani holy moly, fortran is 10th on TIOBE. i was not expect it to be beating rust, swift, assembly, php and ruby. i need to reset my image of how many programmers are doing scientific computing
in reply to Leon

@leon @00dani Based on my experience so far, I would not intentionally use FORTRAN again, but also if I wound up in a situation where I joined a project and they told me "yeah, we're already using FORTRAN for this", I would not throw a tantrum.
in reply to mcc

I wonder if that's a FORTRAN thing or an IBM thing? It's been an age since I read Mythical Man Month, but I remember Fred Brooks mentioning one of the innovations at IBM was to keep documentation in binders so that individual pages could be hot-swapped as errata were published. I mean, nowadays we use word processors and cloud collaboration tools, but I'm sure that was hot shit back in the '70s.

I bet line numbers would have made it a lot easier to publish errata that said stuff like "Lines 305-335 on page 69 are OBSOLETE. Replace with the following:"

in reply to mcc

An interesting thing about the gfortran compiler I've never seen elsewhere… when it wants to mark the position of an error on a line, it has a little ASCII art arrow like Rust or Clang. But instead of an arrow it uses a number 1, which lets it say "blahblah wrong at (1)". It takes a moment to get used to, but it's actually really smart. If you think about it it creates the potential for sentences like "found glarg at (1), but expected blarg because of (2)". rustc struggles with such sentences.

Oblomov reshared this.

in reply to mcc

you could say that gfortran loves line numbers so much that it adds extra numbers to the middle of the line
in reply to mcc

Sensitive content

mcc reshared this.

in reply to mcc

Sensitive content

reshared this

in reply to mcc

So the reason I picked this puzzle for FORTRAN was I heard FORTRAN's builtin multidimensional array types were nice. I probably won't be truly making deep use of those in the end, but I'm at least learning one thing from the experience: FORTRAN's builtins are *not* especially nice for *growable* arrays, regardless of dimension. You can *do* it, but it's not efficient or super friendly. I realized my growable implementation would be O(n^2) on file size, just to read the file into memory.

(1/2)

in reply to mcc

Fortunately, I can make everything easy again by just scanning the file to determine the size of the multidimensional array I need to allocate, seeking back to the beginning, then actually reading the array in. It probably sounds to you like I just made a very basic statement. But something to make clear: fseek() is actually considered a very advanced feature in FORTRAN, and was only added to the language in 2003 (in other words 46 years after the language was first specified)

(2/2)

Oblomov reshared this.

in reply to mcc

back in the day you didn't have this luxury (of allocateable arrays). So you just read everything in a big static 1-dim array (typically called WORK 😀), and then passed it to a subroutine, which took it into a 2-dim array (I never needed anything higher dimension to input like this, the point is that one could then make it look like a dynamically allocated 2d array of the right dimensions).
Questa voce è stata modificata (9 mesi fa)
in reply to mcc

do you mean fitting in "the RAM of the machine"? 🙂
Surely, multitasking OSs are later invention than Fortran. In the olden days you just allocated (statically) however much RAM you could, and use it as you please. If your data won't fit into RAM, then it's a different, much harder, issue...
Questa voce è stata modificata (9 mesi fa)
in reply to mcc

Adding dynamic memory allocation to Fortran has been like adding type safety to C
in reply to Rivimea, god of accidents

@sklrmths What they came up with is not terrible. I'm not even willing to say it's worse than what we have in C.

Like, it would be *nice* to have realloc, but I've never felt *really* convinced that realloc in C actually works

in reply to mcc

Decided to do a bit more on the FORTRAN project this morning… found myself running in circles for a decent bit trying to understand why code wasn't acting the way I expected. I eventually realized the problem was that when I wrote the expression `char_in == '\n'`, this was behaving differently than I expected because '\n' is a string containing a backslash followed by an n. Of course it is. Of course? Why would I have expected it be anything else?
in reply to mcc

On a related note, shortly after this I was in a situation it would be convenient if I could cause a particular loop iteration to abort and resume from the beginning of the loop. I experimentally typed "continue". It was accepted. I run the code. It does not behave as I expected. I go to look it up.

reshared this

in reply to mcc

RTFM would save so much stumbling in the dark. Why do you do this to yourself?
in reply to Howard Chu @ Symas

@hyc I have no idea what you are trying to communicate here. The screenshot above is literally a screenshot of the manual.
in reply to mcc

I mean read the language text thoroughly before trying to write it. Instead of guessing and looking up your mistake after the fact.
in reply to Howard Chu @ Symas

@hyc Typing a nine-letter word, identifying that the syntax highlighter didn't bold it which is suspicious, and running the program once to see what happens is not exactly a substantial investment of time.
in reply to mcc

(So there's no confusion: I think this is a fine feature for a language to have, I think every language should have a "no-op" keyword, it's basically the same as Python "pass" and exists for the same reason [as a target for otherwise-productive flow control] [GOTO labels must point to statements, so you need a way to write a statement with no effect])

Oblomov reshared this.

in reply to mcc

I wonder if it could have also been useful as something that could have easily been replaced with a GOTO as a patch without having to redo a ton of paper tape or punch cards long ago.
in reply to mcc

OK so

I am using the stream input mode for my file input (this freaks the fuck out of every FORTRAN programmer on this site, but)

I need to seek to the beginning of the file. A stack overflow comment suggests this is done with

read(10, "()", advance='no', pos=1)

gfortran prints

runtime error: Format present for UNFORMATTED data transfer

I remove the "()"

read(10, advance='no', pos=1)

Compiler balks

Error: the ADVANCE= specifier at (1) must appear with an explicit format expression

WDID

in reply to mcc

Man if I found a second case where GNU Fortran failed to implement the standard standardly I'm gonna be annoyed

Oblomov reshared this.

in reply to mcc

My fuzzy read of the standard is that the "()" version above is probably inaccurate, but the version without the "()" should probably in this case compile.

I'm actually kinda stuck here, and this (the ability to seek within a file) is a banner feature of the post-2000 STREAM mode, so I think: I wonder if there's a Discord, IRC, otherwise realtime communication channel for FORTRAN programming I could tap.

fortranwiki.org/fortran/show/I…

*squeaking* "No… no!!!"

Questa voce è stata modificata (9 mesi fa)
in reply to mcc

There are some ways that being stuck in 2008 are good but this is not one of them!!

Oblomov reshared this.

in reply to mcc

I successfully worked around gfortran's apparent refusal to do a nonadvancing read by having my actual read look like

if (row_at == 1 .and. col_at == 1) then
! If we detect this is the first character of the file, reposition
read(10, iostat=file_error, pos=1) char_in
else
read(10, iostat=file_error) char_in
end if

But I really, really, *really* hate it

in reply to mcc

I am experiencing confusion about apparent disjoint between docs and behavior. Is the following correct?

! This allocates a matrix "board" of COLS columns and ROWS rows
allocate(board (cols, rows))

! This writes to the "bottom right" cell of board
board(rows, cols) = 1

Everyone agrees FORTRAN is column-major in memory but get vague about syntax (lots of examples where indices are named "i" and "j"). I get incorrect behavior if I DON'T swap rows,cols order between allocation and write/read.

Oblomov reshared this.

in reply to mcc

That doesn’t seem right to me, I expect the indexing to be the same ordering in allocation and indexing.
in reply to mcc

Blghgafhg part 1 done. This was the longest any part 1 took me of this project so far, but I think that was mostly… external distractions, happening this week. Gonna do part 2 before I share my thoughts (part 2 is really simple but I'm going to do it a little more complicated than it has to be just so I have an excuse to do some vector math in FORTRAN)
in reply to mcc

*rubbing eyes*

So I am reading this tutorial

masuday.github.io/fortran_tuto…

I write a program with a helper subroutine using CONTAINS. It's fine. Now I want a helper function. gfortran says "unclassifiable statement" on the word "function". I try literally copypasting the sample code from the tutorial. gfortran rejects the sample code, again saying `function` is "unclassifiable", in all of f2023, f95, and GNU.

What the devil?

Haven't tried digging into the spec (which is made of hell) yet.

in reply to mcc

All right.

Part 1: github.com/mcclure/aoc2024/blo…

Part 2: github.com/mcclure/aoc2024/blo…

Did I learn anything from this? I guess. Yeah. Okay, I guess so.

That wasn't particularly unpleasant. The ergonomics weren't great, but were not-great in forgivable ways. The fact each tutorial/doc/StackOverflow answer I found targeted a different FORTRAN std was definitely frustrating. I got to add an array to an array on two (2) lines of part 2, and other than that this was basically funny-shaped C. C with paperwork

in reply to mcc

The v.a.s.t. bulk of the time here (and in the simpler part 2, the bulk of the code) was spent on file I/O. In the 4 weeks of this project so far, I skipped file i/o (instead embedding the data in the program) for BASIC and ASM, since those are languages with Limitations, and for Forth and FORTRAN I assumed those were Fully Featured so I could just do file i/o. But no, on both Forth and FORTRAN simple file i/o was *a nightmare*, the bulk of the work.

(1/2)

Oblomov reshared this.

in reply to mcc

There's an awkward irony here.

For the Forth week, the input was a list of ASCII numbers. *This* kind of input FORTRAN had easy-to-use builtins for, but Forth had nothing and I had to build it myself.

FORTRAN week, the input was a grid of ASCII characters. *This* Forth could have handled pretty easy, but FORTRAN it's actually sorta impossible unless you use a modern (and, apparently, not completely tested in gfortran??) "stream" mode, which took forever and required consulting the spec. (2/2)

Oblomov reshared this.

in reply to mcc

I got a lot of good help this week (FORTRAN) so, thank you everyone.

I guess that's one "month" of the project down. Here's my completion status.

(Note there are 43 languages on this list, and 25 puzzles in AOC, so only a little over half will get hit by the end. My "for certain" list is: TCL, Haskell, Idris, Smalltalk, Self, Ada, Factor, Mirth, Uiua, at least one of ARM and RISCV.)

Oblomov reshared this.

in reply to Paul Will Gamble 🇨🇦

@paulywill mastodon.social/@mcc/113676228…


I was too busy to do AOC this month (that's adventofcode.com/).

So I'm thinking I'm going to do AOC 2024, *in 2025*, under the following rules:

- One challenge per week.
- I don't have to perform a challenge every week. The goal is to finish by the start of December.
- I have to do a different programming language every time.
- C, C++ and Objective-C are not eligible languages.
- If I make an honest attempt at a language and fail, I may retry in Go (but only Go) (I need to learn Go)


in reply to mcc

Julia is kinda cool, though I've only played with it a bit. It's fairly new and has been rapidly improving. Worth checking out, I think. Best for the more numerically oriented problems.
in reply to Joe

@not2b I actually around 2013 auditioned Julia as my new scripting language to replace Lua. It was interesting but once I realized I couldn't embed it in an executable without embedding the 44MB entirety of LLVM I walked away. This, along with difficulties getting the Clasp compiler to run on my old laptop, was what eventually lead me to create Emily (a language that turned out unsuitable for games as the one game I wrote in it initially ran at 1 FPS)
@Joe
in reply to mcc

the tutorial on tcl.tk and the O'Reilly book are how I learned

oreilly.com/library/view/tcltk…

in reply to mcc

I'm so curious to see how TCL, Haskell, and Smalltalk go 😄
in reply to Meg

@megmac this is gonna be my like third or fourth attempt at haskell, and i've somehow been reading smalltalk tutorials since the year 2000 without ever actually writing a line of it
@Meg
in reply to Meg

@megmac I'm looking forward to COBOL. Mainly because I've been playing around with it recently.

It's remarkably not terrible in some ways (and very annoying in others). In fact, the aplit between nice and horrible appears to be exactly opposite that of FORTRAN.

@Meg
in reply to mcc

@loke @megmac Rumour has it that the compiler course at Lund University now has an explicit "no COBOL" clause for implementation language, after one fateful time, when a student wrote a C compiler in COBOL and handed it in.
in reply to mcc

Ooh, I hope you get to one or more of Tal, Gleam, and Zig, those have all been really fun to learn!
in reply to Finn

@soxfox42 there are several reasons I should learn Zig.
@Finn
in reply to mcc

I did a lot of work in Ada back in the day, so I’m keen to see what you do with it.
in reply to mcc

I was just reminded of the existence of xslt and I think you should add that to this list if you've never used it before.
in reply to Meg

@megmac I actually made a good faith effort to implement a lambda calculus evaluator in XSL/T once
@Meg
in reply to mcc

I'm not doing the Babel-of-Code challenge this week but Andrzej has his writeup of his Prolog week up

mastodon.gamedev.place/@unjell…

and has started a thread for his week with Lean:

mastodon.social/@unjello@masto…

Oblomov reshared this.

in reply to mcc

The good news for when you decide to do Haskell is that it has a powerful parser library (Text.Parsec) built-in to the language.
in reply to mcc

The UK research software engineering Slack has a Fortran channel, you can request to join at docs.google.com/forms/d/e/1FAI…
in reply to Tachibana Kanade

@h0m54r Heh, neat.

Given this still requires a roundtrip before I can post a question, I might just go ahead and finish this with workarounds and then email the GNU mailing list.

in reply to mcc

(Actually, thinking about it, UKRSE is also in the process of taking on on the Fortran standards working group from the British Computer Society, so it makes sense as a home for discussion. I know some channels on that server are bridged to Matrix, but I don’t think the Fortran one is currently unfortunately)
in reply to mcc

Completely irrelevant to your question, but you made me smile as I recall being (what I believe to be) the first person to compile NASA GISTEMP climate index in gfortran back in 2008.
in reply to mcc

Did you try:

read(10, pos=1)

That's what the example code for stream I/O seems to use.

in reply to mcc

@jhamby this is how i did it

mastodon.social/@mcc/113924441…


I successfully worked around gfortran's apparent refusal to do a nonadvancing read by having my actual read look like

if (row_at == 1 .and. col_at == 1) then
! If we detect this is the first character of the file, reposition
read(10, iostat=file_error, pos=1) char_in
else
read(10, iostat=file_error) char_in
end if

But I really, really, *really* hate it


in reply to mcc

You're right. Never mind. I don't know Fortran very well.
in reply to mcc

nice! so I don't have to throw away all my (subsequent) punch cards if I need to remove a line of code. I can just replace it by a CONTINUE and redo only one card! Love the UX in this language
Questa voce è stata modificata (9 mesi fa)
in reply to mcc

they really butchered things in newer fortran manuals. 😠

in good old days one used CONTINUE to place end of loop labels (or for other similar purposes)

DO 42 J=...
...
42 CONTINUE

as old manuals tell you:
docs.oracle.com/cd/E19957-01/8…

in reply to mcc

it's such a funky language if you're used to C or C-like languages. I had like half a semester of Fortran in Uni and I could not get used to it. One of the most fun features I learned about was that arrays are one-indexed by default but can actually start at any index you want, including negative numbers.
in reply to mcc

FORTRAN. WATFOR.
I’ll never forget my first.
in reply to mcc

i’ve dabbled with scientific computing at uni (my master’s was in FORTRAN 77 (they used it for Ultimate Portability)). Don’t remember much about the language, but the general attitude in that area was like „can’t seek or reopen the file? Let’s note somewhere that the input file should contain the payload twice. There, problem solved.”
in reply to mcc

Fortran is good for high performance multidimensional array work. But for easy multidimensional work you might want to look into array languages.

But then again, one had a lot of fun reading this thread, so going with Fortran was clearly the right choice. 😃

in reply to Elias Mårtenson

@loke Among the problems here are

1. I don't know what puzzles might be coming later in the set; if I see a non-numerical multidimensional array program and so hold off on FORTRAN because maybe there'll be a good numerical problem later, well, maybe there actually *won't* be.

2. I don't ever know what part 2 will be when I start part 1;

3. I don't truly know what the different languages are good at until I've used them! And that, more than anything else, is the point.

in reply to mcc

definitely. And you documenting it here provided not just entertainment but also valuable information for those of us who might want to go down a similar path in the future. I'm certainly open to using Fortran for solving some problem where its strenghts are useful. But since I've never actually used it beyond simple hello world style programs, these kinds of threads are useful. And not to mention, fun.

I solved 2024 in my own programming language which happens to be an array language, so seeing the Fortran approach was educational.

in reply to Elias Mårtenson

@loke definitely try to use the 2003 edition or newer, is what I learned.
in reply to mcc

disappointed to discover that these are not column numbers. I learned FORTRAN77 in high school on an Apple IIe. The column numbers were significant because they mapped punch card layout directly.

reshared this

in reply to Ted Mielczarek

the worst part about this was that typing anything but a space in column 1 commented out the line. This made sense on punch cards, so you could skip a line if you punched it incorrectly. It was a lot more confusing on a computer where if you didn't remember to indent every line one space that code just didn't exist.

Oblomov reshared this.

in reply to mcc

@tedmielczarek by the way, even in modern FORTRAN it's actually quite difficult to print a line without it being prefixed with a space. I *assume* the reason for the space prefix on output and the reason for the space prefix on source lines is different.
in reply to mcc

@tedmielczarek Until F90, Fortran output sent to a printer or the console was assumed to have an ASA carriage control character as the first character of the line - see en.m.wikipedia.org/wiki/ASA_ca…

The carriage control character would be consumed on output which meant if you started writing output without a leading space (or 0, 1, or +), the first character would get trimmed off. That's why output lines in F77 and earlier start with an extra space - it's a control code for a long obsolete printer formatting scheme.

To get proper formatting of legacy FORTRAN output, POSIX included the `asa` utility: man7.org/linux//man-pages/man1…

Back in the day I made friends with the head of Design Engineering at the power plant where I worked because I knew the obscure magic to make his department's code output legible and not look like total ass. I didn't have much interaction with him otherwise but I was always happy to help him sort out his code output. Good guy.

in reply to arclight

@arclight this thread has been a delightful goldmine of weird Fortran trivia. I doubt any of it has helped Andi make her program work, but I hope it has at least made it clear that the problem is Fortran, not her.
in reply to Ted Mielczarek

@tedmielczarek @arclight i guess i'm actually doing this more to pick up weird fortran gotcha facts than i am to get a working program…
in reply to mcc

@arclight if you chose COBOL instead you could have wound up with a lucrative career!
in reply to mcc

my teacher told us we were lucky to not be using punch cards because he taught Fortran when those were in use as well. They didn't have punch card machines at the school so you wrote your program on paper with a punch card layout then sent it to the Vo-Tech school where the students who were studying to become punch-card machine operators(!) would punch the actual cards. If *either* of you made a mistake, your program would not work.

Oblomov reshared this.

in reply to mcc

@tedmielczarek I had to do a lot of parsing of Fortran 77 for my first aerospace internship and was desperately trying to remember what the significance of column 6 was

docs.oracle.com/cd/E19957-01/8…

oh right,
"The first five columns must be blank or contain a numeric label.
Continuation lines are identified by a nonblank, nonzero in column 6."

in reply to mcc

bytes were a thing at that point, but machine architectures were not standardized on multiples of 8 bits.

Plenty of very weird systems with non-standard word lengths and storage record sizes that Fortran would have been intending to support.

in reply to mcc

I seem to recall being told that some DSPs have a byte (= contents of a single memory address) that's 32 bits. So there's also that.
in reply to mcc

For similar reasons, IBM style guides recommended saying "octet" for 8 bits rather than "byte".
in reply to mcc

going to start using "8-bit octet" whenever I mean "byte." As in "that file is only three million eight-bit octets, I can just email it to you"

reshared this

in reply to mcc

@peter_mcmahan but:

SHOULD he think like an RFC author?
or
MUST he think like an RFC author?

mcc reshared this.

in reply to mcc

"octet" makes me feel uncomfortably like i'm at work looking at 3gpp specs, which strongly prefer the term. and they've got me saying it when talking about parts of 3gpp formats.
the rfcs i've used that didn't come from 3gpp-adjacent lands seem to call bytes bytes, and byte means 8 bits unless it's April 1 and time to define utf-9 for compatibility with 36-bit machines that have variable byte sizes
in reply to mcc

Isn't there similar stuff in the C standard w.r.t. CHAR_BIT?

I suppose it is a little more constrained, since they require CHAR_BIT >= 8.

in reply to James Henstridge

@jamesh Yes, although this degree of freedom may have been removed sometime in the last 7 years.
in reply to mcc

ah yes, the standard (of course) 8-bit octet. Not that like those octets in other fancy (french) standards, which might have some other number of bits.
in reply to mcc

"8-bit octet", a term from the Dept. of Redundancy Dept..
in reply to mcc

I love how in the year of our lord 2008, which was recent enough that finding a non-8-bit system was likely more or less impossible, they really do struggle to avoid justifying the choice of 8-bit by simply starting that that's what computers use now.
in reply to mcc

Maybe write your test so that it creates a file that has no read permissions?
in reply to Joe

@not2b This is a good idea but my tests are not executable and I have no test harness. I just have a directory of input files, and the expected output of the input file is encoded in the filename.
@Joe
in reply to mcc

afaik git doesn't store permissions or even modification dates

it only stores wether the file is executable or not

in reply to mcc

Fond memories of the time a big repo (Chrome?) checked a test file with an intentional sha1 collision into their repo and promptly broke git
in reply to mcc

i wonder what would happen if you put an empty file in git with permissions 0400 by like manually editing the tree object, probably nothing good. I should try it.
in reply to Julia Evans

@b0rk *thinks*

i may or may not understand what you're proposing. however someone elsewhere in the thread said that the git on-disk format only represents one "readable?" bit per object (IE, it flattens the three-user-category UNIX permissions model to one category), so if that's true it might be there's not actually a way in the format to do the thing you just said.

in reply to mcc

@b0rk "9-bit unix permission. Only 0755 and 0644 are valid for regular files"
github.com/git/git/blob/master…
in reply to mcc

@b0rk is there a reason to avoid having your testcase make a temporary file with the appropriate permission?
in reply to Ellie

@ellie @b0rk the test case is an inert text file. i do not have executable test cases, and the program is too trivial and temporary to justify setting up a test harness.
in reply to Julia Evans

@b0rk likely nothing good, git only really supports 755 and 644 as modes

github.com/git/git/blob/master…

in reply to tef

@tef yeah I'm sure it's nothing good, I'm just curious about how exactly it would fail

(technically tree objects are text files and you can put "0400" as the permission, it's just not a valid value)

this is the format:

100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 empty.txt

@tef
in reply to mcc

@tef I tried and it seems very hard to get git to do this, it'll just change the permissions to 644 (which is probably for the best)

gist.github.com/jvns/4d27efda9…

@tef
in reply to mcc

but you could rewrite the test to programmatically create a file without read permissions…
in reply to Gretyl

@gretyl thank you for suggestion but

mastodon.social/@mcc/113920886…


@not2b This is a good idea but my tests are not executable and I have no test harness. I just have a directory of input files, and the expected output of the input file is encoded in the filename.

in reply to mcc

I like the cut of your jib all the same 🤗
in reply to mcc

I'm a little late to this thread and I see you've already both solved your issue and received all the usual advice about making your test scripts initialize the file permissions they require, but I don't think I saw anyone mention this slightly more esoteric solution:

github.com/git/git/blob/master…

Git has included since 2006 a contributed post-checkout/post-merge hook script to apply extended permission & user/group ownership settings stored in a .gitmeta file in the repo root. Rarely useful!

in reply to mcc

Someone found a way to run scripts after git clone. github.com/git-hook/post-clone

Tested with the non curl | bash method, and this in my_repo/hooks/post-clone paste.xinu.at/PymqFy/

Questa voce è stata modificata (9 mesi fa)
in reply to mcc

I wonder if git "smudge filters" would fit (they're the do/undo steps that git lfs is built on.) I think they're configured rather than committed though?
in reply to mcc

if you used IBM mainframes, this would all be common knowledge. Mainframes don't typically support simple byte-stream files like Unix does. All mainframe files are structured, record-formatted.

And FORTRAN was born in mainframes, so its file handling reflects that. Usually you read input by telling your program which punchcard device to read.

Questa voce è stata modificata (9 mesi fa)
in reply to mcc

: The definition is circular because files are stocked on circular disks.
in reply to mcc

Spoiler: Planet of the Apes (1968)

Sensitive content

@mcc
in reply to mcc

Is it me or is there a word missing in C924?
in reply to mcc

Ah wait, nevermind.
I should go to bed instead of reading about FORTRAN :').
in reply to mcc

If you are trying to manually control seek and advance with Fortran I/O, you are going to have a very bad day. Fortran I/O is record-oriented and handles a lot of EOL detection and parsing for you. You should not be implementing fprintf() because write() and format() will do basically everything you need.

character(len=32) :: mystr
character(len=😀, parameter :: fmta32 = '(A32)'
read(unit=5, fmt=fmta32) mystr

will read up to 32 ASCII characters from console input into mystr. If you give it fewer characters, the remaining characters are padded with blanks; no need to trim \n. \n is a record separator, not part of the record. You will never see it.

If you give it more than 32 characters, mystr is filled with the first 32 characters and the rest of the characters are ignored. You don't have to worry about \0 because mystr is fixed length; \0 never enters the equation because this isn't C. Try to force a buffer overflow all you want - mystr is 32 characters long by definition and there's nothing anyone can do to change that.

None of this changes if you change the edit specifier in fmta32 to '(A)' - mystr gets at most 32 characters because that's how it's defined.

"But I don't know how long my incoming string is!" I would suggest this is a problem with setting requirements because I very sincerely doubt you can't set a reasonable upper limit on your input. I know, it's heresy in modern computing to set hard limits but that opens us up to lazy wasteful design. Is this input a path? Take the longest path on your filesystem and double it - done. If it breaks for someone, refine requirements and modify the code.

"But then every string I read will be huge and I'll run out of memory!" Fine; read each input string into a big fixed string then use adjustl() and trim() to left-justify and trim trailing spaces and stuff the results into an allocatable character variable. You pay for that with some memory accesses (time) but you save on memory (space).

"But I don't want to spend the time copying the data!" Ok, are you sure you want to do massive amounts of text processing in a language oriented toward numerical computation? You might want to rethink your choice of implementation language. Or punt this function off to another language and link to it via Fortran's interface to C. Or you might be prematurely optimizing - how much do you understand about how your code will be used in practice? Do you have an actual performance problem or a reasonably predictable issue? If not, maybe deal with that if/when it arises.

The same issue arises when dealing with arbitrary-length lists of input. I often deal with this sort of issue by reading input into a linked list, counting the elements, allocating a variable-length array, copying the elements over, then deleting the linked list. There's no standard library of collections and data structures so it's DIY or do without. It sucks but nobody wants to spend unpaid effort to build consensus on what goes into a curated standard library and push it through the Fortran language committee. I'm convinced that the only language features that get added today are HPC conveniences for the nuclear weapons complex (see coarray Fortran) - whatever the people paying for large numbers of Intel Fortran licenses want.

Regardless, Fortran input is straightforward if you are reading mildly formatted text files and picking out short strings and numbers. Pretend you're reading from a stack of punch cards - the length limit is far larger than 80 characters but input goes through an implicit readline() step so you never see \r or \n.

You can also open array of strings as a file and use read() and format() for parsing - the keyword to look for is "internal file". I mean, if you really need to write a recursive descent parser but also have random access to the source lines, you can do it. Scanning is a little weird but it's completely doable.

Output is similarly record-oriented - if you're trying to write without advancing, consider compositing output to an allocatable character string; just write the string when you're done appending to it. The edit specification minilanguage can do basically whatever fprintf can do without nearly as much weird punctuation. Just don't expect it to act like stream I/O; this is an application oriented language not a low-level systems language so you don't get (or generally need) fine seek control. You get rewind() and that's about it.

in reply to arclight

@arclight The input is a grid of ASCII characters.

github.com/mcclure/aoc2024/blo…

I am finding STREAM mode from FORTRAN 2003 entirely adequate so far.

in reply to mcc

I just realized that you could change your display name from McC to McFORTRAN while you're doing this thing, and could have changed to McForth during the Forth week etc.
in reply to Oblomov

@oblomov if i was gonna declare for a C derivative it would be Objective C, and the file extension for that is m so i guess that would be mcm? which doesn't work so well
in reply to mcc

hm I hadn't thought about going by file extension rather than language name. Especially since it'd be, what, mccc for C++?
in reply to mcc

This is the first time I've ever seen a Jupiter Rising reference
in reply to mcc

You may be missing a call to COMMAND_ARGUMENT_COUNT() which gives you the number of arguments intel.com/content/www/us/en/do…

Be aware the Fortran I/O is record-oriented. Streams are a C thing from the early 1970s - you have to jump through a lot of hoops to get stream I/O working in Fortran. It's not worth the hassle.

There's a certain subtle and archaic magic to Fortran I/O and for greatest happiness, do not expect it to work like C. In fact, forget that C even exists.

Array indices start at 1 because normal people start counting at one, not zero. (You can set the index bounds of an array to anything you want but you will absolutely regret it.)

Arrays are in column-major order which is pretty much opposite every other language you've used. This will likely trip you up.

Say you've dimensioned A(2,3,5) - 30 elements total in three dimensions or 'ranks'. You'd be tempted to nest loops outer to inner as i=1:2, j=1:3, and k=1:5 and reference elements as A(i,j,k) in the innermost loop. This will have awful memory lookup performance because i is the fastest moving index, followed by j, followed by k. You will typically see nested loops arranged like

do k = 1, 5
do j = 1, 3
do i = 1, 2
A(i,j,k) = whatever()
end do
end do
end do

Note that if whatever() returns a scalar, you could just do

A(1:2, 1:3, 1:5) = whatever()

or

A(:,:,😀 = whatever()

or just

A = whatever()

And get the same behavior without having to worry about efficient memory access. Array operations are your friend - welcome to vectorized (SIMD) optimization with zero effort on your part. Need to initialize A to zero? `A = 0.0` and you're done.

Oh, and numeric types matter. A lot. 3 / 2 = 1, not 1.5. Why? Because integer divided by integer yields an integer. 3 is different from 3.0 which is different from 3.0d0. More formally, these three literals are 3_int32, 3.0_real32, and 3.0_real64 (iso_fortran_env contains definitions of 'kinds' for each of the numeric types.) Type and kind inference and compatibility rules are another rabbit hole of complexity. Remember your discovery of the aint() function? There is also dint() which converts real64 (aka 'double precision') to int32. aint() and dint() are deprecated; int() has some multiple dispatch magic to send whatever numeric type you pass in to aint(), dint(), etc. under the hood. This is another rabbit hole of the Fortran type and object model but for now, all you need to remember is to use the generic forms of int() and real() and to be careful specifying numeric literals. This is a language that cares very deeply about numeric precision and it expects you to be explicit about what you want. It's very good about giving you what you ask for but it also expects that you know what you're asking for. Every new Fortran programmer almost immediately gets bitten by the 3 / 2 = 1 issue. Computer math is very different from formal math, ℤ is not a subset of ℝ here - they are distinct and not necessarily interchangeable or compatible.

This brain dump is getting way too long. Sorry about that.

There are file units, not file handles. FORTRAN was developed for the the IBM 704 which did not have a CRT (in that era, a CRT was more likely to be a memory device not a display). Historically, units may be console, keyboard, printer, tape (magnetic or paper), disk, card punch, card reader, drum, or disk. By convention, console input is unit 5, console output is unit 6. You've already discovered iso_fortran_env which formalizes this convention with standard names.

iso_fortran_env is basically half of Fortran's standard library. There are a few others, mainly relating to IEEE math and C types for cross-language programming.

One of the irritations with Fortran was the need to manually keep track of which unit numbers were previously assigned or in use (like 5 and 6). Good practice today is to define an integer variable to hold the unit number and pass that to open() under as the newunit argument. open() will find a free file unit and store it in the variable which you'll basically use as a file handle.

Fortran is very good about named arguments to functions and I find it helpful to be a little pedantic and wordy to explicitly name all the arguments passed to functions. `read(6, 10) J` becomes `read(unit=6, fmt=10) J` so it's clear which is the unit number and which is the edit descriptor (another deep rabbit hole of Fortran I/O...)

in reply to arclight

@arclight The problem I had was not the number of arguments but rather getting the length of a single argument
in reply to mcc

you can do command-line arguments in Fortran now? Sheesh, my wasted years of wrapping Fortran code in DCL/Shell scripts that renamed input files to FORT.N input units and renaming output files to something sensible on exit ...
Questa voce è stata modificata (9 mesi fa)
in reply to mcc

you made a similar observation about how nobody actually knows what Intel Syntax is that isn't word of mouth. how does anyone learn programming in anything these days
in reply to mcc

FORTRAN's write statement and format codes are a bit akin to dd's command line args ... things like the 'h' format character being for a "Hollerith" field i.e. fixed width text in your output. write(unit,*) is kind of ahead of its time in a way, it works a little like cout << foo in c++. If your compiler doesn't have unformatted write you have to do a format string somewhat like printf.
in reply to mcc

I guess this weirdness would be solved by following the era-correct way to approach the language, which would be to follow a book.
in reply to mcc

I wouldn’t describe C as cleaned up Fortran really? I’d say Fortran has more in common with BASIC than with C. Modern Fortran is a nice language for what it’s designed for (linear algebra especially); I wouldn’t want to use it for something dealing mostly with strings (for reasons you’re encountering).
in reply to Tachibana Kanade

@h0m54r well if i have to I can treat strings as vectors of numbers between 0 and 127
Unknown parent

mastodon - Collegamento all'originale
mcc
@capeta I think they assume the reader is an implementor. If I were implementing a FORTRAN compiler, I think I would ABSOLUTELY LOVE the formatting and wording of this manual. But that is not what I am doing today.
Unknown parent

mastodon - Collegamento all'originale
mcc
@capeta The above looks to me like BNF. I cannot discriminate BNF from EBNF by sight without consulting wikipedia.
Unknown parent

mastodon - Collegamento all'originale
mcc
@glent Yes, the STREAM feature is an extension to the language, and GNU's documentation authors seem vaguely uncomfortable with it.
Unknown parent

glitchsoc - Collegamento all'originale
arclight

@Petra If you're up for reading git history, a few years ago I methodically modernized a F66 text adventure to F2018. gitlab.com/apthorpe/Castleques…

Refactoring away 750+ GOTO statements in the main game loop was satisfying but the last 10 or so took some pretty severe architectural modification. This code is probably a worst case scenario for untangling IF/GOTO logic.

The binary save file format from 1979 should still work and the game should play about identically to the original, though it accepts both upper and lower case commands now and the output defaults to plain text without the ASA carriage control characters. Builds on Mac, Windows, and Linux with identical source code (no #ifdef nonsense) and will create native installers for each platform if the appropriate packaging utilities are installed.

Unknown parent

mastodon - Collegamento all'originale
mcc
@aadmaa @hyc i do not at this time require assistance
in reply to mcc

I really love this challenge, with all the unexpected roadblocks and lack of features we take for granted in modern languages.