Yep, it's just a language. The thing I find oddest about it is how it handles subroutines. A long time ago, I attempted to figure out how I would translate from COBOL to assembly and figured out that the only way to actually do so and duplicate the behavior I'd see with COBOL would be to not use a stack, but instead have a little epilog at the end of each paragraph that was the last paragraph of a perform statement. In pseudo code, it would look something like this.
PERFORM PARAGRAPH_A THRU PARAGRAPH_B.
CODE RESUMES HERE.
Load address of RESUME in register temp1
Store register temp1 in PARAGRAPH_B_EPILOG
Jump to PARAGRAPH_A
code continues here....
Load register temp1 with contents of PARAGRAPH_B_EPILOG
Load address of PARAGRAPH_C in register temp2
Store register temp2 in PARAGRAPH_B_EPILOG
Jump to address in register temp1
Somewhere in data
WORD VALUE initialized to address of PARAGRAPH_C
Really odd and didn't require a stack. But would account for the behavior observed whenever some did a PERFORM statement and somewhere within the target paragraphs did a GO TO to some other section of code. If they did that, it would "look" as if things were OK, but if for some reason the code execution path later crossed the boundary between the last named paragraph in the PERFORM statement and the next paragraph, the flow of control would suddenly jump to the statement following the PERFORM statement. It would also account for the situations where PERFORM statements would be used on overlapping ranges of paragraphs. Definitely an odd language, but understandable since the S/360 didn't have a stack.