├── .clang-format ├── .github └── workflows │ └── c-cpp.yml ├── .gitignore ├── CMakeLists.txt ├── LICENSE ├── Makefile ├── README.md ├── compiler ├── CMakeLists.txt ├── Makefile ├── x1algc.c └── x1algol.pas ├── doc ├── algol-encoding.md ├── algol60-comparison-for-x1-and-x8.pdf ├── algol60-compiler-for-x1.pdf ├── algol60-revised-report.pdf ├── algol60-translator-for-x1.pdf ├── description-of-algol60.pdf ├── dijkstra-phd-thesis.pdf ├── flexowriter-punching-code.jpg ├── instruction-encoding.md ├── library-procedures.md ├── mr35.pdf ├── mr81.pdf ├── pords-and-pards.md ├── the-x1-computer.pdf ├── x1-binary-instructions.png └── x1-binary-p-orders.png ├── examples ├── README.md ├── beer.a60 ├── bulls_and_cows.a60 ├── disarium.a60 ├── hanoi.a60 ├── hello.a60 ├── lisp.a60 ├── lisp.md ├── lisp.sh ├── magic_square.a60 ├── man_or_boy.a60 ├── mersenne.a60 ├── outer_planets.a60 ├── outer_planets.md ├── outer_planets.sh ├── palindromic_primes.a60 ├── pentomino.a60 ├── pentomino.md ├── pentomino3x20.sh ├── pentomino4x15.sh ├── pentomino5x12.sh ├── pentomino6x10.sh ├── perfect_numbers.a60 ├── quinio.a60 ├── quinio.md ├── sieve.a60 ├── sqrt_test.a60 ├── steady_squares.a60 ├── sum.a60 ├── time.a60 └── whetstone.a60 ├── library ├── CMakeLists.txt ├── Makefile ├── absfixt.lib ├── arctan.lib ├── even.5tr ├── even.lib ├── even.src ├── fixt.lib ├── flex-to-algol.c ├── flot.lib ├── from5track.cc ├── mcp4.lib ├── objfile.cc ├── printtext.5tr ├── printtext.lib ├── printtext.src ├── prsym.a60 ├── prsym.lib ├── prsym.src ├── random.a60 ├── random.lib ├── random.src ├── resym.lib ├── resym.src ├── setrandom.a60 ├── setrandom.lib ├── setrandom.src ├── sum.5tr ├── sum.a60 ├── sum.lib ├── sum.src ├── timeofday.a60 ├── timeofday.lib ├── timeofday.src ├── x1algol.lib └── zztail.lib ├── scripts ├── decode.pl ├── restrop.pl ├── underline.pl └── x1-disasm.py ├── simulator ├── CMakeLists.txt ├── byte_pointer.h ├── encoding.cpp ├── encoding.h ├── input.cpp ├── machine.cpp ├── machine.h ├── main.cpp ├── opc.h ├── opcodes.cpp ├── processor.cpp ├── processor.h ├── trace.cpp ├── virtual_stack.cpp ├── virtual_stack.h ├── x1_arch.cpp └── x1_arch.h └── tests ├── CMakeLists.txt ├── arch_test.cpp ├── arith_test.cpp ├── array_test.cpp ├── boolean_test.cpp ├── cli_test.cpp ├── fixture.cpp ├── fixture.h ├── function_test.cpp ├── googletest.xml ├── label_test.cpp ├── loop_test.cpp ├── machine_test.cpp ├── man_or_boy.cpp ├── print123.a60 ├── print123.x1 ├── print_test.cpp └── procedure_test.cpp /.clang-format: -------------------------------------------------------------------------------- 1 | 2 | --- 3 | BasedOnStyle: Google 4 | 5 | # 6 | # Indent by four columns. 7 | # 8 | IndentWidth: 4 9 | 10 | # 11 | # Limit source width by 100 columns. 12 | # 13 | ColumnLimit: 100 14 | 15 | # 16 | # The brace breaking style: 17 | # attach braces to surrounding context, but break before functions. 18 | # 19 | BreakBeforeBraces: WebKit 20 | 21 | # 22 | # For case labels, use the same indentation level as for the switch statement. 23 | # 24 | IndentCaseLabels: false 25 | 26 | # 27 | # Put spaces after { and before } in initializers. 28 | # 29 | Cpp11BracedListStyle: false 30 | 31 | # 32 | # For access modifiers (like public:), 33 | # use the same indentation level as the class statement. 34 | # 35 | AccessModifierOffset: -4 36 | 37 | # 38 | # Align pointers to the right, like: int *a; 39 | # 40 | DerivePointerAlignment: false 41 | PointerAlignment: Right 42 | 43 | # 44 | # Short functions, loops or ifs should be split into multiple lines. 45 | # 46 | AllowShortFunctionsOnASingleLine: InlineOnly 47 | AllowShortIfStatementsOnASingleLine: false 48 | AllowShortLoopsOnASingleLine: false 49 | 50 | # 51 | # Break inheritance list and constructor initializers before colon. 52 | # 53 | BreakInheritanceList: BeforeColon 54 | BreakConstructorInitializers: BeforeColon 55 | ConstructorInitializerAllOnOneLineOrOnePerLine: false 56 | 57 | # 58 | # Align trailing comments. 59 | # 60 | AlignTrailingComments: true 61 | SpacesBeforeTrailingComments: 1 62 | 63 | # 64 | # Allow packing of multiple function definition’s parameters per line. 65 | # 66 | BinPackParameters: true 67 | AllowAllParametersOfDeclarationOnNextLine: false 68 | 69 | AlignConsecutiveAssignments: true 70 | AlignConsecutiveMacros: true 71 | -------------------------------------------------------------------------------- /.github/workflows/c-cpp.yml: -------------------------------------------------------------------------------- 1 | name: Build and Test 2 | 3 | on: 4 | push: 5 | branches: [ "main" ] 6 | pull_request: 7 | branches: [ "main" ] 8 | 9 | jobs: 10 | build: 11 | 12 | runs-on: ubuntu-latest 13 | 14 | steps: 15 | - uses: actions/checkout@v4 16 | - name: install depencencies 17 | run: | 18 | sudo apt-get install neofetch #cppcheck 19 | neofetch --stdout 20 | - name: make 21 | run: make -j4 22 | - name: make test 23 | run: make -j4 test 24 | - name: make install 25 | run: sudo make install 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | test-utf8-input 3 | x1algol 4 | x1algc 5 | *.o 6 | *.trace 7 | *.c- 8 | *.h- 9 | *.txt- 10 | *~ 11 | *.cpp- 12 | *.x1- 13 | examples/*.x1 14 | library/objfile 15 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Set minimum required version of CMake 2 | cmake_minimum_required(VERSION 3.12) 3 | 4 | # Set name of project (as PROJECT_NAME) and C/C++ standards 5 | project(x1algol VERSION 0.1 DESCRIPTION "X1 Algol Simulator") 6 | set(CMAKE_C_STANDARD 11) 7 | set(CMAKE_CXX_STANDARD 17) 8 | add_compile_options(-Wall -Werror -Wshadow) 9 | 10 | # Enable cppcheck by default 11 | find_program(Cppcheck NAMES cppcheck) 12 | if(NOT (Cppcheck MATCHES "NOTFOUND")) 13 | message(STATUS "Found Cppcheck: ${Cppcheck}") 14 | set(CMAKE_CXX_CPPCHECK "${Cppcheck}" 15 | "--std=c++17" 16 | "--enable=style" 17 | "--error-exitcode=1" # Fail on any issues 18 | "--inline-suppr" # Enable inline control like // cppcheck-suppress "id" 19 | "--quiet" # No progress report messages 20 | "--suppress=*:*/_deps/*" # Ignore issues in Googletest 21 | "--library=${CMAKE_SOURCE_DIR}/tests/googletest.xml" # Parse TEST() macro properly 22 | ) 23 | if(APPLE) 24 | list(APPEND CMAKE_CXX_CPPCHECK "--check-level=exhaustive") 25 | endif() 26 | endif() 27 | 28 | # Get git commit hash and revision count 29 | execute_process( 30 | COMMAND git log -1 --format=%h 31 | WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} 32 | OUTPUT_STRIP_TRAILING_WHITESPACE 33 | OUTPUT_VARIABLE GIT_HASH 34 | ) 35 | execute_process( 36 | COMMAND git rev-list HEAD --count 37 | WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} 38 | OUTPUT_STRIP_TRAILING_WHITESPACE 39 | OUTPUT_VARIABLE GIT_REVCOUNT 40 | ) 41 | 42 | # 43 | # Download GoogleTest 44 | # 45 | include(FetchContent) 46 | FetchContent_Declare( 47 | googletest 48 | GIT_REPOSITORY https://github.com/google/googletest.git 49 | GIT_TAG v1.15.2 50 | EXCLUDE_FROM_ALL 51 | ) 52 | FetchContent_MakeAvailable(googletest) 53 | include(GoogleTest) 54 | enable_testing() 55 | 56 | add_subdirectory(compiler) 57 | add_subdirectory(simulator) 58 | add_subdirectory(library) 59 | add_subdirectory(tests) 60 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # make 3 | # make all -- build everything 4 | # 5 | # make test -- run unit tests 6 | # 7 | # make install -- install binaries to /usr/local 8 | # 9 | # make clean -- remove build files 10 | # 11 | # To reconfigure for Debug build: 12 | # make clean; make debug; make 13 | # 14 | 15 | all: build 16 | $(MAKE) -Cbuild $@ 17 | 18 | test: build 19 | $(MAKE) -Cbuild x1test 20 | ctest --test-dir build/tests 21 | 22 | install: build 23 | $(MAKE) -Cbuild $@ 24 | 25 | clean: 26 | rm -rf build 27 | 28 | build: 29 | mkdir $@ 30 | cmake -B$@ -DCMAKE_BUILD_TYPE=RelWithDebInfo 31 | 32 | debug: 33 | mkdir build 34 | cmake -Bbuild -DCMAKE_BUILD_TYPE=Debug 35 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![build status](https://github.com/sergev/x1-algol-compiler/actions/workflows/c-cpp.yml/badge.svg) 2 | 3 | The goal of this project is to revive the historic Algol compiler written by Edsger Dijkstra in 1960 for the Electrologica X1 computer. 4 | 5 | Sources downloaded from: https://gtoal.com/languages/algol60/x1algol/ 6 | 7 | Directories: 8 | 9 | * compiler - sources of Algol-60 compiler in Pascal and C 10 | * doc - documentation about X1 compiler, Electrologica X1 machine and Algol language 11 | * examples - sample code to compile and run 12 | * misc - helper stuff in progress 13 | * scripts - disassemblers, decoders and other useful scripts 14 | * simulator - implementation of a virtual X1-like machine 15 | * tests - unit tests for compiler and simulator 16 | 17 | # Build 18 | 19 | Compile the X1 Algol simulator from sources and install into /usr/local: 20 | 21 | ``` 22 | make 23 | make install 24 | ``` 25 | 26 | Run tests: 27 | ``` 28 | make test 29 | ``` 30 | Expected output: 31 | ``` 32 | ctest --test-dir build/tests 33 | ... 34 | Start 1: arith.x1_to_ieee 35 | 1/105 Test #1: arith.x1_to_ieee ........................ Passed 0.01 sec 36 | Start 2: arith.ieee_to_x1 37 | 2/105 Test #2: arith.ieee_to_x1 ........................ Passed 0.01 sec 38 | Start 3: x1_machine.arith_add 39 | ... 40 | 105/105 Test #105: cli.lib_sum ............................. Passed 0.02 sec 41 | 42 | 100% tests passed, 0 tests failed out of 105 43 | 44 | Total Test time (real) = 1.39 sec 45 | ``` 46 | 47 | # Examples 48 | 49 | A few demos are available in the `examples` directory: 50 | 51 | ``` 52 | $ cd examples 53 | 54 | $ x1sim hello.a60 55 | Hello `Algol' 56 | 57 | $ x1sim man_or_boy.a60 58 | -67 59 | ``` 60 | 61 | See full list on page [examples/README.md](examples/README.md). 62 | 63 | # Known bugs 64 | 65 | ## Misplaced parentheses in the Pascal version of the compiler 66 | 67 | The line `1415 arrc:= arrc - (arrd * store[tlsc-1]) mod d26;` as per the Kruseman Aretz paper, must be 68 | `arrc:= (arrc - arrd * store[tlsc-1]) mod d26;` to ensure correct computation of *storage functions* of multi-dimensional arrays. 69 | 70 | This is a Pascal transcription artifact. 71 | 72 | ## Mistakenly disabled generation of *passing of formals* descriptors 73 | 74 | Formal parameters of procedures directly passed as actual parameters to other procedures produce thunks (*implicit subroutines*) unnecessarily. 75 | 76 | The lines 77 | ``` 78 | 1074 then if (store[tlsc-2] = rlsc) 79 | 1075 and (fflag = 0) and (jflag = 0) and (nflag = 1) 80 | 1076 then begin if nid > nlscop 81 | 1077 then begin if (pflag = 1) and (fflag = 0) 82 | ``` 83 | Have two checks for `fflag = 0` in nested `if` conditions. One of the checks is redundant. 84 | Removing the first one, in line 1075, restores the ability to generate descriptors allowing a more efficient parameter passing. 85 | This saves about 15% of stack depth for the "Man or boy" test. 86 | 87 | It is unclear if this is a Pascal transcription artifact or a genuine performance regression in the original compiler. 88 | 89 | ## Passing predefined functions as procedure arguments sometimes results in bad code 90 | 91 | A numerical actual parameter of a procedure call immediately following a name of a predefined function, e.g. *sin* or *cos*, results in garbage object code. 92 | The check `nid > nlscop` in line 1076 *supra* fails because the variable `nid` still holds the ID of a predefined function when the next parameter 93 | is not an expression and does not contain an identifier, resulting in processing the number as if it were a predefined function. 94 | 95 | A fix is to add a flag which is set when such a name is encountered first (line 1104), and is used to trigger resetting `nid` to an arbitrary number greater than 96 | the predefined function boundary (`nlscop`) at the end of `production_of_object_program`. 97 | -------------------------------------------------------------------------------- /compiler/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # 2 | # Build Pascal version 3 | # 4 | #add_custom_target(x1algol ALL 5 | # COMMAND make -C ${CMAKE_CURRENT_SOURCE_DIR} pascal DESTDIR=${CMAKE_CURRENT_BINARY_DIR} 6 | #) 7 | #install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/x1algol DESTINATION bin) 8 | 9 | # 10 | # Build C version 11 | # 12 | add_executable(x1algc x1algc.c) 13 | install(TARGETS x1algc DESTINATION bin) 14 | -------------------------------------------------------------------------------- /compiler/Makefile: -------------------------------------------------------------------------------- 1 | DESTDIR ?= . 2 | CFLAGS = -Wall -Werror 3 | 4 | all: pascal x1algc 5 | 6 | clean: 7 | rm -f *.o x1algol x1algc 8 | 9 | test: x1algol ../examples/appendix-b.a60 10 | cat ../examples/*.lib > tape$$$$ ;\ 11 | ./x1algol tape$$$$< ../examples/appendix-b.a60 > app-b.pasout ;\ 12 | ./x1algc ../examples/appendix-b.a60 tape$$$$ > app-b.cout ;\ 13 | rm tape$$$$ 14 | diff app-b.pasout app-b.cout 15 | 16 | pascal: $(DESTDIR)/x1algol 17 | 18 | $(DESTDIR)/x1algol: x1algol.pas 19 | fpc -Miso -g -gl $< -o$@ 20 | -------------------------------------------------------------------------------- /doc/algol-encoding.md: -------------------------------------------------------------------------------- 1 | Internal encoding of symbols in X1 Algol compiler. 2 | 3 | Unused symbols are marked as ⎕. 4 | 5 | |Code|Symbol|Code|Symbol|Code| Symbol |Code | Symbol | 6 | | -- | ---- | -- | ---- | -- | -------- | --- | -------- | 7 | | 0 | 0 | 32 | w | 64 | + | 96 | ⎕ | 8 | | 1 | 1 | 33 | x | 65 | - | 97 | ⎕ | 9 | | 2 | 2 | 34 | y | 66 | × or * | 98 | ( | 10 | | 3 | 3 | 35 | z | 67 | / | 99 | ) | 11 | | 4 | 4 | 36 | ⎕ | 68 | ÷ or _: | 100 | [ | 12 | | 5 | 5 | 37 | A | 69 | ↑ or \|∧ | 101 | ] | 13 | | 6 | 6 | 38 | B | 70 | > | 102 | ` or \|< | 14 | | 7 | 7 | 39 | C | 71 | ≥ or _> | 103 | ' or \|> | 15 | | 8 | 8 | 40 | D | 72 | = | 104 | ⎕ | 16 | | 9 | 9 | 41 | E | 73 | ≤ or _< | 105 | ⎕ | 17 | | 10 | a | 42 | F | 74 | < | 106 | ⎕ | 18 | | 11 | b | 43 | G | 75 | ≠ or \|= | 107 | ⎕ | 19 | | 12 | c | 44 | H | 76 | ¬ | 108 | ⎕ | 20 | | 13 | d | 45 | I | 77 | ∧ | 109 | ⎕ | 21 | | 14 | e | 46 | J | 78 | ∨ | 110 | ⎕ | 22 | | 15 | f | 47 | K | 79 | ⊃ or _¬ | 111 | ⎕ | 23 | | 16 | g | 48 | L | 80 | ≡ or _= | 112 | ⎕ | 24 | | 17 | h | 49 | M | 81 | ⎕ | 113 | ⎕ | 25 | | 18 | i | 50 | N | 82 | ⎕ | 114 | ⎕ | 26 | | 19 | j | 51 | O | 83 | ⎕ | 115 | ⎕ | 27 | | 20 | k | 52 | P | 84 | ⎕ | 116 | ⎕ | 28 | | 21 | l | 53 | Q | 85 | ⎕ | 117 | ⎕ | 29 | | 22 | m | 54 | R | 86 | ⎕ | 118 | tab | 30 | | 23 | n | 55 | S | 87 | , | 119 | crlf | 31 | | 24 | o | 56 | T | 88 | . | 120 | ⎕ | 32 | | 25 | p | 57 | U | 89 | ⏨ or @ | 121 | " | 33 | | 26 | q | 58 | V | 90 | : | 122 | ? | 34 | | 27 | r | 59 | W | 91 | ; | 123 | ⎕ | 35 | | 28 | s | 60 | X | 92 | := | 124 | ⎕ | 36 | | 29 | t | 61 | Y | 93 | space | 125 | ⎕ | 37 | | 30 | u | 62 | Z | 94 | ⎕ | 126 | ⎕ | 38 | | 31 | v | 63 | ⎕ | 95 | ⎕ | 127 | ⎕ | 39 | 40 | In the parser, two more symbols are recognized: 41 | 42 | |Code |Symbol| 43 | | --- | ---- | 44 | | 162 | \| | 45 | | 163 | _ | 46 | -------------------------------------------------------------------------------- /doc/algol60-comparison-for-x1-and-x8.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sergev/x1-algol-compiler/73475bbb2acf41105664a1f8a41fd45ee48b4162/doc/algol60-comparison-for-x1-and-x8.pdf -------------------------------------------------------------------------------- /doc/algol60-compiler-for-x1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sergev/x1-algol-compiler/73475bbb2acf41105664a1f8a41fd45ee48b4162/doc/algol60-compiler-for-x1.pdf -------------------------------------------------------------------------------- /doc/algol60-revised-report.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sergev/x1-algol-compiler/73475bbb2acf41105664a1f8a41fd45ee48b4162/doc/algol60-revised-report.pdf -------------------------------------------------------------------------------- /doc/algol60-translator-for-x1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sergev/x1-algol-compiler/73475bbb2acf41105664a1f8a41fd45ee48b4162/doc/algol60-translator-for-x1.pdf -------------------------------------------------------------------------------- /doc/description-of-algol60.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sergev/x1-algol-compiler/73475bbb2acf41105664a1f8a41fd45ee48b4162/doc/description-of-algol60.pdf -------------------------------------------------------------------------------- /doc/dijkstra-phd-thesis.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sergev/x1-algol-compiler/73475bbb2acf41105664a1f8a41fd45ee48b4162/doc/dijkstra-phd-thesis.pdf -------------------------------------------------------------------------------- /doc/flexowriter-punching-code.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sergev/x1-algol-compiler/73475bbb2acf41105664a1f8a41fd45ee48b4162/doc/flexowriter-punching-code.jpg -------------------------------------------------------------------------------- /doc/instruction-encoding.md: -------------------------------------------------------------------------------- 1 | (pages [134](x1-binary-instructions.png)-[135](x1-binary-p-orders.png) from Dijkstra's PhD thesis) 2 | 3 | # Appendix 2. Binary representation of orders 4 | 5 | The digits of the order word are numbered 6 | 7 | d₂₆ d₂₅ . . . d₁ d₀ 8 | 9 | The name of the order (function letter(s) and function number) determines the contents of the six most significant digits d₂₆…d₂₁ of the order word. The number formed by these six binary digits can run from 0 to 63; its value is found by adding a number of times eight to the function number. The multiple of eight is determined by the function letter(s) and is given in the table below. 10 | 11 | A: 0 LS: 3½ 12 | S: 1 B : 4 13 | X: 2 T : 5 14 | LA: 2½ Y : 6 15 | D: 3 Z : 7 16 | 17 | The value of the next six bits is determined by the variants: 18 | ``` 19 | Address modification Condition-setting Condition reaction 20 | d₂₀ d₁₉ d₁₈ d₁₇ d₁₆ d₁₅ 21 | normally 0 0 normally 0 0 normally 0 0 22 | A 0 1 P 0 1 U 0 1 23 | B 1 0 Z 1 0 Y 1 0 24 | C 1 1 E 1 1 N 1 1 25 | ``` 26 | The bits d₁₄…d₀ give the binary representation of the address. 27 | 28 | According to the above rules d₂₁ would be = 0 in counting and subroutine Jumps (4T and 6T); however, it is used for the index m, more precisely, if the binary digits of the index m are b₂ b₁ b₀ (for 4T) or b₃ b₂ b₁ b₀ (for 6T), then the following holds. 29 | ``` 30 | d₂₁ = b₂ 31 | d₂₀ = b₁ 32 | d₁₉ = b₀ 33 | and for 6T: d₁₈ = b₃ 34 | ``` 35 | (In the subroutine jump, the binary digit b₃ is therefore placed at the least significant side.) 36 | 37 | The binary representation of the P-orders is given in the table below (the special paragraph letter C causes an increase of 2¹⁴ in the address: 0 C0 = 16384 X0). 38 | ``` 39 | Circuit 0P n 1P n 2P n 3P n 4P 5P 6P 7P 40 | 41 | AA 6Y nX0 7Y nX0 6Y nX1 7Y nX1 6Y 0X8 7Y 0X8 6Y 0X5 - 42 | AS 6Y nX2 7Y nX2 6Y nX3 7Y nX3 6Y 1X8 7Y 1X8 6Y 0X7 - 43 | AB - - - - 6Y 2X8 7Y 2X8 - - 44 | SA 6Z nX2 7Z nX2 6Z nX3 7Z nX3 6Y 0X9 7Y 0X9 6Y 0X5 - 45 | SS 6Z nX0 7Z nX0 6Z nX1 7Z nX1 6Y 1X9 7Y 1X9 6Z 0X5 - 46 | SB - - - - 6Y 2X9 7Y 2X9 - - 47 | BA - - - - 6Y 0X10 7Y 0X10 - - 48 | BS - - - - 6Y 1X10 7Y 1X10 - - 49 | BB - - - - 6Y 2X10 7Y 2X10 - - 50 | 51 | - - - - - - - - 7Y 0C0 52 | ``` 53 | -------------------------------------------------------------------------------- /doc/mr35.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sergev/x1-algol-compiler/73475bbb2acf41105664a1f8a41fd45ee48b4162/doc/mr35.pdf -------------------------------------------------------------------------------- /doc/mr81.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sergev/x1-algol-compiler/73475bbb2acf41105664a1f8a41fd45ee48b4162/doc/mr81.pdf -------------------------------------------------------------------------------- /doc/pords-and-pards.md: -------------------------------------------------------------------------------- 1 | # The PORD's and the PARD's 2 | 3 | The TRANSMARK logic translates PORD's into PARD's. 4 | The PORD's are in the object program (in descending order, 5 | starting at the return address = 3, see pg 10) and each cover 1 word, 6 | the PARDs derived from this are placed in the stack in ascending order 7 | and each cover two words (see pg 7). 8 | 9 | The structure of a PORD is as follows: 10 | 11 | |26 25 24 23 22|21|20 19|18|17 16|15|14 - 0| 12 | | ------------ |--| --- |--| --- |--| ---- | 13 | | bn |0 | Q |0 | t |0 | addr | 14 | 15 | If t=0, then the 15 bits of addr are a physical address 16 | (quantity from block 0, start address of procedure or implicit subroutine); 17 | the five bits of bn are then irrelevant and are =0. 18 | 19 | The value t=2 does not occur. 20 | 21 | If t=1 or 3, then the bits of addr are a position with respect to a PP, 22 | which is indicated by the bits of bn and in the first instance 23 | the physical address PP[bn] + addr, which 24 | indicates a quantity in the stack, is built up. 25 | (This is therefore the normal "dynamic address" with the difference that 26 | the bits for position and block number are in a different position) 27 | 28 | If t=1, then the address thus formed is continued 29 | as in the case t=0 with the address given directly in addr. 30 | 31 | If t=3, - i.e. the current parameter is at the place where 32 | it is given a formal, the so-called, "passing on of a formal 33 | parameter - then the address thus derived guaranteedly points to one PARD, 34 | and this PARD is passed on without further ado 35 | (so (PP[bn]+addr) and (PP[bn]+addr+1) are together the resulting PARD). 36 | 37 | If t=3, then the bits of Q are irrelevant, and are =0. 38 | 39 | How this physical address should be interpreted is indicated in the bits of Q, 40 | 41 | * Q=0 address of real number 42 | * Q=1 address of integer (or boolean) 43 | * Q=2 start address of procedure or implicit subroutine without or with numerical result 44 | * Q=3 start address of implicit subroutine with an address as result, 45 | -------------------------------------------------------------------------------- /doc/the-x1-computer.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sergev/x1-algol-compiler/73475bbb2acf41105664a1f8a41fd45ee48b4162/doc/the-x1-computer.pdf -------------------------------------------------------------------------------- /doc/x1-binary-instructions.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sergev/x1-algol-compiler/73475bbb2acf41105664a1f8a41fd45ee48b4162/doc/x1-binary-instructions.png -------------------------------------------------------------------------------- /doc/x1-binary-p-orders.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sergev/x1-algol-compiler/73475bbb2acf41105664a1f8a41fd45ee48b4162/doc/x1-binary-p-orders.png -------------------------------------------------------------------------------- /examples/beer.a60: -------------------------------------------------------------------------------- 1 | b̲e̲g̲i̲n̲ 2 | 3 | c̲o̲m̲m̲e̲n̲t̲ 4 | 99 Bottles of Beer on the Wall 5 | written in Algol60, for the a60 interpreter 6 | by Erik Schoenfelder. 7 | 8 | Lower case, whitespace, ASCII, literal strings, 9 | implementation character set, etc, and other 10 | modern conceits are ahistoric and waste cards and tape. 11 | 12 | Tom Jennings 5 Jan 2006 13 | ; 14 | 15 | i̲n̲t̲e̲g̲e̲r̲ p̲r̲o̲c̲e̲d̲u̲r̲e̲ bottles(n); 16 | v̲a̲l̲u̲e̲ n; 17 | i̲n̲t̲e̲g̲e̲r̲ n; 18 | b̲e̲g̲i̲n̲ 19 | i̲f̲ n < 1 t̲h̲e̲n̲ PRINTTEXT(`no more') e̲l̲s̲e̲ print(n); 20 | i̲f̲ n = 1 t̲h̲e̲n̲ PRINTTEXT(` bottle') e̲l̲s̲e̲ PRINTTEXT(` bottles'); 21 | PRINTTEXT(` of beer') 22 | e̲n̲d̲; 23 | 24 | c̲o̲m̲m̲e̲n̲t̲ Here is main. ; 25 | 26 | i̲n̲t̲e̲g̲e̲r̲ i; 27 | 28 | f̲o̲r̲ i := 99 s̲t̲e̲p̲ -1 u̲n̲t̲i̲l̲ 1 d̲o̲ b̲e̲g̲i̲n̲ 29 | bottles(i); PRINTTEXT(` on the wall, '); 30 | bottles(i); NLCR; 31 | PRINTTEXT(`take one down and pass it around, '); 32 | bottles(i - 1); PRINTTEXT(` on the wall.'); NLCR 33 | e̲n̲d̲; 34 | 35 | e̲n̲d̲ 36 | -------------------------------------------------------------------------------- /examples/bulls_and_cows.a60: -------------------------------------------------------------------------------- 1 | b̲e̲g̲i̲n̲ 2 | i̲n̲t̲e̲g̲e̲r̲ secret, count, guess, cows, bulls, i, j; 3 | r̲e̲a̲l̲ seed; 4 | 5 | i̲n̲t̲e̲g̲e̲r̲ p̲r̲o̲c̲e̲d̲u̲r̲e̲ digit(num, ps); 6 | v̲a̲l̲u̲e̲ num; 7 | i̲n̲t̲e̲g̲e̲r̲ num, ps; 8 | b̲e̲g̲i̲n̲ 9 | num := num ÷ 10↑ps; 10 | digit := num - num ÷ 10 * 10 11 | e̲n̲d̲; 12 | 13 | B̲o̲o̲l̲e̲a̲n̲ p̲r̲o̲c̲e̲d̲u̲r̲e̲ malformed(num); 14 | v̲a̲l̲u̲e̲ num; 15 | i̲n̲t̲e̲g̲e̲r̲ num; 16 | b̲e̲g̲i̲n̲ 17 | malformed := num > 9876 ∨ num < 0123 ∨ 18 | digit(num, 0) = digit(num, 1) ∨ 19 | digit(num, 0) = digit(num, 2) ∨ 20 | digit(num, 0) = digit(num, 3) ∨ 21 | digit(num, 1) = digit(num, 2) ∨ 22 | digit(num, 1) = digit(num, 3) ∨ 23 | digit(num, 2) = digit(num, 3); 24 | e̲n̲d̲; 25 | 26 | SETRANDOM(TIMEOFDAY); 27 | secret := 0; 28 | f̲o̲r̲ i := 0 w̲h̲i̲l̲e̲ malformed(secret) d̲o̲ 29 | secret := entier(RANDOM * 9877); 30 | 31 | PRINTTEXT(`Welcome to bulls and cows!'); NLCR; 32 | NLCR; 33 | PRINTTEXT(`I choose a number made of 4 digits (from 0 to 9) without repetitions.'); NLCR; 34 | PRINTTEXT(`You enter a number of 4 digits, and I say you how many of them'); NLCR; 35 | PRINTTEXT(`are in my secret number but in wrong position (cows),'); NLCR; 36 | PRINTTEXT(`and how many are in the right position (bulls).'); NLCR; 37 | NLCR; 38 | 39 | count := 0; 40 | guess := 0; 41 | f̲o̲r̲ i := 0 w̲h̲i̲l̲e̲ guess ≠ secret d̲o̲ b̲e̲g̲i̲n̲ 42 | count := count + 1; 43 | again: 44 | PRINTTEXT(`Guess a number.'); 45 | NLCR; 46 | guess := entier(read); 47 | i̲f̲ malformed(guess) t̲h̲e̲n̲ 48 | g̲o̲t̲o̲ again; 49 | 50 | cows := 0; 51 | bulls := 0; 52 | 53 | f̲o̲r̲ i := 0 s̲t̲e̲p̲ 1 u̲n̲t̲i̲l̲ 3 d̲o̲ 54 | f̲o̲r̲ j := 0 s̲t̲e̲p̲ 1 u̲n̲t̲i̲l̲ 3 d̲o̲ 55 | i̲f̲ digit(secret, i) = digit(guess, j) t̲h̲e̲n̲ 56 | i̲f̲ i = j t̲h̲e̲n̲ 57 | bulls := bulls + 1 58 | e̲l̲s̲e̲ 59 | cows := cows + 1; 60 | 61 | PRINTTEXT(`You scored '); 62 | print(bulls); 63 | PRINTTEXT(` bulls and '); 64 | print(cows); 65 | PRINTTEXT(` cows.'); 66 | NLCR 67 | e̲n̲d̲; 68 | PRINTTEXT(`Correct. That took you '); 69 | print(count); 70 | PRINTTEXT(` guesses.') 71 | NLCR 72 | e̲n̲d̲ 73 | -------------------------------------------------------------------------------- /examples/disarium.a60: -------------------------------------------------------------------------------- 1 | b̲e̲g̲i̲n̲ 2 | c̲o̲m̲m̲e̲n̲t̲ Find some Disarium numbers - numbers whose digit position-power sums 3 | are equal to the number, e.g. 135 = 1^1 + 3^2 + 5^3. 4 | Output: 0 1 2 3 4 5 6 7 8 9 89 135 175 518 598 1306 1676 2427; 5 | i̲n̲t̲e̲g̲e̲r̲ a̲r̲r̲a̲y̲ power [1 : 9, 0 : 9]; 6 | i̲n̲t̲e̲g̲e̲r̲ count, powerOfTen, length, n, d; 7 | 8 | c̲o̲m̲m̲e̲n̲t̲ compute the nth powers of 0-9; 9 | f̲o̲r̲ d := 0 s̲t̲e̲p̲ 1 u̲n̲t̲i̲l̲ 9 d̲o̲ 10 | power[1, d] := d; 11 | f̲o̲r̲ n := 2 s̲t̲e̲p̲ 1 u̲n̲t̲i̲l̲ 8 d̲o̲ b̲e̲g̲i̲n̲ 12 | power[n, 0] := 0; 13 | f̲o̲r̲ d := 1 s̲t̲e̲p̲ 1 u̲n̲t̲i̲l̲ 9 d̲o̲ 14 | power[n, d] := power[n - 1, d] * d 15 | e̲n̲d̲ n; 16 | 17 | c̲o̲m̲m̲e̲n̲t̲ print the first few Disarium numbers; 18 | count := 0; 19 | powerOfTen := 10; 20 | length := 1; 21 | n := -1; 22 | f̲o̲r̲ n := n + 1 w̲h̲i̲l̲e̲ count < 18 d̲o̲ b̲e̲g̲i̲n̲ 23 | i̲n̲t̲e̲g̲e̲r̲ v, dps, p; 24 | i̲f̲ n = powerOfTen t̲h̲e̲n̲ b̲e̲g̲i̲n̲ 25 | c̲o̲m̲m̲e̲n̲t̲ the number of digfits just increased; 26 | powerOfTen := powerOfTen * 10; 27 | length := length + 1 28 | e̲n̲d̲; 29 | c̲o̲m̲m̲e̲n̲t̲ form the digit power sum; 30 | v := n; 31 | dps := 0; 32 | f̲o̲r̲ p := length s̲t̲e̲p̲ -1 u̲n̲t̲i̲l̲ 1 d̲o̲ b̲e̲g̲i̲n̲ 33 | dps := dps + power[p, v - (v ÷ 10 * 10)]; 34 | v := v ÷ 10 35 | e̲n̲d̲ p; 36 | i̲f̲ dps = n t̲h̲e̲n̲ b̲e̲g̲i̲n̲ 37 | c̲o̲m̲m̲e̲n̲t̲ n is Disarium; 38 | count := count + 1; 39 | SPACE(1); 40 | print(n) 41 | e̲n̲d̲ 42 | e̲n̲d̲ n; 43 | NLCR 44 | e̲n̲d̲ 45 | -------------------------------------------------------------------------------- /examples/hanoi.a60: -------------------------------------------------------------------------------- 1 | b̲e̲g̲i̲n̲ 2 | c̲o̲m̲m̲e̲n̲t̲ 3 | The Towers Of Hanoi 4 | Algol-60 5 | Copyright (C) 1999 Amit Singh. All Rights Reserved. 6 | http://hanoi.kernelthread.com 7 | ; 8 | 9 | p̲r̲o̲c̲e̲d̲u̲r̲e̲ movedisk(n, f, t); 10 | i̲n̲t̲e̲g̲e̲r̲ n, f, t; 11 | b̲e̲g̲i̲n̲ 12 | PRINTTEXT(`move '); 13 | print(f); 14 | PRINTTEXT(` --> '); 15 | print(t); 16 | NLCR 17 | e̲n̲d̲; 18 | 19 | p̲r̲o̲c̲e̲d̲u̲r̲e̲ dohanoi(n, f, t, u); 20 | i̲n̲t̲e̲g̲e̲r̲ n, f, t, u; 21 | b̲e̲g̲i̲n̲ 22 | i̲f̲ n < 2 t̲h̲e̲n̲ 23 | movedisk(1, f, t) 24 | e̲l̲s̲e̲ b̲e̲g̲i̲n̲ 25 | dohanoi(n - 1, f, u, t); 26 | movedisk(1, f, t); 27 | dohanoi(n - 1, u, t, f); 28 | e̲n̲d̲; 29 | e̲n̲d̲; 30 | 31 | dohanoi(3, 1, 3, 2); 32 | e̲n̲d̲ 33 | -------------------------------------------------------------------------------- /examples/hello.a60: -------------------------------------------------------------------------------- 1 | b̲e̲g̲i̲n̲ 2 | PRINTTEXT(`Hello `Algol''); 3 | NLCR 4 | e̲n̲d̲ 5 | -------------------------------------------------------------------------------- /examples/lisp.md: -------------------------------------------------------------------------------- 1 | ``` 2 | $ ./lisp.sh 3 | Lisp interpreter version 1, Oktober 2004 4 | 5 | 6 | t nil quote cond lambda define car cdr cons equal atom numberp lessp greaterp add1 sub1 add minus times div 7 | 8 | define (( 9 | (crossriver (lambda ( ) (complete (cons (i) nil)))) 10 | 11 | (complete 12 | (lambda (path) 13 | (cond ((equal (car path) (f)) (cons path nil)) 14 | (t (try path (fullmoveset))) 15 | ) ) ) 16 | 17 | (try 18 | (lambda (path moveset) 19 | (cond ((null moveset) nil) 20 | ((feasible (car moveset) (car path)) 21 | (append (try1 path (result (car moveset) (car path))) 22 | (try path (cdr moveset)))) 23 | (t (try path (cdr moveset))) 24 | ) ) ) 25 | 26 | (try1 27 | (lambda (path newstate) 28 | (cond ((not (admissible newstate)) nil) 29 | ((member newstate path) nil) 30 | (t (complete (cons newstate path))) 31 | ) ) ) 32 | 33 | (i (lambda ( ) (quote ((c c c) (m m m) ( ) ( ) left)))) 34 | 35 | (f (lambda ( ) (quote ((c c c) (m m m) ( ) ( ) right)))) 36 | 37 | (fullmoveset 38 | (lambda ( ) 39 | (quote (((c c) ( )) ((c) (m)) (( ) (m m)) ((c) ( )) (( ) (m)))) 40 | ) ) 41 | 42 | (feasible 43 | (lambda (move state) 44 | (cond ((smaller (car state) (car move)) nil) 45 | ((smaller (cadr state) (cadr move)) nil) 46 | (t t) 47 | ) ) ) 48 | 49 | (admissible 50 | (lambda (state) 51 | (cond ((null (cadr state)) t) 52 | ((null (cadddr state)) t) 53 | (t (ofequallength (car state) (cadr state))) 54 | ) ) ) 55 | 56 | (result 57 | (lambda (move state) 58 | (list (inc (caddr state) (car move)) 59 | (inc (cadddr state) (cadr move)) 60 | (dec (car state) (car move)) 61 | (dec (cadr state) (cadr move)) 62 | (other (caddddr state)) 63 | ) ) ) 64 | 65 | (other 66 | (lambda (riverside) 67 | (cond ((equal riverside (quote left)) (quote right)) 68 | (t (quote left)) 69 | ) ) ) 70 | 71 | (list 72 | (lambda (a b c d e) 73 | (cons a (cons b (cons c (cons d (cons e nil))))) 74 | ) ) 75 | 76 | (smaller 77 | (lambda (x y) 78 | (cond ((null y) nil) 79 | ((null x) t) 80 | (t (smaller (cdr x) (cdr y))) 81 | ) ) ) 82 | 83 | (inc 84 | (lambda (x y) 85 | (cond ((null y) x) 86 | (t (inc (cons (car y) x) (cdr y))) 87 | ) ) ) 88 | (dec 89 | (lambda (x y) 90 | (cond ((null y) x) 91 | (t (dec (cdr x) (cdr y))) 92 | ) ) ) 93 | 94 | (ofequallength 95 | (lambda (x y) 96 | (cond ((null x) (null y)) 97 | ((null y) nil) 98 | (t (ofequallength (cdr x) (cdr y))) 99 | ) ) ) 100 | 101 | (null (lambda (x) (equal x nil))) 102 | 103 | (append 104 | (lambda (x y) 105 | (cond ((null x) y) 106 | (t (cons (car x) (append (cdr x) y))) 107 | ) ) ) 108 | 109 | (not (lambda (x) (equal x nil))) 110 | 111 | (member 112 | (lambda (x y) 113 | (cond ((null y) nil) 114 | ((equal x (car y)) t) 115 | (t (member x (cdr y))) 116 | ) ) ) 117 | 118 | (cadr (lambda (x) (car (cdr x)))) 119 | 120 | (caddr (lambda (x) (car (cdr (cdr x))))) 121 | 122 | (cadddr (lambda (x) (car (cdr (cdr (cdr x)))))) 123 | 124 | (caddddr (lambda (x) (car (cdr (cdr (cdr (cdr x))))))) 125 | )) 126 | 127 | (crossriver complete try try1 i f fullmovese feasible admissible result other list smaller inc dec ofequallen null append not member cadr caddr cadddr caddddr) 128 | crossriver () 129 | 130 | 131 | garbage collector: 1200 132 | 133 | garbage collector: 1031 134 | 135 | garbage collector: 1137 136 | 137 | garbage collector: 1246 138 | 139 | garbage collector: 1020 140 | 141 | garbage collector: 901 142 | 143 | garbage collector: 1069 144 | 145 | ((((c c c) (m m m) nil nil right) 146 | ((c c) nil (c) (m m m) left) 147 | ((c c) (m m m) (c) nil right) 148 | ((c c c) nil nil (m m m) left) 149 | ((c) (m m m) (c c) nil right) 150 | ((c c) (m m) (c) (m) left) 151 | ((c c) (m m) (c) (m) right) 152 | ((c) (m m m) (c c) nil left) 153 | ((c c c) nil nil (m m m) right) 154 | ((c c) (m m m) (c) nil left) 155 | ((c c) nil (c) (m m m) right) 156 | ((c c c) (m m m) nil nil left) 157 | ) 158 | (((c c c) (m m m) nil nil right) 159 | ((c) (m) (c c) (m m) left) 160 | ((c c) (m m m) (c) nil right) 161 | ((c c c) nil nil (m m m) left) 162 | ((c) (m m m) (c c) nil right) 163 | ((c c) (m m) (c) (m) left) 164 | ((c c) (m m) (c) (m) right) 165 | ((c) (m m m) (c c) nil left) 166 | ((c c c) nil nil (m m m) right) 167 | ((c c) (m m m) (c) nil left) 168 | ((c c) nil (c) (m m m) right) 169 | ((c c c) (m m m) nil nil left) 170 | ) 171 | (((c c c) (m m m) nil nil right) 172 | ((c c) nil (c) (m m m) left) 173 | ((c c) (m m m) (c) nil right) 174 | ((c c c) nil nil (m m m) left) 175 | ((c) (m m m) (c c) nil right) 176 | ((c c) (m m) (c) (m) left) 177 | ((c c) (m m) (c) (m) right) 178 | ((c) (m m m) (c c) nil left) 179 | ((c c c) nil nil (m m m) right) 180 | ((c c) (m m m) (c) nil left) 181 | ((c) (m) (c c) (m m) right) 182 | ((c c c) (m m m) nil nil left) 183 | ) 184 | (((c c c) (m m m) nil nil right) 185 | ((c) (m) (c c) (m m) left) 186 | ((c c) (m m m) (c) nil right) 187 | ((c c c) nil nil (m m m) left) 188 | ((c) (m m m) (c c) nil right) 189 | ((c c) (m m) (c) (m) left) 190 | ((c c) (m m) (c) (m) right) 191 | ((c) (m m m) (c c) nil left) 192 | ((c c c) nil nil (m m m) right) 193 | ((c c) (m m m) (c) nil left) 194 | ((c) (m) (c c) (m m) right) 195 | ((c c c) (m m m) nil nil left) 196 | ) 197 | ) 198 | 199 | 200 | +++ error: eof 201 | ``` 202 | -------------------------------------------------------------------------------- /examples/lisp.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Solve the 3 missionaries and 3 cannibals crossing a river puzzle. 4 | # Use a simple LISP 1.5 interpreter written in ALGOL 60. 5 | # 6 | x1sim lisp.a60 << END_OF_INPUT 7 | 8 | t nil quote cond lambda define car cdr cons equal atom numberp lessp greaterp add1 sub1 add minus times div 9 | 10 | define (( 11 | (crossriver (lambda ( ) (complete (cons (i) nil)))) 12 | 13 | (complete 14 | (lambda (path) 15 | (cond ((equal (car path) (f)) (cons path nil)) 16 | (t (try path (fullmoveset))) 17 | ) ) ) 18 | 19 | (try 20 | (lambda (path moveset) 21 | (cond ((null moveset) nil) 22 | ((feasible (car moveset) (car path)) 23 | (append (try1 path (result (car moveset) (car path))) 24 | (try path (cdr moveset)))) 25 | (t (try path (cdr moveset))) 26 | ) ) ) 27 | 28 | (try1 29 | (lambda (path newstate) 30 | (cond ((not (admissible newstate)) nil) 31 | ((member newstate path) nil) 32 | (t (complete (cons newstate path))) 33 | ) ) ) 34 | 35 | (i (lambda ( ) (quote ((c c c) (m m m) ( ) ( ) left)))) 36 | 37 | (f (lambda ( ) (quote ((c c c) (m m m) ( ) ( ) right)))) 38 | 39 | (fullmoveset 40 | (lambda ( ) 41 | (quote (((c c) ( )) ((c) (m)) (( ) (m m)) ((c) ( )) (( ) (m)))) 42 | ) ) 43 | 44 | (feasible 45 | (lambda (move state) 46 | (cond ((smaller (car state) (car move)) nil) 47 | ((smaller (cadr state) (cadr move)) nil) 48 | (t t) 49 | ) ) ) 50 | 51 | (admissible 52 | (lambda (state) 53 | (cond ((null (cadr state)) t) 54 | ((null (cadddr state)) t) 55 | (t (ofequallength (car state) (cadr state))) 56 | ) ) ) 57 | 58 | (result 59 | (lambda (move state) 60 | (list (inc (caddr state) (car move)) 61 | (inc (cadddr state) (cadr move)) 62 | (dec (car state) (car move)) 63 | (dec (cadr state) (cadr move)) 64 | (other (caddddr state)) 65 | ) ) ) 66 | 67 | (other 68 | (lambda (riverside) 69 | (cond ((equal riverside (quote left)) (quote right)) 70 | (t (quote left)) 71 | ) ) ) 72 | 73 | (list 74 | (lambda (a b c d e) 75 | (cons a (cons b (cons c (cons d (cons e nil))))) 76 | ) ) 77 | 78 | (smaller 79 | (lambda (x y) 80 | (cond ((null y) nil) 81 | ((null x) t) 82 | (t (smaller (cdr x) (cdr y))) 83 | ) ) ) 84 | 85 | (inc 86 | (lambda (x y) 87 | (cond ((null y) x) 88 | (t (inc (cons (car y) x) (cdr y))) 89 | ) ) ) 90 | (dec 91 | (lambda (x y) 92 | (cond ((null y) x) 93 | (t (dec (cdr x) (cdr y))) 94 | ) ) ) 95 | 96 | (ofequallength 97 | (lambda (x y) 98 | (cond ((null x) (null y)) 99 | ((null y) nil) 100 | (t (ofequallength (cdr x) (cdr y))) 101 | ) ) ) 102 | 103 | (null (lambda (x) (equal x nil))) 104 | 105 | (append 106 | (lambda (x y) 107 | (cond ((null x) y) 108 | (t (cons (car x) (append (cdr x) y))) 109 | ) ) ) 110 | 111 | (not (lambda (x) (equal x nil))) 112 | 113 | (member 114 | (lambda (x y) 115 | (cond ((null y) nil) 116 | ((equal x (car y)) t) 117 | (t (member x (cdr y))) 118 | ) ) ) 119 | 120 | (cadr (lambda (x) (car (cdr x)))) 121 | 122 | (caddr (lambda (x) (car (cdr (cdr x))))) 123 | 124 | (cadddr (lambda (x) (car (cdr (cdr (cdr x)))))) 125 | 126 | (caddddr (lambda (x) (car (cdr (cdr (cdr (cdr x))))))) 127 | )) 128 | 129 | crossriver () 130 | 131 | END_OF_INPUT 132 | -------------------------------------------------------------------------------- /examples/magic_square.a60: -------------------------------------------------------------------------------- 1 | b̲e̲g̲i̲n̲ 2 | c̲o̲m̲m̲e̲n̲t̲ Magic squares of doubly even order - 10/02/2021; 3 | i̲n̲t̲e̲g̲e̲r̲ a̲r̲r̲a̲y̲ pattern[1:4, 1:4]; 4 | i̲n̲t̲e̲g̲e̲r̲ n, r, c, s, m, i, b, t; 5 | n := 8; 6 | f̲o̲r̲ r := 1 s̲t̲e̲p̲ 1 u̲n̲t̲i̲l̲ 4 d̲o̲ 7 | f̲o̲r̲ c := 1 s̲t̲e̲p̲ 1 u̲n̲t̲i̲l̲ 4 d̲o̲ 8 | pattern[r,c] := i̲f̲ ((c=1 ∨ c=4) ∧ (r=1 ∨ r=4)) ∨ 9 | ((c=2 ∨ c=3) ∧ (r=2 ∨ r=3)) t̲h̲e̲n̲ 1 e̲l̲s̲e̲ 0; 10 | s := n * n; 11 | m := n ÷ 4; 12 | PRINTTEXT(`magic square, n = '); 13 | print(n); 14 | NLCR; 15 | NLCR; 16 | i := 0; 17 | f̲o̲r̲ r := 1 s̲t̲e̲p̲ 1 u̲n̲t̲i̲l̲ n d̲o̲ b̲e̲g̲i̲n̲ 18 | f̲o̲r̲ c := 1 s̲t̲e̲p̲ 1 u̲n̲t̲i̲l̲ n d̲o̲ b̲e̲g̲i̲n̲ 19 | b := pattern[1 + ((r - 1) ÷ m), 1 + ((c - 1) ÷ m)]; 20 | t := i̲f̲ b = 1 t̲h̲e̲n̲ i + 1 e̲l̲s̲e̲ s - i; 21 | SPACE(1); 22 | i̲f̲ t < 10 t̲h̲e̲n̲ 23 | SPACE(1); 24 | print(t); 25 | i := i + 1 26 | e̲n̲d̲; 27 | NLCR 28 | e̲n̲d̲; 29 | NLCR; 30 | PRINTTEXT(`magic constant = '); 31 | print((s + 1) * n ÷ 2); 32 | NLCR 33 | e̲n̲d̲ 34 | -------------------------------------------------------------------------------- /examples/man_or_boy.a60: -------------------------------------------------------------------------------- 1 | b̲e̲g̲i̲n̲ 2 | r̲e̲a̲l̲ p̲r̲o̲c̲e̲d̲u̲r̲e̲ A(k, x1, x2, x3, x4, x5); 3 | v̲a̲l̲u̲e̲ k; i̲n̲t̲e̲g̲e̲r̲ k; 4 | r̲e̲a̲l̲ x1, x2, x3, x4, x5; 5 | b̲e̲g̲i̲n̲ 6 | r̲e̲a̲l̲ p̲r̲o̲c̲e̲d̲u̲r̲e̲ B; 7 | b̲e̲g̲i̲n̲ 8 | k:= k - 1; 9 | B:= A := A (k, B, x1, x2, x3, x4) 10 | e̲n̲d̲; 11 | A := i̲f̲ k < 1 t̲h̲e̲n̲ x4 + x5 e̲l̲s̲e̲ B 12 | e̲n̲d̲; 13 | print (A (10, 1.0, -1.0, -1.0, 1.0, 0.0)); 14 | NLCR 15 | e̲n̲d̲ 16 | -------------------------------------------------------------------------------- /examples/mersenne.a60: -------------------------------------------------------------------------------- 1 | b̲e̲g̲i̲n̲ 2 | i̲n̲t̲e̲g̲e̲r̲ p̲r̲o̲c̲e̲d̲u̲r̲e̲ mersenne(n); v̲a̲l̲u̲e̲ n; i̲n̲t̲e̲g̲e̲r̲ n; b̲e̲g̲i̲n̲ 3 | i̲n̲t̲e̲g̲e̲r̲ i, m; 4 | m := 1; 5 | f̲o̲r̲ i := 1 s̲t̲e̲p̲ 1 u̲n̲t̲i̲l̲ n d̲o̲ 6 | m := m * 2; 7 | mersenne := m - 1; 8 | e̲n̲d̲; 9 | 10 | B̲o̲o̲l̲e̲a̲n̲ p̲r̲o̲c̲e̲d̲u̲r̲e̲ isprime(n); v̲a̲l̲u̲e̲ n; i̲n̲t̲e̲g̲e̲r̲ n; b̲e̲g̲i̲n̲ 11 | i̲f̲ n < 2 t̲h̲e̲n̲ 12 | isprime := f̲a̲l̲s̲e̲ 13 | e̲l̲s̲e̲ i̲f̲ entier(n / 2) * 2 = n t̲h̲e̲n̲ 14 | isprime := (n = 2) 15 | e̲l̲s̲e̲ b̲e̲g̲i̲n̲ 16 | c̲o̲m̲m̲e̲n̲t̲ - check odd divisors up to sqrt(n); 17 | i̲n̲t̲e̲g̲e̲r̲ i, limit; 18 | B̲o̲o̲l̲e̲a̲n̲ divisible; 19 | limit := entier(sqrt(n)); 20 | divisible := f̲a̲l̲s̲e̲; 21 | f̲o̲r̲ i := 3, i+2 w̲h̲i̲l̲e̲ i ≤ limit ∧ ¬ divisible d̲o̲ b̲e̲g̲i̲n̲ 22 | i̲f̲ entier(n / i) * i = n t̲h̲e̲n̲ 23 | divisible := t̲r̲u̲e̲; 24 | i := i + 2 25 | e̲n̲d̲; 26 | isprime := i̲f̲ divisible t̲h̲e̲n̲ f̲a̲l̲s̲e̲ e̲l̲s̲e̲ t̲r̲u̲e̲ 27 | e̲n̲d̲ 28 | e̲n̲d̲; 29 | 30 | c̲o̲m̲m̲e̲n̲t̲ - main code begins here; 31 | i̲n̲t̲e̲g̲e̲r̲ i, m; 32 | PRINTTEXT(`Searching to M(19) for Mersenne primes'); 33 | NLCR; 34 | f̲o̲r̲ i := 1 s̲t̲e̲p̲ 1 u̲n̲t̲i̲l̲ 19 d̲o̲ b̲e̲g̲i̲n̲ 35 | m := mersenne(i); 36 | i̲f̲ isprime(m) t̲h̲e̲n̲ b̲e̲g̲i̲n̲ 37 | PRINTTEXT(`M('); 38 | print(i); 39 | PRINTTEXT(`) : '); 40 | print(m); 41 | NLCR 42 | e̲n̲d̲ 43 | e̲n̲d̲ 44 | e̲n̲d̲ 45 | -------------------------------------------------------------------------------- /examples/outer_planets.a60: -------------------------------------------------------------------------------- 1 | b̲e̲g̲i̲n̲ 2 | c̲o̲m̲m̲e̲n̲t̲ JAZ164, R743, Outer Planets; 3 | i̲n̲t̲e̲g̲e̲r̲ k, t; 4 | r̲e̲a̲l̲ a, k2, x; 5 | B̲o̲o̲l̲e̲a̲n̲ fi; 6 | a̲r̲r̲a̲y̲ y, ya, z, za[1:15], m[0:5], e[1:60], d[1:33]; 7 | 8 | r̲e̲a̲l̲ p̲r̲o̲c̲e̲d̲u̲r̲e̲ f(k); 9 | i̲n̲t̲e̲g̲e̲r̲ k; 10 | b̲e̲g̲i̲n̲ 11 | i̲n̲t̲e̲g̲e̲r̲ i, j, i3, j3; 12 | r̲e̲a̲l̲ p; 13 | o̲w̲n̲ r̲e̲a̲l̲ a̲r̲r̲a̲y̲ d[1:5, 1:5], r[1:5]; 14 | 15 | i̲f̲ k ≠ 1 t̲h̲e̲n̲ g̲o̲t̲o̲ A; 16 | f̲o̲r̲ i := 1 s̲t̲e̲p̲ 1 u̲n̲t̲i̲l̲ 4 d̲o̲ b̲e̲g̲i̲n̲ 17 | i3 := 3*i; 18 | f̲o̲r̲ j := i+1 s̲t̲e̲p̲ 1 u̲n̲t̲i̲l̲ 5 d̲o̲ b̲e̲g̲i̲n̲ 19 | j3 := 3*j; 20 | p := (y[i3-2] - y[j3-2])↑2 + (y[i3-1] - y[j3-1])↑2 + (y[i3] - y[j3])↑2; 21 | d[i, j] := d[j, i] := 1/p/sqrt(p) 22 | e̲n̲d̲ 23 | e̲n̲d̲; 24 | f̲o̲r̲ i := 1 s̲t̲e̲p̲ 1 u̲n̲t̲i̲l̲ 5 d̲o̲ b̲e̲g̲i̲n̲ 25 | i3 := 3*i; 26 | d[i, i] := 0; 27 | p := y[i3-2]↑2 + y[i3-1]↑2 + y[i3]↑2; 28 | r[i] := 1/p/sqrt(p) 29 | e̲n̲d̲; 30 | A: i := (k - 1) ÷ 3 + 1; 31 | f := k2 * (- m[0] * y[k] * r[i] + 32 | SUM(j, 1, 5, m[j]*((y[3*(j-i)+k]-y[k])*d[i, j]-y[3*(j-i)+k]*r[j]))) 33 | e̲n̲d̲ f; 34 | 35 | p̲r̲o̲c̲e̲d̲u̲r̲e̲ RK3n(x, a, b, y, ya, z, za, fxyj, j, e, d, fi, n); 36 | v̲a̲l̲u̲e̲ b, fi, n; 37 | i̲n̲t̲e̲g̲e̲r̲ j, n; 38 | r̲e̲a̲l̲ x, a, b, fxyj; 39 | B̲o̲o̲l̲e̲a̲n̲ fi; 40 | a̲r̲r̲a̲y̲ y, ya, z, za, e, d; 41 | b̲e̲g̲i̲n̲ 42 | i̲n̲t̲e̲g̲e̲r̲ jj; 43 | r̲e̲a̲l̲ xl, h, hmin, int, hl, absh, fhm, discry, discrz, toly, tolz, mu, mu1, fhy, fhz; 44 | B̲o̲o̲l̲e̲a̲n̲ last, first, reject; 45 | a̲r̲r̲a̲y̲ yl, zl, k0, k1, k2, k3, k4, k5[1:n], ee[1:4*n]; 46 | 47 | i̲f̲ fi t̲h̲e̲n̲ b̲e̲g̲i̲n̲ 48 | d[3] := a; 49 | f̲o̲r̲ jj := 1 s̲t̲e̲p̲ 1 u̲n̲t̲i̲l̲ n d̲o̲ b̲e̲g̲i̲n̲ 50 | d[jj+3] := ya[jj]; 51 | d[n+jj+3] := za[jj] 52 | e̲n̲d̲ 53 | e̲n̲d̲; 54 | d[1] := 0; 55 | xl := d[3]; 56 | f̲o̲r̲ jj := 1 s̲t̲e̲p̲ 1 u̲n̲t̲i̲l̲ n d̲o̲ b̲e̲g̲i̲n̲ 57 | yl[jj] := d[jj+3]; 58 | zl[jj] := d[n+jj+3] 59 | e̲n̲d̲; 60 | i̲f̲ fi t̲h̲e̲n̲ 61 | d[2] := b - d[3]; 62 | absh := h := abs(d[2]); 63 | i̲f̲ b - xl < 0 t̲h̲e̲n̲ 64 | h := - h; 65 | int := abs(b - xl); 66 | hmin := int * e[1] + e[2]; 67 | f̲o̲r̲ jj := 2 s̲t̲e̲p̲ 1 u̲n̲t̲i̲l̲ 2*n d̲o̲ b̲e̲g̲i̲n̲ 68 | hl := int * e[2*jj-1] + e[2*jj]; 69 | i̲f̲ hl < hmin t̲h̲e̲n̲ 70 | hmin := hl 71 | e̲n̲d̲; 72 | f̲o̲r̲ jj := 1 s̲t̲e̲p̲ 1 u̲n̲t̲i̲l̲ 4*n d̲o̲ 73 | ee[jj] := e[jj]/int; 74 | first := reject := t̲r̲u̲e̲; 75 | i̲f̲ fi t̲h̲e̲n̲ b̲e̲g̲i̲n̲ 76 | last := t̲r̲u̲e̲; 77 | g̲o̲t̲o̲ step 78 | e̲n̲d̲; 79 | test: absh := abs(h); 80 | i̲f̲ absh < hmin t̲h̲e̲n̲ b̲e̲g̲i̲n̲ 81 | h := i̲f̲ h > 0 t̲h̲e̲n̲ hmin e̲l̲s̲e̲ - hmin; 82 | absh := hmin 83 | e̲n̲d̲; 84 | i̲f̲ h ≥ b - xl ≡ h ≥ 0 t̲h̲e̲n̲ b̲e̲g̲i̲n̲ 85 | d[2] := h; 86 | last := t̲r̲u̲e̲; 87 | h := b - xl; 88 | absh := abs(h) 89 | e̲n̲d̲ e̲l̲s̲e̲ 90 | last := f̲a̲l̲s̲e̲; 91 | step: i̲f̲ reject t̲h̲e̲n̲ b̲e̲g̲i̲n̲ 92 | x := xl; 93 | f̲o̲r̲ jj := 1 s̲t̲e̲p̲ 1 u̲n̲t̲i̲l̲ n d̲o̲ 94 | y[jj] := yl[jj]; 95 | f̲o̲r̲ j := 1 s̲t̲e̲p̲ 1 u̲n̲t̲i̲l̲ n d̲o̲ 96 | k0[j] := fxyj * h 97 | e̲n̲d̲ e̲l̲s̲e̲ b̲e̲g̲i̲n̲ 98 | fhy := h/hl; 99 | f̲o̲r̲ jj := 1 s̲t̲e̲p̲ 1 u̲n̲t̲i̲l̲ n d̲o̲ 100 | k0[jj] := k5[jj] * fhy 101 | e̲n̲d̲; 102 | x := xl + .27639 32022 50021 * h; 103 | f̲o̲r̲ jj := 1 s̲t̲e̲p̲ 1 u̲n̲t̲i̲l̲ n d̲o̲ 104 | y[jj] := yl[jj] + (zl[jj] * .27639 32022 50021 + 105 | k0[jj] * .03819 66011 25011) * h; 106 | f̲o̲r̲ j := 1 s̲t̲e̲p̲ 1 u̲n̲t̲i̲l̲ n d̲o̲ 107 | k1[j] := fxyj * h; 108 | x := xl + .72360 67977 49979 * h; 109 | f̲o̲r̲ jj := 1 s̲t̲e̲p̲ 1 u̲n̲t̲i̲l̲ n d̲o̲ 110 | y[jj] := yl[jj] + (zl[jj] * .72360 67977 49979 + 111 | k1[jj] * .26180 33988 74989) * h; 112 | f̲o̲r̲ j := 1 s̲t̲e̲p̲ 1 u̲n̲t̲i̲l̲ n d̲o̲ 113 | k2[j] := fxyj * h; 114 | x := xl + h * .5; 115 | f̲o̲r̲ jj := 1 s̲t̲e̲p̲ 1 u̲n̲t̲i̲l̲ n d̲o̲ 116 | y[jj] := yl[jj] + (zl[jj] * .5 + 117 | k0[jj] * .04687 5 + 118 | k1[jj] * .07982 41558 39840 - 119 | k2[jj] * .00169 91558 39840) * h; 120 | f̲o̲r̲ j := 1 s̲t̲e̲p̲ 1 u̲n̲t̲i̲l̲ n d̲o̲ 121 | k4[j] := fxyj * h; 122 | x := i̲f̲ last t̲h̲e̲n̲ b e̲l̲s̲e̲ xl + h; 123 | f̲o̲r̲ jj := 1 s̲t̲e̲p̲ 1 u̲n̲t̲i̲l̲ n d̲o̲ 124 | y[jj] := yl[jj] + (zl[jj] + 125 | k0[jj] * .30901 69943 74947 + 126 | k2[jj] * .19098 30056 25053) * h; 127 | f̲o̲r̲ j := 1 s̲t̲e̲p̲ 1 u̲n̲t̲i̲l̲ n d̲o̲ 128 | k3[j] := fxyj * h; 129 | f̲o̲r̲ jj := 1 s̲t̲e̲p̲ 1 u̲n̲t̲i̲l̲ n d̲o̲ 130 | y[jj] := yl[jj] + (zl[jj] + 131 | k0[jj] * .08333 33333 33333 + 132 | k1[jj] * .30150 28323 95825 + 133 | k2[jj] * .11516 38342 70842) * h; 134 | f̲o̲r̲ j := 1 s̲t̲e̲p̲ 1 u̲n̲t̲i̲l̲ n d̲o̲ 135 | k5[j] := fxyj * h; 136 | reject := f̲a̲l̲s̲e̲; 137 | fhm := 0; 138 | f̲o̲r̲ jj := 1 s̲t̲e̲p̲ 1 u̲n̲t̲i̲l̲ n d̲o̲ b̲e̲g̲i̲n̲ 139 | discry := abs((- k0[jj] * .5 + k1[jj] * 1.80901 69943 74947 + 140 | k2[jj] * .69098 30056 25053 - k4[jj] * 2) * h); 141 | discrz := abs((k0[jj] - k3[jj]) * 2 - (k1[jj] + k2[jj]) * 10 + 142 | k4[jj] * 16 + k5[jj] * 4); 143 | toly := absh * (abs(zl[jj]) * ee[2*jj-1] + ee[2*jj]); 144 | tolz := abs(k0[jj]) * ee[2*(jj+n)-1] + absh * ee[2*(jj+n)]; 145 | reject := discry > toly ∨ discrz > tolz ∨ reject; 146 | fhy := discry/toly; 147 | fhz := discrz/tolz; 148 | i̲f̲ fhz > fhy t̲h̲e̲n̲ 149 | fhy := fhz; 150 | i̲f̲ fhy > fhm t̲h̲e̲n̲ 151 | fhm := fhy 152 | e̲n̲d̲; 153 | mu := 1/(1 + fhm) + .45; 154 | i̲f̲ reject t̲h̲e̲n̲ b̲e̲g̲i̲n̲ 155 | i̲f̲ absh ≤ hmin t̲h̲e̲n̲ b̲e̲g̲i̲n̲ 156 | d[1] := d[1] + 1; 157 | f̲o̲r̲ jj := 1 s̲t̲e̲p̲ 1 u̲n̲t̲i̲l̲ n d̲o̲ b̲e̲g̲i̲n̲ 158 | y[jj] := yl[jj]; 159 | z[jj] := zl[jj] 160 | e̲n̲d̲; 161 | first := t̲r̲u̲e̲; 162 | g̲o̲t̲o̲ next 163 | e̲n̲d̲; 164 | h := mu * h; 165 | g̲o̲t̲o̲ test 166 | e̲n̲d̲ rej; 167 | i̲f̲ first t̲h̲e̲n̲ b̲e̲g̲i̲n̲ 168 | first := f̲a̲l̲s̲e̲; 169 | hl := h; 170 | h := mu * h; 171 | g̲o̲t̲o̲ acc 172 | e̲n̲d̲; 173 | fhy := mu * h/hl + mu - mu1; 174 | hl := h; 175 | h := fhy * h; 176 | acc: mu1 := mu; 177 | f̲o̲r̲ jj := 1 s̲t̲e̲p̲ 1 u̲n̲t̲i̲l̲ n d̲o̲ 178 | z[jj] := zl[jj] + (k0[jj] + k3[jj]) * .08333 33333 33333 + 179 | (k1[jj] + k2[jj]) * .41666 66666 66667; 180 | next: i̲f̲ b ≠ x t̲h̲e̲n̲ b̲e̲g̲i̲n̲ 181 | xl := x; 182 | f̲o̲r̲ jj := 1 s̲t̲e̲p̲ 1 u̲n̲t̲i̲l̲ n d̲o̲ b̲e̲g̲i̲n̲ 183 | yl[jj] := y[jj]; 184 | zl[jj] := z[jj] 185 | e̲n̲d̲; 186 | g̲o̲t̲o̲ test 187 | e̲n̲d̲; 188 | i̲f̲ ¬ last t̲h̲e̲n̲ 189 | d[2] := h; 190 | d[3] := x; 191 | f̲o̲r̲ jj := 1 s̲t̲e̲p̲ 1 u̲n̲t̲i̲l̲ n d̲o̲ b̲e̲g̲i̲n̲ 192 | d[jj+3] := y[jj]; 193 | d[n+jj+3] := z[jj] 194 | e̲n̲d̲ 195 | e̲n̲d̲ RK3n; 196 | 197 | p̲r̲o̲c̲e̲d̲u̲r̲e̲ TYP(x); 198 | a̲r̲r̲a̲y̲ x; 199 | b̲e̲g̲i̲n̲ 200 | i̲n̲t̲e̲g̲e̲r̲ k; 201 | NLCR; 202 | PRINTTEXT(`T = '); 203 | ABSFIXT(7, 1, t+a); 204 | NLCR; 205 | NLCR; 206 | f̲o̲r̲ k := 1 s̲t̲e̲p̲ 1 u̲n̲t̲i̲l̲ 5 d̲o̲ b̲e̲g̲i̲n̲ 207 | i̲f̲ k=1 t̲h̲e̲n̲ PRINTTEXT(`J ') e̲l̲s̲e̲ 208 | i̲f̲ k=2 t̲h̲e̲n̲ PRINTTEXT(`S ') e̲l̲s̲e̲ 209 | i̲f̲ k=3 t̲h̲e̲n̲ PRINTTEXT(`U ') e̲l̲s̲e̲ 210 | i̲f̲ k=4 t̲h̲e̲n̲ PRINTTEXT(`N ') e̲l̲s̲e̲ 211 | PRINTTEXT(`P '); 212 | FIXT(2, 9, x[3*k-2]); 213 | FIXT(2, 9, x[3*k-1]); 214 | FIXT(2, 9, x[3*k]); 215 | NLCR 216 | e̲n̲d̲ 217 | e̲n̲d̲ TYP; 218 | 219 | a := read; 220 | f̲o̲r̲ k := 1 s̲t̲e̲p̲ 1 u̲n̲t̲i̲l̲ 15 d̲o̲ b̲e̲g̲i̲n̲ 221 | ya[k] := read; 222 | za[k] := read 223 | e̲n̲d̲; 224 | f̲o̲r̲ k := 0 s̲t̲e̲p̲ 1 u̲n̲t̲i̲l̲ 5 d̲o̲ 225 | m[k] := read; 226 | k2 := read; 227 | e[1] := read; 228 | 229 | f̲o̲r̲ k := 2 s̲t̲e̲p̲ 1 u̲n̲t̲i̲l̲ 60 d̲o̲ 230 | e[k] := e[1]; 231 | PRINTTEXT(`JAZ164, R743, Outer Planets'); 232 | NLCR; 233 | NLCR; 234 | f̲o̲r̲ k := 1 s̲t̲e̲p̲ 1 u̲n̲t̲i̲l̲ 15 d̲o̲ b̲e̲g̲i̲n̲ 235 | FLOT(12, ya[k]); 236 | FLOT(12, za[k]); 237 | NLCR 238 | e̲n̲d̲; 239 | f̲o̲r̲ k := 0 s̲t̲e̲p̲ 1 u̲n̲t̲i̲l̲ 5 d̲o̲ b̲e̲g̲i̲n̲ 240 | NLCR; 241 | FLOT(12, m[k]) 242 | e̲n̲d̲; 243 | NLCR; 244 | NLCR; 245 | FLOT(12, k2); 246 | NLCR; 247 | NLCR; 248 | PRINTTEXT(`eps = '); 249 | FLOT(2, e[1]); 250 | NLCR; 251 | t := 0; 252 | TYP(ya); 253 | fi := t̲r̲u̲e̲; 254 | f̲o̲r̲ t := 500, 1000 d̲o̲ b̲e̲g̲i̲n̲ 255 | RK3n(x, 0, t, y, ya, z, za, f(k), k, e, d, fi, 15); 256 | fi := f̲a̲l̲s̲e̲; 257 | TYP(y) 258 | e̲n̲d̲ 259 | e̲n̲d̲ 260 | -------------------------------------------------------------------------------- /examples/outer_planets.md: -------------------------------------------------------------------------------- 1 | ``` 2 | $ ./outer_planets.sh 3 | JAZ164, R743, Outer Planets 4 | 5 | +.342947415189⏨+ 1 -.557160570446⏨- 2 6 | +.335386959711⏨+ 1 +.505696783289⏨- 2 7 | +.135494901715⏨+ 1 +.230578543901⏨- 2 8 | +.664145542550⏨+ 1 -.415570776342⏨- 2 9 | +.597156957878⏨+ 1 +.365682722812⏨- 2 10 | +.218231499728⏨+ 1 +.169143213293⏨- 2 11 | +.112630437207⏨+ 2 -.325325669158⏨- 2 12 | +.146952576794⏨+ 2 +.189706021964⏨- 2 13 | +.627960525067⏨+ 1 +.877265322780⏨- 3 14 | -.301552268759⏨+ 2 -.240476254170⏨- 3 15 | +.165699966404⏨+ 1 -.287659532608⏨- 2 16 | +.143785752721⏨+ 1 -.117219543175⏨- 2 17 | -.211238353380⏨+ 2 -.176860753121⏨- 2 18 | +.284465098142⏨+ 2 -.216393453025⏨- 2 19 | +.153882659679⏨+ 2 -.148647893090⏨- 3 20 | 21 | +.100000597682⏨+ 1 22 | +.954786104043⏨- 3 23 | +.285583733151⏨- 3 24 | +.437273164546⏨- 4 25 | +.517759138449⏨- 4 26 | +.277777777778⏨- 5 27 | 28 | +.295912208286⏨- 3 29 | 30 | eps = +.10⏨- 3 31 | 32 | T = 2430000.5 33 | 34 | J + 3.429474152 + 3.353869597 + 1.354949017 35 | S + 6.641455426 + 5.971569579 + 2.182314997 36 | U +11.263043721 +14.695257679 + 6.279605251 37 | N -30.155226876 + 1.656999664 + 1.437857527 38 | P -21.123835338 +28.446509814 +15.388265968 39 | 40 | T = 2430500.5 41 | 42 | J - 0.049534455 + 4.714982495 + 2.023963513 43 | S + 4.277614611 + 7.483210480 + 2.909418313 44 | U + 9.582290073 +15.567813885 + 6.685732380 45 | N -30.235783049 + 0.215924799 + 0.849602274 46 | P -21.994991444 +27.345130515 +15.303485551 47 | 48 | T = 2431000.5 49 | 50 | J - 3.535429691 + 3.610053139 + 1.635176964 51 | S + 1.496149963 + 8.261862331 + 3.351487277 52 | U + 7.805112554 +16.281370897 + 7.023579152 53 | N -30.235569469 - 1.228279723 + 0.257987477 54 | P -22.837219187 +26.205087209 +15.197406000 55 | ``` 56 | -------------------------------------------------------------------------------- /examples/outer_planets.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Run a sample ALGOL 60 program from Appendix B of article 4 | # "The Dijkstra–Zonneveld ALGOL 60 compiler for the Electrologica X1" 5 | # by Kruseman Aretz. 6 | # 7 | x1sim outer_planets.a60 << END_OF_INPUT 8 | 9 | 2430000.5 10 | 11 | +.342947415189⏨+1 -.557160570446⏨-2 12 | +.335386959711⏨+1 +.505696783289⏨-2 13 | +.135494901715⏨+1 +.230578543901⏨-2 14 | +.664145542550⏨+1 -.415570776342⏨-2 15 | +.597156957878⏨+1 +.365682722812⏨-2 16 | +.218231499728⏨+1 +.169143213293⏨-2 17 | +.112630437207⏨+2 -.325325669158⏨-2 18 | +.146952576794⏨+2 +.189706021964⏨-2 19 | +.627960525067⏨+1 +.877265322780⏨-3 20 | -.301552268759⏨+2 -.240476254170⏨-3 21 | +.165699966404⏨+1 -.287659532608⏨-2 22 | +.143785752721⏨+1 -.117219543175⏨-2 23 | -.211238353380⏨+2 -.176860753121⏨-2 24 | +.284465098142⏨+2 -.216393453025⏨-2 25 | +.153882659679⏨+2 -.148647893090⏨-3 26 | 27 | +.100000597682⏨+1 28 | +.954786104043⏨-3 29 | +.285583733151⏨-3 30 | +.437273164546⏨-4 31 | +.517759138449⏨-4 32 | +.277777777778⏨-5 33 | 34 | +.295912208286⏨-3 35 | 36 | +.10⏨-3 37 | 38 | END_OF_INPUT 39 | -------------------------------------------------------------------------------- /examples/palindromic_primes.a60: -------------------------------------------------------------------------------- 1 | b̲e̲g̲i̲n̲ 2 | i̲n̲t̲e̲g̲e̲r̲ p, m; 3 | b̲e̲g̲i̲n̲ 4 | B̲o̲o̲l̲e̲a̲n̲ a̲r̲r̲a̲y̲ prime[2 : 100000]; 5 | 6 | c̲o̲m̲m̲e̲n̲t̲ Check for palindromic prime; 7 | B̲o̲o̲l̲e̲a̲n̲ p̲r̲o̲c̲e̲d̲u̲r̲e̲ ispalindrome(n); v̲a̲l̲u̲e̲ n; i̲n̲t̲e̲g̲e̲r̲ n; b̲e̲g̲i̲n̲ 8 | i̲n̲t̲e̲g̲e̲r̲ i, j, q; 9 | i̲n̲t̲e̲g̲e̲r̲ a̲r̲r̲a̲y̲ d[1:10]; 10 | c̲o̲m̲m̲e̲n̲t̲ - decompose n into its digits; 11 | j := 0; 12 | f̲o̲r̲ j := j w̲h̲i̲l̲e̲ n > 0 d̲o̲ b̲e̲g̲i̲n̲ 13 | j := j + 1; 14 | q := entier(n / 10); 15 | d[j] := n - q * 10; 16 | n := q; 17 | e̲n̲d̲; 18 | c̲o̲m̲m̲e̲n̲t̲ - move from outside in checking for equality; 19 | i := 1; 20 | f̲o̲r̲ i := i w̲h̲i̲l̲e̲ (i < j) ∧ (d[i] = d[j]) d̲o̲ b̲e̲g̲i̲n̲ 21 | i := i + 1; 22 | j := j - 1; 23 | e̲n̲d̲; 24 | ispalindrome := d[i] = d[j]; 25 | e̲n̲d̲; 26 | 27 | c̲o̲m̲m̲e̲n̲t̲ Find primes using sieve of Eratosthenes; 28 | PRINTTEXT(`Computing primes up to 100000...'); 29 | f̲o̲r̲ p := 2, 3 s̲t̲e̲p̲ 2 u̲n̲t̲i̲l̲ 100000 d̲o̲ 30 | prime[p] := t̲r̲u̲e̲; 31 | f̲o̲r̲ p := 2, 3 s̲t̲e̲p̲ 2 u̲n̲t̲i̲l̲ 316 d̲o̲ b̲e̲g̲i̲n̲ 32 | i̲f̲ prime[p] t̲h̲e̲n̲ 33 | f̲o̲r̲ m := p * p s̲t̲e̲p̲ p u̲n̲t̲i̲l̲ 100000 d̲o̲ 34 | prime[m] := f̲a̲l̲s̲e̲; 35 | e̲n̲d̲; 36 | NLCR; 37 | 38 | PRINTTEXT(`Palindromic primes:'); 39 | f̲o̲r̲ p := 2, 3 s̲t̲e̲p̲ 2 u̲n̲t̲i̲l̲ 100000 d̲o̲ b̲e̲g̲i̲n̲ 40 | i̲f̲ prime[p] ∧ ispalindrome(p) t̲h̲e̲n̲ b̲e̲g̲i̲n̲ 41 | SPACE(1); 42 | print(p) 43 | e̲n̲d̲ 44 | e̲n̲d̲; 45 | NLCR 46 | e̲n̲d̲ 47 | e̲n̲d̲ 48 | -------------------------------------------------------------------------------- /examples/pentomino.a60: -------------------------------------------------------------------------------- 1 | b̲e̲g̲i̲n̲ 2 | c̲o̲m̲m̲e̲n̲t̲ pentomino, 130968; 3 | 4 | i̲n̲t̲e̲g̲e̲r̲ score, nummer, lengte, breedte, aantal stenen, aantal standen, 5 | i, j, k, teller, lb; 6 | lengte := read; 7 | breedte := read; 8 | aantal stenen := read; 9 | aantal standen := read; 10 | lb := lengte * (breedte - 1); 11 | 12 | b̲e̲g̲i̲n̲ 13 | i̲n̲t̲e̲g̲e̲r̲ a̲r̲r̲a̲y̲ bord[-4*lengte+1 : 60+4*lengte], 14 | standen, wijzer[1 : aantal stenen], 15 | informatie[1 : 4 * aantal standen]; 16 | B̲o̲o̲l̲e̲a̲n̲ a̲r̲r̲a̲y̲ ongebruikt[1 : aantal stenen]; 17 | 18 | p̲r̲o̲c̲e̲d̲u̲r̲e̲ output; b̲e̲g̲i̲n̲ 19 | i̲n̲t̲e̲g̲e̲r̲ i, j; 20 | score := score + 1; 21 | SPACE(1); 22 | f̲o̲r̲ j := 1 s̲t̲e̲p̲ 1 u̲n̲t̲i̲l̲ 2 * lengte d̲o̲ b̲e̲g̲i̲n̲ 23 | PRINTTEXT(`-'); 24 | SPACE(1) 25 | e̲n̲d̲; 26 | c̲o̲m̲m̲e̲n̲t̲ ABSFIXT(6, 2, time); 27 | NLCR; 28 | f̲o̲r̲ i := 0 s̲t̲e̲p̲ lengte u̲n̲t̲i̲l̲ lb d̲o̲ b̲e̲g̲i̲n̲ 29 | PRINTTEXT(`I'); 30 | f̲o̲r̲ j := 1 s̲t̲e̲p̲ 1 u̲n̲t̲i̲l̲ lengte - 1 d̲o̲ b̲e̲g̲i̲n̲ 31 | SPACE(3); 32 | i̲f̲ bord[i + j] ≠ bord[i + j + 1] t̲h̲e̲n̲ 33 | PRINTTEXT(`I') 34 | e̲l̲s̲e̲ 35 | SPACE(1) 36 | e̲n̲d̲; 37 | SPACE(3); PRINTTEXT(`I'); NLCR; SPACE(1); 38 | i̲f̲ i < lb t̲h̲e̲n̲ b̲e̲g̲i̲n̲ 39 | f̲o̲r̲ j := 1 s̲t̲e̲p̲ 1 u̲n̲t̲i̲l̲ lengte d̲o̲ b̲e̲g̲i̲n̲ 40 | i̲f̲ bord[i + j] ≠ bord[i + j + lengte] t̲h̲e̲n̲ b̲e̲g̲i̲n̲ 41 | PRINTTEXT(`-'); SPACE(1); 42 | PRINTTEXT(`-'); SPACE(1) 43 | e̲n̲d̲ e̲l̲s̲e̲ 44 | SPACE(4) 45 | e̲n̲d̲ 46 | e̲n̲d̲ e̲l̲s̲e̲ 47 | f̲o̲r̲ j := 1 s̲t̲e̲p̲ 1 u̲n̲t̲i̲l̲ 2 * lengte d̲o̲ b̲e̲g̲i̲n̲ 48 | PRINTTEXT(`-'); SPACE(1) 49 | e̲n̲d̲; 50 | NLCR 51 | e̲n̲d̲; 52 | NLCR; NLCR; 53 | i̲f̲ score = 7 t̲h̲e̲n̲ 54 | g̲o̲t̲o̲ ex 55 | e̲n̲d̲ output; 56 | 57 | p̲r̲o̲c̲e̲d̲u̲r̲e̲ up(veld, kolom); 58 | v̲a̲l̲u̲e̲ veld, kolom; 59 | i̲n̲t̲e̲g̲e̲r̲ veld, kolom; 60 | b̲e̲g̲i̲n̲ 61 | i̲n̲t̲e̲g̲e̲r̲ i, j, k, r, w, steen, aantal; 62 | nummer := nummer + 1; 63 | f̲o̲r̲ steen := 1 s̲t̲e̲p̲ 1 u̲n̲t̲i̲l̲ aantal stenen d̲o̲ 64 | i̲f̲ ongebruikt[steen] t̲h̲e̲n̲ b̲e̲g̲i̲n̲ 65 | ongebruikt[steen] := f̲a̲l̲s̲e̲; 66 | bord[veld] := steen; 67 | aantal := standen[steen] - 1; 68 | f̲o̲r̲ i := 0 s̲t̲e̲p̲ 1 u̲n̲t̲i̲l̲ aantal d̲o̲ b̲e̲g̲i̲n̲ 69 | w := wijzer[steen] + 4 * i; 70 | i̲f̲ bord[informatie[w] + veld] = 0 t̲h̲e̲n̲ b̲e̲g̲i̲n̲ 71 | i̲f̲ bord[informatie[w + 1] + veld] = 0 t̲h̲e̲n̲ b̲e̲g̲i̲n̲ 72 | i̲f̲ bord[informatie[w + 2] + veld] = 0 t̲h̲e̲n̲ b̲e̲g̲i̲n̲ 73 | i̲f̲ bord[informatie[w + 3] + veld] = 0 t̲h̲e̲n̲ b̲e̲g̲i̲n̲ 74 | f̲o̲r̲ j := 0, 1, 2, 3 d̲o̲ 75 | bord[informatie[w + j] + veld] := steen; 76 | i̲f̲ nummer = aantal stenen t̲h̲e̲n̲ 77 | output 78 | e̲l̲s̲e̲ b̲e̲g̲i̲n̲ 79 | f̲o̲r̲ k := kolom s̲t̲e̲p̲ 1 u̲n̲t̲i̲l̲ lengte d̲o̲ 80 | f̲o̲r̲ r := 0 s̲t̲e̲p̲ lengte u̲n̲t̲i̲l̲ lb d̲o̲ 81 | i̲f̲ bord[r + k] = 0 t̲h̲e̲n̲ 82 | g̲o̲t̲o̲ beet; 83 | beet: up(r + k, k) 84 | e̲n̲d̲; 85 | f̲o̲r̲ j := 0, 1, 2, 3 d̲o̲ 86 | bord[informatie[w + j] + veld] := 0 87 | e̲n̲d̲ 88 | e̲n̲d̲ 89 | e̲n̲d̲ 90 | e̲n̲d̲ 91 | e̲n̲d̲; 92 | ongebruikt[steen] := t̲r̲u̲e̲ 93 | e̲n̲d̲; 94 | bord[veld] := 0; 95 | down: nummer := nummer - 1 96 | e̲n̲d̲ up; 97 | 98 | teller := 1; 99 | f̲o̲r̲ i := 1 s̲t̲e̲p̲ 1 u̲n̲t̲i̲l̲ aantal stenen d̲o̲ b̲e̲g̲i̲n̲ 100 | j := read; 101 | c̲o̲m̲m̲e̲n̲t̲ steennummer, wordt niet gebruikt; 102 | wijzer[i] := teller; 103 | standen[i] := read; 104 | f̲o̲r̲ j := 1 s̲t̲e̲p̲ 1 u̲n̲t̲i̲l̲ standen[i] d̲o̲ b̲e̲g̲i̲n̲ 105 | f̲o̲r̲ k := 0 s̲t̲e̲p̲ 1 u̲n̲t̲i̲l̲ 3 d̲o̲ b̲e̲g̲i̲n̲ 106 | nummer := read; 107 | nummer := nummer + 5 * sign(nummer); 108 | informatie[teller + k] := nummer - nummer ÷ 10 * 10 + 109 | nummer ÷ 10 * lengte - 5 * sign(nummer) 110 | e̲n̲d̲; 111 | teller := teller + 4 112 | e̲n̲d̲ 113 | e̲n̲d̲; 114 | f̲o̲r̲ i := -4 * lengte + 1 s̲t̲e̲p̲ 1 u̲n̲t̲i̲l̲ 0, 115 | 61 s̲t̲e̲p̲ 1 u̲n̲t̲i̲l̲ 60 + 4 * lengte d̲o̲ 116 | bord[i] := - 1; 117 | f̲o̲r̲ i := 1 s̲t̲e̲p̲ 1 u̲n̲t̲i̲l̲ 60 d̲o̲ 118 | bord[i] := 0; 119 | f̲o̲r̲ i := 1 s̲t̲e̲p̲ 1 u̲n̲t̲i̲l̲ aantal stenen d̲o̲ 120 | ongebruikt[i] := t̲r̲u̲e̲; 121 | score := nummer := 0; 122 | PRINTTEXT(`Pentomino '); print(breedte); PRINTTEXT(`x'); print(lengte); 123 | NLCR; PRINTTEXT(`The first 7 solutions:'); NLCR; NLCR; NLCR; 124 | up(1, 1); 125 | ex: 126 | e̲n̲d̲ 127 | e̲n̲d̲ 128 | -------------------------------------------------------------------------------- /examples/pentomino3x20.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Run pentomino solver. 4 | # 5 | x1sim pentomino.a60 << END_OF_INPUT 6 | 20 7 | 3 8 | 12 9 | 63 10 | 1 1 -9 1 2 11 11 | 12 | 2 4 1 2 10 12 13 | 1 10 20 21 14 | 2 10 11 12 15 | 1 11 20 21 16 | 17 | 3 4 10 11 12 20 18 | -8 1 2 12 19 | 1 2 11 21 20 | -19 -9 1 2 21 | 22 | 4 4 10 11 12 22 23 | 1 11 21 22 24 | -8 1 2 10 25 | -19 -18 -9 1 26 | 27 | 5 4 1 2 10 20 28 | 10 20 21 22 29 | -18 -8 1 2 30 | 1 2 12 22 31 | 32 | 6 4 10 11 21 22 33 | -9 -8 1 10 34 | 1 11 12 22 35 | -18 -9 -8 1 36 | 37 | 7 2 1 2 3 4 38 | 10 20 30 40 39 | 40 | 8 8 -8 1 2 11 41 | -9 1 11 12 42 | -9 1 2 10 43 | 1 11 12 21 44 | 10 11 12 21 45 | -9 -8 1 11 46 | -9 1 2 12 47 | -19 -9 -8 1 48 | 49 | 9 8 10 11 21 31 50 | -8 -7 1 2 51 | 10 20 21 31 52 | -9 -8 -7 1 53 | 1 11 12 13 54 | -9 1 10 20 55 | 1 2 12 13 56 | -19 -9 1 10 57 | 58 | 10 8 10 11 20 30 59 | 1 2 3 12 60 | -19 -9 1 11 61 | -9 1 2 3 62 | 1 2 3 11 63 | -9 1 11 21 64 | -8 1 2 3 65 | 10 20 21 30 66 | 67 | 11 8 1 2 3 10 68 | 10 20 30 31 69 | 1 10 20 30 70 | 1 2 3 13 71 | 10 11 12 13 72 | -29 -19 -9 1 73 | -7 1 2 3 74 | 1 11 21 31 75 | 76 | 12 8 1 10 11 20 77 | 1 10 11 12 78 | 1 2 10 11 79 | 1 10 11 21 80 | 10 11 20 21 81 | -9 1 10 11 82 | 1 2 11 12 83 | -9 -8 1 2 84 | 85 | END_OF_INPUT 86 | -------------------------------------------------------------------------------- /examples/pentomino4x15.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Run pentomino solver. 4 | # 5 | x1sim pentomino.a60 << END_OF_INPUT 6 | 15 7 | 4 8 | 12 9 | 63 10 | 1 1 -9 1 2 11 11 | 12 | 2 4 1 2 10 12 13 | 1 10 20 21 14 | 2 10 11 12 15 | 1 11 20 21 16 | 17 | 3 4 10 11 12 20 18 | -8 1 2 12 19 | 1 2 11 21 20 | -19 -9 1 2 21 | 22 | 4 4 10 11 12 22 23 | 1 11 21 22 24 | -8 1 2 10 25 | -19 -18 -9 1 26 | 27 | 5 4 1 2 10 20 28 | 10 20 21 22 29 | -18 -8 1 2 30 | 1 2 12 22 31 | 32 | 6 4 10 11 21 22 33 | -9 -8 1 10 34 | 1 11 12 22 35 | -18 -9 -8 1 36 | 37 | 7 2 1 2 3 4 38 | 10 20 30 40 39 | 40 | 8 8 -8 1 2 11 41 | -9 1 11 12 42 | -9 1 2 10 43 | 1 11 12 21 44 | 10 11 12 21 45 | -9 -8 1 11 46 | -9 1 2 12 47 | -19 -9 -8 1 48 | 49 | 9 8 10 11 21 31 50 | -8 -7 1 2 51 | 10 20 21 31 52 | -9 -8 -7 1 53 | 1 11 12 13 54 | -9 1 10 20 55 | 1 2 12 13 56 | -19 -9 1 10 57 | 58 | 10 8 10 11 20 30 59 | 1 2 3 12 60 | -19 -9 1 11 61 | -9 1 2 3 62 | 1 2 3 11 63 | -9 1 11 21 64 | -8 1 2 3 65 | 10 20 21 30 66 | 67 | 11 8 1 2 3 10 68 | 10 20 30 31 69 | 1 10 20 30 70 | 1 2 3 13 71 | 10 11 12 13 72 | -29 -19 -9 1 73 | -7 1 2 3 74 | 1 11 21 31 75 | 76 | 12 8 1 10 11 20 77 | 1 10 11 12 78 | 1 2 10 11 79 | 1 10 11 21 80 | 10 11 20 21 81 | -9 1 10 11 82 | 1 2 11 12 83 | -9 -8 1 2 84 | 85 | END_OF_INPUT 86 | -------------------------------------------------------------------------------- /examples/pentomino5x12.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Run pentomino solver. 4 | # 5 | x1sim pentomino.a60 << END_OF_INPUT 6 | 12 7 | 5 8 | 12 9 | 63 10 | 1 1 -9 1 2 11 11 | 12 | 2 4 1 2 10 12 13 | 1 10 20 21 14 | 2 10 11 12 15 | 1 11 20 21 16 | 17 | 3 4 10 11 12 20 18 | -8 1 2 12 19 | 1 2 11 21 20 | -19 -9 1 2 21 | 22 | 4 4 10 11 12 22 23 | 1 11 21 22 24 | -8 1 2 10 25 | -19 -18 -9 1 26 | 27 | 5 4 1 2 10 20 28 | 10 20 21 22 29 | -18 -8 1 2 30 | 1 2 12 22 31 | 32 | 6 4 10 11 21 22 33 | -9 -8 1 10 34 | 1 11 12 22 35 | -18 -9 -8 1 36 | 37 | 7 2 1 2 3 4 38 | 10 20 30 40 39 | 40 | 8 8 -8 1 2 11 41 | -9 1 11 12 42 | -9 1 2 10 43 | 1 11 12 21 44 | 10 11 12 21 45 | -9 -8 1 11 46 | -9 1 2 12 47 | -19 -9 -8 1 48 | 49 | 9 8 10 11 21 31 50 | -8 -7 1 2 51 | 10 20 21 31 52 | -9 -8 -7 1 53 | 1 11 12 13 54 | -9 1 10 20 55 | 1 2 12 13 56 | -19 -9 1 10 57 | 58 | 10 8 10 11 20 30 59 | 1 2 3 12 60 | -19 -9 1 11 61 | -9 1 2 3 62 | 1 2 3 11 63 | -9 1 11 21 64 | -8 1 2 3 65 | 10 20 21 30 66 | 67 | 11 8 1 2 3 10 68 | 10 20 30 31 69 | 1 10 20 30 70 | 1 2 3 13 71 | 10 11 12 13 72 | -29 -19 -9 1 73 | -7 1 2 3 74 | 1 11 21 31 75 | 76 | 12 8 1 10 11 20 77 | 1 10 11 12 78 | 1 2 10 11 79 | 1 10 11 21 80 | 10 11 20 21 81 | -9 1 10 11 82 | 1 2 11 12 83 | -9 -8 1 2 84 | 85 | END_OF_INPUT 86 | -------------------------------------------------------------------------------- /examples/pentomino6x10.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Run pentomino solver. 4 | # 5 | x1sim pentomino.a60 << END_OF_INPUT 6 | 10 7 | 6 8 | 12 9 | 63 10 | 1 1 -9 1 2 11 11 | 12 | 2 4 1 2 10 12 13 | 1 10 20 21 14 | 2 10 11 12 15 | 1 11 20 21 16 | 17 | 3 4 10 11 12 20 18 | -8 1 2 12 19 | 1 2 11 21 20 | -19 -9 1 2 21 | 22 | 4 4 10 11 12 22 23 | 1 11 21 22 24 | -8 1 2 10 25 | -19 -18 -9 1 26 | 27 | 5 4 1 2 10 20 28 | 10 20 21 22 29 | -18 -8 1 2 30 | 1 2 12 22 31 | 32 | 6 4 10 11 21 22 33 | -9 -8 1 10 34 | 1 11 12 22 35 | -18 -9 -8 1 36 | 37 | 7 2 1 2 3 4 38 | 10 20 30 40 39 | 40 | 8 8 -8 1 2 11 41 | -9 1 11 12 42 | -9 1 2 10 43 | 1 11 12 21 44 | 10 11 12 21 45 | -9 -8 1 11 46 | -9 1 2 12 47 | -19 -9 -8 1 48 | 49 | 9 8 10 11 21 31 50 | -8 -7 1 2 51 | 10 20 21 31 52 | -9 -8 -7 1 53 | 1 11 12 13 54 | -9 1 10 20 55 | 1 2 12 13 56 | -19 -9 1 10 57 | 58 | 10 8 10 11 20 30 59 | 1 2 3 12 60 | -19 -9 1 11 61 | -9 1 2 3 62 | 1 2 3 11 63 | -9 1 11 21 64 | -8 1 2 3 65 | 10 20 21 30 66 | 67 | 11 8 1 2 3 10 68 | 10 20 30 31 69 | 1 10 20 30 70 | 1 2 3 13 71 | 10 11 12 13 72 | -29 -19 -9 1 73 | -7 1 2 3 74 | 1 11 21 31 75 | 76 | 12 8 1 10 11 20 77 | 1 10 11 12 78 | 1 2 10 11 79 | 1 10 11 21 80 | 10 11 20 21 81 | -9 1 10 11 82 | 1 2 11 12 83 | -9 -8 1 2 84 | 85 | END_OF_INPUT 86 | -------------------------------------------------------------------------------- /examples/perfect_numbers.a60: -------------------------------------------------------------------------------- 1 | b̲e̲g̲i̲n̲ 2 | c̲o̲m̲m̲e̲n̲t̲ Return n mod m; 3 | i̲n̲t̲e̲g̲e̲r̲ p̲r̲o̲c̲e̲d̲u̲r̲e̲ mod(n, m); v̲a̲l̲u̲e̲ n, m; i̲n̲t̲e̲g̲e̲r̲ n, m; b̲e̲g̲i̲n̲ 4 | mod := n - (n ÷ m * m); 5 | e̲n̲d̲; 6 | 7 | c̲o̲m̲m̲e̲n̲t̲ Check whether is perfect; 8 | B̲o̲o̲l̲e̲a̲n̲ p̲r̲o̲c̲e̲d̲u̲r̲e̲ isperfect(n); v̲a̲l̲u̲e̲ n; i̲n̲t̲e̲g̲e̲r̲ n; b̲e̲g̲i̲n̲ 9 | i̲n̲t̲e̲g̲e̲r̲ sum, f1, f2; 10 | sum := 1; 11 | f1 := 1; 12 | f̲o̲r̲ f1 := f1 + 1 w̲h̲i̲l̲e̲ (f1 * f1) ≤ n d̲o̲ b̲e̲g̲i̲n̲ 13 | i̲f̲ mod(n, f1) = 0 t̲h̲e̲n̲ b̲e̲g̲i̲n̲ 14 | sum := sum + f1; 15 | f2 := n / f1; 16 | i̲f̲ f2 > f1 t̲h̲e̲n̲ 17 | sum := sum + f2; 18 | e̲n̲d̲; 19 | e̲n̲d̲; 20 | isperfect := (sum = n); 21 | e̲n̲d̲; 22 | 23 | i̲n̲t̲e̲g̲e̲r̲ i, count; 24 | PRINTTEXT(`Searching up to 10000 for perfect numbers:'); 25 | count := 0; 26 | f̲o̲r̲ i := 2 s̲t̲e̲p̲ 1 u̲n̲t̲i̲l̲ 10000 d̲o̲ 27 | i̲f̲ isperfect(i) t̲h̲e̲n̲ b̲e̲g̲i̲n̲ 28 | SPACE(1); 29 | print(i); 30 | count := count + 1 31 | e̲n̲d̲; 32 | NLCR; 33 | print(count); 34 | PRINTTEXT(` were found.'); 35 | NLCR 36 | e̲n̲d̲ 37 | -------------------------------------------------------------------------------- /examples/quinio.md: -------------------------------------------------------------------------------- 1 | ``` 2 | $ x1sim quinio.a60 3 | 4 | 19 5 | Who plays first, you (1), or I (0)? 6 | Enter number: X1 N.N. 7 | 1 . 10 - 10 8 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 9 | 1 . . . . . . . . . . . . . . . . . . . 10 | 2 . . . . . . . . . . . . . . . . . . . 11 | 3 . . . . . . . . . . . . . . . . . . . 12 | 4 . . . . . . . . . . . . . . . . . . . 13 | 5 . . . . . . . . . . . . . . . . . . . 14 | 6 . . . . . . . . . . . . . . . . . . . 15 | 7 . . . . . . . . . . . . . . . . . . . 16 | 8 . . . . . . . . . . . . . . . . . . . 17 | 9 . . . . . . . . . . . . . . . . . . . 18 | 10 . . . . . . . . . X . . . . . . . . . 19 | 11 . . . . . . . . . . . . . . . . . . . 20 | 12 . . . . . . . . . . . . . . . . . . . 21 | 13 . . . . . . . . . . . . . . . . . . . 22 | 14 . . . . . . . . . . . . . . . . . . . 23 | 15 . . . . . . . . . . . . . . . . . . . 24 | 16 . . . . . . . . . . . . . . . . . . . 25 | 17 . . . . . . . . . . . . . . . . . . . 26 | 18 . . . . . . . . . . . . . . . . . . . 27 | 19 . . . . . . . . . . . . . . . . . . . 28 | Which row? 29 | Enter number: Which column? 30 | Enter number: 31 | 2 . 9 - 9 32 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 33 | 1 . . . . . . . . . . . . . . . . . . . 34 | 2 . . . . . . . . . . . . . . . . . . . 35 | 3 . . . . . . . . . . . . . . . . . . . 36 | 4 . . . . . . . . . . . . . . . . . . . 37 | 5 . . . . . . . . . . . . . . . . . . . 38 | 6 . . . . . . . . . . . . . . . . . . . 39 | 7 . . . . . . . . . . . . . . . . . . . 40 | 8 . . . . . . . . . . . . . . . . . . . 41 | 9 . . . . . . . . O . . . . . . . . . . 42 | 10 . . . . . . . . . X . . . . . . . . . 43 | 11 . . . . . . . . . . . . . . . . . . . 44 | 12 . . . . . . . . . . . . . . . . . . . 45 | 13 . . . . . . . . . . . . . . . . . . . 46 | 14 . . . . . . . . . . . . . . . . . . . 47 | 15 . . . . . . . . . . . . . . . . . . . 48 | 16 . . . . . . . . . . . . . . . . . . . 49 | 17 . . . . . . . . . . . . . . . . . . . 50 | 18 . . . . . . . . . . . . . . . . . . . 51 | 19 . . . . . . . . . . . . . . . . . . . 52 | Are you sure (1), or not (0)? 53 | Enter number: 54 | 3 . 10 - 9 55 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 56 | 1 . . . . . . . . . . . . . . . . . . . 57 | 2 . . . . . . . . . . . . . . . . . . . 58 | 3 . . . . . . . . . . . . . . . . . . . 59 | 4 . . . . . . . . . . . . . . . . . . . 60 | 5 . . . . . . . . . . . . . . . . . . . 61 | 6 . . . . . . . . . . . . . . . . . . . 62 | 7 . . . . . . . . . . . . . . . . . . . 63 | 8 . . . . . . . . . . . . . . . . . . . 64 | 9 . . . . . . . . O . . . . . . . . . . 65 | 10 . . . . . . . . X X . . . . . . . . . 66 | 11 . . . . . . . . . . . . . . . . . . . 67 | 12 . . . . . . . . . . . . . . . . . . . 68 | 13 . . . . . . . . . . . . . . . . . . . 69 | 14 . . . . . . . . . . . . . . . . . . . 70 | 15 . . . . . . . . . . . . . . . . . . . 71 | 16 . . . . . . . . . . . . . . . . . . . 72 | 17 . . . . . . . . . . . . . . . . . . . 73 | 18 . . . . . . . . . . . . . . . . . . . 74 | 19 . . . . . . . . . . . . . . . . . . . 75 | Which row? 76 | Enter number: _ 77 | ``` 78 | -------------------------------------------------------------------------------- /examples/sieve.a60: -------------------------------------------------------------------------------- 1 | b̲e̲g̲i̲n̲ 2 | c̲o̲m̲m̲e̲n̲t̲ zeef van Erathostenes; 3 | i̲n̲t̲e̲g̲e̲r̲ p, m; 4 | b̲e̲g̲i̲n̲ 5 | B̲o̲o̲l̲e̲a̲n̲ a̲r̲r̲a̲y̲ prime [2 : 1000000]; 6 | 7 | PRINTTEXT(`Computing primes...'); 8 | f̲o̲r̲ p := 2, 3 s̲t̲e̲p̲ 2 u̲n̲t̲i̲l̲ 1000000 d̲o̲ 9 | prime[p] := t̲r̲u̲e̲; 10 | PRINTTEXT(`.'); 11 | f̲o̲r̲ p := 2, 3 s̲t̲e̲p̲ 2 u̲n̲t̲i̲l̲ 1000 d̲o̲ b̲e̲g̲i̲n̲ 12 | i̲f̲ prime[p] t̲h̲e̲n̲ 13 | f̲o̲r̲ m := p * p s̲t̲e̲p̲ p u̲n̲t̲i̲l̲ 1000000 d̲o̲ 14 | prime[m] := f̲a̲l̲s̲e̲; 15 | i̲f̲ p ÷ 100 * 100 + 1 = p t̲h̲e̲n̲ 16 | PRINTTEXT(`.'); 17 | e̲n̲d̲; 18 | NLCR; 19 | 20 | m := 0; 21 | f̲o̲r̲ p := 2, 3 s̲t̲e̲p̲ 2 u̲n̲t̲i̲l̲ 1000000 d̲o̲ b̲e̲g̲i̲n̲ 22 | i̲f̲ prime[p] t̲h̲e̲n̲ b̲e̲g̲i̲n̲ 23 | m := m + 1 24 | e̲n̲d̲ 25 | e̲n̲d̲; 26 | PRINTTEXT(`Number of primes below 1000 000: '); 27 | print(m); 28 | NLCR 29 | e̲n̲d̲ 30 | e̲n̲d̲ 31 | -------------------------------------------------------------------------------- /examples/sqrt_test.a60: -------------------------------------------------------------------------------- 1 | b̲e̲g̲i̲n̲ 2 | c̲o̲m̲m̲e̲n̲t̲ square root test; 3 | c̲o̲m̲m̲e̲n̲t̲ From article "Design and correctness proof of an emulation of the 4 | floating-point operations of the Electrologica X8. A case study" 5 | by F.E.J. Kruseman Aretz. 6 | https://pure.tue.nl/ws/portalfiles/portal/3023549/674735.pdf; 7 | i̲n̲t̲e̲g̲e̲r̲ i; 8 | r̲e̲a̲l̲ si; 9 | 10 | f̲o̲r̲ i := 1 s̲t̲e̲p̲ 1 u̲n̲t̲i̲l̲ 1 048 576 + 3 d̲o̲ b̲e̲g̲i̲n̲ 11 | si := sqrt(i * i); 12 | i̲f̲ si ≠ i t̲h̲e̲n̲ b̲e̲g̲i̲n̲ 13 | ABSFIXT(7, 0, i); 14 | FLOT(13, 3, si); 15 | NLCR 16 | e̲n̲d̲; 17 | i̲f̲ i ÷ 100 000 * 100 000 = i t̲h̲e̲n̲ b̲e̲g̲i̲n̲ 18 | ABSFIXT(7, 0, i); 19 | PRINTTEXT(`passed'); 20 | NLCR 21 | e̲n̲d̲ 22 | e̲n̲d̲ 23 | e̲n̲d̲ 24 | -------------------------------------------------------------------------------- /examples/steady_squares.a60: -------------------------------------------------------------------------------- 1 | b̲e̲g̲i̲n̲ 2 | c̲o̲m̲m̲e̲n̲t̲ Find steady squares - numbers whose square ends in the number 3 | e.g.: 376^2 = 141 376; 4 | 5 | i̲n̲t̲e̲g̲e̲r̲ powerOfTen, p; 6 | powerOfTen := 10; 7 | 8 | c̲o̲m̲m̲e̲n̲t̲ note the final digit must be 1, 5 or 6; 9 | PRINTTEXT(`Searching up to 10000 for steady squares:'); 10 | NLCR; 11 | f̲o̲r̲ p := 0 s̲t̲e̲p̲ 10 u̲n̲t̲i̲l̲ 1000 d̲o̲ b̲e̲g̲i̲n̲ 12 | i̲n̲t̲e̲g̲e̲r̲ d; 13 | i̲f̲ p = powerOfTen t̲h̲e̲n̲ b̲e̲g̲i̲n̲ 14 | c̲o̲m̲m̲e̲n̲t̲ number of digits has increased; 15 | powerOfTen := powerOfTen * 10 16 | e̲n̲d̲; 17 | f̲o̲r̲ d := 1, 5, 6 d̲o̲ b̲e̲g̲i̲n̲ 18 | i̲n̲t̲e̲g̲e̲r̲ m, n, n2; 19 | n := p + d; 20 | n2 := n * n; 21 | m := n2 - (n2 ÷ powerOfTen * powerOfTen); 22 | i̲f̲ m = n t̲h̲e̲n̲̲ b̲e̲g̲i̲n̲ 23 | SPACE(1); 24 | print(n) 25 | e̲n̲d̲ 26 | e̲n̲d̲ 27 | e̲n̲d̲; 28 | NLCR 29 | e̲n̲d̲ 30 | -------------------------------------------------------------------------------- /examples/sum.a60: -------------------------------------------------------------------------------- 1 | b̲e̲g̲i̲n̲ 2 | c̲o̲m̲m̲e̲n̲t̲ Prints 55*20 = 1100 ; 3 | i̲n̲t̲e̲g̲e̲r̲ i, j; 4 | print(SUM(i, 1, 10, SUM(j, 1, 10, i + j))); 5 | NLCR 6 | e̲n̲d̲ 7 | -------------------------------------------------------------------------------- /examples/time.a60: -------------------------------------------------------------------------------- 1 | b̲e̲g̲i̲n̲ 2 | c̲o̲m̲m̲e̲n̲t̲ Print time of day as HH : MM : SS.mmm; 3 | r̲e̲a̲l̲ hour, min, sec; 4 | 5 | sec := TIMEOFDAY; 6 | hour := entier(sec / 3600); 7 | sec := sec - hour * 3600; 8 | min := entier(sec / 60); 9 | sec := sec - min * 60; 10 | 11 | ABSFIXT(2, 0, hour); 12 | PRINTTEXT(`:'); 13 | ABSFIXT(2, 0, min); 14 | PRINTTEXT(`:'); 15 | ABSFIXT(2, 3, sec); 16 | NLCR 17 | e̲n̲d̲ 18 | -------------------------------------------------------------------------------- /examples/whetstone.a60: -------------------------------------------------------------------------------- 1 | b̲e̲g̲i̲n̲ 2 | c̲o̲m̲m̲e̲n̲t̲ 3 | The Whetstone Benchmark. 4 | 5 | See: 6 | A Synthetic Benchmark, 7 | H.J. Curnow and B.A. Whichmann, 8 | The Computing Journal, Volume 19 Number 1 9 | Feb 1976, P. 43-49 10 | 11 | Some results 12 | (in thousands of Whetstone Instructions per second): 13 | 14 | IBM 3090: (Delft ?) Algol Compiler 5000 15 | Sun 3/60: Nase Algol Interpreter 10 16 | Nase Algol2C 400 17 | Sparc 2: Nase Algol Interpreter 63 18 | Nase Algol2C 4200 19 | Pyramid ??: Nase Algol Interpreter 20 20 | 21 | ``Nase'' indicates NASE A60. 22 | ; 23 | 24 | r̲e̲a̲l̲ X1, X2, X3, X4, X, Y, Z, T, T1, T2; 25 | a̲r̲r̲a̲y̲ E1[1:4]; 26 | i̲n̲t̲e̲g̲e̲r̲ I, J, K, L, N1, N2, N3, N4, N5, N6, N7, N8, N9, N10,N11; 27 | 28 | p̲r̲o̲c̲e̲d̲u̲r̲e̲ PA(E); 29 | a̲r̲r̲a̲y̲ E; 30 | b̲e̲g̲i̲n̲ 31 | i̲n̲t̲e̲g̲e̲r̲ J; 32 | 33 | J := 0; 34 | LAB: 35 | E[1] := (E[1] + E[2] + E[3] - E[4]) * T; 36 | E[2] := (E[1] + E[2] - E[3] + E[4]) * T; 37 | E[3] := (E[1] - E[2] + E[3] + E[4]) * T; 38 | E[4] := (- E[1] + E[2] + E[3] + E[4]) / T2; 39 | J := J + 1; 40 | i̲f̲ J < 6 t̲h̲e̲n̲ 41 | g̲o̲t̲o̲ LAB; 42 | e̲n̲d̲; 43 | 44 | p̲r̲o̲c̲e̲d̲u̲r̲e̲ P0; 45 | b̲e̲g̲i̲n̲ 46 | E1[J] := E1[K]; 47 | E1[K] := E1[L]; 48 | E1[L] := E1[J]; 49 | e̲n̲d̲; 50 | 51 | p̲r̲o̲c̲e̲d̲u̲r̲e̲ P3(X, Y, Z); 52 | v̲a̲l̲u̲e̲ X, Y; 53 | r̲e̲a̲l̲ X, Y, Z; 54 | b̲e̲g̲i̲n̲ 55 | X := T * (X + Y); 56 | Y := T * (X + Y); 57 | Z := (X + Y) / T2; 58 | e̲n̲d̲; 59 | 60 | p̲r̲o̲c̲e̲d̲u̲r̲e̲ POUT (N, J, K, X1, X2, X3, X4); 61 | v̲a̲l̲u̲e̲ N, J, K, X1, X2, X3, X4; 62 | i̲n̲t̲e̲g̲e̲r̲ N, J, K; 63 | r̲e̲a̲l̲ X1, X2, X3, X4; 64 | b̲e̲g̲i̲n̲ 65 | print(N, J, K, X1, X2, X3, X4); 66 | NLCR 67 | e̲n̲d̲; 68 | 69 | c̲o̲m̲m̲e̲n̲t̲ initialize constants ; 70 | 71 | T := 0.499975; 72 | T1 := 0.50025; 73 | T2 := 2.0; 74 | 75 | c̲o̲m̲m̲e̲n̲t̲ read the value of i, controlling total wight: if i = 10 the 76 | total weight is one million Whetstone instructions ; 77 | 78 | I := 10; 79 | 80 | N1 := 0; N2 := 12 * I; N3 := 14 * I; 81 | N4 := 345 * I; N5 := 0; N6 := 210 * I; 82 | N7 := 32 * I; N8 := 899 * I; N9 := 616 * I; 83 | N10 := 0; N11 := 93 * I; 84 | 85 | c̲o̲m̲m̲e̲n̲t̲ module 1: simple identifiers ; 86 | 87 | X1 := 1.0; 88 | X2 := X3 := X4 := - 1.0; 89 | 90 | f̲o̲r̲ I := 1 s̲t̲e̲p̲ 1 u̲n̲t̲i̲l̲ N1 d̲o̲ 91 | b̲e̲g̲i̲n̲ 92 | X1 := (X1 + X2 + X3 - X4) * T; 93 | X2 := (X1 + X2 - X3 + X4) * T; 94 | X3 := (X1 - X2 + X3 + X4) * T; 95 | X4 := (- X1 + X2 + X3 + X4) * T; 96 | e̲n̲d̲; 97 | 98 | POUT (N1, N1, N1, X1, X2, X3, X4); 99 | 100 | c̲o̲m̲m̲e̲n̲t̲ module 2: array elements ; 101 | 102 | E1[1] := 1.0; 103 | E1[2] := E1[3] := E1[4] := -1.0; 104 | 105 | f̲o̲r̲ I := 1 s̲t̲e̲p̲ 1 u̲n̲t̲i̲l̲ N2 d̲o̲ 106 | b̲e̲g̲i̲n̲ 107 | E1[1] := (E1[1] + E1[2] + E1[3] - E1[4]) * T; 108 | E1[2] := (E1[1] + E1[2] - E1[3] + E1[4]) * T; 109 | E1[3] := (E1[1] - E1[2] + E1[3] + E1[4]) * T; 110 | E1[4] := (- E1[1] + E1[2] + E1[3] + E1[4]) * T; 111 | e̲n̲d̲; 112 | 113 | POUT (N2, N3, N2, E1[1], E1[2], E1[3], E1[4]); 114 | 115 | c̲o̲m̲m̲e̲n̲t̲ module 3: as array parameter ; 116 | 117 | f̲o̲r̲ I:= 1 s̲t̲e̲p̲ 1 u̲n̲t̲i̲l̲ N3 d̲o̲ 118 | PA(E1); 119 | 120 | POUT (N3, N2, N2, E1[1], E1[2], E1[3], E1[4]); 121 | 122 | c̲o̲m̲m̲e̲n̲t̲ module 4: conditional jumps ; 123 | 124 | J := 1; 125 | f̲o̲r̲ I := 1 s̲t̲e̲p̲ 1 u̲n̲t̲i̲l̲ N4 d̲o̲ 126 | b̲e̲g̲i̲n̲ 127 | i̲f̲ J = 1 t̲h̲e̲n̲ 128 | J := 2 129 | e̲l̲s̲e̲ 130 | J := 3; 131 | 132 | i̲f̲ J > 2 t̲h̲e̲n̲ 133 | J := 0 134 | e̲l̲s̲e̲ 135 | J := 1; 136 | 137 | i̲f̲ J < 1 t̲h̲e̲n̲ 138 | J := 1 139 | e̲l̲s̲e̲ 140 | J := 0; 141 | e̲n̲d̲; 142 | 143 | POUT (N4, J, J, X1, X2, X3, X4); 144 | 145 | c̲o̲m̲m̲e̲n̲t̲ module 5: omitted ; 146 | 147 | c̲o̲m̲m̲e̲n̲t̲ module 6: integer arithmetik ; 148 | 149 | J := 1; K := 2; L := 3; 150 | 151 | f̲o̲r̲ I := 1 s̲t̲e̲p̲ 1 u̲n̲t̲i̲l̲ N6 d̲o̲ 152 | b̲e̲g̲i̲n̲ 153 | J := J * (K - J) * (L - K); 154 | K := L * K - (L - J) * K; 155 | L := (L - K) * (K + J) ; c̲o̲m̲m̲e̲n̲t̲ typo in TCJ ; 156 | E1[L-1] := J + K + L; 157 | E1[K-1] := J * K * L; 158 | e̲n̲d̲; 159 | 160 | POUT (N6, J, K, E1[1], E1[2], E1[3], E1[4]); 161 | 162 | c̲o̲m̲m̲e̲n̲t̲ module 7: trig functions ; 163 | 164 | X := Y := 0.5; 165 | 166 | f̲o̲r̲ I := 1 s̲t̲e̲p̲ 1 u̲n̲t̲i̲l̲ N7 d̲o̲ 167 | b̲e̲g̲i̲n̲ 168 | X := T * arctan (T2 * sin (X) * cos (X) / 169 | (cos (X + Y) + cos (X - Y) - 1.0)); 170 | Y := T * arctan (T2 * sin (Y) * cos (Y) / 171 | (cos (X + Y) + cos (X - Y) - 1.0)); 172 | e̲n̲d̲; 173 | 174 | POUT (N7, J, K, X, X, Y, Y); 175 | 176 | c̲o̲m̲m̲e̲n̲t̲ module 8: procedure calls ; 177 | 178 | X := Y := Z := 1.0; 179 | 180 | f̲o̲r̲ I := 1 s̲t̲e̲p̲ 1 u̲n̲t̲i̲l̲ N8 d̲o̲ 181 | P3 (X, Y, Z); 182 | 183 | POUT (N8, J, K, X, Y, Z, Z); 184 | 185 | c̲o̲m̲m̲e̲n̲t̲ module 9: array references ; 186 | 187 | J := 1; K := 2; L := 3; 188 | E1[1] := 1.0; E1[2] := 2.0; E1[3] := 3.0; 189 | 190 | f̲o̲r̲ I := 1 s̲t̲e̲p̲ 1 u̲n̲t̲i̲l̲ N9 d̲o̲ 191 | P0; 192 | 193 | POUT (N9, J, K, E1[1], E1[2], E1[3], E1[4]); 194 | 195 | c̲o̲m̲m̲e̲n̲t̲ module 10: integer arithmetik ; 196 | 197 | J := 2; K := 3; 198 | 199 | f̲o̲r̲ I := 1 s̲t̲e̲p̲ 1 u̲n̲t̲i̲l̲ N10 d̲o̲ 200 | b̲e̲g̲i̲n̲ 201 | J := J + K; 202 | K := J + K; 203 | J := K - J; 204 | K := K -J -J; 205 | e̲n̲d̲; 206 | 207 | POUT (N10, J, K, X1, X2, X3, X4); 208 | 209 | c̲o̲m̲m̲e̲n̲t̲ module 11: standard functions ; 210 | 211 | X := 0.75; 212 | f̲o̲r̲ I := 1 s̲t̲e̲p̲ 1 u̲n̲t̲i̲l̲ N11 d̲o̲ 213 | X := sqrt (exp (ln (X) / T1)); 214 | 215 | POUT (N11, J, K, X, X, X, X); 216 | e̲n̲d̲ 217 | -------------------------------------------------------------------------------- /library/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | install(FILES x1algol.lib DESTINATION lib) 2 | -------------------------------------------------------------------------------- /library/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # List of procedures on the default library tape. 3 | # 4 | TARGET_LIB = sum.lib resym.lib prsym.lib random.lib setrandom.lib 5 | 6 | # 7 | # All procedures compiled from assembly source. 8 | # 9 | ALL_LIB = $(TARGET_LIB) even.lib printtext.lib timeofday.lib 10 | 11 | CXXFLAGS = -O -Wall -Werror 12 | 13 | MCP_SUM = 0 14 | MCP_PRINTTEXT = 1 15 | MCP_EVEN = 2 16 | MCP_RESYM = 7 17 | MCP_PRSYM = 8 18 | MCP_RANDOM = 17 19 | MCP_SETRANDOM = 18 20 | MCP_TIMEOFDAY = 77 21 | 22 | all: $(ALL_LIB) x1algol.lib 23 | 24 | clean: 25 | rm -f *.o objfile 26 | 27 | objfile: objfile.cc 28 | 29 | x1algol.lib: $(TARGET_LIB) 30 | cat $(TARGET_LIB) > $@ 31 | 32 | sum.lib: objfile sum.src 33 | ./objfile $(MCP_SUM) < sum.src > $@ 34 | 35 | even.lib: objfile even.src 36 | ./objfile $(MCP_EVEN) < even.src > $@ 37 | 38 | printtext.lib: objfile printtext.src 39 | ./objfile $(MCP_PRINTTEXT) < printtext.src > $@ 40 | 41 | timeofday.lib: objfile timeofday.src 42 | ./objfile $(MCP_TIMEOFDAY) < timeofday.src > $@ 43 | 44 | resym.lib: objfile resym.src 45 | ./objfile $(MCP_RESYM) < resym.src > $@ 46 | 47 | prsym.lib: objfile prsym.src 48 | ./objfile $(MCP_PRSYM) < prsym.src > $@ 49 | 50 | random.lib: objfile random.src 51 | ./objfile $(MCP_RANDOM) < random.src > $@ 52 | 53 | setrandom.lib: objfile setrandom.src 54 | ./objfile $(MCP_SETRANDOM) < setrandom.src > $@ 55 | -------------------------------------------------------------------------------- /library/absfixt.lib: -------------------------------------------------------------------------------- 1 | 30 65 0 64 24 127 3 126 0 0 0 2 | -------------------------------------------------------------------------------- /library/arctan.lib: -------------------------------------------------------------------------------- 1 | 30 65 0 64 3 127 3 126 0 0 0 2 | -------------------------------------------------------------------------------- /library/even.5tr: -------------------------------------------------------------------------------- 1 | 31 2 | 0 0 12 16 2 3 | 16 24 0 0 1 4 | 26 25 5 | 0 16 0 5 1 6 | 9 3 7 | 4 0 7 8 31 31 31 8 | 20 3 14 3 16 0 0 9 | 20 0 5 4 31 31 28 10 | 20 3 14 12 0 0 1 11 | 20 0 4 18 0 0 1 12 | 20 0 6 19 0 0 1 13 | 20 0 13 0 31 31 28 14 | 8 13 15 | -------------------------------------------------------------------------------- /library/even.lib: -------------------------------------------------------------------------------- 1 | 30 1 0 64 14 0 2 48 54 125 104 65 126 91 65 127 127 78 122 54 48 61 32 127 2 | 71 58 48 15 115 100 63 127 115 127 14 115 96 33 63 83 104 126 127 125 54 14 3 | 14 3 32 127 0 0 0 4 | -------------------------------------------------------------------------------- /library/even.src: -------------------------------------------------------------------------------- 1 | Entered from 2 | https://t-lcarchive.org/wp-content/uploads/EL-X1-ALGOL-COMPLEX-Notebook-2.pdf 3 | page 37. 4 | Format: 5 | offset OPC word 6 | 0 0 0422000001 2B 1 A 7 | 1 89 SCC 8 | 2 0 0122000241 2S 1 X5 A 9 | 3 35 TFR 10 | 4 0 0035077777 3A 32767 X0 B Z 11 | 5 0 0670340000 N 7P 12 | 6 0 0024477774 2A 32764 X0 B P 13 | 7 0 0671400001 1P 1 AA E 14 | 8 0 0022200001 Y 2A 1 A 15 | 9 0 0032300001 N 3A 1 A 16 | 10 0 0064077774 6A 32764 X0 B 17 | 11 0 0422000000 2B 0 A 18 | 12 87 STP 19 | 13 12 RET 20 | -------------------------------------------------------------------------------- /library/fixt.lib: -------------------------------------------------------------------------------- 1 | 30 65 0 64 6 127 3 126 0 0 0 2 | -------------------------------------------------------------------------------- /library/flex-to-algol.c: -------------------------------------------------------------------------------- 1 | // 2 | // Print conversion table from Flexowriter to internal Algol encoding. 3 | // 4 | #include 5 | 6 | unsigned flex_table[128]; 7 | 8 | #define FLEX_TAB 62 9 | #define FLEX_SPACE 16 10 | #define FLEX_CRLF 26 11 | 12 | #if 0 13 | code - uc lc 14 | 0 - shift disable 15 | 1 - 78 1 ∨ 1 16 | 2 - 66 2 × 2 17 | 4 - 72 4 = 4 18 | 7 - 101 7 ] 7 19 | 8 - 98 8 ( 8 20 | 14 - 162 163 | _ 21 | 16 - 123 123 space 22 | 19 - 67 3 / 3 23 | 21 - 91 5 ; 5 24 | 22 - 100 6 [ 6 25 | 25 - 99 9 ) 9 26 | 26 - 119 119 crlf 27 | 32 - 77 0 ∧ 0 28 | 35 - 56 29 T t 29 | 37 - 58 31 V v 30 | 38 - 59 32 W w 31 | 41 - 62 35 Z z 32 | 49 - 70 74 > < 33 | 50 - 55 28 S s 34 | 52 - 57 30 U u 35 | 55 - 60 33 X x 36 | 56 - 61 34 Y y 37 | 59 - 120 89 ' ⏨ 38 | 62 - 118 118 tab 39 | 64 - 76 65 ¬ - 40 | 67 - 48 21 L l 41 | 69 - 50 23 N n 42 | 70 - 51 24 O o 43 | 73 - 54 27 R r 44 | 81 - 46 19 J j 45 | 82 - 47 20 K k 46 | 84 - 49 22 M m 47 | 87 - 52 25 P p 48 | 88 - 53 26 Q q 49 | 91 - 122 87 ? , 50 | 97 - 37 10 A a 51 | 98 - 38 11 B b 52 | 100 - 40 13 D d 53 | 103 - 43 16 G g 54 | 104 - 44 17 H h 55 | 107 - 124 88 : . 56 | 112 - 121 64 " + 57 | 115 - 39 12 C c 58 | 117 - 41 14 E e 59 | 118 - 42 15 F f 60 | 121 - 45 18 I i 61 | 122 - shift to lowercase 62 | 124 - shift to uppercase 63 | 127 - erase 64 | #endif 65 | 66 | void print(int flex_code, int value) 67 | { 68 | printf("%4d - ", flex_code); 69 | 70 | if (value < 128) { 71 | printf("\\%02o", value); 72 | } else { 73 | int uppercase = value / 256; 74 | int lowercase = value % 256; 75 | printf("%3d %3d", uppercase, lowercase); 76 | } 77 | 78 | switch (flex_code) { 79 | case FLEX_TAB: 80 | printf(" tab"); 81 | break; 82 | case FLEX_SPACE: 83 | printf(" space"); 84 | break; 85 | case FLEX_CRLF: 86 | printf(" crlf"); 87 | break; 88 | } 89 | printf("\n"); 90 | } 91 | 92 | int main() 93 | { 94 | // initialization of flex_table 95 | flex_table[ 0] = -2; flex_table[ 1] = 19969; flex_table[ 2] = 16898; 96 | flex_table[ 3] = -0; flex_table[ 4] = 18436; flex_table[ 5] = -0; 97 | flex_table[ 6] = -0; flex_table[ 7] = 25863; flex_table[ 8] = 25096; 98 | flex_table[ 9] = -0; flex_table[ 10] = -0; flex_table[ 11] = -1; 99 | flex_table[ 12] = -0; flex_table[ 13] = -1; flex_table[ 14] = 41635; 100 | flex_table[ 15] = -0; flex_table[ 16] = 31611; flex_table[ 17] = -0; 101 | flex_table[ 18] = -0; flex_table[ 19] = 17155; flex_table[ 20] = -0; 102 | flex_table[ 21] = 23301; flex_table[ 22] = 25606; flex_table[ 23] = -0; 103 | flex_table[ 24] = -0; flex_table[ 25] = 25353; flex_table[ 26] = 30583; 104 | flex_table[ 27] = -0; flex_table[ 28] = -1; flex_table[ 29] = -0; 105 | flex_table[ 30] = -0; flex_table[ 31] = -1; flex_table[ 32] = 19712; 106 | flex_table[ 33] = -0; flex_table[ 34] = -0; flex_table[ 35] = 14365; 107 | flex_table[ 36] = -0; flex_table[ 37] = 14879; flex_table[ 38] = 15136; 108 | flex_table[ 39] = -0; flex_table[ 40] = -0; flex_table[ 41] = 15907; 109 | flex_table[ 42] = -1; flex_table[ 43] = -0; flex_table[ 44] = -1; 110 | flex_table[ 45] = -0; flex_table[ 46] = -0; flex_table[ 47] = -1; 111 | flex_table[ 48] = -0; flex_table[ 49] = 17994; flex_table[ 50] = 14108; 112 | flex_table[ 51] = -0; flex_table[ 52] = 14622; flex_table[ 53] = -0; 113 | flex_table[ 54] = -0; flex_table[ 55] = 15393; flex_table[ 56] = 15650; 114 | flex_table[ 57] = -0; flex_table[ 58] = -0; flex_table[ 59] = 30809; 115 | flex_table[ 60] = -0; flex_table[ 61] = -1; flex_table[ 62] = 30326; 116 | flex_table[ 63] = -0; flex_table[ 64] = 19521; flex_table[ 65] = -0; 117 | flex_table[ 66] = -0; flex_table[ 67] = 12309; flex_table[ 68] = -0; 118 | flex_table[ 69] = 12823; flex_table[ 70] = 13080; flex_table[ 71] = -0; 119 | flex_table[ 72] = -0; flex_table[ 73] = 13851; flex_table[ 74] = -1; 120 | flex_table[ 75] = -0; flex_table[ 76] = -1; flex_table[ 77] = -0; 121 | flex_table[ 78] = -0; flex_table[ 79] = -1; flex_table[ 80] = -0; 122 | flex_table[ 81] = 11795; flex_table[ 82] = 12052; flex_table[ 83] = -0; 123 | flex_table[ 84] = 12566; flex_table[ 85] = -0; flex_table[ 86] = -0; 124 | flex_table[ 87] = 13337; flex_table[ 88] = 13594; flex_table[ 89] = -0; 125 | flex_table[ 90] = -0; flex_table[ 91] = 31319; flex_table[ 92] = -0; 126 | flex_table[ 93] = -1; flex_table[ 94] = -1; flex_table[ 95] = -0; 127 | flex_table[ 96] = -0; flex_table[ 97] = 9482; flex_table[ 98] = 9739; 128 | flex_table[ 99] = -0; flex_table[100] = 10253; flex_table[101] = -0; 129 | flex_table[102] = -0; flex_table[103] = 11024; flex_table[104] = 11281; 130 | flex_table[105] = -0; flex_table[106] = -0; flex_table[107] = 31832; 131 | flex_table[108] = -0; flex_table[109] = -1; flex_table[110] = -1; 132 | flex_table[111] = -0; flex_table[112] = 31040; flex_table[113] = -0; 133 | flex_table[114] = -0; flex_table[115] = 9996; flex_table[116] = -0; 134 | flex_table[117] = 10510; flex_table[118] = 10767; flex_table[119] = -0; 135 | flex_table[120] = -0; flex_table[121] = 11538; flex_table[122] = -2; 136 | flex_table[123] = -0; flex_table[124] = -2; flex_table[125] = -0; 137 | flex_table[126] = -0; flex_table[127] = -2; 138 | 139 | printf("code - uc lc\n"); 140 | for (int i = 0; i < 128; i++) { 141 | int ch = flex_table[i]; 142 | if (ch > 0) { 143 | print(i, ch); 144 | } 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /library/flot.lib: -------------------------------------------------------------------------------- 1 | 30 65 0 64 5 127 3 126 0 0 0 2 | -------------------------------------------------------------------------------- /library/from5track.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int read_byte() { 5 | int byte; 6 | if (0 >= scanf("%d", &byte) || byte < 0 || byte > 31) { 7 | printf("Short or bad tape\n"); 8 | exit(EXIT_FAILURE); 9 | } 10 | return byte; 11 | } 12 | 13 | int parity(unsigned long a) { 14 | for (int i = 0; i < 35; ++i) 15 | a = (a & 1) ^ (a >> 1); 16 | return a; 17 | } 18 | 19 | bool read_header(int& mcp, int& len) { 20 | int byte; 21 | bool p; 22 | if (0 >= scanf("%d", &byte) || byte != 31) { 23 | printf("Header expected\n"); 24 | exit(EXIT_FAILURE); 25 | } 26 | len = read_byte(); 27 | len = (len << 5) | read_byte(); 28 | len = (len << 5) | read_byte(); 29 | p = parity(len); 30 | len &= 037777; 31 | mcp = read_byte(); 32 | mcp = (mcp << 5) | read_byte(); 33 | p |= parity(mcp); 34 | mcp &= 0777; 35 | return p; 36 | } 37 | 38 | int main() { 39 | unsigned word; 40 | int mcp, len; 41 | if (read_header(mcp, len)) { 42 | printf("Parity error in header\n"); 43 | exit(EXIT_FAILURE); 44 | } 45 | printf("Converting MCP %d, length %d\n", mcp, len); 46 | for (int i = 0; i < len; ++i) { 47 | word = read_byte(); 48 | if (word & 8) { 49 | word = (word << 5) | read_byte(); 50 | printf("%d %d%s\n", i, word & 127, parity(word) ? " !" : ""); 51 | } else if ((word & 0xC) == 4) { 52 | unsigned prefix = word; 53 | word = read_byte(); 54 | word = (word << 5) | read_byte(); 55 | word = (word << 5) | read_byte(); 56 | word = (word << 5) | read_byte(); 57 | word = (word << 5) | read_byte(); 58 | word = (word << 5) | read_byte(); 59 | printf("%d %d %010o%s\n", i, (word >> 27) & 3, 60 | word & 0777777777, parity(word^prefix) ? " !" : ""); 61 | } else { 62 | unsigned p = 0777777777; 63 | word = (word << 5) | read_byte(); 64 | word = (word << 5) | read_byte(); 65 | word = (word << 5) | read_byte(); 66 | word = (word << 5) | read_byte(); 67 | switch ((word >> 17) & 31) { 68 | case 1: p = 0000000000; break; 69 | case 2: p = 0022000000; break; 70 | case 3: p = 0120000000; break; 71 | case 4: p = 0122000000; break; 72 | case 5: p = 0420000000; break; 73 | case 6: p = 0422000000; break; 74 | case 7: p = 0520000000; break; 75 | case 8: p = 0522000000; break; 76 | case 9: p = 0520300000; break; 77 | case 10: p = 0040000000; break; 78 | default: printf("Unknown short code %d\n", (word >> 17) & 31); 79 | exit(EXIT_FAILURE); 80 | } 81 | printf("%d %d %010o%s\n", i, (word >> 15) & 3, 82 | p | (word & 077777), parity(word) ? " !" : "" ); 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /library/mcp4.lib: -------------------------------------------------------------------------------- 1 | 30 64 0 64 4 127 3 126 0 0 0 2 | -------------------------------------------------------------------------------- /library/printtext.5tr: -------------------------------------------------------------------------------- 1 | 31 2 | 0 3 | 0 4 | 20 5 | 16 6 | 1 7 | 16 8 | 24 9 | 0 10 | 0 11 | 1 12 | 26 13 | 25 14 | 0 15 | 20 16 | 0 17 | 1 18 | 19 19 | 4 20 | 2 21 | 5 22 | 0 23 | 0 24 | 0 25 | 5 26 | 4 27 | 2 28 | 12 29 | 0 30 | 0 31 | 1 32 | 7 33 | 4 34 | 0 35 | 21 36 | 0 37 | 0 38 | 0 39 | 0 40 | 16 41 | 8 42 | 0 43 | 0 44 | 3 45 | 20 46 | 0 47 | 12 48 | 0 49 | 0 50 | 0 51 | 0 52 | 4 53 | 0 54 | 28 55 | 0 56 | 0 57 | 1 58 | 2 59 | 4 60 | 1 61 | 28 62 | 16 63 | 0 64 | 7 65 | 31 66 | 20 67 | 1 68 | 24 69 | 25 70 | 0 71 | 7 72 | 31 73 | 4 74 | 6 75 | 20 76 | 18 77 | 0 78 | 0 79 | 19 80 | 27 81 | 3 82 | 0 83 | 12 84 | 0 85 | 1 86 | 2 87 | 20 88 | 3 89 | 30 90 | 0 91 | 0 92 | 1 93 | 8 94 | 20 95 | 6 96 | 24 97 | 4 98 | 0 99 | 0 100 | 8 101 | 0 102 | 20 103 | 0 104 | 1 105 | 7 106 | 4 107 | 2 108 | 0 109 | 16 110 | 0 111 | 0 112 | 1 113 | 17 114 | 1 115 | 0 116 | 0 117 | 4 118 | 24 119 | 12 120 | -------------------------------------------------------------------------------- /library/printtext.lib: -------------------------------------------------------------------------------- 1 | 30 1 0 8 2 64 0 22 7 101 9 31 113 12 0 63 98 53 1 19 127 102 56 72 20 63 113 2 | 126 64 37 71 123 36 2 9 101 63 102 52 100 25 126 112 120 114 78 127 127 7 3 | 103 2 63 127 118 100 2 23 123 50 0 65 97 7 126 107 1 16 63 98 88 64 36 127 4 | 120 39 64 18 127 113 26 1 25 110 3 32 127 0 0 0 5 | -------------------------------------------------------------------------------- /library/printtext.src: -------------------------------------------------------------------------------- 1 | 2 | Entered from 3 | https://t-lcarchive.org/wp-content/uploads/EL-X1-ALGOL-COMPLEX-Notebook-2.pdf 4 | page 33. 5 | Format: 6 | offset OPC word 7 | 0 0 0422000001 2B 1 A 8 | 1 89 SCC 9 | 2 0 0420000063 2B 19 X1 10 | 3 0 0424000005 2B 5 X0 B 11 | 4 0 0460000047 6B 7 X1 <-- 18 12 | 5 0 0124000000 2S 0 X0 B 13 | 6 0 0022000003 2A 3 A 14 | 7 0 0060000000 6A 0 X0 15 | 8 0 0160000042 6S 2 X1 <-- 15 16 | 9 0 0362000377 2LS 255 A 17 | 10 0 0343100377 U 0LS 255 A Z 18 | 11 1 0522200023 Y 2T 19 A --> 19 | 12 99 TAS 20 | 13 0 0120000042 2S 2 X1 21 | The next instruction is according to the 5-track tape listing (ibid, page 35). 22 | 14 0 0770000050 3P 8 SS 23 | 15 1 0540400010 4T 8 0 P --> 24 | 16 0 0420000047 2B 7 X1 25 | 17 0 0402000001 0B 1 A 26 | 18 1 0522000004 2T 4 A --> 27 | 19 12 RET <-- 11 28 | -------------------------------------------------------------------------------- /library/prsym.a60: -------------------------------------------------------------------------------- 1 | b̲e̲g̲i̲n̲ 2 | p̲r̲o̲c̲e̲d̲u̲r̲e̲ PRSYM(s); 3 | i̲n̲t̲e̲g̲e̲r̲ s; 4 | b̲e̲g̲i̲n̲ 5 | o̲w̲n̲ i̲n̲t̲e̲g̲e̲r̲ out; 6 | out := s 7 | e̲n̲d̲ 8 | e̲n̲d̲ 9 | -------------------------------------------------------------------------------- /library/prsym.lib: -------------------------------------------------------------------------------- 1 | 30 32 2 0 4 25 12 117 88 56 41 111 127 124 110 3 32 127 0 0 0 2 | -------------------------------------------------------------------------------- /library/prsym.src: -------------------------------------------------------------------------------- 1 | 0 0 0422000001 2B 000001 A 2 | 01 89 SCC 3 | 02 0 0422077773 2B 077773 A 4 | 03 17 TIAS 5 | 04 0 0122000241 2S 000241 A 6 | 05 35 TFR 7 | 06 85 ST 8 | 07 12 RET 9 | -------------------------------------------------------------------------------- /library/random.a60: -------------------------------------------------------------------------------- 1 | b̲e̲g̲i̲n̲ 2 | r̲e̲a̲l̲ p̲r̲o̲c̲e̲d̲u̲r̲e̲ RANDOM; b̲e̲g̲i̲n̲ 3 | o̲w̲n̲ r̲e̲a̲l̲ seed; 4 | RANDOM := seed 5 | e̲n̲d̲ 6 | e̲n̲d̲ 7 | -------------------------------------------------------------------------------- /library/random.lib: -------------------------------------------------------------------------------- 1 | 30 0 0 0 4 0 28 1 11 2 91 118 68 7 14 111 127 125 46 3 32 127 0 0 0 2 | -------------------------------------------------------------------------------- /library/random.src: -------------------------------------------------------------------------------- 1 | 0 0 0422000001 2B 000001 A 2 | 01 89 SCC 3 | 02 0 0422077771 2B 077771 A 4 | 03 32 TRRS 5 | 04 0 0422000000 2B 000000 A 6 | 05 87 STP 7 | 06 12 RET 8 | -------------------------------------------------------------------------------- /library/resym.lib: -------------------------------------------------------------------------------- 1 | 30 9 0 56 0 118 3 55 109 8 1 111 127 127 14 3 32 127 0 0 0 2 | -------------------------------------------------------------------------------- /library/resym.src: -------------------------------------------------------------------------------- 1 | 0 0 0422000001 2B 000001 A 2 | 01 89 SCC 3 | 02 0 0422077774 2B 077774 A 4 | 03 34 TIRS 5 | 04 0 0422000000 2B 000000 A 6 | 05 87 STP 7 | 06 12 RET 8 | -------------------------------------------------------------------------------- /library/setrandom.a60: -------------------------------------------------------------------------------- 1 | b̲e̲g̲i̲n̲ 2 | p̲r̲o̲c̲e̲d̲u̲r̲e̲ SETRANDOM(x); r̲e̲a̲l̲ x; b̲e̲g̲i̲n̲ 3 | o̲w̲n̲ r̲e̲a̲l̲ seed; 4 | seed := x 5 | e̲n̲d̲ 6 | e̲n̲d̲ 7 | -------------------------------------------------------------------------------- /library/setrandom.lib: -------------------------------------------------------------------------------- 1 | 30 0 0 0 2 1 16 0 73 64 103 45 67 70 4 111 127 125 46 3 32 127 0 0 0 2 | -------------------------------------------------------------------------------- /library/setrandom.src: -------------------------------------------------------------------------------- 1 | 0 0 0422000001 2B 000001 A 2 | 01 89 SCC 3 | 02 0 0422077771 2B 077771 A 4 | 03 15 TRAS 5 | 04 0 0122000241 2S 000241 A 6 | 05 35 TFR 7 | 06 85 ST 8 | 07 12 RET 9 | -------------------------------------------------------------------------------- /library/sum.5tr: -------------------------------------------------------------------------------- 1 | 31 2 | 0 3 | 0 4 | 27 5 | 0 6 | 0 7 | 16 8 | 24 9 | 0 10 | 0 11 | 1 12 | 26 13 | 25 14 | 0 15 | 16 16 | 0 17 | 9 18 | 1 19 | 9 20 | 3 21 | 16 22 | 16 23 | 0 24 | 7 25 | 1 26 | 9 27 | 3 28 | 4 29 | 0 30 | 7 31 | 8 32 | 31 33 | 31 34 | 31 35 | 4 36 | 0 37 | 7 38 | 10 39 | 31 40 | 31 41 | 27 42 | 4 43 | 0 44 | 7 45 | 2 46 | 31 47 | 31 48 | 16 49 | 4 50 | 5 51 | 12 52 | 10 53 | 0 54 | 0 55 | 26 56 | 20 57 | 3 58 | 14 59 | 3 60 | 16 61 | 0 62 | 0 63 | 20 64 | 0 65 | 21 66 | 0 67 | 31 68 | 31 69 | 28 70 | 20 71 | 0 72 | 13 73 | 0 74 | 31 75 | 31 76 | 28 77 | 20 78 | 2 79 | 5 80 | 0 81 | 31 82 | 31 83 | 16 84 | 17 85 | 1 86 | 0 87 | 0 88 | 21 89 | 16 90 | 16 91 | 0 92 | 11 93 | 1 94 | 25 95 | 8 96 | 16 97 | 20 98 | 0 99 | 1 100 | 18 101 | 20 102 | 2 103 | 5 104 | 0 105 | 31 106 | 31 107 | 16 108 | 0 109 | 16 110 | 0 111 | 0 112 | 1 113 | 20 114 | 0 115 | 17 116 | 0 117 | 0 118 | 0 119 | 0 120 | 20 121 | 0 122 | 29 123 | 0 124 | 0 125 | 0 126 | 0 127 | 16 128 | 20 129 | 0 130 | 1 131 | 18 132 | 20 133 | 0 134 | 19 135 | 4 136 | 31 137 | 31 138 | 24 139 | 4 140 | 6 141 | 20 142 | 19 143 | 0 144 | 0 145 | 15 146 | 8 147 | 13 148 | 4 149 | 0 150 | 0 151 | 16 152 | 0 153 | 0 154 | 0 155 | -------------------------------------------------------------------------------- /library/sum.a60: -------------------------------------------------------------------------------- 1 | b̲e̲g̲i̲n̲ 2 | r̲e̲a̲l̲ p̲r̲o̲c̲e̲d̲u̲r̲e̲ SUM(a, b, c, d); 3 | v̲a̲l̲u̲e̲ b, c; 4 | i̲n̲t̲e̲g̲e̲r̲ a, b, c; 5 | r̲e̲a̲l̲ d; 6 | b̲e̲g̲i̲n̲ 7 | r̲e̲a̲l̲ t; 8 | t := 0; 9 | a := b; m: i̲f̲ a ≤ c t̲h̲e̲n̲ b̲e̲g̲i̲n̲ 10 | t := t + d; a := a + 1; g̲o̲t̲o̲ m e̲n̲d̲; 11 | SUM := t 12 | e̲n̲d̲ 13 | e̲n̲d̲ 14 | 15 | -------------------------------------------------------------------------------- /library/sum.lib: -------------------------------------------------------------------------------- 1 | 30 64 27 0 0 114 65 102 16 25 13 95 52 33 22 34 105 101 14 39 46 118 9 85 2 | 54 15 9 33 97 109 37 10 98 100 22 68 49 52 63 102 105 76 37 116 109 45 8 82 3 | 22 97 112 112 68 113 74 14 14 31 49 26 17 68 105 116 38 46 81 24 120 2 14 4 | 91 10 32 72 82 14 90 68 112 72 79 14 3 32 127 0 0 0 5 | -------------------------------------------------------------------------------- /library/sum.src: -------------------------------------------------------------------------------- 1 | 0 0 0422000001 2B 000001 A 2 | 01 89 SCC 3 | 02 0 0122000341 2S 000341 A 4 | 03 16 TIAD 5 | 04 0 0122000341 2S 000341 A 6 | 05 35 TFR 7 | 06 85 ST 8 | 07 0 0122000441 2S 000441 A 9 | 010 16 TIAD 10 | 011 0 0122000441 2S 000441 A 11 | 012 35 TFR 12 | 013 85 ST 13 | 014 0 0022000002 2A 000002 A 14 | 015 0 0040000061 4A 000061 15 | 016 0 0040000062 4A 000062 16 | 017 0 0122000641 2S 000641 A 17 | 020 14 TRAD 18 | 021 1 0422000064 2B 000064 A 19 | 022 34 TIRS 20 | 023 85 ST 21 | 024 0 0122000241 2S 000241 A 22 | 025 18 TFA 23 | 026 0 0122000341 2S 000341 A 24 | 027 33 TIRD 25 | 030 85 ST 26 | 031 0 0122000241 2S 000241 A 27 | 032 35 TFR 28 | 033 0 0122000441 2S 000441 A 29 | 034 33 TIRD 30 | 035 68 MST 31 | 036 30 CAC 32 | 037 1 0522300057 N GOTO 000057 A 33 | 040 0 0122000641 2S 000641 A 34 | 041 14 TRAD 35 | 042 0 0122000641 2S 000641 A 36 | 043 31 TRRD 37 | 044 0 0122000541 2S 000541 A 38 | 045 40 ADF 39 | 046 85 ST 40 | 047 0 0122000241 2S 000241 A 41 | 050 18 TFA 42 | 051 0 0122000241 2S 000241 A 43 | 052 35 TFR 44 | 053 1 0422000065 2B 000065 A 45 | 054 39 ADIS 46 | 055 85 ST 47 | 056 1 0522000031 GOTO 000031 A 48 | 057 0 0122000641 2S 000641 A 49 | 060 31 TRRD 50 | 061 0 0422000000 2B 000000 A 51 | 062 87 STP 52 | 063 12 RET 53 | 064 0 0000000000 54 | 065 0 0000000001 55 | -------------------------------------------------------------------------------- /library/timeofday.a60: -------------------------------------------------------------------------------- 1 | b̲e̲g̲i̲n̲ 2 | r̲e̲a̲l̲ p̲r̲o̲c̲e̲d̲u̲r̲e̲ TIMEOFDAY; 3 | b̲e̲g̲i̲n̲ 4 | o̲w̲n̲ r̲e̲a̲l̲ t; 5 | TIMEOFDAY := t 6 | e̲n̲d̲ 7 | e̲n̲d̲ 8 | 9 | -------------------------------------------------------------------------------- /library/timeofday.lib: -------------------------------------------------------------------------------- 1 | 30 0 0 0 4 0 28 4 107 2 91 118 68 7 14 111 127 126 46 3 32 127 0 0 0 2 | -------------------------------------------------------------------------------- /library/timeofday.src: -------------------------------------------------------------------------------- 1 | 0 0 0422000001 2B 000001 A 2 | 01 89 SCC 3 | 02 0 0422077775 2B 077775 A 4 | 03 32 TRRS 5 | 04 0 0422000000 2B 000000 A 6 | 05 87 STP 7 | 06 12 RET 8 | -------------------------------------------------------------------------------- /library/x1algol.lib: -------------------------------------------------------------------------------- 1 | 30 64 27 0 0 114 65 102 16 25 13 95 52 33 22 34 105 101 14 39 46 118 9 85 2 | 54 15 9 33 97 109 37 10 98 100 22 68 49 52 63 102 105 76 37 116 109 45 8 82 3 | 22 97 112 112 68 113 74 14 14 31 49 26 17 68 105 116 38 46 81 24 120 2 14 4 | 91 10 32 72 82 14 90 68 112 72 79 14 3 32 127 0 0 0 5 | 30 9 0 56 0 118 3 55 109 8 1 111 127 127 14 3 32 127 0 0 0 6 | 30 32 2 0 4 25 12 117 88 56 41 111 127 124 110 3 32 127 0 0 0 7 | 30 0 0 0 4 0 28 1 11 2 91 118 68 7 14 111 127 125 46 3 32 127 0 0 0 8 | 30 0 0 0 2 1 16 0 73 64 103 45 67 70 4 111 127 125 46 3 32 127 0 0 0 9 | -------------------------------------------------------------------------------- /library/zztail.lib: -------------------------------------------------------------------------------- 1 | 30 124 0 0 0 0 0 2 | -------------------------------------------------------------------------------- /scripts/decode.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | 5 | my @letters = qw(A A S S X LA D LS B B T T Y Y Z Z); 6 | 7 | my @mods = (' ', 'A', 'B', 'C'); 8 | my @conds = (' ', 'P', 'Z', 'E'); 9 | my @reacts = (' ', 'U', 'Y', 'N'); 10 | 11 | my @opc = (); 12 | $opc[ 8] ='ETMR'; 13 | $opc[ 9] ='ETMP'; 14 | $opc[ 10] ='FTMR'; 15 | $opc[ 11] ='FTMP'; 16 | $opc[ 12] ='RET'; 17 | $opc[ 13] ='EIS'; 18 | $opc[ 14] ='TRAD'; 19 | $opc[ 15] ='TRAS'; 20 | $opc[ 16] ='TIAD'; 21 | $opc[ 17] ='TIAS'; 22 | $opc[ 18] ='TFA'; 23 | $opc[ 19] ='FOR0'; 24 | $opc[ 20] ='FOR1'; 25 | $opc[ 21] ='FOR2'; 26 | $opc[ 22] ='FOR3'; 27 | $opc[ 23] ='FOR4'; 28 | $opc[ 24] ='FOR5'; 29 | $opc[ 25] ='FOR6'; 30 | $opc[ 26] ='FOR7'; 31 | $opc[ 27] ='FOR8'; 32 | $opc[ 28] ='GTA'; 33 | $opc[ 29] ='SSI'; 34 | $opc[ 30] ='CAC'; 35 | $opc[ 31] ='TRRD'; 36 | $opc[ 32] ='TRRS'; 37 | $opc[ 33] ='TIRD'; 38 | $opc[ 34] ='TIRS'; 39 | $opc[ 35] ='TFR'; 40 | $opc[ 36] ='ADRD'; 41 | $opc[ 37] ='ADRS'; 42 | $opc[ 38] ='ADID'; 43 | $opc[ 39] ='ADIS'; 44 | $opc[ 40] ='ADF'; 45 | $opc[ 41] ='SURD'; 46 | $opc[ 42] ='SURS'; 47 | $opc[ 43] ='SUID'; 48 | $opc[ 44] ='SUIS'; 49 | $opc[ 45] ='SUF'; 50 | $opc[ 46] ='MURD'; 51 | $opc[ 47] ='MURS'; 52 | $opc[ 48] ='MUID'; 53 | $opc[ 49] ='MUIS'; 54 | $opc[ 50] ='MUF'; 55 | $opc[ 51] ='DIRD'; 56 | $opc[ 52] ='DIRS'; 57 | $opc[ 53] ='DIID'; 58 | $opc[ 54] ='DIIS'; 59 | $opc[ 55] ='DIF'; 60 | $opc[ 56] ='IND'; 61 | $opc[ 57] ='NEG'; 62 | $opc[ 58] ='TAR'; 63 | $opc[ 59] ='ADD'; 64 | $opc[ 60] ='SUB'; 65 | $opc[ 61] ='MUL'; 66 | $opc[ 62] ='DIV'; 67 | $opc[ 63] ='IDI'; 68 | $opc[ 64] ='TTP'; 69 | $opc[ 65] ='MOR'; 70 | $opc[ 66] ='LST'; 71 | $opc[ 67] ='EQU'; 72 | $opc[ 68] ='MST'; 73 | $opc[ 69] ='LES'; 74 | $opc[ 70] ='UQU'; 75 | $opc[ 71] ='NON'; 76 | $opc[ 72] ='AND'; 77 | $opc[ 73] ='OR'; 78 | $opc[ 74] ='IMP'; 79 | $opc[ 75] ='QVL'; 80 | $opc[ 76] ='abs'; 81 | $opc[ 77] ='sign'; 82 | $opc[ 78] ='sqrt'; 83 | $opc[ 79] ='sin'; 84 | $opc[ 80] ='cos'; 85 | $opc[ 82] ='ln'; 86 | $opc[ 83] ='exp'; 87 | $opc[ 84] ='entier'; 88 | $opc[ 85] ='ST'; 89 | $opc[ 86] ='STA'; 90 | $opc[ 87] ='STP'; 91 | $opc[ 88] ='STAP'; 92 | $opc[ 89] ='SCC'; 93 | $opc[ 90] ='RSF'; 94 | $opc[ 91] ='ISF'; 95 | $opc[ 92] ='RVA'; 96 | $opc[ 93] ='IVA'; 97 | $opc[ 94] ='LAP'; 98 | $opc[ 95] ='VAP'; 99 | $opc[ 96] ='START'; 100 | $opc[ 97] ='STOP'; 101 | $opc[ 98] ='TFP'; 102 | $opc[ 99] ='TAS'; 103 | $opc[100] ='OBC6'; 104 | $opc[101] ='FLOATER'; 105 | $opc[102] ='read'; 106 | $opc[103] ='print'; 107 | $opc[104] ='TAB'; 108 | $opc[105] ='NLCR'; 109 | $opc[106] ='XEEN'; 110 | $opc[107] ='SPACE'; 111 | $opc[108] ='stop'; 112 | $opc[109] ='P21'; 113 | 114 | # Opcode proper, if it does not follow conventional naming. 115 | my @ocp = (); 116 | $ocp[16] = 'MULAS'; 117 | $ocp[17] = 'MULAS-'; 118 | $ocp[18] = 'MULS'; 119 | $ocp[19] = 'MULS-'; 120 | $ocp[24] = 'DIVAS'; 121 | $ocp[25] = 'DIVAS-'; 122 | $ocp[26] = 'DIVA'; 123 | $ocp[27] = 'DIVA-'; 124 | 125 | $ocp[40] = 'JUMP'; 126 | $ocp[41] = 'JUMP-'; 127 | $ocp[42] = 'GOTO'; # also GOTOR 128 | $ocp[46] = 'SUB0'; # also SUB1-SUB15 129 | $ocp[066] = 'MOVR'; 130 | $ocp[067] = 'NEGR'; 131 | 132 | my $decr = $ARGV[0] if $#ARGV >= 0; 133 | @ARGV = (); 134 | my $op; 135 | 136 | while (my $line = <>) { 137 | # print $line; 138 | if ($line =~ /^\s*([0-9]+)\s+([0-9]+)\s*(.*)$/) { 139 | next if $1 < $decr; 140 | my $code = $2; 141 | my $tail = $3; 142 | $op = 0; 143 | if ($code % 32768 >= $decr) { 144 | $code -= $decr; 145 | $op = 1; 146 | } elsif ($code > 7 && $code < 110) { 147 | $op = $code; 148 | } 149 | if ($op >= 8) { 150 | printf "%#6o %3d ", $1-$decr, $op; 151 | } else { 152 | printf "%#6o %3d %#010o ", $1-$decr, $op, $code; 153 | } 154 | if ($code < 110) { 155 | printf "%s", $opc[$code] 156 | } else { 157 | my $addr = $code & 0o77777; 158 | my $letter = $letters[($code >> 23) & 15]; 159 | my $func = ($code >> 21) & (substr($letter, 0, 1) eq 'L' ? 3 : 7); 160 | my $mod = $mods[($code >> 19) & 3]; 161 | my $cond = $conds[($code >> 17) & 3]; 162 | my $react = $reacts[($code >> 15) & 3]; 163 | if (defined($ocp[$code >> 21])) { 164 | printf "%s %s %#06o %s %s", $react, $ocp[$code >> 21], $addr, $mod, $cond; 165 | } else { 166 | printf "%s %d%s %#06o %s %s", $react, $func, $letter, $addr, $mod, $cond; 167 | } 168 | } 169 | printf " ($tail)" if $tail; 170 | printf "\n"; 171 | } 172 | } 173 | 174 | -------------------------------------------------------------------------------- /scripts/restrop.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | sub strop { 3 | return join '_', split '', $_[0]; 4 | } 5 | while (<>) { 6 | s/_([a-z]{2,})/'_'.strop($1)/eg; 7 | print; 8 | } 9 | -------------------------------------------------------------------------------- /scripts/underline.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | $un = substr('◌̲',3,2); 3 | sub strop { 4 | return join $un, split '', $_[0]; 5 | } 6 | while (<>) { 7 | s/_([a-z]{1,})/strop($1).$un/eg; 8 | print; 9 | } 10 | -------------------------------------------------------------------------------- /scripts/x1-disasm.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # 3 | # Disassemble X1 code. 4 | # 5 | import sys 6 | 7 | if len(sys.argv) != 2: 8 | print("Usage: x1-disasm.py input.txt") 9 | sys.exit(1) 10 | 11 | inputfile = sys.argv[1] 12 | 13 | def print_instruction(addr, opcode): 14 | print(f"{addr:05o}: {opcode >> 21 :02o} {opcode >> 15 & 0o77:02o} {opcode & 0o77777 :05o}") 15 | 16 | with open(inputfile, 'r') as f: 17 | for line in f.readlines(): 18 | #print(line) 19 | word = line.split() 20 | if len(word) == 2: 21 | print_instruction(int(word[0]), int(word[1])) 22 | -------------------------------------------------------------------------------- /simulator/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Build library 2 | add_library(simulator STATIC 3 | x1_arch.cpp 4 | machine.cpp 5 | processor.cpp 6 | opcodes.cpp 7 | trace.cpp 8 | virtual_stack.cpp 9 | encoding.cpp 10 | input.cpp 11 | ) 12 | 13 | # Build executable 14 | add_executable(x1sim main.cpp) 15 | target_link_libraries(x1sim simulator) 16 | 17 | set_source_files_properties(main.cpp PROPERTIES COMPILE_FLAGS 18 | -DVERSION_STRING=\\"${CMAKE_PROJECT_VERSION}.${GIT_REVCOUNT}-${GIT_HASH}\\" 19 | ) 20 | 21 | install(TARGETS x1sim DESTINATION bin) 22 | -------------------------------------------------------------------------------- /simulator/byte_pointer.h: -------------------------------------------------------------------------------- 1 | // 2 | // Byte pointer. 3 | // 4 | #include "machine.h" 5 | 6 | class BytePointer { 7 | private: 8 | std::array &memory; 9 | 10 | public: 11 | unsigned word_addr; 12 | unsigned byte_index; 13 | 14 | BytePointer(std::array &m, unsigned wa, unsigned bi = 0) 15 | : memory(m), word_addr(wa), byte_index(bi) 16 | { 17 | } 18 | 19 | // Fetch byte at the pointer. No increment. 20 | uint8_t peek_byte() 21 | { 22 | const Word &w = memory[word_addr]; 23 | return w >> (byte_index * 8); 24 | } 25 | 26 | // Get byte at the pointer, and increment. 27 | uint8_t get_byte() 28 | { 29 | auto ch = peek_byte(); 30 | increment(); 31 | return ch; 32 | } 33 | 34 | // Store byte at the pointer, and increment. 35 | void put_byte(uint8_t ch) 36 | { 37 | Word &w = memory[word_addr]; 38 | const unsigned shift = byte_index * 8; 39 | w = (w & ~(0xff << shift)) | (ch << shift); 40 | increment(); 41 | } 42 | 43 | // Store byte at the pointer, and increment. 44 | void increment() 45 | { 46 | byte_index++; 47 | if (byte_index == 3) { 48 | byte_index = 0; 49 | word_addr++; 50 | } 51 | } 52 | }; 53 | -------------------------------------------------------------------------------- /simulator/encoding.cpp: -------------------------------------------------------------------------------- 1 | #include "encoding.h" 2 | 3 | // 4 | // Internal encoding of symbols in X1 Algol compiler. 5 | // Unused symbols are marked as ⎕. 6 | // For details see: https://github.com/sergev/x1-algol-compiler/blob/main/doc/algol-encoding.md 7 | // 8 | static const char *algol_to_utf8[128] = { 9 | "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f", // 0-15 10 | "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", // 16-31 11 | "w", "x", "y", "z", "⎕", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", // 32-47 12 | "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "⎕", // 48-63 13 | "+", "-", "×", "/", "÷", "↑", ">", "≥", "=", "≤", "<", "≠", "¬", "∧", "∨", "⊃", // 64-79 14 | "≡", "⎕", "⎕", "⎕", "⎕", "⎕", "⎕", ",", ".", "⏨", ":", ";", ":=", " ", "⎕", "⎕", // 80-95 15 | "⎕", "⎕", "(", ")", "[", "]", "`", "'", "⎕", "⎕", "⎕", "⎕", "⎕", "⎕", "⎕", "⎕", // 96-111 16 | "⎕", "⎕", "⎕", "⎕", "⎕", "⎕", "\t", "\n", "⎕", "\"", "?", "⎕", "⎕", "⎕", "⎕", "⎕", // 112-127 17 | }; 18 | 19 | // 20 | // Write character in Algol encoding to UTF-8 stream. 21 | // 22 | void algol_putc(int ch, std::ostream &out) 23 | { 24 | out << algol_to_utf8[ch & 0177]; 25 | } 26 | -------------------------------------------------------------------------------- /simulator/encoding.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // 4 | // Write character in Algol encoding to UTF-8 stream. 5 | // 6 | void algol_putc(int ch, std::ostream &out); 7 | -------------------------------------------------------------------------------- /simulator/input.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "machine.h" 7 | 8 | #ifdef _WIN32 9 | #include 10 | bool Machine::is_interactive = _isatty(0); 11 | #else 12 | #include 13 | bool Machine::is_interactive = isatty(0); 14 | #endif 15 | 16 | class ReplaceTenWithEStreamBuf : public std::streambuf { 17 | public: 18 | explicit ReplaceTenWithEStreamBuf(std::istream& inp) : in_stream(inp.rdbuf()) {} 19 | 20 | protected: 21 | // Override underflow to replace '⏨' with 'E' 22 | int underflow() override { 23 | int ch = in_stream->sbumpc(); // Read the next character from the input stream 24 | 25 | if (ch == EOF) { // Check for end-of-file 26 | return EOF; 27 | } 28 | 29 | const unsigned char U_23E8[] = "⏨"; 30 | int buf_pos = 0; 31 | if (ch == U_23E8[0]) { 32 | char_buffer[buf_pos++] = ch; 33 | ch = in_stream->sbumpc(); 34 | if (ch == EOF) 35 | return EOF; // in the middle of a UTF-8 symbol 36 | if (ch == U_23E8[1]) { 37 | char_buffer[buf_pos++] = ch; 38 | ch = in_stream->sbumpc(); 39 | if (ch == EOF) 40 | return EOF; // in the middle of a UTF-8 symbol 41 | if (ch == U_23E8[2]) { 42 | ch = 'E'; 43 | buf_pos = 0; 44 | } 45 | } 46 | } 47 | 48 | // Put the character back into the stream 49 | this->setg(char_buffer, char_buffer, char_buffer + buf_pos + 1); 50 | char_buffer[buf_pos] = ch; 51 | return int(char_buffer[0]) & 0xFF; 52 | } 53 | 54 | private: 55 | std::streambuf* in_stream; // The original stream buffer 56 | char char_buffer[3]{}; // Buffer to store up to 3 characters 57 | }; 58 | 59 | class ReplaceTenWithEStream : public std::istream { 60 | public: 61 | explicit ReplaceTenWithEStream(std::istream& inp) : std::istream(&buf), buf(inp) {} 62 | 63 | private: 64 | ReplaceTenWithEStreamBuf buf; // Custom stream buffer 65 | }; 66 | 67 | // 68 | // Read real or integer number from input stream. 69 | // Return the number. 70 | // On end of file, throw exception. 71 | // When input is invalid: 72 | // - throw exception when non-interactive 73 | // - retry when in interactive mode 74 | // 75 | long double Machine::input_real(std::istream &orig_stream) 76 | { 77 | ReplaceTenWithEStream input_stream(orig_stream); 78 | // Loop until user enters a valid input 79 | for (;;) { 80 | if (is_interactive) { 81 | std::cout << "Enter number: " << std::flush; 82 | } 83 | long double x{}; 84 | input_stream >> x; 85 | 86 | if (input_stream) { 87 | // Number is valid. 88 | return x; 89 | } 90 | 91 | // Cannot parse the input. 92 | if (input_stream.eof()) { 93 | throw std::runtime_error("No input"); 94 | } 95 | if (!is_interactive) { 96 | throw std::runtime_error("Bad input"); 97 | } 98 | std::cout << "Bad input, try again.\n"; 99 | input_stream.clear(); 100 | 101 | // Remove bad input and try again. 102 | input_stream.ignore(std::numeric_limits::max(), '\n'); 103 | } 104 | } 105 | 106 | // 107 | // Read console switches. 108 | // Called by XEEN procedure. 109 | // 110 | unsigned Machine::read_console_switches(std::istream &input_stream, unsigned bitmask) 111 | { 112 | if (!switches_are_valid) { 113 | // Loop until user enters a valid input 114 | for (;;) { 115 | if (is_interactive) { 116 | std::cout << "\n"; 117 | std::cout << "Enter console switches (up to 27 binary digits)\n"; 118 | std::cout << "> " << std::flush; 119 | } 120 | try { 121 | std::string line; 122 | if (std::getline(input_stream, line)) { 123 | console_switches = std::stoul(line, nullptr, 2); 124 | switches_are_valid = true; 125 | break; 126 | } 127 | } catch (...) { 128 | // No valid number. 129 | } 130 | 131 | // Cannot parse the input. 132 | if (input_stream.eof()) { 133 | throw std::runtime_error("No input"); 134 | } 135 | if (!is_interactive) { 136 | throw std::runtime_error("Bad input"); 137 | } 138 | std::cout << "Bad input, try again.\n"; 139 | input_stream.clear(); 140 | } 141 | } 142 | return console_switches & bitmask; 143 | } 144 | 145 | // 146 | // Read character from input stream. 147 | // Return integer number in Algol encoding. 148 | // On end of file, return 0. 149 | // 150 | int Machine::input_char(std::istream &stream) 151 | { 152 | char ch; 153 | again: 154 | if (!stream.get(ch)) { 155 | // End of file. 156 | eof: return 0377; 157 | } 158 | if (ch >= '0' && ch <= '9') { 159 | // Digits. 160 | return ch - '0'; 161 | } 162 | if (ch >= 'a' && ch <= 'z') { 163 | // Letters lowercase. 164 | return ch - 'a' + 10; 165 | } 166 | if (ch >= 'A' && ch <= 'Z') { 167 | // Letters uppercase. 168 | return ch - 'A' + 37; 169 | } 170 | switch (ch) { 171 | case '+': return 64; 172 | case '-': return 65; 173 | case '*': return 66; // × 174 | case '/': return 67; 175 | case '>': return 70; 176 | case '=': return 72; 177 | case '<': return 74; 178 | case ',': return 87; 179 | case '.': return 88; 180 | case '@': return 89; // ⏨ 181 | case ':': return 90; 182 | case ';': return 91; 183 | case ' ': return 93; // space 184 | case '(': return 98; 185 | case ')': return 99; 186 | case '[': return 100; 187 | case ']': return 101; 188 | case '`': return 102; 189 | case '\'': return 103; 190 | case '\t': return 118; // tab 191 | case '\n': return 119; // newline 192 | case '\r': goto again; // CR - ignore 193 | case '"': return 121; 194 | case '?': return 122; 195 | case '|': return 162; 196 | case '_': return 163; 197 | case '\302': 198 | if (!stream.get(ch)) { 199 | goto eof; 200 | } 201 | switch (ch) { 202 | case '\254': return 76; // ¬ 203 | default: goto bad; 204 | } 205 | case '\303': 206 | if (!stream.get(ch)) { 207 | goto eof; 208 | } 209 | switch (ch) { 210 | case '\227': return 66; // × 211 | case '\267': return 68; // ÷ 212 | default: goto bad; 213 | } 214 | case '\342': 215 | if (!stream.get(ch)) { 216 | goto eof; 217 | } 218 | switch (ch) { 219 | case '\206': 220 | if (!stream.get(ch)) { 221 | goto eof; 222 | } 223 | switch (ch) { 224 | case '\221': return 69; // ↑ 225 | default: goto bad; 226 | } 227 | case '\210': 228 | if (!stream.get(ch)) { 229 | goto eof; 230 | } 231 | switch (ch) { 232 | case '\247': return 77; // ∧ 233 | case '\250': return 78; // ∨ 234 | default: goto bad; 235 | } 236 | case '\211': 237 | if (!stream.get(ch)) { 238 | goto eof; 239 | } 240 | switch (ch) { 241 | case '\240': return 75; // ≠ 242 | case '\241': return 80; // ≡ 243 | case '\244': return 73; // ≤ 244 | case '\245': return 71; // ≥ 245 | default: goto bad; 246 | } 247 | case '\212': 248 | if (!stream.get(ch)) { 249 | goto eof; 250 | } 251 | switch (ch) { 252 | case '\203': return 79; // ⊃ 253 | default: goto bad; 254 | } 255 | case '\217': 256 | if (!stream.get(ch)) { 257 | goto eof; 258 | } 259 | switch (ch) { 260 | case '\250': return 89; // ⏨ 261 | default: goto bad; 262 | } 263 | default: goto bad; 264 | } 265 | default: 266 | bad: throw std::runtime_error("Bad input character 0" + to_octal(ch & 0377)); 267 | } 268 | } 269 | -------------------------------------------------------------------------------- /simulator/machine.h: -------------------------------------------------------------------------------- 1 | #ifndef X1_MACHINE_H 2 | #define X1_MACHINE_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "processor.h" 12 | 13 | class Machine { 14 | private: 15 | // Enable a progress message to stderr. 16 | bool progress_message_enabled{ false }; 17 | 18 | // Every few seconds, print a message to stderr, to track the simulation progress. 19 | void show_progress(); 20 | 21 | // Time of last check. 22 | std::chrono::time_point progress_time_last{ 23 | std::chrono::steady_clock::now() 24 | }; 25 | 26 | // Last instr_count when progress message was printed. 27 | uint64_t progress_count{ 0 }; 28 | 29 | // Trace output. 30 | static std::ofstream trace_stream; 31 | 32 | // Trace machine instuctions and registers. 33 | static bool debug_flag; 34 | 35 | // Count of instructions. 36 | static uint64_t simulated_instructions; 37 | 38 | // Provided input files (Algol source, X1 object file, libraries) 39 | std::vector input_files; 40 | 41 | // Compiler of choice. 42 | std::string compiler_path; 43 | 44 | // Default Algol library. 45 | std::string default_library; 46 | 47 | // Status of the simulation. 48 | int exit_status{ EXIT_SUCCESS }; 49 | 50 | // 32K words of memory. 51 | std::array memory{}; 52 | 53 | // Table of symbol addresses from object program. 54 | std::map symbol_table; 55 | 56 | // Table of entry addresses from object program. 57 | std::vector entry_table; 58 | 59 | // True when stdin is connected to terminal. 60 | static bool is_interactive; 61 | 62 | // State of console switches. 63 | unsigned console_switches{}; 64 | bool switches_are_valid{}; 65 | 66 | // Initial value for random number generator. 67 | unsigned random_seed{}; 68 | Real random_output{}; 69 | std::mt19937 random_generator{ 1 }; 70 | 71 | public: 72 | // Electrologica X1 processor. 73 | Processor cpu{ *this }; 74 | 75 | // Destructor. 76 | ~Machine(); 77 | 78 | // Add a file to the list of input files. 79 | void add_input_file(const std::string &filename); 80 | 81 | // Return the first input file (Algol source or X1 object file). 82 | unsigned input_file_count() const { return input_files.size(); } 83 | 84 | // Set name of compiler. 85 | void set_compiler(const std::string &filename); 86 | 87 | // Find location of default Algol library. 88 | void find_default_library(const char *argv0); 89 | void set_default_library(const std::string &path) { default_library = path; } 90 | 91 | // Compile Algol file to object format. 92 | void compile(const std::vector &filenames, const std::string &obj_filename); 93 | 94 | // Load object file into memory. 95 | void load_object_program(const std::string &obj_filename); 96 | 97 | // Run external program with given input and output files. 98 | static void run_program(const std::string &prog_path, const std::vector &input_filenames, 99 | const std::string &output_filename); 100 | 101 | // Build vector of argument pointers. 102 | static std::vector build_argv(const std::string &arg0, const std::vector &args); 103 | 104 | // Convert vector of arguments into C representation for execvp(). 105 | static auto get_argv(const std::vector &argv) { return const_cast(argv.data()); } 106 | 107 | // Compile the input Algol file and simulate it. 108 | void compile_and_run(); 109 | 110 | // Run simulation. 111 | void run(unsigned start_addr); 112 | 113 | // Get address by name from symbol table. 114 | unsigned get_symbol(const std::string &name) { return symbol_table.at(name); } 115 | 116 | // Get entry address by index. 117 | unsigned get_entry(unsigned index) { return entry_table[index]; } 118 | 119 | // Get status of simulation: either EXIT_SUCCESS (0) or 120 | // EXIT_FAILURE in case of errors. 121 | int get_exit_status() const { return exit_status; } 122 | 123 | // Enable a progress message to stderr. 124 | void enable_progress_message(bool on) { progress_message_enabled = on; } 125 | 126 | // Print string from memory. 127 | void print_string(std::ostream &out, unsigned addr); 128 | 129 | // Get instruction count. 130 | static uint64_t get_instr_count() { return simulated_instructions; } 131 | static void incr_simulated_instructions() { simulated_instructions++; } 132 | 133 | // Enable trace output to the given file, 134 | // or to std::cout when filename not present. 135 | static void enable_trace(bool on = true) { debug_flag = on; } 136 | static void redirect_trace(const char *file_name, bool on = debug_flag); 137 | static void close_trace(); 138 | static bool trace_enabled() { return debug_flag; } 139 | 140 | // Emit trace to this stream. 141 | static std::ostream &get_trace_stream(); 142 | 143 | // Memory access. 144 | Word mem_fetch(unsigned addr); 145 | Word mem_load(unsigned addr); 146 | void mem_store(unsigned addr, Word val); 147 | 148 | // Read number from stream. 149 | static long double input_real(std::istream &stream); 150 | 151 | // Read character from stdin. 152 | static int input_char(std::istream &stream); 153 | 154 | // Read console switches. 155 | unsigned read_console_switches(std::istream &stream, unsigned bitmask); 156 | 157 | // Ask operator for console input. 158 | void ask_console_input() { switches_are_valid = false; } 159 | 160 | // Print number in floating-point representation. 161 | static void print_floating_point(std::ostream &stream, int n, int m, long double x); 162 | 163 | // Print number in fixed-point representation, with or without a sign. 164 | static void print_fixed_point(std::ostream &stream, int n, int m, long double x, 165 | bool need_sign); 166 | 167 | // Print number in fixed-point or floating-point representation. 168 | static void print_int_or_real(std::ostream &stream, long double x); 169 | 170 | // 171 | // Trace methods. 172 | // 173 | static void trace_exception(const char *message) 174 | { 175 | if (trace_enabled()) 176 | print_exception(message); 177 | } 178 | 179 | static void trace_memory_write(unsigned addr, Word val) 180 | { 181 | if (debug_flag) 182 | print_memory_access(addr, val, "Write"); 183 | } 184 | 185 | static void trace_memory_read(unsigned addr, Word val) 186 | { 187 | if (debug_flag) 188 | print_memory_access(addr, val, "Read"); 189 | } 190 | 191 | static void trace_stack(unsigned offset, const std::string &value, const std::string &op) 192 | { 193 | if (debug_flag) 194 | print_stack_op(offset, value, op); 195 | } 196 | 197 | static void trace_display(unsigned level, unsigned value) 198 | { 199 | if (debug_flag) 200 | print_display(level, value); 201 | } 202 | 203 | void trace_level(unsigned level, unsigned frame) 204 | { 205 | if (debug_flag) 206 | print_level(level, frame); 207 | } 208 | 209 | void trace_level() 210 | { 211 | if (debug_flag) 212 | print_level(); 213 | } 214 | 215 | void trace_instruction(unsigned opcode) 216 | { 217 | if (debug_flag) 218 | cpu.print_instruction(); 219 | } 220 | 221 | void trace_registers() 222 | { 223 | if (debug_flag) 224 | cpu.print_registers(); 225 | } 226 | 227 | static void print_exception(const char *message); 228 | static void print_memory_access(unsigned addr, Word val, const char *opname); 229 | static void print_stack_op(unsigned offset, const std::string &value, const std::string &op); 230 | static void print_display(unsigned level, unsigned value); 231 | void print_level(unsigned level, unsigned frame); 232 | void print_level(); 233 | }; 234 | 235 | // 236 | // Decode word as string. 237 | // 238 | std::string word_string(Word w); 239 | 240 | #endif // X1_MACHINE_H 241 | -------------------------------------------------------------------------------- /simulator/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | #include "machine.h" 7 | 8 | // 9 | // CLI options. 10 | // 11 | static const struct option long_options[] = { 12 | // clang-format off 13 | { "help", no_argument, nullptr, 'h' }, 14 | { "version", no_argument, nullptr, 'V' }, 15 | { "trace", required_argument, nullptr, 'T' }, 16 | { "debug", required_argument, nullptr, 'd' }, 17 | { nullptr }, 18 | // clang-format on 19 | }; 20 | 21 | // 22 | // Print usage message. 23 | // 24 | static void print_usage(std::ostream &out, const char *prog_name) 25 | { 26 | out << "X1 Algol Simulator, Version " << VERSION_STRING << "\n"; 27 | out << "Usage:\n"; 28 | out << " " << prog_name << " [options...] file.[a60|x1] [library ...]\n"; 29 | out << "Input files:\n"; 30 | out << " file.a60 Algol-60 program source\n"; 31 | out << " file.x1 Binary program for Electrologica X1\n"; 32 | out << " library If a source file is given, the library file(s)\n"; 33 | out << " are passed to the compiler\n"; 34 | out << "Options:\n"; 35 | out << " -h, --help Display available options\n"; 36 | out << " -V, --version Print the version number and exit\n"; 37 | out << " --trace=FILE Redirect trace to the file\n"; 38 | out << " -d, --debug Enable tracing\n"; 39 | } 40 | 41 | // 42 | // Main routine of the simulator, 43 | // when invoked from a command line. 44 | // 45 | int main(int argc, char *argv[]) 46 | { 47 | // Get the program name. 48 | const char *prog_name = strrchr(argv[0], '/'); 49 | if (prog_name == nullptr) { 50 | prog_name = argv[0]; 51 | } else { 52 | prog_name++; 53 | } 54 | 55 | // Instantiate the machine. 56 | Machine machine; 57 | 58 | // Use C version of the Algol compiler by default. 59 | machine.set_compiler("x1algc"); 60 | 61 | // Parse command line options. 62 | for (;;) { 63 | switch (getopt_long(argc, argv, "-hVT:d", long_options, nullptr)) { 64 | case EOF: 65 | break; 66 | 67 | case 0: 68 | continue; 69 | 70 | case 1: 71 | // Regular argument. 72 | machine.add_input_file(optarg); 73 | continue; 74 | 75 | case 'h': 76 | // Show usage message and exit. 77 | print_usage(std::cout, prog_name); 78 | exit(EXIT_SUCCESS); 79 | 80 | case 'V': 81 | // Show version and exit. 82 | std::cout << "Version " << VERSION_STRING << "\n"; 83 | exit(EXIT_SUCCESS); 84 | 85 | case 'T': 86 | // Redirect tracing to given file. 87 | Machine::redirect_trace(optarg); 88 | Machine::get_trace_stream() << "X1 Algol Simulator Version: " << VERSION_STRING << "\n"; 89 | continue; 90 | 91 | case 'd': 92 | // Set trace options. 93 | machine.enable_trace(); 94 | continue; 95 | 96 | default: 97 | print_usage(std::cerr, prog_name); 98 | exit(EXIT_FAILURE); 99 | } 100 | break; 101 | } 102 | 103 | // Must specify an Algol file or an object file. 104 | if (machine.input_file_count() < 1) { 105 | print_usage(std::cerr, prog_name); 106 | exit(EXIT_FAILURE); 107 | } 108 | 109 | try { 110 | if (machine.input_file_count() == 1) { 111 | machine.find_default_library(argv[0]); 112 | } 113 | machine.compile_and_run(); 114 | 115 | } catch (std::exception &ex) { 116 | std::cerr << "Error: " << ex.what() << std::endl; 117 | exit(EXIT_FAILURE); 118 | } 119 | 120 | return machine.get_exit_status(); 121 | } 122 | -------------------------------------------------------------------------------- /simulator/opc.h: -------------------------------------------------------------------------------- 1 | // 2 | // The OPC table, from Appendix C. 3 | // 4 | enum { 5 | OPC_ETMR = 8, // extransmark result 6 | OPC_ETMP = 9, // extransmark procedure 7 | OPC_FTMR = 10, // formtransmark result 8 | OPC_FTMP = 11, // formtransmark procedure 9 | OPC_RET = 12, // return 10 | OPC_EIS = 13, // end of implicit subroutine 11 | 12 | OPC_TRAD = 14, // take real address dynamic 13 | OPC_TRAS = 15, // take real address static 14 | OPC_TIAD = 16, // take integer address dynamic 15 | OPC_TIAS = 17, // take integer address static 16 | OPC_TFA = 18, // take formal address 17 | 18 | OPC_FOR0 = 19, 19 | OPC_FOR1 = 20, 20 | OPC_FOR2 = 21, 21 | OPC_FOR3 = 22, 22 | OPC_FOR4 = 23, 23 | 24 | OPC_FOR5 = 24, 25 | OPC_FOR6 = 25, 26 | OPC_FOR7 = 26, 27 | OPC_FOR8 = 27, 28 | 29 | OPC_GTA = 28, // goto adjustment 30 | OPC_SSI = 29, // store switch index 31 | OPC_CAC = 30, // copy boolean acc. into condition 32 | 33 | OPC_TRRD = 31, // take real result dynamic 34 | OPC_TRRS = 32, // take real result static 35 | OPC_TIRD = 33, // take integer result dynamic 36 | OPC_TIRS = 34, // take integer result static 37 | OPC_TFR = 35, // take formal result 38 | 39 | OPC_ADRD = 36, // add real dynamic 40 | OPC_ADRS = 37, // add real static 41 | OPC_ADID = 38, // add integer dynamic 42 | OPC_ADIS = 39, // add integer static 43 | OPC_ADF = 40, // add formal 44 | 45 | OPC_SURD = 41, // subtract real dynamic 46 | OPC_SURS = 42, // subtract real static 47 | OPC_SUID = 43, // subtract integer dynamic 48 | OPC_SUIS = 44, // subtract integer static 49 | OPC_SUF = 45, // subtract formal 50 | 51 | OPC_MURD = 46, // multiply real dynamic 52 | OPC_MURS = 47, // multiply real static 53 | OPC_MUID = 48, // multiply integer dynamic 54 | OPC_MUIS = 49, // multiply integer 55 | OPC_MUF = 50, // static multiply formal 56 | 57 | OPC_DIRD = 51, // divide real dynamic 58 | OPC_DIRS = 52, // divide real static 59 | OPC_DIID = 53, // divide integer dynamic 60 | OPC_DIIS = 54, // divide integer static 61 | OPC_DIF = 55, // divide formal 62 | 63 | OPC_IND = 56, // indexer 64 | 65 | OPC_NEG = 57, // invert sign accumulator 66 | 67 | OPC_TAR = 58, // take result 68 | OPC_ADD = 59, // add 69 | OPC_SUB = 60, // subtract 70 | OPC_MUL = 61, // multiply 71 | OPC_DIV = 62, // divide 72 | OPC_IDI = 63, // integer division 73 | OPC_TTP = 64, // to the power 74 | 75 | OPC_MOR = 65, // more > 76 | OPC_LST = 66, // at least ≥ 77 | OPC_EQU = 67, // equal = 78 | OPC_MST = 68, // at most ≤ 79 | OPC_LES = 69, // less < 80 | OPC_UQU = 70, // unequal ̸= 81 | 82 | OPC_NON = 71, // non ¬ 83 | OPC_AND = 72, // and ∧ 84 | OPC_OR = 73, // or ∨ 85 | OPC_IMP = 74, // implies → 86 | OPC_QVL = 75, // equivalent ≡ 87 | 88 | OPC_abs = 76, 89 | OPC_sign = 77, 90 | OPC_sqrt = 78, 91 | OPC_sin = 79, 92 | OPC_cos = 80, 93 | OPC_arctan = 81, 94 | OPC_ln = 82, 95 | OPC_exp = 83, 96 | OPC_entier = 84, 97 | 98 | OPC_ST = 85, // store 99 | OPC_STA = 86, // store also 100 | OPC_STP = 87, // store procedure value 101 | OPC_STAP = 88, // store also procedure value 102 | 103 | OPC_SCC = 89, // short circuit 104 | OPC_RSF = 90, // real arrays storage function frame 105 | OPC_ISF = 91, // integer arrays storage function frame 106 | OPC_RVA = 92, // real value array storage function frame 107 | OPC_IVA = 93, // integer value array storage function frame 108 | OPC_LAP = 94, // local array positioning 109 | OPC_VAP = 95, // value array positioning 110 | 111 | OPC_START = 96, // start of the object program 112 | OPC_STOP = 97, // end of the object program 113 | 114 | OPC_TFP = 98, // take formal parameter 115 | OPC_TAS = 99, // type algol symbol 116 | OPC_OBC6 = 100, // output buffer class 6 117 | OPC_FLOATER = 101, 118 | OPC_read = 102, 119 | OPC_print = 103, 120 | OPC_TAB = 104, 121 | OPC_NLCR = 105, 122 | OPC_XEEN = 106, 123 | OPC_SPACE = 107, 124 | OPC_stop = 108, 125 | OPC_P21 = 109, 126 | 127 | OPC_FLOT = 110, // using OPC for FLOT, FIXT, ABSFIXT 128 | OPC_FIXT = 111, // temporarily for convenience 129 | OPC_ABSFIXT = 112, 130 | }; 131 | -------------------------------------------------------------------------------- /simulator/processor.h: -------------------------------------------------------------------------------- 1 | #ifndef X1_PROCESSOR_H 2 | #define X1_PROCESSOR_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "virtual_stack.h" 9 | #include "x1_arch.h" 10 | 11 | class Machine; 12 | 13 | // 14 | // Internal state of the processor. 15 | // 16 | struct CoreState { 17 | unsigned B; // stack address + sign bit 18 | Word A; // accumulator 19 | Word S; // extension of accumulator 20 | bool C; // condition 21 | bool L; // sign bit at the last condition-setting instruction 22 | }; 23 | 24 | // 25 | // Offsets in stack relative to frame_ptr. 26 | // 27 | namespace Frame_Offset { 28 | enum { 29 | RESULT = -1, // Result to be returned 30 | FP = 0, // Caller's frame pointer 31 | PC = 1, // Caller's program counter 32 | SP = 2, // Caller's stack base 33 | BN = 3, // Lexical scope block level (number) 34 | DISPLAY = 4, // Previous display[bn] 35 | ARG = 5, // First argument of procedure, must be 5 36 | }; 37 | }; 38 | 39 | // 40 | // When retrieving a formal parameter, apply the following operation. 41 | // 42 | enum class Formal_Op { 43 | PUSH_VALUE, // Push number on stack 44 | PUSH_ADDRESS, // Push address on stack 45 | PUSH_STRING, // Push string on stack 46 | REMOVE_ARG, // Remove dummy argument from stack 47 | ADD, // Add number to top of stack 48 | SUBTRACT, // Subtract number from top of stack 49 | MULTIPLY, // Multily top of stack by number 50 | DIVIDE, // Divide top of stack by number 51 | PUSH_DEREF, // Dereference then push on stack 52 | ADD_DEREF, // Dereference then add 53 | SUBTRACT_DEREF, // Dereference then subtract 54 | MULTIPLY_DEREF, // Dereference then multiply 55 | DIVIDE_DEREF, // Dereference then divide 56 | }; 57 | std::ostream &operator<<(std::ostream &out, Formal_Op op); 58 | Formal_Op deref(Formal_Op op); 59 | 60 | // 61 | // Electrologica X1 processor. 62 | // 63 | class Processor { 64 | private: 65 | // Reference to the machine. 66 | Machine &machine; 67 | 68 | // Current state. 69 | struct CoreState core {}; 70 | 71 | // Previous state, for tracing. 72 | struct CoreState prev {}; 73 | unsigned prev_frame_ptr{}; 74 | unsigned prev_stack_ptr{}; 75 | 76 | unsigned OT{}; // order counter 77 | unsigned OR{}; // order register 78 | 79 | // Pointer to a procedure frame in stack. 80 | unsigned frame_ptr{}; 81 | unsigned last_frame_ptr{}; 82 | 83 | // Base of stack in current block. 84 | unsigned stack_base{}; 85 | 86 | // Frame pointers for each block level. 87 | unsigned display[32]{}; 88 | 89 | // Stack contents is mapped to this virtual address. 90 | static unsigned const STACK_BASE = 0100000; 91 | 92 | // Apply this operation when returning from implicit subroutine (on EIS). 93 | // Indexed by stack base. 94 | std::unordered_map eis_operation; 95 | 96 | public: 97 | // Stack of arguments for OPC. 98 | Virtual_Stack stack; 99 | 100 | // Constructor. 101 | explicit Processor(Machine &mach) : machine(mach) { reset(); } 102 | 103 | // Reset to initial state. 104 | void reset(); 105 | 106 | // Simulate one instruction. 107 | // Return true when the processor is stopped. 108 | bool step(); 109 | 110 | // Set register value. 111 | void set_ot(unsigned val) { OT = val; } 112 | void set_b(unsigned val) { core.B = val; } 113 | void set_c(bool val) { core.C = val; } 114 | void set_a(Word val) { core.A = val; } 115 | void set_s(Word val) { core.S = val; } 116 | 117 | // Get register value. 118 | unsigned get_ot() const { return OT; } 119 | unsigned get_b() const { return core.B; } 120 | bool get_c() const { return core.C; } 121 | Word get_a() const { return core.A; } 122 | Word get_s() const { return core.S; } 123 | 124 | // Get frame pointer. 125 | unsigned get_frame_ptr() const { return frame_ptr; } 126 | 127 | // Print trace info. 128 | void print_instruction(); 129 | void print_registers(); 130 | 131 | // Get lexical scope level, or block number (BN). 132 | unsigned get_block_level() const; 133 | unsigned get_display(unsigned block_level) const; 134 | 135 | // Update all display[] entries starting from given level and frame. 136 | void update_display(unsigned block_level, unsigned fp); 137 | 138 | // Roll stack back to the 'goto' frame. 139 | void roll_back(unsigned goto_frame); 140 | 141 | private: 142 | // Invoke run-time routine. 143 | // Return true when the processor is stopped. 144 | bool call_opc(unsigned opc); 145 | 146 | // Loads a real value at addr. 147 | Real load_real(unsigned addr); 148 | 149 | // Create frame in stack for new procedure block. 150 | void frame_create(unsigned ret_addr, unsigned num_args); 151 | 152 | // Deallocate frame in stack when leaving the procedure. 153 | // Return address is returned. 154 | unsigned frame_release(); 155 | 156 | // Allocate local variables. 157 | void allocate_stack(unsigned nwords); 158 | 159 | // Convert dynamic address of variable (relative to stack frame) 160 | // into offset in stack. 161 | unsigned address_in_stack(unsigned dynamic_addr); 162 | 163 | // Extract descriptor of actual argument. 164 | unsigned arg_descriptor(unsigned dynamic_addr); 165 | unsigned arg_address(unsigned dynamic_addr, unsigned arg_descr); 166 | void get_arg_display(unsigned const arg, unsigned &block_level, unsigned &prev_display); 167 | 168 | // Store value given by src cell. 169 | // Write it to memory address given by dest cell. 170 | void store_value(const Stack_Cell &dest, const Stack_Cell &src); 171 | 172 | // Load value by the address in the src cell. 173 | Stack_Cell load_value(const Stack_Cell &src); 174 | 175 | // The common part of all OPCs dealing with dynamic integers. 176 | Stack_Cell get_dynamic_int(unsigned dynamic_addr); 177 | 178 | // The common part of all OPCs dealing with dynamic reals. 179 | Stack_Cell get_dynamic_real(unsigned dynamic_addr); 180 | 181 | // Retrieve value of formal parameter. 182 | void take_formal(unsigned dynamic_addr, Formal_Op op); 183 | 184 | // Get address of procedure parameter at dynamic address. 185 | unsigned get_formal_proc(unsigned dynamic_addr); 186 | 187 | // Set lexical scope level, or block number (BN). 188 | void set_block_level(unsigned block_level); 189 | 190 | // Update display[n] value. 191 | void set_display(unsigned block_level, unsigned value); 192 | 193 | // Helper methods for dynamic arrays. 194 | void make_storage_function_frame(int elt_size); 195 | void make_value_array_function_frame(int elt_size); 196 | Word load_word(unsigned addr); 197 | 198 | // Apply given operation to the retrieved address of formal parameter. 199 | void apply_operation(Formal_Op post_op, unsigned addr, Cell_Type type); 200 | 201 | // Apply operation on top of stack. 202 | void apply_operation(Formal_Op post_op); 203 | 204 | void increment_stack_base(int amount); 205 | }; 206 | 207 | #endif // X1_PROCESSOR_H 208 | -------------------------------------------------------------------------------- /simulator/trace.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "machine.h" 7 | 8 | // 9 | // Flag to enable tracing. 10 | // 11 | bool Machine::debug_flag; 12 | 13 | // 14 | // Emit trace to this stream. 15 | // 16 | std::ofstream Machine::trace_stream; 17 | 18 | // 19 | // Redirect trace output to a given file. 20 | // 21 | void Machine::redirect_trace(const char *file_name, bool on) 22 | { 23 | if (trace_stream.is_open()) { 24 | // Close previous file. 25 | trace_stream.close(); 26 | } 27 | if (file_name && file_name[0]) { 28 | // Open new trace file. 29 | trace_stream.open(file_name); 30 | if (!trace_stream.is_open()) 31 | throw std::runtime_error("Cannot write to " + std::string(file_name)); 32 | } 33 | 34 | if (!trace_enabled()) { 35 | enable_trace(on); 36 | } 37 | } 38 | 39 | std::ostream &Machine::get_trace_stream() 40 | { 41 | if (trace_stream.is_open()) { 42 | return trace_stream; 43 | } 44 | return std::cout; 45 | } 46 | 47 | void Machine::close_trace() 48 | { 49 | if (trace_stream.is_open()) { 50 | // Close output. 51 | trace_stream.close(); 52 | } 53 | 54 | // Disable trace options. 55 | enable_trace(false); 56 | } 57 | 58 | // 59 | // Trace output 60 | // 61 | void Machine::print_exception(const char *message) 62 | { 63 | auto &out = Machine::get_trace_stream(); 64 | out << "--- " << message << std::endl; 65 | } 66 | 67 | // 68 | // Print memory read/write. 69 | // 70 | void Machine::print_memory_access(unsigned addr, Word val, const char *opname) 71 | { 72 | auto &out = Machine::get_trace_stream(); 73 | auto save_flags = out.flags(); 74 | 75 | out << " Memory " << opname << " [" << std::oct << std::setfill('0') << std::setw(5) 76 | << addr << "] = "; 77 | x1_print_word_octal(out, val); 78 | out << std::endl; 79 | 80 | // Restore. 81 | out.flags(save_flags); 82 | } 83 | 84 | // 85 | // Print stack push/pop. 86 | // 87 | void Machine::print_stack_op(unsigned offset, const std::string &value, const std::string &opname) 88 | { 89 | auto &out = Machine::get_trace_stream(); 90 | auto save_flags = out.flags(); 91 | 92 | out << " Stack " << opname << " [" << std::oct << offset << "] = " << value << std::endl; 93 | 94 | // Restore. 95 | out.flags(save_flags); 96 | } 97 | 98 | // 99 | // Print display[] change. 100 | // 101 | void Machine::print_display(unsigned level, unsigned value) 102 | { 103 | auto &out = Machine::get_trace_stream(); 104 | auto save_flags = out.flags(); 105 | 106 | out << " Display [" << std::oct << level << "] = "; 107 | out << std::setfill('0') << std::setw(5) << value; 108 | out << std::endl; 109 | 110 | // Restore. 111 | out.flags(save_flags); 112 | } 113 | 114 | // 115 | // Print change of lexical level. 116 | // 117 | void Machine::print_level(unsigned new_level, unsigned new_frame) 118 | { 119 | unsigned old_level = cpu.get_block_level(); 120 | unsigned old_frame = cpu.get_display(old_level); 121 | 122 | auto &out = Machine::get_trace_stream(); 123 | auto save_flags = out.flags(); 124 | 125 | out << " Change Level " << std::oct << old_level << ", Frame " << old_frame 126 | << " -> Level " << new_level << ", Frame " << new_frame << std::endl; 127 | 128 | // Restore. 129 | out.flags(save_flags); 130 | } 131 | 132 | // 133 | // Print instruction address, opcode from OR and mnemonics. 134 | // 135 | void Processor::print_instruction() 136 | { 137 | auto &out = Machine::get_trace_stream(); 138 | auto save_flags = out.flags(); 139 | 140 | out << std::oct << std::setfill('0') << std::setw(5) << OT << ": "; 141 | x1_print_word_octal(out, OR); 142 | out << ' '; 143 | x1_print_instruction(out, OR); 144 | out << std::endl; 145 | 146 | // Restore. 147 | out.flags(save_flags); 148 | } 149 | 150 | // 151 | // Print changes in CPU registers. 152 | // 153 | void Processor::print_registers() 154 | { 155 | auto &out = Machine::get_trace_stream(); 156 | auto save_flags = out.flags(); 157 | 158 | if (core.A != prev.A) { 159 | out << " A = "; 160 | x1_print_word_octal(out, core.A); 161 | out << std::endl; 162 | } 163 | if (core.B != prev.B) { 164 | out << " B = " << std::oct << core.B << std::dec << std::endl; 165 | } 166 | if (core.C != prev.C) { 167 | out << " C = " << core.C << std::endl; 168 | } 169 | if (core.S != prev.S) { 170 | out << " S = "; 171 | x1_print_word_octal(out, core.S); 172 | out << std::endl; 173 | } 174 | if (stack.count() != prev_stack_ptr) { 175 | out << " SP = " << std::oct << stack.count() << std::dec << std::endl; 176 | } 177 | if (frame_ptr != prev_frame_ptr) { 178 | out << " FP = " << std::oct << frame_ptr << std::dec << std::endl; 179 | } 180 | 181 | // Update previous state. 182 | prev = core; 183 | prev_frame_ptr = frame_ptr; 184 | prev_stack_ptr = stack.count(); 185 | 186 | // Restore output flags. 187 | out.flags(save_flags); 188 | } 189 | -------------------------------------------------------------------------------- /simulator/virtual_stack.h: -------------------------------------------------------------------------------- 1 | #ifndef X1_VIRTUAL_STACK_H 2 | #define X1_VIRTUAL_STACK_H 3 | 4 | #include 5 | 6 | #include "x1_arch.h" 7 | 8 | // 9 | // Tag to indicate whether the cell contains the address of an integer variable 10 | // or array, the address of a real variable or array, an integer value, or a real value. 11 | // 12 | enum class Cell_Type { 13 | NUL, // Empty value 14 | INTEGER_ADDRESS, // Address of integer value 15 | REAL_ADDRESS, // Address of real value 16 | INTEGER_VALUE, // Integer value in bits 26:0 17 | REAL_VALUE, // Real value in bits 53:0 18 | }; 19 | 20 | // 21 | // Stack cells of the hypothetic stack machine. 22 | // 23 | struct Stack_Cell { 24 | Cell_Type type; 25 | uint64_t value; 26 | 27 | // Quick check of the type of the value. 28 | bool is_null() const { return type == Cell_Type::NUL; } 29 | bool is_int_value() const { return type == Cell_Type::INTEGER_VALUE; } 30 | bool is_int_addr() const { return type == Cell_Type::INTEGER_ADDRESS; } 31 | bool is_real_value() const { return type == Cell_Type::REAL_VALUE; } 32 | bool is_real_addr() const { return type == Cell_Type::REAL_ADDRESS; } 33 | 34 | // Get value for a given type. 35 | unsigned get_addr() const { return value & BITS(27); } 36 | Word get_int() const { return value & BITS(27); } 37 | Real get_real() const { return value & BITS(54); } 38 | 39 | // Get sign: +1, 0 or -1. 40 | int sign() const; 41 | 42 | void set(uint64_t v) { value = v; } 43 | 44 | // Convert the value to string. 45 | std::string to_string() const; 46 | 47 | // Compare this item and another one. 48 | bool is_less(const Stack_Cell &another) const; 49 | bool is_equal(const Stack_Cell &another) const; 50 | 51 | // Raise this item to the power given by another cell. 52 | void exponentiate(const Stack_Cell &another); 53 | void exponentiate_int(int a, const Stack_Cell &another); 54 | void exponentiate_real(long double a, const Stack_Cell &another); 55 | 56 | // Multiply this item by another one. 57 | void multiply(const Stack_Cell &another); 58 | void multiply_real(Real another); 59 | 60 | // Divide this item by another one. 61 | void divide(const Stack_Cell &another); 62 | 63 | // Add another item to this one. 64 | void add(const Stack_Cell &another); 65 | void subtract(const Stack_Cell &another); 66 | }; 67 | 68 | class Virtual_Stack { 69 | private: 70 | std::vector storage; 71 | 72 | // Some arbitrary limit on stack size. 73 | static unsigned const SIZE_LIMIT = 0x100000; 74 | 75 | public: 76 | // How many items are on stack? 77 | unsigned count() const { return storage.size(); } 78 | 79 | // Get the top of the stack. 80 | Stack_Cell &top() { return storage.back(); } 81 | 82 | // Remove all items (but don't deallocate). 83 | void erase(unsigned ptr) { storage.erase(storage.begin() + ptr, storage.end()); } 84 | 85 | // Remove one item from stack, and return it as cell. 86 | Stack_Cell pop(); 87 | 88 | // Put an item on stack. 89 | void push(const Stack_Cell &item); 90 | void push(Cell_Type type, uint64_t value); 91 | 92 | // Remove one item from stack, and return it as standard floating point value. 93 | long double pop_ieee(); 94 | 95 | // Remove one item from stack, and return it as standard integer value. 96 | int pop_integer(); 97 | 98 | // Remove one item from stack, and return it as memory address. 99 | unsigned pop_addr(); 100 | 101 | // Remove one item from stack, and return it as standard boolean value. 102 | bool pop_boolean(); 103 | 104 | // Get item by index. 105 | Stack_Cell &get(unsigned index); 106 | const Stack_Cell &get(unsigned index) const; 107 | 108 | // Push any item on stack. 109 | 110 | // Push integer value in X1 format. 111 | void push_int_value(Word value) { push(Cell_Type::INTEGER_VALUE, value); } 112 | 113 | // Push address of integer. 114 | void push_int_addr(Word addr) { push(Cell_Type::INTEGER_ADDRESS, addr); } 115 | 116 | // Push real value in X1 format. 117 | void push_real_value(Real value) { push(Cell_Type::REAL_VALUE, value); } 118 | 119 | // Push address of real. 120 | void push_real_addr(Word addr) { push(Cell_Type::REAL_ADDRESS, addr); } 121 | 122 | // Push a standard floating point value. 123 | void push_ieee(long double value) { push(Cell_Type::REAL_VALUE, ieee_to_x1(value)); } 124 | 125 | // Push null item. 126 | void push_null() { push(Cell_Type::NUL, 0); } 127 | 128 | // Set item by index. 129 | void set(unsigned index, const Stack_Cell &item); 130 | void set_int_value(unsigned index, Word value) 131 | { 132 | set(index, { Cell_Type::INTEGER_VALUE, value }); 133 | } 134 | void set_int_addr(unsigned index, Word addr) 135 | { 136 | set(index, { Cell_Type::INTEGER_ADDRESS, addr }); 137 | } 138 | void set_real_value(unsigned index, Real value) 139 | { 140 | set(index, { Cell_Type::REAL_VALUE, value }); 141 | } 142 | void set_real_addr(unsigned index, Word addr) { set(index, { Cell_Type::REAL_ADDRESS, addr }); } 143 | void set_null(unsigned index) { set(index, { Cell_Type::NUL, 0 }); } 144 | 145 | // Arithmetic on top of stack 146 | void add(const Stack_Cell &another); 147 | void subtract(const Stack_Cell &another); 148 | void multiply(const Stack_Cell &another); 149 | void divide(const Stack_Cell &another); 150 | }; 151 | 152 | #endif // X1_VIRTUAL_STACK_H 153 | -------------------------------------------------------------------------------- /simulator/x1_arch.h: -------------------------------------------------------------------------------- 1 | #ifndef X1_ARCH_H 2 | #define X1_ARCH_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | // 9 | // Memory has 32768 words. 10 | // 11 | static const unsigned MEMORY_NWORDS = 32 * 1024; 12 | 13 | // 14 | // 27-bit memory word in lower bits of unsigned value. 15 | // 16 | using Word = uint32_t; 17 | 18 | // 19 | // Real values are represented by two 27-bit words. 20 | // We combine them into a single 54-bit value. 21 | // 22 | using Real = uint64_t; 23 | 24 | // 25 | // Array of words. 26 | // 27 | using Words = std::vector; 28 | 29 | // 30 | // Convert assembly source code into binary word. 31 | // 32 | Word x1_asm(const char *source); 33 | 34 | // 35 | // Get instruction mnemonics by opcode. 36 | // 37 | const char *x1_opname(unsigned opcode); 38 | 39 | // 40 | // Get instruction opcode by mnemonics (UTF-8). 41 | // 42 | bool x1_opcode(const char *opname, unsigned &opcode); 43 | 44 | // 45 | // Create real value from two words. 46 | // 47 | Real x1_words_to_real(Word hi, Word lo); 48 | 49 | // 50 | // Convert real value between IEEE and X1 formats. 51 | // 52 | Real ieee_to_x1(long double d); 53 | long double x1_to_ieee(Real word); 54 | 55 | // 56 | // Convert integer value between native and X1 formats. 57 | // 58 | Word integer_to_x1(int d); 59 | int x1_to_integer(Word word); 60 | 61 | // 62 | // Print X1 word. 63 | // 64 | void x1_print_word_octal(std::ostream &out, Word value); 65 | void x1_print_word_bytes(std::ostream &out, Word value); 66 | 67 | // 68 | // Print X1 instruction with mnemonics. 69 | // 70 | void x1_print_instruction(std::ostream &out, unsigned cmd); 71 | 72 | // 73 | // Convert numbers to strings. 74 | // 75 | std::string to_octal(unsigned val); 76 | 77 | // 78 | // Bits of memory word, from right to left, starting from 1. 79 | // 80 | #define ONEBIT(n) (1ULL << (n)) // one bit set, from 0 to 31 81 | #define BITS(n) (~0ULL >> (64 - n)) // bitmask of bits from 0 to n 82 | #define ADDR(x) ((x) & BITS(15)) // address of word 83 | 84 | // 85 | // Boolean constants. 86 | // 87 | enum { 88 | X1_TRUE = 0, 89 | X1_FALSE = 1, 90 | }; 91 | 92 | // 93 | // Negate a number. 94 | // 95 | Word x1_negate_int(Word value); 96 | Real x1_negate_real(Real value); 97 | 98 | // 99 | // Standard function: absolute value. 100 | // 101 | Word x1_abs_int(Word value); 102 | Real x1_abs_real(Real value); 103 | 104 | // 105 | // Print a number. 106 | // 107 | void x1_print_integer(std::ostream &out, Word value); 108 | void x1_print_real(std::ostream &out, Real value); 109 | 110 | #endif // X1_ARCH_H 111 | -------------------------------------------------------------------------------- /tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # 2 | # Common includes and libraries for all tests. 3 | # 4 | include_directories(BEFORE ../simulator) 5 | link_libraries(simulator gtest_main) 6 | add_definitions( 7 | -DBUILD_DIR="${CMAKE_BINARY_DIR}" 8 | -DTEST_DIR="${CMAKE_CURRENT_SOURCE_DIR}" 9 | ) 10 | 11 | # 12 | # Unit tests. 13 | # 14 | add_executable(x1test EXCLUDE_FROM_ALL 15 | fixture.cpp 16 | arch_test.cpp 17 | arith_test.cpp 18 | array_test.cpp 19 | boolean_test.cpp 20 | cli_test.cpp 21 | function_test.cpp 22 | loop_test.cpp 23 | machine_test.cpp 24 | procedure_test.cpp 25 | label_test.cpp 26 | print_test.cpp 27 | man_or_boy.cpp 28 | ) 29 | add_dependencies(x1test x1sim) 30 | gtest_discover_tests(x1test EXTRA_ARGS --gtest_repeat=1 PROPERTIES TIMEOUT 120) 31 | -------------------------------------------------------------------------------- /tests/arch_test.cpp: -------------------------------------------------------------------------------- 1 | #include "fixture.h" 2 | 3 | // 4 | // Conversion from X1 to IEEE floating point format. 5 | // 6 | TEST(arith, x1_to_ieee) 7 | { 8 | // clang-format off 9 | // 4-sign exponent 10 | // | ___mantissa_____ __ 11 | // |/ x \/ | 12 | EXPECT_EQ(x1_to_ieee(0'00'00'00000'00'00'00000ull), 0.0L); // 0.0 13 | EXPECT_EQ(x1_to_ieee(0'20'00'00000'00'00'04001ull), 1.0L); // 1.0 14 | EXPECT_EQ(x1_to_ieee(0'20'00'00000'00'00'14001ull), 0x8.000000001p-3L); // epsilon = 1.0000000000018 15 | #if __LDBL_MAX_EXP__ >= 2043 16 | EXPECT_EQ(x1_to_ieee(0'20'00'00000'00'00'00000ull), 0x8p-2052L); // minreal = 1.547173023691⏨-617 17 | EXPECT_EQ(x1_to_ieee(0'37'77'77777'37'77'77777ull), 0xf.fffffffffp+2043L); // maxreal = 1.615850303564⏨616 18 | #else 19 | FAIL() << "Exponent range of long double is too small"; 20 | #endif 21 | 22 | EXPECT_EQ(x1_to_ieee(0'77'77'77777'77'77'77777ull), -0.0L); // -0.0 23 | EXPECT_EQ(x1_to_ieee(0'57'77'77777'77'77'73776ull), -1.0L); // -1.0 24 | EXPECT_EQ(x1_to_ieee(0'57'77'77777'77'77'63776ull), -0x8.000000001p-3L); // -epsilon 25 | #if __LDBL_MAX_EXP__ >= 2043 26 | EXPECT_EQ(x1_to_ieee(0'57'77'77777'77'77'77777ull), -0x8p-2052L); // -minreal 27 | EXPECT_EQ(x1_to_ieee(0'40'00'00000'40'00'00000ull), -0xf.fffffffffp+2043L); // -maxreal 28 | #endif 29 | // clang-format on 30 | } 31 | 32 | // 33 | // Conversion from IEEE to X1 floating point format. 34 | // 35 | TEST(arith, ieee_to_x1) 36 | { 37 | // clang-format off 38 | // 4-sign exponent 39 | // | ___mantissa_____ __ 40 | // |/ x \/ | 41 | EXPECT_EQ(ieee_to_x1(0.0L), 0'00'00'00000'00'00'00000ull); // 0.0 42 | EXPECT_EQ(ieee_to_x1(1.0L), 0'20'00'00000'00'00'04001ull); // 1.0 43 | EXPECT_EQ(ieee_to_x1(0x8.000000001p-3L), 0'20'00'00000'00'00'14001ull); // epsilon = 1.0000000000018 44 | #if __LDBL_MAX_EXP__ >= 2043 45 | EXPECT_EQ(ieee_to_x1(0x8p-2052L), 0'20'00'00000'00'00'00000ull); // minreal = 1.547173023691⏨-617 46 | EXPECT_EQ(ieee_to_x1(0xf.fffffffffp+2043L), 0'37'77'77777'37'77'77777ull); // maxreal = 1.615850303564⏨616 47 | #else 48 | FAIL() << "Exponent range of long double is too small"; 49 | #endif 50 | 51 | EXPECT_EQ(ieee_to_x1(-0.0L), 0'77'77'77777'77'77'77777ull); // -0.0 52 | EXPECT_EQ(ieee_to_x1(-1.0L), 0'57'77'77777'77'77'73776ull); // -1.0 53 | EXPECT_EQ(ieee_to_x1(-0x8.000000001p-3L), 0'57'77'77777'77'77'63776ull); // -epsilon 54 | #if __LDBL_MAX_EXP__ >= 2043 55 | EXPECT_EQ(ieee_to_x1(-0x8p-2052L), 0'57'77'77777'77'77'77777ull); // -minreal 56 | EXPECT_EQ(ieee_to_x1(-0xf.fffffffffp+2043L), 0'40'00'00000'40'00'00000ull); // -maxreal 57 | #endif 58 | // clang-format on 59 | } 60 | 61 | #include 62 | 63 | TEST(arith, log10l) 64 | { 65 | // Positive numbers 66 | EXPECT_FLOAT_EQ(log10l(1e111L), 111.0L); 67 | #if __LDBL_MAX_10_EXP__ >= 555 68 | EXPECT_FLOAT_EQ(log10l(1e444L), 444.0L); 69 | EXPECT_FLOAT_EQ(log10l(1e555L), 555.0L); 70 | #else 71 | FAIL() << "Exponent range of long double is too small"; 72 | #endif 73 | EXPECT_FLOAT_EQ(log10l(1e-222L), -222.0L); 74 | #if __LDBL_MIN_10_EXP__ <= -777 75 | EXPECT_FLOAT_EQ(log10l(1e-666L), -666.0L); 76 | EXPECT_FLOAT_EQ(log10l(1e-777L), -777.0L); 77 | #endif 78 | 79 | // Zero 80 | // cppcheck-suppress invalidFunctionArg 81 | // cppcheck-suppress wrongmathcall 82 | EXPECT_FLOAT_EQ(log10l(0.0), - std::numeric_limits::infinity()); 83 | 84 | // Negative numbers 85 | // cppcheck-suppress invalidFunctionArg 86 | // cppcheck-suppress wrongmathcall 87 | EXPECT_TRUE(std::isnan(log10l(-1.0L))); 88 | #if __LDBL_MAX_10_EXP__ >= 888 89 | EXPECT_TRUE(std::isnan(log10l(-1e888L))); 90 | #endif 91 | #if __LDBL_MIN_10_EXP__ <= -999 92 | EXPECT_TRUE(std::isnan(log10l(-1e-999L))); 93 | #endif 94 | } 95 | -------------------------------------------------------------------------------- /tests/arith_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "fixture.h" 4 | 5 | TEST_F(x1_machine, arith_add) 6 | { 7 | auto output = compile_and_run(R"( 8 | b̲e̲g̲i̲n̲ 9 | print(3 + 4); NLCR; 10 | print(3.25 + 4); NLCR; 11 | print(3 + 4.625); NLCR; 12 | print(3.25 + 4.625); NLCR; 13 | e̲n̲d̲ 14 | )"); 15 | const std::string expect = R"(7 16 | 7.25 17 | 7.625 18 | 7.875 19 | )"; 20 | EXPECT_EQ(output, expect); 21 | } 22 | 23 | TEST_F(x1_machine, arith_subtract) 24 | { 25 | auto output = compile_and_run(R"( 26 | b̲e̲g̲i̲n̲ 27 | print(3 - 4); NLCR; 28 | print(3.25 - 4); NLCR; 29 | print(3 - 4.625); NLCR; 30 | print(3.25 - 4.625); NLCR; 31 | e̲n̲d̲ 32 | )"); 33 | const std::string expect = R"(-1 34 | -0.75 35 | -1.625 36 | -1.375 37 | )"; 38 | EXPECT_EQ(output, expect); 39 | } 40 | 41 | TEST_F(x1_machine, arith_multiply_constants) 42 | { 43 | auto output = compile_and_run(R"( 44 | b̲e̲g̲i̲n̲ 45 | print(3 × 4); NLCR; 46 | print(3.125 × 4); NLCR; 47 | print(3 × 4.625); NLCR; 48 | print(3.25 × 4.625); NLCR; 49 | e̲n̲d̲ 50 | )"); 51 | const std::string expect = R"(12 52 | 12.5 53 | 13.875 54 | 15.03125 55 | )"; 56 | EXPECT_EQ(output, expect); 57 | } 58 | 59 | TEST_F(x1_machine, arith_multiply_args) 60 | { 61 | auto output = compile_and_run(R"( 62 | b̲e̲g̲i̲n̲ 63 | r̲e̲a̲l̲ p̲r̲o̲c̲e̲d̲u̲r̲e̲ mul(a, b); 64 | v̲a̲l̲u̲e̲ a, b; 65 | r̲e̲a̲l̲ a, b; 66 | b̲e̲g̲i̲n̲ 67 | mul := a × b; 68 | e̲n̲d̲; 69 | print(mul(3, 4)); NLCR; 70 | print(mul(3.125, -4)); NLCR; 71 | print(mul(3, 4.625)); NLCR; 72 | print(mul(3.25, -4.625)); NLCR; 73 | e̲n̲d̲ 74 | )"); 75 | const std::string expect = R"(12 76 | -12.5 77 | 13.875 78 | -15.03125 79 | )"; 80 | EXPECT_EQ(output, expect); 81 | } 82 | 83 | TEST_F(x1_machine, arith_real_divide) 84 | { 85 | auto output = compile_and_run(R"( 86 | b̲e̲g̲i̲n̲ 87 | print(3 / 4); NLCR; 88 | print(3.125 / 4); NLCR; 89 | print(3 / 4.5); NLCR; 90 | print(3.25 / 4.5); NLCR; 91 | e̲n̲d̲ 92 | )"); 93 | const std::string expect = R"(0.75 94 | 0.78125 95 | 0.666666666667 96 | 0.7222222222226 97 | )"; 98 | EXPECT_EQ(output, expect); 99 | } 100 | 101 | TEST_F(x1_machine, arith_integer_divide) 102 | { 103 | auto output = compile_and_run(R"( 104 | b̲e̲g̲i̲n̲ 105 | print(13 ÷ 4); NLCR; 106 | print(-13 ÷ 4); NLCR; 107 | print(13 ÷ (-4)); NLCR; 108 | print(-13 ÷ (-4)); NLCR; 109 | e̲n̲d̲ 110 | )"); 111 | // Note that this fails: print(13 ÷ -4); 112 | 113 | const std::string expect = R"(3 114 | -3 115 | -3 116 | 3 117 | )"; 118 | EXPECT_EQ(output, expect); 119 | } 120 | 121 | TEST_F(x1_machine, arith_exponent) 122 | { 123 | auto output = compile_and_run(R"( 124 | b̲e̲g̲i̲n̲ 125 | print(3 ↑ 4); NLCR; 126 | print((-2.5) ↑ (-4)); NLCR; 127 | print(3 ↑ 4.625); NLCR; 128 | print(2.5 ↑ (-4.625)); NLCR; 129 | e̲n̲d̲ 130 | )"); 131 | const std::string expect = R"(81 132 | 0.0256 133 | 160.9480810601 134 | 0.01443867895348 135 | )"; 136 | EXPECT_EQ(output, expect); 137 | } 138 | 139 | TEST_F(x1_machine, arith_if_clause) 140 | { 141 | auto output = compile_and_run(R"( 142 | b̲e̲g̲i̲n̲ 143 | print(i̲f̲ t̲r̲u̲e̲ t̲h̲e̲n̲ 1.5 e̲l̲s̲e̲ 2); NLCR; 144 | print(i̲f̲ f̲a̲l̲s̲e̲ t̲h̲e̲n̲ 3.5 e̲l̲s̲e̲ 4); NLCR; 145 | print(i̲f̲ t̲r̲u̲e̲ t̲h̲e̲n̲ 5 e̲l̲s̲e̲ 6.5); NLCR; 146 | print(i̲f̲ f̲a̲l̲s̲e̲ t̲h̲e̲n̲ 7 e̲l̲s̲e̲ 8.5); NLCR; 147 | e̲n̲d̲ 148 | )"); 149 | const std::string expect = R"(1.5 150 | 4 151 | 5 152 | 8.5 153 | )"; 154 | EXPECT_EQ(output, expect); 155 | } 156 | 157 | TEST_F(x1_machine, variables) 158 | { 159 | auto output = compile_and_run(R"( 160 | b̲e̲g̲i̲n̲ i̲n̲t̲e̲g̲e̲r̲ i; r̲e̲a̲l̲ r; 161 | i := 1; r := 1.1; i := i + 10; r := r + 10.01; 162 | print(i, r); NLCR; 163 | r := i; print(r); NLCR; 164 | i := 3.14159; print(i); NLCR; 165 | i := 2.71828; print(i); NLCR; 166 | e̲n̲d̲ 167 | )"); 168 | const std::string expect = R"(11 11.11 169 | 11 170 | 3 171 | 3 172 | )"; 173 | EXPECT_EQ(output, expect); 174 | } 175 | 176 | TEST_F(x1_machine, dynamic_arith) 177 | { 178 | auto output = compile_and_run(R"( 179 | b̲e̲g̲i̲n̲ b̲e̲g̲i̲n̲ i̲n̲t̲e̲g̲e̲r̲ i; r̲e̲a̲l̲ r; 180 | i := 1; 181 | i := 10 - i; 182 | i := 1 + i; 183 | i := 95 / i; 184 | i := 5 * i; 185 | r := 1.5; 186 | r := 10.5 - r; 187 | r := 1.5 + r; 188 | r := 94.5 / r; 189 | r := 5.5 * r; 190 | print(i, r); NLCR; 191 | e̲n̲d̲ e̲n̲d̲ 192 | )"); 193 | const std::string expect = R"(50 49.5 194 | )"; 195 | EXPECT_EQ(output, expect); 196 | } 197 | 198 | TEST_F(x1_machine, multiply_large_ints) 199 | { 200 | auto output = compile_and_run(R"( 201 | b̲e̲g̲i̲n̲ 202 | print(1048579 * 1048579); NLCR; 203 | e̲n̲d̲ 204 | )"); 205 | // Note: result differs from 1048579^2 = 1099517919241. 206 | const std::string expect = "1099517919242\n"; 207 | EXPECT_EQ(output, expect); 208 | } 209 | -------------------------------------------------------------------------------- /tests/array_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "fixture.h" 4 | 5 | TEST_F(x1_machine, array_single_dim) 6 | { 7 | auto output = compile_and_run(R"( 8 | b̲e̲g̲i̲n̲ 9 | r̲e̲a̲l̲ a̲r̲r̲a̲y̲ a[1:10]; 10 | a[1] := 1; 11 | a[10] := a[1] + 9; 12 | print(a[1]); NLCR; 13 | print(a[10]); NLCR; 14 | e̲n̲d̲ 15 | )"); 16 | const std::string expect = R"(1 17 | 10 18 | )"; 19 | EXPECT_EQ(output, expect); 20 | } 21 | 22 | TEST_F(x1_machine, array_multi_dim) 23 | { 24 | auto output = compile_and_run(R"( 25 | b̲e̲g̲i̲n̲ 26 | i̲n̲t̲e̲g̲e̲r̲ a̲r̲r̲a̲y̲ a[1:10,2:9,3:8,4:7]; 27 | a[1,2,3,4] := 1234; 28 | a[10,9,8,7] := a[1,2,3,4] + 5678; 29 | print(a[1,2,3,4]); NLCR; 30 | print(a[10,9,8,7]); NLCR; 31 | e̲n̲d̲ 32 | )"); 33 | const std::string expect = R"(1234 34 | 6912 35 | )"; 36 | EXPECT_EQ(output, expect); 37 | } 38 | 39 | TEST_F(x1_machine, array_negative_bound) 40 | { 41 | auto output = compile_and_run(R"( 42 | b̲e̲g̲i̲n̲ 43 | i̲n̲t̲e̲g̲e̲r̲ a̲r̲r̲a̲y̲ a[-1:1,-1:1]; 44 | a[0,0] := 1234; 45 | a[-1,1] := a[1,-1] := 5678; 46 | print(a[-1,1], a[0,0], a[1,-1]); NLCR; 47 | print(a[-6,2]); NLCR; 48 | e̲n̲d̲ 49 | )"); 50 | const std::string expect = R"(5678 1234 5678 51 | 1234 52 | )"; 53 | EXPECT_EQ(output, expect); 54 | } 55 | 56 | TEST_F(x1_machine, array_local_real) 57 | { 58 | auto output = compile_and_run(R"( 59 | _b_e_g_i_n _i_n_t i; 60 | _b_e_g_i_n _i_n_t a; 61 | _r_e_a_l _a_r_r_a_y b[-1:11]; 62 | _i_n_t z; 63 | a := 12345; 64 | z := 54321; 65 | b[-1] := -1.5; 66 | b[11] := 11.25; 67 | print(a); NLCR; 68 | print(z); NLCR; 69 | i := -1; 70 | loop: _i_f i < 12 _t_h_e_n _b_e_g_i_n 71 | print(b[i]); NLCR; 72 | i := i + 4; 73 | _g_o_t_o loop 74 | _e_n_d 75 | _e_n_d 76 | _e_n_d 77 | )"); 78 | const std::string expect = R"(12345 79 | 54321 80 | -1.5 81 | 0 82 | 0 83 | 11.25 84 | )"; 85 | EXPECT_EQ(output, expect); 86 | } 87 | 88 | TEST_F(x1_machine, value_array_real) 89 | { 90 | auto output = compile_and_run(R"( 91 | _b_e_g_i_n _r_e_a_l _a_r_r_a_y a[7:8]; 92 | _p_r_o_c_e_d_u_r_e p(x); 93 | _v_a_l_u_e x; _a_r_r_a_y x; 94 | _b_e_g_i_n 95 | print(x[7], x[8]); NLCR; 96 | x[8] := -1; 97 | _e_n_d; 98 | a[7] := 7.75; a[8] := 8.875; 99 | p(a); print(a[8]); NLCR; 100 | _b_e_g_i_n 101 | _r_e_a_l _a_r_r_a_y b[1:10]; 102 | b[7] := -7.5; b[8] := -8.25; 103 | p(b); print(b[8]); NLCR; 104 | _e_n_d 105 | _e_n_d 106 | )"); 107 | const std::string expect = R"(7.75 8.875 108 | 8.875 109 | -7.5 -8.25 110 | -8.25 111 | )"; 112 | EXPECT_EQ(output, expect); 113 | } 114 | 115 | TEST_F(x1_machine, value_array_integer) 116 | { 117 | auto output = compile_and_run(R"( 118 | _b_e_g_i_n _i_n_t_e_g_e_r _a_r_r_a_y a[7:8]; 119 | _p_r_o_c_e_d_u_r_e p(x); 120 | _v_a_l_u_e x; _i_n_t_e_g_e_r _a_r_r_a_y x; 121 | _b_e_g_i_n 122 | print(x[7], x[8]); NLCR; 123 | x[8] := -1; 124 | _e_n_d; 125 | a[7] := 7; a[8] := 8; 126 | p(a); print(a[8]); NLCR; 127 | _b_e_g_i_n 128 | _i_n_t_e_g_e_r _a_r_r_a_y b[1:10]; 129 | b[7] := -7; b[8] := -8; 130 | p(b); print(b[8]); NLCR; 131 | _e_n_d 132 | _e_n_d 133 | )"); 134 | const std::string expect = R"(7 8 135 | 8 136 | -7 -8 137 | -8 138 | )"; 139 | EXPECT_EQ(output, expect); 140 | } 141 | 142 | TEST_F(x1_machine, value_array_multidim_conv) 143 | { 144 | auto output = compile_and_run(R"( 145 | _b_e_g_i_n 146 | _r_e_a_l _a_r_r_a_y r[1:3,3:6]; 147 | _i_n_t_e_g_e_r _a_r_r_a_y i[2:3,3:5]; 148 | _p_r_o_c asint(x); _v_a_l_u_e x; _i_n_t_e_g_e_r _a_r_r_a_y x; 149 | print(x[3,3]); 150 | _p_r_o_c asreal(x); _v_a_l_u_e x; _r_e_a_l _a_r_r_a_y x; 151 | print(x[3,3]/2); 152 | r[3,3] := 2.75; 153 | i[3,3] := 275; 154 | asint(i); NLCR; 155 | asreal(r); NLCR; 156 | asint(r); NLCR; 157 | asreal(i); NLCR; 158 | _e_n_d 159 | )"); 160 | const std::string expect = R"(275 161 | 1.375 162 | 3 163 | 137.5 164 | )"; 165 | EXPECT_EQ(output, expect); 166 | } 167 | -------------------------------------------------------------------------------- /tests/boolean_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "fixture.h" 4 | 5 | TEST_F(x1_machine, boolean_operations) 6 | { 7 | auto output = compile_and_run(R"( 8 | b̲e̲g̲i̲n̲ 9 | print(f̲a̲l̲s̲e̲); NLCR; 10 | print(t̲r̲u̲e̲); NLCR; 11 | NLCR; 12 | print(¬ f̲a̲l̲s̲e̲); NLCR; 13 | print(¬ t̲r̲u̲e̲); NLCR; 14 | NLCR; 15 | print(f̲a̲l̲s̲e̲ ∧ f̲a̲l̲s̲e̲); NLCR; 16 | print(f̲a̲l̲s̲e̲ ∧ t̲r̲u̲e̲); NLCR; 17 | print(t̲r̲u̲e̲ ∧ f̲a̲l̲s̲e̲); NLCR; 18 | print(t̲r̲u̲e̲ ∧ t̲r̲u̲e̲); NLCR; 19 | NLCR; 20 | print(f̲a̲l̲s̲e̲ ∨ f̲a̲l̲s̲e̲); NLCR; 21 | print(f̲a̲l̲s̲e̲ ∨ t̲r̲u̲e̲); NLCR; 22 | print(t̲r̲u̲e̲ ∨ f̲a̲l̲s̲e̲); NLCR; 23 | print(t̲r̲u̲e̲ ∨ t̲r̲u̲e̲); NLCR; 24 | NLCR; 25 | print(f̲a̲l̲s̲e̲ ⊃ f̲a̲l̲s̲e̲); NLCR; 26 | print(f̲a̲l̲s̲e̲ ⊃ t̲r̲u̲e̲); NLCR; 27 | print(t̲r̲u̲e̲ ⊃ f̲a̲l̲s̲e̲); NLCR; 28 | print(t̲r̲u̲e̲ ⊃ t̲r̲u̲e̲); NLCR; 29 | NLCR; 30 | print(f̲a̲l̲s̲e̲ ≡ f̲a̲l̲s̲e̲); NLCR; 31 | print(f̲a̲l̲s̲e̲ ≡ t̲r̲u̲e̲); NLCR; 32 | print(t̲r̲u̲e̲ ≡ f̲a̲l̲s̲e̲); NLCR; 33 | print(t̲r̲u̲e̲ ≡ t̲r̲u̲e̲); NLCR; 34 | e̲n̲d̲ 35 | )"); 36 | const std::string expect = R"(1 37 | 0 38 | 39 | 0 40 | 1 41 | 42 | 1 43 | 1 44 | 1 45 | 0 46 | 47 | 1 48 | 0 49 | 0 50 | 0 51 | 52 | 0 53 | 0 54 | 1 55 | 0 56 | 57 | 0 58 | 1 59 | 1 60 | 0 61 | )"; 62 | EXPECT_EQ(output, expect); 63 | } 64 | 65 | TEST_F(x1_machine, relations) 66 | { 67 | auto output = compile_and_run(R"( 68 | b̲e̲g̲i̲n̲ 69 | print(3 < 3.14); NLCR; 70 | print(3 < 3); NLCR; 71 | print(3.14 < 3); NLCR; 72 | print(3.14 < 3.14); NLCR; 73 | NLCR; 74 | print(3 ≤ 3.14); NLCR; 75 | print(3 ≤ 3); NLCR; 76 | print(3.14 ≤ 3); NLCR; 77 | print(3.14 ≤ 3.14); NLCR; 78 | NLCR; 79 | print(3 = 3.14); NLCR; 80 | print(3 = 3); NLCR; 81 | print(3.14 = 3); NLCR; 82 | print(3.14 = 3.14); NLCR; 83 | NLCR; 84 | print(3 ≥ 3.14); NLCR; 85 | print(3 ≥ 3); NLCR; 86 | print(3.14 ≥ 3); NLCR; 87 | print(3.14 ≥ 3.14); NLCR; 88 | NLCR; 89 | print(3 > 3.14); NLCR; 90 | print(3 > 3); NLCR; 91 | print(3.14 > 3); NLCR; 92 | print(3.14 > 3.14); NLCR; 93 | NLCR; 94 | print(3 ≠ 3.14); NLCR; 95 | print(3 ≠ 3); NLCR; 96 | print(3.14 ≠ 3); NLCR; 97 | print(3.14 ≠ 3.14); NLCR; 98 | e̲n̲d̲ 99 | )"); 100 | const std::string expect = R"(0 101 | 1 102 | 1 103 | 1 104 | 105 | 0 106 | 0 107 | 1 108 | 0 109 | 110 | 1 111 | 0 112 | 1 113 | 0 114 | 115 | 1 116 | 0 117 | 0 118 | 0 119 | 120 | 1 121 | 1 122 | 0 123 | 1 124 | 125 | 0 126 | 1 127 | 0 128 | 1 129 | )"; 130 | EXPECT_EQ(output, expect); 131 | } 132 | -------------------------------------------------------------------------------- /tests/cli_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "fixture.h" 6 | 7 | static void run_command(std::string &result, const std::string &cmd) 8 | { 9 | // Run simulator via shell. 10 | setenv("PATH", "../compiler", 1); 11 | FILE *pipe = popen(cmd.c_str(), "r"); 12 | ASSERT_TRUE(pipe != nullptr); 13 | 14 | // Capture output. 15 | result = stream_contents(pipe); 16 | std::cout << result; 17 | 18 | // Check exit code. 19 | int exit_status = pclose(pipe); 20 | int exit_code = WEXITSTATUS(exit_status); 21 | ASSERT_NE(exit_status, -1); 22 | ASSERT_EQ(exit_code, 0); 23 | } 24 | 25 | TEST(cli, usage) 26 | { 27 | std::string result; 28 | run_command(result, "../simulator/x1sim --help"); 29 | 30 | // Check output. 31 | EXPECT_NE(result.find("Version"), std::string::npos); 32 | EXPECT_NE(result.find("Usage:"), std::string::npos); 33 | EXPECT_NE(result.find("Options:"), std::string::npos); 34 | } 35 | 36 | TEST(cli, version) 37 | { 38 | std::string result; 39 | run_command(result, "../simulator/x1sim --version"); 40 | 41 | // Check output. 42 | EXPECT_NE(result.find("Version"), std::string::npos); 43 | EXPECT_NE(result.find("."), std::string::npos); 44 | EXPECT_NE(result.find("-"), std::string::npos); 45 | } 46 | 47 | TEST(cli, print123_a60) 48 | { 49 | std::string result; 50 | run_command(result, "../simulator/x1sim " TEST_DIR "/print123.a60"); 51 | 52 | EXPECT_EQ(result, "123\n"); 53 | } 54 | 55 | TEST(cli, print123_x1) 56 | { 57 | std::string result; 58 | run_command(result, "../simulator/x1sim " TEST_DIR "/print123.x1"); 59 | 60 | EXPECT_EQ(result, "123\n"); 61 | } 62 | 63 | TEST(cli, lib_sum) 64 | { 65 | std::string result; 66 | run_command(result, "../simulator/x1sim " TEST_DIR "/../examples/sum.a60 " TEST_DIR "/../library/sum.lib"); 67 | 68 | // This example shoult print 55*20 = 1100. 69 | EXPECT_EQ(result, "1100\n"); 70 | } 71 | -------------------------------------------------------------------------------- /tests/fixture.cpp: -------------------------------------------------------------------------------- 1 | #include "fixture.h" 2 | 3 | #include 4 | #include 5 | 6 | // 7 | // Compile Algol sources and store binaries in memory. 8 | // 9 | void x1_machine::compile(const std::string &source_code) 10 | { 11 | const auto algol_filename = test_name + ".a60"; 12 | const auto obj_filename = test_name + ".x1"; 13 | 14 | create_file(algol_filename, source_code); 15 | 16 | machine->compile(std::vector(1, algol_filename), obj_filename); 17 | machine->load_object_program(obj_filename); 18 | } 19 | 20 | // 21 | // Compile and run Algol code. 22 | // Return captured output. 23 | // 24 | std::string x1_machine::compile_and_run(const std::string &source_code) 25 | { 26 | compile(source_code); 27 | 28 | // Redirect stdout. 29 | std::streambuf *save_cout = std::cout.rdbuf(); 30 | std::ostringstream output; 31 | std::cout.rdbuf(output.rdbuf()); 32 | 33 | // Run the program. 34 | EXPECT_NO_THROW(machine->run(machine->get_entry(0))); 35 | 36 | // Return output. 37 | std::cout.rdbuf(save_cout); 38 | return output.str(); 39 | } 40 | 41 | // 42 | // Read file contents and return it as a string. 43 | // 44 | std::string file_contents(const std::string &filename) 45 | { 46 | std::ifstream input(filename); 47 | if (!input.is_open()) { 48 | std::cerr << filename << ": " << std::strerror(errno) << std::endl; 49 | return ""; 50 | } 51 | std::stringstream contents; 52 | contents << input.rdbuf(); 53 | return contents.str(); 54 | } 55 | 56 | // 57 | // Read file contents as vector of strings. 58 | // 59 | std::vector split_stream(std::istream &input) 60 | { 61 | std::vector output; 62 | std::string line; 63 | while (std::getline(input, line)) { 64 | output.push_back(line); 65 | } 66 | return output; 67 | } 68 | 69 | // 70 | // Read file contents as vector of strings. 71 | // 72 | std::vector file_contents_split(const std::string &filename) 73 | { 74 | std::ifstream input(filename); 75 | return split_stream(input); 76 | } 77 | 78 | // 79 | // Read file contents as vector of strings. 80 | // 81 | std::vector multiline_split(const std::string &multiline) 82 | { 83 | std::stringstream input(multiline); 84 | return split_stream(input); 85 | } 86 | 87 | // 88 | // Read FILE* stream contents until EOF and return it as a string. 89 | // 90 | std::string stream_contents(FILE *input) 91 | { 92 | std::stringstream contents; 93 | char line[256]; 94 | while (fgets(line, sizeof(line), input)) { 95 | contents << line; 96 | } 97 | return contents.str(); 98 | } 99 | 100 | // 101 | // Create file with given contents. 102 | // 103 | void create_file(const std::string &filename, const std::string &contents) 104 | { 105 | std::ofstream output(filename); 106 | output << contents; 107 | } 108 | 109 | // 110 | // Create file with given contents. 111 | // 112 | void create_file(const std::string &dest_filename, const std::string &prolog, 113 | const std::string &src_filename, const std::string &epilog) 114 | { 115 | std::ofstream output(dest_filename); 116 | EXPECT_TRUE(output.is_open()) << dest_filename; 117 | 118 | std::ifstream input(src_filename); 119 | EXPECT_TRUE(input.is_open()) << src_filename; 120 | 121 | output << prolog; 122 | output << input.rdbuf(); 123 | output << epilog; 124 | } 125 | 126 | // 127 | // Check whether string starts with given prefix. 128 | // 129 | bool starts_with(const std::string &str, const char *prefix) 130 | { 131 | auto prefix_size = strlen(prefix); 132 | return str.size() >= prefix_size && memcmp(str.c_str(), prefix, prefix_size) == 0; 133 | } 134 | 135 | // 136 | // Compare output of simulation. 137 | // Ignore footer. 138 | // 139 | void check_output(const std::string &output_str, const std::string &expect_str) 140 | { 141 | std::stringstream output(output_str); 142 | std::stringstream expect(expect_str); 143 | 144 | // Compare line by line. 145 | for (unsigned lineno = 1; expect.good(); lineno++) { 146 | ASSERT_TRUE(output.good()) << "Output is too short"; 147 | 148 | std::string output_line; 149 | getline(output, output_line); 150 | if (output_line == "------------------------------------------------------------") 151 | break; 152 | 153 | // Remove trailing spaces. 154 | output_line.resize(1 + output_line.find_last_not_of(' ')); 155 | 156 | std::string expect_line; 157 | getline(expect, expect_line); 158 | EXPECT_EQ(output_line, expect_line) 159 | << "line #" << lineno; 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /tests/fixture.h: -------------------------------------------------------------------------------- 1 | #ifndef X1_TESTS_UTIL_H 2 | #define X1_TESTS_UTIL_H 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | #include "x1_arch.h" 10 | #include "machine.h" 11 | 12 | // 13 | // Fixture with preallocated machine. 14 | // 15 | // For details, see: https://github.com/google/googletest/blob/main/docs/primer.md 16 | // 17 | class x1_machine : public ::testing::Test { 18 | protected: 19 | std::unique_ptr machine; 20 | 21 | // Name of current test, as specified in TEST() macro. 22 | const std::string test_name{ ::testing::UnitTest::GetInstance()->current_test_info()->name() }; 23 | 24 | void SetUp() override 25 | { 26 | // Allocate fresh new machine. 27 | machine = std::make_unique(); 28 | 29 | // Select compiler 30 | machine->set_compiler(BUILD_DIR "/compiler/x1algc"); 31 | machine->set_default_library(TEST_DIR "/../library/x1algol.lib"); 32 | } 33 | 34 | // Compile Algol sources and store binaries in memory. 35 | void compile(const std::string &source_code); 36 | 37 | // Compile and run Algol code. 38 | // Return captured output. 39 | std::string compile_and_run(const std::string &input); 40 | }; 41 | 42 | // 43 | // Read file contents and return it as a string. 44 | // 45 | std::string file_contents(const std::string &filename); 46 | 47 | // 48 | // Read file contents as vector of strings. 49 | // 50 | std::vector file_contents_split(const std::string &filename); 51 | 52 | // 53 | // Split multi-line text as vector of strings. 54 | // 55 | std::vector multiline_split(const std::string &multiline); 56 | 57 | // 58 | // Read FILE* stream contents and return it as a string. 59 | // 60 | std::string stream_contents(FILE *input); 61 | 62 | // 63 | // Create file with given contents. 64 | // 65 | void create_file(const std::string &filename, const std::string &contents); 66 | void create_file(const std::string &dest_filename, const std::string &prolog, 67 | const std::string &src_filename, const std::string &epilog); 68 | 69 | // 70 | // Check whether string starts with given prefix. 71 | // 72 | bool starts_with(const std::string &str, const char *prefix); 73 | 74 | // 75 | // Compare output of simulation. 76 | // Ignore footer. 77 | // 78 | void check_output(const std::string &output_str, const std::string &expect_str); 79 | 80 | #endif // X1_TESTS_UTIL_H 81 | -------------------------------------------------------------------------------- /tests/function_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "fixture.h" 4 | 5 | TEST_F(x1_machine, function_abs) 6 | { 7 | auto output = compile_and_run(R"( 8 | b̲e̲g̲i̲n̲ 9 | print(abs(-123.456)); NLCR; 10 | print(abs(123.456)); NLCR; 11 | print(abs(-1.615850303564⏨616)); NLCR; 12 | print(abs(1.615850303564⏨616)); NLCR; 13 | print(abs(-0.0)); NLCR; 14 | print(abs(0.0)); NLCR; 15 | print(abs(-67108863)); NLCR; 16 | print(abs(67108863)); NLCR; 17 | print(abs(-0)); NLCR; 18 | print(abs(0)); NLCR; 19 | e̲n̲d̲ 20 | )"); 21 | const std::string expect = R"(123.456 22 | 123.456 23 | 1.615850303564e+616 24 | 1.615850303564e+616 25 | 0 26 | 0 27 | 67108863 28 | 67108863 29 | 0 30 | 0 31 | )"; 32 | EXPECT_EQ(output, expect); 33 | } 34 | 35 | TEST_F(x1_machine, function_sign) 36 | { 37 | auto output = compile_and_run(R"( 38 | b̲e̲g̲i̲n̲ 39 | print(sign(-123.456)); NLCR; 40 | print(sign(123.456)); NLCR; 41 | print(sign(-1.615850303564⏨616)); NLCR; 42 | print(sign(1.615850303564⏨616)); NLCR; 43 | print(sign(-0.0)); NLCR; 44 | print(sign(0.0)); NLCR; 45 | print(sign(-1)); NLCR; 46 | print(sign(1)); NLCR; 47 | print(sign(-67108863)); NLCR; 48 | print(sign(67108863)); NLCR; 49 | print(sign(-0)); NLCR; 50 | print(sign(0)); NLCR; 51 | e̲n̲d̲ 52 | )"); 53 | const std::string expect = R"(-1 54 | 1 55 | -1 56 | 1 57 | 0 58 | 0 59 | -1 60 | 1 61 | -1 62 | 1 63 | 0 64 | 0 65 | )"; 66 | EXPECT_EQ(output, expect); 67 | } 68 | 69 | TEST_F(x1_machine, function_sqrt) 70 | { 71 | auto output = compile_and_run(R"( 72 | b̲e̲g̲i̲n̲ 73 | print(sqrt(2)); NLCR; 74 | print(sqrt(99999)); NLCR; 75 | print(sqrt(1.01)); NLCR; 76 | print(sqrt(0.99)); NLCR; 77 | print(sqrt(0.0003)); NLCR; 78 | e̲n̲d̲ 79 | )"); 80 | const std::string expect = R"(1.414213562373 81 | 316.2261848738 82 | 1.004987562112 83 | 0.9949874371068 84 | 0.0173205080757 85 | )"; 86 | EXPECT_EQ(output, expect); 87 | } 88 | 89 | TEST_F(x1_machine, function_sin) 90 | { 91 | auto output = compile_and_run(R"( 92 | b̲e̲g̲i̲n̲ 93 | print(sin(0.0001)); NLCR; 94 | print(sin(-0.0001)); NLCR; 95 | print(sin(0.7854)); NLCR; 96 | print(sin(-0.7854)); NLCR; 97 | print(sin(1.5)); NLCR; 98 | print(sin(-1.6)); NLCR; 99 | print(sin(3141.6)); NLCR; 100 | print(sin(-3141.6)); NLCR; 101 | e̲n̲d̲ 102 | )"); 103 | const std::string expect = R"(9.999999983334e-05 104 | -9.999999983334e-05 105 | 0.7071080798596 106 | -0.7071080798596 107 | 0.9974949866037 108 | -0.9995736030414 109 | 0.007346345616369 110 | -0.007346345616369 111 | )"; 112 | EXPECT_EQ(output, expect); 113 | } 114 | 115 | TEST_F(x1_machine, function_cos) 116 | { 117 | auto output = compile_and_run(R"( 118 | b̲e̲g̲i̲n̲ 119 | print(cos(0.01)); NLCR; 120 | print(cos(-0.01)); NLCR; 121 | print(cos(0.7854)); NLCR; 122 | print(cos(-0.7854)); NLCR; 123 | print(cos(1.5)); NLCR; 124 | print(cos(-1.6)); NLCR; 125 | print(cos(3141.6)); NLCR; 126 | print(cos(-3141.6)); NLCR; 127 | e̲n̲d̲ 128 | )"); 129 | const std::string expect = R"(0.9999500004169 130 | 0.9999500004169 131 | 0.707105482511 132 | 0.707105482511 133 | 0.07073720166773 134 | -0.02919952230164 135 | 0.9999730152385 136 | 0.9999730152385 137 | )"; 138 | EXPECT_EQ(output, expect); 139 | } 140 | 141 | // 142 | // Cannot compile this program: it wants a library tape. 143 | // "Need MCP 3" 144 | // "Need MCP 4" 145 | // 146 | TEST_F(x1_machine, function_arctan) 147 | { 148 | auto output = compile_and_run(R"( 149 | b̲e̲g̲i̲n̲ 150 | print(arctan(0.0001)); NLCR; 151 | print(arctan(-0.0001)); NLCR; 152 | print(arctan(0.5)); NLCR; 153 | print(arctan(-0.5)); NLCR; 154 | print(arctan(2)); NLCR; 155 | print(arctan(-2)); NLCR; 156 | print(arctan(999.9)); NLCR; 157 | print(arctan(-999.9)); NLCR; 158 | e̲n̲d̲ 159 | )"); 160 | const std::string expect = R"(9.99999996667e-05 161 | -9.99999996667e-05 162 | 0.4636476090009 163 | -0.4636476090009 164 | 1.107148717794 165 | -1.107148717794 166 | 1.569796227119 167 | -1.569796227119 168 | )"; 169 | EXPECT_EQ(output, expect); 170 | } 171 | 172 | TEST_F(x1_machine, function_ln) 173 | { 174 | auto output = compile_and_run(R"( 175 | b̲e̲g̲i̲n̲ 176 | print(ln(0.0001)); NLCR; 177 | print(ln(0.5)); NLCR; 178 | print(ln(0.9999)); NLCR; 179 | print(ln(1.0001)); NLCR; 180 | print(ln(2)); NLCR; 181 | print(ln(4)); NLCR; 182 | print(ln(8)); NLCR; 183 | print(ln(99999)); NLCR; 184 | e̲n̲d̲ 185 | )"); 186 | const std::string expect = R"(-9.210340371981 187 | -0.6931471805601 188 | -0.0001000050005356 189 | 9.999499962621e-05 190 | 0.6931471805601 191 | 1.38629436112 192 | 2.079441541679 193 | 11.51291546492 194 | )"; 195 | EXPECT_EQ(output, expect); 196 | } 197 | 198 | TEST_F(x1_machine, function_exp) 199 | { 200 | auto output = compile_and_run(R"( 201 | b̲e̲g̲i̲n̲ 202 | print(exp(-6)); NLCR; 203 | print(exp(-1)); NLCR; 204 | print(exp(0.0001)); NLCR; 205 | print(exp(1)); NLCR; 206 | print(exp(6)); NLCR; 207 | e̲n̲d̲ 208 | )"); 209 | const std::string expect = R"(0.002478752176668 210 | 0.3678794411712 211 | 1.000100005 212 | 2.71828182846 213 | 403.4287934927 214 | )"; 215 | EXPECT_EQ(output, expect); 216 | } 217 | 218 | TEST_F(x1_machine, function_entier) 219 | { 220 | auto output = compile_and_run(R"( 221 | b̲e̲g̲i̲n̲ 222 | print(entier(-98.7777)); NLCR; 223 | print(entier(98.7777)); NLCR; 224 | print(entier(-5.4444)); NLCR; 225 | print(entier(5.4444)); NLCR; 226 | print(entier(-0.9999)); NLCR; 227 | print(entier(0.9999)); NLCR; 228 | print(entier(-0.1111)); NLCR; 229 | print(entier(0.1111)); NLCR; 230 | e̲n̲d̲ 231 | )"); 232 | const std::string expect = R"(-99 233 | 98 234 | -6 235 | 5 236 | -1 237 | 0 238 | -1 239 | 0 240 | )"; 241 | EXPECT_EQ(output, expect); 242 | } 243 | 244 | TEST_F(x1_machine, function_EVEN) 245 | { 246 | auto output = compile_and_run(R"( 247 | b̲e̲g̲i̲n̲ 248 | print(EVEN(0), EVEN(1), EVEN(-0), EVEN(-1)); NLCR; 249 | print(EVEN(2), EVEN(3), EVEN(22), EVEN(33)); NLCR; 250 | print(EVEN(-2), EVEN(-3), EVEN(-22), EVEN(-33)); NLCR; 251 | e̲n̲d̲ 252 | )"); 253 | const std::string expect = R"(1 -1 1 -1 254 | 1 -1 1 -1 255 | 1 -1 1 -1 256 | )"; 257 | EXPECT_EQ(output, expect); 258 | } 259 | -------------------------------------------------------------------------------- /tests/googletest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /tests/label_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "fixture.h" 4 | 5 | TEST_F(x1_machine, label_arg) 6 | { 7 | auto output = compile_and_run(R"( 8 | b̲e̲g̲i̲n̲ 9 | p̲r̲o̲c̲e̲d̲u̲r̲e̲ jump(x); l̲a̲b̲e̲l̲ x; 10 | g̲o̲t̲o̲ x; 11 | 12 | print(123); NLCR; 13 | jump(L); 14 | print(456); NLCR; 15 | L: print(789); NLCR; 16 | e̲n̲d̲ 17 | )"); 18 | const std::string expect = R"(123 19 | 789 20 | )"; 21 | EXPECT_EQ(output, expect); 22 | } 23 | 24 | TEST_F(x1_machine, switch_one_two_three) 25 | { 26 | auto output = compile_and_run(R"( 27 | b̲e̲g̲i̲n̲ 28 | i̲n̲t̲e̲g̲e̲r̲ i; 29 | s̲w̲i̲t̲c̲h̲ sw := one, two, three, done; 30 | i := 0; 31 | next: i := i + 1; 32 | g̲o̲ t̲o̲ sw[i]; 33 | three: print(33); NLCR; 34 | g̲o̲ t̲o̲ next; 35 | two: print(22); NLCR; 36 | g̲o̲ t̲o̲ next; 37 | one: print(11); NLCR; 38 | g̲o̲ t̲o̲ next; 39 | done: print(0); NLCR; 40 | e̲n̲d̲ 41 | )"); 42 | const std::string expect = R"(11 43 | 22 44 | 33 45 | 0 46 | )"; 47 | EXPECT_EQ(output, expect); 48 | } 49 | 50 | TEST_F(x1_machine, jump_one_two_three) 51 | { 52 | auto output = compile_and_run(R"( 53 | b̲e̲g̲i̲n̲ 54 | i̲n̲t̲e̲g̲e̲r̲ i; 55 | s̲w̲i̲t̲c̲h̲ sw := one, two, three, done; 56 | 57 | p̲r̲o̲c̲e̲d̲u̲r̲e̲ jump(s, n); s̲w̲i̲t̲c̲h̲ s; i̲n̲t̲e̲g̲e̲r̲ n; 58 | g̲o̲t̲o̲ s[n]; 59 | 60 | i := 0; 61 | next: i := i + 1; 62 | jump(sw, i); 63 | three: print(33); NLCR; 64 | g̲o̲ t̲o̲ next; 65 | two: print(22); NLCR; 66 | g̲o̲ t̲o̲ next; 67 | one: print(11); NLCR; 68 | g̲o̲ t̲o̲ next; 69 | done: print(0); NLCR; 70 | e̲n̲d̲ 71 | )"); 72 | const std::string expect = R"(11 73 | 22 74 | 33 75 | 0 76 | )"; 77 | EXPECT_EQ(output, expect); 78 | } 79 | 80 | TEST_F(x1_machine, switch_xyzt) 81 | { 82 | auto output = compile_and_run(R"( 83 | b̲e̲g̲i̲n̲ 84 | b̲o̲o̲l̲e̲a̲n̲ b; 85 | i̲n̲t̲e̲g̲e̲r̲ i; 86 | s̲w̲i̲t̲c̲h̲ s := x, y, i̲f̲ b t̲h̲e̲n̲ z e̲l̲s̲e̲ t; 87 | 88 | p̲r̲o̲c̲e̲d̲u̲r̲e̲ p(s); s̲w̲i̲t̲c̲h̲ s; 89 | g̲o̲t̲o̲ s[i]; 90 | 91 | b := t̲r̲u̲e̲; 92 | i:= 1; 93 | p(s); 94 | t: 95 | PRINTTEXT(`t'); NLCR; 96 | g̲o̲t̲o̲ e; 97 | y: 98 | i := 3; 99 | PRINTTEXT(`y'); 100 | p(s); 101 | z: 102 | b := f̲a̲l̲s̲e̲; 103 | PRINTTEXT(`z'); 104 | p(s); 105 | x: 106 | i := 2; 107 | PRINTTEXT(`x'); 108 | p(s); 109 | e: 110 | e̲n̲d̲ 111 | )"); 112 | const std::string expect = "xyzt\n"; 113 | EXPECT_EQ(output, expect); 114 | } 115 | 116 | TEST_F(x1_machine, switch_at_level1) 117 | { 118 | auto output = compile_and_run(R"( 119 | b̲e̲g̲i̲n̲ 120 | i̲n̲t̲e̲g̲e̲r̲ i; 121 | 122 | p̲r̲o̲c̲e̲d̲u̲r̲e̲ jump(s, n); s̲w̲i̲t̲c̲h̲ s; i̲n̲t̲e̲g̲e̲r̲ n; 123 | g̲o̲t̲o̲ s[n]; 124 | 125 | p̲r̲o̲c̲e̲d̲u̲r̲e̲ level1; b̲e̲g̲i̲n̲ 126 | s̲w̲i̲t̲c̲h̲ sw := one, two, three, done; 127 | 128 | i := 0; 129 | next: i := i + 1; 130 | jump(sw, i); 131 | three: print(33); NLCR; 132 | g̲o̲ t̲o̲ next; 133 | two: print(22); NLCR; 134 | g̲o̲ t̲o̲ next; 135 | one: print(11); NLCR; 136 | g̲o̲ t̲o̲ next; 137 | done: print(0); NLCR; 138 | e̲n̲d̲; 139 | 140 | level1; 141 | e̲n̲d̲ 142 | )"); 143 | const std::string expect = R"(11 144 | 22 145 | 33 146 | 0 147 | )"; 148 | EXPECT_EQ(output, expect); 149 | } 150 | 151 | TEST_F(x1_machine, goto_recursive) 152 | { 153 | auto output = compile_and_run(R"( 154 | b̲e̲g̲i̲n̲ 155 | p̲r̲o̲c̲e̲d̲u̲r̲e̲ m(i, x, y); 156 | v̲a̲l̲u̲e̲ i; 157 | i̲n̲t̲e̲g̲e̲r̲ i; 158 | l̲a̲b̲e̲l̲ x, y; 159 | b̲e̲g̲i̲n̲ 160 | i̲f̲ i < 20 t̲h̲e̲n̲ b̲e̲g̲i̲n̲ 161 | m(i+1, y, pr); 162 | g̲o̲t̲o̲ x; 163 | e̲n̲d̲ e̲l̲s̲e̲ i̲f̲ f̲a̲l̲s̲e̲ t̲h̲e̲n̲ b̲e̲g̲i̲n̲ 164 | pr: print(i); NLCR 165 | e̲n̲d̲ 166 | e̲n̲d̲; 167 | 168 | m(0, done, done); 169 | done: 170 | e̲n̲d̲ 171 | )"); 172 | const std::string expect = R"(17 173 | 14 174 | 11 175 | 8 176 | 5 177 | 2 178 | )"; 179 | EXPECT_EQ(output, expect); 180 | } 181 | 182 | TEST_F(x1_machine, goto_from_for_loop) 183 | { 184 | auto output = compile_and_run(R"( 185 | b̲e̲g̲i̲n̲ 186 | i̲n̲t̲e̲g̲e̲r̲ n; 187 | f̲o̲r̲ n := 1 s̲t̲e̲p̲ 1 u̲n̲t̲i̲l̲ 1 d̲o̲ b̲e̲g̲i̲n̲ 188 | print(123); 189 | NLCR; 190 | g̲o̲t̲o̲ done; 191 | e̲n̲d̲; 192 | done: print(456); 193 | NLCR 194 | e̲n̲d̲ 195 | )"); 196 | const std::string expect = R"(123 197 | 456 198 | )"; 199 | EXPECT_EQ(output, expect); 200 | } 201 | -------------------------------------------------------------------------------- /tests/loop_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "fixture.h" 4 | 5 | TEST_F(x1_machine, loop_value_list) 6 | { 7 | auto output = compile_and_run(R"( 8 | _b_e_g_i_n _i_n_t_e_g_e_r i,j; 9 | _f_o_r i := 1,2,3 _d_o 10 | _f_o_r j := 1,2,3 _d_o _b_e_g_i_n 11 | print(10*i+j); NLCR; 12 | _e_n_d 13 | _e_n_d 14 | )"); 15 | const std::string expect = R"(11 16 | 12 17 | 13 18 | 21 19 | 22 20 | 23 21 | 31 22 | 32 23 | 33 24 | )"; 25 | EXPECT_EQ(output, expect); 26 | } 27 | 28 | TEST_F(x1_machine, loop_while) 29 | { 30 | auto output = compile_and_run(R"( 31 | _b_e_g_i_n _i_n_t_e_g_e_r i,j; 32 | _f_o_r i := 1,i+1 _w_h_i_l_e i < 6, 33 | i*2 _w_h_i_l_e i < 100 _d_o _b_e_g_i_n 34 | print(i); NLCR; 35 | _e_n_d 36 | _e_n_d 37 | )"); 38 | const std::string expect = R"(1 39 | 2 40 | 3 41 | 4 42 | 5 43 | 12 44 | 24 45 | 48 46 | 96 47 | )"; 48 | EXPECT_EQ(output, expect); 49 | } 50 | 51 | TEST_F(x1_machine, loop_step) 52 | { 53 | auto output = compile_and_run(R"( 54 | _b_e_g_i_n _i_n_t_e_g_e_r i,j; 55 | _f_o_r i := 1 _s_t_e_p 1 _u_n_t_i_l 5, 56 | i*2 _s_t_e_p -3 _u_n_t_i_l 1 _d_o _b_e_g_i_n 57 | print(i); NLCR; 58 | _e_n_d 59 | _e_n_d 60 | )"); 61 | const std::string expect = R"(1 62 | 2 63 | 3 64 | 4 65 | 5 66 | 12 67 | 9 68 | 6 69 | 3 70 | )"; 71 | EXPECT_EQ(output, expect); 72 | } 73 | 74 | TEST_F(x1_machine, loop_fibonacci) 75 | { 76 | auto output = compile_and_run(R"( 77 | _b_e_g_i_n _i_n_t_e_g_e_r i; 78 | _i_n_t_e_g_e_r _a_r_r_a_y a[0:1]; 79 | a[0] := 0; i := 1; 80 | _f_o_r a[i] := 1 _s_t_e_p a[1-i] _u_n_t_i_l 100 _d_o 81 | _b_e_g_i_n 82 | print(a[i]); NLCR; 83 | i := 1-i; 84 | _e_n_d 85 | _e_n_d 86 | )"); 87 | const std::string expect = R"(1 88 | 1 89 | 2 90 | 3 91 | 5 92 | 8 93 | 13 94 | 21 95 | 34 96 | 55 97 | 89 98 | )"; 99 | EXPECT_EQ(output, expect); 100 | } 101 | 102 | TEST_F(x1_machine, loop_locarray) 103 | { 104 | auto output = compile_and_run(R"( 105 | b̲e̲g̲i̲n̲ 106 | b̲e̲g̲i̲n̲ i̲n̲t̲ a; 107 | r̲e̲a̲l̲ a̲r̲r̲a̲y̲ b[-1:11]; 108 | i̲n̲t̲ z, i; 109 | a := 12345; 110 | z := 54321; 111 | b[-1] := -1.5; 112 | b[11] := 11.25; 113 | print(a); NLCR; 114 | print(z); NLCR; 115 | f̲o̲r̲ i := -1 s̲t̲e̲p̲ 4 u̲n̲t̲i̲l̲ 11 d̲o̲ 116 | b̲e̲g̲i̲n̲ 117 | print(b[i]); NLCR; 118 | e̲n̲d̲ 119 | e̲n̲d̲ 120 | e̲n̲d̲ 121 | )"); 122 | const std::string expect = R"(12345 123 | 54321 124 | -1.5 125 | 0 126 | 0 127 | 11.25 128 | )"; 129 | EXPECT_EQ(output, expect); 130 | } 131 | -------------------------------------------------------------------------------- /tests/man_or_boy.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "fixture.h" 4 | 5 | TEST_F(x1_machine, man_or_boy) 6 | { 7 | auto output = compile_and_run(R"( 8 | b̲e̲g̲i̲n̲ 9 | r̲e̲a̲l̲ p̲r̲o̲c̲e̲d̲u̲r̲e̲ A(k, x1, x2, x3, x4, x5); 10 | v̲a̲l̲u̲e̲ k; i̲n̲t̲e̲g̲e̲r̲ k; 11 | r̲e̲a̲l̲ x1, x2, x3, x4, x5; 12 | b̲e̲g̲i̲n̲ 13 | r̲e̲a̲l̲ p̲r̲o̲c̲e̲d̲u̲r̲e̲ B; 14 | b̲e̲g̲i̲n̲ 15 | k := k - 1; 16 | B := A := A(k, B, x1, x2, x3, x4); 17 | e̲n̲d̲; 18 | A := i̲f̲ k < 1 t̲h̲e̲n̲ x4 + x5 e̲l̲s̲e̲ B; 19 | e̲n̲d̲; 20 | print(A(10, 1.0, -1.0, -1.0, 1.0, 0.0)); NLCR; 21 | e̲n̲d̲ 22 | )"); 23 | const std::string expect = "-67\n"; 24 | EXPECT_EQ(output, expect); 25 | 26 | // Check symbol table. 27 | EXPECT_EQ(machine->get_symbol("A"), 2); 28 | EXPECT_EQ(machine->get_symbol("B"), 10); 29 | } 30 | 31 | // 32 | // Simplified version for easy debug. 33 | // 34 | TEST_F(x1_machine, mob1) 35 | { 36 | auto output = compile_and_run(R"( 37 | b̲e̲g̲i̲n̲ 38 | i̲n̲t̲e̲g̲e̲r̲ p̲r̲o̲c̲e̲d̲u̲r̲e̲ A(k, x1, x2); 39 | v̲a̲l̲u̲e̲ k; i̲n̲t̲e̲g̲e̲r̲ k, x1, x2; 40 | b̲e̲g̲i̲n̲ 41 | i̲n̲t̲e̲g̲e̲r̲ p̲r̲o̲c̲e̲d̲u̲r̲e̲ B; 42 | b̲e̲g̲i̲n̲ 43 | print(k); NLCR; 44 | k := k - 1; 45 | print(k); NLCR; 46 | B := A(k, B, x1); 47 | e̲n̲d̲; 48 | A := i̲f̲ k < 1 t̲h̲e̲n̲ x2 e̲l̲s̲e̲ B; 49 | e̲n̲d̲; 50 | print(A(1, 1, -1)); NLCR; 51 | e̲n̲d̲ 52 | )"); 53 | const std::string expect = R"(1 54 | 0 55 | 1 56 | )"; 57 | EXPECT_EQ(output, expect); 58 | } 59 | 60 | // 61 | // Even more simplified version. 62 | // 63 | TEST_F(x1_machine, mob0) 64 | { 65 | auto output = compile_and_run(R"( 66 | b̲e̲g̲i̲n̲ 67 | p̲r̲o̲c̲e̲d̲u̲r̲e̲ A(k, x); 68 | v̲a̲l̲u̲e̲ k; 69 | i̲n̲t̲e̲g̲e̲r̲ k, x; 70 | b̲e̲g̲i̲n̲ 71 | p̲r̲o̲c̲e̲d̲u̲r̲e̲ B(y); 72 | i̲n̲t̲e̲g̲e̲r̲ y; 73 | b̲e̲g̲i̲n̲ 74 | print(k, x, y); NLCR; 75 | i̲f̲ x > -10 t̲h̲e̲n̲ A(456, -10); 76 | i̲f̲ y < 0 t̲h̲e̲n̲ B(20); 77 | e̲n̲d̲ B; 78 | 79 | print(k, x); NLCR; 80 | B(x - 1); 81 | e̲n̲d̲ A; 82 | A(123, -1); 83 | e̲n̲d̲ 84 | )"); 85 | const std::string expect = R"(123 -1 86 | 123 -1 -2 87 | 456 -10 88 | 456 -10 -11 89 | 456 -10 20 90 | 123 -1 20 91 | 456 -10 92 | 456 -10 -11 93 | 456 -10 20 94 | )"; 95 | EXPECT_EQ(output, expect); 96 | } 97 | 98 | // 99 | // Two levels of recursion. 100 | // 101 | TEST_F(x1_machine, mob2) 102 | { 103 | auto output = compile_and_run(R"( 104 | b̲e̲g̲i̲n̲ 105 | r̲e̲a̲l̲ p̲r̲o̲c̲e̲d̲u̲r̲e̲ A(k, x1, x2, x3, x4, x5); 106 | v̲a̲l̲u̲e̲ k; i̲n̲t̲e̲g̲e̲r̲ k; 107 | r̲e̲a̲l̲ x1, x2, x3, x4, x5; 108 | b̲e̲g̲i̲n̲ 109 | r̲e̲a̲l̲ p̲r̲o̲c̲e̲d̲u̲r̲e̲ B; 110 | b̲e̲g̲i̲n̲ 111 | k := k - 1; 112 | print(k); NLCR; 113 | B := A(k, B, x1, x2, x3, x4); 114 | e̲n̲d̲; 115 | A := i̲f̲ k < 1 t̲h̲e̲n̲ x4 + x5 e̲l̲s̲e̲ B; 116 | e̲n̲d̲; 117 | print(A(2, 11.0, 22.0, 33.0, 44.0, 0.0)); NLCR; 118 | e̲n̲d̲ 119 | )"); 120 | const std::string expect = R"(1 121 | 0 122 | 55 123 | )"; 124 | EXPECT_EQ(output, expect); 125 | } 126 | 127 | // 128 | // Four levels of recursion. 129 | // 130 | TEST_F(x1_machine, mob4) 131 | { 132 | auto output = compile_and_run(R"( 133 | b̲e̲g̲i̲n̲ 134 | r̲e̲a̲l̲ p̲r̲o̲c̲e̲d̲u̲r̲e̲ A(k, x1, x2, x3, x4, x5); 135 | v̲a̲l̲u̲e̲ k; i̲n̲t̲e̲g̲e̲r̲ k; 136 | r̲e̲a̲l̲ x1, x2, x3, x4, x5; 137 | b̲e̲g̲i̲n̲ 138 | r̲e̲a̲l̲ p̲r̲o̲c̲e̲d̲u̲r̲e̲ B; 139 | b̲e̲g̲i̲n̲ 140 | k := k - 1; 141 | print(k); NLCR; 142 | B := A(k, B, x1, x2, x3, x4); 143 | e̲n̲d̲; 144 | A := i̲f̲ k < 1 t̲h̲e̲n̲ x4 + x5 e̲l̲s̲e̲ B; 145 | e̲n̲d̲; 146 | print(A(4, 11.0, 22.0, 33.0, 44.0, 0.0)); NLCR; 147 | e̲n̲d̲ 148 | )"); 149 | const std::string expect = R"(3 150 | 2 151 | 1 152 | 0 153 | 2 154 | 1 155 | 0 156 | 44 157 | )"; 158 | EXPECT_EQ(output, expect); 159 | } 160 | -------------------------------------------------------------------------------- /tests/print123.a60: -------------------------------------------------------------------------------- 1 | b̲e̲g̲i̲n̲ 2 | print(123); NLCR 3 | e̲n̲d̲ 4 | -------------------------------------------------------------------------------- /tests/print123.x1: -------------------------------------------------------------------------------- 1 | 2 | 9 29 0 3 | 9 29 0 4 | 5 | 6 | 10144 96 7 | 10145 71837606 8 | 10146 34 9 | 10147 103 10 | 10148 105 11 | 10149 97 12 | 10150 123 13 | -------------------------------------------------------------------------------- /tests/print_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "fixture.h" 4 | 5 | TEST_F(x1_machine, procedure_PRINTTEXT) 6 | { 7 | auto output = compile_and_run(R"( 8 | b̲e̲g̲i̲n̲ 9 | p̲r̲o̲c̲e̲d̲u̲r̲e̲ prline(s); s̲t̲r̲i̲n̲g̲ s; 10 | b̲e̲g̲i̲n̲ 11 | PRINTTEXT(s); NLCR 12 | e̲n̲d̲; 13 | prline(`Hello `Algol''); 14 | prline(``0123456789''); 15 | prline(``abcdefghijklmnopqrstuvwxyz''); 16 | prline(``ABCDEFGHIJKLMNOPQRSTUVWXYZ''); 17 | prline(``+-×/÷↑>≥=≤<≠¬∧∨⊃≡,.⏨:;:= ''); 18 | prline(``()[]`'''); 19 | e̲n̲d̲ 20 | )"); 21 | const std::string expect = R"(Hello `Algol' 22 | `0123456789' 23 | `abcdefghijklmnopqrstuvwxyz' 24 | `ABCDEFGHIJKLMNOPQRSTUVWXYZ' 25 | `+-×/÷↑>≥=≤<≠¬∧∨⊃≡,.⏨:;:= ' 26 | `()[]`'' 27 | )"; 28 | EXPECT_EQ(output, expect); 29 | } 30 | 31 | TEST_F(x1_machine, procedure_FIXT) 32 | { 33 | auto output = compile_and_run(R"( 34 | b̲e̲g̲i̲n̲ 35 | p̲r̲o̲c̲e̲d̲u̲r̲e̲ pr(n, m, x); v̲a̲l̲u̲e̲ n, m, x; i̲n̲t̲e̲g̲e̲r̲ n, m; r̲e̲a̲l̲ x; b̲e̲g̲i̲n̲ 36 | PRINTTEXT(`/'); 37 | FIXT(n, m, x); 38 | PRINTTEXT(`/'); 39 | NLCR; 40 | e̲n̲d̲; 41 | pr(1, 0, 1.234); 42 | pr(4, 0, -56.789); 43 | pr(21, 0, 123.456); 44 | pr(1, 1, -1.234); 45 | pr(4, 1, 56.789); 46 | pr(20, 1, -123.456); 47 | pr(1, 20, 8 / 7); 48 | pr(4, 17, 9999 / 7); 49 | pr(0, 21, -1 / 7); 50 | pr(2, 0, 0.0); 51 | pr(3, 0, -0.0); 52 | e̲n̲d̲ 53 | )"); 54 | const std::string expect = R"(/+1 / 55 | /- 57 / 56 | /+ 123 / 57 | /-1.2 / 58 | /+ 56.8 / 59 | /- 123.5 / 60 | /+1.14285714285688300151 / 61 | /+1428.42857142910361289 / 62 | /-.142857142857110375189 / 63 | /+ 0 / 64 | /- 0 / 65 | )"; 66 | EXPECT_EQ(output, expect); 67 | } 68 | 69 | TEST_F(x1_machine, procedure_ABSFIXT) 70 | { 71 | auto output = compile_and_run(R"( 72 | b̲e̲g̲i̲n̲ 73 | p̲r̲o̲c̲e̲d̲u̲r̲e̲ pr(n, m, x); v̲a̲l̲u̲e̲ n, m, x; i̲n̲t̲e̲g̲e̲r̲ n, m; r̲e̲a̲l̲ x; b̲e̲g̲i̲n̲ 74 | PRINTTEXT(`/'); 75 | ABSFIXT(n, m, x); 76 | PRINTTEXT(`/'); 77 | NLCR; 78 | e̲n̲d̲; 79 | pr(1, 0, 1.234); 80 | pr(4, 0, -56.789); 81 | pr(21, 0, 123.456); 82 | pr(1, 1, -1.234); 83 | pr(4, 1, 56.789); 84 | pr(20, 1, -123.456); 85 | pr(1, 20, 8 / 7); 86 | pr(4, 17, 9999 / 7); 87 | pr(0, 21, -1 / 7); 88 | pr(2, 0, 0.0); 89 | pr(3, 0, -0.0); 90 | e̲n̲d̲ 91 | )"); 92 | const std::string expect = R"(/ 1 / 93 | / 57 / 94 | / 123 / 95 | / 1.2 / 96 | / 56.8 / 97 | / 123.5 / 98 | / 1.14285714285688300151 / 99 | / 1428.42857142910361289 / 100 | / .142857142857110375189 / 101 | / 0 / 102 | / 0 / 103 | )"; 104 | EXPECT_EQ(output, expect); 105 | } 106 | 107 | TEST_F(x1_machine, procedure_FLOT) 108 | { 109 | auto output = compile_and_run(R"( 110 | b̲e̲g̲i̲n̲ 111 | p̲r̲o̲c̲e̲d̲u̲r̲e̲ pr(n, m, x); v̲a̲l̲u̲e̲ n, m, x; i̲n̲t̲e̲g̲e̲r̲ n, m; r̲e̲a̲l̲ x; b̲e̲g̲i̲n̲ 112 | PRINTTEXT(`/'); 113 | FLOT(n, m, x); 114 | PRINTTEXT(`/'); 115 | NLCR; 116 | e̲n̲d̲; 117 | pr(1, 1, 1.234); 118 | pr(4, 1, -56.789); 119 | pr(13, 1, 123.456); 120 | pr(4, 2, -1.234); 121 | pr(5, 2, 56.789); 122 | pr(13, 2, -123.456); 123 | pr(4, 3, 8⏨555 / 7); 124 | pr(5, 3, 9999⏨444 / 7); 125 | pr(13, 3, -1⏨-111 / 7); 126 | pr(4, 1, 9.999); 127 | pr(4, 1, 9.9999); 128 | pr(1, 1, 0.0); 129 | pr(3, 1, -0.0); 130 | e̲n̲d̲ 131 | )"); 132 | const std::string expect = R"(/+.1⏨+1 / 133 | /-.5679⏨+2 / 134 | /+.1234560000000⏨+3 / 135 | /-.1234⏨+ 1 / 136 | /+.56789⏨+ 2 / 137 | /-.1234560000000⏨+ 3 / 138 | /+.1143⏨+556 / 139 | /+.14284⏨+448 / 140 | /-.1428571428571⏨-111 / 141 | /+.9999⏨+1 / 142 | /+.1000⏨+2 / 143 | /+.0⏨+0 / 144 | /-.000⏨+0 / 145 | )"; 146 | EXPECT_EQ(output, expect); 147 | } 148 | --------------------------------------------------------------------------------