Pascal is a great easy language with strong typing. It was great at protecting you from yourself. It was a great language for students. It had strong typing that was very solid. You could not easily subvert it. (This is the original, standard Pascal; I'll talk about Turbo later.)

You couldn't even run past the end of an array, because the size of an array was part of the type. You couldn't even compile code that tried to access past the end of an array.

But that was a huge problem. The type system was too strict. Take those arrays, for example. You could not have a variable-sized array, because the size was part of the type, so there was no possible type for that array to have. You literally could not talk about such a thing.

This bit me, for example, where we we trying to do a numerical simulation of EM wave interference patterns on a 2D grid, with the user specifying the size of the grid. We literally were not allowed to create a 2D array with size determined at runtime. So the initial implementation simulated it with a doubly-linked list of allocated points. That solved the type issue, but it had at least two negative results. First, in a node, the next and previous links took as much memory as the actual node data, so it was very memory inefficient. Second, having to walk a pointer to N nodes further to refer to the point directly below you on the grid was both inefficient and error-prone.

We finally improved it by allocating a fixed-sized 2D grid that was as big as we could allocate (we knew at compile time how much memory was available on the machine we were running on) and only using the part that was within the bounds the user specified, but that was also wasteful.

The runtime gave you certain functions that would deal with variable-length strings, but if you found those functions inadequate, you could not implement your own, because you could not talk about variable-length arrays.

And it wasn't just arrays. You could write only the things that fit within Wirth's vision of what you should be allowed to write. Writing your own memory allocator? What's going to be the returned type? Writing to memory-mapped hardware? No way, not allowed.

To write to memory-mapped hardware, we literally had to call a subroutine written in assembly - at which point, we lost all type safety. In the name of the language being as safe as possible, we were forced to do something completely unsafe in order to be able to work at all. (That lack of type safety caused a crash when something changed.)

That was the original Pascal. Everyone who used it seriously saw that it was inadequate for real work, so it got extended in order to be usable. But the problem is that everyone extended it in different ways. Turbo Pascal had extensions, but they weren't going to compile on other compilers - at least not until Turbo became the dominant compiler, which took a while. Code written using other compiler extensions would not compile on Turbo unless Turbo adopted their extensions - which never happened, at least so far as I know. You could not write portable software that did anything outside the standard Pascal straightjacket. (Of course, if you're writing to memory-mapped I/O, you're probably not portable to any other hardware anyway...)

For a more extended discussion of this, read "Why Pascal Is Not My Favorite Programming Language" (https://www.cs.virginia.edu/~evans/cs655/readings/bwk-on-pas...). It's by Brian Kernighan (yes, that Kernighan), but it's not a hit piece. He wrote a book called "Software Tools" with P. J. Plaugher, in Ratfor (a Fortran pre-processor). After Pascal came out, he re-wrote the book using Pascal, and then he wondered why it was so hard. Pascal should have been far easier to write in that Ratfor. Why wasn't it? The article is trying to answer that question. It's still an interesting read if you want to know why Pascal didn't really catch on.