RCSNUSP/COBOL: Difference between revisions

m
Fixed syntax highlighting.
m (Added works with tag.)
m (Fixed syntax highlighting.)
 
(6 intermediate revisions by one other user not shown)
Line 1:
This an SNUSP interpreter written in COBOL. It supports Modular SNUSP but not yetand Bloated SNUSP.
 
The file path to the code is passed as a parameter to the program. The file is assumed to be a text file with lines having a maximum length of 100 characters. It is also assumed the file will not be more than 1024 lines long.
 
The memory is a 2048 byte array and, the stack has a size of 512 and there is a maximum of 16 threads.
 
{{works with|GNU Cobol|2.0}}
 
<lang cobol> >>SOURCE FREE
snusp.cob:
<syntaxhighlight lang="cobol"> >>SOURCE FREE
IDENTIFICATION DIVISION.
PROGRAM-ID. snusp-interpreter.
 
ENVIRONMENT DIVISION.
CONFIGURATION SECTION.
REPOSITORY.
FUNCTION find-initial
FUNCTION ALL INTRINSIC
.
DATA DIVISION.
WORKING-STORAGE SECTION.
COPY "dd-program-arguments.cpy".
COPY "dd-code-area.cpy".
01 program-state-flag PIC X VALUE SPACE.
88 program-ok VALUE SPACE.
88 empty-stack VALUE "E".
88 out-of-code-space VALUE "O".
01 memory-area.
03 memory-rows OCCURS 1024 TIMES.
05 memory-cols OCCURS 1024 TIMES.
07 memory-cell USAGE BINARY-CHAR.
07 memory-cell-char REDEFINES memory-cell PIC X.
01 num-threads PIC 99 COMP VALUE 1.
01 threads-data-area.
03 threads-data OCCURS 1 TO 16 TIMES
DEPENDING ON num-threads
INDEXED BY thread-idx.
05 thread-status-flag PIC X VALUE SPACE.
88 thread-started VALUE "Y".
05 call-stack.
07 calls OCCURS 512 TIMES
INDEXED BY stack-idx.
09 direction PIC X.
88 up-dir VALUE "U".
88 down-dir VALUE "D".
88 left-dir VALUE "L".
88 right-dir VALUE "R".
09 instruction-ptr.
11 ip-line USAGE INDEX.
11 ip-char USAGE INDEX.
05 memory-pointer.
07 row-idx USAGE INDEX.
07 col-idx USAGE INDEX.
01 input-char PIC X.
01 current-thread-idx USAGE INDEX.
PROCEDURE DIVISION.
000-main SECTION.
001-prepare-code.
CALL "parse-arguments" USING program-arguments
IF code-file-path = SPACES
DISPLAY "No file path specified."
STOP RUN
END-IF
CALL "read-code-file" USING CONTENT code-file-path, REFERENCE code-area
 
MOVE find-initial(code-area) TO instruction-ptr (1, 1)
.
010-interpret-code.
SET right-dir (1, 1) TO TRUE
SET stack-idx, thread-idx, row-idx (1), col-idx (1) TO 1
PERFORM UNTIL num-threads = 0
PERFORM VARYING thread-idx FROM 1 BY 1 UNTIL thread-idx > num-threads
PERFORM 100-move-instruction-ptr
IF out-of-code-space
PERFORM 200-stop-thread
END-IF
EVALUATE code-chars (ip-line (thread-idx, stack-idx),
ip-char (thread-idx, stack-idx))
*> Core SNUSP
WHEN "<" *> LEFT
SET col-idx (thread-idx) DOWN BY 1
WHEN ">" *> RIGHT
SET col-idx (thread-idx) UP BY 1
WHEN "+" *> INCR
ADD 1 TO
memory-cell (row-idx (thread-idx), col-idx (thread-idx))
WHEN "-" *> DECR
SUBTRACT 1 FROM
memory-cell (row-idx (thread-idx), col-idx (thread-idx))
WHEN "." *> WRITE
IF NOT write-numbers
DISPLAY memory-cell-char (row-idx (thread-idx),
col-idx (thread-idx))
ELSE
DISPLAY memory-cell (row-idx (thread-idx),
col-idx (thread-idx))
END-IF
WHEN "," *> READ
IF NOT read-numbers
ACCEPT memory-cell-char (row-idx (thread-idx),
col-idx (thread-idx))
ELSE
ACCEPT memory-cell (row-idx (thread-idx),
col-idx (thread-idx))
END-IF
*> LURD (/ is not used as it is mucks up syntax highlighting.)
WHEN X"5C"
EVALUATE TRUE
WHEN up-dir (thread-idx, stack-idx)
SET left-dir (thread-idx, stack-idx) TO TRUE
WHEN down-dir (thread-idx, stack-idx)
SET right-dir (thread-idx, stack-idx) TO TRUE
WHEN left-dir (thread-idx, stack-idx)
SET up-dir (thread-idx, stack-idx) TO TRUE
WHEN right-dir (thread-idx, stack-idx)
SET down-dir (thread-idx, stack-idx) TO TRUE
END-EVALUATE
WHEN "/" *> RULD
EVALUATE TRUE
WHEN up-dir (thread-idx, stack-idx)
SET right-dir (thread-idx, stack-idx) TO TRUE
WHEN down-dir (thread-idx, stack-idx)
SET left-dir (thread-idx, stack-idx) TO TRUE
WHEN left-dir (thread-idx, stack-idx)
SET down-dir (thread-idx, stack-idx) TO TRUE
WHEN right-dir (thread-idx, stack-idx)
SET up-dir (thread-idx, stack-idx) TO TRUE
END-EVALUATE
WHEN "!" *> SKIP
PERFORM 100-move-instruction-ptr
WHEN "?" *> SKIPZ
IF memory-cell (row-idx (thread-idx), col-idx (thread-idx))
= 0
PERFORM 100-move-instruction-ptr
END-IF
*> Modular SNUSP
WHEN "@" *> ENTER
*> Push current direction and IP location onto call stack
MOVE calls (thread-idx, stack-idx)
TO calls (thread-idx, stack-idx + 1)
SET stack-idx UP BY 1
WHEN "#" *> LEAVE
IF stack-idx <> 1
*> Pop direction and IP location off call stack and
*> advance the IP one step.
SET stack-idx DOWN BY 1
PERFORM 100-move-instruction-ptr
ELSE
PERFORM 200-stop-thread
END-IF
*> Bloated SNUSP
WHEN ":" *> UP
SET row-idx (thread-idx) UP BY 1
WHEN ";" *> DOWN
SET row-idx (thread-idx) DOWN BY 1
WHEN "&" *> SPLIT
*> Create a new thread
ADD 1 TO num-threads
MOVE call-stack (thread-idx) TO call-stack (num-threads)
MOVE memory-pointer (thread-idx) TO call-stack (num-threads)
SET thread-started (thread-idx) TO TRUE
WHEN "%" *> RAND
COMPUTE memory-cell (row-idx (thread-idx),
col-idx (thread-idx)) =
FUNCTION MOD(FUNCTION RANDOM,
memory-cell (row-idx (thread-idx),
col-idx (thread-idx)) + 1)
WHEN OTHER
CONTINUE
END-EVALUATE
IF out-of-code-space
PERFORM 200-stop-thread
END-IF
END-PERFORM
END-PERFORM
.
099-terminate.
GOBACK
.
100-move-instruction-ptr SECTION.
EVALUATE TRUE
WHEN up-dir (thread-idx, stack-idx)
SET ip-line (thread-idx, stack-idx) DOWN BY 1
WHEN down-dir (thread-idx, stack-idx)
SET ip-line (thread-idx, stack-idx) UP BY 1
WHEN left-dir (thread-idx, stack-idx)
SET ip-char (thread-idx, stack-idx) DOWN BY 1
WHEN right-dir (thread-idx, stack-idx)
SET ip-char (thread-idx, stack-idx) UP BY 1
END-EVALUATE
.
199-exit.
EXIT
.
200-stop-thread SECTION.
*> Shift data from following threads over stopped thread.
SET current-thread-idx TO thread-idx
PERFORM VARYING thread-idx FROM thread-idx BY 1
UNTIL NOT thread-started (thread-idx + 1)
OR thread-idx = num-threads
MOVE threads-data (thread-idx + 1) TO threads-data (thread-idx)
END-PERFORM
SUBTRACT 1 FROM num-threads
SET thread-idx TO current-thread-idx
.
299-exit.
EXIT
.
END PROGRAM snusp-interpreter.
 
 
IDENTIFICATION DIVISION.
PROGRAM-ID. parse-arguments.
 
DATA DIVISION.
LOCAL-STORAGE SECTION.
01 num-args PIC 9 COMP.
01 arg-num PIC 9 COMP.
01 arg PIC X(100).
 
COPY "dd-flag-constants.cpy".
 
01 program-flag PIC X.
88 help-flag VALUE Help-Flag-Char.
88 read-num-flag VALUE Read-Num-Flag-Char.
88 write-num-flag VALUE Write-Num-Flag-Char.
 
LINKAGE SECTION.
COPY "dd-program-arguments.cpy".
 
PROCEDURE DIVISION USING program-arguments.
ACCEPT num-args FROM ARGUMENT-NUMBER
IF num-args = 0
CALL "display-help"
STOP RUN
END-IF
 
PERFORM VARYING arg-num FROM 1 BY 1 UNTIL arg-num > num-args
DISPLAY arg-num UPON ARGUMENT-NUMBER
ACCEPT arg FROM ARGUMENT-VALUE
EVALUATE TRUE
WHEN arg (1:1) = Flag-Indicator
MOVE arg (2:1) TO program-flag
EVALUATE TRUE
WHEN help-flag
CALL "display-help"
STOP RUN
WHEN read-num-flag
SET read-numbers TO TRUE
WHEN write-num-flag
SET write-numbers TO TRUE
WHEN OTHER
DISPLAY "Flag '" FUNCTION TRIM(arg) "' not recongnized."
END-EVALUATE
WHEN code-file-path <> SPACES
DISPLAY "Argument " arg-num " ignored - only one source code "
"file can be interpreted."
WHEN OTHER
MOVE arg TO code-file-path
END-EVALUATE
END-PERFORM
.
END PROGRAM parse-arguments.
 
 
IDENTIFICATION DIVISION.
PROGRAM-ID. read-code-file.
 
ENVIRONMENT DIVISION.
Line 16 ⟶ 303:
ORGANIZATION LINE SEQUENTIAL
FILE STATUS code-file-status.
 
DATA DIVISION.
FILE SECTION.
FD code-file.
01 code-record PIC X(100).
 
WORKINGLOCAL-STORAGE SECTION.
01 code-file-path PIC X(100).
01 code-file-status PIC 99.
88 end-of-code-file VALUE 10.
 
LINKAGE SECTION.
01 num-lines PIC 9(4) COMP.
01 COPY "dd-code-area.cpy".
03 code-lines OCCURS 1 TO 1024 TIMES
DEPENDING ON num-lines
INDEXED BY line-idx.
05 code-chars PIC X OCCURS 100 TIMES
INDEXED BY char-idx.
 
01 programcode-statefile-flagpath PIC X VALUE SPACE PIC X(100).
88 program-ok VALUE SPACE.
88 empty-stack VALUE "E".
88 out-of-code-space VALUE "O".
 
PROCEDURE DIVISION USING code-file-path, code-area.
01 array-area.
03 array OCCURS 2048 TIMES
INDEXED BY table-idx.
05 array-table USAGE BINARY-CHAR.
05 array-table-char REDEFINES array-table PIC X.
 
01 call-stack-area.
03 calls OCCURS 512 TIMES INDEXED BY stack-idx.
05 direction PIC X.
88 up-dir VALUE "U".
88 down-dir VALUE "D".
88 left-dir VALUE "L".
88 right-dir VALUE "R".
05 ip-line USAGE INDEX.
05 ip-char USAGE INDEX.
01 input-char PIC X.
 
PROCEDURE DIVISION.
DECLARATIVES.
code-file-error SECTION.
USE AFTER ERROR ON code-file.
DISPLAY "An error occurred while using " FUNCTION TRIM(code-file-path)
DISPLAY "Error code " code-file-status
DISPLAY "Error triggered at " FUNCTION TRIM(FUNCTION EXCEPTION-LOCATION)
" by " FUNCTION EXCEPTION-STATEMENT "."
DISPLAY "The program will terminate."
 
GOBACKSTOP RUN
.
END DECLARATIVES.
 
000-main SECTION.
ACCEPT code-file-path FROM COMMAND-LINE
 
*> Store contents of file into memory.
OPEN INPUT code-file
PERFORM VARYING line-idx FROM 1 BY 1 UNTIL end-of-code-file
ADD 1 TO num-lines
READ code-file INTO code-lines (line-idx)
NOT AT END
ADD 1 TO num-lines
AT END
SUBTRACT 1 FROM num-lines
EXIT PERFORM
END-READ
END-PERFORM
 
CLOSE code-file
.
END PROGRAM read-code-file.
*> Search for any initial charcters.
 
PERFORM VARYING ip-line (1) FROM 1 BY 1 UNTIL ip-line (1) > num-lines
 
AFTER ip-char (1) FROM 1 BY 1 UNTIL ip-char (1) > 100
IDENTIFICATION DIVISION.
IF code-chars (ip-line (1), ip-char (1)) = "$"
FUNCTION-ID. find-initial.
 
DATA DIVISION.
LINKAGE SECTION.
COPY "dd-code-area.cpy".
 
01 instruction-ptr.
03 ip-line USAGE INDEX.
03 ip-char USAGE INDEX.
 
PROCEDURE DIVISION USING code-area RETURNING instruction-ptr.
PERFORM VARYING ip-line FROM 1 BY 1 UNTIL ip-line > num-lines
AFTER ip-char FROM 1 BY 1 UNTIL ip-char > 100
IF code-chars (ip-line, ip-char) = "$"
EXIT PERFORM
END-IF
END-PERFORM
*> Set position to first char if no initial characters were found.
IF ip-line (1) > num-lines
SET lineip-idxline, charip-idxchar TO 1
END-IF
.
END FUNCTION find-initial.
*> Interpret the code while the instruction pointer remains in code space.
SET right-dir (1) TO TRUE
SET stack-idx TO 1
PERFORM UNTIL NOT program-ok
PERFORM 100-move-instruction-ptr
IF out-of-code-space
EXIT PERFORM
END-IF
EVALUATE code-chars (ip-line (stack-idx), ip-char (stack-idx))
*> Core SNUSP
WHEN ">"
SET table-idx UP BY 1
 
WHEN "<"
SET table-idx DOWN BY 1
 
IDENTIFICATION DIVISION.
WHEN "+"
PROGRAM-ID. display-help.
ADD 1 TO array-table (table-idx)
 
DATA DIVISION.
WHEN "-"
WORKING-STORAGE SECTION.
SUBTRACT 1 FROM array-table (table-idx)
COPY "dd-flag-constants.cpy".
 
01 Tab-Char WHEN CONSTANT X".09".
DISPLAY array-table-char (table-idx)
 
PROCEDURE DIVISION.
WHEN ","
DISPLAY "This is a interpreter for SNUSP written in COBOL."
ACCEPT array-table-char (table-idx)
DISPLAY "The file path to the source code should be specified as a "
"command-line argument."
DISPLAY "This program supports the following flags as arguments:"
DISPLAY Tab-Char Flag-Indicator Help-Flag-Char ": Displays this help "
"message."
DISPLAY Tab-Char Flag-Indicator Write-Num-Flag-Char ": Display memory "
"contents as numbers."
DISPLAY Tab-Char Flag-Indicator Read-Num-Flag-Char ": Reads a byte to "
"memory as a number."
.
END PROGRAM display-help.</syntaxhighlight>
 
dd-code-area.cpy:
WHEN X"5C" *> Backslash mucks up syntax highlighting
<syntaxhighlight lang="cobol">01 code-area.
EVALUATE TRUE
03 num-lines WHEN up-dir PIC 9(stack-idx4) COMP.
03 code-lines SET left-dir (stack-idx) OCCURS 1 TO TRUE1024 TIMES
WHEN down-dir (stack DEPENDING ON num-idx)lines
SET right-dir (stack-idx) TO TRUE INDEXED BY line-idx.
05 code-chars WHEN left-dir (stack-idx) PIC X OCCURS 100 TIMES.</syntaxhighlight>
SET up-dir (stack-idx) TO TRUE
WHEN right-dir (stack-idx)
SET down-dir (stack-idx) TO TRUE
END-EVALUATE
 
dd-flag-constants.cpy:
<syntaxhighlight lang="cobol">01 Flag-Indicator CONSTANT "-".
WHEN "/"
01 Help-Flag-Char EVALUATE TRUE CONSTANT "h".
01 Read-Num-Flag-Char WHENCONSTANT up-dir (stack-idx)"r".
01 Write-Num-Flag-Char CONSTANT SET right-dir (stack-idx) TO TRUE"w".</syntaxhighlight>
WHEN down-dir (stack-idx)
SET left-dir (stack-idx) TO TRUE
WHEN left-dir (stack-idx)
SET down-dir (stack-idx) TO TRUE
WHEN right-dir (stack-idx)
SET up-dir (stack-idx) TO TRUE
END-EVALUATE
WHEN "!"
PERFORM 100-move-instruction-ptr
WHEN "?"
IF array-table (table-idx) = 0
PERFORM 100-move-instruction-ptr
END-IF
 
dd-program-arguments.cpy:
*> Modular SNUSP
<syntaxhighlight lang="cobol">01 program-arguments.
WHEN "@"
03 code-file-path *> Push current direction and IP location onto callPIC stackX(100).
03 read-flag MOVE calls (stack-idx) TO calls (stack-idx +PIC 1)X.
88 read-numbers SET stack-idx UPVALUE BY"N". 1
03 write-flag PIC X.
88 write-numbers WHEN VALUE "#N".</syntaxhighlight>
IF stack-idx <> 1
*> Pop direction and IP location off call stack and advance
*> the IP one step.
SET stack-idx DOWN BY 1
PERFORM 100-move-instruction-ptr
ELSE
SET empty-stack TO TRUE
END-IF
 
*> Bloated SNUSP
WHEN OTHER
CONTINUE
END-EVALUATE
END-PERFORM
 
GOBACK
.
100-move-instruction-ptr SECTION.
EVALUATE TRUE
WHEN up-dir (stack-idx)
SET ip-line (stack-idx) DOWN BY 1
WHEN down-dir (stack-idx)
SET ip-line (stack-idx) UP BY 1
WHEN left-dir (stack-idx)
SET ip-char (stack-idx) DOWN BY 1
WHEN right-dir (stack-idx)
SET ip-char (stack-idx) UP BY 1
END-EVALUATE
.
END PROGRAM snusp-interpreter.</lang>
9,476

edits