Pascal

2025-06-28

I started to write programs again in Pascal.

I have learned to accept Lazarus a bit, but tried a bit to get a nice Emacs setup first. But, I would switch between debugging the major problem I had with the LSPs (which I learned uh-lot from) while rewriting this text editor in Pascal: https://github.com/antirez/kilo While I am not finished yet, and I am slow at it, it's been interesting.

I am focused only on procedural Pascal. The Object Pascal extensions are a different beast entirely. This is the similar argument for any OOP language, whether you need it or not. However, for my education, I will write an Object Pascal program (probably convert something else.)

Since Pascal was my first proper programming language I learned, it did dig into my head, even if I didn't work in it at all (and granted, it lost a lot of popularity.) While Pascal is certainly not the first thing that even processor makers like Intel work on (like, since they have their own compilers), it can produce pretty small and zippy code.

I chose the text editor as a simple example writing an equivalent program from C, but that could be easily rewritten in Python, for example. The bigger test is if I could write a reasonable operating system kernel in Pascal. It's been done.

Observations thus far

Pascal (and it's descendants, particuarly Ada) is a much more type-safe language than C. Practically, when rewriting C logic to Pascal, some C idioms don't make sense in a type safe way. Some observations so far:

  1. := and = vs. = and == ... Pascal has always done this better in my opinion.
  2. nil is not a keyword, but a pointer type. Setting a record type to nil throws a compliation error. I didn't think much of that, but this means that you must explicitly use pointers if you want to nil them. Objects are implicitly pointers, but records are not. You don't use much pointer syntax as you do in C. If you want to change a record variable in a function, you can add `var in front of a parameter in a procedure or function to pass-by-reference.
  3. For example, erow *row = (filerow >= E.numrows) ? NULL : &E.row[filerow]; looks like an immediate no-no if you use records, pass-by-reference and no pointers.
    1. First, there is no tertiary operators in Pascal.
    2. Second, it's clearer anyway to create a value that is explicitly "non-existing" (just like Option types). That would be the NULL here.
    3. This ends up being my contribution here.
      row := EmptyRow;
      if fileRow < E.numRows then row := E.row[fileRow];
      
  4. Declaring variables on the top might be really annoying, but I always thought in the back of my head this is good. Now doing this deliberately has made me rethink a little how I should be writing functions. I feel like refactoring procedures at some point to make the variable declarations more local, using nested procedures. While reading a function's source straight through makes it easy to read code for some, it really does encourage a style of 'throwaway' variables that start to make up the logic of your code. In the C code I am looking at, I can see that habit, that in one case, it threw me off, because the variable was named the same, but it started to serve a different intent. Declaring variables in logic helps towards creating 'meandering' functions: you either need a bigger screen for these functions or you sit and rewrite everything to capture the flow nicer. (This is not a 'clean code' argument, it's a 'I am lazy, I don't want to read this garbage' one, for the next person who would look at any code.)
  5. Pascal can get tedious to write. But, maybe that's good. I get confused quickly over "bad" patterns.

Going forward

In the past, I gave up on projects, so I am trying to be deliberate here. I just want to make stuff, but with things no one likes to use. So I am slowly finishing my text editor and make weekend-progress. As I write this, I cleaned up cursor moving and new line additions. The C code uses memset to adjust rows for new lines. I think my approach is simpler (iterate through each line backwards and set the current line to the last one), but that's not a C or Pascal thing. It's probably more efficient to memset() and it's there to use in the Unix package but who cares.

I am looking at other softwares to convert, but will not settle until this one is done.

In the meanwhile, links:

In: pascal