From cc2545b09be137813ced74692ee7ec71fdd5b232 Mon Sep 17 00:00:00 2001 From: Ed Nutting Date: Sun, 8 May 2016 15:04:09 +0100 Subject: [PATCH] Initial public upload of TSS --- .gitignore | 276 ++ .mvn/wrapper/maven-wrapper.jar | Bin 0 -> 49519 bytes .mvn/wrapper/maven-wrapper.properties | 1 + .travis.yml | 9 + ASM Generator TODO.txt | 3 + README.md | 46 + assignment.s | 14 + doc/TSILGenerator functions.md | 374 ++ .../Metadata Package Class Diagram.uml | 197 ++ doc/metadata/Workspaces.md | 130 + doc/occam-intermediate-language.md | 99 + doc/simulator.md | 91 + doc/transputer-assembler.md | 135 + mvnw | 234 ++ mvnw-custom-java | 7 + mvnw.cmd | 145 + tss-occam-compiler-test/pom.xml | 113 + .../transputersystems/occam/ParserTest.java | 55 + .../occam/TSILGeneratorTest.java | 480 +++ .../open_transputer/ASMGeneratorTest.java | 505 +++ tss-occam-compiler/etc/toc | 3 + tss-occam-compiler/pom.xml | 162 + .../uk/co/transputersystems/occam/Occam.g4 | 619 ++++ .../occam/ErrorListener.java | 15 + .../occam/ILOpFormatter.java | 50 + .../occam/OccamCompiler.java | 97 + .../occam/OccamCompilerApplication.java | 124 + .../occam/ParseTreePretty.java | 77 + .../occam/ReferencedTSILGenerator.java | 342 ++ .../occam/StringUtilities.java | 11 + .../occam/TSILGenerator.java | 3128 +++++++++++++++++ .../occam/TSILGeneratorHelpers.java | 184 + .../uk/co/transputersystems/occam/il/Add.java | 29 + .../co/transputersystems/occam/il/After.java | 28 + .../occam/il/BitwiseAnd.java | 25 + .../occam/il/BitwiseNot.java | 25 + .../transputersystems/occam/il/BitwiseOr.java | 25 + .../occam/il/BitwiseXor.java | 25 + .../occam/il/BooleanAnd.java | 27 + .../occam/il/BooleanNot.java | 27 + .../transputersystems/occam/il/BooleanOr.java | 27 + .../co/transputersystems/occam/il/Branch.java | 29 + .../occam/il/BranchEqZero.java | 29 + .../occam/il/BranchIfFalse.java | 30 + .../occam/il/BranchIfTrue.java | 30 + .../occam/il/BranchNotEqZero.java | 29 + .../co/transputersystems/occam/il/Call.java | 32 + .../occam/il/CompareEqual.java | 27 + .../occam/il/CompareGreaterThan.java | 25 + .../occam/il/CompareGreaterThanOrEqual.java | 25 + .../occam/il/CompareLessThan.java | 27 + .../occam/il/CompareLessThanOrEqual.java | 25 + .../occam/il/CompareNotEqual.java | 27 + .../occam/il/DelayedTimerInput.java | 27 + .../occam/il/DisableChannel.java | 31 + .../occam/il/DisablePort.java | 33 + .../occam/il/DisableSkip.java | 30 + .../occam/il/DisableTimer.java | 33 + .../co/transputersystems/occam/il/Divide.java | 26 + .../transputersystems/occam/il/Duplicate.java | 25 + .../occam/il/EnableChannel.java | 26 + .../occam/il/EnablePort.java | 27 + .../occam/il/EnableSkip.java | 26 + .../occam/il/EnableTimer.java | 27 + .../co/transputersystems/occam/il/EndAlt.java | 29 + .../occam/il/EndProcess.java | 28 + .../transputersystems/occam/il/ILBlock.java | 134 + .../co/transputersystems/occam/il/ILOp.java | 85 + .../occam/il/ILOpVisitor.java | 72 + .../transputersystems/occam/il/InitAlt.java | 28 + .../occam/il/InitChannel.java | 31 + .../occam/il/InitProcesses.java | 40 + .../co/transputersystems/occam/il/Label.java | 45 + .../transputersystems/occam/il/LeftShift.java | 28 + .../occam/il/LoadArgument.java | 33 + .../occam/il/LoadChannelRef.java | 27 + .../occam/il/LoadConstant.java | 30 + .../occam/il/LoadGlobal.java | 34 + .../transputersystems/occam/il/LoadLocal.java | 38 + .../occam/il/LoadPortRef.java | 31 + .../transputersystems/occam/il/MethodEnd.java | 29 + .../occam/il/MethodStart.java | 29 + .../co/transputersystems/occam/il/Modulo.java | 26 + .../occam/il/MostNegative.java | 30 + .../occam/il/MostPositive.java | 30 + .../transputersystems/occam/il/Multiply.java | 29 + .../occam/il/ProcessPriorities.java | 7 + .../occam/il/ReadChannel.java | 27 + .../transputersystems/occam/il/ReadPort.java | 27 + .../transputersystems/occam/il/ReadTimer.java | 28 + .../occam/il/RightShift.java | 28 + .../co/transputersystems/occam/il/Skip.java | 26 + .../occam/il/StartProcess.java | 31 + .../occam/il/StoreArgument.java | 33 + .../occam/il/StoreGlobal.java | 33 + .../occam/il/StoreLocal.java | 43 + .../transputersystems/occam/il/Subtract.java | 29 + .../occam/il/UnaryMinus.java | 30 + .../transputersystems/occam/il/WaitAlt.java | 28 + .../occam/il/WriteChannel.java | 27 + .../transputersystems/occam/il/WritePort.java | 30 + .../occam/metadata/Abbreviation.java | 98 + .../occam/metadata/Argument.java | 32 + .../occam/metadata/ArrayAbbreviation.java | 26 + .../occam/metadata/ArrayDataType.java | 36 + .../occam/metadata/Channel.java | 13 + .../occam/metadata/ChannelAbbreviation.java | 7 + .../occam/metadata/DataType.java | 19 + .../occam/metadata/Field.java | 36 + .../occam/metadata/FileInformation.java | 68 + .../occam/metadata/Function.java | 93 + .../occam/metadata/LibraryInformation.java | 261 ++ .../occam/metadata/LocationAbbreviation.java | 26 + .../occam/metadata/NamedDataType.java | 25 + .../occam/metadata/NamedOperand.java | 47 + .../occam/metadata/Port.java | 13 + .../occam/metadata/PortAbbreviation.java | 7 + .../occam/metadata/PrimitiveDataType.java | 23 + .../occam/metadata/RecordDataType.java | 37 + .../occam/metadata/Scope.java | 474 +++ .../occam/metadata/Timer.java | 15 + .../occam/metadata/TimerAbbreviation.java | 14 + .../occam/metadata/ValueAbbreviation.java | 16 + .../occam/metadata/Variable.java | 22 + .../occam/metadata/VariableAbbreviation.java | 9 + .../occam/metadata/VerifiableData.java | 8 + .../occam/metadata/VerificationContext.java | 45 + .../occam/metadata/Workspace.java | 242 ++ .../occam/metadata/WorkspaceLocation.java | 25 + .../occam/open_transputer/ASMBlock.java | 27 + .../occam/open_transputer/ASMGenerator.java | 1957 +++++++++++ .../open_transputer/ASMGeneratorContext.java | 159 + .../open_transputer/ASMGeneratorHelpers.java | 621 ++++ .../occam/open_transputer/ASMOpFormatter.java | 14 + .../occam/open_transputer/DependencyTree.java | 120 + .../occam/open_transputer/StackBranch.java | 28 + .../occam/open_transputer/StackItem.java | 40 + .../occam/open_transputer/StackTracker.java | 40 + .../occam/open_transputer/assembly/ASMOp.java | 11 + .../occam/open_transputer/assembly/Adc.java | 10 + .../occam/open_transputer/assembly/Add.java | 7 + .../occam/open_transputer/assembly/Ajw.java | 8 + .../occam/open_transputer/assembly/Alt.java | 7 + .../open_transputer/assembly/Altend.java | 7 + .../occam/open_transputer/assembly/Altwt.java | 7 + .../occam/open_transputer/assembly/And.java | 7 + .../occam/open_transputer/assembly/Bcnt.java | 7 + .../open_transputer/assembly/Bitcnt.java | 7 + .../open_transputer/assembly/Bitrevnbits.java | 7 + .../open_transputer/assembly/Bitrevword.java | 7 + .../occam/open_transputer/assembly/Bsub.java | 7 + .../occam/open_transputer/assembly/Call.java | 8 + .../occam/open_transputer/assembly/Ccnt1.java | 7 + .../open_transputer/assembly/Cflerr.java | 7 + .../open_transputer/assembly/Channel.java | 10 + .../occam/open_transputer/assembly/Cj.java | 8 + .../open_transputer/assembly/Clrhalterr.java | 7 + .../open_transputer/assembly/Crcbyte.java | 7 + .../open_transputer/assembly/Crcword.java | 7 + .../occam/open_transputer/assembly/Csngl.java | 7 + .../occam/open_transputer/assembly/Csub0.java | 7 + .../occam/open_transputer/assembly/Cword.java | 7 + .../occam/open_transputer/assembly/Data.java | 8 + .../occam/open_transputer/assembly/Diff.java | 7 + .../occam/open_transputer/assembly/Disc.java | 7 + .../occam/open_transputer/assembly/Diss.java | 7 + .../occam/open_transputer/assembly/Dist.java | 7 + .../occam/open_transputer/assembly/Div.java | 7 + .../occam/open_transputer/assembly/Dup.java | 7 + .../occam/open_transputer/assembly/Enbc.java | 7 + .../occam/open_transputer/assembly/Enbs.java | 7 + .../occam/open_transputer/assembly/Enbt.java | 7 + .../occam/open_transputer/assembly/Endp.java | 7 + .../occam/open_transputer/assembly/Eqc.java | 8 + .../occam/open_transputer/assembly/Fmul.java | 7 + .../occam/open_transputer/assembly/Gajw.java | 7 + .../occam/open_transputer/assembly/Gcall.java | 7 + .../occam/open_transputer/assembly/Gt.java | 7 + .../occam/open_transputer/assembly/In.java | 7 + .../occam/open_transputer/assembly/J.java | 8 + .../occam/open_transputer/assembly/Label.java | 16 + .../occam/open_transputer/assembly/Ladd.java | 7 + .../occam/open_transputer/assembly/Lb.java | 7 + .../occam/open_transputer/assembly/Ldc.java | 17 + .../occam/open_transputer/assembly/Ldiff.java | 7 + .../occam/open_transputer/assembly/Ldinf.java | 7 + .../occam/open_transputer/assembly/Ldiv.java | 7 + .../occam/open_transputer/assembly/Ldl.java | 7 + .../occam/open_transputer/assembly/Ldlp.java | 7 + .../occam/open_transputer/assembly/Ldnl.java | 7 + .../occam/open_transputer/assembly/Ldnlp.java | 7 + .../occam/open_transputer/assembly/Ldpi.java | 7 + .../occam/open_transputer/assembly/Ldpri.java | 7 + .../open_transputer/assembly/Ldtimer.java | 7 + .../occam/open_transputer/assembly/Lend.java | 7 + .../occam/open_transputer/assembly/Lmul.java | 7 + .../occam/open_transputer/assembly/Lshl.java | 7 + .../occam/open_transputer/assembly/Lshr.java | 7 + .../occam/open_transputer/assembly/Lsub.java | 7 + .../occam/open_transputer/assembly/Lsum.java | 7 + .../occam/open_transputer/assembly/Mint.java | 7 + .../occam/open_transputer/assembly/Move.java | 7 + .../open_transputer/assembly/Move2dall.java | 7 + .../open_transputer/assembly/Move2dinit.java | 7 + .../assembly/Move2dnonzero.java | 7 + .../open_transputer/assembly/Move2dzero.java | 7 + .../occam/open_transputer/assembly/Mul.java | 7 + .../occam/open_transputer/assembly/Nfix.java | 7 + .../occam/open_transputer/assembly/Norm.java | 7 + .../occam/open_transputer/assembly/Not.java | 7 + .../occam/open_transputer/assembly/Opr.java | 7 + .../occam/open_transputer/assembly/Or.java | 7 + .../occam/open_transputer/assembly/Out.java | 7 + .../open_transputer/assembly/Outbyte.java | 7 + .../open_transputer/assembly/Outword.java | 7 + .../occam/open_transputer/assembly/Pfix.java | 7 + .../open_transputer/assembly/Postnormsn.java | 7 + .../occam/open_transputer/assembly/Prod.java | 11 + .../occam/open_transputer/assembly/Rem.java | 7 + .../open_transputer/assembly/Resetch.java | 7 + .../occam/open_transputer/assembly/Ret.java | 7 + .../occam/open_transputer/assembly/Rev.java | 7 + .../open_transputer/assembly/Roundsn.java | 7 + .../occam/open_transputer/assembly/Runp.java | 7 + .../occam/open_transputer/assembly/Saveh.java | 7 + .../occam/open_transputer/assembly/Savel.java | 7 + .../occam/open_transputer/assembly/Sb.java | 7 + .../open_transputer/assembly/Seterr.java | 7 + .../open_transputer/assembly/Sethalterr.java | 7 + .../occam/open_transputer/assembly/Shl.java | 7 + .../occam/open_transputer/assembly/Shr.java | 7 + .../open_transputer/assembly/Startp.java | 7 + .../occam/open_transputer/assembly/Sthb.java | 7 + .../occam/open_transputer/assembly/Sthf.java | 7 + .../occam/open_transputer/assembly/Stl.java | 7 + .../occam/open_transputer/assembly/Stlb.java | 7 + .../occam/open_transputer/assembly/Stlf.java | 7 + .../occam/open_transputer/assembly/Stnl.java | 7 + .../open_transputer/assembly/Stoperr.java | 7 + .../occam/open_transputer/assembly/Stopp.java | 7 + .../open_transputer/assembly/Sttimer.java | 7 + .../occam/open_transputer/assembly/Sub.java | 7 + .../occam/open_transputer/assembly/Sum.java | 7 + .../occam/open_transputer/assembly/Talt.java | 7 + .../open_transputer/assembly/Taltwt.java | 7 + .../open_transputer/assembly/Testerr.java | 7 + .../open_transputer/assembly/Testhalterr.java | 7 + .../open_transputer/assembly/Testpranal.java | 7 + .../occam/open_transputer/assembly/Tin.java | 7 + .../open_transputer/assembly/Unpacksn.java | 7 + .../occam/open_transputer/assembly/Wcnt.java | 7 + .../occam/open_transputer/assembly/Wsub.java | 7 + .../open_transputer/assembly/Wsubdb.java | 7 + .../occam/open_transputer/assembly/Xdble.java | 7 + .../occam/open_transputer/assembly/Xor.java | 7 + .../occam/open_transputer/assembly/Xword.java | 7 + .../occam/TSILGeneratorHelpersTest.java | 49 + .../transputersystems/occam/il/ILOpTest.java | 50 + .../ASMGeneratorHelpersTest.java | 7 + tss-occam-test-resources/pom.xml | 53 + .../src/main/resources/basic-tests/test01.occ | 17 + .../src/main/resources/basic-tests/test02.occ | 6 + .../src/main/resources/basic-tests/test03.occ | 15 + .../src/main/resources/basic-tests/test04.occ | 8 + .../src/main/resources/basic-tests/test05.occ | 8 + .../src/main/resources/basic-tests/test06.occ | 8 + .../src/main/resources/basic-tests/test07.occ | 24 + .../src/main/resources/basic-tests/test08.occ | 7 + .../src/main/resources/basic-tests/test09.occ | 7 + .../src/main/resources/basic-tests/test10.occ | 12 + .../src/main/resources/basic-tests/test11.occ | 25 + .../resources/feature-tests/alternatives.occ | 24 + .../main/resources/feature-tests/array.occ | 28 + .../feature-tests/array_abbreviations.occ | 22 + .../feature-tests/array_segments.occ | 34 + .../resources/feature-tests/assignment.occ | 11 + .../resources/feature-tests/byte_literal.occ | 10 + .../feature-tests/channel_abbreviations.occ | 12 + .../main/resources/feature-tests/channels.occ | 14 + .../resources/feature-tests/conditional.occ | 19 + .../resources/feature-tests/constants.occ | 15 + .../resources/feature-tests/declarations.occ | 8 + .../feature-tests/dyadic_expression.occ | 30 + .../expression_features_nested.occ | 11 + .../feature-tests/monadic_expressions.occ | 20 + .../feature-tests/operations_types.occ | 21 + .../src/main/resources/feature-tests/par.occ | 11 + .../resources/feature-tests/par_advanced.occ | 24 + .../src/main/resources/feature-tests/port.occ | 14 + .../feature-tests/proc_arguments.occ | 14 + .../feature-tests/proc_par_arguments.occ | 14 + .../procedure_static_assignment.occ | 16 + .../feature-tests/record_declaration.occ | 16 + .../feature-tests/record_operations.occ | 28 + .../feature-tests/replicated_conditionals.occ | 13 + .../resources/feature-tests/replicator.occ | 10 + .../resources/feature-tests/selection.occ | 15 + .../resources/feature-tests/sequential.occ | 16 + .../feature-tests/variable_abbreviations.occ | 19 + .../resources/feature-tests/while_loops.occ | 20 + .../function-tests/function_el_0_in_1_out.occ | 8 + .../function-tests/function_el_0_in_2_out.occ | 8 + .../function-tests/function_el_0_in_3_out.occ | 8 + .../function-tests/function_el_0_in_4_out.occ | 8 + .../function-tests/function_el_1_in_1_out.occ | 8 + .../function-tests/function_el_1_in_2_out.occ | 8 + .../function-tests/function_el_1_in_3_out.occ | 8 + .../function-tests/function_el_1_in_4_out.occ | 8 + .../function-tests/function_el_2_in_1_out.occ | 8 + .../function-tests/function_el_2_in_2_out.occ | 8 + .../function-tests/function_el_2_in_3_out.occ | 8 + .../function-tests/function_el_2_in_4_out.occ | 8 + .../function-tests/function_el_3_in_1_out.occ | 8 + .../function-tests/function_el_3_in_2_out.occ | 8 + .../function-tests/function_el_3_in_3_out.occ | 8 + .../function-tests/function_el_3_in_4_out.occ | 8 + .../function-tests/function_el_4_in_1_out.occ | 8 + .../function-tests/function_el_4_in_2_out.occ | 8 + .../function-tests/function_el_4_in_3_out.occ | 8 + .../function-tests/function_el_4_in_4_out.occ | 8 + .../function_expression_list.occ | 10 + .../function-tests/function_value_process.occ | 20 + .../function-tests/function_vp_0_in_1_out.occ | 14 + .../function-tests/function_vp_0_in_2_out.occ | 15 + .../function-tests/function_vp_0_in_3_out.occ | 16 + .../function-tests/function_vp_0_in_4_out.occ | 17 + .../function-tests/function_vp_1_in_1_out.occ | 14 + .../function-tests/function_vp_1_in_2_out.occ | 15 + .../function-tests/function_vp_1_in_3_out.occ | 16 + .../function-tests/function_vp_1_in_4_out.occ | 17 + .../function-tests/function_vp_2_in_1_out.occ | 14 + .../function-tests/function_vp_2_in_2_out.occ | 15 + .../function-tests/function_vp_2_in_3_out.occ | 16 + .../function-tests/function_vp_2_in_4_out.occ | 17 + .../function-tests/function_vp_3_in_1_out.occ | 14 + .../function-tests/function_vp_3_in_2_out.occ | 15 + .../function-tests/function_vp_3_in_3_out.occ | 16 + .../function-tests/function_vp_3_in_4_out.occ | 17 + .../function-tests/function_vp_4_in_1_out.occ | 14 + .../function-tests/function_vp_4_in_2_out.occ | 15 + .../function-tests/function_vp_4_in_3_out.occ | 16 + .../function-tests/function_vp_4_in_4_out.occ | 20 + tss-transputer-assembler-test/pom.xml | 121 + .../assembler/AssembleFileTest.java | 614 ++++ tss-transputer-assembler/etc/tas | 3 + tss-transputer-assembler/pom.xml | 181 + .../assembler/AssemblerExpression.g4 | 26 + .../transputer/assembler/Assembler.java | 670 ++++ .../assembler/AssemblerApplication.java | 76 + .../transputer/assembler/Assembly.java | 16 + .../transputer/assembler/Instruction.java | 35 + .../transputer/assembler/InstructionType.java | 6 + .../transputer/assembler/Opcode.java | 20 + .../transputer/assembler/OpcodeType.java | 6 + .../assembler/config/AssemblerConfig.java | 17 + .../assembler/config/Connection.java | 37 + .../transputer/assembler/config/IOPin.java | 37 + .../assembler/config/Processor.java | 41 + .../expression/ExpressionEvaluator.java | 49 + .../assembler/AssemblerRegexTest.java | 229 ++ .../transputer/assembler/AssemblerTest.java | 489 +++ .../expression/ExpressionEvaluatorTest.java | 83 + tss-transputer-simulator-test/pom.xml | 125 + .../simulator/SimulateFileTest.java | 693 ++++ tss-transputer-simulator/etc/tsim | 3 + tss-transputer-simulator/pom.xml | 184 + .../transputer/simulator/DebuggerCommand.g4 | 85 + .../transputer/simulator/ErrorListener.java | 15 + .../transputer/simulator/Simulator.java | 257 ++ .../simulator/SimulatorApplication.java | 26 + .../transputer/simulator/SimulatorConfig.java | 24 + .../transputer/simulator/Transputer.java | 2205 ++++++++++++ .../simulator/TransputerConstants.java | 179 + .../simulator/TransputerHelpers.java | 93 + .../UnexpectedOverflowException.java | 4 + .../simulator/debugger/CommandExecutor.java | 288 ++ .../simulator/debugger/CommandResult.java | 8 + .../debugger/DebuggerRecordedState.java | 15 + .../simulator/debugger/NumberListParser.java | 14 + .../simulator/debugger/Process.java | 38 + .../simulator/debugger/ProcessStatus.java | 7 + .../simulator/models/InputLink.java | 39 + .../simulator/models/OutputLink.java | 32 + .../transputer/simulator/models/Priority.java | 6 + .../simulator/models/Registers.java | 27 + .../simulator/models/StatusRegister.java | 15 + .../simulator/DebuggerCommandParserTest.java | 108 + .../debugger/CommandExecutorTest.java | 9 + tss-transputer-utils/pom.xml | 107 + .../transputer/utils/InteractivePrefix.java | 72 + 390 files changed, 24273 insertions(+) create mode 100644 .mvn/wrapper/maven-wrapper.jar create mode 100644 .mvn/wrapper/maven-wrapper.properties create mode 100644 .travis.yml create mode 100644 ASM Generator TODO.txt create mode 100644 README.md create mode 100644 assignment.s create mode 100644 doc/TSILGenerator functions.md create mode 100644 doc/metadata/Metadata Package Class Diagram.uml create mode 100644 doc/metadata/Workspaces.md create mode 100644 doc/occam-intermediate-language.md create mode 100644 doc/simulator.md create mode 100644 doc/transputer-assembler.md create mode 100644 mvnw create mode 100644 mvnw-custom-java create mode 100644 mvnw.cmd create mode 100644 tss-occam-compiler-test/pom.xml create mode 100644 tss-occam-compiler-test/src/test/java/uk/co/transputersystems/occam/ParserTest.java create mode 100644 tss-occam-compiler-test/src/test/java/uk/co/transputersystems/occam/TSILGeneratorTest.java create mode 100644 tss-occam-compiler-test/src/test/java/uk/co/transputersystems/occam/open_transputer/ASMGeneratorTest.java create mode 100644 tss-occam-compiler/etc/toc create mode 100644 tss-occam-compiler/pom.xml create mode 100644 tss-occam-compiler/src/main/antlr4/uk/co/transputersystems/occam/Occam.g4 create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/ErrorListener.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/ILOpFormatter.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/OccamCompiler.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/OccamCompilerApplication.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/ParseTreePretty.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/ReferencedTSILGenerator.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/StringUtilities.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/TSILGenerator.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/TSILGeneratorHelpers.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/Add.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/After.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/BitwiseAnd.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/BitwiseNot.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/BitwiseOr.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/BitwiseXor.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/BooleanAnd.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/BooleanNot.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/BooleanOr.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/Branch.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/BranchEqZero.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/BranchIfFalse.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/BranchIfTrue.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/BranchNotEqZero.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/Call.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/CompareEqual.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/CompareGreaterThan.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/CompareGreaterThanOrEqual.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/CompareLessThan.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/CompareLessThanOrEqual.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/CompareNotEqual.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/DelayedTimerInput.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/DisableChannel.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/DisablePort.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/DisableSkip.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/DisableTimer.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/Divide.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/Duplicate.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/EnableChannel.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/EnablePort.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/EnableSkip.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/EnableTimer.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/EndAlt.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/EndProcess.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/ILBlock.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/ILOp.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/ILOpVisitor.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/InitAlt.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/InitChannel.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/InitProcesses.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/Label.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/LeftShift.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/LoadArgument.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/LoadChannelRef.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/LoadConstant.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/LoadGlobal.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/LoadLocal.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/LoadPortRef.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/MethodEnd.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/MethodStart.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/Modulo.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/MostNegative.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/MostPositive.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/Multiply.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/ProcessPriorities.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/ReadChannel.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/ReadPort.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/ReadTimer.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/RightShift.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/Skip.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/StartProcess.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/StoreArgument.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/StoreGlobal.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/StoreLocal.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/Subtract.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/UnaryMinus.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/WaitAlt.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/WriteChannel.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/WritePort.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/Abbreviation.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/Argument.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/ArrayAbbreviation.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/ArrayDataType.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/Channel.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/ChannelAbbreviation.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/DataType.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/Field.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/FileInformation.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/Function.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/LibraryInformation.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/LocationAbbreviation.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/NamedDataType.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/NamedOperand.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/Port.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/PortAbbreviation.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/PrimitiveDataType.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/RecordDataType.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/Scope.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/Timer.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/TimerAbbreviation.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/ValueAbbreviation.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/Variable.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/VariableAbbreviation.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/VerifiableData.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/VerificationContext.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/Workspace.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/WorkspaceLocation.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/ASMBlock.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/ASMGenerator.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/ASMGeneratorContext.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/ASMGeneratorHelpers.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/ASMOpFormatter.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/DependencyTree.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/StackBranch.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/StackItem.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/StackTracker.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/ASMOp.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Adc.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Add.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Ajw.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Alt.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Altend.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Altwt.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/And.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Bcnt.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Bitcnt.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Bitrevnbits.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Bitrevword.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Bsub.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Call.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Ccnt1.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Cflerr.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Channel.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Cj.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Clrhalterr.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Crcbyte.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Crcword.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Csngl.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Csub0.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Cword.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Data.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Diff.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Disc.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Diss.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Dist.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Div.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Dup.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Enbc.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Enbs.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Enbt.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Endp.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Eqc.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Fmul.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Gajw.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Gcall.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Gt.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/In.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/J.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Label.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Ladd.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Lb.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Ldc.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Ldiff.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Ldinf.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Ldiv.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Ldl.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Ldlp.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Ldnl.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Ldnlp.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Ldpi.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Ldpri.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Ldtimer.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Lend.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Lmul.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Lshl.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Lshr.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Lsub.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Lsum.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Mint.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Move.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Move2dall.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Move2dinit.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Move2dnonzero.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Move2dzero.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Mul.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Nfix.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Norm.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Not.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Opr.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Or.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Out.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Outbyte.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Outword.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Pfix.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Postnormsn.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Prod.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Rem.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Resetch.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Ret.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Rev.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Roundsn.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Runp.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Saveh.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Savel.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Sb.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Seterr.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Sethalterr.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Shl.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Shr.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Startp.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Sthb.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Sthf.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Stl.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Stlb.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Stlf.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Stnl.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Stoperr.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Stopp.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Sttimer.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Sub.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Sum.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Talt.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Taltwt.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Testerr.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Testhalterr.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Testpranal.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Tin.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Unpacksn.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Wcnt.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Wsub.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Wsubdb.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Xdble.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Xor.java create mode 100644 tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Xword.java create mode 100644 tss-occam-compiler/src/test/java/uk/co/transputersystems/occam/TSILGeneratorHelpersTest.java create mode 100644 tss-occam-compiler/src/test/java/uk/co/transputersystems/occam/il/ILOpTest.java create mode 100644 tss-occam-compiler/src/test/java/uk/co/transputersystems/occam/open_transputer/ASMGeneratorHelpersTest.java create mode 100644 tss-occam-test-resources/pom.xml create mode 100644 tss-occam-test-resources/src/main/resources/basic-tests/test01.occ create mode 100644 tss-occam-test-resources/src/main/resources/basic-tests/test02.occ create mode 100644 tss-occam-test-resources/src/main/resources/basic-tests/test03.occ create mode 100644 tss-occam-test-resources/src/main/resources/basic-tests/test04.occ create mode 100644 tss-occam-test-resources/src/main/resources/basic-tests/test05.occ create mode 100644 tss-occam-test-resources/src/main/resources/basic-tests/test06.occ create mode 100644 tss-occam-test-resources/src/main/resources/basic-tests/test07.occ create mode 100644 tss-occam-test-resources/src/main/resources/basic-tests/test08.occ create mode 100644 tss-occam-test-resources/src/main/resources/basic-tests/test09.occ create mode 100644 tss-occam-test-resources/src/main/resources/basic-tests/test10.occ create mode 100644 tss-occam-test-resources/src/main/resources/basic-tests/test11.occ create mode 100644 tss-occam-test-resources/src/main/resources/feature-tests/alternatives.occ create mode 100644 tss-occam-test-resources/src/main/resources/feature-tests/array.occ create mode 100644 tss-occam-test-resources/src/main/resources/feature-tests/array_abbreviations.occ create mode 100644 tss-occam-test-resources/src/main/resources/feature-tests/array_segments.occ create mode 100644 tss-occam-test-resources/src/main/resources/feature-tests/assignment.occ create mode 100644 tss-occam-test-resources/src/main/resources/feature-tests/byte_literal.occ create mode 100644 tss-occam-test-resources/src/main/resources/feature-tests/channel_abbreviations.occ create mode 100644 tss-occam-test-resources/src/main/resources/feature-tests/channels.occ create mode 100644 tss-occam-test-resources/src/main/resources/feature-tests/conditional.occ create mode 100644 tss-occam-test-resources/src/main/resources/feature-tests/constants.occ create mode 100644 tss-occam-test-resources/src/main/resources/feature-tests/declarations.occ create mode 100644 tss-occam-test-resources/src/main/resources/feature-tests/dyadic_expression.occ create mode 100644 tss-occam-test-resources/src/main/resources/feature-tests/expression_features_nested.occ create mode 100644 tss-occam-test-resources/src/main/resources/feature-tests/monadic_expressions.occ create mode 100644 tss-occam-test-resources/src/main/resources/feature-tests/operations_types.occ create mode 100644 tss-occam-test-resources/src/main/resources/feature-tests/par.occ create mode 100644 tss-occam-test-resources/src/main/resources/feature-tests/par_advanced.occ create mode 100644 tss-occam-test-resources/src/main/resources/feature-tests/port.occ create mode 100644 tss-occam-test-resources/src/main/resources/feature-tests/proc_arguments.occ create mode 100644 tss-occam-test-resources/src/main/resources/feature-tests/proc_par_arguments.occ create mode 100644 tss-occam-test-resources/src/main/resources/feature-tests/procedure_static_assignment.occ create mode 100644 tss-occam-test-resources/src/main/resources/feature-tests/record_declaration.occ create mode 100644 tss-occam-test-resources/src/main/resources/feature-tests/record_operations.occ create mode 100644 tss-occam-test-resources/src/main/resources/feature-tests/replicated_conditionals.occ create mode 100644 tss-occam-test-resources/src/main/resources/feature-tests/replicator.occ create mode 100644 tss-occam-test-resources/src/main/resources/feature-tests/selection.occ create mode 100644 tss-occam-test-resources/src/main/resources/feature-tests/sequential.occ create mode 100644 tss-occam-test-resources/src/main/resources/feature-tests/variable_abbreviations.occ create mode 100644 tss-occam-test-resources/src/main/resources/feature-tests/while_loops.occ create mode 100644 tss-occam-test-resources/src/main/resources/function-tests/function_el_0_in_1_out.occ create mode 100644 tss-occam-test-resources/src/main/resources/function-tests/function_el_0_in_2_out.occ create mode 100644 tss-occam-test-resources/src/main/resources/function-tests/function_el_0_in_3_out.occ create mode 100644 tss-occam-test-resources/src/main/resources/function-tests/function_el_0_in_4_out.occ create mode 100644 tss-occam-test-resources/src/main/resources/function-tests/function_el_1_in_1_out.occ create mode 100644 tss-occam-test-resources/src/main/resources/function-tests/function_el_1_in_2_out.occ create mode 100644 tss-occam-test-resources/src/main/resources/function-tests/function_el_1_in_3_out.occ create mode 100644 tss-occam-test-resources/src/main/resources/function-tests/function_el_1_in_4_out.occ create mode 100644 tss-occam-test-resources/src/main/resources/function-tests/function_el_2_in_1_out.occ create mode 100644 tss-occam-test-resources/src/main/resources/function-tests/function_el_2_in_2_out.occ create mode 100644 tss-occam-test-resources/src/main/resources/function-tests/function_el_2_in_3_out.occ create mode 100644 tss-occam-test-resources/src/main/resources/function-tests/function_el_2_in_4_out.occ create mode 100644 tss-occam-test-resources/src/main/resources/function-tests/function_el_3_in_1_out.occ create mode 100644 tss-occam-test-resources/src/main/resources/function-tests/function_el_3_in_2_out.occ create mode 100644 tss-occam-test-resources/src/main/resources/function-tests/function_el_3_in_3_out.occ create mode 100644 tss-occam-test-resources/src/main/resources/function-tests/function_el_3_in_4_out.occ create mode 100644 tss-occam-test-resources/src/main/resources/function-tests/function_el_4_in_1_out.occ create mode 100644 tss-occam-test-resources/src/main/resources/function-tests/function_el_4_in_2_out.occ create mode 100644 tss-occam-test-resources/src/main/resources/function-tests/function_el_4_in_3_out.occ create mode 100644 tss-occam-test-resources/src/main/resources/function-tests/function_el_4_in_4_out.occ create mode 100644 tss-occam-test-resources/src/main/resources/function-tests/function_expression_list.occ create mode 100644 tss-occam-test-resources/src/main/resources/function-tests/function_value_process.occ create mode 100644 tss-occam-test-resources/src/main/resources/function-tests/function_vp_0_in_1_out.occ create mode 100644 tss-occam-test-resources/src/main/resources/function-tests/function_vp_0_in_2_out.occ create mode 100644 tss-occam-test-resources/src/main/resources/function-tests/function_vp_0_in_3_out.occ create mode 100644 tss-occam-test-resources/src/main/resources/function-tests/function_vp_0_in_4_out.occ create mode 100644 tss-occam-test-resources/src/main/resources/function-tests/function_vp_1_in_1_out.occ create mode 100644 tss-occam-test-resources/src/main/resources/function-tests/function_vp_1_in_2_out.occ create mode 100644 tss-occam-test-resources/src/main/resources/function-tests/function_vp_1_in_3_out.occ create mode 100644 tss-occam-test-resources/src/main/resources/function-tests/function_vp_1_in_4_out.occ create mode 100644 tss-occam-test-resources/src/main/resources/function-tests/function_vp_2_in_1_out.occ create mode 100644 tss-occam-test-resources/src/main/resources/function-tests/function_vp_2_in_2_out.occ create mode 100644 tss-occam-test-resources/src/main/resources/function-tests/function_vp_2_in_3_out.occ create mode 100644 tss-occam-test-resources/src/main/resources/function-tests/function_vp_2_in_4_out.occ create mode 100644 tss-occam-test-resources/src/main/resources/function-tests/function_vp_3_in_1_out.occ create mode 100644 tss-occam-test-resources/src/main/resources/function-tests/function_vp_3_in_2_out.occ create mode 100644 tss-occam-test-resources/src/main/resources/function-tests/function_vp_3_in_3_out.occ create mode 100644 tss-occam-test-resources/src/main/resources/function-tests/function_vp_3_in_4_out.occ create mode 100644 tss-occam-test-resources/src/main/resources/function-tests/function_vp_4_in_1_out.occ create mode 100644 tss-occam-test-resources/src/main/resources/function-tests/function_vp_4_in_2_out.occ create mode 100644 tss-occam-test-resources/src/main/resources/function-tests/function_vp_4_in_3_out.occ create mode 100644 tss-occam-test-resources/src/main/resources/function-tests/function_vp_4_in_4_out.occ create mode 100644 tss-transputer-assembler-test/pom.xml create mode 100644 tss-transputer-assembler-test/src/test/java/uk/co/transputersystems/transputer/assembler/AssembleFileTest.java create mode 100644 tss-transputer-assembler/etc/tas create mode 100644 tss-transputer-assembler/pom.xml create mode 100644 tss-transputer-assembler/src/main/antlr4/uk/co/transputersystems/transputer/assembler/AssemblerExpression.g4 create mode 100644 tss-transputer-assembler/src/main/java/uk/co/transputersystems/transputer/assembler/Assembler.java create mode 100644 tss-transputer-assembler/src/main/java/uk/co/transputersystems/transputer/assembler/AssemblerApplication.java create mode 100644 tss-transputer-assembler/src/main/java/uk/co/transputersystems/transputer/assembler/Assembly.java create mode 100644 tss-transputer-assembler/src/main/java/uk/co/transputersystems/transputer/assembler/Instruction.java create mode 100644 tss-transputer-assembler/src/main/java/uk/co/transputersystems/transputer/assembler/InstructionType.java create mode 100644 tss-transputer-assembler/src/main/java/uk/co/transputersystems/transputer/assembler/Opcode.java create mode 100644 tss-transputer-assembler/src/main/java/uk/co/transputersystems/transputer/assembler/OpcodeType.java create mode 100644 tss-transputer-assembler/src/main/java/uk/co/transputersystems/transputer/assembler/config/AssemblerConfig.java create mode 100644 tss-transputer-assembler/src/main/java/uk/co/transputersystems/transputer/assembler/config/Connection.java create mode 100644 tss-transputer-assembler/src/main/java/uk/co/transputersystems/transputer/assembler/config/IOPin.java create mode 100644 tss-transputer-assembler/src/main/java/uk/co/transputersystems/transputer/assembler/config/Processor.java create mode 100644 tss-transputer-assembler/src/main/java/uk/co/transputersystems/transputer/assembler/expression/ExpressionEvaluator.java create mode 100644 tss-transputer-assembler/src/test/java/uk/co/transputersystems/transputer/assembler/AssemblerRegexTest.java create mode 100644 tss-transputer-assembler/src/test/java/uk/co/transputersystems/transputer/assembler/AssemblerTest.java create mode 100644 tss-transputer-assembler/src/test/java/uk/co/transputersystems/transputer/assembler/expression/ExpressionEvaluatorTest.java create mode 100644 tss-transputer-simulator-test/pom.xml create mode 100644 tss-transputer-simulator-test/src/test/java/uk/co/transputersystems/transputer/simulator/SimulateFileTest.java create mode 100644 tss-transputer-simulator/etc/tsim create mode 100644 tss-transputer-simulator/pom.xml create mode 100644 tss-transputer-simulator/src/main/antlr4/uk/co/transputersystems/transputer/simulator/DebuggerCommand.g4 create mode 100644 tss-transputer-simulator/src/main/java/uk/co/transputersystems/transputer/simulator/ErrorListener.java create mode 100644 tss-transputer-simulator/src/main/java/uk/co/transputersystems/transputer/simulator/Simulator.java create mode 100644 tss-transputer-simulator/src/main/java/uk/co/transputersystems/transputer/simulator/SimulatorApplication.java create mode 100644 tss-transputer-simulator/src/main/java/uk/co/transputersystems/transputer/simulator/SimulatorConfig.java create mode 100644 tss-transputer-simulator/src/main/java/uk/co/transputersystems/transputer/simulator/Transputer.java create mode 100644 tss-transputer-simulator/src/main/java/uk/co/transputersystems/transputer/simulator/TransputerConstants.java create mode 100644 tss-transputer-simulator/src/main/java/uk/co/transputersystems/transputer/simulator/TransputerHelpers.java create mode 100644 tss-transputer-simulator/src/main/java/uk/co/transputersystems/transputer/simulator/UnexpectedOverflowException.java create mode 100644 tss-transputer-simulator/src/main/java/uk/co/transputersystems/transputer/simulator/debugger/CommandExecutor.java create mode 100644 tss-transputer-simulator/src/main/java/uk/co/transputersystems/transputer/simulator/debugger/CommandResult.java create mode 100644 tss-transputer-simulator/src/main/java/uk/co/transputersystems/transputer/simulator/debugger/DebuggerRecordedState.java create mode 100644 tss-transputer-simulator/src/main/java/uk/co/transputersystems/transputer/simulator/debugger/NumberListParser.java create mode 100644 tss-transputer-simulator/src/main/java/uk/co/transputersystems/transputer/simulator/debugger/Process.java create mode 100644 tss-transputer-simulator/src/main/java/uk/co/transputersystems/transputer/simulator/debugger/ProcessStatus.java create mode 100644 tss-transputer-simulator/src/main/java/uk/co/transputersystems/transputer/simulator/models/InputLink.java create mode 100644 tss-transputer-simulator/src/main/java/uk/co/transputersystems/transputer/simulator/models/OutputLink.java create mode 100644 tss-transputer-simulator/src/main/java/uk/co/transputersystems/transputer/simulator/models/Priority.java create mode 100644 tss-transputer-simulator/src/main/java/uk/co/transputersystems/transputer/simulator/models/Registers.java create mode 100644 tss-transputer-simulator/src/main/java/uk/co/transputersystems/transputer/simulator/models/StatusRegister.java create mode 100644 tss-transputer-simulator/src/test/java/uk/co/transputersystems/transputer/simulator/DebuggerCommandParserTest.java create mode 100644 tss-transputer-simulator/src/test/java/uk/co/transputersystems/transputer/simulator/debugger/CommandExecutorTest.java create mode 100644 tss-transputer-utils/pom.xml create mode 100644 tss-transputer-utils/src/main/java/uk/co/transputersystems/transputer/utils/InteractivePrefix.java diff --git a/.gitignore b/.gitignore index 32858aa..dc98ffe 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,10 @@ +# ignore external occam files +*.ext.occ +# ignore compiled assembly code +*.auto.s +*.asm +### + *.class # Mobile Tools for Java (J2ME) @@ -10,3 +17,272 @@ # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml hs_err_pid* + + +# Created by .ignore support plugin (hsz.mobi) +### Eclipse template +*.pydevproject +.metadata +.gradle +bin/ +tmp/ +*.tmp +*.bak +*.swp +*~.nib +local.properties +.settings/ +.loadpath + +# Eclipse Core +.project + +# External tool builders +.externalToolBuilders/ + +# Locally stored "Eclipse launch configurations" +*.launch + +# CDT-specific +.cproject + +# JDT-specific (Eclipse Java Development Tools) +.classpath + +# Java annotation processor (APT) +.factorypath + +# PDT-specific +.buildpath + +# sbteclipse plugin +.target + +# TeXlipse plugin +.texlipse +### CMake template +CMakeCache.txt +CMakeFiles +CMakeScripts +cmake_install.cmake +install_manifest.txt +### Kate template +# Swap Files # +.*.kate-swp +.swp.* +### Windows template +# Windows image file caches +Thumbs.db +ehthumbs.db + +# Folder config file +Desktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msm +*.msp + +### OSX template +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk +### LibreOffice template +# LibreOffice locks +.~lock.*# +### SublimeText template +# cache files for sublime text +*.tmlanguage.cache +*.tmPreferences.cache +*.stTheme.cache + +# workspace files are user-specific +*.sublime-workspace + +# project files should be checked into the repository, unless a significant +# proportion of contributors will probably not be using SublimeText +# *.sublime-project + +# sftp configuration file +sftp-config.json + +# Word temporary +~$*.doc* + +# Excel temporary +~$*.xls* + +# Excel Backup File +*.xlk +### TextMate template +*.tmproj +*.tmproject +tmtags +### Emacs template +# -*- mode: gitignore; -*- +*~ +\#*\# +/.emacs.desktop +/.emacs.desktop.lock +*.elc +auto-save-list +tramp +.\#* + +# Org-mode +.org-id-locations +*_archive + +# flymake-mode +*_flymake.* + +# eshell files +/eshell/history +/eshell/lastdir + +# elpa packages +/elpa/ + +# reftex files +*.rel + +# AUCTeX auto folder +/auto/ + +# cask packages +.cask/ + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* +### Vim template +[._]*.s[a-w][a-z] +[._]s[a-w][a-z] +*.un~ +Session.vim +.netrwhist + +### JetBrains template +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio + +*.iml + +## Directory-based project format: +.idea/ +# if you remove the above rule, at least ignore the following: + +# User-specific stuff: +# .idea/workspace.xml +# .idea/tasks.xml +# .idea/dictionaries + +# Sensitive or high-churn files: +# .idea/dataSources.ids +# .idea/dataSources.xml +# .idea/sqlDataSources.xml +# .idea/dynamic.xml +# .idea/uiDesigner.xml + +# Gradle: +# .idea/gradle.xml +# .idea/libraries + +# Mongo Explorer plugin: +# .idea/mongoSettings.xml + +## File-based project format: +*.ipr +*.iws + +## Plugin-specific files: + +# IntelliJ +/out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +### Maven template +target/ +pom.xml.tag +pom.xml.releaseBackup +pom.xml.versionsBackup +pom.xml.next +release.properties +dependency-reduced-pom.xml +buildNumber.properties +.mvn/timing.properties +### C template +# Object files +*.o +*.ko +*.obj +*.elf + +# Precompiled Headers +*.gch +*.pch + +# Libraries +*.lib +*.a +*.la +*.lo + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib + +# Executables +*.exe +*.out +*.app +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ + +# Un-ignore the Maven wrapper +!maven-wrapper.jar +.vagrant + +# Virtualenv +.venv/ \ No newline at end of file diff --git a/.mvn/wrapper/maven-wrapper.jar b/.mvn/wrapper/maven-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..c6feb8bb6f76f2553e266ff8bf8867105154237e GIT binary patch literal 49519 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%0A$pwhjXzyA0ZzErH{1@M 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 literal 0 HcmV?d00001 diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000..eb91947 --- /dev/null +++ b/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1 @@ +distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.3.3/apache-maven-3.3.3-bin.zip \ No newline at end of file diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..9cd11f9 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,9 @@ +language: java +jdk: + - oraclejdk8 +notifications: + email: false + +cache: + directories: + - $HOME/.m2 \ No newline at end of file diff --git a/ASM Generator TODO.txt b/ASM Generator TODO.txt new file mode 100644 index 0000000..f76701b --- /dev/null +++ b/ASM Generator TODO.txt @@ -0,0 +1,3 @@ +InitChannel +LoadChannelRef +LoadPortRef diff --git a/README.md b/README.md new file mode 100644 index 0000000..967497f --- /dev/null +++ b/README.md @@ -0,0 +1,46 @@ +# TSS-COMS20805 + +[![Build Status](https://travis-ci.com/sammhicks/TSS-COMS20805.svg?token=dbgXCzPBz3EpuBEbnqMF&branch=master)](https://travis-ci.com/sammhicks/TSS-COMS20805) +[![Codacy Badge](https://api.codacy.com/project/badge/grade/90ae6f82c1e34063a3810125d65571ea)](https://www.codacy.com) + +The tss Occam Toolchain allows you to compile and assemble Occam 2.1 for the Transputer/OpenTransputer. It also includes a simulator for testing those programs. + +## Project status + +### Compiler + +* Handles most of the Occam 2.1 language +* No type checking +* Incomplete IO support + +### Assembler + +* Fully supports Transputer assembly +* Supports OpenTransputer channel configuration +* Produces binaries that run on the simulator +* Does not yet produce binaries that run directly on the Transputer or OpenTransputer hardware + +### Simulator + +* Supports most of the Transputer features +* Limited debugging support +* Supports multiple-Transputer execution and communication + +## Acknowledgements + +This project relies on a number of excellent libraries. + +* [ANTLR](http://www.antlr.org/) (BSD) +* [JUnit](http://www.junit.org/) (Eclipse Public License 1.0) +* [antlr-denter](https://github.com/yshavit/antlr-denter) (MIT) +* [gson](https://github.com/google/gson) (Apache 2.0) +* [AssertJ](http://joel-costigliola.github.io/assertj/) (Apache 2.0) +* [FindBugs](http://findbugs.sourceforge.net/) (LGPL) +* [jopt-simple](https://pholser.github.io/jopt-simple/) (MIT) +* [snakeyaml](https://bitbucket.org/asomov/snakeyaml) (Apache 2.0) + +### Other + +* Maven +* pegdown-doclet +* javafx-maven-plugin \ No newline at end of file diff --git a/assignment.s b/assignment.s new file mode 100644 index 0000000..4e9bbac --- /dev/null +++ b/assignment.s @@ -0,0 +1,14 @@ +init: +ajw -5 +ldc 1 +stl 4 +ldc 2 +stl 3 +ldc 3 +stl 2 +ldl 2 +stl 4 +ajw 5 +ret + + diff --git a/doc/TSILGenerator functions.md b/doc/TSILGenerator functions.md new file mode 100644 index 0000000..4fa9485 --- /dev/null +++ b/doc/TSILGenerator functions.md @@ -0,0 +1,374 @@ +## List of TSILGenerator functions + +*Ticked indicates function has been created but not necessarily completed.* + +* [ ] `visitAbbreviation_expression` +* [ ] `visitAbbreviation_name_channel` +* [ ] `visitAbbreviation_name_channel_list` +* [ ] `visitAbbreviation_name_port` +* [ ] `visitAbbreviation_name_timer` +* [ ] `visitAbbreviation_name_var` +* [ ] `visitAbbreviation_spec_channel` +* [ ] `visitAbbreviation_spec_channel_list` +* [ ] `visitAbbreviation_spec_expression` +* [ ] `visitAbbreviation_spec_port` +* [ ] `visitAbbreviation_spec_timer` +* [ ] `visitAbbreviation_spec_var` +* [ ] `visitActual_channel` +* [ ] `visitActual_expression` +* [ ] `visitActual_port` +* [ ] `visitActual_timer` +* [ ] `visitActual_variable` +* [ ] `visitAllocation` +* [ ] `visitAlternation_alternatives` +* [ ] `visitAlternation_replicator_alternative` +* [ ] `visitAlternative_alternation` +* [ ] `visitAlternative_bool_channel` +* [ ] `visitAlternative_channel` +* [ ] `visitAlternative_guarded` +* [ ] `visitAlternative_spec` +* [x] `visitAssignment` +* [x] `visitBase` +* [x] `visitBool` +* [ ] `visitCase_expression` +* [ ] `visitCase_input` +* [ ] `visitChannel_channel_expression` +* [ ] `visitChannel_expression_channel_type` +* [ ] `visitChannel_for_count` +* [ ] `visitChannel_from_base` +* [ ] `visitChannel_name` +* [ ] `visitChannel_type_protocol` +* [x] `visitChoice_conditional` +* [x] `visitChoice_guarded` +* [ ] `visitChoice_specification` +* [ ] `visitCompound_stmt_alternation` +* [ ] `visitCompound_stmt_case_input` +* [ ] `visitCompound_stmt_conditional` +* [ ] `visitCompound_stmt_loop` +* [ ] `visitCompound_stmt_parallel` +* [ ] `visitCompound_stmt_selection` +* [ ] `visitCompound_stmt_sequence` +* [ ] `visitCompound_stmt_spec_or_alloc_stmt` +* [x] `visitConditional_choices` +* [ ] `visitConditional_replicator` +* [ ] `visitConversion` +* [x] `visitCount` +* [x] `visitData_type_bool` +* [x] `visitData_type_byte` +* [x] `visitData_type_expr_data_type` +* [x] `visitData_type_int` +* [x] `visitData_type_int16` +* [x] `visitData_type_int32` +* [x] `visitData_type_int64` +* [x] `visitData_type_name` +* [x] `visitData_type_real32` +* [x] `visitData_type_real64` +* [x] `visitDeclaration` +* [ ] `visitDef_DATA_Name` +* [x] `visitDef_function_expression_list` +* [x] `visitDef_function_value_process` +* [x] `visitDef_PROC` +* [ ] `visitDef_PROTOCOL_NAME_INDENT` +* [ ] `visitDef_PROTOCOL_NAME_IS` +* [ ] `visitDef_specifier` +* [ ] `visitDef_specifier2` +* [ ] `visitDef_val` +* [ ] `visitDelayed_input` +* [x] `visitDyadic_operator` +* [ ] `visitExpression_conversion` +* [x] `visitExpression_dyadic_operator` +* [x] `visitExpression_list_expressions` +* [x] `visitExpression_list_function_call` +* [x] `visitExpression_monadic` +* [ ] `visitExpression_most_data_type` +* [x] `visitExpression_operand` +* [ ] `visitExpression_size_of` +* [ ] `visitField_name` +* [x] `visitFile_input` +* [x] `visitFormal` +* [x] `visitFunction_call` +* [x] `visitFunction_header` +* [ ] `visitGuarded_alternative` +* [x] `visitGuarded_choice` +* [ ] `visitGuard_bool_input_or_skip` +* [ ] `visitGuard_input` +* [ ] `visitInput_channel_input_items` +* [ ] `visitInput_channel_tagged_list` +* [ ] `visitInput_delayed_input` +* [ ] `visitInput_item_multiple_variables` +* [ ] `visitInput_item_variable` +* [ ] `visitInput_port_variable` +* [ ] `visitInput_timer_input` +* [x] `visitLiteral_integer` +* [x] `visitLiteral_byte` +* [ ] `visitLiteral_real` +* [x] `visitLiteral_true` +* [x] `visitLiteral_false` +* [x] `visitLoop` +* [x] `visitMonadic_operator` +* [ ] `visitOperand_bytesin` +* [x] `visitOperand_expression` +* [x] `visitOperand_literal` +* [x] `visitOperand_function_call` +* [ ] `visitOperand_offsetof` +* [ ] `visitOperand_operand_expression` +* [ ] `visitOperand_table` +* [ ] `visitOperand_value_process` +* [x] `visitOperand_variable` +* [ ] `visitOption_case_expression_stmt` +* [ ] `visitOption_spec_option` +* [ ] `visitOption_stmt` +* [ ] `visitOutputitem_multiple_expression` +* [ ] `visitOutputitem_single_expression` +* [ ] `visitOutput_channel_outputitems` +* [ ] `visitOutput_channel_tag_outputitems` +* [ ] `visitOutput_port_expression` +* [ ] `visitParallel_placedpar` +* [x] `visitParallel_pripar_replicator` +* [x] `visitParallel_pripar_suite` +* [ ] `visitPlacedpar_expression_stmt` +* [ ] `visitPlacedpar_placedpars` +* [ ] `visitPlacedpar_replicator_placedpar` +* [ ] `visitPort_name` +* [ ] `visitPort_port_base_count` +* [ ] `visitPort_port_count` +* [ ] `visitPort_port_expression` +* [ ] `visitPort_type_data_type` +* [ ] `visitPort_type_expression_port_type` +* [ ] `visitProc_instance` +* [ ] `visitProtocol` +* [x] `visitReplicator` +* [ ] `visitSelection` +* [ ] `visitSelector` +* [ ] `visitSequence_replicator` +* [x] `visitSequence_suite` +* [ ] `visitSequential_protocol` +* [ ] `visitSimple_protocol` +* [x] `visitSimple_stmt` +* [x] `visitSmall_stmt_assignment` +* [ ] `visitSmall_stmt_input` +* [ ] `visitSmall_stmt_output` +* [ ] `visitSmall_stmt_proc` +* [x] `visitSmall_stmt_skip` +* [ ] `visitSmall_stmt_stop` +* [x] `visitSpecificationAbrv` +* [x] `visitSpecificationDec` +* [x] `visitSpecificationDef` +* [ ] `visitSpecifier_channel_type` +* [x] `visitSpecifier_data_type` +* [ ] `visitSpecifier_expression_specifier` +* [ ] `visitSpecifier_port_type` +* [ ] `visitSpecifier_timer_type` +* [x] `visitStmt_compound_stmt` +* [x] `visitStmt_simple_stmt` +* [ ] `visitStructured_type` +* [x] `visitSuite` +* [ ] `visitTable_expressions` +* [ ] `visitTable_string` +* [ ] `visitTable_table_base_count` +* [ ] `visitTable_table_count` +* [ ] `visitTable_table_expression` +* [ ] `visitTag` +* [ ] `visitTagged_list` +* [ ] `visitTagged_protocol` +* [ ] `visitTimer_expression` +* [ ] `visitTimer_expression_timer_type` +* [ ] `visitTimer_input` +* [ ] `visitTimer_name` +* [ ] `visitTimer_timer_base_count` +* [ ] `visitTimer_timer_count` +* [ ] `visitTimer_type_timer` +* [x] `visitValue_process_specification` +* [x] `visitValue_process_stmt` +* [x] `visitVariable_list` +* [x] `visitVariable_name` +* [ ] `visitVariable_variable_base_count` +* [ ] `visitVariable_variable_count` +* [ ] `visitVariable_variable_expression` +* [ ] `visitVariant_specification_variant` +* [ ] `visitVariant_tagged_list_stmt` + +## Work Assignment + +| | Ed | Ross | John | Sam | +|-------------------------------------------|:-----:|:-----:|:-----:|:-----:| +| `visitAbbreviation_expression` | - | | | | +| `visitAbbreviation_name_channel` | - | | | | +| `visitAbbreviation_name_channel_list` | - | | | | +| `visitAbbreviation_name_port` | - | | | | +| `visitAbbreviation_name_timer` | - | | | | +| `visitAbbreviation_name_var` | - | | | | +| `visitAbbreviation_spec_channel` | - | | | | +| `visitAbbreviation_spec_channel_list` | - | | | | +| `visitAbbreviation_spec_expression` | - | | | | +| `visitAbbreviation_spec_port` | - | | | | +| `visitAbbreviation_spec_timer` | - | | | | +| `visitAbbreviation_spec_var` | - | | | | +| `visitActual_channel` | - | | | | +| `visitActual_expression` | - | | | | +| `visitActual_port` | - | | | | +| `visitActual_timer` | - | | | | +| `visitActual_variable` | - | | | | +| `visitAllocation` | | | - | | +| `visitAlternation_alternatives` | | - | | | +| `visitAlternation_replicator_alternative` | | - | | | +| `visitAlternative_alternation` | | - | | | +| `visitAlternative_bool_channel` | | - | | | +| `visitAlternative_channel` | | - | | | +| `visitAlternative_guarded` | | - | | | +| `visitAlternative_spec` | | - | | | +| `visitAssignment` | | - | | | +| `visitBase` | - | | | | +| `visitBool` | - | | | | +| `visitCase_expression` | | | - | | +| `visitCase_input` | | | - | | +| `visitChannel_channel_expression` | | | - | | +| `visitChannel_expression_channel_type` | | | - | | +| `visitChannel_for_count` | | | - | | +| `visitChannel_from_base` | | | - | | +| `visitChannel_name` | | | - | | +| `visitChannel_type_protocol` | | | - | | +| `visitChoice_conditional` | | | - | | +| `visitChoice_guarded` | | | - | | +| `visitChoice_specification` | | | - | | +| `visitCompound_stmt_alternation` | | - | | | +| `visitCompound_stmt_case_input` | | | - | | +| `visitCompound_stmt_conditional` | - | | | | +| `visitCompound_stmt_loop` | - | | | | +| `visitCompound_stmt_parallel` | - | | | | +| `visitCompound_stmt_selection` | - | | | | +| `visitCompound_stmt_sequence` | - | | | | +| `visitCompound_stmt_spec_or_alloc_stmt` | - | | | | +| `visitConditional_choices` | | | - | | +| `visitConditional_replicator` | | | - | | +| `visitConversion` | | | - | | +| `visitCount` | - | | | | +| `visitData_type_bool` | - | | | | +| `visitData_type_byte` | - | | | | +| `visitData_type_expr_data_type` | - | | | | +| `visitData_type_int` | - | | | | +| `visitData_type_int16` | - | | | | +| `visitData_type_int32` | - | | | | +| `visitData_type_int64` | - | | | | +| `visitData_type_name` | - | | | | +| `visitData_type_real32` | - | | | | +| `visitData_type_real64` | - | | | | +| `visitDeclaration` | - | | | | +| `visitDef_DATA_Name` | - | | | | +| `visitDef_data_type` | - | | | | +| `visitDef_data_type2` | - | | | | +| `visitDef_PROC` | | - | | | +| `visitDef_PROTOCOL_NAME_INDENT` | | - | | | +| `visitDef_PROTOCOL_NAME_IS` | | - | | | +| `visitDef_specifier` | - | | | | +| `visitDef_specifier2` | - | | | | +| `visitDef_val` | | | - | | +| `visitDelayed_input` | | | - | | +| `visitDyadic_operator` | | - | | | +| `visitExpression_conversion` | | - | | | +| `visitExpression_dyadic_operator` | | - | | | +| `visitExpression_list_expressions` | - | | | | +| `visitExpression_list_name` | | - | | | +| `visitExpression_monadic` | | - | | | +| `visitExpression_most_data_type` | | - | | | +| `visitExpression_operand` | | - | | | +| `visitExpression_size_of` | | - | | | +| `visitField_name` | - | | | | +| `visitFile_input` | - | | | | +| `visitFormal` | - | | | | +| `visitFunction_header` | - | | | | +| `visitGuarded_alternative` | | | - | | +| `visitGuarded_choice` | | | - | | +| `visitGuard_bool_input_or_skip` | | | - | | +| `visitGuard_input` | | | - | | +| `visitInput_channel_input_items` | | | - | | +| `visitInput_channel_tagged_list` | | | - | | +| `visitInput_delayed_input` | | | - | | +| `visitInput_item_multiple_variables` | | | - | | +| `visitInput_item_variable` | | | - | | +| `visitInput_port_variable` | | | - | | +| `visitInput_timer_input` | | | - | | +| `visitLiteral` | | - | | | +| `visitLoop` | - | | | | +| `visitMonadic_operator` | | - | | | +| `visitOperand_bytesin` | | - | | | +| `visitOperand_expression` | - | | | | +| `visitOperand_literal` | - | | | | +| `visitOperand_name_expressionlist` | | - | | | +| `visitOperand_offsetof` | | - | | | +| `visitOperand_operand_expression` | | - | | | +| `visitOperand_table` | | - | | | +| `visitOperand_value_process` | | - | | | +| `visitOperand_variable` | - | | | | +| `visitOption_case_expression_stmt` | | - | | | +| `visitOption_spec_option` | | - | | | +| `visitOption_stmt` | | - | | | +| `visitOutputitem_multiple_expression` | | | - | | +| `visitOutputitem_single_expression` | | | - | | +| `visitOutput_channel_outputitems` | | | - | | +| `visitOutput_channel_tag_outputitems` | | | - | | +| `visitOutput_port_expression` | | | - | | +| `visitParallel_placedpar` | | - | | | +| `visitParallel_pripar_replicator` | - | | | | +| `visitParallel_pripar_suite` | - | | | | +| `visitPlacedpar_expression_stmt` | | - | | | +| `visitPlacedpar_placedpars` | | - | | | +| `visitPlacedpar_replicator_placedpar` | | - | | | +| `visitPort_name` | | | - | | +| `visitPort_port_base_count` | | | - | | +| `visitPort_port_count` | | | - | | +| `visitPort_port_expression` | | | - | | +| `visitPort_type_data_type` | | | - | | +| `visitPort_type_expression_port_type` | | | - | | +| `visitProc_instance` | | | - | | +| `visitProtocol` | | - | | | +| `visitReplicator` | - | | | | +| `visitSelection` | | - | | | +| `visitSelector` | | - | | | +| `visitSequence_replicator` | | - | | | +| `visitSequence_suite` | | - | | | +| `visitSequential_protocol` | | - | | | +| `visitSimple_protocol` | | - | | | +| `visitSimple_stmt` | - | | | | +| `visitSmall_stmt_assignment` | - | | | | +| `visitSmall_stmt_input` | | - | | | +| `visitSmall_stmt_output` | | - | | | +| `visitSmall_stmt_proc` | | | | | +| `visitSmall_stmt_skip` | - | | | | +| `visitSmall_stmt_stop` | | | - | | +| `visitSpecificationAbrv` | - | | | | +| `visitSpecificationDec` | | - | | | +| `visitSpecificationDef` | | - | | | +| `visitSpecifier_channel_type` | - | | | | +| `visitSpecifier_data_type` | - | | | | +| `visitSpecifier_expression_specifier` | - | | | | +| `visitSpecifier_port_type` | - | | | | +| `visitSpecifier_timer_type` | - | | | | +| `visitStmt_compound_stmt` | - | | | | +| `visitStmt_simple_stmt` | - | | | | +| `visitStructured_type` | - | | | | +| `visitSuite` | - | | | | +| `visitTable_expressions` | - | | | | +| `visitTable_string` | - | | | | +| `visitTable_table_base_count` | - | | | | +| `visitTable_table_count` | - | | | | +| `visitTable_table_expression` | - | | | | +| `visitTag` | - | | | | +| `visitTagged_list` | - | | | | +| `visitTagged_protocol` | - | | | | +| `visitTimer_expression` | | | - | | +| `visitTimer_expression_timer_type` | | | - | | +| `visitTimer_input` | | | - | | +| `visitTimer_name` | | | - | | +| `visitTimer_timer_base_count` | | | - | | +| `visitTimer_timer_count` | | | - | | +| `visitTimer_type_timer` | | | - | | +| `visitValue_process_specification` | - | | | | +| `visitValue_process_stmt` | - | | | | +| `visitVariable_list` | - | | | | +| `visitVariable_name` | - | | | | +| `visitVariable_variable_base_count` | | - | | | +| `visitVariable_variable_count` | | - | | | +| `visitVariable_variable_expression` | | - | | | +| `visitVariant_specification_variant` | | - | | | +| `visitVariant_tagged_list_stmt` | | - | | | diff --git a/doc/metadata/Metadata Package Class Diagram.uml b/doc/metadata/Metadata Package Class Diagram.uml new file mode 100644 index 0000000..5ef0a79 --- /dev/null +++ b/doc/metadata/Metadata Package Class Diagram.uml @@ -0,0 +1,197 @@ + + + JAVA + eu.rossng.occam.metadata.LibraryInformation + + eu.rossng.occam.metadata.DataType + eu.rossng.occam.metadata.Abbreviation + eu.rossng.occam.metadata.ArrayDataType + eu.rossng.occam.metadata.Channel + eu.rossng.occam.metadata.Function + eu.rossng.occam.metadata.ArrayAbbreviation + eu.rossng.occam.metadata.Port + eu.rossng.occam.metadata.ChannelAbbreviation + eu.rossng.occam.Test + eu.rossng.occam.metadata.TimerAbbreviation + eu.rossng.occam.metadata.VariableAbbreviation + eu.rossng.occam.TSILGenerator + eu.rossng.occam.metadata.Scope + eu.rossng.occam.metadata.Field + eu.rossng.occam.metadata.Timer + eu.rossng.occam.metadata.LibraryInformation + eu.rossng.occam.metadata.FileInformation + eu.rossng.occam.metadata.RecordDataType + eu.rossng.occam.metadata.Variable + eu.rossng.occam.metadata.PrimitiveDataType + eu.rossng.occam.metadata.Argument + eu.rossng.occam.metadata.ValueAbbreviation + eu.rossng.occam.metadata.NamedDataType + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + All + public + + diff --git a/doc/metadata/Workspaces.md b/doc/metadata/Workspaces.md new file mode 100644 index 0000000..08b56db --- /dev/null +++ b/doc/metadata/Workspaces.md @@ -0,0 +1,130 @@ +# Workspaces + +--- + +## Workspaces in general + +### What is a workspace? + +A workspace is a block of memory for a process. It acts as the memory stack space for the process. It contains arguments, locals and temporaries (which result from overflow from the A, B and C registers being pushed to). + +A workspace is special in that its size is pre-calculated i.e. statically allocated at compile time. Its size is that of the size required for all the process' locals, arguments, temporaries and any child workspaces. + +For those familiar with modern languages and architectures, a workspace is most closely related to a stack frame. + +### When are workspaces created? + +A single, massive workspace is created for the main process when the processor starts. All other workspaces are created as chunks allocated from this. + +Child workspaces originate from creating a new process, which will require a new workspace. A new process may be created for a statement within a parallel. The new workspace is allocated as a block from the current workspace. + +This nested and statically allocated system of workspaces is also the reason recursive calls are not supported. + +### When are workspaces destroyed? + +When a process ends, the space for its workspaces becomes free for use again. Due to the way parallels are implemented, this can mean that space within a current workspace gets re-used for multiple child workspaces at different (sequential) times. + +--- + +## Workspaces in the compiler + +### What is a scope? + +A scope is a region of code for which a name operand exists. A named operand is a variable, channel, abbreviation, port or timer. Scopes form a tree structure as shown below: + +``` +File + | + | > Function + | | + | | > Scope + | | | + | | | > Scope + | | | | + | | | ... + | | | + | | | > Scope + | | | | + | | | ... + | | | + | | ... + | ... + | + | > Function + | | + | ... + ... +``` + +A single scope can only contain one named operand of a given name. Child scopes can *hide* a named opernad declared in a parent scope by declaring a named operand of the same name. The type of the hider operand need not be the same as that of the hidden named operand. + +### What is the relationship between a workspace and a scope? + +A workspace contains a flat list of arguments, locals and other workspaces. In this sense, it is what is commonly referred to as an environment. However, workspaces form a linked list so that a process can access a local variable from a parent process (sometimes referred to as procedure). + +A scope is associated with a single workspace. This means that the variables within that scope (but not necessarily its child scopes) reside within the specified workspace. A local variable (or argument) can be located in memory by knowing the current scope, and thus current workspace, and comparing that to the workspace for the scope which declared the variable. If the workspace is different, then the scope tree can be chased up from the current scope to the declaring scope, keeping track of how many workspaces are passed through. + +An example of the relationship between code, scopes and workspaces is shown below. (Note that this example is simplified from the metadata actually produced by the compiler. The compiler's metadata is more bloated.) + +``` +CODE | SCOPES | WORKSPACES +-------------------------------------------------------- +INT a : Scope Workspace 0 +SEQ | > a | + PAR | | + INT b : | > Scope | > Workspace 1 + b := 1 | - > b | : 'b' located in current workspace + SEQ | | + INT c : | > Scope | > Workspace 2 + a := 2 | | > c | : 'a' located in parent workspace + c := 3 | - | : 'c' located in current workspace + a := 4 - : 'a' located in current workspace + +| = Continuation of scope/workspace +- = Temrination of scope/workspace +: = Use of variable from a workspace +``` + +The following is a more complex example to demonstrate where new scopes and workspaces aren't always directly correlated: + +``` +CODE | SCOPES | WORKSPACES +-------------------------------------------------------- +INT a : Scope Workspace 0 +SEQ | > a | + REAL32 a : | > Scope | + PAR | | > a (hides) | + INT b : | | > Scope | > Workspace 1 + b := 1 | | - > b | : 'b' located in current workspace + SEQ | | | + INT c : | | > Scope | > Workspace 2 + a := 2 | | > c | : 'a' located in parent workspace (at 2nd location) + c := 3 | - | : 'c' located in current workspace + a := 4 - : 'a' located in current workspace (at 1st location) + +| = Continuation of scope/workspace +- = Temrination of scope/workspace +: = Use of variable from a workspace +``` + +To rewrite the scope/workspace tree above in unified form shows that multiple scopes can be part of the same workspace: + + ``` + Scope : Workspace 0 + | (Declares 'a' @ location 0 of workspace 0) + | + | > Scope : Workspace 0 + | (Declares 'a' @ location 1 of workspace 0) + | + | > Scope : Workspace 1 + | | (Declares 'b' at location 0 of workspace 1) + | + | > Scope : Workspace 2 + | (Declares 'c' at location 0 of workspace 2) + ``` + +### How are workspaces tracked? + +Workspaces are tracked using a unique identifier. Since workspaces need to be tracked within a function, the `Function` class (which extends `Scope`) handles all new workspace id generation. + +Following this, a scope always requests its parent generates a new workspace id for it except in `Function` where `generateWorkspaceId` is overridden and uses a simple counter to generate unique ids. \ No newline at end of file diff --git a/doc/occam-intermediate-language.md b/doc/occam-intermediate-language.md new file mode 100644 index 0000000..7b7a35e --- /dev/null +++ b/doc/occam-intermediate-language.md @@ -0,0 +1,99 @@ +# Occam Intermediate Language + +## Instructions + +* `add` Add +* `and` Bitwise And +* `beq` Branch if Equal to 0 +* `bgt` Branch if Greater Than 0 +* `bgte` Branch if Greater Than or Equal to 0 +* `blt` Branch if Less Than 0 +* `blte` Branch if Less Than or Equal to 0 +* `bneq` Branch if Not Equal to 0 +* `br` Unconditional Branch +* `brf` Branch if False +* `brt` Branch if True +* `call` Call +* `ceq` Compare Equal +* `cgt` Compare Greater Than +* `clt` Compare Less Than +* `div` Divide +* `endp` End Process +* `initprocs` Initialise Processes +* `label` Label +* `ldarg` Load Argument +* `ldarga` Load Argument's Address +* `ldloc` Load Local +* `ldloca` Load Local's Address +* `ldvar` Load Variable +* `ldvara` Load Variable's Address +* `mod` Modulo +* `mul` Multiply +* `neg` Negate +* `not` Bitwise Not +* `or` Bitwise Or +* `pop` Pop value from stack +* `loop` Loop +* `ret` Return +* `rotl` Left Rotate +* `rotr` Right Rotate +* `sar` Arithmetic Right Shift +* `starg` Store Argument +* `startp` Start Process +* `stloc` Store Local +* `stvar` Store Variable +* `shl` Logical Left Shift +* `shr` Logical Right Shift +* `sub` Subtract +* `xor` Bitwise Xor + +## Example Occam Program + +```Occam +PROC init () + INT x, y: locals + SEQ sequential IL ops (blocks) + my.function (x+1) function call, arguments + x := 4 asignment of locals + y := (x+1) loading locals, binary operations + CHAN OF INT c: channel declaration + PAR parallel IL ops (blocks) + some.procedure (x,y,c) procedure call, arguments including channel + another.procedure (c) + y := 5 end of parallel ops +``` + +## Instruction Specifications + +### `initprocs` Initialise Processes + +* Initialises the stack ready for the specified number of processes to be executed (number must include the current process if an endp instruction will be executed for the current process) and with the specified continuation address for after all the processes (including the current process) have completed. +* Metadata: + * `numProcesses` : The number of processes executing in parallel (including the current process and any proceses that will be started.) + * `continueILOpID` : The ID of the IL op the current process should continue executing at after `numProcesses` `endp` instructions have been executed. + +---- + +### `endp` End Process + +* Terminates the current process and continues a parent process if it is no longer waiting on any other children. +* Metadata: + * `creatorILOpID` : The ID of the `startp` IL op which started the process or `initprocs` IL op which initialised the number of processes to wait on. + +---- + +### `label` Label + +* Represents a label which can be used for calls etc. The label is preferably human readable, otherwise it is preferable to use the next IL op's (or a SKIP IL op's) ID. +* Metadata: + * `label` The label name. + * `isGlobal` Whether the label is accssible outside of the file or not. + +---- + +### `startp` Start Process + +* Starts a new process at the specified instruction. +* Metadata: + * `firstILOpID` : The ID of the first IL op of the new process + * `newPriority` : The priority of the new process. Use Current to indicate the priority should equal the current process' priority. diff --git a/doc/simulator.md b/doc/simulator.md new file mode 100644 index 0000000..65a0f2a --- /dev/null +++ b/doc/simulator.md @@ -0,0 +1,91 @@ +# Simulator + +## Debugger commands + +``: the id of a Transputer +``: a memory address. Can be specified as decimal or as hex prepended by `0x` +``: a breakpoint identifier + +### `help` + +Display a list of the available commands. + +### `transputers` + +Display a list of the transputers currently being simulated. + +### `{, } x [/Nuf] ` + +Examine the memory at the provided address. + +#### Flags + +##### N + +Decimal number. Number of units of memory to examine. + +##### u + +Size of units to examine. + +* `b` bytes +* `h` halfwords (two bytes) +* `w` words (four bytes) +* `g` giant words (eight bytes) + +##### f + +Format for printing the units. + +* `i` instruction +* `x` hexadecimal +* `d` decimal +* `o` octal +* `a` address +* `c` character + + +### `{, } info mem` + +Print information about memory used during execution so far. + +### `{, } info reg` + +Print basic register information. + +### `{, } info s-reg` + +Print information about the s registers. + +### `{, } info c-reg` + +Print information about the c registers. + +### `{, } info link` + +Print information about the Transputer links. + +### `{, } info break` + +Print information about the Transputers' breakpoints. + +### `{, } info instruction` + +Print information about the next instruction to be executed on the specified Transputers. + +### `{, } break ` + +Print information about the Transputer links. + +### `{, } delete ` + +Delete the specified breakpoint. + +### `step` + +Execute the next instruction. + +### `continue` + +Continue executing until a breakpoint is hit. + diff --git a/doc/transputer-assembler.md b/doc/transputer-assembler.md new file mode 100644 index 0000000..76b3357 --- /dev/null +++ b/doc/transputer-assembler.md @@ -0,0 +1,135 @@ +# Assembler + +This document defines the assembly language accepted by our assembler. + +## EBNF Grammar + +``` +assembly file = { line , newline } ; + +line = [ label , { space } , ":" ] , { space } , [ code ] , space , { space } , [ comment ] ; + +code = opcode , [ space , { space } , operand ] + | "#data" , space , { space } , digit , { digit } + | "#chan" , space , { space } , ( letter | digit ) , { letter | digit } ; + +label = ( letter | digit | label symbol ) , { letter | digit | label symbol } ; + +operand = operand atom , [ binary operator , operand atom ] ; + +operand atom = number + | label + | "$" + | "(" , operand , ")" ; + +comment = "--" , [ space , { character | space } ] ; + +newline = "\n" | "\r" | "\r\n" ; + +character = letter | digit | symbol ; + +letter = uppercase letter | lowercase letter + +uppercase letter = "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" + | "J" | "K" | "L" | "M" | "N" | "O" | "P" | "Q" | "R" + | "S" | "T" | "U" | "V" | "W" | "X" | "Y" | "Z" ; + +lowercase letter = "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" + | "j" | "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r" + | "s" | "t" | "u" | "v" | "w" | "x" | "y" | "z" ; + +digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ; + +number = [ "-" ], digit, { digit } ; + +symbol = "[" | "]" | "{" | "}" | "(" | ")" | "<" | ">" | "'" | '"' + | "=" | "|" | "." | "," | ";" | "_" ; + +label symbol = "~" | "_" | "." ; + +binary operator = "+" | "-" | "*" ; + +space = " " | "\t" ; + +indent = " " | "\t" ; + +``` + +## Directives + +### #data + +Expands to the specified number of **words** of space, filled with zeros. + +#### Example + +``` +#data 1 +``` + +Produces (hex): +``` +00 +00 +00 +00 +``` +on a 32-bit system or +``` +00 +00 +00 +00 +00 +00 +00 +00 +``` +on a 64-bit system. + +### #chan + +A `#chan` directive takes the form `#chan channelname`, where `channelname` is the name of a channel specified in the config yaml file supplied to the assembler. + +This is expanded to a `ldc` instruction by the assembler, with the operand equal to the address of the named channel. + +TODO: document the config format + +### #data + +A `#data` directive takes the form `#data numbytes`, where `numbytes` is a positive integer specifying the number of bytes of zeros to be allocated at that position. + +## Labels + +Labels may consist of letters, numbers, underscores and tildes. + +### Init + +The assembly must contain an `init:` label to mark where execution begins. + +### $X + +`$X` in a label operand denotes the *relative address from the start of the file* of the start of the instruction after `X` instructions from the current instruction. Negative counts (i.e. negative `X`) is not permitted and any count which refers to an instruction beyond the end of the file (i.e. which does not exist) is not permitted. Use of either will result in an error. `$C` provides the address of the start of the current instruction (as opposed to the address of the end of the current instruction, provided by `$0`). + +When counting, lines that contain only labels or comments are ignored. Any executable instruction (e.g. `ldc 5`, `confio`) counts as a single instruction. Any directive (`#chan`, `#data`) counts as a single instruction. + +## Example + +``` +L0: -- section label +init: + ldc 10 + stl 0 + ldl 0 + call DECREMENT-$C + ldl -3 + stl 0 + j END-$0 +DECREMENT: ajw -0 + ldl 1 + adc -1 + stl 1 + ajw 0 + ret +END: -- exit program +``` diff --git a/mvnw b/mvnw new file mode 100644 index 0000000..a89f8c9 --- /dev/null +++ b/mvnw @@ -0,0 +1,234 @@ +#!/usr/bin/env bash +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Maven2 Start Up Batch script +# +# Required ENV vars: +# ------------------ +# JAVA_HOME - location of a JDK home dir +# +# Optional ENV vars +# ----------------- +# M2_HOME - location of maven2's installed home dir +# MAVEN_OPTS - parameters passed to the Java VM when running Maven +# e.g. to debug Maven itself, use +# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +# MAVEN_SKIP_RC - flag to disable loading of mavenrc files +# ---------------------------------------------------------------------------- + +if [ -z "$MAVEN_SKIP_RC" ] ; then + + if [ -f /etc/mavenrc ] ; then + . /etc/mavenrc + fi + + if [ -f "$HOME/.mavenrc" ] ; then + . "$HOME/.mavenrc" + fi + +fi + +# OS specific support. $var _must_ be set to either true or false. +cygwin=false; +darwin=false; +mingw=false +case "`uname`" in + CYGWIN*) cygwin=true ;; + MINGW*) mingw=true;; + Darwin*) darwin=true + # + # Look for the Apple JDKs first to preserve the existing behaviour, and then look + # for the new JDKs provided by Oracle. + # + if [ -z "$JAVA_HOME" ] && [ -L /System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK ] ; then + # + # Apple JDKs + # + export JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK/Home + fi + + if [ -z "$JAVA_HOME" ] && [ -L /System/Library/Java/JavaVirtualMachines/CurrentJDK ] ; then + # + # Apple JDKs + # + export JAVA_HOME=/System/Library/Java/JavaVirtualMachines/CurrentJDK/Contents/Home + fi + + if [ -z "$JAVA_HOME" ] && [ -L "/Library/Java/JavaVirtualMachines/CurrentJDK" ] ; then + # + # Oracle JDKs + # + export JAVA_HOME=/Library/Java/JavaVirtualMachines/CurrentJDK/Contents/Home + fi + + if [ -z "$JAVA_HOME" ] && [ -x "/usr/libexec/java_home" ]; then + # + # Apple JDKs + # + export JAVA_HOME=`/usr/libexec/java_home` + fi + ;; +esac + +if [ -z "$JAVA_HOME" ] ; then + if [ -r /etc/gentoo-release ] ; then + JAVA_HOME=`java-config --jre-home` + fi +fi + +if [ -z "$M2_HOME" ] ; then + ## resolve links - $0 may be a link to maven's home + PRG="$0" + + # need this for relative symlinks + while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG="`dirname "$PRG"`/$link" + fi + done + + saveddir=`pwd` + + M2_HOME=`dirname "$PRG"`/.. + + # make it fully qualified + M2_HOME=`cd "$M2_HOME" && pwd` + + cd "$saveddir" + # echo Using m2 at $M2_HOME +fi + +# For Cygwin, ensure paths are in UNIX format before anything is touched +if $cygwin ; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --unix "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --unix "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --unix "$CLASSPATH"` +fi + +# For Migwn, ensure paths are in UNIX format before anything is touched +if $mingw ; then + [ -n "$M2_HOME" ] && + M2_HOME="`(cd "$M2_HOME"; pwd)`" + [ -n "$JAVA_HOME" ] && + JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" + # TODO classpath? +fi + +if [ -z "$JAVA_HOME" ]; then + javaExecutable="`which javac`" + if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then + # readlink(1) is not available as standard on Solaris 10. + readLink=`which readlink` + if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then + if $darwin ; then + javaHome="`dirname \"$javaExecutable\"`" + javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" + else + javaExecutable="`readlink -f \"$javaExecutable\"`" + fi + javaHome="`dirname \"$javaExecutable\"`" + javaHome=`expr "$javaHome" : '\(.*\)/bin'` + JAVA_HOME="$javaHome" + export JAVA_HOME + fi + fi +fi + +if [ -z "$JAVACMD" ] ; then + if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + else + JAVACMD="`which java`" + fi +fi + +if [ ! -x "$JAVACMD" ] ; then + echo "Error: JAVA_HOME is not defined correctly." >&2 + echo " We cannot execute $JAVACMD" >&2 + exit 1 +fi + +if [ -z "$JAVA_HOME" ] ; then + echo "Warning: JAVA_HOME environment variable is not set." +fi + +CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher + +# For Cygwin, switch paths to Windows format before running java +if $cygwin; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --path --windows "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --windows "$CLASSPATH"` +fi + +# traverses directory structure from process work directory to filesystem root +# first directory with .mvn subdirectory is considered project base directory +find_maven_basedir() { + local basedir=$(pwd) + local wdir=$(pwd) + while [ "$wdir" != '/' ] ; do + if [ -d "$wdir"/.mvn ] ; then + basedir=$wdir + break + fi + wdir=$(cd "$wdir/.."; pwd) + done + echo "${basedir}" +} + +# concatenates all lines of a file +concat_lines() { + if [ -f "$1" ]; then + echo "$(tr -s '\n' ' ' < "$1")" + fi +} + +export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-$(find_maven_basedir)} +MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" + +# Provide a "standardized" way to retrieve the CLI args that will +# work with both Windows and non-Windows executions. +MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" +export MAVEN_CMD_LINE_ARGS + +WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +exec "$JAVACMD" \ + $MAVEN_OPTS \ + -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ + "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ + ${WRAPPER_LAUNCHER} $MAVEN_CMD_LINE_ARGS + diff --git a/mvnw-custom-java b/mvnw-custom-java new file mode 100644 index 0000000..0fb1954 --- /dev/null +++ b/mvnw-custom-java @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +# JAVA_HOME must be set the the location of the Java 8 JDK +export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64/ + +# run the maven script using the above JAVA_HOME +./mvnw $@ \ No newline at end of file diff --git a/mvnw.cmd b/mvnw.cmd new file mode 100644 index 0000000..0010480 --- /dev/null +++ b/mvnw.cmd @@ -0,0 +1,145 @@ +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Maven2 Start Up Batch script +@REM +@REM Required ENV vars: +@REM JAVA_HOME - location of a JDK home dir +@REM +@REM Optional ENV vars +@REM M2_HOME - location of maven2's installed home dir +@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands +@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending +@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven +@REM e.g. to debug Maven itself, use +@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files +@REM ---------------------------------------------------------------------------- + +@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' +@echo off +@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' +@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% + +@REM set %HOME% to equivalent of $HOME +if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") + +@REM Execute a user defined script before this one +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre +@REM check for pre script, once with legacy .bat ending and once with .cmd ending +if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" +if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" +:skipRcPre + +@setlocal + +set ERROR_CODE=0 + +@REM To isolate internal variables from possible post scripts, we use another setlocal +@setlocal + +@REM ==== START VALIDATION ==== +if not "%JAVA_HOME%" == "" goto OkJHome + +echo. +echo Error: JAVA_HOME not found in your environment. >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +:OkJHome +if exist "%JAVA_HOME%\bin\java.exe" goto init + +echo. +echo Error: JAVA_HOME is set to an invalid directory. >&2 +echo JAVA_HOME = "%JAVA_HOME%" >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +@REM ==== END VALIDATION ==== + +:init + +set MAVEN_CMD_LINE_ARGS=%MAVEN_CONFIG% %* + +@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". +@REM Fallback to current working directory if not found. + +set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% +IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir + +set EXEC_DIR=%CD% +set WDIR=%EXEC_DIR% +:findBaseDir +IF EXIST "%WDIR%"\.mvn goto baseDirFound +cd .. +IF "%WDIR%"=="%CD%" goto baseDirNotFound +set WDIR=%CD% +goto findBaseDir + +:baseDirFound +set MAVEN_PROJECTBASEDIR=%WDIR% +cd "%EXEC_DIR%" +goto endDetectBaseDir + +:baseDirNotFound +set MAVEN_PROJECTBASEDIR=%EXEC_DIR% +cd "%EXEC_DIR%" + +:endDetectBaseDir + +IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig + +@setlocal EnableExtensions EnableDelayedExpansion +for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a +@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% + +:endReadAdditionalConfig + +SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" + +set WRAPPER_JAR=""%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"" +set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CMD_LINE_ARGS% +if ERRORLEVEL 1 goto error +goto end + +:error +set ERROR_CODE=1 + +:end +@endlocal & set ERROR_CODE=%ERROR_CODE% + +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost +@REM check for post script, once with legacy .bat ending and once with .cmd ending +if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" +if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" +:skipRcPost + +@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' +if "%MAVEN_BATCH_PAUSE%" == "on" pause + +if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% + +exit /B %ERROR_CODE% diff --git a/tss-occam-compiler-test/pom.xml b/tss-occam-compiler-test/pom.xml new file mode 100644 index 0000000..e22d981 --- /dev/null +++ b/tss-occam-compiler-test/pom.xml @@ -0,0 +1,113 @@ + + 4.0.0 + + uk.co.transputersystems + tss-occam-compiler-test + 1.0-SNAPSHOT + + jar + tss-occam-compiler-test + + + UTF-8 + + + + + junit + junit + 4.12 + + + + org.assertj + assertj-core + 3.3.0 + test + + + + com.google.code.findbugs + jsr305 + 2.0.1 + + + + uk.co.transputersystems + tss-occam-compiler + 1.0-SNAPSHOT + + + + uk.co.transputersystems + tss-occam-test-resources + 1.0-SNAPSHOT + + + + + + ${project.basedir}/src/test/resources + + + ${project.build.directory}/maven-shared-archive-resources + + **/*.occ + + + + install + + + org.apache.maven.plugins + maven-surefire-plugin + 2.19.1 + + 0 + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.5.1 + + 1.8 + 1.8 + + + + maven-remote-resources-plugin + 1.5 + + + + process + + + + uk.co.transputersystems:tss-occam-test-resources:1.0-SNAPSHOT + + + + + + + maven-javadoc-plugin + 2.10.3 + + ch.raffael.doclets.pegdown.PegdownDoclet + + ch.raffael.pegdown-doclet + pegdown-doclet + 1.2.1 + + true + + + + + + + \ No newline at end of file diff --git a/tss-occam-compiler-test/src/test/java/uk/co/transputersystems/occam/ParserTest.java b/tss-occam-compiler-test/src/test/java/uk/co/transputersystems/occam/ParserTest.java new file mode 100644 index 0000000..586f91c --- /dev/null +++ b/tss-occam-compiler-test/src/test/java/uk/co/transputersystems/occam/ParserTest.java @@ -0,0 +1,55 @@ +package uk.co.transputersystems.occam; + +import org.antlr.v4.runtime.tree.ParseTree; +import org.junit.Test; + +import java.io.File; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.Arrays; +import java.util.stream.Stream; + +public class ParserTest { +/* + @Test + public void testParsingFiles() { + File dir; + URL url = getClass().getResource("feature-tests"); + try { + dir = new File(url.toURI()); + } catch(URISyntaxException e) { + dir = new File(url.getPath()); + } + + OccamCompiler compiler = new OccamCompiler(); + ErrorListener errorListener = new ErrorListener(); + + Stream parseTrees = Arrays.stream(dir.listFiles((f, n) -> n.endsWith(".occ"))) + .sorted((f1, f2) -> f1.getName().compareTo(f2.getName())) + .map(f -> compiler.makeParseTree(f, OccamParser::file_input, errorListener)); + + assert(parseTrees.allMatch(t -> t != null)); + assert(errorListener.errors == 0); + } + + @Test + public void testParsingFunctionFiles() { + File dir; + URL url = getClass().getResource("function-tests"); + try { + dir = new File(url.toURI()); + } catch(URISyntaxException e) { + dir = new File(url.getPath()); + } + + OccamCompiler compiler = new OccamCompiler(); + ErrorListener errorListener = new ErrorListener(); + + Stream parseTrees = Arrays.stream(dir.listFiles((f, n) -> n.endsWith(".occ"))) + .sorted((f1, f2) -> f1.getName().compareTo(f2.getName())) + .map(f -> compiler.makeParseTree(f, OccamParser::file_input, errorListener)); + + assert(parseTrees.allMatch(t -> t != null)); + assert(errorListener.errors == 0); + }*/ +} diff --git a/tss-occam-compiler-test/src/test/java/uk/co/transputersystems/occam/TSILGeneratorTest.java b/tss-occam-compiler-test/src/test/java/uk/co/transputersystems/occam/TSILGeneratorTest.java new file mode 100644 index 0000000..a347d73 --- /dev/null +++ b/tss-occam-compiler-test/src/test/java/uk/co/transputersystems/occam/TSILGeneratorTest.java @@ -0,0 +1,480 @@ +package uk.co.transputersystems.occam; + +import uk.co.transputersystems.occam.il.ILBlock; +import uk.co.transputersystems.occam.il.ILOp; +import uk.co.transputersystems.occam.metadata.LibraryInformation; +import org.antlr.v4.runtime.tree.ParseTree; +import org.junit.Ignore; +import org.junit.Test; + +import java.io.IOException; +import java.io.InputStream; +import java.io.PrintWriter; +import java.util.List; +import java.util.UUID; + +import static org.junit.Assert.assertTrue; + +public class TSILGeneratorTest { + + public InputStream getResource(String name) { + return getClass().getResourceAsStream(name); + } + + /** + * Given a file, attempt to parse and compile it to TSIL. + * @param file The file to be compiled + * @return true if the compilation appears to have succeeded, otherwise false. + */ + public boolean testCompilingFile(InputStream file, String filePath, String fileName) { + return testCompilingFile(file, filePath, fileName, true); + } + /** + * Given a file, attempt to parse and compile it to TSIL. Checks that the + * compiled code is not null or empty. + * TODO: find a way to test the output other than checking nullity + * @param inputStream The file to be compiled + * @param verbose Whether to print debug output or not. + * @return true if the compilation appears to have succeeded, otherwise false. + */ + public boolean testCompilingFile(InputStream inputStream, String filePath, String fileName, boolean verbose) { + ErrorListener errorListener = new ErrorListener(); + OccamCompiler compiler = new OccamCompiler(); + + PrintWriter out = new PrintWriter(System.out); + + if (verbose) { + out.println("TEST: " + inputStream); + } + + ParseTree tree = compiler.makeParseTree(inputStream, OccamParser::file_input, errorListener); + + if (verbose) { + compiler.printParseTree(out, tree); + } + + List>> intermediate = compiler.generateTSIL(new TSILGenerator(new LibraryInformation("TEST")), tree, filePath, fileName); + + assertTrue(intermediate != null); + assertTrue(intermediate.size() > 0); + + if (verbose) { + // Convert UUID IL to sequential integer-labelled IL + List>> intermediateRef = compiler.generateReferencedTSIL(new ReferencedTSILGenerator<>(), intermediate); + + try { + compiler.writeDivider(out); + for (ILBlock block : intermediateRef) { + out.println(block.toString()); + } + compiler.writeDivider(out); + out.flush(); + } catch (IOException ex) { + out.println(ex.toString()); + } + } + + return true; + } + + @Ignore("Not yet fully implemented") + @Test + public void testArrays() { + String path = "/feature-tests/array.occ"; + assertTrue(testCompilingFile(getResource(path), path, "array.occ")); + } + + @Ignore("Not yet fully implemented") + @Test + public void testArraySegments() { + String path = "/feature-tests/array_segment.occ"; + assertTrue(testCompilingFile(getResource(path), path, "array_segment.occ")); + } + + @Test + public void testAssignment() { + String path = "/feature-tests/assignment.occ"; + assertTrue(testCompilingFile(getResource(path), path, "assignment.occ")); + } + + @Test + public void testByteLiterals() { + String path = "/feature-tests/byte_literal.occ"; + assertTrue(testCompilingFile(getResource(path), path, "byte_literal.occ")); + } + + @Test + public void testChannels() { + String path = "/feature-tests/channels.occ"; + assertTrue(testCompilingFile(getResource(path), path, "channels.occ")); + } + + @Test + public void testConditionals() { + String path = "/feature-tests/conditional.occ"; + assertTrue(testCompilingFile(getResource(path), path, "conditional.occ")); + } + + @Test + public void testDeclarations() { + String path = "/feature-tests/declarations.occ"; + assertTrue(testCompilingFile(getResource(path), path, "declarations.occ")); + } + + @Test + public void testDyadicExpressions() { + String path = "/feature-tests/dyadic_expression.occ"; + assertTrue(testCompilingFile(getResource(path), path, "dyadic_expression.occ")); + } + + @Test + public void testNestedExpressionFeatures() { + String path = "/feature-tests/expression_features_nested.occ"; + assertTrue(testCompilingFile(getResource(path), path, "expression_features_nested.occ")); + } + + @Test + public void testFunctionsOfExpressionList() { + String path = "/function-tests/function_expression_list.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_expression_list.occ")); + } + + @Test + public void testFunctionsOfValueProcess() { + String path = "/function-tests/function_value_process.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_value_process.occ")); + } + + @Test + public void testFunctionsVp0In1Out() { + String path = "/function-tests/function_vp_0_in_1_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_vp_0_in_1_out.occ")); + } + + @Test + public void testFunctionsVp0In2Out() { + String path = "/function-tests/function_vp_0_in_2_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_vp_0_in_2_out.occ")); + } + + @Test + public void testFunctionsVp0In3Out() { + String path = "/function-tests/function_vp_0_in_3_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_vp_0_in_3_out.occ")); + } + + @Test + public void testFunctionsVp0In4Out() { + String path = "/function-tests/function_vp_0_in_4_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_vp_0_in_4_out.occ")); + } + + @Test + public void testFunctionsVp1In1Out() { + String path = "/function-tests/function_vp_1_in_1_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_vp_1_in_1_out.occ")); + } + + @Test + public void testFunctionsVp1In2Out() { + String path = "/function-tests/function_vp_1_in_2_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_vp_1_in_2_out.occ")); + } + + @Test + public void testFunctionsVp1In3Out() { + String path = "/function-tests/function_vp_1_in_3_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_vp_1_in_3_out.occ")); + } + + @Test + public void testFunctionsVp1In4Out() { + String path = "/function-tests/function_vp_1_in_4_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_vp_1_in_4_out.occ")); + } + + @Test + public void testFunctionsVp2In1Out() { + String path = "/function-tests/function_vp_2_in_1_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_vp_2_in_1_out.occ")); + } + + @Test + public void testFunctionsVp2In2Out() { + String path = "/function-tests/function_vp_2_in_2_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_vp_2_in_2_out.occ")); + } + + @Test + public void testFunctionsVp2In3Out() { + String path = "/function-tests/function_vp_2_in_3_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_vp_2_in_3_out.occ")); + } + + @Test + public void testFunctionsVp2In4Out() { + String path = "/function-tests/function_vp_2_in_4_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_vp_2_in_4_out.occ")); + } + + @Test + public void testFunctionsVp3In1Out() { + String path = "/function-tests/function_vp_3_in_1_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_vp_3_in_1_out.occ")); + } + + @Test + public void testFunctionsVp3In2Out() { + String path = "/function-tests/function_vp_3_in_2_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_vp_3_in_2_out.occ")); + } + + @Test + public void testFunctionsVp3In3Out() { + String path = "/function-tests/function_vp_3_in_3_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_vp_3_in_3_out.occ")); + } + + @Test + public void testFunctionsVp3In4Out() { + String path = "/function-tests/function_vp_3_in_4_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_vp_3_in_4_out.occ")); + } + + @Test + public void testFunctionsVp4In1Out() { + String path = "/function-tests/function_vp_4_in_1_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_vp_4_in_1_out.occ")); + } + + @Test + public void testFunctionsVp4In2Out() { + String path = "/function-tests/function_vp_4_in_2_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_vp_4_in_2_out.occ")); + } + + @Test + public void testFunctionsVp4In3Out() { + String path = "/function-tests/function_vp_4_in_3_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_vp_4_in_3_out.occ")); + } + + @Test + public void testFunctionsVp4In4Out() { + String path = "/function-tests/function_vp_4_in_4_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_vp_4_in_4_out.occ")); + } + + @Test + public void testFunctionsEl0In1Out() { + String path = "/function-tests/function_el_0_in_1_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_el_0_in_1_out.occ")); + } + + @Test + public void testFunctionsEl0In2Out() { + String path = "/function-tests/function_el_0_in_2_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_el_0_in_2_out.occ")); + } + + @Test + public void testFunctionsEl0In3Out() { + String path = "/function-tests/function_el_0_in_3_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_el_0_in_3_out.occ")); + } + + @Test + public void testFunctionsEl0In4Out() { + String path = "/function-tests/function_el_0_in_4_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_el_0_in_4_out.occ")); + } + + @Test + public void testFunctionsEl1In1Out() { + String path = "/function-tests/function_el_1_in_1_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_el_1_in_1_out.occ")); + } + + @Test + public void testFunctionsEl1In2Out() { + String path = "/function-tests/function_el_1_in_2_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_el_1_in_2_out.occ")); + } + + @Test + public void testFunctionsEl1In3Out() { + String path = "/function-tests/function_el_1_in_3_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_el_1_in_3_out.occ")); + } + + @Test + public void testFunctionsEl1In4Out() { + String path = "/function-tests/function_el_1_in_4_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_el_1_in_4_out.occ")); + } + + @Test + public void testFunctionsEl2In1Out() { + String path = "/function-tests/function_el_2_in_1_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_el_2_in_1_out.occ")); + } + + @Test + public void testFunctionsEl2In2Out() { + String path = "/function-tests/function_el_2_in_2_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_el_2_in_2_out.occ")); + } + + @Test + public void testFunctionsEl2In3Out() { + String path = "/function-tests/function_el_2_in_3_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_el_2_in_3_out.occ")); + } + + @Test + public void testFunctionsEl2In4Out() { + String path = "/function-tests/function_el_2_in_4_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_el_2_in_4_out.occ")); + } + + @Test + public void testFunctionsEl3In1Out() { + String path = "/function-tests/function_el_3_in_1_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_el_3_in_1_out.occ")); + } + + @Test + public void testFunctionsEl3In2Out() { + String path = "/function-tests/function_el_3_in_2_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_el_3_in_2_out.occ")); + } + + @Test + public void testFunctionsEl3In3Out() { + String path = "/function-tests/function_el_3_in_3_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_el_3_in_3_out.occ")); + } + + @Test + public void testFunctionsEl3In4Out() { + String path = "/function-tests/function_el_3_in_4_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_el_3_in_4_out.occ")); + } + + @Test + public void testFunctionsEl4In1Out() { + String path = "/function-tests/function_el_4_in_1_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_el_4_in_1_out.occ")); + } + + @Test + public void testFunctionsEl4In2Out() { + String path = "/function-tests/function_el_4_in_2_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_el_4_in_2_out.occ")); + } + + @Test + public void testFunctionsEl4In3Out() { + String path = "/function-tests/function_el_4_in_3_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_el_4_in_3_out.occ")); + } + + @Test + public void testFunctionsEl4In4Out() { + String path = "/function-tests/function_el_4_in_4_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_el_4_in_4_out.occ")); + } + + @Test + public void testMonadicExpressions() { + String path = "/feature-tests/monadic_expressions.occ"; + assertTrue(testCompilingFile(getResource(path), path, "monadic_expressions.occ")); + } + + @Test + public void testTypeOperations() { + String path = "/feature-tests/operations_types.occ"; + assertTrue(testCompilingFile(getResource(path), path, "operations_types.occ")); + } + + @Test + public void testPars() { + String path = "/feature-tests/par.occ"; + assertTrue(testCompilingFile(getResource(path), path, "par.occ")); + } + + @Test + public void testParAdvanced() { + String path = "/feature-tests/par_advanced.occ"; + assertTrue(testCompilingFile(getResource(path), path, "par_advanced.occ")); + } + + @Test + public void testProcArguments() { + String path = "/feature-tests/proc_arguments.occ"; + assertTrue(testCompilingFile(getResource(path), path, "proc_arguments.occ")); + } + + @Test + public void testProcedureStaticAssignment() { + String path = "/feature-tests/procedure_static_assignment.occ"; + assertTrue(testCompilingFile(getResource(path), path, "procedure_static_assignment.occ")); + } + + @Ignore("Not yet fully implemented") + @Test + public void testRecordDeclarations() { + String path = "/feature-tests/record_declaration.occ"; + assertTrue(testCompilingFile(getResource(path), path, "record_declaration.occ")); + } + + @Ignore("Not yet fully implemented") + @Test + public void testRecordOperations() { + String path = "/feature-tests/record_operations.occ"; + assertTrue(testCompilingFile(getResource(path), path, "record_operations.occ")); + } + + @Test + public void testReplicatedConditionals() { + String path = "/feature-tests/replicated_conditionals.occ"; + assertTrue(testCompilingFile(getResource(path), path, "replicated_conditionals.occ")); + } + + @Test + public void testReplicators() { + String path = "/feature-tests/replicator.occ"; + assertTrue(testCompilingFile(getResource(path), path, "replicator.occ")); + } + + @Test + public void testSequentials() { + String path = "/feature-tests/sequential.occ"; + assertTrue(testCompilingFile(getResource(path), path, "sequential.occ")); + } + + @Test + public void testVariableAbbreviations() { + String path = "/feature-tests/variable_abbreviations.occ"; + assertTrue(testCompilingFile(getResource(path), path, "variable_abbreviations.occ")); + } + + @Test + public void testChannelAbbreviations() { + String path = "/feature-tests/channel_abbreviations.occ"; + assertTrue(testCompilingFile(getResource(path), path, "channel_abbreviations.occ")); + } + + @Ignore("Not yet fully implemented") + @Test + public void testArrayAbbreviations() { + String path = "/feature-tests/array.occ"; + assertTrue(testCompilingFile(getResource(path), path, "array.occ")); + } + + @Test + public void testWhileLoops() { + String path = "/feature-tests/while_loops.occ"; + assertTrue(testCompilingFile(getResource(path), path, "while_loops.occ")); + } +} diff --git a/tss-occam-compiler-test/src/test/java/uk/co/transputersystems/occam/open_transputer/ASMGeneratorTest.java b/tss-occam-compiler-test/src/test/java/uk/co/transputersystems/occam/open_transputer/ASMGeneratorTest.java new file mode 100644 index 0000000..21c8344 --- /dev/null +++ b/tss-occam-compiler-test/src/test/java/uk/co/transputersystems/occam/open_transputer/ASMGeneratorTest.java @@ -0,0 +1,505 @@ +package uk.co.transputersystems.occam.open_transputer; + +import uk.co.transputersystems.occam.OccamCompiler; +import uk.co.transputersystems.occam.OccamParser; +import uk.co.transputersystems.occam.ReferencedTSILGenerator; +import uk.co.transputersystems.occam.TSILGenerator; +import uk.co.transputersystems.occam.il.ILBlock; +import uk.co.transputersystems.occam.il.ILOp; +import uk.co.transputersystems.occam.metadata.LibraryInformation; +import org.antlr.v4.runtime.tree.ParseTree; +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; +import uk.co.transputersystems.occam.ErrorListener; + +import java.io.*; +import java.util.List; +import java.util.UUID; + +import static org.junit.Assert.assertTrue; + +public class ASMGeneratorTest { + + @Before + public void before() throws Exception { + File dir = new File("target/test-output/asm-generator-test/function-tests"); + File dir2 = new File("target/test-output/asm-generator-test/feature-tests"); + File dir3 = new File("target/test-output/asm-generator-test/basic-tests"); + dir.mkdirs(); + dir2.mkdirs(); + dir3.mkdirs(); + } + + public InputStream getResource(String name) { + return getClass().getResourceAsStream(name); + } + + /** + * Given a file, attempt to parse and compile it to TSIL. + * + * @param file The file to be compiled + * @return true if the compilation appears to have succeeded, otherwise false. + */ + public boolean testCompilingFile(InputStream file, String filePath, String fileName) throws Exception { + return testCompilingFile(file, filePath, fileName, true); + } + + /** + * Given a file, attempt to parse and compile it to TSIL. Checks that the + * compiled code is not null or empty. + * TODO: find a way to test the output other than checking nullity + * + * @param inputStream The file to be compiled + * @param verbose Whether to print debug output or not. + * @return true if the compilation appears to have succeeded, otherwise false. + */ + public boolean testCompilingFile(InputStream inputStream, String filePath, String fileName, boolean verbose) throws Exception { + ErrorListener errorListener = new ErrorListener(); + OccamCompiler compiler = new OccamCompiler(); + + PrintWriter out = new PrintWriter(System.out); + + if (verbose) { + out.println("TEST: " + inputStream); + } + + ParseTree tree = compiler.makeParseTree(inputStream, OccamParser::file_input, errorListener); + + if (verbose) { + compiler.printParseTree(out, tree); + } + + LibraryInformation libraryInfo = new LibraryInformation("TEST"); + List>> intermediate = compiler.generateTSIL(new TSILGenerator(libraryInfo), tree, filePath, fileName); + + assertTrue(intermediate != null); + assertTrue(intermediate.size() > 0); + + // Convert UUID IL to sequential integer-labelled IL + List>> intermediateRef = compiler.generateReferencedTSIL(new ReferencedTSILGenerator<>(), intermediate); + + ASMGeneratorContext asmGeneratorContext = new ASMGeneratorContext(libraryInfo); + + List asmBlocks = compiler.generateASM(new ASMGenerator(), intermediateRef, asmGeneratorContext, false); + + assertTrue(asmBlocks != null); + assertTrue(asmBlocks.size() > 0); + + if (verbose) { + compiler.writeDivider(out); + compiler.writeASMBlocks(out, asmBlocks); + compiler.writeDivider(out); + out.flush(); + } + + File outputFile = new File("target/test-output/asm-generator-test" + filePath.replace(".occ", ".auto.s")); + FileWriter outputWriter = new FileWriter(outputFile); + compiler.writeASMBlocks(outputWriter, asmBlocks); + outputWriter.flush(); + outputWriter.close(); + + return true; + } + + @Ignore("Not yet fully implemented") + @Test + public void testArrays() throws Exception { + String path = "/feature-tests/array.occ"; + assertTrue(testCompilingFile(getResource(path), path, "array.occ")); + } + + @Ignore("Not yet fully implemented") + @Test + public void testArraySegments() throws Exception { + String path = "/feature-tests/array_segment.occ"; + assertTrue(testCompilingFile(getResource(path), path, "array_segments.occ")); + } + + @Test + public void testAssignment() throws Exception { + String path = "/feature-tests/assignment.occ"; + assertTrue(testCompilingFile(getResource(path), path, "assignment.occ")); + } + + @Test + public void testByteLiterals() throws Exception { + String path = "/feature-tests/byte_literal.occ"; + assertTrue(testCompilingFile(getResource(path), path, "byte_literal.occ")); + } + + @Test + public void testChannels() throws Exception { + String path = "/feature-tests/channels.occ"; + assertTrue(testCompilingFile(getResource(path), path, "channels.occ")); + } + + @Test + public void testConditionals() throws Exception { + String path = "/feature-tests/conditional.occ"; + assertTrue(testCompilingFile(getResource(path), path, "conditional.occ")); + } + + @Test + public void testDeclarations() throws Exception { + String path = "/feature-tests/declarations.occ"; + assertTrue(testCompilingFile(getResource(path), path, "declarations.occ")); + } + + @Test + public void testDyadicExpressions() throws Exception { + String path = "/feature-tests/dyadic_expression.occ"; + assertTrue(testCompilingFile(getResource(path), path, "dyadic_expression.occ")); + } + + @Test + public void testNestedExpressionFeatures() throws Exception { + String path = "/feature-tests/expression_features_nested.occ"; + assertTrue(testCompilingFile(getResource(path), path, "expression_features_nested.occ")); + } + + @Test + public void testFunctionsOfExpressionList() throws Exception { + String path = "/function-tests/function_expression_list.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_expression_list.occ")); + } + + @Test + public void testFunctionsOfValueProcess() throws Exception { + String path = "/function-tests/function_value_process.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_value_process.occ")); + } + + @Test + public void testFunctionsVp0In1Out() throws Exception { + String path = "/function-tests/function_vp_0_in_1_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_vp_0_in_1_out.occ")); + } + + @Test + public void testFunctionsVp0In2Out() throws Exception { + String path = "/function-tests/function_vp_0_in_2_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_vp_0_in_2_out.occ")); + } + + @Test + public void testFunctionsVp0In3Out() throws Exception { + String path = "/function-tests/function_vp_0_in_3_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_vp_0_in_3_out.occ")); + } + + @Test + public void testFunctionsVp0In4Out() throws Exception { + String path = "/function-tests/function_vp_0_in_4_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_vp_0_in_4_out.occ")); + } + + @Test + public void testFunctionsVp1In1Out() throws Exception { + String path = "/function-tests/function_vp_1_in_1_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_vp_1_in_1_out.occ")); + } + + @Test + public void testFunctionsVp1In2Out() throws Exception { + String path = "/function-tests/function_vp_1_in_2_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_vp_1_in_2_out.occ")); + } + + @Test + public void testFunctionsVp1In3Out() throws Exception { + String path = "/function-tests/function_vp_1_in_3_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_vp_1_in_3_out.occ")); + } + + @Test + public void testFunctionsVp1In4Out() throws Exception { + String path = "/function-tests/function_vp_1_in_4_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_vp_1_in_4_out.occ")); + } + + @Test + public void testFunctionsVp2In1Out() throws Exception { + String path = "/function-tests/function_vp_2_in_1_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_vp_2_in_1_out.occ")); + } + + @Test + public void testFunctionsVp2In2Out() throws Exception { + String path = "/function-tests/function_vp_2_in_2_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_vp_2_in_2_out.occ")); + } + + @Test + public void testFunctionsVp2In3Out() throws Exception { + String path = "/function-tests/function_vp_2_in_3_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_vp_2_in_3_out.occ")); + } + + @Test + public void testFunctionsVp2In4Out() throws Exception { + String path = "/function-tests/function_vp_2_in_4_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_vp_2_in_4_out.occ")); + } + + @Test + public void testFunctionsVp3In1Out() throws Exception { + String path = "/function-tests/function_vp_3_in_1_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_vp_3_in_1_out.occ")); + } + + @Test + public void testFunctionsVp3In2Out() throws Exception { + String path = "/function-tests/function_vp_3_in_2_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_vp_3_in_2_out.occ")); + } + + @Test + public void testFunctionsVp3In3Out() throws Exception { + String path = "/function-tests/function_vp_3_in_3_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_vp_3_in_3_out.occ")); + } + + @Test + public void testFunctionsVp3In4Out() throws Exception { + String path = "/function-tests/function_vp_3_in_4_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_vp_3_in_4_out.occ")); + } + + @Test + public void testFunctionsVp4In1Out() throws Exception { + String path = "/function-tests/function_vp_4_in_1_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_vp_4_in_1_out.occ")); + } + + @Test + public void testFunctionsVp4In2Out() throws Exception { + String path = "/function-tests/function_vp_4_in_2_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_vp_4_in_2_out.occ")); + } + + @Test + public void testFunctionsVp4In3Out() throws Exception { + String path = "/function-tests/function_vp_4_in_3_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_vp_4_in_3_out.occ")); + } + + @Test + public void testFunctionsVp4In4Out() throws Exception { + String path = "/function-tests/function_vp_4_in_4_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_vp_4_in_4_out.occ")); + } + + @Test + public void testFunctionsEl0In1Out() throws Exception { + String path = "/function-tests/function_el_0_in_1_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_el_0_in_1_out.occ")); + } + + @Test + public void testFunctionsEl0In2Out() throws Exception { + String path = "/function-tests/function_el_0_in_2_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_el_0_in_2_out.occ")); + } + + @Test + public void testFunctionsEl0In3Out() throws Exception { + String path = "/function-tests/function_el_0_in_3_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_el_0_in_3_out.occ")); + } + + @Test + public void testFunctionsEl0In4Out() throws Exception { + String path = "/function-tests/function_el_0_in_4_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_el_0_in_4_out.occ")); + } + + @Test + public void testFunctionsEl1In1Out() throws Exception { + String path = "/function-tests/function_el_1_in_1_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_el_1_in_1_out.occ")); + } + + @Test + public void testFunctionsEl1In2Out() throws Exception { + String path = "/function-tests/function_el_1_in_2_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_el_1_in_2_out.occ")); + } + + @Test + public void testFunctionsEl1In3Out() throws Exception { + String path = "/function-tests/function_el_1_in_3_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_el_1_in_3_out.occ")); + } + + @Test + public void testFunctionsEl1In4Out() throws Exception { + String path = "/function-tests/function_el_1_in_4_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_el_1_in_4_out.occ")); + } + + @Test + public void testFunctionsEl2In1Out() throws Exception { + String path = "/function-tests/function_el_2_in_1_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_el_2_in_1_out.occ")); + } + + @Test + public void testFunctionsEl2In2Out() throws Exception { + String path = "/function-tests/function_el_2_in_2_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_el_2_in_2_out.occ")); + } + + @Test + public void testFunctionsEl2In3Out() throws Exception { + String path = "/function-tests/function_el_2_in_3_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_el_2_in_3_out.occ")); + } + + @Test + public void testFunctionsEl2In4Out() throws Exception { + String path = "/function-tests/function_el_2_in_4_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_el_2_in_4_out.occ")); + } + + @Test + public void testFunctionsEl3In1Out() throws Exception { + String path = "/function-tests/function_el_3_in_1_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_el_3_in_1_out.occ")); + } + + @Test + public void testFunctionsEl3In2Out() throws Exception { + String path = "/function-tests/function_el_3_in_2_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_el_3_in_2_out.occ")); + } + + @Test + public void testFunctionsEl3In3Out() throws Exception { + String path = "/function-tests/function_el_3_in_3_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_el_3_in_3_out.occ")); + } + + @Test + public void testFunctionsEl3In4Out() throws Exception { + String path = "/function-tests/function_el_3_in_4_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_el_3_in_4_out.occ")); + } + + @Test + public void testFunctionsEl4In1Out() throws Exception { + String path = "/function-tests/function_el_4_in_1_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_el_4_in_1_out.occ")); + } + + @Test + public void testFunctionsEl4In2Out() throws Exception { + String path = "/function-tests/function_el_4_in_2_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_el_4_in_2_out.occ")); + } + + @Test + public void testFunctionsEl4In3Out() throws Exception { + String path = "/function-tests/function_el_4_in_3_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_el_4_in_3_out.occ")); + } + + @Test + public void testFunctionsEl4In4Out() throws Exception { + String path = "/function-tests/function_el_4_in_4_out.occ"; + assertTrue(testCompilingFile(getResource(path), path, "function_el_4_in_4_out.occ")); + } + + @Test + public void testMonadicExpressions() throws Exception { + String path = "/feature-tests/monadic_expressions.occ"; + assertTrue(testCompilingFile(getResource(path), path, "monadic_expressions.occ")); + } + + @Test + public void testTypeOperations() throws Exception { + String path = "/feature-tests/operations_types.occ"; + assertTrue(testCompilingFile(getResource(path), path, "operations_types.occ")); + } + + @Test + public void testPars() throws Exception { + String path = "/feature-tests/par.occ"; + assertTrue(testCompilingFile(getResource(path), path, "par.occ")); + } + + @Test + public void testParAdvanced() throws Exception { + String path = "/feature-tests/par_advanced.occ"; + assertTrue(testCompilingFile(getResource(path), path, "par_advanced.occ")); + } + + @Test + public void testProcArguments() throws Exception { + String path = "/feature-tests/proc_arguments.occ"; + assertTrue(testCompilingFile(getResource(path), path, "proc_arguments.occ")); + } + + @Test + public void testProcedureStaticAssignment() throws Exception { + String path = "/feature-tests/procedure_static_assignment.occ"; + assertTrue(testCompilingFile(getResource(path), path, "procedure_static_assignment.occ")); + } + + @Ignore("Not yet fully implemented") + @Test + public void testRecordDeclarations() throws Exception { + String path = "/feature-tests/record_declaration.occ"; + assertTrue(testCompilingFile(getResource(path), path, "record_declaration.occ")); + } + + @Ignore("Not yet fully implemented") + @Test + public void testRecordOperations() throws Exception { + String path = "/feature-tests/record_operations.occ"; + assertTrue(testCompilingFile(getResource(path), path, "record_operations.occ")); + } + + @Test + public void testReplicatedConditionals() throws Exception { + String path = "/feature-tests/replicated_conditionals.occ"; + assertTrue(testCompilingFile(getResource(path), path, "replicated_conditionals.occ")); + } + + @Test + public void testReplicators() throws Exception { + String path = "/feature-tests/replicator.occ"; + assertTrue(testCompilingFile(getResource(path), path, "replicator.occ")); + } + + @Test + public void testSequentials() throws Exception { + String path = "/feature-tests/sequential.occ"; + assertTrue(testCompilingFile(getResource(path), path, "sequential.occ")); + } + + @Test + public void testVariableAbbreviations() throws Exception { + String path = "/feature-tests/variable_abbreviations.occ"; + assertTrue(testCompilingFile(getResource(path), path, "variable_abbreviations.occ")); + } + + @Test + public void testChannelAbbreviations() throws Exception { + String path = "/feature-tests/channel_abbreviations.occ"; + assertTrue(testCompilingFile(getResource(path), path, "channel_abbreviations.occ")); + } + + @Ignore("Not yet fully implemented") + @Test + public void testArrayAbbreviations() throws Exception { + String path = "/feature-tests/array.occ"; + assertTrue(testCompilingFile(getResource(path), path, "array.occ")); + } + + @Test + public void testWhileLoops() throws Exception { + String path = "/feature-tests/while_loops.occ"; + assertTrue(testCompilingFile(getResource(path), path, "while_loops.occ")); + } +} diff --git a/tss-occam-compiler/etc/toc b/tss-occam-compiler/etc/toc new file mode 100644 index 0000000..fed613a --- /dev/null +++ b/tss-occam-compiler/etc/toc @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +java -jar "tss-occam-compiler-1.0-SNAPSHOT-jfx.jar" "$@" \ No newline at end of file diff --git a/tss-occam-compiler/pom.xml b/tss-occam-compiler/pom.xml new file mode 100644 index 0000000..1d7010b --- /dev/null +++ b/tss-occam-compiler/pom.xml @@ -0,0 +1,162 @@ + + 4.0.0 + + uk.co.transputersystems + tss-occam-compiler + 1.0-SNAPSHOT + + jar + tss-occam-compiler + + + UTF-8 + tss + tss-occam-compiler + + + + + org.antlr + antlr4-runtime + 4.5.2 + + + + junit + junit + 4.12 + + + + com.yuvalshavit + antlr-denter + 1.1 + + + + com.google.code.gson + gson + 2.5 + + + + org.assertj + assertj-core + 3.3.0 + test + + + + com.google.code.findbugs + jsr305 + 2.0.1 + + + + net.sf.jopt-simple + jopt-simple + 5.0 + + + + + + + ${project.basedir}/src/test/resources + + + ${project.build.directory}/maven-shared-archive-resources + + **/*.occ + + + + src/main/java + install + + + org.apache.maven.plugins + maven-surefire-plugin + 2.19.1 + + 0 + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.5.1 + + 1.8 + 1.8 + + + + org.antlr + antlr4-maven-plugin + 4.5.2 + + true + true + UTF-8 + + + + antlr4 + + + + + maven-assembly-plugin + + + + make-compiler-assembly + + occam-compiler + + jar-with-dependencies + + + + uk.co.transputersystems.occam.OccamCompilerApplication + + + + package + + attached + + + + + + maven-javadoc-plugin + 2.10.3 + + ch.raffael.doclets.pegdown.PegdownDoclet + + ch.raffael.pegdown-doclet + pegdown-doclet + 1.2.1 + + true + + + + com.zenjava + javafx-maven-plugin + 8.4.0 + + uk.co.transputersystems.occam.OccamCompilerApplication + true + etc + + + + + + + \ No newline at end of file diff --git a/tss-occam-compiler/src/main/antlr4/uk/co/transputersystems/occam/Occam.g4 b/tss-occam-compiler/src/main/antlr4/uk/co/transputersystems/occam/Occam.g4 new file mode 100644 index 0000000..6df89cd --- /dev/null +++ b/tss-occam-compiler/src/main/antlr4/uk/co/transputersystems/occam/Occam.g4 @@ -0,0 +1,619 @@ +grammar Occam; + +tokens { INDENT, DEDENT } + + +@lexer::members { + + // A queue where extra tokens are pushed on (see the NEWLINE lexer rule). + private java.util.LinkedList tokens = new java.util.LinkedList<>(); + + // The stack that keeps track of the indentation level. + private java.util.Stack indents = new java.util.Stack<>(); + + // The amount of opened braces, brackets and parenthesis. + private int opened = 0; + + // The most recently produced token. + private Token lastToken = null; + + @Override + public void emit(Token t) { + super.setToken(t); + tokens.offer(t); + } + + @Override + public Token nextToken() { + + // Check if the end-of-file is ahead and there are still some DEDENTS expected. + if (_input.LA(1) == EOF && !this.indents.isEmpty()) { + + // Remove any trailing EOF tokens from our buffer. + for (int i = tokens.size() - 1; i >= 0; i--) { + if (tokens.get(i).getType() == EOF) { + tokens.remove(i); + } + } + + // First emit an extra line break that serves as the end of the statement. + this.emit(commonToken(OccamParser.NL, "\n")); + + // Now emit as much DEDENT tokens as needed. + while (!indents.isEmpty()) { + this.emit(createDedent()); + indents.pop(); + } + + // Put the EOF back on the token stream. + this.emit(commonToken(OccamParser.EOF, "")); + } + + Token next = super.nextToken(); + + if (next.getChannel() == Token.DEFAULT_CHANNEL) { + // Keep track of the last token on the default channel. + this.lastToken = next; + } + + return tokens.isEmpty() ? next : tokens.poll(); + } + + private Token createDedent() { + CommonToken dedent = commonToken(OccamParser.DEDENT, ""); + dedent.setLine(this.lastToken.getLine()); + return dedent; + } + + private CommonToken commonToken(int type, String text) { + int stop = this.getCharIndex() - 1; + int start = text.isEmpty() ? stop : stop - text.length() + 1; + return new CommonToken(this._tokenFactorySourcePair, type, DEFAULT_TOKEN_CHANNEL, start, stop); + } + + // Calculates the indentation of the provided spaces, taking the + // following rules into account: + // + // "Tabs are replaced (from left to right) by one to eight spaces + // such that the total number of characters up to and including + // the replacement is a multiple of eight [...]" + // + // -- https://docs.python.org/3.1/reference/lexical_analysis.html#indentation + static int getIndentationCount(String spaces) { + + int count = 0; + + for (char ch : spaces.toCharArray()) { + switch (ch) { + case '\t': + count += 8 - (count % 8); + break; + default: + // A normal space char. + count++; + } + } + + return count; + } + + boolean atStartOfInput() { + return super.getCharPositionInLine() == 0 && super.getLine() == 1; + } +} + + +NL + : ( {atStartOfInput()}? SPACES + | ('\r'? '\n' | '\r' ) SPACES? + ) + { + String newLine = getText().replaceAll("[^\r\n]+", ""); + String spaces = getText().replaceAll("[\r\n]+", ""); + int next = _input.LA(1); + int nextNext = _input.LA(2); + + if (opened > 0 || next == '\r' || next == '\n' || (next == '-' && nextNext == '-')) { + // If we're inside a list or on a blank line, ignore all indents, + // dedents and line breaks. + skip(); + } + else { + emit(commonToken(NL, newLine)); + + int indent = getIndentationCount(spaces); + int previous = indents.isEmpty() ? 0 : indents.peek(); + + if (indent == previous) { + // skip indents of the same size as the present indent-size + skip(); + } + else if (indent > previous) { + indents.push(indent); + emit(commonToken(OccamParser.INDENT, spaces)); + } + else { + // Possibly emit more than 1 DEDENT token. + while(!indents.isEmpty() && indents.peek() > indent) { + this.emit(createDedent()); + indents.pop(); + } + } + } + } + ; + +file_input : ( NL | specification ) * EOF; + +stmt : simple_stmt #stmt_simple_stmt + | compound_stmt #stmt_compound_stmt + ; + +simple_stmt : small_stmt NL + ; + +small_stmt + : assignment #small_stmt_assignment + | input #small_stmt_input + | output #small_stmt_output + | SKIP_T #small_stmt_skip + | STOP #small_stmt_stop + | proc_instance #small_stmt_proc + ; + +compound_stmt + : sequence #compound_stmt_sequence + | conditional #compound_stmt_conditional + | selection #compound_stmt_selection + | loop #compound_stmt_loop + | parallel #compound_stmt_parallel + | alternation #compound_stmt_alternation + | case_input #compound_stmt_case_input + | (specification | allocation) NL stmt #compound_stmt_spec_or_alloc_stmt + ; + +abbreviation: NAME IS named_operand ':' #abbreviation_name_operand + | specifier NAME IS named_operand ':' #abbreviation_spec_name_operand + | VAL NAME IS expression ':' #abbreviation_expression + | VAL specifier NAME IS expression ':' #abbreviation_spec_expression + | NAME IS '[' channel ( ',' channel ) * ']' ':' #abbreviation_name_channel_list + | specifier NAME IS '[' channel ( ',' channel ) * ']' ':' #abbreviation_spec_channel_list + ; + +actual : named_operand #actual_named_operand + | channel #actual_channel + | expression #actual_expression + ; + +allocation : PLACE NAME AT expression ':' ; + +alternation : PRI ? ALT NL INDENT alternative ( alternative ) * DEDENT #alternation_alternatives + | PRI ? ALT replicator NL INDENT alternative DEDENT #alternation_replicator_alternative + ; + +alternative : guarded_alternative #alternative_guarded + | alternation #alternative_alternation + | channel '?' CASE NL INDENT variant ( NL variant ) * DEDENT #alternative_channel + | bool '&' channel '?' CASE NL INDENT variant ( NL variant ) * DEDENT #alternative_bool_channel + | specification NL alternative #alternative_spec + ; + +assignment : variable_list ':=' expression_list; + +base : expression; + +bool : expression; + +case_expression + : expression ; + +case_input : channel '?' CASE NL INDENT variant ( NL variant ) * DEDENT ; + +channel : NAME #channel_name + | channel '[' expression ']' #channel_channel_expression + | '[' channel FROM base ( FOR count ) ? ']' #channel_from_base + | '[' channel FOR count ']' #channel_for_count + ; + +channel_type : CHANOF protocol #channel_type_protocol + | '[' expression ']' channel_type #channel_expression_channel_type + ; + +choice : guarded_choice #choice_guarded + | conditional #choice_conditional + | specification NL choice #choice_specification + ; + +conditional : IF NL INDENT choice ( choice ) * DEDENT #conditional_choices + | IF replicator NL INDENT choice DEDENT #conditional_replicator + ; + +conversion : data_type ( ROUND | TRUNC ) ? operand ; + +count : expression ; + +data_type : BOOL #data_type_bool + | BYTE_KWD #data_type_byte + | INT #data_type_int + | INT16 #data_type_int16 + | INT32 #data_type_int32 + | INT64 #data_type_int64 + | REAL32 #data_type_real32 + | REAL64 #data_type_real64 + | NAME #data_type_name + | '[' expression ']' data_type #data_type_expr_data_type + ; + +declaration : ( data_type | channel_type | timer_type | port_type ) NAME ( ',' NAME )* ':' ; + +definition : DATA TYPE NAME (IS data_type | NL INDENT structured_type DEDENT ) ':' #def_DATA_Name + | PROTOCOL NAME IS (simple_protocol | sequential_protocol) ':' #def_PROTOCOL_NAME_IS + | PROTOCOL NAME INDENT CASE INDENT ( tagged_protocol ( NL tagged_protocol ) * ) ? DEDENT DEDENT ':' #def_PROTOCOL_NAME_INDENT + | PROC NAME '(' ( formal (',' formal)* )? ')' NL ( INDENT stmt DEDENT )? ':' #def_PROC + | data_type (',' data_type)* function_header NL INDENT value_process DEDENT ':' #def_function_value_process + | data_type (',' data_type)* function_header IS expression_list ':' #def_function_expression_list + | specifier NAME RETYPES named_operand ':' #def_specifier + | specifier NAME (RETYPES | RESHAPES) named_operand ':' #def_specifier2 + | VAL specifier NAME (RETYPES | RESHAPES) expression ':' #def_val + ; + +delayed_input + : named_operand '?' AFTER expression ; + +dyadic_operator + : LTHAN + | PLUS + | MINUS + | TIMES + | DIVIDE + | PLUS_MOD + | MINUS_MOD + | TIMES_MOD + | REM + | BITWISE_AND + | AND_KWD + | BITWISE_OR + | OR_KWD + | XOR + | BITWISE_AND_KWD + | GTHAN + | + | EQUAL + | BITOR + | NOTEQ + | LTHANEQ + | GTHANEQ + | AFTER + | RIGHTSHIFT + | LEFTSHIFT + ; + +expression : operand #expression_operand + | monadic_operator operand #expression_monadic + | operand dyadic_operator operand #expression_dyadic_operator + | (MOSTPOS | MOSTNEG) data_type #expression_most_data_type + | SIZE data_type #expression_size_of + | conversion #expression_conversion + ; + +expression_list + : function_call #expression_list_function_call + | expression ( ',' expression )* #expression_list_expressions + //| '(' value_process NL ')' //todo: expression list, add new line support + ; + +field_name : NAME ; + +formal : specifier NAME ( ',' NAME ) * + | VAL specifier NAME ( ',' NAME ) * + ; + +function_call + : NAME '(' ( expression ( ',' expression) * ) ? ')' + ; + +function_header + : FUNCTION NAME '(' ( formal (',' formal )* )? ')' + ; + +guard : input #guard_input + | bool '&' ( input | SKIP_T ) #guard_bool_input_or_skip + ; + +guarded_alternative + : guard NL (INDENT stmt DEDENT); + +guarded_choice + : bool NL (INDENT stmt DEDENT); + +input : named_operand '?' input_item ( ';' input_item ) * #input_named_operand_input_items + | channel '?' CASE tagged_list #input_named_operand_tagged_list + | delayed_input #input_delayed_input + ; + +input_item : named_operand #input_item_variable + | named_operand '::' named_operand #input_item_multiple_variables + ; + +literal : INTEGER ('(' data_type ')')? #literal_integer + | BYTE_LITERAL ('(' data_type ')')? #literal_byte + | REAL ('(' data_type ')')? #literal_real + | TRUE_LITERAL #literal_true + | FALSE_LITERAL #literal_false + ; + +loop : WHILE bool NL INDENT stmt DEDENT; + +monadic_operator + : NOT_KWD + | BITWISE_NOT + | BITWISE_NOT_KWD + | MINUS + | MINUS_MOD + | SIZE + ; + +operand : named_operand #operand_variable + | literal #operand_literal + | table #operand_table + | '(' expression ')' #operand_expression + | '(' value_process NL ')' #operand_value_process + | function_call #operand_function_call + | operand '[' expression ']' #operand_operand_expression + | BYTESIN '(' ( operand | data_type ) ')' #operand_bytesin + | OFFSETOF '(' NAME ',' field_name ')' #operand_offsetof + ; + +option : case_expression ( ',' case_expression ) * NL INDENT stmt DEDENT #option_case_expression_stmt + | ELSE NL INDENT stmt DEDENT #option_else + | specification NL option #option_spec_option + ; + +output : named_operand '!' outputitem (';' outputitem ) * #output_named_operand_outputitems + | named_operand '!' tag ( ';' outputitem ( ';' outputitem ) * ) ? #output_named_operand_tag_outputitems + ; + +outputitem : expression #outputitem_single_expression + | expression '::' expression #outputitem_multiple_expression + ; + +parallel : PRI ? PAR suite #parallel_pripar_suite + | PRI ? PAR replicator NL INDENT stmt DEDENT #parallel_pripar_replicator + | placedpar #parallel_placedpar + ; + +single_stmt : NL INDENT stmt DEDENT; + +suite : NL INDENT (stmt+ | simple_stmt) DEDENT + ; + +placedpar : PLACED PAR NL INDENT placedpar ( NL placedpar ) * #placedpar_placedpars + | PLACED PAR replicator NL INDENT placedpar DEDENT #placedpar_replicator_placedpar + | PROCESSOR expression NL INDENT stmt DEDENT #placedpar_expression_stmt + ; + +port_type : PORTOF data_type #port_type_data_type + | '[' expression ']' port_type #port_type_expression_port_type + ; + +proc_instance + : NAME '(' ( actual (',' actual ) * ) ? ')'; + +protocol : NAME #protcol_name + | simple_protocol #protcol_simple_protocol + ; + +replicator : NAME EQUAL base FOR count; + +selection : CASE selector NL INDENT option * DEDENT ; + +selector : expression; + +sequence : SEQ suite #sequence_suite + | SEQ replicator NL INDENT stmt DEDENT #sequence_replicator + ; + +sequential_protocol + : simple_protocol ( ';' simple_protocol ) *; + +simple_protocol + : data_type #simple_protocol_data_type + | ANY #simple_protocol_any + | data_type '::' '['']' data_type #simple_protocol_data_type_data_type + ; + +specification + : declaration #specificationDec + | abbreviation #specificationAbrv + | definition #specificationDef + ; + +specifier : data_type #specifier_data_type + | channel_type #specifier_channel_type + | timer_type #specifier_timer_type + | port_type #specifier_port_type + | '['(expression)?']'specifier #specifier_expression_specifier + ; + +structured_type + : PACKED ? RECORD NL INDENT ( single_record_declaration ) ( NL single_record_declaration) * NL DEDENT ; + +single_record_declaration + : (data_type field_name ( ',' field_name ) * ':') + ; + +table : STRING_LITERAL ( '(' NAME ')' ) ? #table_string + | '[' expression ( ',' expression ) * ']' #table_expressions + | table '[' expression ']' #table_table_expression + | '[' table FROM base (FOR count) ? ']' #table_table_base_count + | '[' table FOR count ']' #table_table_count + ; + +tag : NAME; + +tagged_list : tag ( ';' input_item ( ';' input_item ) * ) ? ; + +tagged_protocol + : tag ( ';' sequential_protocol ) ? ; + +timer_type : TIMER #timer_type_timer + | '[' expression ']' timer_type #timer_expression_timer_type + ; + +value_process + : VALOF NL INDENT stmt RESULT expression_list NL DEDENT #value_process_stmt + | specification NL value_process #value_process_specification + ; + +named_operand : NAME #named_operand_name + | named_operand '[' expression ']' #named_operand_expression + | '[' named_operand FROM base (FOR count)? ']' #named_operand_base_count + | '[' named_operand FOR count ']' #named_operand_count + ; + +variable_list: named_operand ( ',' named_operand ) *; + +variant : tagged_list NL INDENT stmt DEDENT #variant_tagged_list_stmt + | specification NL variant #variant_specification_variant + ; + +// FLOW CONTROL +CASE : 'CASE' ; +ELSE : 'ELSE' ; +FUNCTION : 'FUNCTION' ; +IF : 'IF' ; +PAR : 'PAR' ; +PROC : 'PROC' ; +SEQ : 'SEQ' ; +SKIP_T : 'SKIP' ; +STOP : 'STOP' ; +WHILE : 'WHILE' ; + +// TYPES AND VARIABLES +BOOL : 'BOOL' ; +BYTE_KWD : 'BYTE' ; +CHANOF : 'CHAN OF' ; +DATA : 'DATA' ; +INT : 'INT' ; +INT16 : 'INT16' ; +INT32 : 'INT32' ; +INT64 : 'INT64' ; +MOSTNEG : 'MOSTNEG' ; +MOSTPOS : 'MOSTPOS' ; +PACKED : 'PACKED' ; +PORTOF : 'PORT OF' ; +PROTOCOL : 'PROTOCOL' ; +REAL32 : 'REAL32' ; +REAL64 : 'REAL64' ; +RECORD : 'RECORD' ; +TIMER : 'TIMER' ; +TYPE : 'TYPE' ; +VAL : 'VAL' ; +VALOF : 'VALOF' ; + +// OPERATORS +AFTER : 'AFTER' ; +AND_KWD : 'AND' ; //boolean AND +BYTESIN : 'BYTESIN' ; // width, 'bytes in' +BITWISE_AND_KWD : 'BITAND' ; +BITWISE_NOT_KWD : 'BITNOT' ; +BITOR : 'BITOR' ; +MINUS_MOD : 'MINUS' ; // modulo subtraction/negation +NOT_KWD : 'NOT' ; // boolean not +OR_KWD : 'OR' ; //boolean OR +PLUS_MOD : 'PLUS' ; // modulo addition +REM_KWD : 'REM' ; // remainder +ROUND : 'ROUND' ; +SIZE : 'SIZE' ; +TIMES_MOD : 'TIMES' ; // modulo multiplication +TRUNC : 'TRUNC' ; // truncation + +PLUS : '+' ; +MINUS : '-' ; +TIMES : '*' ; +DIVIDE : '/' ; + + +// Symbols +REM : '\\' ; + +BITWISE_AND : '/\\' ; +BITWISE_OR : '\\/' ; +XOR : '><' ; +BITWISE_NOT : '~' ; +LEFTSHIFT : '<<' ; +RIGHTSHIFT : '>>' ; + +EQUAL : '=' ; +LTHAN : '<' ; +GTHAN : '>' ; +LTHANEQ : '<=' ; +GTHANEQ : '>=' ; +NOTEQ : '<>' ; + +// LITERALS +FALSE_LITERAL: 'FALSE' ; +TRUE_LITERAL: 'TRUE' ; +BYTE_LITERAL: '\'' CHARACTER '\'' ; +STRING_LITERAL + : '"' CHARACTER* ('*' NL '*' CHARACTER* )* '"'; + +INTEGER : DIGITS | '#'HEXDIGITS ; +REAL : DIGITS '.' DIGITS ( 'E' EXPONENT )? ; +fragment EXPONENT : ( '+' | '-' ) DIGITS ; + + + + +// COMMUNICATION +INPUT : '?' ; +OUTPUT : '!' ; + +// OTHER KEYWORDS +ALT : 'ALT' ; +ANY : 'ANY' ; +ASM : 'ASM' ; +AT : 'AT' ; +FOR : 'FOR'; +FROM : 'FROM' ; +INLINE : 'INLINE' ; +IS : 'IS' ; +OFFSETOF : 'OFFSETOF' ; +PLACE : 'PLACE' ; +PLACED : 'PLACED' ; +PRI : 'PRI' ; +PROCESSOR : 'PROCESSOR' ; +RESHAPES : 'RESHAPES' ; +RESULT : 'RESULT' ; +RETYPES : 'RETYPES' ; + + +NAME : [a-zA-Z][a-zA-Z0-9.]*; + +DIGITS : DIGIT+ ; +HEXDIGITS : HEXDIGIT+ ; +DIGIT : [0-9] ; +HEXDIGIT : [0-9A-F] ; + + +IGNORED : ( SPACES | COMMENT | LINE_JOINING ) -> skip + ; + + +fragment SPACES + : [ \t]+ + ; + +fragment COMMENT + : '--' ~[\r\n]* + ; + +fragment LINE_JOINING + : '\\' SPACES? ( '\r'? '\n' | '\r' ) + ; + +fragment CHARACTER + : ~['"*] // any ASCII char + | '*' ( [cC] | [nN] | [tT] | [sS] | '\'' | '"' | '*' ) // escape sequences + | '*#' HEXDIGIT HEXDIGIT; + diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/ErrorListener.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/ErrorListener.java new file mode 100644 index 0000000..b51bdab --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/ErrorListener.java @@ -0,0 +1,15 @@ +package uk.co.transputersystems.occam; + +import org.antlr.v4.runtime.BaseErrorListener; +import org.antlr.v4.runtime.RecognitionException; +import org.antlr.v4.runtime.Recognizer; + +public class ErrorListener extends BaseErrorListener { + public int errors = 0; + + @Override + public void syntaxError(Recognizer recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e) { + errors++; + super.syntaxError(recognizer, offendingSymbol, line, charPositionInLine, msg, e); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/ILOpFormatter.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/ILOpFormatter.java new file mode 100644 index 0000000..ac56a6d --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/ILOpFormatter.java @@ -0,0 +1,50 @@ +package uk.co.transputersystems.occam; + +import uk.co.transputersystems.occam.il.ILBlock; +import uk.co.transputersystems.occam.il.ILOp; + +import java.util.Arrays; +import java.util.StringJoiner; + +public class ILOpFormatter { + /** + * Format the details of an ILOp into a human-readable string. + * @return A human-readable string representing the ILOp. + */ + public static String formatOp(ILOp op, ILBlock> ctx) { + StringBuilder result = new StringBuilder(); + + result + .append(op.getId().toString()) + .append(" : ") + .append(op.getOpName()); + + result = padRight(result, 55, 1); + + StringJoiner argJoiner = new StringJoiner(", ", "(", ")"); + for (String arg : op.getArgs()) { + argJoiner.add(arg); + } + + result.append(argJoiner.toString()); + + result = padRight(result, 120, 1); + + result + .append("// ") + .append(op.getComment()); + + return result.toString(); + } + + /** + * Given a `StringBuilder`, pad it with spaces until it has at least `minLength`. If no padding it required, add at + * least `minPadding` spaces. + * @return The padded `StringBuilder`. + */ + private static StringBuilder padRight(StringBuilder sb, int minLength, int minPadding) { + char[] padding = new char[minLength - sb.length() > 0 ? minLength - sb.length() : minPadding]; + Arrays.fill(padding, ' '); + return sb.append(padding); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/OccamCompiler.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/OccamCompiler.java new file mode 100644 index 0000000..a1dc740 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/OccamCompiler.java @@ -0,0 +1,97 @@ +package uk.co.transputersystems.occam; + +import uk.co.transputersystems.occam.il.ILBlock; +import uk.co.transputersystems.occam.il.ILOp; +import uk.co.transputersystems.occam.metadata.LibraryInformation; +import uk.co.transputersystems.occam.open_transputer.ASMBlock; +import uk.co.transputersystems.occam.open_transputer.ASMGenerator; +import uk.co.transputersystems.occam.open_transputer.ASMGeneratorContext; +import uk.co.transputersystems.occam.open_transputer.ASMOpFormatter; +import uk.co.transputersystems.occam.open_transputer.assembly.ASMOp; +import org.antlr.v4.runtime.ANTLRInputStream; +import org.antlr.v4.runtime.CommonTokenStream; +import org.antlr.v4.runtime.tree.ParseTree; +import org.antlr.v4.runtime.tree.ParseTreeWalker; + +import javax.annotation.Nonnull; +import java.io.*; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import java.util.function.Function; + +public class OccamCompiler { + + public void writeILBlocks(FileWriter outputILWriter, List>> ilBlocks) throws IOException { + for (ILBlock block : ilBlocks) { + outputILWriter.write(block.toString()); + } + outputILWriter.flush(); + } + + public void writeASMBlocks(Writer outputWriter, List asmBlocks) throws IOException { + for (ASMBlock block : asmBlocks) { + for (ASMOp op : block.getOps()) { + outputWriter.write(ASMOpFormatter.formatOp(op)); + outputWriter.write('\n'); + } + outputWriter.write('\n'); + } + outputWriter.flush(); + } + + public void writeDivider(Writer out) throws IOException { + out.write("-------------------------------------------------------------------------\n"); + } + + public List>> generateTSIL(TSILGenerator tsilGenerator, ParseTree tree, String filePath, String fileName) { + LibraryInformation libraryInfo = tsilGenerator.getLibraryInfo(); + libraryInfo.startNewFile(filePath, fileName); + return tsilGenerator.visit(tree); + + } + + public List>> generateReferencedTSIL(@Nonnull ReferencedTSILGenerator tsilGenerator, @Nonnull List>> ilBlocks) { + List>> referencedIlBlocks = new ArrayList<>(); + for (ILBlock> ilBlock : ilBlocks) { + ILBlock> newBlock = new ILBlock<>(ilBlock.getScopeId(), ilBlock.isFunctionBlock()); + for (ILOp op : ilBlock.getAll()) { + newBlock.add(tsilGenerator.visit(op, ilBlock)); + } + referencedIlBlocks.add(newBlock); + } + return referencedIlBlocks; + } + + public List generateASM(@Nonnull ASMGenerator asmGenerator, @Nonnull List>> ilBlocks, ASMGeneratorContext asmGeneratorContext, boolean suppressErrors) throws Exception { + List asmBlocks = asmGenerator.generateASM(ilBlocks, asmGeneratorContext, suppressErrors); + asmBlocks.add(asmGeneratorContext.getGlobalsBlock()); + return asmBlocks; + } + + public ParseTree makeParseTree(InputStream inputStream, Function startRule, ErrorListener errorListener) { + try { + ANTLRInputStream antlrInputStream = new ANTLRInputStream(inputStream); + OccamLexer synLexer = new OccamLexer(antlrInputStream); + + CommonTokenStream tokenStream = new CommonTokenStream(synLexer); + OccamParser occamParser = new OccamParser(tokenStream); + occamParser.addErrorListener(errorListener); + + return startRule.apply(occamParser); + + } catch (Exception e) { + System.out.println(e.getMessage()); + return null; + } + } + + public void printParseTree(PrintWriter out, ParseTree tree) { + new OccamParser(null); + + ParseTreePretty listener = new ParseTreePretty(new OccamParser(null)); + ParseTreeWalker.DEFAULT.walk(listener,tree); + out.println(listener.toString()); + } + +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/OccamCompilerApplication.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/OccamCompilerApplication.java new file mode 100644 index 0000000..8fcf563 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/OccamCompilerApplication.java @@ -0,0 +1,124 @@ +package uk.co.transputersystems.occam; + +import uk.co.transputersystems.occam.il.ILBlock; +import uk.co.transputersystems.occam.il.ILOp; +import uk.co.transputersystems.occam.metadata.LibraryInformation; +import uk.co.transputersystems.occam.metadata.VerificationContext; +import uk.co.transputersystems.occam.open_transputer.ASMBlock; +import uk.co.transputersystems.occam.open_transputer.ASMGenerator; +import uk.co.transputersystems.occam.open_transputer.ASMGeneratorContext; +import javafx.application.Application; +import javafx.application.Platform; +import javafx.stage.Stage; +import joptsimple.OptionParser; +import joptsimple.OptionSet; +import joptsimple.OptionSpec; +import org.antlr.v4.runtime.tree.ParseTree; + +import java.io.*; +import java.util.Collections; +import java.util.List; +import java.util.UUID; + +public class OccamCompilerApplication extends Application { + + public static void main(String[] args) throws Exception { + Application.launch(args); + } + + @Override + public void start(Stage primaryStage) throws Exception { + String[] args = new String[getParameters().getRaw().size()]; + args = getParameters().getRaw().toArray(args); + OptionParser optionParser = new OptionParser(); + OptionSpec inputArg = optionParser + .accepts("input") + .withRequiredArg() + .required() + .ofType(File.class) + .describedAs("Occam source code"); + + OptionSpec outputArg = optionParser + .accepts("output") + .withRequiredArg() + .required() + .ofType(File.class) + .describedAs("Transputer assembly"); + + OptionSpec outputILArg = optionParser + .accepts("output-il") + .withRequiredArg() + .ofType(File.class) + .describedAs("Intermediate Language"); + + optionParser.accepts("verbose"); + + OptionSet options = optionParser.parse(args); + + File inputFile = options.valueOf(inputArg); + File outputFile = options.valueOf(outputArg); + + OccamCompiler compiler = new OccamCompiler(); + + PrintWriter out = new PrintWriter(System.out); + + InputStream inputStream = new FileInputStream(inputFile); + + ErrorListener errorListener = new ErrorListener(); + ParseTree tree = compiler.makeParseTree(inputStream, OccamParser::file_input, errorListener); + + if (options.has("verbose")) { + compiler.printParseTree(out, tree); + } + + LibraryInformation libraryInfo = new LibraryInformation("Root Library"); + TSILGenerator tsilGenerator = new TSILGenerator(libraryInfo); + ReferencedTSILGenerator rTsilGenerator = new ReferencedTSILGenerator<>(); + + if (options.has("verbose")) { + out.println(libraryInfo.getName() + ": " + inputFile.getName()); + } + + // Generate IL with UUID identifiers + List>> ilBlocks = compiler.generateTSIL(tsilGenerator, tree, inputFile.getPath(), inputFile.getName()); + + // Perform sanity checks + VerificationContext verificationContext = new VerificationContext(Collections.singletonList(libraryInfo)); + verificationContext.verify(ilBlocks); + + // Convert UUID IL to sequential integer-labelled IL + List>> referencedIlBlocks = compiler.generateReferencedTSIL(rTsilGenerator, ilBlocks); + + try { + if (options.has("output-il")) { + File outputILFile = options.valueOf(outputILArg); + FileWriter outputILWriter = new FileWriter(outputILFile); + compiler.writeILBlocks(outputILWriter, referencedIlBlocks); + } + + ASMGeneratorContext asmGeneratorContext = new ASMGeneratorContext(libraryInfo); + + List asmBlocks = compiler.generateASM(new ASMGenerator(), referencedIlBlocks, asmGeneratorContext, true); + + if (options.has("verbose")) { + compiler.writeDivider(out); + for (ILBlock block : referencedIlBlocks) { + out.println(block.toString()); + } + compiler.writeDivider(out); + compiler.writeASMBlocks(out, asmBlocks); + compiler.writeDivider(out); + out.flush(); + } + + FileWriter outputWriter = new FileWriter(outputFile); + compiler.writeASMBlocks(outputWriter, asmBlocks); + outputWriter.flush(); + outputWriter.close(); + + } catch (Exception ex) { + System.out.println(ex.toString()); + } + Platform.exit(); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/ParseTreePretty.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/ParseTreePretty.java new file mode 100644 index 0000000..2498dde --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/ParseTreePretty.java @@ -0,0 +1,77 @@ +package uk.co.transputersystems.occam; + +import org.antlr.v4.runtime.Parser; +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.misc.Utils; +import org.antlr.v4.runtime.tree.ErrorNode; +import org.antlr.v4.runtime.tree.TerminalNode; +import org.antlr.v4.runtime.tree.Trees; + +import java.util.Arrays; +import java.util.List; + +public class ParseTreePretty extends OccamBaseListener { + + private final List ruleNames; + private final StringBuilder builder = new StringBuilder(); + + public ParseTreePretty(Parser parser) { + this.ruleNames = Arrays.asList(parser.getRuleNames()); + } + + public ParseTreePretty(List ruleNames) { + this.ruleNames = ruleNames; + } + + @Override + public void visitTerminal(TerminalNode node) { + if (builder.length() > 0) { + builder.append(' '); + } + + builder.append(Utils.escapeWhitespace(Trees.getNodeText(node, ruleNames), false)); + } + + @Override + public void visitErrorNode(ErrorNode node) { + if (builder.length() > 0) { + builder.append(' '); + } + + builder.append(Utils.escapeWhitespace(Trees.getNodeText(node, ruleNames), false)); + } + + @Override + public void enterEveryRule(ParserRuleContext ctx) { + if (builder.length() > 0) { + builder.append(' '); + } + + if (ctx.getChildCount() > 0) { + builder.append('('); + } + + int ruleIndex = ctx.getRuleIndex(); + String ruleName; + if (ruleIndex >= 0 && ruleIndex < ruleNames.size()) { + ruleName = ruleNames.get(ruleIndex); + } + else { + ruleName = Integer.toString(ruleIndex); + } + + builder.append(ruleName); + } + + @Override + public void exitEveryRule(ParserRuleContext ctx) { + if (ctx.getChildCount() > 0) { + builder.append(')'); + } + } + + @Override + public String toString() { + return builder.toString(); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/ReferencedTSILGenerator.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/ReferencedTSILGenerator.java new file mode 100644 index 0000000..c8e52d4 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/ReferencedTSILGenerator.java @@ -0,0 +1,342 @@ +package uk.co.transputersystems.occam; + +import uk.co.transputersystems.occam.il.*; + +/** + * Visitor for converting `ILOp`s to `ILOp`s, where the `Integer` is the offset of that `ILOp` in the + * `ILBlock` passed as context to the `visit()` method. + * @param Usually `UUID`, but this may change if the unique `ILOp` identifiers change. + */ +public class ReferencedTSILGenerator extends ILOpVisitor,TIdentifier,ILBlock>> { + + @Override + public ILOp visitMethodStart(MethodStart op, ILBlock> ctx) { + return new MethodStart<>(ctx.getOffset(op), op.getComment()); + } + + @Override + public ILOp visitMethodEnd(MethodEnd op, ILBlock> ctx) { + return new MethodEnd<>(ctx.getOffset(op), op.getComment()); + } + + @Override + public ILOp visitStartProcess(StartProcess op, ILBlock> ctx) { + return new StartProcess<>(ctx.getOffset(op), ctx.getOffset(op.firstILOpID), op.newPriority, op.getComment()); + } + + @Override + public ILOp visitEndProcess(EndProcess op, ILBlock> ctx) { + return new EndProcess<>(ctx.getOffset(op), ctx.getOffset(op.creatorILOpID), op.getComment()); + } + + @Override + public ILOp visitInitProcesses(InitProcesses op, ILBlock> ctx) { + return new InitProcesses<>(ctx.getOffset(op), op.numProcesses, ctx.getOffset(op.continueILOpID), op.workspaceIds, op.getComment()); + } + + @Override + public ILOp visitSkip(Skip op, ILBlock> ctx) { + return new Skip<>(ctx.getOffset(op), op.getComment()); + } + + @Override + public ILOp visitLabel(Label op, ILBlock> ctx) { + return new Label<>(ctx.getOffset(op), op.label, op.isGlobal, op.getComment()); + } + + @Override + public ILOp visitLoadConstant(LoadConstant op, ILBlock> ctx) { + return new LoadConstant<>(ctx.getOffset(op), op.value, op.getComment()); + } + + @Override + public ILOp visitLoadLocal(LoadLocal op, ILBlock> ctx) { + return new LoadLocal<>(ctx.getOffset(op), op.index, op.getComment(), op.loadAddress); + } + + @Override + public ILOp visitLoadArgument(LoadArgument op, ILBlock> ctx) { + return new LoadArgument<>(ctx.getOffset(op), op.index, op.getComment(), op.loadAddress); + } + + @Override + public ILOp visitLoadGlobal(LoadGlobal op, ILBlock> ctx) { + return new LoadGlobal<>(ctx.getOffset(op), op.globalName, op.getComment(), op.loadAddress); + } + + @Override + public ILOp visitStoreLocal(StoreLocal op, ILBlock> ctx) { + return new StoreLocal<>(ctx.getOffset(op), op.index, op.getComment()); + } + + @Override + public ILOp visitStoreArgument(StoreArgument op, ILBlock> ctx) { + return new StoreArgument<>(ctx.getOffset(op), op.index, op.getComment()); + } + + @Override + public ILOp visitStoreGlobal(StoreGlobal op, ILBlock> ctx) { + return new StoreGlobal<>(ctx.getOffset(op), op.globalName, op.getComment()); + } + + @Override + public ILOp visitReadChannel(ReadChannel op, ILBlock> ctx) { + return new ReadChannel<>(ctx.getOffset(op), op.getComment()); + } + + @Override + public ILOp visitAdd(Add op, ILBlock> ctx) { + return new Add<>(ctx.getOffset(op), op.ignore_overflow, op.getComment()); + } + + @Override + public ILOp visitSubtract(Subtract op, ILBlock> ctx) { + return new Subtract<>(ctx.getOffset(op), op.ignore_overflow, op.getComment()); + } + + @Override + public ILOp visitMultiply(Multiply op, ILBlock> ctx) { + return new Multiply<>(ctx.getOffset(op), op.ignore_overflow, op.getComment()); + } + + @Override + public ILOp visitDuplicate(Duplicate op, ILBlock> ctx) { + return new Duplicate<>(ctx.getOffset(op), op.getComment()); + } + + @Override + public ILOp visitUnaryMinus(UnaryMinus op, ILBlock> ctx) { + return new UnaryMinus<>(ctx.getOffset(op) , op.ignore_overflow , op.getComment()); + } + + @Override + public ILOp visitBranchEqZero(BranchEqZero op, ILBlock> ctx) { + return new BranchEqZero<>(ctx.getOffset(op), ctx.getOffset(op.target), op.getComment()); + } + + @Override + public ILOp visitBranchNotEqZero(BranchNotEqZero op, ILBlock> ctx) { + return new BranchNotEqZero<>(ctx.getOffset(op), ctx.getOffset(op.target), op.getComment()); + } + + @Override + public ILOp visitBranch(Branch op, ILBlock> ctx) { + return new Branch<>(ctx.getOffset(op), ctx.getOffset(op.target), op.getComment()); + } + + @Override + public ILOp visitCompareGreaterThan(CompareGreaterThan op, ILBlock> ctx) { + return new CompareGreaterThan<>(ctx.getOffset(op), op.getComment()); + } + + @Override + public ILOp visitCompareGreaterThanOrEqual(CompareGreaterThanOrEqual op, ILBlock> ctx) { + return new CompareGreaterThanOrEqual<>(ctx.getOffset(op), op.getComment()); + } + + @Override + public ILOp visitBranchIfTrue(BranchIfTrue op, ILBlock> ctx) { + return new BranchIfTrue<>(ctx.getOffset(op), ctx.getOffset(op.target), op.getComment()); + } + + @Override + public ILOp visitBranchIfFalse(BranchIfFalse op, ILBlock> ctx) { + return new BranchIfFalse<>(ctx.getOffset(op), ctx.getOffset(op.target), op.getComment()); + } + + @Override + public ILOp visitCompareLessThan(CompareLessThan op, ILBlock> ctx) { + return new CompareLessThan<>(ctx.getOffset(op), op.getComment()); + } + + @Override + public ILOp visitCompareLessThanOrEqual(CompareLessThanOrEqual op, ILBlock> ctx) { + return new CompareLessThanOrEqual<>(ctx.getOffset(op), op.getComment()); + } + + @Override + public ILOp visitCompareEqual(CompareEqual op, ILBlock> ctx) { + return new CompareEqual<>(ctx.getOffset(op), op.getComment()); + } + + @Override + public ILOp visitCompareNotEqual(CompareNotEqual op, ILBlock> ctx) { + return new CompareNotEqual<>(ctx.getOffset(op), op.getComment()); + } + + @Override + public ILOp visitBitwiseAnd(BitwiseAnd op, ILBlock> ctx) { + return new BitwiseAnd<>(ctx.getOffset(op), op.getComment()); + } + + @Override + public ILOp visitBitwiseOr(BitwiseOr op, ILBlock> ctx) { + return new BitwiseOr<>(ctx.getOffset(op), op.getComment()); + } + + @Override + public ILOp visitBitwiseNot(BitwiseNot op, ILBlock> ctx) { + return new BitwiseNot<>(ctx.getOffset(op), op.getComment()); + } + + @Override + public ILOp visitBooleanNot(BooleanNot op, ILBlock> ctx) { + return new BooleanNot<>(ctx.getOffset(op), op.getComment()); + } + + @Override + public ILOp visitDivide(Divide op, ILBlock> ctx) { + return new Divide<>(ctx.getOffset(op), op.getComment()); + } + + @Override + public ILOp visitModulo(Modulo op, ILBlock> ctx) { + return new Modulo<>(ctx.getOffset(op), op.getComment()); + } + + @Override + public ILOp visitBitwiseXor(BitwiseXor op, ILBlock> ctx) { + return new BitwiseXor<>(ctx.getOffset(op), op.getComment()); + } + + @Override + public ILOp visitCall(Call op, ILBlock> ctx) { + return new Call<>(ctx.getOffset(op), op.functionName, op.getComment()); + } + + @Override + public ILOp visitWriteChannel(WriteChannel op, ILBlock> ctx) { + return new WriteChannel<>(ctx.getOffset(op) , op.getComment()); + } + + @Override + public ILOp visitReadPort(ReadPort op, ILBlock> ctx) { + return new ReadPort<>(ctx.getOffset(op), op.getComment()); + } + + @Override + public ILOp visitWritePort(WritePort op, ILBlock> ctx) { + return new WritePort<>(ctx.getOffset(op), op.getComment()); + } + + @Override + public ILOp visitReadTimer(ReadTimer op, ILBlock> ctx) { + return new ReadTimer<>(ctx.getOffset(op), op.getComment()); + } + + @Override + public ILOp visitInitChannel(InitChannel op, ILBlock> ctx) { + return new InitChannel<>(ctx.getOffset(op), op.name, op.index , op.typeName , op.getComment()); + } + + @Override + public ILOp visitLoadChannelRef(LoadChannelRef op, ILBlock> ctx) { + return new LoadChannelRef<>(ctx.getOffset(op) , op.index, op.getComment()); + } + + @Override + public ILOp visitLoadPortRef(LoadPortRef op, ILBlock> ctx) { + return new LoadPortRef<>(ctx.getOffset(op) , op.index , op.getComment()); + } + + @Override + public ILOp visitDelayedTimerInput(DelayedTimerInput op, ILBlock> ctx) { + return new DelayedTimerInput<>(ctx.getOffset(op), op.getComment()); + } + + + @Override + public ILOp visitAfter(After op, ILBlock> ctx) { + return new After<>(ctx.getOffset(op), op.getComment()); + } + + @Override + public ILOp visitLeftShift(LeftShift op, ILBlock> ctx) { + return new LeftShift<>(ctx.getOffset(op), op.getComment()); + } + + @Override + public ILOp visitRightShift(RightShift op, ILBlock> ctx) { + return new RightShift<>(ctx.getOffset(op), op.getComment()); + } + + @Override + public ILOp visitDisableChannel(DisableChannel op, ILBlock> ctx) { + return new DisableChannel<>( ctx.getOffset(op), ctx.getOffset(op.target) , ctx.getOffset(op.endAlt) , op.getComment()); + } + + @Override + public ILOp visitDisableSkip(DisableSkip op, ILBlock> ctx) { + return new DisableSkip<>( ctx.getOffset(op), ctx.getOffset(op.target), ctx.getOffset(op.endAlt) , op.getComment()); + } + + @Override + public ILOp visitDisableTimer(DisableTimer op, ILBlock> ctx) { + return new DisableTimer<>( ctx.getOffset(op), ctx.getOffset(op.target), ctx.getOffset(op.endAlt) , op.getComment()); + } + + @Override + public ILOp visitEnableChannel(EnableChannel op, ILBlock> ctx) { + return new EnableChannel<>(ctx.getOffset(op), op.getComment()); + } + + @Override + public ILOp visitEnableSkip(EnableSkip op, ILBlock> ctx) { + return new EnableSkip<>(ctx.getOffset(op), op.getComment()); + } + + @Override + public ILOp visitEnableTimer(EnableTimer op, ILBlock> ctx) { + return new EnableTimer<>(ctx.getOffset(op), op.getComment()); + } + + @Override + public ILOp visitInitAlt(InitAlt op, ILBlock> ctx) { + return new InitAlt<>(ctx.getOffset(op), op.getComment()); + } + + @Override + public ILOp visitEndAlt(EndAlt op, ILBlock> ctx) { + return new EndAlt<>(ctx.getOffset(op), op.getComment()); + } + + @Override + public ILOp visitWaitAlt(WaitAlt op, ILBlock> ctx) { + return new WaitAlt<>(ctx.getOffset(op), op.getComment()); + } + + @Override + public ILOp visitDisablePort(DisablePort op, ILBlock> ctx) { + return new DisablePort<>(ctx.getOffset(op), ctx.getOffset(op.target) , ctx.getOffset(op.endAlt) , op.getComment()); + } + + @Override + public ILOp visitEnablePort(EnablePort op, ILBlock> ctx) { + return new EnablePort<>(ctx.getOffset(op), op.getComment()); + } + + + @Override + public ILOp visitMostNegative(MostNegative op, ILBlock> ctx) { + return new MostNegative<>(ctx.getOffset(op), op.type , op.getComment()); + } + + @Override + public ILOp visitMostPositive(MostPositive op, ILBlock> ctx) { + return new MostPositive<>(ctx.getOffset(op), op.type , op.getComment()); + } + + + @Override + public ILOp visitBooleanAnd(BooleanAnd op, ILBlock> ctx) { + return new BooleanAnd<>(ctx.getOffset(op), op.getComment()); + } + + + @Override + public ILOp visitBooleanOr(BooleanOr op, ILBlock> ctx) { + return new BooleanOr<>(ctx.getOffset(op) , op.getComment()); + } +} + + diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/StringUtilities.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/StringUtilities.java new file mode 100644 index 0000000..676e698 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/StringUtilities.java @@ -0,0 +1,11 @@ +package uk.co.transputersystems.occam; + +public class StringUtilities { + public static String padRight(String s, int n) { + return String.format("%1$-" + n + "s", s); + } + + public static String padLeft(String s, int n) { + return String.format("%1$" + n + "s", s); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/TSILGenerator.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/TSILGenerator.java new file mode 100644 index 0000000..ef06272 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/TSILGenerator.java @@ -0,0 +1,3128 @@ +package uk.co.transputersystems.occam; + +import org.antlr.v4.runtime.tree.TerminalNode; +import sun.reflect.generics.reflectiveObjects.NotImplementedException; +import uk.co.transputersystems.occam.il.*; +import uk.co.transputersystems.occam.metadata.*; + +import java.util.*; + +public class TSILGenerator extends OccamBaseVisitor>>> { + + + private LibraryInformation libraryInfo; + + public TSILGenerator(LibraryInformation libraryInfo) { + super(); + + this.libraryInfo = libraryInfo; + } + + public LibraryInformation getLibraryInfo() { + return libraryInfo; + } + + public void setLibraryInfo(LibraryInformation libraryInfo) { + this.libraryInfo = libraryInfo; + } + + /* + + Sample function structure: + + @Override + public List>> visitSmall_stmt_skip(OccamParser.Small_stmt_skipContext ctx) { + List>> result = new ArrayList<>(); + //result.add(new ) + return result; + } + */ + + @Override + public List>> visitFile_input(OccamParser.File_inputContext ctx) { + List>> result = new ArrayList<>(); + for (OccamParser.SpecificationContext context : ctx.specification()) { + result.addAll(visit(context)); + } + return result; + } + + @Override + public List>> visitSpecificationAbrv(OccamParser.SpecificationAbrvContext ctx) { + return visit(ctx.abbreviation()); + } + + @Override + public List>> visitSpecificationDef(OccamParser.SpecificationDefContext ctx) { + return visit(ctx.definition()); + } + + @Override + public List>> visitSpecificationDec(OccamParser.SpecificationDecContext ctx) { + return visit(ctx.declaration()); + } + + /** + * Generates the il for a process definition. + * + * Syntax: + * + * ``` + * PROC name ( formal, formal ... ) + * statements + * ``` + * + * @param ctx + * @return + */ + @Override + public List>> visitDef_PROC(OccamParser.Def_PROCContext ctx) { + /* Notes: + * + * A process definition has the following grammar: + * PROC NAME '(' ( formal (',' formal)* )? ')' NL ( INDENT stmt DEDENT )? ':' + * + * A process is a flat list of il ops for the statements proceeded by a label for the + * process. The process needs to be added to the global state tracking for later. + * + */ + + Scope rootScope = libraryInfo.getCurrentScope(); + + // Everything inside the `PROC` is in a new scope, so add one to the stack + String procedureName = ctx.NAME().getText(); + Scope functionScope = libraryInfo.pushNewFunctionScope(procedureName); + + // Update the current scope with information about each of the `PROC`'s `formal`s + for (OccamParser.FormalContext formal : ctx.formal()) { + visit(formal); + } + + ILBlock> functionBlock = new ILBlock<>(functionScope.getScopeId(), true); + functionBlock.add(new Label(UUID.randomUUID(), procedureName, true, "")); + functionBlock.add(new MethodStart<>(UUID.randomUUID(), "Start of `" + procedureName + "`")); + + List>> statementBlocks = visit(ctx.stmt()); + List> > result = functionBlock.mergeBlockList(statementBlocks); + + while (libraryInfo.getCurrentScope() != rootScope) { + libraryInfo.popScope(); + } + + functionBlock.add(new MethodEnd<>(UUID.randomUUID(), "End of `" + procedureName + "`")); + + libraryInfo.getCurrentScope().pushConstruction(true); + + return result; + } + + /** + * Add a list of `formal`s (i.e. parameters) to the current function scope. + * Each formal can have a single specifier, but this may apply to multiple identifiers. + * + * Syntax: + * + * ``` + * specifier name [name, name ...] | VAL specifier name [name, name ...] + * ``` + * + * @param ctx An AST node containing a formal + * @return null + */ + @Override + public List>> visitFormal(OccamParser.FormalContext ctx) { + + // Add the `formal`'s `specifier` (i.e. data type) to the construction stack + visit(ctx.specifier()); + + // Retrieve the current scope and the type name that was just pushed to the construction stack + Function functionScope = (Function) libraryInfo.getCurrentScope(); + String typeName = (String) functionScope.popConstruction(); + + // Determine whether the `formal` is to be passed by value + boolean passByVal = (ctx.VAL() != null); + + // For each identifier, add an argument to the function's scope + for (TerminalNode nameNode : ctx.NAME()) { + functionScope.addArgument(new Argument(nameNode.getText(), typeName, passByVal)); + } + + // No need to return IL + return null; + } + + /** + * Wrapper method. + * Passes through to a method which adds the name of a type to the construction stack + * + * @param ctx A `specifier` AST node which is a `data_type` + * @return null + */ + @Override + public List>> visitSpecifier_data_type(OccamParser.Specifier_data_typeContext ctx) { + visit(ctx.data_type()); + return null; + } + + /** + * Add the "BOOL" type name to the construction stack. + * + * @param ctx A `data_type` AST node which is a `BOOL` + * @return null + */ + @Override + public List>> visitData_type_bool(OccamParser.Data_type_boolContext ctx) { + libraryInfo.getCurrentScope().pushConstruction("BOOL"); + return null; + } + + /** + * Add the "BYTE" type name to the construction stack. + * + * @param ctx A `data_type` AST node which is a `BYTE` + * @return null + */ + @Override + public List>> visitData_type_byte(OccamParser.Data_type_byteContext ctx) { + libraryInfo.getCurrentScope().pushConstruction("BYTE"); + return null; + } + + /** + * Add the "INT" type name to the construction stack. + * + * @param ctx A `data_type` AST node which is a `INT` + * @return null + */ + @Override + public List>> visitData_type_int(OccamParser.Data_type_intContext ctx) { + libraryInfo.getCurrentScope().pushConstruction("INT"); + return null; + } + + /** + * Add the "INT16" type name to the construction stack. + * + * @param ctx A `data_type` AST node which is a `INT16` + * @return null + */ + @Override + public List>> visitData_type_int16(OccamParser.Data_type_int16Context ctx) { + libraryInfo.getCurrentScope().pushConstruction("INT16"); + return null; + } + + /** + * Add the "INT32" type name to the construction stack. + * + * @param ctx A `data_type` AST node which is a `INT32` + * @return null + */ + @Override + public List>> visitData_type_int32(OccamParser.Data_type_int32Context ctx) { + libraryInfo.getCurrentScope().pushConstruction("INT32"); + return null; + } + + /** + * Add the "INT64" type name to the construction stack. + * + * @param ctx A `data_type` AST node which is a `INT64` + * @return null + */ + @Override + public List>> visitData_type_int64(OccamParser.Data_type_int64Context ctx) { + libraryInfo.getCurrentScope().pushConstruction("INT64"); + return null; + } + + /** + * Add the "REAL32" type name to the construction stack. + * + * @param ctx A `data_type` AST node which is a `REAL32` + * @return null + */ + @Override + public List>> visitData_type_real32(OccamParser.Data_type_real32Context ctx) { + libraryInfo.getCurrentScope().pushConstruction("REAL32"); + return null; + } + + /** + * Add the "REAL64" type name to the construction stack. + * + * @param ctx A `data_type` AST node which is a `REAL64` + * @return null + */ + @Override + public List>> visitData_type_real64(OccamParser.Data_type_real64Context ctx) { + libraryInfo.getCurrentScope().pushConstruction("REAL64"); + return null; + } + + /** + * Add the name of a record type to the construction stack. + * + * @param ctx A `data_type` AST node which contains a `NAME` - i.e. a custom type + * @return null + */ + @Override + public List>> visitData_type_name(OccamParser.Data_type_nameContext ctx) { + libraryInfo.getCurrentScope().pushConstruction(ctx.NAME().getText()); + return null; + } + + /** + * Add the name of an array type to the construction stack. + * + * @param ctx A `data_type` AST node which is an array + * @return null + */ + @Override + public List>> visitData_type_expr_data_type(OccamParser.Data_type_expr_data_typeContext ctx) { + + // Retrieve the current scope + Scope currentScope = libraryInfo.getCurrentScope(); + + // Get the type of the array + // Push type name to construction stack + visit(ctx.data_type()); + // Pop type name from construction stack + String typeName = (String) currentScope.popConstruction(); + + // Evaluate the (constant) expression specifying the array size + Integer expressionValue = -1; + if (ctx.expression() != null) { + // Push the expression value to the construction stack + visit(ctx.expression()); + // Pop the expression value from the construction stack + expressionValue = (Integer) currentScope.popConstruction(); + } + + // Push the name of the array type onto the construction stack + currentScope.pushConstruction("[" + expressionValue.toString() + "]" + typeName); + + return null; + } + + /** + * Visit each subexpression in a list of expressions, returning any IL code generated. + * + * Syntax: + * + * ``` + * expression [expression, expression ...] + * ``` + * + * @param ctx An `expression_list` AST node which is just a list of expressions. + * @return The IL ops for this list. + */ + @Override + public List>> visitExpression_list_expressions(OccamParser.Expression_list_expressionsContext ctx) { + // For each expression in the list, visit the expression and add any IL returned to the result + List>> ilBlocks = new ArrayList<>(); + for (OccamParser.ExpressionContext expression : ctx.expression()) { + List>> interimResult = visit(expression); + if (interimResult != null) { + if (interimResult.size() > 1) { + // TODO: can we remove this error? + throw new IllegalArgumentException("Cannot currently evaluate expressions in more than one IL Block."); + } + ilBlocks.addAll(interimResult); + } + } + + // Push number of expressions in this list onto construction stack + libraryInfo.getCurrentScope().pushConstruction(ctx.expression().size()); + + return ilBlocks; + } + + /** + * Visit each variable in a list of variables, returning any IL code generated. + * + * Syntax: + * + * ``` + * variable [variable, variable ...] + * ``` + * + * @param ctx A `variable_list` AST node + * @return The IL ops for this list. + */ + @Override + public List>> visitVariable_list(OccamParser.Variable_listContext ctx) { + + // Retrieve the current scope + Scope currentScope = libraryInfo.getCurrentScope(); + + List>> result = new ArrayList<>(); + List constructionResult = new ArrayList<>(); + + // For each variable in the list, visit it, add the resulting NamedOperand to the + // construction stack and then add any resulting IL to the return value + for (OccamParser.Named_operandContext variable : ctx.named_operand()) { + // TODO: specific action of this visit() + List>> interimResult = visit(variable); + constructionResult.add((NamedOperand) currentScope.popConstruction()); + if (interimResult != null) { + if (interimResult.size() > 1) { + //TODO: Throw an error + } + result.add(interimResult.get(0)); + } + } + + currentScope.pushConstruction(constructionResult); + + return result; + } + + /** + * Pass-through. + * + * @param ctx An `expression` AST node containing an `operand` + * @return The IL ops generated for the `operand`. + */ + @Override + public List>> visitExpression_operand(OccamParser.Expression_operandContext ctx) { + //TODO: This might need modifying for other parent situations (e.g. returning IL ops) + return visit(ctx.operand()); + } + + /** + * Pass-through. + * + * @param ctx An `expression` AST node containing a `literal` + * @return The IL ops generated for the `literal`. + */ + @Override + public List>> visitOperand_literal(OccamParser.Operand_literalContext ctx) { + //TODO: This might need modifying for other parent situations (e.g. returning IL ops) + return visit(ctx.literal()); + } + + /** + * TODO + * + * @param ctx An `operand` AST node containing a `variable` + * @return TODO + */ + @Override + public List>> visitOperand_variable(OccamParser.Operand_variableContext ctx) { + //TODO: This might need modifying for other parent situations (e.g. returning IL ops) + + // Visit the `variable`, which will retrieve its information from the library info + // and push it to the construction stack + visit(ctx.named_operand()); + + // Now retrieve the scope and pop the `variable` information from the construction stack + Scope currentScope = libraryInfo.getCurrentScope(); + NamedOperand operand = (NamedOperand) currentScope.popConstruction(); + + // Create an empty IL block + ILBlock> result = new ILBlock<>(); + + // If the operand is an `Abbreviation`, retrieve the actual operand the abbreviation represents + operand = TSILGeneratorHelpers.resolveAbbreviations(operand); + + // If the operand is a constant, push its value to the construction stack and add the IL ops for loading it + // to the result + if (operand.isConstant()) { + currentScope.pushConstruction(operand.getConstantValue()); + result.appendBlock(TSILGeneratorHelpers.loadConstant(operand.getConstantValue(), operand.getTypeName())); + } else { + // Otherwise, push the `NamedOperand` itself to the construction stack + currentScope.pushConstruction(operand); + + // Depending on the kind of the operand, add the appropriate Load* instruction to the ILBlock + if (operand instanceof Variable) { + Variable variable = (Variable) operand; + if (libraryInfo.isGlobal(variable)) { + result.add(new LoadGlobal<>(UUID.randomUUID(), variable.getName(), "", false)); + } else { + result.add(new LoadLocal<>(UUID.randomUUID(), variable.getIndex(), "", false)); + } + } else if (operand instanceof Argument) { + Argument argument = (Argument) operand; + result.add(new LoadArgument<>(UUID.randomUUID(), argument.getIndex(), "", false)); + } else if (operand instanceof ArrayAbbreviation) { + throw new NotImplementedException(); + //TODO: Load Reference + //TODO: Load Element + } + } + + return Collections.singletonList(result); + } + + /** + * Generate the IL required to load a literal integer, and push the value of the literal onto the construction stack. + * @param ctx A `literal_integer` AST node + * @return The IL ops required to load the integer. + */ + @Override + public List>> visitLiteral_integer(OccamParser.Literal_integerContext ctx) { + //TODO: Handle data type specifier + //TODO: Handle the other literal types + + // Retrieve the current scope + Scope currentScope = libraryInfo.getCurrentScope(); + + // Initialise an empty list of IL ops + ILBlock> result = new ILBlock<>(); + + // Get the source text representing the integer + String valueStr = ctx.INTEGER().getText(); + Long value; + + if (valueStr.startsWith("#")) { + // Parse the string as a hex integer + value = Long.valueOf(valueStr.substring(1), 16); + } else { + // Or parse the string as a decimal integer + value = Long.valueOf(valueStr, 10); + } + + // Push the parsed value of the literal integer onto the construction stack + currentScope.pushConstruction(value); + + // Generate the IL ops for loading the literal and add them to the result + //TODO: Take into account the type specifier + result.appendBlock(TSILGeneratorHelpers.loadConstant(value, "INT")); + + return Collections.singletonList(result); + } + + /** + * Generate the IL required to load a literal byte, and push the value of the byte onto the construction stack. + * @param ctx A `literal_byte` AST node + * @return The IL ops required to load the byte. + */ + @Override + public List>> visitLiteral_byte(OccamParser.Literal_byteContext ctx) { + ILBlock> result = new ILBlock<>(); + + // Retrieve the byte literal text from the parse tree + String byteLiteral = ctx.BYTE_LITERAL().getText(); + + // Remove the quote marks and convert the literal to an integer value + int byteValue = TSILGeneratorHelpers.parseCharacterLiteral(byteLiteral.substring(1, byteLiteral.length() - 1)); + + // Generate IL op for loading the literal + result.add(new LoadConstant<>(UUID.randomUUID(), String.valueOf(byteValue), "Byte literal: " + byteLiteral)); + + // Push the parsed value of the literal onto the construction stack + libraryInfo.getCurrentScope().pushConstruction(byteValue); + + return Collections.singletonList(result); + } + + /** + * Generate the IL required to load a `true` boolean literal, and push it onto the construction stack. + * @param ctx A `literal_true` AST node + * @return The IL ops required to load the `true` value + */ + @Override + public List>> visitLiteral_true(OccamParser.Literal_trueContext ctx) { + ILBlock> result = new ILBlock<>(); + + result.add(new LoadConstant<>(UUID.randomUUID(), "1", "")); + libraryInfo.getCurrentScope().pushConstruction("1"); + + return Collections.singletonList(result); + } + + /** + * Generate the IL required to load a `false` boolean literal, and push it onto the construction stack. + * @param ctx A `literal_false` AST node + * @return The IL ops required to load the `false` value + */ + @Override + public List>> visitLiteral_false(OccamParser.Literal_falseContext ctx) { + ILBlock> result = new ILBlock<>(); + + result.add(new LoadConstant<>(UUID.randomUUID(), "0", "")); + libraryInfo.getCurrentScope().pushConstruction("0"); + + return Collections.singletonList(result); + } + + + + /** + * Pass-through. + * + * @param ctx A `stmt` AST node of type `compound_stmt` + * @return The result of visiting the `compound_stmt` + */ + @Override + public List>> visitStmt_compound_stmt(OccamParser.Stmt_compound_stmtContext ctx) { + return visit(ctx.compound_stmt()); + } + + /** + * Pass-through. + * + * @param ctx A `stmt` AST node of type `simple_stmt` + * @return The result of visiting the `simple_stmt` + */ + @Override + public List>> visitStmt_simple_stmt(OccamParser.Stmt_simple_stmtContext ctx) { + return visit(ctx.simple_stmt()); + } + + /** + * Generate the IL required for a `PRI` or `PRI PAR` block. + * TODO: what is pushed to the construction stack? + * + * ``` + * PAR + * simple_stmt | stmt + * stmt? + * stmt? + * ``` + * + * or + * + * ``` + * PRI PAR + * simple_stmt | stmt + * stmt? + * stmt? + * ``` + * + * @param ctx A (non-replicated) `parallel` AST node containing a `PAR` or `PRI PAR` + * @return TODO + */ + @Override + public List>> visitParallel_pripar_suite(OccamParser.Parallel_pripar_suiteContext ctx) { + if (ctx.PRI() != null) { + //TODO: Priority parallels need implementing + throw new NotImplementedException(); + //return null; + } else { + /* Notes: + * Normal parallel has the following structure: + * + * PAR + * suite + * suite + * + * where suite is: + * + * stmt + * stmt + * ... + * + * or: + * + * simple_stmt + * + * In either case, the statements in the suite constitute independent il blocks that will be executed in + * parallel. + * + * Parallel is implemented as follows in the IL: + * + * [IDSx = ID of the StartProcess IL op for the block at index x] + * [IDRx = ID of the first IL op for the block at index x] + * + * IDS0 : InitProcesses (n, IDEnd) + * IDS1 : StartProcess (IDR1) + * IDS(x) : StartProcess (IDRx) + * ... + * IDS(n-1): StartProcess (IDR(n-1)) + * + * + * [Statements for block 0] + * EndProcess (IDS0) + * + * IDR1 : [Statements for block 1] + * EndProcess (IDS1) + * + * IDRx : [Statements for block x] + * EndProcess (IDSx) + * + * ... + * + * IDR(n-1): Statements for block n-1 + * EndProcess (IDS(n-1)) + * + * IDEnd : SKIP + * + * The final SKIP operation is the end of the parallel block at which + * the process should continue executing. + */ + + // Push 'true' onto the construction stack of the current scope + // Popped by visiting the suite. Indicates that the statements within the suite + // will be executed in parallel (i.e. in new processes) as opposed to in sequence + // (i.e. in the current process) + libraryInfo.getCurrentScope().pushConstruction(true); + + // Get the current scope + Scope currentScope = libraryInfo.getCurrentScope(); + + // Get the total number of child scopes already in existence, prior to processing the suite + // * This acts as the starting index for new scopes created by visiting the suite + // * The suite is for a parallel (see pushConstruction(true) above) and thus a new scope + // will be created for each statement within the suite + // * Each scope created by visiting the suite is also a new workspace because it will be + // executing in a new process + int childScopeIndex = currentScope.getChildren().size(); + + // Generate the IL for the statements inside the PAR block + // * Visiting the suite also causes a new scope to be created for each statement within the suite + // (see above for more details) + List>> statementBlocks = visit(ctx.suite()); + + // Initialise an array to store the workspace IDs of each parallel process (i.e. statement) + List workspaceIds = new ArrayList<>(statementBlocks.size()); + + // Retrieve child scopes from the current scope + List childScopes = currentScope.getChildren(); + + // Register the workspace ID for each process + // The new workspaces (i.e. new scopes) for each new process (i.e. each statement within the suite) + // were created visiting the suite. They will have been added as children to the current scope. + // Thus all scopes from the index before processing the suite (see above) to the last one in the list + // are new workspaces for the new processes of the parallel. + for (int i = 0; i < statementBlocks.size(); i++) { + Scope theChildScope = childScopes.get(childScopeIndex + i); + workspaceIds.add(theChildScope.getWorkspace().getId()); + } + + // Now generate the parallelised IL code for the statements (see Javadoc comment) + ILBlock> result = TSILGeneratorHelpers.parallel(statementBlocks, workspaceIds); + + return Collections.singletonList(result); + } + } + + + @Override + public List>> visitParallel_pripar_replicator(OccamParser.Parallel_pripar_replicatorContext ctx) { + if (ctx.PRI() != null) { + //TODO: Priority parallels need implementing + + return null; + } else { + /* Notes: + * Normal replicated parallel has the following structure: + * + * PAR x = base FOR count + * STMT + * + * Replicated parallel is implemented just like a normal parallel but where the + * IL for each parallel process is re-processed each time with the replicator variable + * defined as a (constant) value abbreviation. + */ + + //TODO: Allow base and count to be runtime variables instead of requiring constants + + Scope rootScope = libraryInfo.getCurrentScope(); + + visit(ctx.replicator()); + + List replicatorAbbreviations = (List) rootScope.popConstruction(); + List>> statementBlocks = new ArrayList<>(); + List workspaceIds = new ArrayList<>(); + boolean doneFirst = false; + for (ValueAbbreviation replicatorAbbreviation : replicatorAbbreviations) { + Scope newScope = libraryInfo.pushNewScope(); + Integer newWorkspaceId; + // The first new process of a set of parallels actually executes in the current process, so no + // new workspace is created + if (doneFirst) { + newWorkspaceId = newScope.newWorkspace(false).getId(); + } else { + newWorkspaceId = newScope.getWorkspace().getId(); + } + workspaceIds.add(newWorkspaceId); + libraryInfo.getCurrentScope().addAbbreviation(replicatorAbbreviation); + List>> statementBlock = visit(ctx.stmt()); + statementBlocks.add(statementBlock.get(0)); + libraryInfo.popScope(); + + doneFirst = true; + } + + ILBlock> result = TSILGeneratorHelpers.parallel(statementBlocks, workspaceIds); + return Arrays.asList(result); + } + } + + @Override + public List>> visitReplicator(OccamParser.ReplicatorContext ctx) { + + //TODO: Allow non-constant (i.e. runtime variable) base + //TODO: Allow non-constant (i.e. runtime variable) count + + Scope currentScope = libraryInfo.getCurrentScope(); + + String name = ctx.NAME().getText(); + + visit(ctx.base()); + Long base = (Long) currentScope.popConstruction(); + visit(ctx.count()); + Long count = (Long) currentScope.popConstruction(); + List result = new ArrayList<>(); + for (Integer i = 0; i < count; i++) { + result.add(new ValueAbbreviation<>(null, name, "INT", i + base)); + } + currentScope.pushConstruction(result); + + return null; + } + + @Override + public List>> visitBase(OccamParser.BaseContext ctx) { + visit(ctx.expression()); + return null; + } + + @Override + public List>> visitCount(OccamParser.CountContext ctx) { + visit(ctx.expression()); + return null; + } + + /** + * Generate the IL for a suite (i.e. a group of statements). Expects a boolean on top of the construction stack + * where `true` indicates that the statements are going to be executed in parallel (`false` indicates sequential). + * + * @param ctx The `suite` AST node + * @return The IL ops generated for the suite + */ + @Override + public List>> visitSuite(OccamParser.SuiteContext ctx) { + List>> result; + + // Determine, from the construction stack, whether this suite is inside a parallel block. If so, the management + // of scopes and workspaces is different + boolean forParallel = (Boolean) libraryInfo.getCurrentScope().popConstruction(); + + // Get the initial scope + Scope rootScope = libraryInfo.getCurrentScope(); + + // If the suite contains a `simple_stmt`, process that + if (ctx.simple_stmt() != null) { + // If the statement should be executed in parallel, create a new scope + // but let the caller decide whether to associate it with a new workspace or not + if (forParallel) { + Scope newScope = libraryInfo.pushNewScope(); + } + + // Generate the IL ops for the statement + result = visit(ctx.simple_stmt()); + + // Pop scopes until we return to the original scope we had on entering this method + if (forParallel) { + while (libraryInfo.getCurrentScope() != rootScope) { + libraryInfo.popScope(); + } + } + } else { + // Otherwise, process each statement in turn. + result = new ArrayList<>(); + boolean doneFirst = false; + for (OccamParser.StmtContext statement : ctx.stmt()) { + // If the statements should be executed in parallel, create a new scope for this statement and, + // if it is not the first statement in the parallel, associate it with a new workspace + if (forParallel) { + Scope newScope = libraryInfo.pushNewScope(); + if (doneFirst) { + newScope.newWorkspace(false); + } + doneFirst = true; + } + + // Generate the IL blocks for this statement + List>> blocks = visit(statement); + + // Return to the scope we were in on entering this method + if (forParallel) { + while (libraryInfo.getCurrentScope() != rootScope) { + libraryInfo.popScope(); + } + } + + // If some IL ops were returned, add them to the result + // TODO: in future, the compiler should throw an error here if nothing is returned. A null result is ignored for now because not many features are implemented + if (blocks != null) { + result.addAll(blocks); + } + } + } + + // If the statements were to be executed sequentially, we will not have returned to the original scope yet - + // so do it now + if (!forParallel) { + while (libraryInfo.getCurrentScope() != rootScope) { + libraryInfo.popScope(); + } + } + + return result; + } + + @Override + public List>> visitSimple_stmt(OccamParser.Simple_stmtContext ctx) { + return visit(ctx.small_stmt()); + } + + @Override + public List>> visitSmall_stmt_skip(OccamParser.Small_stmt_skipContext ctx) { + List>> result = new ArrayList<>(); + result.add(new ILBlock<>(new Skip<>(UUID.randomUUID(), ""))); + return result; + } + + @Override + public List>> visitSmall_stmt_assignment(OccamParser.Small_stmt_assignmentContext ctx) { + return visit(ctx.assignment()); + } + + @Override + public List>> visitSmall_stmt_input(OccamParser.Small_stmt_inputContext ctx) { + List>> ilBlocks = visit(ctx.input()); + //Discard the two values on the construction stack from visiting input + libraryInfo.getCurrentScope().popConstruction(); + libraryInfo.getCurrentScope().popConstruction(); + return ilBlocks; + } + + @Override + public List>> visitAssignment(OccamParser.AssignmentContext ctx) { + /* Notes: + * + * Structure: + * Statements for expression 0 + * ... + * Statements for expression n + * Store [local/argument/global] n + * ... + * Store [local/argument/global] 0 + */ + + Scope currentScope = libraryInfo.getCurrentScope(); + + visit(ctx.variable_list()); + List lvalues = (List) currentScope.popConstruction(); + ILBlock> opILBlock = new ILBlock<>(); + List>> rvalueBlocks = opILBlock.mergeBlockList(visit(ctx.expression_list())); + + Integer numRvalues = (Integer) currentScope.popConstruction(); + + if (lvalues.size() != numRvalues) { + throw new IllegalArgumentException("Assignments must have the same number of l-values as r-values."); + } + + // Add IL ops to store expression values. Note: Storing happens in reverse order. + for (int i = numRvalues - 1; i > -1; i--) { + //NOTE: These could be variables, arguments or abbreviations + NamedOperand operand = lvalues.get(i); + + operand = TSILGeneratorHelpers.resolveAbbreviations(operand); + + if (operand instanceof Variable) { + Variable variable = (Variable) operand; + if (libraryInfo.isGlobal(variable)) { + opILBlock.add(new StoreGlobal<>(UUID.randomUUID(), variable.getName(), "")); + } else { + opILBlock.add(new StoreLocal<>(UUID.randomUUID(), variable.getIndex(), "")); + } + } else if (operand instanceof Argument) { + Argument argument = (Argument) operand; + opILBlock.add(new StoreArgument<>(UUID.randomUUID(), argument.getIndex(), "")); + } else if (operand instanceof ArrayAbbreviation) { + //TODO: Load Reference + //TODO: Store Element + } + } + + return rvalueBlocks; + } + + @Override + public List>> visitDeclaration(OccamParser.DeclarationContext ctx) { + Scope currentScope = libraryInfo.getCurrentScope(); + + ILBlock> ilBlock = new ILBlock<>(); + + if (ctx.data_type() != null) { + visit(ctx.data_type()); + + String dataTypeName = (String) currentScope.getConstructionStack().pop(); + + for (TerminalNode name : ctx.NAME()) { + currentScope.addVariable(name.getText(), dataTypeName); + if (!(currentScope instanceof FileInformation)) { + currentScope = libraryInfo.pushNewScope(); + } + } + + + } else if (ctx.channel_type() != null) { + visit(ctx.channel_type()); + + String dataTypeName = (String) currentScope.getConstructionStack().pop(); + + for (TerminalNode name : ctx.NAME()) { + currentScope.addChannel(name.getText(), dataTypeName); + ilBlock.add(new InitChannel<>(UUID.randomUUID(), name.getText(), currentScope.getChannel(name.getText()).getIndex(), dataTypeName , "")); + if (!(currentScope instanceof FileInformation)) { + currentScope = libraryInfo.pushNewScope(); + } + } + + + } else if (ctx.port_type() != null) { + + visit(ctx.port_type()); + + String dataTypeName = (String) currentScope.getConstructionStack().pop(); + + for (TerminalNode name : ctx.NAME()) { + currentScope.addPort(name.getText(), dataTypeName); + if (!(currentScope instanceof FileInformation)) { + currentScope = libraryInfo.pushNewScope(); + } + } + + + } else {//Timer type + //throw new NotImplementedException(); + } + + return Collections.singletonList(ilBlock); + } + + @Override + public List>> visitSequence_suite(OccamParser.Sequence_suiteContext ctx) { + /* Notes: + * Normal sequential has the following structure: + * + * SEQ + * SUITE + * SUITE + * + * Sequential is implemented as follows: + * + * Statements for block 0 + * ... + * Statements for block n + */ + + ILBlock> result = new ILBlock<>(); + libraryInfo.getCurrentScope().pushConstruction(false); + List>> statementBlocks = visit(ctx.suite()); + return result.mergeBlockList(statementBlocks); + } + + @Override + public List>> visitChannel_type_protocol(OccamParser.Channel_type_protocolContext ctx) { + return visit(ctx.protocol()); + } + + + @Override + public List>> visitProtcol_name(OccamParser.Protcol_nameContext ctx) { + String name = ctx.NAME().getText(); + libraryInfo.getCurrentScope().pushConstruction(name); + return null; + } + + + @Override + public List>> visitOutputitem_single_expression(OccamParser.Outputitem_single_expressionContext ctx) { + return visit(ctx.expression()); + } + + + @Override + public List>> visitPort_type_data_type(OccamParser.Port_type_data_typeContext ctx) { + return visit(ctx.data_type()); + } + + + @Override + public List>> visitCase_expression(OccamParser.Case_expressionContext ctx) { + return visit(ctx.expression()); + } + + @Override + public List>> visitChannel_name(OccamParser.Channel_nameContext ctx) { + String name = ctx.NAME().getText(); + NamedOperand namedOperand = libraryInfo.searchForNamedOperand(name); + + if (namedOperand instanceof Channel) { + + libraryInfo.getCurrentScope().pushConstruction(namedOperand); + + } else { + + //Throw error, we should be dealing with channels + } + + return null; + } + + @Override + public List>> visitInput_named_operand_input_items(OccamParser.Input_named_operand_input_itemsContext ctx) { + + Scope currentScope = libraryInfo.getCurrentScope(); + + visit(ctx.named_operand()); + + //We have channel on the scope construction stack + NamedOperand namedOperand = (NamedOperand) libraryInfo.getCurrentScope().popConstruction(); + + namedOperand = TSILGeneratorHelpers.resolveAbbreviations(namedOperand); + + ILBlock> ilBlock = new ILBlock<>(); + + if (namedOperand instanceof Channel) { + + Iterator itemContextIterator = ctx.input_item().iterator(); + + try { + + while (itemContextIterator.hasNext()) { + + OccamParser.Input_itemContext input_itemContext = itemContextIterator.next(); + + visit(input_itemContext); + + NamedOperand stackTop = (NamedOperand) libraryInfo.getCurrentScope().popConstruction(); + + //TODO: Resolve abbreviations + + if (stackTop instanceof Variable) { + + Variable variable = (Variable) stackTop; + + if (libraryInfo.isGlobal(variable)) { + ilBlock.add(new LoadGlobal(UUID.randomUUID(), variable.getName(), "Load address", true)); + } else { + ilBlock.add(new LoadLocal(UUID.randomUUID(), variable.getIndex(), "Load address", true)); + } + + } else if(stackTop instanceof Argument) { + + ilBlock.add(new LoadArgument(UUID.randomUUID(), ((Argument) stackTop).getIndex(), "", true)); + + } else { + throw new NotImplementedException(); + } + + ilBlock.add(new LoadChannelRef<>(UUID.randomUUID(), ((Channel) namedOperand).getIndex(), "")); + ilBlock.add(new LoadConstant<>(UUID.randomUUID(), String.valueOf(libraryInfo.getTypeSize(namedOperand.getTypeName())), "")); + ilBlock.add(new ReadChannel<>(UUID.randomUUID(), "")); + + currentScope.pushConstruction(((Channel) namedOperand).getIndex()); + currentScope.pushConstruction("CHANNEL"); + + } + + }catch (Exception e){ + System.out.println("Error calculating variable size"); + System.exit(0); + } + + }else if (namedOperand instanceof Port) { + + try { + + visit(ctx.input_item(0)); + + Object stackTop = libraryInfo.getCurrentScope().popConstruction(); + + if (stackTop instanceof Variable) { + + Variable variable = (Variable) stackTop; + + if (libraryInfo.isGlobal(variable)) { + ilBlock.add(new LoadGlobal(UUID.randomUUID(), variable.getName(), "Load address", true)); + } else { + ilBlock.add(new LoadLocal(UUID.randomUUID(), variable.getIndex(), "Load address", true)); + } + + }else if(stackTop instanceof Argument){ + + ilBlock.add(new LoadArgument(UUID.randomUUID(), ((Argument) stackTop).getIndex(), "", true)); + + } else { + + throw new NotImplementedException(); + + } + + ilBlock.add(new LoadPortRef<>(UUID.randomUUID(), ((Port) namedOperand).getIndex(), "")); + ilBlock.add(new LoadConstant<>(UUID.randomUUID(), String.valueOf(libraryInfo.getTypeSize(namedOperand.getTypeName())), "")); + ilBlock.add(new ReadPort<>(UUID.randomUUID(), "")); + + currentScope.pushConstruction(((Port) namedOperand).getIndex()); + currentScope.pushConstruction("PORT"); + + }catch (Exception e){ + System.out.println("Error calculating variable size"); + System.exit(0); + } + + }else if (namedOperand instanceof uk.co.transputersystems.occam.metadata.Timer){ + + ilBlock.add(new ReadTimer<>(UUID.randomUUID(), "")); + + visit(ctx.input_item(0)); + + Object stackTop = libraryInfo.getCurrentScope().popConstruction(); + + if (stackTop instanceof Variable) { + + Variable variable = (Variable) stackTop; + + if (libraryInfo.isGlobal(variable)) { + ilBlock.add(new StoreGlobal<>(UUID.randomUUID(), variable.getName(), "" )); + } else { + ilBlock.add(new StoreLocal<>(UUID.randomUUID(), variable.getIndex(), "")); + } + + }else if(stackTop instanceof Argument){ + + ilBlock.add(new StoreArgument(UUID.randomUUID(), ((Argument) stackTop).getIndex(), "")); + + } else { + + throw new NotImplementedException(); + + } + + currentScope.pushConstruction("0"); + currentScope.pushConstruction("TIMER"); + + + } else if (namedOperand instanceof ArrayAbbreviation) { + //todo add ArrayAbbreviation channel implementation + throw new NotImplementedException(); + } else { + + throw new NotImplementedException(); + } + + return Collections.singletonList(ilBlock); + } + + @Override + public List>> visitInput_item_variable(OccamParser.Input_item_variableContext ctx) { + return visit(ctx.named_operand()); + } + + /** + * First visits the two operands and inserts the relevant ILOPs so + * the two values will be on the top of the stack + * The dyadic operator is then visited putting the correct ILOP's to calculate + * the values on the stack + * @param ctx An `expression_dyadic_operator` AST node + * @return The IL ops required to evaluate and load the dyadic expression. + */ + @Override + public List>> visitExpression_dyadic_operator(OccamParser.Expression_dyadic_operatorContext ctx) { + + ILBlock> result = new ILBlock<>(); + + // Visiting operand will return a List of ILBlocks + // An expression must return a single ILBlock + // Therefore we must manually add each element of the List>> + // to a single ILBlock + List>> lhs = visit(ctx.operand(0)); + + List>> rhs = visit(ctx.operand(1)); + + result.appendBlockList(lhs); + result.appendBlockList(rhs); + + //Two operands at top of the stack + //ready for the next instruction + List>> op = visit(ctx.dyadic_operator()); + + result.appendBlock(op.get(0)); + + return Collections.singletonList(result); + } + + /** + * Generate the IL ops to evaluate and load the result of a expression subject to a monadic operator. + * For example: + * ``` + * - (a+b) + * | +----> Expression + * +-------> Monadic operator + * + * ``` + * @param ctx An `expression_monadic` AST node + * @return The IL ops to evaluate and load the result of the monadic expression. + */ + @Override + public List>> visitExpression_monadic(OccamParser.Expression_monadicContext ctx) { + // Initialise an empty result + ILBlock> result_root = new ILBlock<>(); + List>> result_list = new ArrayList<>(); + + // Generate the IL ops that will load the monadic operator's operand onto the stack + List>> operandBlock = visit(ctx.operand()); + + // Append those IL ops to the result + result_list = result_root.mergeBlockList(operandBlock); + + // Generate the IL ops that will perform the correct monadic operation to the item currently on top of the stack + List>> monadicBlocks = visit(ctx.monadic_operator()); + result_list.addAll(monadicBlocks); + result_list = new ILBlock>().mergeBlockList(result_list); + + return result_list; + } + + /** + * Generate the IL ops to perform the provided monadic (unary) operation. + * The generated code assumes that the operand is already on the stack. + * @param ctx A `monadic_operator` AST node + * @return IL ops to perform the operation + */ + @Override + public List>> visitMonadic_operator(OccamParser.Monadic_operatorContext ctx) { + + ILBlock> result = new ILBlock<>(); + + if (ctx.NOT_KWD() != null) { + result.add(new BooleanNot<>(UUID.randomUUID(), "")); + } else if (ctx.BITWISE_NOT_KWD() != null) { + result.add(new BitwiseNot<>(UUID.randomUUID(), "")); + } else if (ctx.BITWISE_NOT() != null) { + result.add(new BitwiseNot<>(UUID.randomUUID(), "")); + } else if (ctx.MINUS() != null){ + result.add(new UnaryMinus<>(UUID.randomUUID(), false, "")); + } else if (ctx.MINUS_MOD() != null){ + result.add(new UnaryMinus<>(UUID.randomUUID(), true , "")); + } else if (ctx.SIZE() != null) { + throw new NotImplementedException(); + } + else { + throw new NotImplementedException(); + } + + return Collections.singletonList(result); + } + + /** + * Generate the IL ops to perform the provided dyadic (binary) operation. + * The generated code assumes that the two operands are already on the stack. + * @param ctx A `dyadic_operator` AST node. + * @return IL ops to perform the operation. + */ + @Override + public List>> visitDyadic_operator(OccamParser.Dyadic_operatorContext ctx) { + + ILBlock> ilBlock = new ILBlock<>(); + + //TODO: rest of operators + //TODO: document any obscure implementation details - especially for overflow-sensitive operations + + if (ctx.PLUS() != null) { + ilBlock.add(new Add<>(UUID.randomUUID(), false, "")); + } else if (ctx.MINUS() != null) { + ilBlock.add(new Subtract<>(UUID.randomUUID(), false, "")); + } else if (ctx.TIMES() != null) { + ilBlock.add(new Multiply<>(UUID.randomUUID(), false, "")); + } else if (ctx.DIVIDE() != null) { + ilBlock.add(new Divide<>(UUID.randomUUID(), "")); + } else if(ctx.PLUS_MOD() != null) { + ilBlock.add(new Add<>(UUID.randomUUID(), true, "")); + } else if(ctx.MINUS_MOD() != null){ + ilBlock.add(new Subtract<>(UUID.randomUUID(),true , "Minus modulo")); + } else if(ctx.TIMES_MOD() != null) { + ilBlock.add(new Multiply<>(UUID.randomUUID(), true, "")); + } else if(ctx.REM() != null) { + ilBlock.add(new Modulo<>(UUID.randomUUID(), "")); + } else if(ctx.BITWISE_AND() != null){ + ilBlock.add(new BitwiseAnd<>(UUID.randomUUID(), "")); + }else if(ctx.AND_KWD() != null) { + ilBlock.add(new BooleanAnd<>(UUID.randomUUID(), "")); + }else if (ctx.BITWISE_OR() != null) { + ilBlock.add(new BitwiseOr<>(UUID.randomUUID(), "")); + }else if(ctx.OR_KWD() != null) { + ilBlock.add(new BooleanOr<>(UUID.randomUUID(), "")); + } else if(ctx.XOR() != null) { + ilBlock.add(new BitwiseXor<>(UUID.randomUUID(), "")); + } else if(ctx.BITWISE_AND_KWD() != null){ + ilBlock.add(new BitwiseAnd<>(UUID.randomUUID(), "")); + } else if (ctx.GTHAN() != null) { + ilBlock.add(new CompareGreaterThan<>(UUID.randomUUID(), "")); + } else if (ctx.LTHAN() != null) { + ilBlock.add(new CompareLessThan<>(UUID.randomUUID(), "")); + } else if (ctx.EQUAL() != null) { + ilBlock.add(new CompareEqual<>(UUID.randomUUID(), "")); + } else if(ctx.BITOR() != null) { + ilBlock.add(new BitwiseOr<>(UUID.randomUUID(), "")); + } else if(ctx.NOTEQ() != null) { + ilBlock.add(new CompareNotEqual<>(UUID.randomUUID(), "")); + } else if(ctx.LTHANEQ() != null) { + ilBlock.add(new CompareLessThanOrEqual<>(UUID.randomUUID(), "")); + } else if(ctx.GTHANEQ() != null) { + ilBlock.add(new CompareGreaterThanOrEqual<>(UUID.randomUUID(), "")); + } else if(ctx.AFTER() != null) { + ilBlock.add(new After<>(UUID.randomUUID(),"")); + } else if(ctx.RIGHTSHIFT() != null ) { + ilBlock.add(new RightShift<>(UUID.randomUUID(),"")); + }else if(ctx.LEFTSHIFT() != null) { + ilBlock.add(new LeftShift<>(UUID.randomUUID(),"")); + } else { + throw new NotImplementedException(); + } + + return Collections.singletonList(ilBlock); + } + + + /** + * Pass-though to `visitExpression`. + * @param ctx An `operand_expression` AST node - i.e. an expression surround by parentheses. + */ + @Override + public List>> visitOperand_expression(OccamParser.Operand_expressionContext ctx) { + return visit(ctx.expression()); + } + + /** + * Pass-though to `visitConditional`. + * @param ctx A `choice_conditional` AST node. + */ + @Override + public List>> visitChoice_conditional(OccamParser.Choice_conditionalContext ctx) { + return visit(ctx.conditional()); + } + + /** + * Pass-though to `visitGuarded_choice`. + * @param ctx A `choice_guarded` AST node. + */ + @Override + public List>> visitChoice_guarded(OccamParser.Choice_guardedContext ctx) { + return visit(ctx.guarded_choice()); + } + + /** + * Visiting the conditional choices will generate the ILOP's for + * handling conditional choices + * It calculates each 'choice' in reverse order so each choice knows where + * to jump to if it's condition is false + * @param ctx 'Conditional choice' context + * @return List of ILBlocks for calculating the structure + */ + @Override + public List>> visitConditional_choices(OccamParser.Conditional_choicesContext ctx) { + + Scope currentScope = libraryInfo.getCurrentScope(); + + ILOp endLabel = new Label<>(UUID.randomUUID(), false, ""); + + currentScope.pushConstruction(endLabel); + + int choiceCount = ctx.choice().size(); + + + List>> result = new ArrayList<>(); + + /* + + Summary of the structure of the ILOp's returned + + Bool ilBlocks 0 + Conditional jump to stmt 0 + ... + ... + ... + Bool ilBlocks n + Conditional jump to stmt n + + + Label stmt 0 + Stmt ILBlock> 0 + jmp to end + ... + ... + ... + Label stmt n + Stmt ILBlock> n + jmp to end + + Label end + + + */ + + + for (int i = choiceCount - 1; i >= 0; i--) { + + libraryInfo.pushNewScope(); + + List>> choiceBlocks = visit(ctx.choice(i)); + + Label stmtLabel = new Label<>(UUID.randomUUID(), false, ""); + + ILBlock> boolBlock = choiceBlocks.get(0); + ILBlock> stmtBlock = choiceBlocks.get(1); + + //If true, branch to statement label + boolBlock.add(new BranchIfTrue<>(UUID.randomUUID(), stmtLabel.getId(), "")); + + //Label marking start of statement + stmtBlock.add(0, stmtLabel); + //Unconditional target to end of the structure + stmtBlock.add(new Branch<>(UUID.randomUUID(), endLabel.getId(), "")); + + //We are visiting the choices in reverse + //So add bool block to start of the list + result.add(0, boolBlock); + + //Add a statement block to the end of the list + result.add(stmtBlock); + + libraryInfo.popScope(); + + + } + + ILBlock> endBlock = new ILBlock<>(endLabel); + + result.add(endBlock); + + return result; + + } + + + /** + * Visiting a guarded choice context will calculate + * the ILBlock> for the boolean section and statement section + * A guarded choice has it's own scope. + * We push a new scope and pop one at the end of the method + * @param ctx Guarded choice context + * @return A list of two ILBlocks. Boolean block and Statement block + */ + @Override + public List>> visitGuarded_choice(OccamParser.Guarded_choiceContext ctx) { + + libraryInfo.pushNewScope(); + + List>> result = new ArrayList<>(); + + // Create the ILBlocks from the statements + List>> statements = visit(ctx.stmt()); + // Create the ILBlocks from the conditions + List>> conditionBlocks = visit(ctx.bool()); + + //Flatten the ILBlocks for calculating the boolean expression + ILBlock> conditionBlock = new ILBlock<>(); + + //Add the List of ILBlocks from stmts and bools into a + //single ILBlock> each. + conditionBlock.appendBlockList(conditionBlocks); + statements = statements.get(0).mergeBlockList(statements); + + result.add(conditionBlock); + result.addAll(statements); + + libraryInfo.popScope(); + + return result; + } + + @Override + public List>> visitBool(OccamParser.BoolContext ctx) { + return visit(ctx.expression()); + } + + @Override + public List>> visitLoop(OccamParser.LoopContext ctx) { + + //Branch bool-conditons + //Label stmts + //Statments + //... + //... + //Label bool-conditons + //Bool conditions + //Branch - stmts + + + ILBlock> result = new ILBlock<>(); + + ILOp boolLabel = new Label<>(UUID.randomUUID(), false, ""); + ILOp stmtLabel = new Label<>(UUID.randomUUID(), false, ""); + + result.add(new Branch<>(UUID.randomUUID(), boolLabel.getId(), "")); + result.add(stmtLabel); + + List>> stmtBlocks = visit(ctx.stmt()); + stmtBlocks = result.mergeBlockList(stmtBlocks); + + result.add(boolLabel); + + //Visit boolean condition and add the returned ILBlocks to the result + List>> boolBlocks = visit(ctx.bool()); + result.appendBlockList(boolBlocks); + + //If true target to statements + result.add(new BranchIfTrue<>(UUID.randomUUID(), stmtLabel.getId(), "")); + + return stmtBlocks; + } + + @Override + public List>> visitCase_input(OccamParser.Case_inputContext ctx) { + return super.visitCase_input(ctx); + } + + @Override + public List>> visitChoice_specification(OccamParser.Choice_specificationContext ctx) { + + //Visit the specification which will adjust the scope + visit(ctx.specification()); + + //Return the code ILBlocks generated from visiting the choice + return visit(ctx.choice()); + } + + + /** + * When visiting a replicated conditional we first visit the replicator + * context. Here we calculate the number of replications to make by returning a list of + * Value Abbreviations + * Currently this only supports constant number of replications due to the value being + * calculated at compile time. + * We then visit each choice, this generates ILBlocks from Bool and GuardedChoice context + * These ILBlocks are then organised and then added to the output of the method + * @param ctx + * @return + */ + @Override + public List>> visitConditional_replicator(OccamParser.Conditional_replicatorContext ctx) { + + Scope currentScope = libraryInfo.getCurrentScope(); + + List>> result = new ArrayList<>(); + + //Visiting replicator adds a list of ValueAbbreviations to the stack + //Currently does not support non-static variables + visit(ctx.replicator()); + + List replicatorAbbreviations = (List) currentScope.popConstruction(); + + Label exitReplicator = new Label<>(UUID.randomUUID(), false, ""); + + //Reverse the list so we can easily handle each value abbreviation in reverse + Collections.reverse(replicatorAbbreviations); + + /* + + Bool block 0 + Conditional jump to stmt 0 + ... + ... + ... + Bool block n + Conditional jump to stmt n + + Jump to end - If no bool returns true + Label stmt 0 + Stmt block 0 + jmp to end + ... + ... + ... + Label stmt n + Stmt block n + jmp to end + + Label end + + + */ + + //Jump to the end of the replicator block if all bool exp are false + result.add(new ILBlock<>(new Branch<>(UUID.randomUUID(), exitReplicator.getId(), ""))); + + for ( ValueAbbreviation valueAbbreviation : replicatorAbbreviations ){ + + Scope rootScope = libraryInfo.pushNewScope(); + + //Add the value abbreviation to the current scope + rootScope.addAbbreviation(valueAbbreviation); + + //Visiting the choice block will return a list of two ILBlocks + List>> choiceBlock = visit(ctx.choice()); + ILBlock> stmtBlock = choiceBlock.get(1); + ILBlock> boolBlock = choiceBlock.get(0); + + Label stmtLabel = new Label<>(UUID.randomUUID(), false, ""); + + //Branch to the statement if true + boolBlock.add(new BranchIfTrue<>(UUID.randomUUID(), stmtLabel.getId(), "")); + + //Add a label to the start of the statement + stmtBlock.add(0 , stmtLabel ); + //Add a unconditional target to the end of the structure + stmtBlock.add(new Branch<>(UUID.randomUUID(), exitReplicator.getId(), "")); + + //Add the bool block to the start of the ILBlock> list + result.add(0 , boolBlock); + + //Add the statement block to the end of the list + //The statement is independent so we don't care about it's position + result.add(stmtBlock); + + + libraryInfo.popScope(); + + } + result.add(new ILBlock<>(exitReplicator)); + return result; + } + + + + /* + * Visiting a selection generates the list of ILBlocks for the selection language feature + * @param ctx Selection context + * @return List of ILBlocks for the selection + */ + @Override + public List>> visitSelection(OccamParser.SelectionContext ctx) { + + List>> result = new ArrayList<>(); + // Label indicating the end of the selection block - jump here once one of the options has executed + Label exitLabel = new Label<>(UUID.randomUUID(), false, ""); + // The ops required to load the selector + List>> loadSelector = visit(ctx.selector()); + + for (OccamParser.OptionContext option : ctx.option()) { + libraryInfo.getCurrentScope().pushConstruction(exitLabel); + libraryInfo.getCurrentScope().pushConstruction(loadSelector); + result.addAll(visit(option)); + } + + //Exit label marking end of selection + result.add(new ILBlock(exitLabel)); + + return result; + } + + /* + * Visiting Option case expression block returns the ILBLock code for each 'option' and a single 'stmt' + * @param ctx The Option case expression context + * @return List of ILBlocks in the following format: Position 0:stmtBlock , rest of the list: option blocks + */ + public List>> visitOption_case_expression_stmt(OccamParser.Option_case_expression_stmtContext ctx) { + + List>> result = new ArrayList<>(); + + Scope currentScope = libraryInfo.getCurrentScope(); + + // Retrieve the ops required to load the selector so that we can compare our list of case_expressions against it + List>> loadSelector = (List>>)(List) currentScope.popConstruction(); + + // Retrieve the exit label for the whole selection block, which we jump to if the statement in this option actually gets executed + Label endLabel = (Label) currentScope.popConstruction(); + + libraryInfo.pushNewScope(); + + // Inserted just before the statement - jump to this if any of the case_expressions is true + Label stmt = new Label<>(UUID.randomUUID(), false, ""); + Label afterStmt = new Label(UUID.randomUUID(), false, ""); + + for(OccamParser.Case_expressionContext caseExpressionContext : ctx.case_expression()){ + result.addAll(loadSelector); + result.addAll(visit(caseExpressionContext)); + result.add(new ILBlock<>(new CompareEqual<>(UUID.randomUUID(), ""))); + result.add(new ILBlock<>(new BranchIfTrue<>(UUID.randomUUID(), stmt.getId(),""))); + } + + result.add(new ILBlock<>(new Branch<>(UUID.randomUUID() , afterStmt.getId(), ""))); + + result.add(new ILBlock<>(stmt)); + result.addAll(visit(ctx.stmt())); + result.add(new ILBlock<>(new Branch<>(UUID.randomUUID(), endLabel.getId(), ""))); + result.add(new ILBlock<>(afterStmt)); + + libraryInfo.popScope(); + + return result; + } + + @Override + public List>> visitOption_else(OccamParser.Option_elseContext ctx) { + + + Scope currentScope = libraryInfo.getCurrentScope(); + + // Retrieve the ops required to load the selector so that we can compare our list of case_expressions against it + // However we can discard the result as we are in the ELSE section + currentScope.popConstruction(); + + // Retrieve the exit label for the whole selection block, which we jump to if the statement in this option actually gets executed + Label endLabel = (Label) currentScope.popConstruction(); + + libraryInfo.pushNewScope(); + + List>> result = new ArrayList<>(); + + List>> stmt = visit(ctx.stmt()); + + result.addAll(stmt); + result.add(new ILBlock<>(new Branch(UUID.randomUUID(), endLabel.getId(), ""))); + + libraryInfo.popScope(); + + return result; + } + + + + + /** + * Visits the sequence that makes up the compound statement. + */ + @Override public List>> visitCompound_stmt_sequence(OccamParser.Compound_stmt_sequenceContext ctx) { return visit(ctx.sequence()); } + /** + * Visits the conditional that makes up the compound statement. + */ + @Override public List>> visitCompound_stmt_conditional(OccamParser.Compound_stmt_conditionalContext ctx) { return visit(ctx.conditional()); } + /** + * Visits the selection that makes up the compound statement. + */ + @Override public List>> visitCompound_stmt_selection(OccamParser.Compound_stmt_selectionContext ctx) { return visit(ctx.selection()); } + /** + * Visits the loop that makes up the compound statement. + */ + @Override public List>> visitCompound_stmt_loop(OccamParser.Compound_stmt_loopContext ctx) { return visit(ctx.loop()); } + /** + * Visits the parallel that makes up the compound statement. + */ + @Override public List>> visitCompound_stmt_parallel(OccamParser.Compound_stmt_parallelContext ctx) { return visit(ctx.parallel()); } + /** + * Visits the alternation that makes up the compound statement. + */ + @Override public List>> visitCompound_stmt_alternation(OccamParser.Compound_stmt_alternationContext ctx) { return visit(ctx.alternation()); } + /** + * Visits the case input that makes up the compound statement. + */ + @Override public List>> visitCompound_stmt_case_input(OccamParser.Compound_stmt_case_inputContext ctx) { return visit(ctx.case_input()); } + /** + * Implements visiting a compound statement which is made up of either a "specification with statement(s)" or an "allocation with statements". + * + * The IL will either continue as expected, or become part of a separate function. + */ + @Override public List>> visitCompound_stmt_spec_or_alloc_stmt(OccamParser.Compound_stmt_spec_or_alloc_stmtContext ctx) { + ILBlock> result_root = new ILBlock<>(); + List>> result_list = new ArrayList<>(); + + boolean popFunctionScope = false; + + if (ctx.allocation() != null) { + result_list = result_root.mergeBlockList(visit(ctx.allocation())); + } else if (ctx.specification() != null) { + result_list = result_root.mergeBlockList(visit(ctx.specification())); + if (ctx.specification() instanceof OccamParser.SpecificationDefContext) { + popFunctionScope = (boolean) libraryInfo.getCurrentScope().popConstruction(); + } + } else { + //TODO: Throw an error + } + + result_list.addAll(visit(ctx.stmt())); + result_list = new ILBlock>().mergeBlockList(result_list); + + if (popFunctionScope) { + libraryInfo.popScope(); + } + + return result_list; + } + + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public List>> visitAbbreviation_expression(OccamParser.Abbreviation_expressionContext ctx) { + Scope currentScope = libraryInfo.getCurrentScope(); + + List>> expressionOps = visit(ctx.expression()); + String newVarName = ctx.NAME().getText(); + + // TODO: Determine the type of the expression. This means tracking the type of the expression when it is visited using the construction stack + Variable variable = currentScope.addVariable(newVarName, "INT"); + if (!(currentScope instanceof FileInformation)) { + libraryInfo.pushNewScope(); + } + + expressionOps.get(0).add(new StoreLocal<>(UUID.randomUUID(), variable.getIndex(), "")); + + return expressionOps; + } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public List>> visitAbbreviation_spec_expression(OccamParser.Abbreviation_spec_expressionContext ctx) { + Scope currentScope = libraryInfo.getCurrentScope(); + + List>> expressionOps = visit(ctx.expression()); + String newVarName = ctx.NAME().getText(); + visit(ctx.specifier()); + String spec = (String) currentScope.popConstruction(); + + // TODO: Determine the type of the expression. This means tracking the type of the expression when it is visited using the construction stack + Variable variable = currentScope.addVariable(newVarName, spec); + if (!(currentScope instanceof FileInformation)) { + libraryInfo.pushNewScope(); + } + + expressionOps.get(0).add(new StoreLocal<>(UUID.randomUUID(), variable.getIndex(), "")); + + return expressionOps; + } + + //TODO: Channel lists to be implemented when Arrays are sorted + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public List>> visitAbbreviation_name_channel_list(OccamParser.Abbreviation_name_channel_listContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public List>> visitAbbreviation_spec_channel_list(OccamParser.Abbreviation_spec_channel_listContext ctx) { return visitChildren(ctx); } + + + @Override + public List>> visitAbbreviation_name_operand(OccamParser.Abbreviation_name_operandContext ctx) { + + Scope currentScope = libraryInfo.getCurrentScope(); + visit(ctx.named_operand()); + + NamedOperand namedOperand = (NamedOperand)currentScope.popConstruction(); + + TSILGeneratorHelpers.abbreviate(currentScope, namedOperand, ctx.NAME().getText(), namedOperand.getTypeName()); + + if (!(currentScope instanceof FileInformation)) { + libraryInfo.pushNewScope(); + } + + return Collections.emptyList(); + + } + + + @Override + public List>> visitAbbreviation_spec_name_operand(OccamParser.Abbreviation_spec_name_operandContext ctx) { + Scope currentScope = libraryInfo.getCurrentScope(); + + visit(ctx.named_operand()); + NamedOperand operand = (NamedOperand) currentScope.popConstruction(); + + visit(ctx.specifier()); + String spec = (String) currentScope.popConstruction(); + + TSILGeneratorHelpers.abbreviate(currentScope, operand, ctx.NAME().getText(), spec); + + if (!(currentScope instanceof FileInformation)) { + libraryInfo.pushNewScope(); + } + + return Collections.emptyList(); + } + + + //TODO: + // Move the todo comment down when a function has been successfully implemented + + + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public List>> visitActual_named_operand(OccamParser.Actual_named_operandContext ctx) { + //TODO: This might need modifying for other parent situations (e.g. returning IL ops) + + boolean passByValue = (boolean) libraryInfo.getCurrentScope().popConstruction(); + + // Visit the `variable`, which will retrieve its information from the library info + // and push it to the construction stack + visit(ctx.named_operand()); + + // Now retrieve the scope and pop the `variable` information from the construction stack + Scope currentScope = libraryInfo.getCurrentScope(); + NamedOperand operand = (NamedOperand) currentScope.popConstruction(); + + // Create an empty IL block + ILBlock> result = new ILBlock<>(); + + // If the operand is an `Abbreviation`, retrieve the actual operand the abbreviation represents + operand = TSILGeneratorHelpers.resolveAbbreviations(operand); + + // If the operand is a constant, push its value to the construction stack and add the IL ops for loading it + // to the result + if (operand.isConstant() && !passByValue) { + throw new IllegalArgumentException("Cannot pass a constant by reference."); + } + if (operand.isConstant()) { + currentScope.pushConstruction(operand.getConstantValue()); + result.appendBlock(TSILGeneratorHelpers.loadConstant(operand.getConstantValue(), operand.getTypeName())); + } else { + // Otherwise, push the `NamedOperand` itself to the construction stack + currentScope.pushConstruction(operand); + + // Depending on the kind of the operand, add the appropriate Load* instruction to the ILBlock + if (operand instanceof Variable) { + Variable variable = (Variable) operand; + if (libraryInfo.isGlobal(variable)) { + result.add(new LoadGlobal<>(UUID.randomUUID(), variable.getName(), "", !passByValue)); + } else { + result.add(new LoadLocal<>(UUID.randomUUID(), variable.getIndex(), "", !passByValue)); + } + } else if (operand instanceof Argument) { + Argument argument = (Argument) operand; + result.add(new LoadArgument<>(UUID.randomUUID(), argument.getIndex(), "", !passByValue)); + } else if (operand instanceof ArrayAbbreviation) { + throw new NotImplementedException(); + //TODO: Load Reference + //TODO: Load Element + } + } + + return Collections.singletonList(result); + } + + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public List>> visitActual_channel(OccamParser.Actual_channelContext ctx) { + //TODO: This might need modifying for other parent situations (e.g. returning IL ops) + + boolean passByValue = (boolean) libraryInfo.getCurrentScope().popConstruction(); + + // Visit the `channel`, which will retrieve its information from the library info + // and push it to the construction stack + visit(ctx.channel()); + + // Now retrieve the scope and pop the `variable` information from the construction stack + Scope currentScope = libraryInfo.getCurrentScope(); + NamedOperand operand = (NamedOperand) currentScope.popConstruction(); + + // Create an empty IL block + ILBlock> result = new ILBlock<>(); + + // If the operand is an `Abbreviation`, retrieve the actual channel the abbreviation represents + Channel channel = (Channel) TSILGeneratorHelpers.resolveAbbreviations(operand); + + // Otherwise, push the `NamedOperand` itself to the construction stack + currentScope.pushConstruction(channel); + + // Depending on the kind of the operand, add the appropriate Load* instruction to the ILBlock + if (libraryInfo.isGlobal(channel)) { + result.add(new LoadGlobal<>(UUID.randomUUID(), channel.getName(), "", !passByValue)); + } else { + result.add(new LoadLocal<>(UUID.randomUUID(), channel.getIndex(), "", !passByValue)); + } + + return Collections.singletonList(result); + } + + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public List>> visitActual_expression(OccamParser.Actual_expressionContext ctx) { + boolean passByValue = (boolean) libraryInfo.getCurrentScope().popConstruction(); + if (!passByValue) { + throw new IllegalArgumentException("Cannot pass an expression by reference."); + } + return visit(ctx.expression()); + } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public List>> visitAllocation(OccamParser.AllocationContext ctx) { return visitChildren(ctx); } + + /** + * Calculate the ILBlocks for an Alternative + */ + @Override public List>> visitAlternation_alternatives(OccamParser.Alternation_alternativesContext ctx) { + + Scope currentScope = libraryInfo.getCurrentScope(); + + if(ctx.PRI() != null) { + //todo PRI + throw new NotImplementedException(); + } + + List>> ilBlocks = new ArrayList<>(); + + + ILBlock> enableBlock = new ILBlock<>(); + ILBlock> disableBlock = new ILBlock<>(); + ILBlock> stmtBlock = new ILBlock<>(); + + ILOp waitAlt = new WaitAlt<>(UUID.randomUUID(), ""); + ILOp endAlt = new EndAlt(UUID.randomUUID(),""); + ILOp afterEndAlt = new Skip(UUID.randomUUID(), "After EndAlt Placeholder"); + + //See CWG 6.10.3 for the order that items need to be on the construction stack + + for(OccamParser.AlternativeContext alternativeContext : ctx.alternative()){ + + visit(alternativeContext); + + List>> stmtBlockList = (List>>)currentScope.popConstruction(); + + //Guard block contains two ILBLOCKS + //ILBlock 0: Guard ilops + //ILBlock 1: ILOP's to calculate the input + List>> guardBlockList = (List>>)currentScope.popConstruction(); + + + enableBlock.appendBlock(guardBlockList.get(0)); + + //Store the result of calculating the guard in a temporary variable + //It will be used by both the enable and disable instruction + + String tempVariable = TSILGeneratorHelpers.generateTempVariable(); + currentScope.addVariable(tempVariable, "BOOL"); + int guardTempValueIndex = currentScope.getVariable(tempVariable).getIndex(); + + enableBlock.add(new StoreLocal<>(UUID.randomUUID(),guardTempValueIndex,"")); + + //Load the type of guarded input from the construction stack + String inputType = (String)currentScope.popConstruction(); + + if (inputType.equals("CHANNEL")) { + + int inputValue = (Integer) currentScope.popConstruction(); + + //Load the channel address onto the stack + enableBlock.add(new LoadChannelRef<>(UUID.randomUUID(),inputValue,"")); + enableBlock.add(new LoadLocal(UUID.randomUUID(),guardTempValueIndex,"",false)); + enableBlock.add(new EnableChannel<>(UUID.randomUUID(),"")); + + + //Pre-pend the ilblock for reading the channel + stmtBlockList.add(0, guardBlockList.get(1)); + + //Load the channel address onto the stack + disableBlock.add(new LoadChannelRef<>(UUID.randomUUID(),inputValue,"")); + //Load the temporary variable which contains the guard value onto the stack + disableBlock.add(new LoadLocal(UUID.randomUUID(),guardTempValueIndex,"",false)); + + // From CWG + // c; e; L; disc + // + // Where c is channel address + // Where e is the alternative guard result + // Where L is the offset from "altend" instruction to the start of the statement instructins + // Where disc is the disable instruction + + // DisableChannel contains the target process address which is to be + // calculated at asm generation + + disableBlock.add(new DisableChannel<>(UUID.randomUUID(), stmtBlockList.get(0).get(0).getId(), afterEndAlt.getId(), "" )); + + + } else if(inputType.equals("PORT")) { + + int inputValue = (Integer) currentScope.popConstruction(); + + enableBlock.add(new LoadPortRef<>(UUID.randomUUID(),inputValue,"")); + enableBlock.add(new LoadLocal(UUID.randomUUID(),guardTempValueIndex,"",false)); + enableBlock.add(new EnablePort<>(UUID.randomUUID(),"")); + + stmtBlockList.add(0, guardBlockList.get(1)); + + disableBlock.add(new LoadLocal(UUID.randomUUID(),guardTempValueIndex,"",false)); + disableBlock.add(new LoadChannelRef<>(UUID.randomUUID(),inputValue,"")); + disableBlock.add(new DisablePort<>(UUID.randomUUID(), stmtBlockList.get(0).get(0).getId(), afterEndAlt.getId(), "" )); + + } else if (inputType.equals("DELAYED_INPUT")) { + + //Take the ILBlocks from the evaluation stack + ILBlock> blockCalculateTimer = (ILBlock>)currentScope.popConstruction(); + + //We need to store the result of the time operations in a temporary variable + //as the value is used in both enable and disable instructions + + String tempTime = TSILGeneratorHelpers.generateTempVariable(); + currentScope.addVariable(tempTime, "INT"); + int tempTimeIndex = currentScope.getVariable(tempTime).getIndex(); + + enableBlock.appendBlock(blockCalculateTimer); + //Duplicate the value on the stack so we can store the value + //and use it for the EnableTimer op + enableBlock.add(new Duplicate<>(UUID.randomUUID(),"")); + enableBlock.add(new StoreLocal<>(UUID.randomUUID(),tempTimeIndex,"")); + enableBlock.add(new LoadLocal(UUID.randomUUID(),guardTempValueIndex,"",false)); + enableBlock.add(new EnableTimer<>(UUID.randomUUID(),"")); + + disableBlock.add(new LoadLocal(UUID.randomUUID(),tempTimeIndex,"",false)); + disableBlock.add(new LoadLocal(UUID.randomUUID(),guardTempValueIndex,"",false)); + disableBlock.add(new DisableTimer<>(UUID.randomUUID(), stmtBlockList.get(0).get(0).getId(), afterEndAlt.getId() , "" )); + + } else if(inputType.equals("SKIP")) { + + enableBlock.add(new LoadLocal(UUID.randomUUID(),guardTempValueIndex,"",false)); + enableBlock.add(new EnableSkip<>(UUID.randomUUID(), "")); + + disableBlock.add(new LoadLocal(UUID.randomUUID(),guardTempValueIndex,"",false)); + disableBlock.add(new DisableSkip<>(UUID.randomUUID(), stmtBlockList.get(0).get(0).getId() , afterEndAlt.getId(), "" )); + + } else { + throw new NotImplementedException(); + } + + stmtBlock.add(new Branch<>(UUID.randomUUID(),endAlt.getId(), "")); + ilBlocks.addAll(stmtBlock.mergeBlockList(stmtBlockList)); + ilBlocks.remove(stmtBlock); + } + + //Add the ILBLocks to the output list + ilBlocks.add(new ILBlock<>(new InitAlt(UUID.randomUUID(),""))); + ilBlocks.add(enableBlock); + ilBlocks.add(new ILBlock<>(new WaitAlt(UUID.randomUUID(),""))); + ilBlocks.add(disableBlock); + ilBlocks.add(new ILBlock<>(waitAlt)); + ilBlocks.add(stmtBlock); + ilBlocks.add(new ILBlock<>(endAlt)); + ilBlocks.add(new ILBlock<>(afterEndAlt)); + + return ilBlocks; + + } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public List>> visitAlternation_replicator_alternative(OccamParser.Alternation_replicator_alternativeContext ctx) { + throw new NotImplementedException(); + } + /** + * Visit guarded alternative will trigger visiting it's childed guarded_alternative + */ + @Override public List>> visitAlternative_guarded(OccamParser.Alternative_guardedContext ctx) { + return visit(ctx.guarded_alternative()); + } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public List>> visitAlternative_alternation(OccamParser.Alternative_alternationContext ctx) { + throw new NotImplementedException(); + } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public List>> visitAlternative_channel(OccamParser.Alternative_channelContext ctx) { + throw new NotImplementedException(); + } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public List>> visitAlternative_bool_channel(OccamParser.Alternative_bool_channelContext ctx) { + throw new NotImplementedException(); + } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public List>> visitAlternative_spec(OccamParser.Alternative_specContext ctx) { + visit(ctx.specification()); + return visit(ctx.alternative()); + }; + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public List>> visitChannel_from_base(OccamParser.Channel_from_baseContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public List>> visitChannel_channel_expression(OccamParser.Channel_channel_expressionContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public List>> visitChannel_for_count(OccamParser.Channel_for_countContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public List>> visitChannel_expression_channel_type(OccamParser.Channel_expression_channel_typeContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public List>> visitConversion(OccamParser.ConversionContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public List>> visitDef_DATA_Name(OccamParser.Def_DATA_NameContext ctx) { + libraryInfo.getCurrentScope().pushConstruction(false); + return visitChildren(ctx); + } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public List>> visitDef_PROTOCOL_NAME_IS(OccamParser.Def_PROTOCOL_NAME_ISContext ctx) { + libraryInfo.getCurrentScope().pushConstruction(false); + return visitChildren(ctx); + } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public List>> visitDef_PROTOCOL_NAME_INDENT(OccamParser.Def_PROTOCOL_NAME_INDENTContext ctx) { + libraryInfo.getCurrentScope().pushConstruction(false); + return visitChildren(ctx); + } + /** + * {@inheritDoc} + * Visit a function header bound to a value process. Adds a function scope to the metadata and produces the necessary + * IL ops for the value process. + */ + @Override public List>> visitDef_function_value_process(OccamParser.Def_function_value_processContext ctx) { + /* Notes: + * + * A value process function definition has the following grammar: + * data_type (',' data_type)* function_header NL INDENT value_process DEDENT ':' + * + */ + + Scope rootScope = libraryInfo.getCurrentScope(); + + // Creates the function scope and populates it with details of the formals + visit(ctx.function_header()); + // Add the return types to the function definition + Function functionScope = (Function) libraryInfo.getCurrentScope(); + for (OccamParser.Data_typeContext data_type : ctx.data_type()) { + visit(data_type); + functionScope.addReturnType((String)functionScope.popConstruction()); + } + + ILBlock> functionBlock = new ILBlock<>(functionScope.getScopeId(), true); + functionBlock.add(new Label<>(UUID.randomUUID(), functionScope.getName(), true, "")); + functionBlock.add(new MethodStart<>(UUID.randomUUID(), "Start of `" + functionScope.getName() + "`")); + + List>> valueProcess = visit(ctx.value_process()); + List> > result = functionBlock.mergeBlockList(valueProcess); + + while (libraryInfo.getCurrentScope() != rootScope) { + libraryInfo.popScope(); + } + + functionBlock.add(new MethodEnd<>(UUID.randomUUID(), "End of `" + functionScope.getName() + "`")); + + libraryInfo.getCurrentScope().pushConstruction(true); + + return result; + } + /** + * {@inheritDoc} + * Visit a function header bound to an expression list. Adds a function scope to the metadata and produces the necessary + * IL ops to evaluate the expressions. + */ + @Override public List>> visitDef_function_expression_list(OccamParser.Def_function_expression_listContext ctx) { + /* Notes: + * + * An expression-list function definition has the following grammar: + * data_type (',' data_type)* function_header IS expression_list ':' + */ + + Scope rootScope = libraryInfo.getCurrentScope(); + + // Creates the function scope and populates it with details of the formals + visit(ctx.function_header()); + Function functionScope = (Function) libraryInfo.getCurrentScope(); + for (OccamParser.Data_typeContext data_type : ctx.data_type()) { + visit(data_type); + functionScope.addReturnType((String)functionScope.popConstruction()); + } + + ILBlock> functionBlock = new ILBlock<>(functionScope.getScopeId(), true); + functionBlock.add(new Label<>(UUID.randomUUID(), functionScope.getName(), true, "")); + functionBlock.add(new MethodStart<>(UUID.randomUUID(), "Start of `" + functionScope.getName() + "`")); + + List>> expressionList = visit(ctx.expression_list()); + List> > result = functionBlock.mergeBlockList(expressionList); + + while (libraryInfo.getCurrentScope() != rootScope) { + libraryInfo.popScope(); + } + + functionBlock.add(new MethodEnd<>(UUID.randomUUID(), "End of `" + functionScope.getName() + "`")); + + libraryInfo.getCurrentScope().pushConstruction(true); + + return result; + } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public List>> visitDef_specifier(OccamParser.Def_specifierContext ctx) { + libraryInfo.getCurrentScope().pushConstruction(false); + return visitChildren(ctx); + } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public List>> visitDef_specifier2(OccamParser.Def_specifier2Context ctx) { + libraryInfo.getCurrentScope().pushConstruction(false); + return visitChildren(ctx); + } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public List>> visitDef_val(OccamParser.Def_valContext ctx) { + libraryInfo.getCurrentScope().pushConstruction(false); + return visitChildren(ctx); + } + /** + * Visiting delayed input will push "DELAYED_INPUT" and the ILBlocks for calculating + * the delay onto the construction stack + */ + @Override public List>> visitDelayed_input(OccamParser.Delayed_inputContext ctx) { + + + List>> ilBlocks = new ArrayList<>(); + + List>> expressionILBlocks = visit(ctx.expression()); + ILBlock> expressionBlock = new ILBlock<>(); + + ilBlocks = expressionBlock.mergeBlockList(expressionILBlocks); + + //Delayed timer input will execute when the current value on the evaluation stack is + //less than or equal to the timer value + + expressionBlock.add(new DelayedTimerInput<>(UUID.randomUUID(), "")); + + getLibraryInfo().getCurrentScope().pushConstruction(expressionBlock); + getLibraryInfo().getCurrentScope().pushConstruction("DELAYED_INPUT"); + + return ilBlocks; + } + /** + * TODO + * + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public List>> visitExpression_most_data_type(OccamParser.Expression_most_data_typeContext ctx) { + + Scope scope = libraryInfo.getCurrentScope(); + + visit(ctx.data_type()); + + //Data type is now on the construction stack. + + String type = (String)scope.popConstruction(); + + ILBlock> result = new ILBlock<>(); + + if(ctx.MOSTPOS() != null) { + + result.add(new MostPositive<>(UUID.randomUUID(), type, "")); + + }else{ + + result.add(new MostNegative<>(UUID.randomUUID(),type, "")); + + } + + return Collections.singletonList(result); + + } + /** + * TODO + * + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public List>> visitExpression_size_of(OccamParser.Expression_size_ofContext ctx) { return visitChildren(ctx); } + /** + * TODO + * + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public List>> visitExpression_conversion(OccamParser.Expression_conversionContext ctx) { return visitChildren(ctx); } + + @Override + public List>> visitFunction_call(OccamParser.Function_callContext ctx) { + List>> ilBlocks = new ArrayList<>(); + Function functionDefinition = libraryInfo.getFunction(ctx.NAME().getText()); + + libraryInfo.pushNewScope(); + // Load the arguments onto the stack + for (int i = ctx.expression().size() - 1; i >= 0; i--) { + ilBlocks.addAll(visit(ctx.expression(i))); + } + libraryInfo.popScope(); + + // Call the function + ilBlocks.add(new ILBlock<>(new Call(UUID.randomUUID(), ctx.NAME().getText(), "Call " + ctx.getText()))); + + // Add return types to construction stack + for (String returnType : functionDefinition.getReturnTypes()) { + libraryInfo.getCurrentScope().pushConstruction(returnType); + } + + libraryInfo.getCurrentScope().pushConstruction(functionDefinition); + + return ilBlocks; + } + + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public List>> visitExpression_list_function_call(OccamParser.Expression_list_function_callContext ctx) { + List>> ilBlocks = new ArrayList<>(); + + ilBlocks.addAll(visit(ctx.function_call())); + + Function fn = (Function) libraryInfo.getCurrentScope().popConstruction(); + libraryInfo.getCurrentScope().pushConstruction(fn.getReturnTypes().size()); + + return ilBlocks; + } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public List>> visitField_name(OccamParser.Field_nameContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public List>> visitFunction_header(OccamParser.Function_headerContext ctx) { + // Everything inside the function is in a new scope, so add one to the stack + String procedureName = ctx.NAME().getText(); + libraryInfo.pushNewFunctionScope(procedureName); + + // Update the current scope with information about each of the functions's arguments + for (OccamParser.FormalContext formal : ctx.formal()) { + visit(formal); + } + + return null; + } + /** + * Visit a guarded input + * + */ + @Override public List>> visitGuard_input(OccamParser.Guard_inputContext ctx) { + + List>> ilBlocks = new ArrayList<>(); + + List>> inputBlocks = visit(ctx.input()); + ILBlock> inputBlock = new ILBlock<>(); + + //Add a TRUE guard + inputBlocks.add(0, new ILBlock<>(new LoadConstant<> ( UUID.randomUUID() ,"1" , "") )); + + return inputBlock.mergeBlockList(inputBlocks); + + } + + + + + /** + * Generate the ILBlocks for calculating a guarded input + */ + @Override public List>> visitGuard_bool_input_or_skip(OccamParser.Guard_bool_input_or_skipContext ctx) { + + List>> ilBlocks = new ArrayList<>(); + + + //Generate the ILBlocks for calculating the boolean guard + List>> boolBlocks = visit(ctx.bool()); + + libraryInfo.getCurrentScope().popConstruction();//We don't need the boolean value on construction stack + + ILBlock> boolBlock = new ILBlock<>(); + boolBlocks = boolBlock.mergeBlockList(boolBlocks); + ilBlocks.addAll(boolBlocks); + + if ( ctx.input() != null ) { + + + //Generate the ILBlocks for calculating the input blocks + List>> inputBlockList = visit(ctx.input()); + ILBlock> inputBlock = new ILBlock<>(); + + inputBlockList = inputBlock.mergeBlockList(inputBlockList); + ilBlocks.addAll(inputBlockList); + + }else { + + ilBlocks.add(new ILBlock<>(new Skip(UUID.randomUUID(), ""))); + libraryInfo.getCurrentScope().pushConstruction("SKIP"); + } + + return new ILBlock>().mergeBlockList(ilBlocks); + + } + /** + * Visiting the guarded alternative will push two lists onto the construction stack + * The ILBlock list for calculating the guard + * THe ILBlock list for executing the stmt + */ + @Override public List>> visitGuarded_alternative(OccamParser.Guarded_alternativeContext ctx) { + + List>> guardBlockList = visit(ctx.guard()); + List>> stmtBlockList = visit(ctx.stmt()); + + Scope currentScope = libraryInfo.getCurrentScope(); + + currentScope.pushConstruction(guardBlockList); + currentScope.pushConstruction(stmtBlockList); + + return Collections.emptyList(); + } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public List>> visitInput_named_operand_tagged_list(OccamParser.Input_named_operand_tagged_listContext ctx) { return visitChildren(ctx); } + + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public List>> visitInput_delayed_input(OccamParser.Input_delayed_inputContext ctx) { return visitChildren(ctx); } + + + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public List>> visitInput_item_multiple_variables(OccamParser.Input_item_multiple_variablesContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public List>> visitLiteral_real(OccamParser.Literal_realContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public List>> visitOperand_value_process(OccamParser.Operand_value_processContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public List>> visitOperand_offsetof(OccamParser.Operand_offsetofContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public List>> visitOperand_function_call(OccamParser.Operand_function_callContext ctx) { + return visit(ctx.function_call()); + } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public List>> visitOperand_bytesin(OccamParser.Operand_bytesinContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public List>> visitOperand_operand_expression(OccamParser.Operand_operand_expressionContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public List>> visitOperand_table(OccamParser.Operand_tableContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public List>> visitOption_spec_option(OccamParser.Option_spec_optionContext ctx) { return visitChildren(ctx); } + /* + * Writing input items to a channel + */ + @Override public List>> visitOutput_named_operand_outputitems(OccamParser.Output_named_operand_outputitemsContext ctx) { + Scope currentScope = libraryInfo.getCurrentScope(); + visit(ctx.named_operand()); + + //We have channel on the scope construction stack + NamedOperand namedOperand = (NamedOperand)currentScope.popConstruction(); + + namedOperand = TSILGeneratorHelpers.resolveAbbreviations(namedOperand); + + ILBlock> ilBlock = new ILBlock<>(); + List>> result = new ArrayList<>(); + + //Create a temp variable + String tempVar = TSILGeneratorHelpers.generateTempVariable(); + + currentScope.addVariable(tempVar , namedOperand.getTypeName()); + + if (namedOperand instanceof Channel) { + + Iterator outputitemContextIterator = ctx.outputitem().iterator(); + + while (outputitemContextIterator.hasNext()) { + + try { + + OccamParser.OutputitemContext outputitemContext = outputitemContextIterator.next(); + + //Load ilBlocks for calculating the expression + List>> outputBlock = visit(outputitemContext); + result.addAll(ilBlock.mergeBlockList(outputBlock)); + result.remove(ilBlock); + ilBlock.add(new StoreLocal<>(UUID.randomUUID(), currentScope.getVariable(tempVar).getIndex(), "Temporary variable")); + ilBlock.add(new LoadLocal(UUID.randomUUID(), currentScope.getVariable(tempVar).getIndex(), "Load address", true)); + ilBlock.add(new LoadChannelRef<>(UUID.randomUUID(), ((Channel) namedOperand).getIndex() , "")); + ilBlock.add(new LoadConstant<> ( UUID.randomUUID() , String.valueOf(libraryInfo.getTypeSize(namedOperand.getTypeName())) , "" )); + ilBlock.add(new WriteChannel<>(UUID.randomUUID(), "")); + + }catch (Exception e){ + System.out.println("Error calculating variable size"); + System.exit(0); + } + + } + + } else if(namedOperand instanceof Port) { + + try { + + + //Load ilBlocks for calculating the expression + //Grammar defines that for port we can only write 1 item + List>> outputBlock = visit(ctx.outputitem(0)); + + result.addAll(ilBlock.mergeBlockList(outputBlock)); + result.remove(ilBlock); + + ilBlock.add(new StoreLocal<>(UUID.randomUUID(), currentScope.getVariable(tempVar).getIndex(), "Temporary variable")); + ilBlock.add(new LoadLocal(UUID.randomUUID(), currentScope.getVariable(tempVar).getIndex(), "Load address", true)); + ilBlock.add(new LoadPortRef<>(UUID.randomUUID(), ((Port) namedOperand).getIndex(), "")); + ilBlock.add(new LoadConstant<>(UUID.randomUUID(), String.valueOf(libraryInfo.getTypeSize(namedOperand.getTypeName())), "")); + + ilBlock.add(new WritePort<>(UUID.randomUUID(), "")); + + }catch( Exception e){ + System.out.println("Error calculating variable size"); + System.exit(0); + } + + } else if (namedOperand instanceof ArrayAbbreviation) { + //todo add ArrayAbbreviation channel implementation + throw new NotImplementedException(); + } else { + + throw new NotImplementedException(); + } + + return result; + + + } + + /** + * Push information about a variable to the construction stack. + * + * @param ctx A `variable` AST node that is just an identifier (`NAME`) + * @return null + */ + @Override + public List>> visitNamed_operand_name(OccamParser.Named_operand_nameContext ctx) { + // Retrieve the variable identifier from the AST node + String variableName = ctx.NAME().getText(); + + // Attempt to retrieve the variable's information from the library info, then + // push it to the construction stack + NamedOperand variable = libraryInfo.searchForNamedOperand(variableName); + libraryInfo.getCurrentScope().pushConstruction(variable); + + return null; + } + + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public List>> visitOutputitem_multiple_expression(OccamParser.Outputitem_multiple_expressionContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public List>> visitParallel_placedpar(OccamParser.Parallel_placedparContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public List>> visitSingle_stmt(OccamParser.Single_stmtContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public List>> visitPlacedpar_placedpars(OccamParser.Placedpar_placedparsContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public List>> visitPlacedpar_replicator_placedpar(OccamParser.Placedpar_replicator_placedparContext ctx) { return visitChildren(ctx); } + + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public List>> visitPort_type_expression_port_type(OccamParser.Port_type_expression_port_typeContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public List>> visitProc_instance(OccamParser.Proc_instanceContext ctx) { + List>> ilBlocks = new ArrayList<>(ctx.actual().size()); + Function functionDefinition = libraryInfo.getFunction(ctx.NAME().getText()); + + libraryInfo.pushNewScope(); + + for (int i = ctx.actual().size() - 1; i >= 0; i--) { + boolean passByValue = functionDefinition.getArguments().get(i).getPassByValue(); + libraryInfo.getCurrentScope().pushConstruction(passByValue); + ilBlocks.addAll(visit(ctx.actual(i))); + } + libraryInfo.popScope(); + + ilBlocks.add(new ILBlock<>(new Call(UUID.randomUUID(), ctx.NAME().getText(), "Call " + ctx.getText()))); + return ilBlocks; + } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public List>> visitProtcol_simple_protocol(OccamParser.Protcol_simple_protocolContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public List>> visitSelector(OccamParser.SelectorContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public List>> visitSequence_replicator(OccamParser.Sequence_replicatorContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public List>> visitSequential_protocol(OccamParser.Sequential_protocolContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public List>> visitSimple_protocol_data_type(OccamParser.Simple_protocol_data_typeContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public List>> visitSimple_protocol_any(OccamParser.Simple_protocol_anyContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public List>> visitSimple_protocol_data_type_data_type(OccamParser.Simple_protocol_data_type_data_typeContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public List>> visitSpecifier_channel_type(OccamParser.Specifier_channel_typeContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public List>> visitSpecifier_timer_type(OccamParser.Specifier_timer_typeContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public List>> visitSpecifier_port_type(OccamParser.Specifier_port_typeContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public List>> visitSpecifier_expression_specifier(OccamParser.Specifier_expression_specifierContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public List>> visitStructured_type(OccamParser.Structured_typeContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public List>> visitSingle_record_declaration(OccamParser.Single_record_declarationContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public List>> visitTable_table_base_count(OccamParser.Table_table_base_countContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public List>> visitTable_table_count(OccamParser.Table_table_countContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public List>> visitTable_expressions(OccamParser.Table_expressionsContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public List>> visitTable_string(OccamParser.Table_stringContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public List>> visitTable_table_expression(OccamParser.Table_table_expressionContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public List>> visitTag(OccamParser.TagContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public List>> visitTagged_list(OccamParser.Tagged_listContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public List>> visitTagged_protocol(OccamParser.Tagged_protocolContext ctx) { return visitChildren(ctx); } + + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public List>> visitTimer_type_timer(OccamParser.Timer_type_timerContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public List>> visitTimer_expression_timer_type(OccamParser.Timer_expression_timer_typeContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public List>> visitValue_process_stmt(OccamParser.Value_process_stmtContext ctx) { + List>> ilBlocks = new ArrayList<>(); + ilBlocks.addAll(visit(ctx.stmt())); + ilBlocks.addAll(visit(ctx.expression_list())); + return ilBlocks; + } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public List>> visitValue_process_specification(OccamParser.Value_process_specificationContext ctx) { + libraryInfo.pushNewScope(); + + // Adjust the scope + visit(ctx.specification()); + + // Then process the actual contents of the value process + List>> ilBlocks = visit(ctx.value_process()); + + libraryInfo.popScope(); + + return ilBlocks; + } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public List>> visitVariant_tagged_list_stmt(OccamParser.Variant_tagged_list_stmtContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public List>> visitVariant_specification_variant(OccamParser.Variant_specification_variantContext ctx) { return visitChildren(ctx); } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/TSILGeneratorHelpers.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/TSILGeneratorHelpers.java new file mode 100644 index 0000000..a59a9fc --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/TSILGeneratorHelpers.java @@ -0,0 +1,184 @@ +package uk.co.transputersystems.occam; + +import uk.co.transputersystems.occam.il.*; +import uk.co.transputersystems.occam.metadata.*; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +public class TSILGeneratorHelpers { + + static int tempCounter = 0; + + public static String generateTempVariable(){ + return "~temp" + tempCounter++; + } + + /** + * + * @param operand + * @return + */ + public static NamedOperand resolveAbbreviations(NamedOperand operand) { + // TODO: Chase through array abbreviations which lead to constant values + // (because you can create an array abbreviation for a part of a value abbreviation where the value + // abbreviation was an abbreviation of an array). + + if(operand.isConstant()) { + return operand; + } + + NamedOperand currentOperand = operand; + + while (currentOperand instanceof Abbreviation && !(currentOperand instanceof ArrayAbbreviation)) { + currentOperand = ((Abbreviation) currentOperand).resolveHiddenOperand(); + } + + return currentOperand; + } + + /** + * Given some constant value, generate a series of IL ops that load that constant. + * @param value The constant value + * @param typeName The name of the type of the constant value + * @param The type of the constant + * @return The generated IL ops + */ + public static ILBlock> loadConstant(T value, String typeName) { + ILBlock> result = new ILBlock<>(); + switch (typeName) { + case "INT": + result.add(new LoadConstant<>(UUID.randomUUID(), value.toString(), "")); + break; + case "BYTE": + result.add(new LoadConstant<>(UUID.randomUUID(), value.toString(), "")); + break; + default: + // TODO: Support loading constants of more types + System.out.print("Don't know how to load constant of type '" + typeName + "' : " + value.toString()); + break; + } + + return result; + } + + public static ILBlock> parallel(List>> statementBlocks, List workspaceIds) { + if (statementBlocks.size() == 1) { + return statementBlocks.get(0); + } else { + ILBlock> result = new ILBlock<>(); + + ILOp endOp = new Skip<>(UUID.randomUUID(), ""); + ILOp initOp = new InitProcesses<>(UUID.randomUUID(), statementBlocks.size(), endOp.getId(), workspaceIds, ""); + + List startOps = new ArrayList<>(); + startOps.add(initOp.getId()); + + result.add(initOp); + for (int i = 1; i < statementBlocks.size(); i++) { + ILBlock> block = statementBlocks.get(i); + StartProcess startOp = new StartProcess<>(UUID.randomUUID(), block.get(0).getId(), ProcessPriorities.Current, ""); + startOps.add(startOp.getId()); + result.add(startOp); + } + + for (int i = 0; i < statementBlocks.size(); i++) { + ILBlock> block = statementBlocks.get(i); + block.get(0).setComment("[Process" + Integer.toString(i) + "]"); + result.appendBlock(block); + result.add(new EndProcess<>(UUID.randomUUID(), startOps.get(i), "")); + } + + result.add(endOp); + + return result; + } + } + + /** + * Converts a character literal to its decimal integer value. If the literal is invalid, throws an `IllegalArgumentException`. + * + * Occam guarantees support for the ASCII characters in the range `#20` through `#7F` inclusive, plus the escape sequences below: + * + * * `*c`, `*C`: carriage return + * * `*n`, `*N`: newline + * * `*t`, `*T`: tab + * * `*s`, `*S`: space + * * `*'`: single quote + * * `*"`: double quote + * * `**`: asterisk + * + * @param literal A character literal without any enclosing quotes + * @return The decimal integer representation of that character. + */ + public static int parseCharacterLiteral(String literal) throws IllegalArgumentException { + + if (literal.length() < 1) { + throw new IllegalArgumentException("A character literal must have at least one character."); + } + + if (literal.charAt(0) == '*') { + // Handle escape sequences + if (literal.length() == 2) { + switch (literal.charAt(1)) { + case 'c': + case 'C': + + return 13; + case 'n': + case 'N': + return 10; + case 't': + case 'T': + return 9; + case 's': + case 'S': + return 32; + case '\'': + return 39; + case '"': + return 34; + case '*': + return 42; + default: + break; + } + } else if (literal.length() == 4 && literal.charAt(1) == '#') { + return Integer.parseInt(literal.substring(2, 4), 16); + } else { + throw new IllegalArgumentException(String.format("Illegal literal escape sequence %s", literal)); + } + } else { + // Otherwise, check that this is a normal character literal and convert it + if (literal.length() != 1) { + throw new IllegalArgumentException("A normal character literal must be exactly one character."); + } else { + int literalValue = (int)literal.charAt(0); + if (32 <= literalValue && literalValue <= 127) { + return literalValue; + } else { + throw new IllegalArgumentException(String.format("The character %c is not permitted in a character literal.", literal.charAt(0))); + } + } + } + + throw new IllegalArgumentException("The character literal provided is not legal."); + } + + public static void abbreviate(Scope currentScope, NamedOperand operand, String name, String spec) { + if (operand instanceof Channel || operand instanceof ChannelAbbreviation) { + currentScope.addAbbreviation(new ChannelAbbreviation(currentScope, name, spec, operand.getName())); + } else if (operand instanceof Variable || operand instanceof Argument || operand instanceof VariableAbbreviation) { + currentScope.addAbbreviation(new VariableAbbreviation(currentScope, name, spec, operand.getName())); + } else if (operand instanceof Timer || operand instanceof TimerAbbreviation) { + currentScope.addAbbreviation(new TimerAbbreviation(currentScope, name, operand.getName())); + } else if (operand instanceof Port || operand instanceof PortAbbreviation) { + currentScope.addAbbreviation(new PortAbbreviation(currentScope, name, spec, operand.getName())); + } else if (operand instanceof ArrayAbbreviation || operand instanceof ValueAbbreviation) { + currentScope.addAbbreviation(new VariableAbbreviation(currentScope, name, spec, operand.getName())); + } else { + //TODO: Throw an error + } + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/Add.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/Add.java new file mode 100644 index 0000000..2010a14 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/Add.java @@ -0,0 +1,29 @@ +package uk.co.transputersystems.occam.il; + +import java.util.Collections; + +public class Add extends ILOp { + + public final boolean ignore_overflow; + + public Add(TIdentifier id, boolean ignore_overflow, String comment) { + super(id, "Add", ignore_overflow ? "ignore_overflow" : "allow_underflow"); + this.ignore_overflow = ignore_overflow; + } + + @Override + public Integer getEncodedSize() { + //TODO: Set encoded size properly + return 1; + } + + @Override + public Iterable getArgs() { + return Collections.emptyList(); + } + + @Override + public TReturn accept(ILOpVisitor visitor, TContext ctx) { + return visitor.visitAdd(this, ctx); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/After.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/After.java new file mode 100644 index 0000000..e772212 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/After.java @@ -0,0 +1,28 @@ +package uk.co.transputersystems.occam.il; + + +import java.util.Collections; + +public class After extends ILOp { + + + public After(TIdentifier id , String comment) { + super(id, "After ", comment); + } + + @Override + public Integer getEncodedSize() { + //TODO: Set encoded size properly + return 1; + } + + @Override + public Iterable getArgs() { + return Collections.emptyList(); + } + + @Override + public TReturn accept(ILOpVisitor visitor, TContext ctx) { + return visitor.visitAfter(this, ctx); + } +} \ No newline at end of file diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/BitwiseAnd.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/BitwiseAnd.java new file mode 100644 index 0000000..3d7188f --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/BitwiseAnd.java @@ -0,0 +1,25 @@ +package uk.co.transputersystems.occam.il; + +import java.util.Collections; + +public class BitwiseAnd extends ILOp { + public BitwiseAnd(TIdentifier id, String comment) { + super(id, "BitwiseAnd", comment); + } + + @Override + public TReturn accept(ILOpVisitor visitor, TContext ctx) { + return visitor.visitBitwiseAnd(this, ctx); + } + + @Override + public Integer getEncodedSize() { + //TODO: Set encoded size properly + return 1; + } + + @Override + public Iterable getArgs() { + return Collections.emptyList(); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/BitwiseNot.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/BitwiseNot.java new file mode 100644 index 0000000..b10cdd5 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/BitwiseNot.java @@ -0,0 +1,25 @@ +package uk.co.transputersystems.occam.il; + +import java.util.Collections; + +public class BitwiseNot extends ILOp { + public BitwiseNot(TIdentifier id, String comment) { + super(id, "BitwiseNot", comment); + } + + @Override + public TReturn accept(ILOpVisitor visitor, TContext ctx) { + return visitor.visitBitwiseNot(this, ctx); + } + + @Override + public Integer getEncodedSize() { + //TODO: Set encoded size properly + return 1; + } + + @Override + public Iterable getArgs() { + return Collections.emptyList(); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/BitwiseOr.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/BitwiseOr.java new file mode 100644 index 0000000..0f3c46c --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/BitwiseOr.java @@ -0,0 +1,25 @@ +package uk.co.transputersystems.occam.il; + +import java.util.Collections; + +public class BitwiseOr extends ILOp { + public BitwiseOr(TIdentifier id, String comment) { + super(id, "BitwiseOr", comment); + } + + @Override + public TReturn accept(ILOpVisitor visitor, TContext ctx) { + return visitor.visitBitwiseOr(this, ctx); + } + + @Override + public Integer getEncodedSize() { + //TODO: Set encoded size properly + return 1; + } + + @Override + public Iterable getArgs() { + return Collections.emptyList(); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/BitwiseXor.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/BitwiseXor.java new file mode 100644 index 0000000..06f2be5 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/BitwiseXor.java @@ -0,0 +1,25 @@ +package uk.co.transputersystems.occam.il; + +import java.util.Collections; + +public class BitwiseXor extends ILOp { + public BitwiseXor(TIdentifier id, String comment) { + super(id, "BitwiseXor", comment); + } + + @Override + public TReturn accept(ILOpVisitor visitor, TContext ctx) { + return visitor.visitBitwiseXor(this, ctx); + } + + @Override + public Integer getEncodedSize() { + //TODO: Set encoded size properly + return 1; + } + + @Override + public Iterable getArgs() { + return Collections.emptyList(); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/BooleanAnd.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/BooleanAnd.java new file mode 100644 index 0000000..29d31a3 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/BooleanAnd.java @@ -0,0 +1,27 @@ +package uk.co.transputersystems.occam.il; + + +import java.util.Collections; + +public class BooleanAnd extends ILOp { + + public BooleanAnd(TIdentifier id, String comment) { + super(id, "BooleanAnd", comment); + } + + @Override + public TReturn accept(ILOpVisitor visitor, TContext ctx) { + return visitor.visitBooleanAnd(this, ctx); + } + + @Override + public Integer getEncodedSize() { + //TODO: Set encoded size properly + return 1; + } + + @Override + public Iterable getArgs() { + return Collections.emptyList(); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/BooleanNot.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/BooleanNot.java new file mode 100644 index 0000000..ec59463 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/BooleanNot.java @@ -0,0 +1,27 @@ +package uk.co.transputersystems.occam.il; + + +import java.util.Collections; + +public class BooleanNot extends ILOp { + + public BooleanNot(TIdentifier id, String comment) { + super(id, "BooleanNot", comment); + } + + @Override + public TReturn accept(ILOpVisitor visitor, TContext ctx) { + return visitor.visitBooleanNot(this, ctx); + } + + @Override + public Integer getEncodedSize() { + //TODO: Set encoded size properly + return 1; + } + + @Override + public Iterable getArgs() { + return Collections.emptyList(); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/BooleanOr.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/BooleanOr.java new file mode 100644 index 0000000..832d22f --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/BooleanOr.java @@ -0,0 +1,27 @@ +package uk.co.transputersystems.occam.il; + + +import java.util.Collections; + +public class BooleanOr extends ILOp { + + public BooleanOr(TIdentifier id, String comment) { + super(id, "BooleanOr", comment); + } + + @Override + public TReturn accept(ILOpVisitor visitor, TContext ctx) { + return visitor.visitBooleanOr(this, ctx); + } + + @Override + public Integer getEncodedSize() { + //TODO: Set encoded size properly + return 1; + } + + @Override + public Iterable getArgs() { + return Collections.emptyList(); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/Branch.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/Branch.java new file mode 100644 index 0000000..96891b3 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/Branch.java @@ -0,0 +1,29 @@ +package uk.co.transputersystems.occam.il; + +import java.util.Collections; + +public class Branch extends ILOp { + + public final TIdentifier target; + + public Branch(TIdentifier id, TIdentifier target, String comment) { + super(id, "Branch", comment); + this.target = target; + } + + @Override + public Iterable getArgs() { + return Collections.singletonList(target.toString()); + } + + @Override + public Integer getEncodedSize() { + //TODO: Set encoded size properly + return 1; + } + + @Override + public TReturn accept(ILOpVisitor visitor, TContext ctx) { + return visitor.visitBranch(this, ctx); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/BranchEqZero.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/BranchEqZero.java new file mode 100644 index 0000000..f2a7018 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/BranchEqZero.java @@ -0,0 +1,29 @@ +package uk.co.transputersystems.occam.il; + +import java.util.Collections; + +public class BranchEqZero extends ILOp { + + public final TIdentifier target; + + public BranchEqZero(TIdentifier id, TIdentifier target, String comment) { + super(id, "BranchIfEqualsZero", comment); + this.target = target; + } + + @Override + public Integer getEncodedSize() { + //TODO: Set encoded size properly + return 1; + } + + @Override + public Iterable getArgs() { + return Collections.singletonList(target.toString()); + } + + @Override + public TReturn accept(ILOpVisitor visitor, TContext ctx) { + return visitor.visitBranchEqZero(this, ctx); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/BranchIfFalse.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/BranchIfFalse.java new file mode 100644 index 0000000..eada232 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/BranchIfFalse.java @@ -0,0 +1,30 @@ +package uk.co.transputersystems.occam.il; + +import java.util.Collections; + + +public class BranchIfFalse extends ILOp { + + public final TIdentifier target; + + public BranchIfFalse(TIdentifier id, TIdentifier target, String comment) { + super(id, "BranchIfFalse", comment); + this.target = target; + } + + @Override + public Integer getEncodedSize() { + //TODO: Set encoded size properly + return 1; + } + + @Override + public Iterable getArgs() { + return Collections.singletonList(target.toString()); + } + + @Override + public TReturn accept(ILOpVisitor visitor, TContext ctx) { + return visitor.visitBranchIfFalse(this, ctx); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/BranchIfTrue.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/BranchIfTrue.java new file mode 100644 index 0000000..a41669e --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/BranchIfTrue.java @@ -0,0 +1,30 @@ +package uk.co.transputersystems.occam.il; + +import java.util.Collections; + + +public class BranchIfTrue extends ILOp { + + public final TIdentifier target; + + public BranchIfTrue(TIdentifier id, TIdentifier target, String comment) { + super(id, "BranchIfTrue", comment); + this.target = target; + } + + @Override + public Integer getEncodedSize() { + //TODO: Set encoded size properly + return 1; + } + + @Override + public Iterable getArgs() { + return Collections.singletonList(target.toString()); + } + + @Override + public TReturn accept(ILOpVisitor visitor, TContext ctx) { + return visitor.visitBranchIfTrue(this, ctx); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/BranchNotEqZero.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/BranchNotEqZero.java new file mode 100644 index 0000000..48124f3 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/BranchNotEqZero.java @@ -0,0 +1,29 @@ +package uk.co.transputersystems.occam.il; + +import java.util.Collections; + +public class BranchNotEqZero extends ILOp { + + public final TIdentifier target; + + public BranchNotEqZero(TIdentifier id, TIdentifier branch, String comment) { + super(id, "BranchIfNotEqualsZero", comment); + this.target = branch; + } + + @Override + public Integer getEncodedSize() { + //TODO: Set encoded size properly + return 1; + } + + @Override + public Iterable getArgs() { + return Collections.singletonList(target.toString()); + } + + @Override + public TReturn accept(ILOpVisitor visitor, TContext ctx) { + return visitor.visitBranchNotEqZero(this, ctx); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/Call.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/Call.java new file mode 100644 index 0000000..32871bd --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/Call.java @@ -0,0 +1,32 @@ +package uk.co.transputersystems.occam.il; + +import java.util.Collections; + +/** + * Created by Ed on 16/04/2016. + */ +public class Call extends ILOp { + + public final String functionName; + + public Call(TIdentifier id, String functionName, String comment) { + super(id, "Call", comment); + this.functionName = functionName; + } + + @Override + public Integer getEncodedSize() { + //TODO: Set encoded size properly + return 1; + } + + @Override + public Iterable getArgs() { + return Collections.singletonList(functionName); + } + + @Override + public TReturn accept(ILOpVisitor visitor, TContext ctx) { + return visitor.visitCall(this, ctx); + } +} \ No newline at end of file diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/CompareEqual.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/CompareEqual.java new file mode 100644 index 0000000..80fc955 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/CompareEqual.java @@ -0,0 +1,27 @@ +package uk.co.transputersystems.occam.il; + + +import java.util.Collections; + +public class CompareEqual extends ILOp { + + public CompareEqual(TIdentifier id, String comment) { + super(id, "CompareEqual", comment); + } + + @Override + public TReturn accept(ILOpVisitor visitor, TContext ctx) { + return visitor.visitCompareEqual(this, ctx); + } + + @Override + public Integer getEncodedSize() { + //TODO: Set encoded size properly + return 1; + } + + @Override + public Iterable getArgs() { + return Collections.emptyList(); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/CompareGreaterThan.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/CompareGreaterThan.java new file mode 100644 index 0000000..85f1e99 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/CompareGreaterThan.java @@ -0,0 +1,25 @@ +package uk.co.transputersystems.occam.il; + +import java.util.Collections; + +public class CompareGreaterThan extends ILOp { + public CompareGreaterThan(TIdentifier id, String comment) { + super(id, "CompareGreaterThan", comment); + } + + @Override + public Integer getEncodedSize() { + //TODO: Set encoded size properly + return 1; + } + + @Override + public Iterable getArgs() { + return Collections.emptyList(); + } + + @Override + public TReturn accept(ILOpVisitor visitor, TContext ctx) { + return visitor.visitCompareGreaterThan(this, ctx); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/CompareGreaterThanOrEqual.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/CompareGreaterThanOrEqual.java new file mode 100644 index 0000000..af3d602 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/CompareGreaterThanOrEqual.java @@ -0,0 +1,25 @@ +package uk.co.transputersystems.occam.il; + +import java.util.Collections; + +public class CompareGreaterThanOrEqual extends ILOp { + public CompareGreaterThanOrEqual(TIdentifier id, String comment) { + super(id, "CompareGreaterThanOrEqual", comment); + } + + @Override + public Integer getEncodedSize() { + //TODO: Set encoded size properly + return 1; + } + + @Override + public Iterable getArgs() { + return Collections.emptyList(); + } + + @Override + public TReturn accept(ILOpVisitor visitor, TContext ctx) { + return visitor.visitCompareGreaterThanOrEqual(this, ctx); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/CompareLessThan.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/CompareLessThan.java new file mode 100644 index 0000000..97a3665 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/CompareLessThan.java @@ -0,0 +1,27 @@ +package uk.co.transputersystems.occam.il; + + +import java.util.Collections; + +public class CompareLessThan extends ILOp { + + public CompareLessThan(TIdentifier id, String comment) { + super(id, "CompareLessThan", comment); + } + + @Override + public Integer getEncodedSize() { + //TODO: Set encoded size properly + return 1; + } + + @Override + public Iterable getArgs() { + return Collections.emptyList(); + } + + @Override + public TReturn accept(ILOpVisitor visitor, TContext ctx) { + return visitor.visitCompareLessThan(this, ctx); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/CompareLessThanOrEqual.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/CompareLessThanOrEqual.java new file mode 100644 index 0000000..c9ecdcf --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/CompareLessThanOrEqual.java @@ -0,0 +1,25 @@ +package uk.co.transputersystems.occam.il; + +import java.util.Collections; + +public class CompareLessThanOrEqual extends ILOp { + public CompareLessThanOrEqual(TIdentifier id, String comment) { + super(id, "CompareLessThanOrEqual", comment); + } + + @Override + public Integer getEncodedSize() { + //TODO: Set encoded size properly + return 1; + } + + @Override + public Iterable getArgs() { + return Collections.emptyList(); + } + + @Override + public TReturn accept(ILOpVisitor visitor, TContext ctx) { + return visitor.visitCompareLessThanOrEqual(this, ctx); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/CompareNotEqual.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/CompareNotEqual.java new file mode 100644 index 0000000..2004ed8 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/CompareNotEqual.java @@ -0,0 +1,27 @@ +package uk.co.transputersystems.occam.il; + + +import java.util.Collections; + +public class CompareNotEqual extends ILOp { + + public CompareNotEqual(TIdentifier id, String comment) { + super(id, "CompareNotEqual", comment); + } + + @Override + public TReturn accept(ILOpVisitor visitor, TContext ctx) { + return visitor.visitCompareNotEqual(this, ctx); + } + + @Override + public Integer getEncodedSize() { + //TODO: Set encoded size properly + return 1; + } + + @Override + public Iterable getArgs() { + return Collections.emptyList(); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/DelayedTimerInput.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/DelayedTimerInput.java new file mode 100644 index 0000000..acb2cd4 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/DelayedTimerInput.java @@ -0,0 +1,27 @@ +package uk.co.transputersystems.occam.il; + +import java.util.Collections; + +public class DelayedTimerInput extends ILOp { + + public DelayedTimerInput(TIdentifier id, String comment) { + super(id, "DelayedTimerInput", comment); + } + + @Override + public Integer getEncodedSize() { + //TODO: Set encoded size properly + return 1; + } + + @Override + public Iterable getArgs() { + return Collections.emptyList(); + } + + @Override + public TReturn accept(ILOpVisitor visitor, TContext ctx) { + return visitor.visitDelayedTimerInput(this, ctx); + } + +} \ No newline at end of file diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/DisableChannel.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/DisableChannel.java new file mode 100644 index 0000000..6622ec2 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/DisableChannel.java @@ -0,0 +1,31 @@ +package uk.co.transputersystems.occam.il; + +import java.util.Arrays; + +public class DisableChannel extends ILOp { + + public TIdentifier target , endAlt ; + + public DisableChannel(TIdentifier id , TIdentifier target , TIdentifier endAlt, String comment) { + super(id, "DisableChannel", comment); + this.target = target; + this.endAlt = endAlt; + } + + @Override + public TReturn accept(ILOpVisitor visitor, TContext ctx) { + return visitor.visitDisableChannel(this, ctx); + } + + @Override + public Integer getEncodedSize() { + //TODO: Set encoded size properly + return 1; + } + + @Override + public Iterable getArgs() { + return Arrays.asList(String.valueOf(target), String.valueOf(endAlt)); + } + +} \ No newline at end of file diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/DisablePort.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/DisablePort.java new file mode 100644 index 0000000..e69e2b3 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/DisablePort.java @@ -0,0 +1,33 @@ +package uk.co.transputersystems.occam.il; + +import java.util.Arrays; + + +public class DisablePort extends ILOp { + + public TIdentifier target , endAlt ; + + + public DisablePort(TIdentifier id, TIdentifier target, TIdentifier endAlt , String comment) { + super(id, "DisablePort", comment); + this.target = target; + this.endAlt = endAlt; + } + + @Override + public TReturn accept(ILOpVisitor visitor, TContext ctx) { + return visitor.visitDisablePort(this, ctx); + } + + @Override + public Integer getEncodedSize() { + //TODO: Set encoded size properly + return 1; + } + + @Override + public Iterable getArgs() { + return Arrays.asList(String.valueOf(target), String.valueOf(endAlt)); + } + +} \ No newline at end of file diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/DisableSkip.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/DisableSkip.java new file mode 100644 index 0000000..85e9c84 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/DisableSkip.java @@ -0,0 +1,30 @@ +package uk.co.transputersystems.occam.il; + +import java.util.Arrays; + +public class DisableSkip extends ILOp { + + public TIdentifier target, endAlt; + + public DisableSkip(TIdentifier id, TIdentifier target , TIdentifier endAlt , String comment) { + super(id, "DisableSkip", comment); + this.target = target; + this.endAlt = endAlt; + } + + @Override + public TReturn accept(ILOpVisitor visitor, TContext ctx) { + return visitor.visitDisableSkip(this, ctx); + } + + @Override + public Integer getEncodedSize() { + //TODO: Set encoded size properly + return 1; + } + + @Override + public Iterable getArgs() { + return Arrays.asList(String.valueOf(target), String.valueOf(endAlt)); + } +} \ No newline at end of file diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/DisableTimer.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/DisableTimer.java new file mode 100644 index 0000000..a035ee4 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/DisableTimer.java @@ -0,0 +1,33 @@ +package uk.co.transputersystems.occam.il; + +import java.util.Arrays; + + +public class DisableTimer extends ILOp { + + public TIdentifier target , endAlt ; + + + public DisableTimer(TIdentifier id, TIdentifier target, TIdentifier endAlt , String comment) { + super(id, "DisableTimer", comment); + this.target = target; + this.endAlt = endAlt; + } + + @Override + public TReturn accept(ILOpVisitor visitor, TContext ctx) { + return visitor.visitDisableTimer(this, ctx); + } + + @Override + public Integer getEncodedSize() { + //TODO: Set encoded size properly + return 1; + } + + @Override + public Iterable getArgs() { + return Arrays.asList(String.valueOf(target), String.valueOf(endAlt)); + } + +} \ No newline at end of file diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/Divide.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/Divide.java new file mode 100644 index 0000000..057283c --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/Divide.java @@ -0,0 +1,26 @@ +package uk.co.transputersystems.occam.il; + +import java.util.Collections; + +public class Divide extends ILOp { + + public Divide(TIdentifier id, String comment) { + super(id, "Divide", comment); + } + + @Override + public TReturn accept(ILOpVisitor visitor, TContext ctx) { + return visitor.visitDivide(this, ctx); + } + + @Override + public Integer getEncodedSize() { + //TODO: Set encoded size properly + return 1; + } + + @Override + public Iterable getArgs() { + return Collections.emptyList(); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/Duplicate.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/Duplicate.java new file mode 100644 index 0000000..f292fdc --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/Duplicate.java @@ -0,0 +1,25 @@ +package uk.co.transputersystems.occam.il; + +import java.util.Collections; + +public class Duplicate extends ILOp { + public Duplicate(TIdentifier id, String comment) { + super(id, "Duplicate", comment); + } + + @Override + public Integer getEncodedSize() { + //TODO: Set encoded size properly + return 1; + } + + @Override + public Iterable getArgs() { + return Collections.emptyList(); + } + + @Override + public TReturn accept(ILOpVisitor visitor, TContext ctx) { + return visitor.visitDuplicate(this, ctx); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/EnableChannel.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/EnableChannel.java new file mode 100644 index 0000000..a1dfa08 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/EnableChannel.java @@ -0,0 +1,26 @@ +package uk.co.transputersystems.occam.il; + +import java.util.Collections; + +public class EnableChannel extends ILOp { + + public EnableChannel(TIdentifier id, String comment) { + super(id, "EnableChannel", comment); + } + + @Override + public TReturn accept(ILOpVisitor visitor, TContext ctx) { + return visitor.visitEnableChannel(this, ctx); + } + + @Override + public Integer getEncodedSize() { + //TODO: Set encoded size properly + return 1; + } + + @Override + public Iterable getArgs() { + return Collections.emptyList(); + } +} \ No newline at end of file diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/EnablePort.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/EnablePort.java new file mode 100644 index 0000000..681a263 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/EnablePort.java @@ -0,0 +1,27 @@ +package uk.co.transputersystems.occam.il; + +import java.util.Collections; + + +public class EnablePort extends ILOp { + + public EnablePort(TIdentifier id, String comment) { + super(id, "EnablePort", comment); + } + + @Override + public TReturn accept(ILOpVisitor visitor, TContext ctx) { + return visitor.visitEnablePort(this, ctx); + } + + @Override + public Integer getEncodedSize() { + //TODO: Set encoded size properly + return 1; + } + + @Override + public Iterable getArgs() { + return Collections.emptyList(); + } +} \ No newline at end of file diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/EnableSkip.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/EnableSkip.java new file mode 100644 index 0000000..ca1b3b2 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/EnableSkip.java @@ -0,0 +1,26 @@ +package uk.co.transputersystems.occam.il; + +import java.util.Collections; + +public class EnableSkip extends ILOp { + + public EnableSkip(TIdentifier id, String comment) { + super(id, "EnableSkip", comment); + } + + @Override + public TReturn accept(ILOpVisitor visitor, TContext ctx) { + return visitor.visitEnableSkip(this, ctx); + } + + @Override + public Integer getEncodedSize() { + //TODO: Set encoded size properly + return 1; + } + + @Override + public Iterable getArgs() { + return Collections.emptyList(); + } +} \ No newline at end of file diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/EnableTimer.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/EnableTimer.java new file mode 100644 index 0000000..44aef93 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/EnableTimer.java @@ -0,0 +1,27 @@ +package uk.co.transputersystems.occam.il; + +import java.util.Collections; + + +public class EnableTimer extends ILOp { + + public EnableTimer(TIdentifier id, String comment) { + super(id, "EnableTimer", comment); + } + + @Override + public TReturn accept(ILOpVisitor visitor, TContext ctx) { + return visitor.visitEnableTimer(this, ctx); + } + + @Override + public Integer getEncodedSize() { + //TODO: Set encoded size properly + return 1; + } + + @Override + public Iterable getArgs() { + return Collections.emptyList(); + } +} \ No newline at end of file diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/EndAlt.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/EndAlt.java new file mode 100644 index 0000000..9065464 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/EndAlt.java @@ -0,0 +1,29 @@ +package uk.co.transputersystems.occam.il; + +import java.util.Collections; + +public class EndAlt extends ILOp { + + + + public EndAlt(TIdentifier id, String comment) { + super(id, "EndAlt", comment); + } + + @Override + public TReturn accept(ILOpVisitor visitor, TContext ctx) { + return visitor.visitEndAlt(this, ctx); + } + + @Override + public Integer getEncodedSize() { + //TODO: Set encoded size properly + return 1; + } + + @Override + public Iterable getArgs() { + return Collections.emptyList(); + } +} + diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/EndProcess.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/EndProcess.java new file mode 100644 index 0000000..a44aaa6 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/EndProcess.java @@ -0,0 +1,28 @@ +package uk.co.transputersystems.occam.il; + +import java.util.Collections; + +public class EndProcess extends ILOp { + public TIdentifier creatorILOpID; + + public EndProcess(TIdentifier id, TIdentifier creatorILOpID, String comment) { + super(id, "EndProcess", comment); + this.creatorILOpID = creatorILOpID; + } + + @Override + public Integer getEncodedSize() { + //TODO: Set encoded size properly + return 1; + } + + @Override + public Iterable getArgs() { + return Collections.singletonList(creatorILOpID.toString()); + } + + @Override + public TReturn accept(ILOpVisitor visitor, TContext ctx) { + return visitor.visitEndProcess(this, ctx); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/ILBlock.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/ILBlock.java new file mode 100644 index 0000000..42b7af1 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/ILBlock.java @@ -0,0 +1,134 @@ +package uk.co.transputersystems.occam.il; + +import uk.co.transputersystems.occam.ILOpFormatter; +import uk.co.transputersystems.occam.metadata.VerificationContext; + +import java.util.ArrayList; +import java.util.List; + +public class ILBlock> { + private List ilOps = new ArrayList<>(); + /** + * The Id of the scope to which this ILBlock belongs or -1 to indicate that it doesn't matter. + * + * This value is only relevant for the top-most ILBlock which represents the container of all the ILOps for a particular procedure. + */ + private int scopeId = -1; + + private boolean functionBlock = false; + + public ILBlock() { + } + + public ILBlock(TILOp op) { + ilOps.add(op); + } + + public ILBlock(int scopeId, boolean functionBlock) { + this.functionBlock = functionBlock; + this.scopeId = scopeId; + } + + public int getScopeId() { + return scopeId; + } + public boolean isFunctionBlock() { + return functionBlock; + } + + public TILOp get(int index) { + return ilOps.get(index); + } + public TILOp get(TIdentifier id) { + for (TILOp op : ilOps) { + if (op.getId().equals(id)) { + return op; + } + } + return null; + } + + public void add(int position, TILOp op){ + ilOps.add(position, op); + } + + public void add(TILOp op) { + ilOps.add(op); + } + public void addAll(List ops) { + ilOps.addAll(ops); + } + public void appendBlock(ILBlock block) { + addAll(block.getAll()); + } + public void appendBlockList(Iterable> blocks){ + for(ILBlock ilBlock : blocks){ + this.appendBlock(ilBlock); + } + } + public List getAll() { + return new ArrayList<>(ilOps); + } + + public List> mergeBlockList(Iterable> blocks) { + List> result = new ArrayList<>(); + for(ILBlock ilBlock : blocks){ + if (ilBlock.isFunctionBlock()) { + result.add(ilBlock); + } else { + this.appendBlock(ilBlock); + } + } + result.add(this); + return result; + } + + /** + * Gets the offset, in bytes, of the specified IL op from the start of the block. + * @param opId The Id of the operation to get the offset of. + * @return The offset, in bytes, from the start of the block. + */ + public Integer getOffset(TIdentifier opId) { + int offset = 0; + for (TILOp op : ilOps) { + if (op.getId().equals(opId)) { + return offset; + } + offset += op.getEncodedSize(); + } + return null; + } + + public Integer getOffset(ILOp searchOp) { + int offset = 0; + for (TILOp op : ilOps) { + if (op.equals(searchOp)) { + return offset; + } + offset += op.getEncodedSize(); + } + return null; + } + + @Override + public String toString() { + String result = " [ILBlock scope: " + (scopeId == -1 ? "[PARENT]" : Integer.toString(scopeId)) + "]\n"; + for (TILOp ilOp : ilOps) { + result += ILOpFormatter.formatOp(ilOp, this) + "\n"; + } + return result; + } + + public void verify(VerificationContext ctx) { + int methodStartOps = 0; + + for (ILOp ilOp : ilOps) { + if (ilOp instanceof MethodStart) { + methodStartOps++; + } + ilOp.verify(ctx); + } + + assert (methodStartOps == (isFunctionBlock() ? 1 : 0)); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/ILOp.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/ILOp.java new file mode 100644 index 0000000..e34232c --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/ILOp.java @@ -0,0 +1,85 @@ +package uk.co.transputersystems.occam.il; + +import uk.co.transputersystems.occam.metadata.VerifiableData; +import uk.co.transputersystems.occam.metadata.VerificationContext; + +import java.util.ArrayList; +import java.util.List; + +public abstract class ILOp implements VerifiableData { + protected final TIdentifier id; + protected final String opName; + protected String comment; + protected boolean requiresLabel = false; + protected boolean requiresPopAfterLabel = false; + protected List storeResultIndices = new ArrayList<>(); + + protected ILOp(TIdentifier id, String opName, String comment) { + this.id = id; + this.opName = opName; + this.comment = comment; + } + + /** + * A unique identifier for this ILOp + */ + public final TIdentifier getId() { + return this.id; + }; + + /** + * @return A human-readable IL op type + */ + public final String getOpName() { + return this.opName; + }; + + /** + * @return A human-readable comment about this `ILOp`. + */ + public final String getComment() { + return this.comment; + }; + + public final void setComment(String value) { + this.comment = value; + }; + + /** + * @return A list of static args to this `ILOp`. + */ + public abstract Iterable getArgs(); + + /** + * @return The size of this `ILOp`, in bytes, when encoded. + */ + public abstract Integer getEncodedSize(); + + public boolean getRequiresLabel() { + return requiresLabel; + } + public void setRequiresLabel(boolean value) { + requiresLabel = value; + } + + public boolean getRequiresPopAfterLabel() { + return requiresPopAfterLabel; + } + public void setRequiresPopAfterLabel(boolean value) { + requiresPopAfterLabel = value; + } + + public boolean storeResult(int index) { + return storeResultIndices.contains(index); + } + public void setStoreResult(int index) { + storeResultIndices.add(index); + } + + public abstract TReturn accept(ILOpVisitor visitor, TContext ctx); + + public void verify(VerificationContext ctx) { + //TODO: This method should be abstract in future + //TODO: Verify all IL ops - should implement in all extension classes + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/ILOpVisitor.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/ILOpVisitor.java new file mode 100644 index 0000000..d01661a --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/ILOpVisitor.java @@ -0,0 +1,72 @@ +package uk.co.transputersystems.occam.il; + +public abstract class ILOpVisitor { + public abstract TReturn visitStartProcess(StartProcess op, TContext ctx); + public abstract TReturn visitEndProcess(EndProcess op, TContext ctx); + public abstract TReturn visitInitProcesses(InitProcesses op, TContext ctx); + public abstract TReturn visitSkip(Skip op, TContext ctx); + public abstract TReturn visitLabel(Label op, TContext ctx); + public abstract TReturn visitLoadConstant(LoadConstant op, TContext ctx); + public abstract TReturn visitLoadLocal(LoadLocal op, TContext ctx); + public abstract TReturn visitLoadArgument(LoadArgument op, TContext ctx); + public abstract TReturn visitLoadGlobal(LoadGlobal op, TContext ctx); + public abstract TReturn visitStoreLocal(StoreLocal op, TContext ctx); + public abstract TReturn visitStoreArgument(StoreArgument op, TContext ctx); + public abstract TReturn visitStoreGlobal(StoreGlobal op, TContext ctx); + public abstract TReturn visitReadChannel(ReadChannel op, TContext ctx); + public abstract TReturn visitAdd(Add op, TContext ctx); + public abstract TReturn visitSubtract(Subtract op, TContext ctx); + public abstract TReturn visitMultiply(Multiply op, TContext ctx); + public abstract TReturn visitDuplicate(Duplicate op, TContext ctx); + public abstract TReturn visitBranchEqZero(BranchEqZero op, TContext ctx); + public abstract TReturn visitBranchNotEqZero(BranchNotEqZero op, TContext ctx); + public abstract TReturn visitBranch(Branch op, TContext ctx); + public abstract TReturn visitCompareGreaterThan(CompareGreaterThan op, TContext ctx); + public abstract TReturn visitCompareGreaterThanOrEqual(CompareGreaterThanOrEqual op, TContext ctx); + public abstract TReturn visitBranchIfTrue(BranchIfTrue op, TContext ctx); + public abstract TReturn visitBranchIfFalse(BranchIfFalse op, TContext ctx); + public abstract TReturn visitCompareLessThan(CompareLessThan op, TContext ctx); + public abstract TReturn visitCompareLessThanOrEqual(CompareLessThanOrEqual op, TContext ctx); + public abstract TReturn visitCompareEqual(CompareEqual op, TContext ctx); + public abstract TReturn visitCompareNotEqual(CompareNotEqual op, TContext ctx); + public abstract TReturn visitBitwiseAnd(BitwiseAnd op, TContext ctx); + public abstract TReturn visitBitwiseOr(BitwiseOr op, TContext ctx); + public abstract TReturn visitBitwiseNot(BitwiseNot op, TContext ctx); + public abstract TReturn visitBooleanNot(BooleanNot op, TContext ctx); + public abstract TReturn visitDivide(Divide op, TContext ctx); + public abstract TReturn visitModulo(Modulo op, TContext ctx); + public abstract TReturn visitBitwiseXor(BitwiseXor op, TContext ctx); + public abstract TReturn visitUnaryMinus(UnaryMinus op, TContext ctx); + public abstract TReturn visitMethodStart(MethodStart op, TContext ctx); + public abstract TReturn visitMethodEnd(MethodEnd op, TContext ctx); + public abstract TReturn visitCall(Call op, TContext ctx); + public abstract TReturn visitWriteChannel(WriteChannel op, TContext ctx); + public abstract TReturn visitWritePort(WritePort op, TContext ctx); + public abstract TReturn visitReadPort(ReadPort op, TContext ctx); + public abstract TReturn visitReadTimer(ReadTimer op, TContext ctx); + public abstract TReturn visitInitChannel(InitChannel op, TContext ctx); + public abstract TReturn visitLoadChannelRef(LoadChannelRef op, TContext ctx); + public abstract TReturn visitLoadPortRef(LoadPortRef op, TContext ctx); + public abstract TReturn visitDelayedTimerInput(DelayedTimerInput op , TContext ctx); + public abstract TReturn visitAfter(After op , TContext ctx); + public abstract TReturn visitLeftShift(LeftShift op , TContext ctx); + public abstract TReturn visitRightShift(RightShift op , TContext ctx); + public abstract TReturn visitDisableChannel(DisableChannel op, TContext ctx); + public abstract TReturn visitEnableChannel(EnableChannel op, TContext ctx); + public abstract TReturn visitDisableTimer(DisableTimer op, TContext ctx); + public abstract TReturn visitEnableTimer(EnableTimer op, TContext ctx); + public abstract TReturn visitDisableSkip(DisableSkip op, TContext ctx); + public abstract TReturn visitEnableSkip(EnableSkip op, TContext ctx); + public abstract TReturn visitInitAlt(InitAlt op , TContext ctx); + public abstract TReturn visitWaitAlt(WaitAlt op , TContext ctx); + public abstract TReturn visitEndAlt(EndAlt op , TContext ctx); + public abstract TReturn visitEnablePort(EnablePort op , TContext ctx); + public abstract TReturn visitDisablePort(DisablePort op , TContext ctx); + public abstract TReturn visitMostPositive(MostPositive op, TContext ctx); + public abstract TReturn visitMostNegative(MostNegative op, TContext ctx); + public abstract TReturn visitBooleanAnd(BooleanAnd op , TContext ctx); + public abstract TReturn visitBooleanOr(BooleanOr op , TContext ctx); + public TReturn visit(ILOp op, TContext ctx) { + return op.accept(this, ctx); + } +} \ No newline at end of file diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/InitAlt.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/InitAlt.java new file mode 100644 index 0000000..42a4def --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/InitAlt.java @@ -0,0 +1,28 @@ +package uk.co.transputersystems.occam.il; + +import java.util.Collections; + +public class InitAlt extends ILOp { + + + + public InitAlt(TIdentifier id, String comment) { + super(id, "InitAlt", comment); + } + + @Override + public TReturn accept(ILOpVisitor visitor, TContext ctx) { + return visitor.visitInitAlt(this, ctx); + } + + @Override + public Integer getEncodedSize() { + //TODO: Set encoded size properly + return 1; + } + + @Override + public Iterable getArgs() { + return Collections.emptyList(); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/InitChannel.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/InitChannel.java new file mode 100644 index 0000000..dca554b --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/InitChannel.java @@ -0,0 +1,31 @@ +package uk.co.transputersystems.occam.il; + +import java.util.Arrays; + +public class InitChannel extends ILOp { + public String name; + public String typeName; + public int index ; + public InitChannel(TIdentifier id, String name, int index, String typeName, String comment) { + super(id, "InitChannel", comment); + this.name = name; + this.index = index; + this.typeName = typeName; + } + + @Override + public TReturn accept(ILOpVisitor visitor, TContext ctx) { + return visitor.visitInitChannel(this, ctx); + } + + @Override + public Integer getEncodedSize() { + //TODO: Set encoded size properly + return 1; + } + + @Override + public Iterable getArgs() { + return Arrays.asList(name, String.valueOf(index), typeName); + } +} \ No newline at end of file diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/InitProcesses.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/InitProcesses.java new file mode 100644 index 0000000..e07adec --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/InitProcesses.java @@ -0,0 +1,40 @@ +package uk.co.transputersystems.occam.il; + +import java.util.Arrays; +import java.util.List; + +/** + * Marks the beginning of a series of `StartProcess` operations, defining the: + * * number of processes that will exist after all processes are started + * * a location to continue executing from once the processes are started + * * the IDs of the workspaces owned by each process + */ +public class InitProcesses extends ILOp { + public int numProcesses; + public TIdentifier continueILOpID; + public List workspaceIds; + + public InitProcesses(TIdentifier id, int numProcesses, TIdentifier continueILOpID, List workspaceIds, String comment) { + super(id, "InitProcesses", comment); + + this.numProcesses = numProcesses; + this.continueILOpID = continueILOpID; + this.workspaceIds = workspaceIds; + } + + @Override + public Integer getEncodedSize() { + //TODO: Set encoded size properly + return 1; + } + + @Override + public Iterable getArgs() { + return Arrays.asList(Integer.toString(numProcesses), continueILOpID.toString(), workspaceIds.toString()); + } + + @Override + public TReturn accept(ILOpVisitor visitor, TContext ctx) { + return visitor.visitInitProcesses(this, ctx); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/Label.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/Label.java new file mode 100644 index 0000000..9319add --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/Label.java @@ -0,0 +1,45 @@ +package uk.co.transputersystems.occam.il; + +import java.util.Arrays; + +public class Label extends ILOp { + + public String label; + public boolean isGlobal; + + private static int labelIncrementer = 0; + + //TODO: Only function names should be using this. Convert everything other usage to Skip ops + //TODO: Refactor this class to be called FunctionName + + public Label(TIdentifier id, String label, boolean isGlobal, String comment) { + super(id, "Label", comment); + this.label = label; + this.isGlobal = isGlobal; + } + + /* + When generating a label with no specified name + One will be automatically generated using an auto incrementer + E.g L0, L1, L2, .... + */ + public Label(TIdentifier id, boolean isGlobal, String comment){ + this(id, "L" + labelIncrementer++, isGlobal, comment); + } + + @Override + public Integer getEncodedSize() { + //TODO: Set encoded size properly + return 1; + } + + @Override + public Iterable getArgs() { + return Arrays.asList(label, Boolean.toString(isGlobal)); + } + + @Override + public TReturn accept(ILOpVisitor visitor, TContext ctx) { + return visitor.visitLabel(this, ctx); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/LeftShift.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/LeftShift.java new file mode 100644 index 0000000..4dcc440 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/LeftShift.java @@ -0,0 +1,28 @@ +package uk.co.transputersystems.occam.il; + + +import java.util.Collections; + +public class LeftShift extends ILOp { + + + public LeftShift(TIdentifier id , String comment) { + super(id, "LeftShift", comment); + } + + @Override + public Integer getEncodedSize() { + //TODO: Set encoded size properly + return 1; + } + + @Override + public Iterable getArgs() { + return Collections.emptyList(); + } + + @Override + public TReturn accept(ILOpVisitor visitor, TContext ctx) { + return visitor.visitLeftShift(this, ctx); + } +} \ No newline at end of file diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/LoadArgument.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/LoadArgument.java new file mode 100644 index 0000000..f05dce5 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/LoadArgument.java @@ -0,0 +1,33 @@ +package uk.co.transputersystems.occam.il; + +import java.util.Arrays; + +public class LoadArgument extends ILOp { + //TODO: Document this IL op in the specification + + public int index; + public boolean loadAddress; + + public LoadArgument(TIdentifier id, int index, String comment, boolean loadAddress) { + super(id, "LoadArgument", comment); + this.index = index; + this.loadAddress = loadAddress; + } + + @Override + public Integer getEncodedSize() { + //TODO: Set encoded size properly + return 1; + } + + @Override + public Iterable getArgs() { + return Arrays.asList(String.valueOf(index), String.valueOf(loadAddress)); + } + + @Override + public TReturn accept(ILOpVisitor visitor, TContext ctx) { + return visitor.visitLoadArgument(this, ctx); + } + +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/LoadChannelRef.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/LoadChannelRef.java new file mode 100644 index 0000000..1e3bb7c --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/LoadChannelRef.java @@ -0,0 +1,27 @@ +package uk.co.transputersystems.occam.il; + +import java.util.Arrays; + +public class LoadChannelRef extends ILOp { + public int index; + public LoadChannelRef(TIdentifier id, int index ,String comment) { + super(id, "LoadChannelRef", comment); + this.index = index; + } + + @Override + public TReturn accept(ILOpVisitor visitor, TContext ctx) { + return visitor.visitLoadChannelRef(this, ctx); + } + + @Override + public Integer getEncodedSize() { + //TODO: Set encoded size properly + return 1; + } + + @Override + public Iterable getArgs() { + return Arrays.asList(String.valueOf(index)); + } +} \ No newline at end of file diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/LoadConstant.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/LoadConstant.java new file mode 100644 index 0000000..4d3ae23 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/LoadConstant.java @@ -0,0 +1,30 @@ +package uk.co.transputersystems.occam.il; + +import java.util.Collections; + +public class LoadConstant extends ILOp { + //TODO: Document this IL op in the specification + + public String value; + + public LoadConstant(TIdentifier id, String value, String comment) { + super(id, "LoadConstant", comment); + this.value = value; + } + + @Override + public Integer getEncodedSize() { + //TODO: Set encoded size properly + return 1; + } + + @Override + public Iterable getArgs() { + return Collections.singletonList(value); + } + + @Override + public TReturn accept(ILOpVisitor visitor, TContext ctx) { + return visitor.visitLoadConstant(this, ctx); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/LoadGlobal.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/LoadGlobal.java new file mode 100644 index 0000000..33296f4 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/LoadGlobal.java @@ -0,0 +1,34 @@ +package uk.co.transputersystems.occam.il; + +import java.util.Arrays; + +public class LoadGlobal extends ILOp { + + //TODO: Document this IL op in the specification + + public String globalName; + public boolean loadAddress; + + public LoadGlobal(TIdentifier id, String globalName, String comment, boolean loadAddress) { + super(id, "LoadGlobal", comment); + this.globalName = globalName; + this.loadAddress = loadAddress; + } + + @Override + public Integer getEncodedSize() { + //TODO: Set encoded size properly + return 1; + } + + @Override + public Iterable getArgs() { + return Arrays.asList(globalName, String.valueOf(loadAddress)); + } + + @Override + public TReturn accept(ILOpVisitor visitor, TContext ctx) { + return visitor.visitLoadGlobal(this, ctx); + } + +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/LoadLocal.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/LoadLocal.java new file mode 100644 index 0000000..6a9cbf5 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/LoadLocal.java @@ -0,0 +1,38 @@ +package uk.co.transputersystems.occam.il; + +import java.util.Arrays; + +public class LoadLocal extends ILOp { + + //TODO: Document this IL op in the specification + + /* + * See Notes in StoreLocal. + */ + + public int index; + public boolean loadAddress; + + public LoadLocal(TIdentifier id, int index, String comment, boolean loadAddress) { + super(id, "LoadLocal", comment); + this.index = index; + this.loadAddress = loadAddress; + } + + @Override + public Integer getEncodedSize() { + //TODO: Set encoded size properly + return 1; + } + + @Override + public Iterable getArgs() { + return Arrays.asList(String.valueOf(index), String.valueOf(loadAddress)); + } + + @Override + public TReturn accept(ILOpVisitor visitor, TContext ctx) { + return visitor.visitLoadLocal(this, ctx); + } + +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/LoadPortRef.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/LoadPortRef.java new file mode 100644 index 0000000..d7251c6 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/LoadPortRef.java @@ -0,0 +1,31 @@ +package uk.co.transputersystems.occam.il; + +import java.util.Arrays; + +public class LoadPortRef extends ILOp { + + + public int index; + + public LoadPortRef(TIdentifier id, int index, String comment) { + super(id, "LoadPortRef", comment); + this.index = index; + } + + @Override + public Integer getEncodedSize() { + //TODO: Set encoded size properly + return 1; + } + + @Override + public Iterable getArgs() { + return Arrays.asList(String.valueOf(index)); + } + + @Override + public TReturn accept(ILOpVisitor visitor, TContext ctx) { + return visitor.visitLoadPortRef(this, ctx); + } + +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/MethodEnd.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/MethodEnd.java new file mode 100644 index 0000000..4f492d5 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/MethodEnd.java @@ -0,0 +1,29 @@ +package uk.co.transputersystems.occam.il; + +import java.util.Collections; + +/** + * Created by Ed on 30/03/2016. + */ +public class MethodEnd extends ILOp { + + public MethodEnd(TIdentifier id, String comment) { + super(id, "MethodEnd", comment); + } + + @Override + public Integer getEncodedSize() { + //TODO: Set encoded size properly + return 1; + } + + @Override + public Iterable getArgs() { + return Collections.emptyList(); + } + + @Override + public TReturn accept(ILOpVisitor visitor, TContext ctx) { + return visitor.visitMethodEnd(this, ctx); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/MethodStart.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/MethodStart.java new file mode 100644 index 0000000..6dfe87a --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/MethodStart.java @@ -0,0 +1,29 @@ +package uk.co.transputersystems.occam.il; + +import java.util.Collections; + +/** + * Created by Ed on 30/03/2016. + */ +public class MethodStart extends ILOp { + + public MethodStart(TIdentifier id, String comment) { + super(id, "MethodStart", comment); + } + + @Override + public Integer getEncodedSize() { + //TODO: Set encoded size properly + return 1; + } + + @Override + public Iterable getArgs() { + return Collections.emptyList(); + } + + @Override + public TReturn accept(ILOpVisitor visitor, TContext ctx) { + return visitor.visitMethodStart(this, ctx); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/Modulo.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/Modulo.java new file mode 100644 index 0000000..01f20a6 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/Modulo.java @@ -0,0 +1,26 @@ +package uk.co.transputersystems.occam.il; + +import java.util.Collections; + +public class Modulo extends ILOp { + + public Modulo(TIdentifier id, String comment) { + super(id, "Modulo", comment); + } + + @Override + public TReturn accept(ILOpVisitor visitor, TContext ctx) { + return visitor.visitModulo(this, ctx); + } + + @Override + public Integer getEncodedSize() { + //TODO: Set encoded size properly + return 1; + } + + @Override + public Iterable getArgs() { + return Collections.emptyList(); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/MostNegative.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/MostNegative.java new file mode 100644 index 0000000..23fe080 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/MostNegative.java @@ -0,0 +1,30 @@ +package uk.co.transputersystems.occam.il; + +import java.util.Collections; + + +public class MostNegative extends ILOp { + + public final String type; + + public MostNegative(TIdentifier id, String type, String comment) { + super(id, "MostNegative", comment + ", " + type ); + this.type = type; + } + + @Override + public Integer getEncodedSize() { + //TODO: Set encoded size properly + return 1; + } + + @Override + public Iterable getArgs() { + return Collections.singleton(type); + } + + @Override + public TReturn accept(ILOpVisitor visitor, TContext ctx) { + return visitor.visitMostNegative(this, ctx); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/MostPositive.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/MostPositive.java new file mode 100644 index 0000000..b9f24bf --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/MostPositive.java @@ -0,0 +1,30 @@ +package uk.co.transputersystems.occam.il; + +import java.util.Collections; + + +public class MostPositive extends ILOp { + + public final String type; + + public MostPositive(TIdentifier id, String type, String comment) { + super(id, "MostPositive", comment + ", " + type ); + this.type = type; + } + + @Override + public Integer getEncodedSize() { + //TODO: Set encoded size properly + return 1; + } + + @Override + public Iterable getArgs() { + return Collections.singleton(type); + } + + @Override + public TReturn accept(ILOpVisitor visitor, TContext ctx) { + return visitor.visitMostPositive(this, ctx); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/Multiply.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/Multiply.java new file mode 100644 index 0000000..5bd569e --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/Multiply.java @@ -0,0 +1,29 @@ +package uk.co.transputersystems.occam.il; + +import java.util.Collections; + +public class Multiply extends ILOp { + + public final boolean ignore_overflow; + + public Multiply(TIdentifier id, boolean ignore_overflow, String comment) { + super(id, "Multiply", comment + ", " + (ignore_overflow ? "ignore_overflow" : "don't ignore overflow")); + this.ignore_overflow = ignore_overflow; + } + + @Override + public Integer getEncodedSize() { + //TODO: Set encoded size properly + return 1; + } + + @Override + public Iterable getArgs() { + return Collections.emptyList(); + } + + @Override + public TReturn accept(ILOpVisitor visitor, TContext ctx) { + return visitor.visitMultiply(this, ctx); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/ProcessPriorities.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/ProcessPriorities.java new file mode 100644 index 0000000..72df004 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/ProcessPriorities.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.il; + +public enum ProcessPriorities { + Low, + High, + Current +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/ReadChannel.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/ReadChannel.java new file mode 100644 index 0000000..28eda38 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/ReadChannel.java @@ -0,0 +1,27 @@ +package uk.co.transputersystems.occam.il; + +import java.util.Collections; + +public class ReadChannel extends ILOp { + + public ReadChannel(TIdentifier id, String comment) { + super(id, "ReadChannel", comment); + } + + @Override + public Integer getEncodedSize() { + //TODO: Set encoded size properly + return 1; + } + + @Override + public Iterable getArgs() { + return Collections.emptyList(); + } + + @Override + public TReturn accept(ILOpVisitor visitor, TContext ctx) { + return visitor.visitReadChannel(this, ctx); + } + +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/ReadPort.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/ReadPort.java new file mode 100644 index 0000000..4eb4f64 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/ReadPort.java @@ -0,0 +1,27 @@ +package uk.co.transputersystems.occam.il; +import java.util.Collections; + +public class ReadPort extends ILOp { + + public ReadPort(TIdentifier id, String comment) { + super(id, "ReadPort", comment); + } + + @Override + public Integer getEncodedSize() { + //TODO: Set encoded size properly + return 1; + } + + @Override + public Iterable getArgs() { + return Collections.emptyList(); + } + + @Override + public TReturn accept(ILOpVisitor visitor, TContext ctx) { + return visitor.visitReadPort(this, ctx); + } + +} + diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/ReadTimer.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/ReadTimer.java new file mode 100644 index 0000000..37c3380 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/ReadTimer.java @@ -0,0 +1,28 @@ +package uk.co.transputersystems.occam.il; + +import java.util.Collections; + +public class ReadTimer extends ILOp { + + public ReadTimer(TIdentifier id, String comment) { + super(id, "ReadTimer", comment); + } + + @Override + public Integer getEncodedSize() { + //TODO: Set encoded size properly + return 1; + } + + @Override + public Iterable getArgs() { + return Collections.emptyList(); + } + + @Override + public TReturn accept(ILOpVisitor visitor, TContext ctx) { + return visitor.visitReadTimer(this, ctx); + } + +} + diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/RightShift.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/RightShift.java new file mode 100644 index 0000000..c134603 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/RightShift.java @@ -0,0 +1,28 @@ +package uk.co.transputersystems.occam.il; + + +import java.util.Collections; + +public class RightShift extends ILOp { + + + public RightShift(TIdentifier id , String comment) { + super(id, "RightShift", comment); + } + + @Override + public Integer getEncodedSize() { + //TODO: Set encoded size properly + return 1; + } + + @Override + public Iterable getArgs() { + return Collections.emptyList(); + } + + @Override + public TReturn accept(ILOpVisitor visitor, TContext ctx) { + return visitor.visitRightShift(this, ctx); + } +} \ No newline at end of file diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/Skip.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/Skip.java new file mode 100644 index 0000000..f5a2098 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/Skip.java @@ -0,0 +1,26 @@ +package uk.co.transputersystems.occam.il; + +import java.util.Collections; + +public class Skip extends ILOp { + + public Skip(TIdentifier id, String comment) { + super(id, "Skip", comment); + } + + @Override + public Integer getEncodedSize() { + //TODO: Set encoded size properly + return 1; + } + + @Override + public Iterable getArgs() { + return Collections.emptyList(); + } + + @Override + public TReturn accept(ILOpVisitor visitor, TContext ctx) { + return visitor.visitSkip(this, ctx); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/StartProcess.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/StartProcess.java new file mode 100644 index 0000000..fdda2f3 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/StartProcess.java @@ -0,0 +1,31 @@ +package uk.co.transputersystems.occam.il; + +import java.util.Arrays; + +public class StartProcess extends ILOp { + public TIdentifier firstILOpID; + public ProcessPriorities newPriority; + + public StartProcess(TIdentifier id, TIdentifier creatorILOpID, ProcessPriorities newPriority, String comment) { + super(id, "StartProcess", comment); + + this.firstILOpID = creatorILOpID; + this.newPriority = newPriority; + } + + @Override + public Integer getEncodedSize() { + //TODO: Set encoded size properly + return 1; + } + + @Override + public Iterable getArgs() { + return Arrays.asList(firstILOpID.toString(), newPriority.name()); + } + + @Override + public TReturn accept(ILOpVisitor visitor, TContext ctx) { + return visitor.visitStartProcess(this, ctx); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/StoreArgument.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/StoreArgument.java new file mode 100644 index 0000000..e106135 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/StoreArgument.java @@ -0,0 +1,33 @@ +package uk.co.transputersystems.occam.il; + +import java.util.Collections; + +public class StoreArgument extends ILOp { + + //TODO: Document this IL op in the specification + + public int index; + + public StoreArgument(TIdentifier id, int index, String comment) { + super(id, "StoreArgument", comment); + + this.index = index; + } + + @Override + public Integer getEncodedSize() { + //TODO: Set encoded size properly + return 1; + } + + @Override + public Iterable getArgs() { + return Collections.singletonList(String.valueOf(index)); + } + + @Override + public TReturn accept(ILOpVisitor visitor, TContext ctx) { + return visitor.visitStoreArgument(this, ctx); + } + +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/StoreGlobal.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/StoreGlobal.java new file mode 100644 index 0000000..6cb984a --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/StoreGlobal.java @@ -0,0 +1,33 @@ +package uk.co.transputersystems.occam.il; + +import java.util.Collections; + +public class StoreGlobal extends ILOp { + + //TODO: Document this IL op in the specification + + public String globalName; + + public StoreGlobal(TIdentifier id, String globalName, String comment) { + super(id, "StoreGlobal", comment); + + this.globalName = globalName; + } + + @Override + public Integer getEncodedSize() { + //TODO: Set encoded size properly + return 1; + } + + @Override + public Iterable getArgs() { + return Collections.singletonList(String.valueOf(globalName)); + } + + @Override + public TReturn accept(ILOpVisitor visitor, TContext ctx) { + return visitor.visitStoreGlobal(this, ctx); + } + +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/StoreLocal.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/StoreLocal.java new file mode 100644 index 0000000..4c3af4f --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/StoreLocal.java @@ -0,0 +1,43 @@ +package uk.co.transputersystems.occam.il; + +import java.util.Collections; + +public class StoreLocal extends ILOp { + + //TODO: Document this IL op in the specification + + /* + * Notes: + * - Local index refers to index within the current scope and parent scopes. However, Scopes will need to + * be translated into different workspaces by the ASMGenerator. This means that just because a local index + * from the current scope is the same as a local index from a horizontally level scope, they will not + * necessarily point to the same memory. They might point to the same offset from the workspace pointer. + * It may also be necessary to travel up the workspace linked list to reach the memory for a particular local. + * Scopes do not directly translate to new workspaces. + */ + + public int index; + + public StoreLocal(TIdentifier id, int index, String comment) { + super(id, "StoreLocal", comment); + + this.index = index; + } + + @Override + public Integer getEncodedSize() { + //TODO: Set encoded size properly + return 1; + } + + @Override + public Iterable getArgs() { + return Collections.singletonList(String.valueOf(index)); + } + + @Override + public TReturn accept(ILOpVisitor visitor, TContext ctx) { + return visitor.visitStoreLocal(this, ctx); + } + +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/Subtract.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/Subtract.java new file mode 100644 index 0000000..7d0a303 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/Subtract.java @@ -0,0 +1,29 @@ +package uk.co.transputersystems.occam.il; + +import java.util.Collections; + +public class Subtract extends ILOp { + + public final boolean ignore_overflow; + + public Subtract(TIdentifier id, boolean ignore_overflow, String comment) { + super(id, "Subtract", comment + ", " + (ignore_overflow ? "ignore_overflow" : "allow_underflow")); + this.ignore_overflow = ignore_overflow; + } + + @Override + public Integer getEncodedSize() { + //TODO: Set encoded size properly + return 1; + } + + @Override + public Iterable getArgs() { + return Collections.emptyList(); + } + + @Override + public TReturn accept(ILOpVisitor visitor, TContext ctx) { + return visitor.visitSubtract(this, ctx); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/UnaryMinus.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/UnaryMinus.java new file mode 100644 index 0000000..422920b --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/UnaryMinus.java @@ -0,0 +1,30 @@ +package uk.co.transputersystems.occam.il; + + +import java.util.Collections; + +public class UnaryMinus extends ILOp { + + + public final boolean ignore_overflow; + + public UnaryMinus(TIdentifier id, boolean ignore_overflow, String comment) { + super(id, "Unary minus", comment + ", " + (ignore_overflow ? "ignore_overflow" : "allow_underflow" )); + this.ignore_overflow = ignore_overflow; + } + + @Override + public Iterable getArgs() { + return Collections.emptyList(); + } + + @Override + public Integer getEncodedSize() { + return 1; + } + + @Override + public TReturn accept(ILOpVisitor visitor, TContext ctx) { + return visitor.visitUnaryMinus(this, ctx); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/WaitAlt.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/WaitAlt.java new file mode 100644 index 0000000..eda67dd --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/WaitAlt.java @@ -0,0 +1,28 @@ +package uk.co.transputersystems.occam.il; + +import java.util.Collections; + +public class WaitAlt extends ILOp { + + + + public WaitAlt(TIdentifier id, String comment) { + super(id, "WaitAlt", comment); + } + + @Override + public TReturn accept(ILOpVisitor visitor, TContext ctx) { + return visitor.visitWaitAlt(this, ctx); + } + + @Override + public Integer getEncodedSize() { + //TODO: Set encoded size properly + return 1; + } + + @Override + public Iterable getArgs() { + return Collections.emptyList(); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/WriteChannel.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/WriteChannel.java new file mode 100644 index 0000000..efc3bd1 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/WriteChannel.java @@ -0,0 +1,27 @@ +package uk.co.transputersystems.occam.il; + +import java.util.Collections; + +public class WriteChannel extends ILOp { + + public WriteChannel(TIdentifier id, String comment) { + super(id, "WriteChannel", comment); + } + + @Override + public Integer getEncodedSize() { + //TODO: Set encoded size properly + return 1; + } + + @Override + public Iterable getArgs() { + return Collections.emptyList(); + } + + @Override + public TReturn accept(ILOpVisitor visitor, TContext ctx) { + return visitor.visitWriteChannel(this, ctx); + } + +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/WritePort.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/WritePort.java new file mode 100644 index 0000000..846d761 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/il/WritePort.java @@ -0,0 +1,30 @@ +package uk.co.transputersystems.occam.il; + +import java.util.Collections; + +public class WritePort extends ILOp { + + + + public WritePort(TIdentifier id, String comment) { + super(id, "WritePort", comment); + } + + @Override + public Integer getEncodedSize() { + //TODO: Set encoded size properly + return 1; + } + + @Override + public Iterable getArgs() { + return Collections.emptyList(); + } + + @Override + public TReturn accept(ILOpVisitor visitor, TContext ctx) { + return visitor.visitWritePort(this, ctx); + } + +} + diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/Abbreviation.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/Abbreviation.java new file mode 100644 index 0000000..619f8e1 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/Abbreviation.java @@ -0,0 +1,98 @@ +package uk.co.transputersystems.occam.metadata; + +/** + * An `Abbreviation` binds a new name to an existing variable. As per the Occam 2.1 reference, §4.5: + * + * An abbreviation simply provides a name to identify an existing variable. + * + * @param This abbreviation may optionally represent a constant, whose type is defined by this type parameter. + */ +public abstract class Abbreviation extends NamedOperand { + + protected transient Scope declaringScope; + protected String hiddenName; + + /** + * Construct an `Abbreviation` that hides a non-constant variable. + * @param declaringScope The scope in which this abbreviation is being declared + * @param name The name of the abbreviation + * @param typeName The type of the abbreviation. This is because abbreviations can be used to re-type constants and variables. + * @param hiddenName The name of the variable, array, channel, port or timer being abbreviated. + */ + public Abbreviation(Scope declaringScope, String name, String typeName, String hiddenName) { + super(name, typeName); + + this.hiddenName = hiddenName; + this.declaringScope = declaringScope; + } + + + /** + * Construct an `Abbreviation` that hides a constant value. + * @param declaringScope The scope in which this abbreviation is being declared + * @param name The name of the abbreviation + * @param typeName The type of the abbreviation. This is because abbreviations can be used to re-type constants and variables. + * @param hiddenName The name of the variable, array, channel, port or timer being abbreviated. + * @param constant Whether the abbreviation represents a constant value or not. Abbreviations to constants should be resolved before being created. + * @param constantValue The constant value the abbreviation is for. + */ + public Abbreviation(Scope declaringScope, String name, String typeName, String hiddenName, boolean constant, ConstantType constantValue) { + super(name, typeName, constant, constantValue); + + this.hiddenName = hiddenName; + this.declaringScope = declaringScope; + } + + public String getHiddenName() { + return hiddenName; + } + + public Scope getDeclaringScope() { + return declaringScope; + } + public void setDeclaringScope(Scope scope) { + declaringScope = scope; + } + + /** + * Resolves to the actual `NamedOperand` that is represented by this `Abbreviation`. + * Initially searches the scope in which the abbreviation was declared, then recursively + * searches the parents until a result is found (the result may be null if the root scope + * is reached). + * + * Note that for array abbreviations, this will return the NamedOperand for the underlying array + * but the array abbreviation's index must then be taken into account. + * + * TODO: Callers of this should check whether "this" is an ArrayAbbreviation. If it is, special processing is required. + * + * Said special processing is: + * - For arrays which are in fact constants, the index should be used to resolve to the constant element + * - For arrays which are not constant, the index should be combined with the returned NamedOperand to create IL + * ops to runtime access the element from the array. + * + * @return If found, the `NamedOperand` represented by this `Abbreviation`, otherwise null + */ + public NamedOperand resolveHiddenOperand() { + // Retrieve the scope where this abbreviation was declared - the search will start + // from there (rather than the currentScope) + Scope currentScope = declaringScope; + + // Recursively search the declaringScope and its parents for a `NamedOperand` matching + // the name that this abbreviation hides + NamedOperand result = null; + while (result == null && currentScope != null) { + result = currentScope.searchForNamedOperand(hiddenName); + currentScope = currentScope.getParent(); + } + + return result; + } + + @Override + public void verify(VerificationContext ctx) { + super.verify(ctx); + + assert (declaringScope != null); + assert(resolveHiddenOperand() != null); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/Argument.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/Argument.java new file mode 100644 index 0000000..07997d2 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/Argument.java @@ -0,0 +1,32 @@ +package uk.co.transputersystems.occam.metadata; + +public class Argument extends NamedOperand { + private int index; + private int workspaceOffset; + private boolean passByValue; + + public Argument(String name, String typeName, boolean passByValue) { + super(name, typeName); + + this.index = -1; + this.passByValue = passByValue; + } + + public int getIndex() { + return index; + } + public void setIndex(int index) { + this.index = index; + } + + public boolean getPassByValue() { + return passByValue; + } + + @Override + public void verify(VerificationContext ctx) { + super.verify(ctx); + + assert(index > -1); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/ArrayAbbreviation.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/ArrayAbbreviation.java new file mode 100644 index 0000000..23f7cc5 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/ArrayAbbreviation.java @@ -0,0 +1,26 @@ +package uk.co.transputersystems.occam.metadata; + +public class ArrayAbbreviation extends Abbreviation { + + //TODO: ARGH! The index of an array abbreviation can be a runtime variable (e.g. counter inside a loop) + // So index should resolved to a constant if possible + // Otherwise we will need to store a NamedOperand (or expression???) here to act as the index + protected int index; + + public ArrayAbbreviation(Scope declaringScope, String name, String typeName, String hideName, int index) { + super(declaringScope, name, typeName, hideName); + + this.index = index; + } + + public int getIndex() { + return index; + } + + @Override + public void verify(VerificationContext ctx) { + super.verify(ctx); + + //TODO: Array abbreviation verification + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/ArrayDataType.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/ArrayDataType.java new file mode 100644 index 0000000..5daf262 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/ArrayDataType.java @@ -0,0 +1,36 @@ +package uk.co.transputersystems.occam.metadata; + +import java.util.List; + +public class ArrayDataType extends DataType { + + private String elementTypeName; + private List dimensions; + + public ArrayDataType(String name, String elementTypeName, List dimensions) { + super(name); + + this.elementTypeName = elementTypeName; + this.dimensions = dimensions; + } + + public String getElementTypeName() { + return elementTypeName; + } + + public List getDimensions() { + return dimensions; + } + + @Override + public void verify(VerificationContext ctx) { + super.verify(ctx); + + assert (elementTypeName != null); + assert (!elementTypeName.isEmpty()); + assert (ctx.isDataTypeKnown(elementTypeName)); + + assert (dimensions.size() > 0); + + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/Channel.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/Channel.java new file mode 100644 index 0000000..5cf43e4 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/Channel.java @@ -0,0 +1,13 @@ +package uk.co.transputersystems.occam.metadata; + +public class Channel extends NamedOperand { + int index; + public Channel(String name, int index , String typeName ) { + super(name, typeName); + this.index = index; + } + + public int getIndex(){ + return index; + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/ChannelAbbreviation.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/ChannelAbbreviation.java new file mode 100644 index 0000000..ab6ee1c --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/ChannelAbbreviation.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.metadata; + +public class ChannelAbbreviation extends Abbreviation { + public ChannelAbbreviation(Scope declaringScope, String name, String typeName, String hideName) { + super(declaringScope, name, typeName, hideName); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/DataType.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/DataType.java new file mode 100644 index 0000000..769d4de --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/DataType.java @@ -0,0 +1,19 @@ +package uk.co.transputersystems.occam.metadata; + +public abstract class DataType implements VerifiableData { + + protected String name; + + public DataType(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void verify(VerificationContext ctx) { + assert(name != null); + assert(!name.isEmpty()); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/Field.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/Field.java new file mode 100644 index 0000000..bdc1f78 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/Field.java @@ -0,0 +1,36 @@ +package uk.co.transputersystems.occam.metadata; + +public class Field implements VerifiableData { + private String name; + private String typeName; + private int index; + + public Field(String name, String typeName, int index) { + this.name = name; + this.typeName = typeName; + this.index = index; + } + + public String getName() { + return name; + } + + public String getTypeName() { + return typeName; + } + + public int getIndex() { + return index; + } + + public void verify(VerificationContext ctx) { + assert(name != null); + assert(!name.isEmpty()); + + assert(typeName != null); + assert(!typeName.isEmpty()); + assert (ctx.isDataTypeKnown(typeName)); + + assert(index > -1); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/FileInformation.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/FileInformation.java new file mode 100644 index 0000000..531a58c --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/FileInformation.java @@ -0,0 +1,68 @@ +package uk.co.transputersystems.occam.metadata; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +public class FileInformation extends Scope { + + private String filePath; + private String fileName; + + private List functions = new ArrayList<>(); + + public FileInformation(Scope parent, String filePath, String fileName) { + super(parent, -1, false); + + this.filePath = filePath; + this.fileName = fileName; + } + + public String getFilePath() { + return filePath; + } + + public String getFileName() { + return fileName; + } + + public List getFunctions() { + return new ArrayList<>(functions); + } + public void addFunction(Function function){ + functions.add(function); + } + public Function getFunction(String name) { + for (Function function : functions) { + if (function.getName().equals(name)) { + return function; + } + } + return null; + } + + @Override + public void verify(VerificationContext ctx) { + super.verify(ctx); + + assert (filePath != null); + assert (!filePath.isEmpty()); + + File f = new File(filePath); + assert (f.exists()); + assert (!f.isDirectory()); + + assert (fileName != null); + assert (!fileName.isEmpty()); + + assert (functions != null); + List usedNames = new ArrayList<>(); + for (Function function : functions) { + assert (function != null); + function.verify(ctx); + + assert (!usedNames.contains(function.getName())); + usedNames.add(function.getName()); + } + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/Function.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/Function.java new file mode 100644 index 0000000..d9ab5f0 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/Function.java @@ -0,0 +1,93 @@ +package uk.co.transputersystems.occam.metadata; + +import java.util.ArrayList; +import java.util.List; + +public class Function extends Scope { + + private String name; + private List returnTypes; + private List arguments; + + public Function(Scope parent, int scopeId, String name, List returnTypes, List arguments) { + super(parent, scopeId, true); + + this.name = name; + this.returnTypes = returnTypes; + this.arguments = arguments; + } + + public String getName() { + return name; + } + + public List getReturnTypes() { + return new ArrayList<>(returnTypes); + } + public void addReturnType(String typeName) { + returnTypes.add(typeName); + } + + public List getArguments() { + return new ArrayList<>(arguments); + } + public void addArgument(Argument argument) { + argument.setIndex(arguments.size()+1); + arguments.add(argument); + workspace.allocateArgument(argument); + } + public Argument getArgument(String name) { + for (Argument argument : arguments) { + if (argument.getName().equals(name)) { + return argument; + } + } + return null; + } + public Argument getArgument(Integer index) { + index = Math.abs(index); + for (Argument argument : arguments) { + if (argument.getIndex() == index) { + return argument; + } + } + return null; + } + + @Override + public NamedOperand searchForNamedOperand(String name) { + NamedOperand result = super.searchForNamedOperand(name); + if (result != null) { + return result; + } + + result = getArgument(name); + if (result != null) { + return result; + } + + return null; + } + + @Override + public void verify(VerificationContext ctx) { + super.verify(ctx); + + assert (name != null); + assert (!name.isEmpty()); + + assert (returnTypes != null); + for (String returnTypeName : returnTypes) { + assert (returnTypeName != null); + assert (!returnTypeName.isEmpty()); + assert (ctx.isDataTypeKnown(returnTypeName)); + } + + assert (arguments != null); + for (Argument argument : arguments) { + assert (argument != null); + argument.verify(ctx); + } + } +} + diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/LibraryInformation.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/LibraryInformation.java new file mode 100644 index 0000000..3979011 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/LibraryInformation.java @@ -0,0 +1,261 @@ +package uk.co.transputersystems.occam.metadata; + +import java.util.ArrayList; +import java.util.List; + +public class LibraryInformation implements VerifiableData { + + private String name; + private List dataTypes = new ArrayList<>(); + private List fileInfos = new ArrayList<>(); + private FileInformation currentFileInfo; + private Scope currentScope; + private int scopeIdGenerator = 0; + + /** + * Construct a LibraryInformation object. + * @param name The name of the library. + */ + public LibraryInformation(String name) { + this.name = name; + + addDataType(new PrimitiveDataType("BOOL", 1)); + addDataType(new PrimitiveDataType("BYTE", 1)); + addDataType(new PrimitiveDataType("INT", 4)); //TODO: This size should be configurable based on the target platform word size + addDataType(new PrimitiveDataType("INT16", 2)); + addDataType(new PrimitiveDataType("INT32", 4)); + + //TODO: Uncomment when support for INT64/REAL32/REAL64 is actually added + //addDataType(new PrimitiveDataType("INT64", 8)); + //addDataType(new PrimitiveDataType("REAL32", 4)); + //addDataType(new PrimitiveDataType("REAL64", 8)); + } + + /** + * @return The name of the library + */ + public String getName() { + return name; + } + + /** + * @return The list of data types declared in all files within the library. + * + * Declared data types are any declared Array, Named, Primitive or Record types. + */ + public List getDataTypes() { + return new ArrayList<>(dataTypes); + } + + /** + * Add a provided `DataType` to the list of data types. + */ + public void addDataType(DataType dataType){ + dataTypes.add(dataType); + } + + /** + * Retrieve a `DataType` from the list of data types by name. + * @return The first matching `DataType` + */ + public DataType getDataType(String name) { + for (DataType dataType : dataTypes) { + if (dataType.getName().equals(name)) { + return dataType; + } + } + return null; + } + + /** + * @return `FileInformation` objects representing the files contained in this library + */ + public List getFileInfos() { + return new ArrayList<>(fileInfos); + } + + public void addFileInfo(FileInformation info) { + fileInfos.add(info); + } + + /** + * Return the first `FileInformation` object which has a path matching the supplied path. + * @param filePath The file path to search for. Format is absolute file path and uses the Java standard format for the current platform. + * @return The `FileInformation` for the first matching file. + */ + public FileInformation getFileInfo(String filePath) { + for (FileInformation fileInfo : fileInfos) { + if (fileInfo.getFilePath().equals(filePath)) { + return fileInfo; + } + } + return null; + } + + public FileInformation getCurrentFileInfo() { + return currentFileInfo; + } + + public void startNewFile(String filePath, String fileName) { + FileInformation newInfo = new FileInformation(null, filePath, fileName); + fileInfos.add(newInfo); + currentFileInfo = newInfo; + currentScope = newInfo; + } + + public Scope getScopeById(int id) { + if (id == -1) { + return null; + } + + for (FileInformation file : fileInfos) { + Scope potentialResult = file.getScopeById(id); + if (potentialResult != null) { + return potentialResult; + } + } + + return null; + } + public Scope getCurrentScope() { + return currentScope; + } + public Scope pushNewScope() { + if (currentScope instanceof FileInformation) { + return currentScope; + } + return pushScope(new Scope(currentScope, scopeIdGenerator++, false)); + } + public Scope pushNewFunctionScope(String name) { + Function newFunction = new Function(currentScope, scopeIdGenerator++, name, new ArrayList<>(), new ArrayList<>()); + currentFileInfo.addFunction(newFunction); + newFunction.newWorkspace(true); + return pushScope(newFunction); + } + private Scope pushScope(Scope scope) { + currentScope.addChild(scope); + currentScope = scope; + return currentScope; + } + public void popScope() { + currentScope = currentScope.parent; + } + + public Function getFunction(String name) { + for (FileInformation fileInfo : fileInfos) { + Function potentialResult = fileInfo.getFunction(name); + if (potentialResult != null) { + return potentialResult; + } + } + return null; + } + + /** + * Search for the provided name in the current scope and its parent scopes until: + * + * * the name is found, in which case return the relevant `NamedOperand` + * * we have reached the final parent, in which case return null + * + * @param name An operand name to search for in the current scope + * @return A `NamedOperand` matching the provided name, or null + */ + public NamedOperand searchForNamedOperand(String name) { + return searchForNamedOperand(name, this.currentScope); + } + public static NamedOperand searchForNamedOperand(String name, Scope bottomScope) { + // Search for the name in the current scope. If it is not found, recursively search + // the parent scopes. When the name is found, return the relevant object + while (bottomScope != null) { + NamedOperand result = bottomScope.searchForNamedOperand(name); + if (result != null) { + return result; + } + bottomScope = bottomScope.parent; + } + + // If nothing is found, return null + return null; + } + + public NamedOperand searchForGlobalNamedOperand(String name) { + for (FileInformation fileInfo : fileInfos) { + NamedOperand result = searchForGlobalNamedOperand(name, fileInfo); + if (result != null) { + return result; + } + } + + // If nothing is found, return null + return null; + } + private NamedOperand searchForGlobalNamedOperand(String name, Scope scope) { + NamedOperand result = scope.searchForNamedOperand(name); + if (result != null) { + return result; + } + + for (Scope childScope : scope.children) { + result = searchForGlobalNamedOperand(name, childScope); + if (result != null) { + return result; + } + } + + return null; + } + + public boolean isGlobal(NamedOperand operand) { + //TODO: Should global variables be shared across files, like data types are? + // If so, this function should search all files + // In which case, we need to process global parts of files before the functions within them + return currentFileInfo.searchForNamedOperand(operand.getName()) == operand; + } + + public int getTypeSize(String typeName) throws Exception { + return getTypeSize(getDataType(typeName)); + } + public int getTypeSize(DataType type) throws Exception { + if (type instanceof PrimitiveDataType) { + return ((PrimitiveDataType) type).getSize(); + } else if (type instanceof NamedDataType) { + return getTypeSize(((NamedDataType) type).getUnderlyingTypeName()); + } else if (type instanceof ArrayDataType) { + int elementSize = getTypeSize(((ArrayDataType) type).getElementTypeName()); + int size = elementSize; + for (Integer dimension : ((ArrayDataType) type).getDimensions()) { + size *= dimension; + } + return size; + } else if (type instanceof RecordDataType) { + int size = 0; + for(Field field : ((RecordDataType) type).getFields()) { + size += getTypeSize(field.getTypeName()); + } + return size; + } else { + throw new Exception("Unknown data type descriptor type! " + type.getClass().getName()); + } + } + + public void verify(VerificationContext ctx) { + assert (name != null); + assert (!name.isEmpty()); + + for (DataType aType : dataTypes) { + assert (aType != null); + aType.verify(ctx); + } + + List usedPaths = new ArrayList<>(); + for (FileInformation fileInfo : fileInfos) { + assert (fileInfo != null); + fileInfo.verify(ctx); + + assert (!usedPaths.contains(fileInfo.getFilePath())); + usedPaths.add(fileInfo.getFilePath()); + } + + assert (currentScope == null); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/LocationAbbreviation.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/LocationAbbreviation.java new file mode 100644 index 0000000..81af8f0 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/LocationAbbreviation.java @@ -0,0 +1,26 @@ +package uk.co.transputersystems.occam.metadata; + +/** + * Created by Ed on 09/04/2016. + */ +public class LocationAbbreviation extends Abbreviation { + + private String locationExpression; + + public LocationAbbreviation(Scope declaringScope, String name, String typeName, String locationExpression) { + super(declaringScope, name, typeName, "[LOCATION]"); + + this.locationExpression = locationExpression; + } + + public String getLocationExpression() { + return locationExpression; + } + + @Override + public void verify(VerificationContext ctx) { + super.verify(ctx); + + //TODO: Location abbreviation verification + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/NamedDataType.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/NamedDataType.java new file mode 100644 index 0000000..56183aa --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/NamedDataType.java @@ -0,0 +1,25 @@ +package uk.co.transputersystems.occam.metadata; + +public class NamedDataType extends DataType { + + private String underlyingTypeName; + + public NamedDataType(String name, String underlyingTypeName) { + super(name); + + this.underlyingTypeName = underlyingTypeName; + } + + public String getUnderlyingTypeName() { + return underlyingTypeName; + } + + @Override + public void verify(VerificationContext ctx) { + super.verify(ctx); + + assert (underlyingTypeName != null); + assert (!underlyingTypeName.isEmpty()); + assert (ctx.isDataTypeKnown(underlyingTypeName)); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/NamedOperand.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/NamedOperand.java new file mode 100644 index 0000000..e811880 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/NamedOperand.java @@ -0,0 +1,47 @@ +package uk.co.transputersystems.occam.metadata; + +public abstract class NamedOperand implements VerifiableData { + protected String name; + protected String typeName; + protected boolean constant; + protected T constantValue; + + public NamedOperand(String name, String typeName) { + this(name, typeName, false, null); + } + public NamedOperand(String name, String typeName, boolean constant, T constantValue) { + this.name = name; + this.typeName = typeName; + this.constant = constant; + this.constantValue = constantValue; + } + + public String getName() { + return name; + } + + public String getTypeName() { + return typeName; + } + + public boolean isConstant() { + return constant; + } + + public T getConstantValue() { + return constantValue; + } + + public void verify(VerificationContext ctx) { + assert(name != null); + assert(!name.isEmpty()); + + assert (typeName != null); + assert (!typeName.isEmpty()); + assert (ctx.isDataTypeKnown(typeName)); + + if (constant) { + assert (constantValue != null); + } + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/Port.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/Port.java new file mode 100644 index 0000000..7093b57 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/Port.java @@ -0,0 +1,13 @@ +package uk.co.transputersystems.occam.metadata; + +public class Port extends NamedOperand { + public int index; + public Port(String name, int index, String typeName) { + super(name, typeName); + } + + + public int getIndex() { + return index; + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/PortAbbreviation.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/PortAbbreviation.java new file mode 100644 index 0000000..96bda74 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/PortAbbreviation.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.metadata; + +public class PortAbbreviation extends Abbreviation { + public PortAbbreviation(Scope declaringScope, String name, String typeName, String hideName) { + super(declaringScope, name, typeName, hideName); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/PrimitiveDataType.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/PrimitiveDataType.java new file mode 100644 index 0000000..39286f6 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/PrimitiveDataType.java @@ -0,0 +1,23 @@ +package uk.co.transputersystems.occam.metadata; + +public class PrimitiveDataType extends DataType { + + private int size; + + public PrimitiveDataType(String name, int size) { + super(name); + + this.size = size; + } + + public int getSize() { + return size; + } + + @Override + public void verify(VerificationContext ctx) { + super.verify(ctx); + + assert (size >= 0); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/RecordDataType.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/RecordDataType.java new file mode 100644 index 0000000..86d0017 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/RecordDataType.java @@ -0,0 +1,37 @@ +package uk.co.transputersystems.occam.metadata; + +import java.util.ArrayList; +import java.util.List; + +public class RecordDataType extends DataType { + private List fields = new ArrayList<>(); + + public RecordDataType(String name) { + super(name); + } + + public List getFields() { + return new ArrayList<>(fields); + } + public void addField(String name, String typeName) { + fields.add(new Field(name, typeName, fields.size())); + } + public Field getField(String name) { + for (Field field : fields) { + if (field.getName().equals(name)) { + return field; + } + } + return null; + } + + @Override + public void verify(VerificationContext ctx) { + super.verify(ctx); + + for (Field field : fields) { + assert (field != null); + field.verify(ctx); + } + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/Scope.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/Scope.java new file mode 100644 index 0000000..caba271 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/Scope.java @@ -0,0 +1,474 @@ +package uk.co.transputersystems.occam.metadata; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + +/** + * A scope may also be known as an 'environment' or 'context'. It contains metadata about the context in which a particular + * section of an Occam program should be executed. Each instance of `Scope` represents a distinct scope in an Occam + * program, and contains various pieces of information: + * + * * the channels, variables, ports and timers declared in that scope + * * the abbreviations declared in that scope for named operands that already exist in the scope (or its ancestors) + * * a label stack - TODO: currently unused + * * a construction stack, which is used to pass around temporary metadata needed while the IR tree is being built. + * This exists to overcome a limitation in ANTLR4's visitor-generation system: you cannot pass extra arguments into the `visit[*]` methods. + * * a workspace ID, which links the scope to a single workspace. + * * the parent scope - whose contents are still accessible in the current scope unless their names are explicitly shadowed + * * the child scopes - for example, each process in a `PAR` block would have its own scope + */ +public class Scope implements VerifiableData { + + protected transient Scope parent; + protected List children = new ArrayList<>(); + + protected List channels = new ArrayList<>(); + protected List variables = new ArrayList<>(); + protected List ports = new ArrayList<>(); + protected List timers = new ArrayList<>(); + protected List abbreviations = new ArrayList<>(); + + protected Stack labelStack = new Stack<>(); + protected Stack constructionStack = new Stack<>(); + + protected int scopeId; + protected Workspace workspace; + + /** + * Construct a new `Scope`. The workspace ID is set, by default, to the parent's workspace ID. + * @param parent The parent of the new `Scope` + */ + public Scope(Scope parent, int scopeId, boolean function) { + this.parent = parent; + if (parent != null) { + setWorkspace(parent.getWorkspace()); + } else { + this.workspace = new Workspace(null, function); + } + + this.scopeId = scopeId; + } + + public Scope getParent() { + return parent; + } + + public Workspace getWorkspace() { + return workspace; + } + protected void setWorkspace(Workspace value) { + // Update child scopes which are part of this scope's workspace, because they will be affected too. + for (Scope childScope : children) { + if (childScope.getWorkspace().equals(this.workspace)) { + childScope.setWorkspace(value); + } + } + + // Update this scope + this.workspace = value; + } + + public int getScopeId() { + return scopeId; + } + protected Scope getScopeById(int id) { + if (scopeId == id) { + return this; + } + + for (Scope child : children) { + Scope potentialResult = child.getScopeById(id); + if (potentialResult != null) { + return potentialResult; + } + } + + return null; + } + + /** + * Set the workspace ID of this `Scope` to that of a newly-generated workspace + * @return The new workspace ID + */ + public Workspace newWorkspace(boolean functionSpace) { + setWorkspace(new Workspace(insideFunction() ? parent.getWorkspace() : null, functionSpace)); + return workspace; + } + public boolean insideFunction() { + if (parent != null) { + if (parent instanceof Function) { + return true; + } else { + return parent.insideFunction(); + } + } + return false; + } + + public List getChildren() { + return new ArrayList<>(children); + } + public void addChild(Scope scope) { + children.add(scope); + } + + public List getVariables() { + return new ArrayList<>(variables); + } + public List getVariablesInWorkspaceAndBelow() { + List result = new ArrayList<>(variables); + + for (Scope child : children) { + if (!(child instanceof Function)) { + result.addAll(child.getVariablesInWorkspaceAndBelow()); + } + } + + return result; + } + public Variable addVariable(String name, String typeName) { + Variable variable = new Variable(name, getLocalVariableCount(this)+1, typeName); + variables.add(variable); + workspace.allocateVariable(variable); + return variable; + } + public Variable getVariable(String name) { + for (Variable variable : variables) { + if (variable.getName().equals(name)) { + return variable; + } + } + return null; + } + public Variable getVariable(int index) { + return getVariable(index, this); + } + private Variable getVariable(int index, Scope caller) { + for (Variable variable : variables) { + if (variable.getIndex() == index) { + return variable; + } + } + + for (Scope child : children) { + if (!child.equals(caller) && child.workspace.equals(workspace)) { + Variable potentialResult = child.getVariable(index, this); + if (potentialResult != null) { + return potentialResult; + } + } + } + + if (!caller.equals(parent) && !(this instanceof Function)) { + return parent.getVariable(index, this); + } + + return null; + } + public Scope findScopeOfVariable(Variable variable) { + if (variables.contains(variable)) { + return this; + } + + for (Scope child : children) { + Scope potentialResult = child.findScopeOfVariable(variable); + if (potentialResult != null) { + return potentialResult; + } + } + + return null; + } + + public List getChannels() { + return new ArrayList<>(channels); + } + public void addChannel(String name, String typeName) { + channels.add(new Channel(name, getLocalChannelCount(this)+1, typeName)); + } + public Channel getChannel(String name) { + for (Channel channel : channels) { + if (channel.getName().equals(name)) { + return channel; + } + } + return null; + } + + public List getPorts() { + return new ArrayList<>(ports); + } + public void addPort(String name, String typeName) { + ports.add(new Port(name, getLocalPortCount(this)+1,typeName)); + } + public Port getPort(String name) { + for (Port port : ports) { + if (port.getName().equals(name)) { + return port; + } + } + return null; + } + + public List getTimers() { + return new ArrayList<>(timers); + } + public void addTimer(String name) { + timers.add(new Timer(name)); + } + public Timer getTimer(String name) { + for (Timer timer : timers) { + if (timer.getName().equals(name)) { + return timer; + } + } + return null; + } + + public List getAbbreviations() { + return new ArrayList<>(abbreviations); + } + public void addAbbreviation(Abbreviation abbreviation) { + abbreviation.setDeclaringScope(this); + abbreviations.add(0,abbreviation); + } + public Abbreviation getAbbreviation(String name) { + for (Abbreviation Abbreviation : abbreviations) { + if (Abbreviation.getName().equals(name)) { + return Abbreviation; + } + } + return null; + } + + /** + * Given the name of an operand, attempt to find it in the scope. Search is performed in the order: + * + * * variables + * * abbreviations + * * channels + * * ports + * * timers + * + * Note that the order of the search should **not** make any difference to the result, as names cannot clash in the + * same scope. The ordering here is simply designed to look for the most-likely-to-exist types first. + * + * @param name The name of the operand to attempt to retrieve + * @return If a matching operand is found, the operand, otherwise `null` + */ + public NamedOperand searchForNamedOperand(String name) { + NamedOperand result = getVariable(name); + if (result != null) { + return result; + } + + result = getAbbreviation(name); + if (result != null) { + return result; + } + + result = getChannel(name); + if (result != null) { + return result; + } + + result = getPort(name); + if (result != null) { + return result; + } + + result = getTimer(name); + if (result != null) { + return result; + } + + return null; + } + + public Stack getLabelStack() { + return labelStack; + } + public void pushLabel(String label) { + labelStack.push(label); + } + public String popLabel() { + return labelStack.pop(); + } + public String peekLabel() { + return labelStack.peek(); + } + + public Stack getConstructionStack() { + return constructionStack; + } + public void pushConstruction(Object construction) { + constructionStack.push(construction); + } + public Object popConstruction() { + return constructionStack.pop(); + } + public Object peekConstruction() { + return constructionStack.peek(); + } + + public int getLocalVariableCount(Scope caller) { + int result = variables.size(); + if (parent != null && !parent.equals(caller) && !(this instanceof Function)) { + result += parent.getLocalVariableCount(this); + } + for (Scope childScope : children) { + if (childScope.getWorkspace().equals(workspace)) { + if (!childScope.equals(caller)) { + result += childScope.getLocalVariableCount(this); + } + } + } + return result; + } + + public int getLocalChannelCount(Scope caller){ + int result = channels.size(); + if (parent != null && !parent.equals(caller) && !(this instanceof Function)) { + result += parent.getLocalChannelCount(this); + } + for (Scope childScope : children) { + if (childScope.getWorkspace().equals(workspace)) { + if (!childScope.equals(caller)) { + result += childScope.getLocalChannelCount(this); + } + } + } + return result; + + } + + public int getLocalPortCount(Scope caller){ + int result = channels.size(); + if (parent != null && !parent.equals(caller) && !(this instanceof Function)) { + result += parent.getLocalPortCount(this); + } + for (Scope childScope : children) { + if (childScope.getWorkspace().equals(workspace)) { + if (!childScope.equals(caller)) { + result += childScope.getLocalPortCount(this); + } + } + } + return result; + } + + public Scope getScopeByWorkspaceId(int id) { + if (workspace.getId() == id) { + return this; + } + + for (Scope child : children) { + Scope potentialResult = child.getScopeByWorkspaceId(id); + if (potentialResult != null) { + return potentialResult; + } + } + + return null; + } + public Workspace getWorkspaceById(int id) { + if (workspace.getId() == id) { + return workspace; + } + + for (Scope child : children) { + Workspace potentialResult = child.getWorkspaceById(id); + if (potentialResult != null) { + return potentialResult; + } + } + + return null; + } + public void updateAllWSSizesAndOffsets() { + updateAllWSSizesAndOffsets(null); + } + protected void updateAllWSSizesAndOffsets(Scope caller) { + if (caller == null || !caller.getWorkspace().equals(workspace)) { + workspace.updateSizeAndOffsets(); + } + + if (parent != null) { + if (caller == null || !parent.equals(caller)) { + parent.updateAllWSSizesAndOffsets(this); + } + } + + for (Scope child : children) { + if (caller == null || !child.equals(caller)) { + child.updateAllWSSizesAndOffsets(this); + } + } + } + + public void verify(VerificationContext ctx) { + assert (parent != this); + + assert (children != null); + for (Scope childScope : children) { + assert (childScope != null); + childScope.verify(ctx); + } + + List usedNames = new ArrayList<>(); + + assert (channels != null); + for (Channel channel : channels) { + assert (channel != null); + channel.verify(ctx); + + assert (!usedNames.contains(channel.getName())); + usedNames.add(channel.getName()); + } + + assert (variables != null); + for (Variable variable : variables) { + assert (variable != null); + variable.verify(ctx); + + assert (!usedNames.contains(variable.getName())); + usedNames.add(variable.getName()); + } + + assert (ports != null); + for (Port port : ports) { + assert (port != null); + port.verify(ctx); + + assert (!usedNames.contains(port.getName())); + usedNames.add(port.getName()); + } + + assert (timers != null); + for (Timer timer : timers) { + assert (timer != null); + timer.verify(ctx); + + assert (!usedNames.contains(timer.getName())); + usedNames.add(timer.getName()); + } + + assert (abbreviations != null); + for (Abbreviation abbreviation : abbreviations) { + assert (abbreviation != null); + abbreviation.verify(ctx); + + assert (!usedNames.contains(abbreviation.getName())); + usedNames.add(abbreviation.getName()); + } + + assert (labelStack != null); + assert (labelStack.isEmpty()); + + assert (constructionStack != null); + assert (constructionStack.isEmpty()); + + assert (workspace != null); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/Timer.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/Timer.java new file mode 100644 index 0000000..1f1dc0a --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/Timer.java @@ -0,0 +1,15 @@ +package uk.co.transputersystems.occam.metadata; + +public class Timer extends NamedOperand { + + public Timer(String name) { + super(name, "{TIMER}"); + } + + @Override + public void verify(VerificationContext ctx) { + super.verify(ctx); + + assert (typeName == "{TIMER}"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/TimerAbbreviation.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/TimerAbbreviation.java new file mode 100644 index 0000000..8b7b971 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/TimerAbbreviation.java @@ -0,0 +1,14 @@ +package uk.co.transputersystems.occam.metadata; + +public class TimerAbbreviation extends Abbreviation { + public TimerAbbreviation(Scope declaringScope, String name, String hideName) { + super(declaringScope, name, "{TIMER}", hideName); + } + + @Override + public void verify(VerificationContext ctx) { + super.verify(ctx); + + assert (typeName == "{TIMER}"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/ValueAbbreviation.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/ValueAbbreviation.java new file mode 100644 index 0000000..dbd3211 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/ValueAbbreviation.java @@ -0,0 +1,16 @@ +package uk.co.transputersystems.occam.metadata; + +public class ValueAbbreviation extends Abbreviation { + + public ValueAbbreviation(Scope declaringScope, String name, String typeName, T constantValue) { + super(declaringScope, name, typeName, null, true, constantValue); + } + + @Override + public void verify(VerificationContext ctx) { + super.verify(ctx); + + assert (hiddenName == null); + assert (constant == true); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/Variable.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/Variable.java new file mode 100644 index 0000000..1a91ce6 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/Variable.java @@ -0,0 +1,22 @@ +package uk.co.transputersystems.occam.metadata; + +public class Variable extends NamedOperand { + private int index; + + public Variable(String name, int index, String typeName) { + super(name, typeName); + + this.index = index; + } + + public int getIndex() { + return index; + } + + @Override + public void verify(VerificationContext ctx) { + super.verify(ctx); + + assert (index > -1); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/VariableAbbreviation.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/VariableAbbreviation.java new file mode 100644 index 0000000..cb58471 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/VariableAbbreviation.java @@ -0,0 +1,9 @@ +package uk.co.transputersystems.occam.metadata; + +public class VariableAbbreviation extends Abbreviation { + + public VariableAbbreviation(Scope declaringScope, String name, String typeName, String hideName) { + super(declaringScope, name, typeName, hideName); + } + +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/VerifiableData.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/VerifiableData.java new file mode 100644 index 0000000..029ada6 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/VerifiableData.java @@ -0,0 +1,8 @@ +package uk.co.transputersystems.occam.metadata; + +/** + * Created by Edward on 25/02/2016. + */ +public interface VerifiableData { + void verify(VerificationContext ctx); +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/VerificationContext.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/VerificationContext.java new file mode 100644 index 0000000..011e7f7 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/VerificationContext.java @@ -0,0 +1,45 @@ +package uk.co.transputersystems.occam.metadata; + +import uk.co.transputersystems.occam.il.ILBlock; +import uk.co.transputersystems.occam.il.ILOp; + +import java.util.List; +import java.util.UUID; + +/** + * Created by Edward on 26/02/2016. + */ +public class VerificationContext { + + private List libraries; + + public VerificationContext(List libraries) { + this.libraries = libraries; + } + + public List getLibraries() { + return libraries; + } + + public boolean isDataTypeKnown(String typeName) { + for (LibraryInformation library : libraries) { + if (library.getDataType(typeName) != null) { + return true; + } + } + return false; + } + + public void verify(List>> ilBlocks) { + assert (libraries != null); + assert (libraries.size() > 0); + + for (LibraryInformation library : libraries) { + library.verify(this); + } + + for (ILBlock> ilBlock : ilBlocks) { + ilBlock.verify(this); + } + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/Workspace.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/Workspace.java new file mode 100644 index 0000000..aa3788b --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/Workspace.java @@ -0,0 +1,242 @@ +package uk.co.transputersystems.occam.metadata; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by Ed on 31/03/2016. + */ +public class Workspace { + + private List locations = new ArrayList<>(); + + private int size = 0; + private int numTemporaries = 0; + private int maxNumTemporaries = 0; + private int expansionAreaSize; + private int maxExpansionAreaSize; + private boolean functionSpace; + + private int idGenerator = 0; + + private int id; + private transient Workspace parent; + + public Workspace(Workspace parent, boolean functionSpace) { + this.parent = parent; + this.expansionAreaSize = 5; + this.maxExpansionAreaSize = this.expansionAreaSize; + this.functionSpace = functionSpace; + + if (parent != null) { + this.id = parent.generateWorkspaceId(); + + allocateVariable(new Variable("[PARENT WPTR]", Integer.MIN_VALUE, "POINTER")); + } else { + this.id = idGenerator++; + } + } + + public int getId() { + return id; + } + public int getInitSize() { + int result = size; + + if (functionSpace) { + int args = 0; + for (WorkspaceLocation location : locations) { + if (location.itemIndex < 0) { + args++; + } + } + args = Math.max(args, 3); + result -= args; + + result--; // Return Ptr + } + + return result; + } + public int getSize() { + return size; + } + public int getFullSize() { + return size + maxExpansionAreaSize; + } + public int getExpansionAreaSize() { + return expansionAreaSize; + } + public int getMaxTempsSize() { + return maxNumTemporaries; + } + public Workspace getParent() { + return parent; + } + + public void allocateTemporary() { + locations.add(new WorkspaceLocation(0)); + numTemporaries++; + if (numTemporaries > maxNumTemporaries) { + maxNumTemporaries = numTemporaries; + } + } + + public void allocateVariable(Variable variable) { + //TODO: Handle variables > one word in size + //TODO: Handle the word size using some form of config file + locations.add(new WorkspaceLocation(0, variable.getIndex())); + } + + public void allocateArgument(Argument argument) { + //TODO: Handle arguments > one word in size + //TODO: Handle the word size using some form of config file + locations.add(new WorkspaceLocation(0, -argument.getIndex())); + } + + public void removeTemporaryFromWorkspace() { + for (int i = 0; i < locations.size(); i++) { + if (locations.get(i).itemIndex == Integer.MAX_VALUE) { + locations.remove(i); + break; + } + } + numTemporaries--; + if (numTemporaries < 0) { + throw new IndexOutOfBoundsException("Cannot remove more temporaries than were added!"); + } + } + + public void updateSizeAndOffsets() { + // Order by item index (descending) + locations.sort((WorkspaceLocation wsl1, WorkspaceLocation wsl2) -> Integer.compare(wsl2.itemIndex, wsl1.itemIndex)); + + // Reserve WPtr+0 + size = 1; + + // Add space for temporaries + size += maxNumTemporaries; + + int lastItemIndex = Integer.MAX_VALUE; + for (WorkspaceLocation wsl : locations) { + + // Ignore temporaries + if (wsl.itemIndex != Integer.MAX_VALUE) { + + // Gone from above zero to below zero + if (wsl.itemIndex < 0 && lastItemIndex >= 0) { + // Hit args or parent WS pointer + break; + } + + //TODO: Deal with locals/args which are bigger than one word + wsl.offset = size++; + } + + lastItemIndex = wsl.itemIndex; + } + + if (functionSpace) { + // Add one to offset for return pointer + size++; + + // Order by item index (ascending) + locations.sort((WorkspaceLocation wsl1, WorkspaceLocation wsl2) -> Integer.compare(wsl1.itemIndex, wsl2.itemIndex)); + + int numArgs = 0; + WorkspaceLocation parentWSPtrWSL = null; + for (WorkspaceLocation wsl : locations) { + if (wsl.itemIndex >= 0) { + break; + } + + if (wsl.itemIndex == Integer.MIN_VALUE) { + parentWSPtrWSL = wsl; + } + + numArgs++; + } + + for (int i = numArgs; i < 3; i++) { + size++; + } + + if (parentWSPtrWSL != null) { + parentWSPtrWSL.offset = size++; + } + + size += numArgs - (parentWSPtrWSL != null ? 1 : 0); + + int offset = size - 1; + for (WorkspaceLocation wsl : locations) { + if (wsl.itemIndex >= 0) { + break; + } + + if (wsl != parentWSPtrWSL) { + wsl.offset = offset--; + } + } + } else { + for (WorkspaceLocation wsl : locations) { + if (wsl.itemIndex >= 0) { + break; + } + + if (wsl.itemIndex == Integer.MIN_VALUE) { + wsl.offset = size++; + } + } + } + } + + public int getLastTemporaryOffset(int distance) { + return (maxNumTemporaries - numTemporaries + 1 + distance); // Add one for WPtr+0 then add one to get from count value to index value + } + public int getNextTemporaryOffset() { + return (maxNumTemporaries - (numTemporaries+1)) + 1; // Add one for reserved location: WPtr+0 + } + public int getOffset(int itemIndex) { + for (WorkspaceLocation wsl : locations) { + if (wsl.itemIndex == itemIndex) { + return wsl.offset; + } + } + return -1; + } + + public Workspace getOwner(int itemIndex) { + for (WorkspaceLocation wsl : locations) { + if (wsl.itemIndex == itemIndex) { + return this; + } + } + + if (parent != null) { + return parent.getOwner(itemIndex); + } + + return null; + } + + private int generateWorkspaceId() { + if (parent != null) { + return parent.generateWorkspaceId(); + } else { + return idGenerator++; + } + } + + public void growExpansionArea(int amount) { + expansionAreaSize += amount; + if (expansionAreaSize > maxExpansionAreaSize) { + maxExpansionAreaSize = expansionAreaSize; + } + } + public void shrinkExpansionArea(int amount) { + if (amount > expansionAreaSize) { + throw new IllegalArgumentException("Shrink amount cannot be larger than expansion area size!"); + } + expansionAreaSize -= amount; + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/WorkspaceLocation.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/WorkspaceLocation.java new file mode 100644 index 0000000..ab606ce --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/metadata/WorkspaceLocation.java @@ -0,0 +1,25 @@ +package uk.co.transputersystems.occam.metadata; + +/** + * Created by Ed on 31/03/2016. + */ +public class WorkspaceLocation { + public int offset; + /** Special meanings: + * Integer.MIN_VALUE = Parent workspace pointer + * Integer.MAX_VALUE = Temporary value + * Otherwise: + * -ve = Argument + * +ve = Variable + */ + public int itemIndex; + + public WorkspaceLocation(int offset) { + this.offset = offset; + this.itemIndex = Integer.MAX_VALUE; + } + public WorkspaceLocation(int offset, int itemIndex) { + this.offset = offset; + this.itemIndex = itemIndex; + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/ASMBlock.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/ASMBlock.java new file mode 100644 index 0000000..c433ab8 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/ASMBlock.java @@ -0,0 +1,27 @@ +package uk.co.transputersystems.occam.open_transputer; + +import uk.co.transputersystems.occam.open_transputer.assembly.ASMOp; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by Ed on 31/03/2016. + */ +public class ASMBlock { + private List ops = new ArrayList<>(); + + public ASMBlock() { + + } + + public List getOps() { + return ops; + } + public void addOp(ASMOp op) { + ops.add(op); + } + public void addOps(List opsToAdd) { + ops.addAll(opsToAdd); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/ASMGenerator.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/ASMGenerator.java new file mode 100644 index 0000000..834c3bc --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/ASMGenerator.java @@ -0,0 +1,1957 @@ +package uk.co.transputersystems.occam.open_transputer; + +import uk.co.transputersystems.occam.ILOpFormatter; +import uk.co.transputersystems.occam.il.Add; +import uk.co.transputersystems.occam.il.Call; +import uk.co.transputersystems.occam.metadata.Function; +import uk.co.transputersystems.occam.il.*; +import uk.co.transputersystems.occam.open_transputer.assembly.*; +import uk.co.transputersystems.occam.open_transputer.assembly.Label; + +import java.io.InvalidObjectException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class ASMGenerator { + + public List generateASM(List>> ilBlocks, ASMGeneratorContext> context, boolean suppressErrors) throws Exception { + + DependencyTree dependencyTree = new DependencyTree<>(ilBlocks); + ilBlocks = dependencyTree.flatten(); + + List result = new ArrayList<>(); + + /** + * Preprocessing means going through all the IL ops, performing all the relevant stack tracking stuff + * but not actually producing any ASM ops. + * + * Processing means going through all the IL ops and actually creating the relevant ASM ops. + * + * Preprocessing is required for calculating the maximum workspace size and thus at what offsets + * things which overflow from the ABC register stack will go into. Also, what offsets variables + * and arguments will be at and how big the workspace adjustments have to be. + */ + + // Preprocess all blocks + for (ILBlock> block : ilBlocks) { + context.setCurrentILBlock(block); + context.setCurrentASMBlock(null); + + for (ILOp ilOp : block.getAll()) { + try { + process(ilOp, context, true); + + context.getCurrentFunction().updateAllWSSizesAndOffsets(); + } catch (InvalidObjectException e) { + System.err.println(e.toString()); + System.err.flush(); + + if (!suppressErrors) { + throw e; + } + } catch (Exception e) { + System.err.println(e.toString()); + System.err.flush(); + + if (!suppressErrors) { + throw e; + } + } + } + } + + // Process all blocks + for (ILBlock> block : ilBlocks) { + ASMBlock asmBlock = new ASMBlock(); + + context.setCurrentILBlock(block); + context.setCurrentASMBlock(asmBlock); + + for (ILOp ilOp : block.getAll()) { + try { + process(ilOp, context, false); + } catch (InvalidObjectException e) { + System.err.println(e.toString()); + System.err.flush(); + asmBlock.addOp(new Label("ERROR! Couldn't process: " + ILOpFormatter.formatOp(ilOp, context.getCurrentILBlock()))); + + if (!suppressErrors) { + throw e; + } + } catch (Exception e) { + System.err.println(e.toString()); + System.err.flush(); + asmBlock.addOp(new Label("ERROR! Couldn't process: " + ILOpFormatter.formatOp(ilOp, context.getCurrentILBlock()))); + + if (!suppressErrors) { + throw e; + } + } + } + + result.add(asmBlock); + } + + return result; + } + + private void process(ILOp ilOp, ASMGeneratorContext context, boolean preProcess) throws Exception { + + // Pre-op processing that occurs for every op + context.checkForWorkspaceTransition(ilOp); + context.updateCurrentStackBranch(ilOp.getId()); + + boolean prefixWithJump = false; + if (ilOp.getRequiresLabel()) { + if (ilOp.getRequiresPopAfterLabel()) { + if (context.getEvaluationStackSize() == 0) { + prefixWithJump = true; + } else { + context.popFromEvaluationStack(); + } + } + } + + // Preprocess or process the IL op + + // Holds the result of processing. Should remain null for preprocessing + List asmOps = null; + if (ilOp instanceof Add) { + asmOps = processAdd((Add) ilOp, context, preProcess); + } else if (ilOp instanceof After) { + asmOps = processAfter((After) ilOp, context, preProcess); + } else if (ilOp instanceof BitwiseAnd) { + asmOps = processBitwiseAnd((BitwiseAnd) ilOp, context, preProcess); + } else if (ilOp instanceof BitwiseNot) { + asmOps = processBitwiseNot((BitwiseNot) ilOp, context, preProcess); + } else if (ilOp instanceof BitwiseOr) { + asmOps = processBitwiseOr((BitwiseOr) ilOp, context, preProcess); + } else if (ilOp instanceof BitwiseXor) { + asmOps = processBitwiseXor((BitwiseXor) ilOp, context, preProcess); + } else if (ilOp instanceof BooleanAnd) { + asmOps = processBooleanAnd((BooleanAnd) ilOp, context, preProcess); + } else if (ilOp instanceof BooleanNot) { + asmOps = processBooleanNot((BooleanNot) ilOp, context, preProcess); + } else if (ilOp instanceof BooleanOr) { + asmOps = processBooleanOr((BooleanOr) ilOp, context, preProcess); + } else if (ilOp instanceof Branch) { + asmOps = processBranch((Branch) ilOp, context, preProcess); + } else if (ilOp instanceof BranchEqZero) { + asmOps = processBranchEqZero((BranchEqZero) ilOp, context, preProcess); + } else if (ilOp instanceof BranchIfFalse) { + asmOps = processBranchIfFalse((BranchIfFalse) ilOp, context, preProcess); + } else if (ilOp instanceof BranchIfTrue) { + asmOps = processBranchIfTrue((BranchIfTrue) ilOp, context, preProcess); + } else if (ilOp instanceof BranchNotEqZero) { + asmOps = processBranchNotEqZero((BranchNotEqZero) ilOp, context, preProcess); + } else if (ilOp instanceof Call) { + asmOps = processCall((Call) ilOp, context, preProcess); + } else if (ilOp instanceof CompareEqual) { + asmOps = processCompareEqual((CompareEqual) ilOp, context, preProcess); + } else if (ilOp instanceof CompareGreaterThan) { + asmOps = processCompareGreaterThan((CompareGreaterThan) ilOp, context, preProcess); + } else if (ilOp instanceof CompareGreaterThanOrEqual) { + asmOps = processCompareGreaterThanOrEqual((CompareGreaterThanOrEqual) ilOp, context, preProcess); + } else if (ilOp instanceof CompareLessThan) { + asmOps = processCompareLessThan((CompareLessThan) ilOp, context, preProcess); + } else if (ilOp instanceof CompareLessThanOrEqual) { + asmOps = processCompareLessThanOrEqual((CompareLessThanOrEqual) ilOp, context, preProcess); + } else if (ilOp instanceof CompareNotEqual) { + asmOps = processCompareNotEqual((CompareNotEqual) ilOp, context, preProcess); + } else if (ilOp instanceof DelayedTimerInput) { + asmOps = processDelayedTimerInput((DelayedTimerInput) ilOp, context, preProcess); + } else if (ilOp instanceof DisableChannel) { + asmOps = processDisableChannel((DisableChannel) ilOp, context, preProcess); + } else if (ilOp instanceof DisablePort) { + asmOps = processDisablePort((DisablePort) ilOp, context, preProcess); + } else if (ilOp instanceof DisableSkip) { + asmOps = processDisableSkip((DisableSkip) ilOp, context, preProcess); + } else if (ilOp instanceof DisableTimer) { + asmOps = processDisableTimer((DisableTimer) ilOp, context, preProcess); + } else if (ilOp instanceof Divide) { + asmOps = processDivide((Divide) ilOp, context, preProcess); + } else if (ilOp instanceof Duplicate) { + asmOps = processDuplicate((Duplicate) ilOp, context, preProcess); + } else if (ilOp instanceof EnableChannel) { + asmOps = processEnableChannel((EnableChannel) ilOp, context, preProcess); + } else if (ilOp instanceof EnablePort) { + asmOps = processEnablePort((EnablePort) ilOp, context, preProcess); + } else if (ilOp instanceof EnableSkip) { + asmOps = processEnableSkip((EnableSkip) ilOp, context, preProcess); + } else if (ilOp instanceof EnableTimer) { + asmOps = processEnableTimer((EnableTimer) ilOp, context, preProcess); + } else if (ilOp instanceof EndAlt) { + asmOps = processEndAlt((EndAlt) ilOp, context, preProcess); + } else if (ilOp instanceof EndProcess) { + asmOps = processEndProcess((EndProcess) ilOp, context, preProcess); + } else if (ilOp instanceof InitAlt) { + asmOps = processInitAlt((InitAlt) ilOp, context, preProcess); + /*} else if (ilOp instanceof InitChannel) { + asmOps = processInitChannel((InitChannel) ilOp, context, preProcess);*/ + } else if (ilOp instanceof InitProcesses) { + asmOps = processInitProcesses((InitProcesses) ilOp, context, preProcess); + } else if (ilOp instanceof uk.co.transputersystems.occam.il.Label) { + asmOps = processLabel((uk.co.transputersystems.occam.il.Label) ilOp, context, preProcess); + } else if (ilOp instanceof LeftShift) { + asmOps = processLeftShift((LeftShift) ilOp, context, preProcess); + } else if (ilOp instanceof LoadArgument) { + asmOps = processLoadArgument((LoadArgument) ilOp, context, preProcess); + /*} else if (ilOp instanceof LoadChannelRef) { + asmOps = processLoadChannelRef((LoadChannelRef) ilOp, context, preProcess);*/ + } else if (ilOp instanceof LoadConstant) { + asmOps = processLoadConstant((LoadConstant) ilOp, context, preProcess); + } else if (ilOp instanceof LoadGlobal) { + asmOps = processLoadGlobal((LoadGlobal) ilOp, context, preProcess); + } else if (ilOp instanceof LoadLocal) { + asmOps = processLoadLocal((LoadLocal) ilOp, context, preProcess); + /*} else if (ilOp instanceof LoadPortRef) { + asmOps = processLoadPortRef((LoadPortRef) ilOp, context, preProcess);*/ + } else if (ilOp instanceof MethodEnd) { + asmOps = processMethodEnd((MethodEnd) ilOp, context, preProcess); + } else if (ilOp instanceof MethodStart) { + asmOps = processMethodStart((MethodStart) ilOp, context, preProcess); + } else if (ilOp instanceof Modulo) { + asmOps = processModulo((Modulo) ilOp, context, preProcess); + }else if (ilOp instanceof MostPositive) { + asmOps = processMostPositive((MostPositive) ilOp, context, preProcess); + }else if (ilOp instanceof MostNegative){ + asmOps = processMostNegative((MostNegative) ilOp, context, preProcess); + } else if (ilOp instanceof Multiply) { + asmOps = processMultiply((Multiply) ilOp, context, preProcess); + } else if (ilOp instanceof ReadChannel) { + asmOps = processReadChannel((ReadChannel) ilOp, context, preProcess); + } else if (ilOp instanceof ReadPort) { + asmOps = processReadPort((ReadPort) ilOp, context, preProcess); + } else if (ilOp instanceof ReadTimer) { + asmOps = processReadTimer((ReadTimer) ilOp, context, preProcess); + } else if (ilOp instanceof RightShift) { + asmOps = processRightShift((RightShift) ilOp, context, preProcess); + } else if (ilOp instanceof Skip) { + asmOps = processSkip((Skip) ilOp, context, preProcess); + } else if (ilOp instanceof StartProcess) { + asmOps = processStartProcess((StartProcess) ilOp, context, preProcess); + } else if (ilOp instanceof StoreArgument) { + asmOps = processStoreArgument((StoreArgument) ilOp, context, preProcess); + } else if (ilOp instanceof StoreGlobal) { + asmOps = processStoreGlobal((StoreGlobal) ilOp, context, preProcess); + } else if (ilOp instanceof StoreLocal) { + asmOps = processStoreLocal((StoreLocal) ilOp, context, preProcess); + } else if (ilOp instanceof Subtract) { + asmOps = processSubtract((Subtract) ilOp, context, preProcess); + } else if (ilOp instanceof UnaryMinus) { + asmOps = processUnaryMinus((UnaryMinus) ilOp, context, preProcess); + } else if (ilOp instanceof WaitAlt) { + asmOps = processWaitAlt((WaitAlt) ilOp, context, preProcess); + } else if (ilOp instanceof WriteChannel) { + asmOps = processWriteChannel((WriteChannel) ilOp, context, preProcess); + } else if (ilOp instanceof WritePort) { + asmOps = processWritePort((WritePort) ilOp, context, preProcess); + } else { + throw new InvalidObjectException("Unrecognised IL op type in the ASMGenerator! IL op: " + ILOpFormatter.formatOp(ilOp, context.getCurrentILBlock())); + } + + if (!preProcess && asmOps != null) { + + // Post-op processing + + if (context.initProcesses_ContinueOpIds.size() > 0) { + if (context.initProcesses_ContinueOpIds.peek().equals(ilOp.getId())) { + context.initProcesses_ContinueOpIds.pop(); + + asmOps.add(0, new Ajw(-(int)context.initProcesses_ProcCountOffsets.pop())); + } + } + + if (ilOp.getRequiresLabel()) { + String labelStr = context.generateILOpLabel(ilOp); + Label label = new Label(labelStr); + if (asmOps.size() > 0) { + asmOps = new ArrayList<>(asmOps); + asmOps.add(0, label); + } else { + asmOps = new ArrayList<>(); + asmOps.add(label); + } + + if (prefixWithJump) { + asmOps.add(0, new Ldc(0)); + asmOps.add(1, new Cj(labelStr + "-$0")); + } + + if (ilOp.getRequiresPopAfterLabel()) { + asmOps.add(new Diff()); + } + } + + // Save the ops + context.getCurrentASMBlock().addOps(asmOps); + } else if (preProcess && asmOps != null) { + System.out.println("Pre-processing mistake. The op's process method returned a non-null list for a preprocess call. Il op: " + ILOpFormatter.formatOp(ilOp, context.getCurrentILBlock())); + } + } + + + private List processCall(Call op, ASMGeneratorContext> context, boolean preProcess) { + // Pre-op code for both process and preprocess + Function functionToCall = context.libraryInformation.getFunction(op.functionName); + + + // Push parent WS pointer as last argument + List parentWSPtrOps = preProcess ? null : new ArrayList<>(); + int argsSize = functionToCall.getArguments().size(); + if (functionToCall.getWorkspace().getParent() != null) { + argsSize += 1; + + List pushPtrOps = ASMGeneratorHelpers.processPushes(1, op, context, preProcess); + + if (!preProcess) { + parentWSPtrOps.add(new Ldlp(0)); + parentWSPtrOps.addAll(pushPtrOps); + } + } + + + + int expansionSize = ASMGeneratorHelpers.getFullWorkspaceSize(context, functionToCall); + expansionSize -= Math.max(argsSize - 3, 0); + context.getCurrentWorkspace().growExpansionArea(expansionSize); + + + + /* int extraSpace = functionToCall.getArguments().size() >= functionToCall.getReturnTypes().size() ? 0 : + functionToCall.getReturnTypes().size() - functionToCall.getArguments().size(); + for (int i = 0; i < extraSpace; i++) { + context.getCurrentWorkspace().allocateTemporary(); + }*/ + + List popOps = ASMGeneratorHelpers.processPops(Math.min(argsSize, 3), op, context, preProcess); + for (int i = 0; i < argsSize - 3; i++) { + if (preProcess) { + StackItem item = context.popFromEvaluationStack(); + + ASMGeneratorHelpers.setupTempStore(context, item, true); + } else { + context.getCurrentWorkspace().removeTemporaryFromWorkspace(); + } + } + + for (int i = 0; i < functionToCall.getReturnTypes().size() - 3; i++) { + if (preProcess) { + context.pushToEvaluationStack(op.getId(), i+3); + } else { + context.getCurrentWorkspace().allocateTemporary(); + } + } + List pushOps = ASMGeneratorHelpers.processPushes(Math.min(functionToCall.getReturnTypes().size(), 3), op, context, preProcess); + + List result; + if (preProcess) { + // Code for preprocess only + + result = null; + } else { + // Code for process only + + result = new ArrayList<>(); + result.addAll(parentWSPtrOps); + result.addAll(popOps); + + for (int i = argsSize; i < 3; i++) { + result.add(new Ldc(0)); + } + + int offset = context.getCurrentWorkspace().getLastTemporaryOffset(Math.max(functionToCall.getReturnTypes().size()-3,0) - Math.max(argsSize-3,0)); + result.add(new Ajw(offset)); + result.add(new uk.co.transputersystems.occam.open_transputer.assembly.Call(op.functionName + "-$0" )); + + offset = context.getCurrentWorkspace().getLastTemporaryOffset(0); + result.add(new Ajw(-offset)); + + result.addAll(pushOps); + } + + // Post-op code for both process and preprocess + context.getCurrentWorkspace().shrinkExpansionArea(expansionSize); + + return result; + } + + + private List processMethodStart(MethodStart op, ASMGeneratorContext> context, boolean preProcess) { + // Pre-op code for both process and preprocess + + List result; + if (preProcess) { + // Code for preprocess only + + result = null; + } else { + // Code for process only + + result = Collections.singletonList(new Ajw(-context.getCurrentWorkspace().getInitSize())); + } + + // Post-op code for both process and preprocess + + return result; + } + + private List processMethodEnd(MethodEnd op, ASMGeneratorContext> context, boolean preProcess) { + // Pre-op code for both process and preprocess + + List popOps = preProcess ? null : new ArrayList<>(); + int retValsToPop = context.getCurrentFunction().getReturnTypes().size(); + if (retValsToPop > 3) { + if (preProcess) { + StackItem item1 = context.popFromEvaluationStack(); + StackItem item2 = context.popFromEvaluationStack(); + StackItem item3 = context.popFromEvaluationStack(); + + + for (int i = 3; i < retValsToPop; i++) { + StackItem item = context.popFromEvaluationStack(); + ASMGeneratorHelpers.setupTempStore(context, item, false); + } + + context.pushToEvaluationStack(item3); + context.pushToEvaluationStack(item2); + context.pushToEvaluationStack(item1); + } + + retValsToPop = 3; + } + if (retValsToPop > 0) { + popOps = ASMGeneratorHelpers.processPops(retValsToPop, op, context, preProcess); + } + + int iPtrStoreLocation = context.getCurrentWorkspace().getNextTemporaryOffset(); + context.getCurrentWorkspace().allocateTemporary(); + int r2StoreLocation = Integer.MIN_VALUE; + if (context.getCurrentFunction().getReturnTypes().size() >= 3) { + r2StoreLocation = context.getCurrentWorkspace().getNextTemporaryOffset(); + context.getCurrentWorkspace().allocateTemporary(); + } + int r1StoreLocation = Integer.MIN_VALUE; + if (context.getCurrentFunction().getReturnTypes().size() >= 2) { + r1StoreLocation = context.getCurrentWorkspace().getNextTemporaryOffset(); + context.getCurrentWorkspace().allocateTemporary(); + } + int r0StoreLocation = Integer.MIN_VALUE; + if (context.getCurrentFunction().getReturnTypes().size() >= 1) { + r0StoreLocation = context.getCurrentWorkspace().getNextTemporaryOffset(); + context.getCurrentWorkspace().allocateTemporary(); + } + + + List result; + if (preProcess) { + // Code for preprocess only + + result = null; + } else { + // Code for process only + + result = new ArrayList<>(); + result.addAll(popOps); + + //Store r0, r1, r2 + if (context.getCurrentFunction().getReturnTypes().size() >= 1) { + + result.add(new Stl(r0StoreLocation)); + + if (context.getCurrentFunction().getReturnTypes().size() >= 2) { + result.add(new Stl(r1StoreLocation)); + } + if (context.getCurrentFunction().getReturnTypes().size() >= 3) { + result.add(new Stl(r2StoreLocation)); + } + //Load iPtr + result.add(new Ldl(context.getCurrentWorkspace().getInitSize())); + //Store iPtr + result.add(new Stl(iPtrStoreLocation)); + //Copy rN...r3 to `size` + int rNDstOffset = context.getCurrentWorkspace().getSize() - 1; + if (context.getCurrentFunction().getReturnTypes().size() > 3) { + int rNSrcOffset = context.getCurrentWorkspace().getLastTemporaryOffset(4 + context.getCurrentFunction().getReturnTypes().size() - 3 - 1); + for (int i = 0; i < context.getCurrentFunction().getReturnTypes().size()-3; i++, rNSrcOffset--, rNDstOffset--) { + result.add(new Ldl(rNSrcOffset)); + result.add(new Stl(rNDstOffset)); + } + } + rNDstOffset -= 3; + // + //Copy iPtr to `size` - ((rets - 3) downto 0) - 1 - 1 + // cntToIdx + result.add(new Ldl(iPtrStoreLocation)); + result.add(new Stl(rNDstOffset)); + //Restore r0 to r2 (size-args) + if (context.getCurrentFunction().getReturnTypes().size() >= 3) { + result.add(new Ldl(r2StoreLocation)); + } + if (context.getCurrentFunction().getReturnTypes().size() >= 2) { + result.add(new Ldl(r1StoreLocation)); + } + + result.add(new Ldl(r0StoreLocation)); + + //Ajw + result.add(new Ajw(rNDstOffset)); + } else { + //Ajw + result.add(new Ajw(context.getCurrentWorkspace().getSize() - 4)); + } + //Ret + result.add(new Ret()); + } + + // Post-op code for both process and preprocess + + // Remove r0, r1, r2 + if (context.getCurrentFunction().getReturnTypes().size() >= 1) { + context.getCurrentWorkspace().removeTemporaryFromWorkspace(); + } + if (context.getCurrentFunction().getReturnTypes().size() >= 2) { + context.getCurrentWorkspace().removeTemporaryFromWorkspace(); + } + if (context.getCurrentFunction().getReturnTypes().size() >= 3) { + context.getCurrentWorkspace().removeTemporaryFromWorkspace(); + } + + // Remove iPtr + context.getCurrentWorkspace().removeTemporaryFromWorkspace(); + + retValsToPop = context.getCurrentFunction().getReturnTypes().size(); + if (retValsToPop > 3) { + if (preProcess) { + for (int i = 3; i < retValsToPop; i++) { + context.getCurrentWorkspace().removeTemporaryFromWorkspace(); + } + } + } + + return result; + } + + + + private List processInitProcesses(InitProcesses op, ASMGeneratorContext> context, boolean preProcess) { + // Pre-op code for both process and preprocess + + List wsIds = new ArrayList<>(op.workspaceIds); + wsIds.remove(0); + context.setStartingProcessesWorkspaceIds(wsIds); + context.addWorkspaceTransition(op.continueILOpID, context.getCurrentWorkspace().getId()); + + context.getCurrentWorkspace().allocateTemporary(); + context.getCurrentWorkspace().allocateTemporary(); + + context.initProcesses_NumProcessesToStart.push(op.numProcesses - 1); + context.initProcesses_NumProcessesToEnd.push(op.numProcesses); + context.initProcesses_TotalNumProcessesToEnd.push(op.numProcesses); + context.initProcesses_ExpandedSizes.push(0); + + context.getCurrentWorkspace().allocateTemporary(); + int processesCountOffset = context.getCurrentWorkspace().getLastTemporaryOffset(0); + context.getCurrentWorkspace().allocateTemporary(); + int continuePtrOffset = context.getCurrentWorkspace().getLastTemporaryOffset(0); + + context.initProcesses_ProcCountOffsets.push(continuePtrOffset); + context.initProcesses_ContinueOpIds.push(op.continueILOpID); + + List result; + if (preProcess) { + // Code for preprocess only + + context.getCurrentILBlock().get(op.continueILOpID).setRequiresLabel(true); + + result = null; + } else { + // Code for process only + + result = new ArrayList<>(); + result.add(new Ldc(op.numProcesses)); + result.add(new Stl(processesCountOffset)); + result.add(new Ldc(context.generateILOpLabel(op.continueILOpID) + "-$1")); + result.add(new Ldpi()); + result.add(new Stl(continuePtrOffset)); + } + + // Post-op code for both process and preprocess + + return result; + } + + private List processStartProcess(StartProcess op, ASMGeneratorContext> context, boolean preProcess) { + // Pre-op code for both process and preprocess + + List workspaceIds = context.getStartingProcessesWorkspaceIds(); + Integer newWorkspaceId = workspaceIds.remove(0); + context.addWorkspaceTransition(op.firstILOpID, newWorkspaceId); + + int numProcessesToStart = context.initProcesses_NumProcessesToStart.pop(); + numProcessesToStart--; + if (numProcessesToStart > 0) { + context.initProcesses_NumProcessesToStart.push(numProcessesToStart); + } + + ILOp processStartOp = context.getCurrentILBlock().get(op.firstILOpID); + + List result; + if (preProcess) { + // Code for preprocess only + + processStartOp.setRequiresLabel(true); + + result = null; + } else { + // Code for process only + + result = new ArrayList<>(); + + result.add(new Ldlp(context.initProcesses_ProcCountOffsets.peek())); + result.add(new Stl(-context.getCurrentWorkspace().getExpansionAreaSize() - 1)); + + String processLabelStr = context.generateILOpLabel(processStartOp); + result.add(new Ldc(processLabelStr + "-$2")); + result.add(new Ldlp(-context.getCurrentWorkspace().getExpansionAreaSize() - context.getCurrentFunction().getWorkspaceById(newWorkspaceId).getInitSize())); + result.add(new Startp()); + } + + // Post-op code for both process and preprocess + int newWorkspaceFullSize = ASMGeneratorHelpers.getFullWorkspaceSize(context, context.getCurrentFunction().getScopeByWorkspaceId(newWorkspaceId)); + context.initProcesses_ExpandedSizes.push(context.initProcesses_ExpandedSizes.pop() + newWorkspaceFullSize); + context.getCurrentWorkspace().growExpansionArea(newWorkspaceFullSize); + + return result; + } + + private List processEndProcess(EndProcess op, ASMGeneratorContext> context, boolean preProcess) { + // Pre-op code for both process and preprocess + + int totalNumProcessesToEnd = context.initProcesses_TotalNumProcessesToEnd.peek(); + int numProcessesToEnd = context.initProcesses_NumProcessesToEnd.pop(); + numProcessesToEnd--; + if (numProcessesToEnd > 0) { + context.initProcesses_NumProcessesToEnd.push(numProcessesToEnd); + } else { + context.initProcesses_TotalNumProcessesToEnd.pop(); + context.getCurrentWorkspace().getParent().removeTemporaryFromWorkspace(); + context.getCurrentWorkspace().getParent().removeTemporaryFromWorkspace(); + } + + if (numProcessesToEnd == totalNumProcessesToEnd - 1) { + context.getCurrentWorkspace().shrinkExpansionArea(context.initProcesses_ExpandedSizes.pop()); + + context.getCurrentWorkspace().removeTemporaryFromWorkspace(); + context.getCurrentWorkspace().removeTemporaryFromWorkspace(); + } + + List result; + if (preProcess) { + // Code for preprocess only + + result = null; + } else { + // Code for process only + + result = new ArrayList<>(); + if (numProcessesToEnd == totalNumProcessesToEnd - 1) { + result.add(new Ldlp(context.initProcesses_ProcCountOffsets.peek())); + } else { + result.add(new Ldl(context.getCurrentWorkspace().getOffset(Integer.MIN_VALUE))); + } + result.add(new Endp()); + } + + // Post-op code for both process and preprocess + + return result; + } + + + + private List processSkip(Skip op, ASMGeneratorContext> context, boolean preProcess) { + // Pre-op code for both process and preprocess + + List result; + if (preProcess) { + // Code for preprocess only + + result = null; + } else { + // Code for process only + + result = new ArrayList<>(); + } + + // Post-op code for both process and preprocess + + return result; + } + + private List processLabel(uk.co.transputersystems.occam.il.Label op, ASMGeneratorContext> context, boolean preProcess) { + // Pre-op code for both process and preprocess + + List result; + if (preProcess) { + // Code for preprocess only + + result = null; + } else { + // Code for process only + + //TODO: Handle is global + result = Collections.singletonList(new uk.co.transputersystems.occam.open_transputer.assembly.Label(op.label)); + } + + // Post-op code for both process and preprocess + + return result; + } + + + + private List processMostPositive(MostPositive op, ASMGeneratorContext> context, boolean preProcess) { + // Pre-op code for both process and preprocess + + List pushOps = ASMGeneratorHelpers.processPushes(1, op, context, preProcess); + List result; + if (preProcess) { + // Code for preprocess only + + result = null; + } else { + // Code for process only + + result = new ArrayList<>(); + Long value = null; + switch(op.type) { + case "BOOL": + value = 1l; + break; + case "BYTE": + value = (long)Byte.MAX_VALUE; + break; + case "INT": + value = (long)Integer.MAX_VALUE; // TODO: Load byte size from config + break; + case "INT16": + value = (long)Short.MAX_VALUE; + break; + case "INT32": + value = (long)Integer.MAX_VALUE; + break; + case "INT64": + value = Long.MAX_VALUE; + break; + } + result.add(new Ldc(value)); + result.addAll(pushOps); + } + + // Post-op code for both process and preprocess + + return result; + } + + private List processMostNegative(MostNegative op, ASMGeneratorContext> context, boolean preProcess) { + // Pre-op code for both process and preprocess + + List pushOps = ASMGeneratorHelpers.processPushes(1, op, context, preProcess); + List result; + if (preProcess) { + // Code for preprocess only + + result = null; + } else { + // Code for process only + + result = new ArrayList<>(); + Long value = null; + switch(op.type) { + case "BOOL": + value = 0l; + break; + case "BYTE": + value = (long)Byte.MIN_VALUE; + break; + case "INT": + value = (long)Integer.MIN_VALUE; // TODO: Load byte size from config + break; + case "INT16": + value = (long)Short.MIN_VALUE; + break; + case "INT32": + value = (long)Integer.MIN_VALUE; + break; + case "INT64": + value = Long.MIN_VALUE; + break; + } + result.add(new Ldc(value)); + result.addAll(pushOps); + } + + // Post-op code for both process and preprocess + + return result; + } + + private List processLoadConstant(LoadConstant op, ASMGeneratorContext> context, boolean preProcess) { + // Pre-op code for both process and preprocess + + List pushOps = ASMGeneratorHelpers.processPushes(1, op, context, preProcess); + List result; + if (preProcess) { + // Code for preprocess only + + result = null; + } else { + // Code for process only + + result = new ArrayList<>(); + long value = Long.parseLong(op.value); // TODO: may throw exception + result.add(new Ldc(value)); + result.addAll(pushOps); + } + + // Post-op code for both process and preprocess + + return result; + } + + private List processLoadArgument(LoadArgument op, ASMGeneratorContext> context, boolean preProcess) { + return ASMGeneratorHelpers.processLoadArgument(-op.index, op, context, preProcess, op.loadAddress); + } + + private List processLoadLocal(LoadLocal op, ASMGeneratorContext> context, boolean preProcess) { + return ASMGeneratorHelpers.processLoadLocal(op.index, op, context, preProcess, op.loadAddress); + } + + private List processLoadGlobal(LoadGlobal op, ASMGeneratorContext> context, boolean preProcess) { + // Pre-op code for both process and preprocess + // Ldc + if (!op.loadAddress) { + context.pushToEvaluationStack(op.getId(), -1); + context.popFromEvaluationStack(); + } + List pushOps = ASMGeneratorHelpers.processPushes(1, op, context, preProcess); + + List result; + if (preProcess) { + // Code for preprocess only + + result = null; + } else { + // Code for process only + + result = new ArrayList<>(); + result.add(new Ldc(context.generateGlobalRepresentation(op.globalName))); + if (!op.loadAddress) { + //TODO: Handle globals which are record types i.e. reference types + //TODO: Handle globals which are > word size + result.add(new Ldnl(0)); + } + result.addAll(pushOps); + } + + // Post-op code for both process and preprocess + + return result; + } + + private List processStoreArgument(StoreArgument op, ASMGeneratorContext> context, boolean preProcess) { + return ASMGeneratorHelpers.processStoreArgument(-op.index, op, context, preProcess); + } + + private List processStoreLocal(StoreLocal op, ASMGeneratorContext> context, boolean preProcess) { + return ASMGeneratorHelpers.processStoreLocal(op.index, op, context, preProcess); + } + + private List processStoreGlobal(StoreGlobal op, ASMGeneratorContext> context, boolean preProcess) { + // Pre-op code for both process and preprocess + + context.pushToEvaluationStack(op.getId(), -1); + context.popFromEvaluationStack(); + + List popOps = ASMGeneratorHelpers.processPops(1, op, context, preProcess); + + List result; + if (preProcess) { + // Code for preprocess only + + result = null; + } else { + // Code for process only + + result = new ArrayList<>(); + //TODO: Handle globals which are record types i.e. reference types + //TODO: Handle globals which are > word size + result.add(new Ldc(context.generateGlobalRepresentation(op.globalName))); + result.addAll(popOps); + result.add(new Stnl(0)); + } + + // Post-op code for both process and preprocess + + return result; + } + + + + private List processReadChannel(ReadChannel op, ASMGeneratorContext> context, boolean preProcess) { + //TODO + + // Pre-op code for both process and preprocess + + List popOps = ASMGeneratorHelpers.processPops(3, op, context, preProcess); + + List result; + if (preProcess) { + // Code for preprocess only + + result = null; + } else { + // Code for process only + + result = new ArrayList<>(); + result.addAll(popOps); + result.add(new In()); + } + + // Post-op code for both process and preprocess + + return result; + } + + private List processReadPort(ReadPort op, ASMGeneratorContext> context, boolean preProcess) { + //TODO + + // Pre-op code for both process and preprocess + + List popOps = ASMGeneratorHelpers.processPops(3, op, context, preProcess); + + List result; + if (preProcess) { + // Code for preprocess only + + result = null; + } else { + // Code for process only + + result = new ArrayList<>(); + result.addAll(popOps); + result.add(new In()); + } + + // Post-op code for both process and preprocess + + return result; + } + + private List processReadTimer(ReadTimer op, ASMGeneratorContext> context, boolean preProcess) { + //TODO + + // Pre-op code for both process and preprocess + + List pushOps = ASMGeneratorHelpers.processPushes(1, op, context, preProcess); + + List result; + if (preProcess) { + // Code for preprocess only + + result = null; + } else { + // Code for process only + + result = new ArrayList<>(); + result.add(new Ldtimer()); + result.addAll(pushOps); + } + + // Post-op code for both process and preprocess + + return result; + } + + + private List processWriteChannel(WriteChannel op, ASMGeneratorContext> context, boolean preProcess) { + //TODO + + // Pre-op code for both process and preprocess + + List popOps = ASMGeneratorHelpers.processPops(3, op, context, preProcess); + + List result; + if (preProcess) { + // Code for preprocess only + + result = null; + } else { + // Code for process only + + result = new ArrayList<>(); + result.addAll(popOps); + result.add(new Out()); + } + + // Post-op code for both process and preprocess + + return result; + } + + private List processWritePort(WritePort op, ASMGeneratorContext> context, boolean preProcess) { + //TODO + + // Pre-op code for both process and preprocess + + List popOps = ASMGeneratorHelpers.processPops(3, op, context, preProcess); + + List result; + if (preProcess) { + // Code for preprocess only + + result = null; + } else { + // Code for process only + + result = new ArrayList<>(); + result.addAll(popOps); + result.add(new Out()); + } + + // Post-op code for both process and preprocess + + return result; + } + + + private List processAdd(Add op, ASMGeneratorContext> context, boolean preProcess) { + // Pre-op code for both process and preprocess + List popOps = ASMGeneratorHelpers.processPops(2, op, context, preProcess); + List pushOps = ASMGeneratorHelpers.processPushes(1, op, context, preProcess); + + List result; + if (preProcess) { + // Code for preprocess only + + result = null; + } else { + // Code for process only + + result = new ArrayList<>(); + result.addAll(popOps); + + //Sum assembly op ignores overflow check + if (op.ignore_overflow) { + result.add(new Sum()); + } else { + result.add(new uk.co.transputersystems.occam.open_transputer.assembly.Add()); + } + + result.addAll(pushOps); + } + + // Post-op code for both process and preprocess + + return result; + + } + + private List processSubtract(Subtract op, ASMGeneratorContext> context, boolean preProcess) { + // Pre-op code for both process and preprocess + List popOps = ASMGeneratorHelpers.processPops(2, op, context, preProcess); + List pushOps = ASMGeneratorHelpers.processPushes(1, op, context, preProcess); + + List result; + if (preProcess) { + // Code for preprocess only + + result = null; + } else { + // Code for process only + + result = new ArrayList<>(); + result.addAll(popOps); + + //Diff instruction ignores overflow + if (op.ignore_overflow) { + result.add(new Diff()); + } else { + result.add(new Sub()); + } + + result.addAll(pushOps); + } + + // Post-op code for both process and preprocess + + return result; + + + } + + private List processMultiply(Multiply op, ASMGeneratorContext> context, boolean preProcess) { + // Pre-op code for both process and preprocess + List popOps = ASMGeneratorHelpers.processPops(2, op, context, preProcess); + List pushOps = ASMGeneratorHelpers.processPushes(1, op, context, preProcess); + + List result; + if (preProcess) { + // Code for preprocess only + + result = null; + } else { + // Code for process only + + result = new ArrayList<>(); + result.addAll(popOps); + + if (op.ignore_overflow) { //Prod instruction ignores overflow + result.add(new Prod()); + } else { //Mul doesn't ignore overflow + result.add(new Mul()); + } + + result.addAll(pushOps); + } + + // Post-op code for both process and preprocess + + return result; + + } + + private List processDuplicate(Duplicate op, ASMGeneratorContext> context, boolean preProcess) { + // Pre-op code for both process and preprocess + + // Dup + List popOps = ASMGeneratorHelpers.processPops(1, op, context, preProcess); + List pushOps = ASMGeneratorHelpers.processPushes(2, op, context, preProcess); + + List result; + if (preProcess) { + // Code for preprocess only + + result = null; + } else { + // Code for process only + + result = new ArrayList<>(); + result.addAll(popOps); + result.add(new Dup()); + result.addAll(pushOps); + } + + // Post-op code for both process and preprocess + + return result; + } + + + + private List processBranch(Branch op, ASMGeneratorContext> context, boolean preProcess) throws Exception { + // Currently we store the Id of the destination label in a separate destination field for all branch instructions + + // Pre-op code for both process and preprocess + + // Ldc + if (context.getEvaluationStackSize() != 0) { + throw new Exception("Stack should be empty before branching!"); + } + + List result; + if (preProcess) { + // Code for preprocess only + + ILOp target = context.getCurrentILBlock().get(op.target); + target.setRequiresLabel(true); + target.setRequiresPopAfterLabel(true); + + result = null; + } else { + // Code for process only + + // Avoid being time sliced by using conditional jump + result = new ArrayList<>(); + result.add(new Ldc(0)); + result.add(new Cj(context.generateILOpLabel(op.target) + "-$0")); + } + + // Post-op code for both process and preprocess + + // Branch + context.pushToEvaluationStack(op.getId(), -1); + context.forkCurrentState(op.target); + context.popFromEvaluationStack(); + + return result; + } + + private List processBranchEqZero(BranchEqZero op, ASMGeneratorContext> context, boolean preProcess) { + return ASMGeneratorHelpers.processConditionalBranch_False(op.target, op, context, preProcess); + } + + private List processBranchNotEqZero(BranchNotEqZero op, ASMGeneratorContext> context, boolean preProcess) { + return ASMGeneratorHelpers.processConditionalBranch_True(op.target, op, context, preProcess); + } + + private List processBranchIfFalse(BranchIfFalse op, ASMGeneratorContext> context, boolean preProcess) { + return ASMGeneratorHelpers.processConditionalBranch_False(op.target, op, context, preProcess); + } + + private List processBranchIfTrue(BranchIfTrue op, ASMGeneratorContext> context, boolean preProcess) { + return ASMGeneratorHelpers.processConditionalBranch_True(op.target, op, context, preProcess); + } + + + + private List processCompareGreaterThan(CompareGreaterThan op, ASMGeneratorContext> context, boolean preProcess) { + // Pre-op code for both process and preprocess + + // Gt + List popOps = ASMGeneratorHelpers.processPops(2, op, context, preProcess); + List pushOps = ASMGeneratorHelpers.processPushes(1, op, context, preProcess); + + List result; + if (preProcess) { + // Code for preprocess only + + result = null; + } else { + // Code for process only + + result = Collections.singletonList(new Gt()); + } + + // Post-op code for both process and preprocess + + return result; + } + + /** + * See *Transputer Instruction Set: a compiler writer's guide*, p23 + * (X >= Y) ≡ ¬(Y > X) + */ + private List processCompareGreaterThanOrEqual(CompareGreaterThanOrEqual op, ASMGeneratorContext> context, boolean preProcess) { + // Pre-op code for both process and preprocess + + // Rev + + List popOps = ASMGeneratorHelpers.processPops(2, op, context, preProcess); + + context.pushToEvaluationStack(op.getId(), -1); + context.pushToEvaluationStack(op.getId(), -1); + // Gt + context.popFromEvaluationStack(); + context.popFromEvaluationStack(); + context.pushToEvaluationStack(op.getId(), -1); + // Eqc + context.popFromEvaluationStack(); + + List pushOps = ASMGeneratorHelpers.processPushes(1, op, context, preProcess); + + List result; + if (preProcess) { + // Code for preprocess only + + result = null; + } else { + // Code for process only + + result = new ArrayList<>(); + + result.addAll(popOps); + result.add(new Rev()); + result.add(new Gt()); + result.add(new Eqc(0)); + result.addAll(pushOps); + } + + // Post-op code for both process and preprocess + + return result; + } + + /** + * See *Transputer Instruction Set: a compiler writer's guide*, p23 + * (X - Y) = 0 ≡ X = Y + */ + private List processCompareEqual(CompareEqual op, ASMGeneratorContext> context, boolean preProcess) { + // Pre-op code for both process and preprocess + + List popOps = ASMGeneratorHelpers.processPops(2, op, context, preProcess); + + // Diff + context.pushToEvaluationStack(op.getId(), -1); + // Eqc + context.popFromEvaluationStack(); + + List pushOps = ASMGeneratorHelpers.processPushes(1, op, context, preProcess); + + List result; + if (preProcess) { + // Code for preprocess only + + result = null; + } else { + // Code for process only + + result = new ArrayList<>(); + result.addAll(popOps); + result.add(new Diff()); + result.add(new Eqc(0)); + result.addAll(pushOps); + } + + // Post-op code for both process and preprocess + + return result; + } + + /** + * See *Transputer Instruction Set: a compiler writer's guide*, p23 + * ¬((X - Y) = 0) ≡ X ≠ Y + */ + private List processCompareNotEqual(CompareNotEqual op, ASMGeneratorContext> context, boolean preProcess) { + // Pre-op code for both process and preprocess + + List popOps = ASMGeneratorHelpers.processPops(2, op, context, preProcess); + + // Diff + context.pushToEvaluationStack(op.getId(), -1); + // Eqc + context.popFromEvaluationStack(); + context.pushToEvaluationStack(op.getId(), -1); + // Eqc + context.popFromEvaluationStack(); + + List pushOps = ASMGeneratorHelpers.processPushes(1, op, context, preProcess); + + List result; + if (preProcess) { + // Code for preprocess only + + result = null; + } else { + // Code for process only + + result = new ArrayList<>(); + result.addAll(popOps); + result.add(new Diff()); + result.add(new Eqc(0)); + result.add(new Eqc(0)); + result.addAll(pushOps); + } + + // Post-op code for both process and preprocess + + return result; + } + + /** + * See *Transputer Instruction Set: a compiler writer's guide*, p23 + * (X < Y) ≡ (Y > X) + */ + private List processCompareLessThan(CompareLessThan op, ASMGeneratorContext> context, boolean preProcess) { + // Pre-op code for both process and preprocess + + List popOps = ASMGeneratorHelpers.processPops(2, op, context, preProcess); + + // Rev + context.pushToEvaluationStack(op.getId(), -1); + context.pushToEvaluationStack(op.getId(), -1); + // Gt + context.popFromEvaluationStack(); + context.popFromEvaluationStack(); + + List pushOps = ASMGeneratorHelpers.processPushes(1, op, context, preProcess); + + List result; + if (preProcess) { + // Code for preprocess only + + result = null; + } else { + // Code for process only + + result = new ArrayList<>(); + result.addAll(popOps); + result.add(new Rev()); + result.add(new Gt()); + result.addAll(pushOps); + } + + // Post-op code for both process and preprocess + + return result; + } + + /** + * See *Transputer Instruction Set: a compiler writer's guide*, p23 + * (X <= Y) ≡ ¬(X > Y) + */ + private List processCompareLessThanOrEqual(CompareLessThanOrEqual op, ASMGeneratorContext> context, boolean preProcess) { + // Pre-op code for both process and preprocess + + List popOps = ASMGeneratorHelpers.processPops(2, op, context, preProcess); + + // Gt + context.pushToEvaluationStack(op.getId(), -1); + // Eqc + context.popFromEvaluationStack(); + + List pushOps = ASMGeneratorHelpers.processPushes(1, op, context, preProcess); + + List result; + if (preProcess) { + // Code for preprocess only + + result = null; + } else { + // Code for process only + + result = new ArrayList<>(); + result.addAll(popOps); + result.add(new Gt()); + result.add(new Eqc(0)); + result.addAll(pushOps); + } + + // Post-op code for both process and preprocess + + return result; + } + + private List processBooleanAnd(BooleanAnd op, ASMGeneratorContext> context, boolean preProcess) { + // Pre-op code for both process and preprocess + + // And + List popOps = ASMGeneratorHelpers.processPops(2, op, context, preProcess); + List pushOps = ASMGeneratorHelpers.processPushes(1, op, context, preProcess); + + List result; + if (preProcess) { + // Code for preprocess only + + result = null; + } else { + // Code for process only + + result = new ArrayList<>(); + result.addAll(popOps); + result.add(new Eqc(0)); + result.add(new Rev()); + result.add(new Eqc(0)); + result.add(new Or()); + result.add(new Eqc(0)); + result.addAll(pushOps); + } + + // Post-op code for both process and preprocess + + return result; + } + private List processBooleanOr(BooleanOr op, ASMGeneratorContext> context, boolean preProcess) { + // Pre-op code for both process and preprocess + + // And + List popOps = ASMGeneratorHelpers.processPops(2, op, context, preProcess); + List pushOps = ASMGeneratorHelpers.processPushes(1, op, context, preProcess); + + List result; + if (preProcess) { + // Code for preprocess only + + result = null; + } else { + // Code for process only + + result = new ArrayList<>(); + result.addAll(popOps); + result.add(new Or()); + result.add(new Eqc(0)); + result.add(new Eqc(0)); + result.addAll(pushOps); + } + + // Post-op code for both process and preprocess + + return result; + } + + private List processBitwiseAnd(BitwiseAnd op, ASMGeneratorContext> context, boolean preProcess) { + // Pre-op code for both process and preprocess + + // And + List popOps = ASMGeneratorHelpers.processPops(2, op, context, preProcess); + List pushOps = ASMGeneratorHelpers.processPushes(1, op, context, preProcess); + + List result; + if (preProcess) { + // Code for preprocess only + + result = null; + } else { + // Code for process only + + result = new ArrayList<>(); + result.addAll(popOps); + result.add(new And()); + result.addAll(pushOps); + } + + // Post-op code for both process and preprocess + + return result; + } + + private List processBitwiseOr(BitwiseOr op, ASMGeneratorContext> context, boolean preProcess) { + // Pre-op code for both process and preprocess + + // Or + List popOps = ASMGeneratorHelpers.processPops(2, op, context, preProcess); + List pushOps = ASMGeneratorHelpers.processPushes(1, op, context, preProcess); + + List result; + if (preProcess) { + // Code for preprocess only + + result = null; + } else { + // Code for process only + + result = new ArrayList<>(); + result.addAll(popOps); + result.add(new Or()); + result.addAll(pushOps); + } + + // Post-op code for both process and preprocess + + return result; + } + + private List processBooleanNot(BooleanNot op, ASMGeneratorContext> context, boolean preProcess) { + // Pre-op code for both process and preprocess + List popOps = ASMGeneratorHelpers.processPops(1, op, context, preProcess); + List pushOps = ASMGeneratorHelpers.processPushes(1, op, context, preProcess); + + List result; + if (preProcess) { + // Code for preprocess only + + result = null; + } else { + // Code for process only + + result = new ArrayList<>(); + result.addAll(popOps); + result.add(new Eqc(0)); + result.addAll(pushOps); + } + + // Post-op code for both process and preprocess + + return result; + } + + private List processBitwiseNot(BitwiseNot op, ASMGeneratorContext> context, boolean preProcess) { + // Pre-op code for both process and preprocess + + List popOps = ASMGeneratorHelpers.processPops(1, op, context, preProcess); + List pushOps = ASMGeneratorHelpers.processPushes(1, op, context, preProcess); + + List result; + if (preProcess) { + // Code for preprocess only + + result = null; + } else { + // Code for process only + + result = new ArrayList<>(); + result.addAll(popOps); + result.add(new Not()); + result.addAll(pushOps); + } + + // Post-op code for both process and preprocess + + return result; + } + + private List processBitwiseXor(BitwiseXor op, ASMGeneratorContext> context, boolean preProcess) { + // Pre-op code for both process and preprocess + List popOps = ASMGeneratorHelpers.processPops(2, op, context, preProcess); + List pushOps = ASMGeneratorHelpers.processPushes(1, op, context, preProcess); + + List result; + if (preProcess) { + // Code for preprocess only + + result = null; + } else { + // Code for process only + + result = new ArrayList<>(); + result.addAll(popOps); + result.add(new Xor()); + result.addAll(pushOps); + } + + // Post-op code for both process and preprocess + + return result; + } + + private List processDivide(Divide op, ASMGeneratorContext> context, boolean preProcess) { + // Pre-op code for both process and preprocess + List popOps = ASMGeneratorHelpers.processPops(2, op, context, preProcess); + List pushOps = ASMGeneratorHelpers.processPushes(1, op, context, preProcess); + + List result; + if (preProcess) { + // Code for preprocess only + + result = null; + } else { + // Code for process only + + result = new ArrayList<>(); + result.addAll(popOps); + result.add(new Div()); + result.addAll(pushOps); + } + + // Post-op code for both process and preprocess + + return result; + } + + private List processUnaryMinus(UnaryMinus op, ASMGeneratorContext> context, boolean preProcess) { + // See page 5.3.5 of Compilers Writers Guide + + List prePushOps = null; + List popOps; + List pushOps; + + // Pre-op code for both process and preprocess + if (op.ignore_overflow) { + + // Ldc + prePushOps = ASMGeneratorHelpers.processPushes(1, op, context, preProcess); + // Prod + popOps = ASMGeneratorHelpers.processPops(2, op, context, preProcess); + pushOps = ASMGeneratorHelpers.processPushes(1, op, context, preProcess); + + + } else { + // Ldc + prePushOps = ASMGeneratorHelpers.processPushes(1, op, context, preProcess); + // Mul + popOps = ASMGeneratorHelpers.processPops(2, op, context, preProcess); + pushOps = ASMGeneratorHelpers.processPushes(1, op, context, preProcess); + } + + + List result; + if (preProcess) { + // Code for preprocess only + + result = null; + } else { + // Code for process only + + result = new ArrayList<>(); + result.add(new Ldc(-1)); + result.addAll(prePushOps); + result.addAll(popOps); + if (op.ignore_overflow) { + result.add(new Prod()); + } else { + result.add(new Mul()); + } + result.addAll(pushOps); + } + + // Post-op code for both process and preprocess + + return result; + } + + private List processModulo(Modulo op, ASMGeneratorContext> context, boolean preProcess) { + + // Pre-op code for both process and preprocess + List popOps = ASMGeneratorHelpers.processPops(2, op, context, preProcess); + List pushOps = ASMGeneratorHelpers.processPushes(1, op, context, preProcess); + + List result; + if (preProcess) { + // Code for preprocess only + + result = null; + } else { + // Code for process only + + result = new ArrayList<>(); + result.addAll(popOps); + result.add(new Rem()); + result.addAll(pushOps); + } + + // Post-op code for both process and preprocess + + return result; + } + + private List processLeftShift(LeftShift op, ASMGeneratorContext> context, boolean preProcess) { + // Pre-op code for both process and preprocess + + // And + List popOps = ASMGeneratorHelpers.processPops(2, op, context, preProcess); + List pushOps = ASMGeneratorHelpers.processPushes(1, op, context, preProcess); + + List result; + if (preProcess) { + // Code for preprocess only + + result = null; + } else { + // Code for process only + + result = new ArrayList<>(); + result.addAll(popOps); + //TODO: Handle long data types + result.add(new Shl()); + result.addAll(pushOps); + } + + // Post-op code for both process and preprocess + + return result; + } + + private List processRightShift(RightShift op, ASMGeneratorContext> context, boolean preProcess) { + // Pre-op code for both process and preprocess + + // And + List popOps = ASMGeneratorHelpers.processPops(2, op, context, preProcess); + List pushOps = ASMGeneratorHelpers.processPushes(1, op, context, preProcess); + + List result; + if (preProcess) { + // Code for preprocess only + + result = null; + } else { + // Code for process only + + result = new ArrayList<>(); + result.addAll(popOps); + //TODO: Handle long data types + result.add(new Shr()); + result.addAll(pushOps); + } + + // Post-op code for both process and preprocess + + return result; + } + + private List processAfter(After op, ASMGeneratorContext> context, boolean preProcess) { + + // Pre-op code for both process and preprocess + List pushOps = ASMGeneratorHelpers.processPushes(1, op, context, preProcess); + List popOps = ASMGeneratorHelpers.processPops(2, op, context, preProcess); + + List result; + if (preProcess) { + // Code for preprocess only + + result = null; + } else { + // Code for process only + + result = new ArrayList<>(); + result.add(new Ldtimer()); + result.addAll(pushOps); + result.addAll(popOps); + result.add(new Sum()); + result.add(new Tin()); + } + + // Post-op code for both process and preprocess + + return result; + } + private List processDelayedTimerInput(DelayedTimerInput op, ASMGeneratorContext> context, boolean preProcess) { + + // Pre-op code for both process and preprocess + List pushOps = ASMGeneratorHelpers.processPushes(1, op, context, preProcess); + List popOps = ASMGeneratorHelpers.processPops(2, op, context, preProcess); + + List result; + if (preProcess) { + // Code for preprocess only + + result = null; + } else { + // Code for process only + + result = new ArrayList<>(); + result.add(new Ldtimer()); + result.addAll(pushOps); + result.addAll(popOps); + result.add(new Sum()); + result.add(new Tin()); + } + + // Post-op code for both process and preprocess + + return result; + } + + private List processDisableChannel(DisableChannel op, ASMGeneratorContext> context, boolean preProcess) { + return ASMGeneratorHelpers.processDisable(op.target, op.endAlt, new Disc(), op, context, preProcess); + } + + private List processDisablePort(DisablePort op, ASMGeneratorContext> context, boolean preProcess) { + return ASMGeneratorHelpers.processDisable(op.target, op.endAlt, new Disc(), op, context, preProcess); + } + + private List processDisableSkip(DisableSkip op, ASMGeneratorContext> context, boolean preProcess) { + return ASMGeneratorHelpers.processDisable(op.target, op.endAlt, new Diss(), op, context, preProcess); + } + + private List processDisableTimer(DisableTimer op, ASMGeneratorContext> context, boolean preProcess) { + return ASMGeneratorHelpers.processDisable(op.target, op.endAlt, new Dist(), op, context, preProcess); + } + + + private List processEnableChannel(EnableChannel op, ASMGeneratorContext> context, boolean preProcess) { + return ASMGeneratorHelpers.processEnable(new Enbc(), op, context, preProcess); + } + + private List processEnablePort(EnablePort op, ASMGeneratorContext> context, boolean preProcess) { + return ASMGeneratorHelpers.processEnable(new Enbc(), op, context, preProcess); + } + + private List processEnableSkip(EnableSkip op, ASMGeneratorContext> context, boolean preProcess) { + return ASMGeneratorHelpers.processEnable(new Enbs(), op, context, preProcess); + } + + private List processEnableTimer(EnableTimer op, ASMGeneratorContext> context, boolean preProcess) { + return ASMGeneratorHelpers.processEnable(new Enbt(), op, context, preProcess); + } + + + private List processInitAlt(InitAlt op, ASMGeneratorContext> context, boolean preProcess) { + // Pre-op code for both process and preprocess + + List result; + if (preProcess) { + // Code for preprocess only + + result = null; + } else { + // Code for process only + + //TODO: Talt? + result = new ArrayList<>(); + result.add(new Alt()); + } + + // Post-op code for both process and preprocess + + return result; + } + + private List processWaitAlt(WaitAlt op, ASMGeneratorContext> context, boolean preProcess) { + // Pre-op code for both process and preprocess + + List result; + if (preProcess) { + // Code for preprocess only + + result = null; + } else { + // Code for process only + + //TODO: Taltwt? + result = new ArrayList<>(); + result.add(new Altwt()); + } + + // Post-op code for both process and preprocess + + return result; + } + + private List processEndAlt(EndAlt op, ASMGeneratorContext> context, boolean preProcess) { + // Pre-op code for both process and preprocess + + List result; + if (preProcess) { + // Code for preprocess only + + result = null; + } else { + // Code for process only + + result = new ArrayList<>(); + result.add(new Altend()); + } + + // Post-op code for both process and preprocess + + return result; + } + + + private List processInitChannel(InitChannel op, ASMGeneratorContext> context, boolean preProcess) { + // Pre-op code for both process and preprocess + + context.setChannel(op.index, op.name, op.typeName); + + List result; + if (preProcess) { + // Code for preprocess only + + result = null; + } else { + // Code for process only + + result = new ArrayList<>(); + } + + // Post-op code for both process and preprocess + + return result; + } + + private List processLoadChannelRef(LoadChannelRef op, ASMGeneratorContext> context, boolean preProcess) { + + // Pre-op code for both process and preprocess + List pushOps = ASMGeneratorHelpers.processPushes(1, op, context, preProcess); + + List result; + if (preProcess) { + // Code for preprocess only + + result = null; + } else { + // Code for process only + + result = new ArrayList<>(); + //TODO: Handle channel data type + result.add(new Channel(context.getChannel(op.index).getKey())); + result.addAll(pushOps); + } + + // Post-op code for both process and preprocess + + return result; + } +} \ No newline at end of file diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/ASMGeneratorContext.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/ASMGeneratorContext.java new file mode 100644 index 0000000..14e6997 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/ASMGeneratorContext.java @@ -0,0 +1,159 @@ +package uk.co.transputersystems.occam.open_transputer; + +import uk.co.transputersystems.occam.il.ILBlock; +import uk.co.transputersystems.occam.il.ILOp; +import uk.co.transputersystems.occam.metadata.*; +import uk.co.transputersystems.occam.open_transputer.assembly.Data; +import uk.co.transputersystems.occam.open_transputer.assembly.Label; + +import javax.annotation.Nonnull; +import java.util.*; + + +public class ASMGeneratorContext> { + + public final LibraryInformation libraryInformation; + private ILBlock currentILBlock; + private ASMBlock currentASMBlock; + private Function currentFunction; + private Workspace currentWorkspace; + @Nonnull private Map workspaceTransitionPoints = new HashMap<>(); + + private List startingProcessesWorkspaceIds; + + private List>> stackBranches; + private StackBranch> currentStackBranch; + + private ASMBlock globalsBlock = new ASMBlock(); + + public Stack initProcesses_NumProcessesToStart = new Stack<>(); + public Stack initProcesses_TotalNumProcessesToEnd = new Stack<>(); + public Stack initProcesses_NumProcessesToEnd = new Stack<>(); + public Stack initProcesses_ProcCountOffsets = new Stack<>(); + public Stack initProcesses_ExpandedSizes = new Stack<>(); + public Stack initProcesses_ContinueOpIds = new Stack<>(); + + public Map>> channelMappings = new HashMap<>(); + + public ASMGeneratorContext(LibraryInformation libraryInformation) throws Exception { + this.libraryInformation = libraryInformation; + + initGlobalVariables(); + } + + public ILBlock getCurrentILBlock() { + return currentILBlock; + } + public void setCurrentILBlock(ILBlock value) { + currentILBlock = value; + setCurrentFunction((Function)libraryInformation.getScopeById(currentILBlock.getScopeId())); + } + + public ASMBlock getCurrentASMBlock() { + return currentASMBlock; + } + public void setCurrentASMBlock(ASMBlock block) { + currentASMBlock = block; + } + + public Function getCurrentFunction() { + return currentFunction; + } + public void setCurrentFunction(Function value) { + currentFunction = value; + currentWorkspace = currentFunction.getWorkspace(); + channelMappings.clear(); + channelMappings.put(currentFunction.getWorkspace().getId(), new HashMap<>()); + stackBranches = new ArrayList<>(); + currentStackBranch = new StackBranch(); + stackBranches.add(currentStackBranch); + } + + public List getStartingProcessesWorkspaceIds() { + return startingProcessesWorkspaceIds; + } + public void setStartingProcessesWorkspaceIds(List value) { + // Shallow clone to prevent accidental corruption of InitProcess IL ops + startingProcessesWorkspaceIds = new ArrayList<>(value); + } + + public Workspace getCurrentWorkspace() { + return currentWorkspace; + } + public void addWorkspaceTransition(TIdentifier targetId, Integer newWorkspaceId) { + workspaceTransitionPoints.put(targetId, newWorkspaceId); + channelMappings.put(newWorkspaceId, new HashMap<>()); + } + + public void checkForWorkspaceTransition(TILOp op) { + if (workspaceTransitionPoints.containsKey(op.getId())) { + Integer newWorkspaceId = workspaceTransitionPoints.remove(op.getId()); + currentWorkspace = currentFunction.getWorkspaceById(newWorkspaceId); + } + } + + public void setChannel(Integer index, String name, String typeName) { + channelMappings.get(currentWorkspace.getId()).put(index, new AbstractMap.SimpleImmutableEntry<>(name,typeName)); + } + public Map.Entry getChannel(Integer index) { + return channelMappings.get(currentWorkspace.getId()).get(index); + } + + public void updateCurrentStackBranch(int currentPosition) { + List branches = new ArrayList<>(stackBranches); + branches.removeIf((StackBranch branch) -> branch.from > currentPosition); + branches.sort((StackBranch b1, StackBranch b2) -> Integer.compare(b1.from, b2.from)); + currentStackBranch = branches.get(branches.size() - 1); + } + public void forkCurrentState(int targetPosition) { + stackBranches.add(currentStackBranch.fork(targetPosition)); + } + public StackItem pushToEvaluationStack(TIdentifier currentOpId, int itemIndex) { + return currentStackBranch.pushToEvaluationStack(new StackItem(currentOpId, itemIndex)); + } + public StackItem pushToEvaluationStack(StackItem item) { + return currentStackBranch.pushToEvaluationStack(item); + } + public StackItem popFromEvaluationStack() { + return currentStackBranch.popFromEvaluationStack(); + } + public int getEvaluationStackSize() { + return currentStackBranch.getStackSize(); + } + + public String generateILOpLabel(ILOp op) { + return generateILOpLabel(op.getId()); + } + public String generateILOpLabel(TIdentifier id) { + return getCurrentFunction().getName() + "~IL_" + id.toString(); + } + + public String generateGlobalRepresentation(String expression) { + if (expression.startsWith("#")) { + return expression; + } else { + return generateGlobalVariableLabel(expression); + } + } + public String generateGlobalVariableLabel(Variable variable) { + return generateGlobalVariableLabel(variable.getName()); + } + public String generateGlobalVariableLabel(String variableName) { + return "GlobalVariable_" + variableName; + } + + public ASMBlock getGlobalsBlock() { + return globalsBlock; + } + public void initGlobalVariables() throws Exception { + for (FileInformation fileInfo : libraryInformation.getFileInfos()) { + for (Variable variable : fileInfo.getVariablesInWorkspaceAndBelow()) { + String variableLabel = generateGlobalVariableLabel(variable); + globalsBlock.addOp(new Label(variableLabel)); + + String variableTypeName = variable.getTypeName(); + globalsBlock.addOp(new Data(libraryInformation.getTypeSize(variableTypeName))); + } + } + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/ASMGeneratorHelpers.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/ASMGeneratorHelpers.java new file mode 100644 index 0000000..9eeabf7 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/ASMGeneratorHelpers.java @@ -0,0 +1,621 @@ +package uk.co.transputersystems.occam.open_transputer; + +import uk.co.transputersystems.occam.il.ILOp; +import uk.co.transputersystems.occam.metadata.Argument; +import uk.co.transputersystems.occam.metadata.Scope; +import uk.co.transputersystems.occam.metadata.Workspace; +import uk.co.transputersystems.occam.open_transputer.assembly.*; + +import java.util.*; + +public class ASMGeneratorHelpers { + + public static int calculateStaticChainDistance(Workspace ownerWorkspace, Workspace currentWorkspace) { + // See Compiler Writer's Guide page 32 : 5.10.3 The static chain + + int distance = 0; + int ownerWorkspaceId = ownerWorkspace.getId(); + int lastWorkspaceId = currentWorkspace.getId(); + while (lastWorkspaceId != ownerWorkspaceId) { + currentWorkspace = currentWorkspace.getParent(); + if (currentWorkspace == null) { + throw new IllegalAccessError("Climbed too high in static workspace chain!"); + } + + if (lastWorkspaceId != currentWorkspace.getId()) { + distance++; + } + lastWorkspaceId = currentWorkspace.getId(); + } + + return distance; + } + + public static boolean climbStaticChain(List result, Workspace currentWorkspace, Workspace ownerWorkspace, ASMGeneratorContext> context, boolean preProcess) { + // Calculate distance from current WS to owner WS in terms of WS jumps (i.e. static chain distance) + int workspacesToClimb = ASMGeneratorHelpers.calculateStaticChainDistance(ownerWorkspace, currentWorkspace); + // Whether the variable is local to the current WS or not + boolean isLocal = workspacesToClimb == 0; + + // If not local, climb the static chain + if (!isLocal) { + Workspace tempWorkspace = currentWorkspace; + for (int i = 0; i < workspacesToClimb; i++) { + // Parent workspace pointer is always held at max offset within the child workspace + int parentWSPtrOffset = currentWorkspace.getOffset(Integer.MIN_VALUE); + + if (i == 0) { + // Load local if starting from actual current workspace + context.pushToEvaluationStack(-3, -1); + result.add(new Ldl(parentWSPtrOffset)); + } else { + // Load non-local if climbing through a remote workspace + context.popFromEvaluationStack(); + context.pushToEvaluationStack(-3, -1); + result.add(new Ldnl(parentWSPtrOffset)); + } + + tempWorkspace = tempWorkspace.getParent(); + } + } + return isLocal; + } + + public static int getFullWorkspaceSize(ASMGeneratorContext> context, Scope wsScope) { + //TODO: This size has to take into account the required workspace size of all functions called from within the current workspace + // This will require a dependency tree between IL blocks. No circular references can occur due to lack of recursion in Occam + // so process tree bottom-up + return getFullWorkspaceSize(context, wsScope, -1); + } + public static int getFullWorkspaceSize(ASMGeneratorContext> context, Scope scope, int parentWSId) { + int result = 0; + if (scope.getWorkspace().getId() != parentWSId) { + result += scope.getWorkspace().getFullSize(); + } + + int newParentWSId = scope.getWorkspace().getId(); + for (Scope child : scope.getChildren()) { + result += getFullWorkspaceSize(context, child, newParentWSId); + } + + return result; + } + + public static List processConditionalBranch_True(Integer targetId, ILOp currentOp, ASMGeneratorContext> context, boolean preProcess) { + // Pre-op code for both process and preprocess + + // Eqc + + List popOps = processPops(1, currentOp, context, preProcess); + context.pushToEvaluationStack(currentOp.getId(), -1); + + List result; + if (preProcess) { + // Code for preprocess only + + ILOp target = context.getCurrentILBlock().get(targetId); + target.setRequiresLabel(true); + target.setRequiresPopAfterLabel(true); + + result = null; + } else { + // Code for process only + + result = new ArrayList<>(); + result.addAll(popOps); + result.add(new Eqc(0)); + result.add(new Cj(context.generateILOpLabel(targetId) + "-$0")); + } + + // Post-op code for both process and preprocess + + // Branch + context.forkCurrentState(targetId); + + // Continuation + context.popFromEvaluationStack(); + + return result; + } + public static List processConditionalBranch_False(Integer targetId, ILOp currentOp, ASMGeneratorContext> context, boolean preProcess) { + // Pre-op code for both process and preprocess + + List popOps = processPops(1, currentOp, context, preProcess); + context.pushToEvaluationStack(currentOp.getId(), -1); + + List result; + if (preProcess) { + // Code for preprocess only + + ILOp target = context.getCurrentILBlock().get(targetId); + target.setRequiresLabel(true); + target.setRequiresPopAfterLabel(true); + + result = null; + } else { + // Code for process only + + result = new ArrayList<>(); + result.addAll(popOps); + result.add(new Cj(context.generateILOpLabel(targetId) + "-$0")); + } + + // Post-op code for both process and preprocess + + // Branch + context.forkCurrentState(targetId); + + // Continuation + context.popFromEvaluationStack(); + + return result; + } + + public static List processStoreArgument(int itemIndex, ILOp currentOp, ASMGeneratorContext> context, boolean preProcess) { + // Pre-op code for both process and preprocess + + Workspace currentWorkspace = context.getCurrentWorkspace(); + Workspace ownerWorkspace = currentWorkspace.getOwner(itemIndex); + Argument argument = context.getCurrentFunction().getArgument(itemIndex); + + List result = new ArrayList<>(); + + boolean isLocal = ASMGeneratorHelpers.climbStaticChain(result, currentWorkspace, ownerWorkspace, context, preProcess); + + List popOps; + + /* + * Combinations: + * Store Argument + * Local + * ArgByRef + * [Store value of argument by doing then ] + * + * ArgByValue + * [Load value of argument by doing ] + * + * Non-local + * ArgByRef + * [Load value of argument by doing then ] + * + * ArgByValue + * [Load value of argument by doing ] + * + */ + if (isLocal) { + popOps = processPops(1, currentOp, context, preProcess); + } else { + context.popFromEvaluationStack(); + popOps = processPops(1, currentOp, context, preProcess); + } + + if (preProcess) { + // Code for preprocess only + + result = null; + } else { + // Code for process only + + result.addAll(popOps); + + int varWSOffset = ownerWorkspace.getOffset(itemIndex); + + if (isLocal) { + if (!argument.getPassByValue()) { + result.add(new Ldl(varWSOffset)); + result.add(new Stnl(0)); + } else { + result.add(new Stl(varWSOffset)); + } + } else { + if (!argument.getPassByValue()) { + result.add(new Ldnl(varWSOffset)); + result.add(new Stnl(0)); + } else { + result.add(new Stnl(varWSOffset)); + } + } + } + + // Post-op code for both process and preprocess + + return result; + } + public static List processStoreLocal(int itemIndex, ILOp currentOp, ASMGeneratorContext> context, boolean preProcess) { + // Pre-op code for both process and preprocess + + Workspace currentWorkspace = context.getCurrentWorkspace(); + Workspace ownerWorkspace = currentWorkspace.getOwner(itemIndex); + + List result = new ArrayList<>(); + + boolean isLocal = ASMGeneratorHelpers.climbStaticChain(result, currentWorkspace, ownerWorkspace, context, preProcess); + + List popOps; + + if (isLocal) { + popOps = processPops(1, currentOp, context, preProcess); + } else { + context.popFromEvaluationStack(); + popOps = processPops(1, currentOp, context, preProcess); + } + + if (preProcess) { + // Code for preprocess only + + result = null; + } else { + // Code for process only + + result.addAll(popOps); + + int varWSOffset = ownerWorkspace.getOffset(itemIndex); + if (isLocal) { + result.add(new Stl(varWSOffset)); + } else { + result.add(new Stnl(varWSOffset)); + } + } + + // Post-op code for both process and preprocess + + return result; + } + public static List processLoadArgument(int itemIndex, ILOp currentOp, ASMGeneratorContext> context, boolean preProcess, boolean loadAddress) { + // Pre-op code for both process and preprocess + + Workspace currentWorkspace = context.getCurrentWorkspace(); + Workspace ownerWorkspace = currentWorkspace.getOwner(itemIndex); + Argument argument = context.getCurrentFunction().getArgument(itemIndex); + + List result = new ArrayList<>(); + + boolean isLocal = ASMGeneratorHelpers.climbStaticChain(result, currentWorkspace, ownerWorkspace, context, preProcess); + + List pushOps; + + /* + * Combinations: + * Load Argument + * Local + * ArgByRef + * [Load value of argument by doing then ] + * + * ArgByValue + * [Load value of argument by doing ] + * + * Non-local + * ArgByRef + * [Load value of argument by doing then ] + * + * ArgByValue + * [Load value of argument by doing ] + * + * Load Argument by Address + * Local + * ArgByRef + * [Load address of argument by doing ] + * + * ArgByValue + * [Load address of argument by doing ] + * + * Non-local + * ArgByRef + * [Load address of argument by doing ] + * + * ArgByValue + * [Load address of argument by doing nothing extra] + * + */ + if (!loadAddress) { + if (isLocal) { + if (!argument.getPassByValue()) { + pushOps = processPushes(1, currentOp, context, preProcess); + } else { + pushOps = processPushes(1, currentOp, context, preProcess); + } + } else { + if (!argument.getPassByValue()) { + pushOps = processPushes(1, currentOp, context, preProcess); + } else { + pushOps = processPushes(1, currentOp, context, preProcess); + } + } + } else { + if (isLocal) { + if (!argument.getPassByValue()) { + pushOps = processPushes(1, currentOp, context, preProcess); + } else { + pushOps = processPushes(1, currentOp, context, preProcess); + } + } else { + if (!argument.getPassByValue()) { + pushOps = processPushes(1, currentOp, context, preProcess); + } else { + // Nothing extra + pushOps = new ArrayList<>(); + } + } + } + + if (preProcess) { + // Code for preprocess only + + result = null; + } else { + // Code for process only + + int varWSOffset = ownerWorkspace.getOffset(itemIndex); + + if (!loadAddress) { + if (isLocal) { + if (!argument.getPassByValue()) { + result.add(new Ldl(varWSOffset)); + result.add(new Ldnl(0)); + } else { + result.add(new Ldl(varWSOffset)); + } + } else { + if (!argument.getPassByValue()) { + result.add(new Ldnl(varWSOffset)); + result.add(new Ldnl(0)); + } else { + result.add(new Ldnl(varWSOffset)); + } + } + } else { + if (isLocal) { + if (!argument.getPassByValue()) { + result.add(new Ldl(varWSOffset)); + } else { + result.add(new Ldlp(varWSOffset)); + } + } else { + if (!argument.getPassByValue()) { + result.add(new Ldnl(varWSOffset)); + } else { + // Nothing extra + } + } + } + + result.addAll(pushOps); + } + + // Post-op code for both process and preprocess + + return result; + } + public static List processLoadLocal(int itemIndex, ILOp currentOp, ASMGeneratorContext> context, boolean preProcess, boolean loadAddress) { + // Pre-op code for both process and preprocess + + Workspace currentWorkspace = context.getCurrentWorkspace(); + Workspace ownerWorkspace = currentWorkspace.getOwner(itemIndex); + + List result = new ArrayList<>(); + + boolean isLocal = ASMGeneratorHelpers.climbStaticChain(result, currentWorkspace, ownerWorkspace, context, preProcess); + + List pushOps; + + if (isLocal) { + pushOps = processPushes(1, currentOp, context, preProcess); + } else if (!loadAddress) { + context.popFromEvaluationStack(); + pushOps = processPushes(1, currentOp, context, preProcess); + } else { + context.popFromEvaluationStack(); + pushOps = processPushes(1, currentOp, context, preProcess); + } + + if (preProcess) { + // Code for preprocess only + + result = null; + } else { + // Code for process only + + int varWSOffset = ownerWorkspace.getOffset(itemIndex); + if (isLocal) { + if (loadAddress) { + result.add(new Ldlp(varWSOffset)); + } else { + result.add(new Ldl(varWSOffset)); + } + } else if (!loadAddress) { + result.add(new Ldnl(varWSOffset)); + } + + result.addAll(pushOps); + } + + // Post-op code for both process and preprocess + + return result; + } + + public static List processPushes(int numPushes, ILOp currentOp, ASMGeneratorContext> context, boolean preProcess) throws IndexOutOfBoundsException { + List result = null; + + if (numPushes > 3) { + throw new IndexOutOfBoundsException("Cannot push more than three items in one go!"); + } + + if (!preProcess) { + result = new ArrayList<>(); + } + + for (int i = 0; i < numPushes; i++) { + context.pushToEvaluationStack(currentOp.getId(), i); + + if (!preProcess) { + if (currentOp.storeResult(i)) { + context.getCurrentWorkspace().allocateTemporary(); + int offset = context.getCurrentWorkspace().getLastTemporaryOffset(0); + + result.add(new Stl(offset)); + context.popFromEvaluationStack(); + } + } else { + if (context.getEvaluationStackSize() > 3) { + context.getCurrentWorkspace().allocateTemporary(); + } + } + } + + return result; + } + public static List processPops(int numPops, ILOp currentOp, ASMGeneratorContext> context, boolean preProcess) throws IndexOutOfBoundsException { + List result = null; + + if (numPops > 3) { + throw new IndexOutOfBoundsException("Cannot pop more than three items in one go!"); + } + + if (preProcess) { + + for (int i = 0; i < numPops; i++) { + if (context.getEvaluationStackSize() > 3) { + context.getCurrentWorkspace().removeTemporaryFromWorkspace(); + } + + StackItem item = context.popFromEvaluationStack(); + + setupTempStore(context, item, true); + } + + } else { + + result = new ArrayList<>(); + + int size = context.getEvaluationStackSize(); + if (size < numPops) { + + switch (size) { + // Case 0 : Empty register stack + case 0: + // Just load the items in order + for (int i = 0; i < numPops; i++) { + int offset = context.getCurrentWorkspace().getLastTemporaryOffset(0); + context.getCurrentWorkspace().removeTemporaryFromWorkspace(); + + context.pushToEvaluationStack(-1, -1); + result.add(new Ldl(offset)); + } + break; + + // Case 1 : 1 item on register stack + case 1: + // Load each item but reverse top 2 items after each in order to keep correct ordering + for (int i = 0; i < numPops-1; i++) { + int offset = context.getCurrentWorkspace().getLastTemporaryOffset(0); + context.getCurrentWorkspace().removeTemporaryFromWorkspace(); + + context.pushToEvaluationStack(-1, -1); + result.add(new Ldl(offset)); + + result.add(new Rev()); + } + break; + + // Case 2 : 2 items on register stack + case 2: + // Trying to load a single item into CReg + // Store AReg + // Load value for CReg + // Reverse top two items + // Restore AReg + + { + result.add(new Stl(0)); + + int offset = context.getCurrentWorkspace().getLastTemporaryOffset(0); + context.getCurrentWorkspace().removeTemporaryFromWorkspace(); + + context.pushToEvaluationStack(-1, -1); + result.add(new Ldl(offset)); + + result.add(new Rev()); + result.add(new Ldl(0)); + } + break; + + default: + throw new IndexOutOfBoundsException("Stack size during processing mustn't go larger than 3!"); + } + } + + for (int i = 0; i < numPops; i++) { + context.popFromEvaluationStack(); + } + } + + return result; + } + public static void setupTempStore(ASMGeneratorContext> context, StackItem item, boolean removeIfAllocated) { + if (item.getMaxDepth() > 3) { + context.getCurrentILBlock().get(item.createdAt).setStoreResult(item.index); + int count = (item.getMaxDepth() - 3) - context.getCurrentWorkspace().getMaxTempsSize(); + for (int j = 0; j < count; j++) { + context.getCurrentWorkspace().allocateTemporary(); + } + if (removeIfAllocated) { + for (int j = 0; j < count; j++) { + context.getCurrentWorkspace().removeTemporaryFromWorkspace(); + } + } + } + } + + public static List processDisable(Integer target, Integer endAlt, ASMOp disableOp, ILOp op, ASMGeneratorContext> context, boolean preProcess) { + // Pre-op code for both process and preprocess + List pushOps1 = ASMGeneratorHelpers.processPushes(1, op, context, preProcess); + List popOps = ASMGeneratorHelpers.processPops(disableOp instanceof Diss ? 2 : 3, op, context, preProcess); + List pushOps2 = ASMGeneratorHelpers.processPushes(1, op, context, preProcess); + + List result; + if (preProcess) { + // Code for preprocess only + + context.getCurrentILBlock().get(target).setRequiresLabel(true); + context.getCurrentILBlock().get(endAlt).setRequiresLabel(true); + + result = null; + } else { + // Code for process only + + result = new ArrayList<>(); + /*Start of guarded process - Byte after altend instruction*/ + result.add(new Ldc( context.generateILOpLabel(target) + "-" + context.generateILOpLabel(endAlt))); + result.addAll(pushOps1); + result.addAll(popOps); + result.add(disableOp); + result.addAll(pushOps2); + } + + // Post-op code for both process and preprocess + + return result; + } + public static List processEnable(ASMOp enableOp, ILOp op, ASMGeneratorContext> context, boolean preProcess) { + // Pre-op code for both process and preprocess + List popOps = ASMGeneratorHelpers.processPops(enableOp instanceof Enbs ? 1 : 2, op, context, preProcess); + + List result; + if (preProcess) { + // Code for preprocess only + + result = null; + } else { + // Code for process only + + result = new ArrayList<>(); + result.addAll(popOps); + result.add(enableOp); + } + + // Post-op code for both process and preprocess + + return result; + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/ASMOpFormatter.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/ASMOpFormatter.java new file mode 100644 index 0000000..06658a2 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/ASMOpFormatter.java @@ -0,0 +1,14 @@ +package uk.co.transputersystems.occam.open_transputer; + +import uk.co.transputersystems.occam.StringUtilities; +import uk.co.transputersystems.occam.open_transputer.assembly.ASMOp; + +public class ASMOpFormatter { + /** + * Format the details of an ILOp into a human-readable string. + * @return A human-readable string representing the ILOp. + */ + public static String formatOp(ASMOp op) { + return StringUtilities.padRight(op.name, 12) + (op.data != null ? op.data.toString() : ""); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/DependencyTree.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/DependencyTree.java new file mode 100644 index 0000000..6920658 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/DependencyTree.java @@ -0,0 +1,120 @@ +package uk.co.transputersystems.occam.open_transputer; + +import uk.co.transputersystems.occam.il.*; + +import java.util.*; + +/** + * Created by Ed on 16/04/2016. + */ +public class DependencyTree { + private class Node { + public final String functionName; + public final ILBlock> block; + public List calledFunctions = new ArrayList<>(); + public List children = new ArrayList<>(); + public boolean called = false; + public boolean visited = false; + + public Node(String functionName, ILBlock> block, List calledFunctions) { + this.functionName = functionName; + this.block = block; + this.calledFunctions = calledFunctions; + } + + public List>> flatten() { + if (visited) { + return Collections.emptyList(); + } + + visited = true; + + List>> result = new ArrayList<>(); + + for (Node child : children) { + List>> childResult = child.flatten(); + for (ILBlock> block : childResult) { + if (!result.contains(block)) { + result.add(block); + } + } + } + + result.add(block); + + return result; + } + } + + private Map nodes = new HashMap<>(); + + public DependencyTree(List>> ilBlocks) { + load(ilBlocks); + } + private void load(List>> ilBlocks) { + for (ILBlock> ilBlock : ilBlocks) { + String functionName = getFunctionName(ilBlock); + List calledFunctions = getCalledFunctionNames(ilBlock); + nodes.put(functionName, new Node(functionName, ilBlock, calledFunctions)); + } + } + public List>> flatten() { + convert(); + + List>> result = new ArrayList<>(); + + for (Node child : nodes.values()) { + if (!child.called) { + List>> childResult = child.flatten(); + for (ILBlock> block : childResult) { + if (!result.contains(block)) { + result.add(block); + } + } + } + } + + return result; + } + private void convert() { + for (Node node : nodes.values()) { + node.children = convertFunctionNames(node.calledFunctions); + } + } + private List convertFunctionNames(List functionNames) { + List result = new ArrayList<>(); + + for (String functionName : functionNames) { + Node node = nodes.get(functionName); + node.called = true; + result.add(node); + } + + return result; + } + + private String getFunctionName(ILBlock> ilBlock) { + Label lastLabel = null; + for (ILOp op : ilBlock.getAll()) { + if (op instanceof Label) { + lastLabel = (Label)op; + } else if (op instanceof MethodStart) { + return lastLabel.label; + } + } + + return null; + } + private List getCalledFunctionNames(ILBlock> ilBlock) { + List result = new ArrayList<>(); + + for (ILOp op : ilBlock.getAll()) { + if (op instanceof Call) { + Call callOp = (Call)op; + result.add(callOp.functionName); + } + } + + return result; + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/StackBranch.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/StackBranch.java new file mode 100644 index 0000000..b3c7dc4 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/StackBranch.java @@ -0,0 +1,28 @@ +package uk.co.transputersystems.occam.open_transputer; + +/** + * Created by Ed on 31/03/2016. + */ +public class StackBranch> { + public int from = 0; + + private StackTracker tracker = new StackTracker<>(); + + public TItem pushToEvaluationStack(TItem item) { + return tracker.push(item); + } + public TItem popFromEvaluationStack() { + return tracker.pop(); + } + + public int getStackSize() { + return tracker.size(); + } + + public StackBranch fork(int from) { + StackBranch result = new StackBranch(); + result.tracker = new StackTracker<>(tracker.listIterator()); + result.from = from; + return result; + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/StackItem.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/StackItem.java new file mode 100644 index 0000000..787ca85 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/StackItem.java @@ -0,0 +1,40 @@ +package uk.co.transputersystems.occam.open_transputer; + +/** + * Created by Ed on 17/04/2016. + */ +public class StackItem { + private int maxDepth; + private int depth; + public final int index; + + public final TIdentifier createdAt; + + public StackItem(TIdentifier createdAt, int index) { + this.createdAt = createdAt; + this.index = index; + } + public StackItem(StackItem original) { + this.createdAt = original.createdAt; + this.index = original.index; + this.depth = original.depth; + this.maxDepth = original.maxDepth; + } + + public int getMaxDepth() { + return maxDepth; + } + + public void increaseDepth() { + depth++; + if (depth > maxDepth) { + maxDepth = depth; + } + } + public void decreaseDepth() throws IndexOutOfBoundsException { + depth--; + if (depth < 0) { + throw new IndexOutOfBoundsException("Stack item depth < 0!"); + } + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/StackTracker.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/StackTracker.java new file mode 100644 index 0000000..d5f7540 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/StackTracker.java @@ -0,0 +1,40 @@ +package uk.co.transputersystems.occam.open_transputer; + +import java.util.ListIterator; +import java.util.Stack; + +/** + * Created by Ed on 17/04/2016. + */ +public class StackTracker> extends Stack { + + public StackTracker() { + super(); + } + public StackTracker(ListIterator items){ + super(); + + while(items.hasNext()) { + super.push((E)new StackItem<>(items.next())); + } + } + + @Override + public E push(E item) { + ListIterator iterator = this.listIterator(); + while(iterator.hasNext()) { + iterator.next().increaseDepth(); + } + item.increaseDepth(); + return super.push(item); + } + + @Override + public synchronized E pop() throws IndexOutOfBoundsException { + ListIterator iterator = this.listIterator(); + while(iterator.hasNext()) { + iterator.next().decreaseDepth(); + } + return super.pop(); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/ASMOp.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/ASMOp.java new file mode 100644 index 0000000..8a6132a --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/ASMOp.java @@ -0,0 +1,11 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public abstract class ASMOp { + final public TData data; + final public String name; + + public ASMOp(TData data, String name) { + this.data = data; + this.name = name; + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Adc.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Adc.java new file mode 100644 index 0000000..4154714 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Adc.java @@ -0,0 +1,10 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +/** + * Add a constant to `Areg`. Checked overflow. + */ +public class Adc extends ASMOp { + public Adc(int data) { + super(data, "adc"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Add.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Add.java new file mode 100644 index 0000000..6c19c4b --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Add.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Add extends ASMOp { + public Add() { + super(null, "add"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Ajw.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Ajw.java new file mode 100644 index 0000000..fef3cf6 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Ajw.java @@ -0,0 +1,8 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + + +public class Ajw extends ASMOp { + public Ajw(int data) { + super(data, "ajw"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Alt.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Alt.java new file mode 100644 index 0000000..f68e848 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Alt.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Alt extends ASMOp { + public Alt() { + super(null, "alt"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Altend.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Altend.java new file mode 100644 index 0000000..ab36e0f --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Altend.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Altend extends ASMOp { + public Altend() { + super(null, "altend"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Altwt.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Altwt.java new file mode 100644 index 0000000..2f4ab8b --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Altwt.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Altwt extends ASMOp { + public Altwt() { + super(null, "altwt"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/And.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/And.java new file mode 100644 index 0000000..98b6379 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/And.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class And extends ASMOp { + public And() { + super(null, "and"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Bcnt.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Bcnt.java new file mode 100644 index 0000000..a67341c --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Bcnt.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Bcnt extends ASMOp { + public Bcnt(byte data) { + super(data, "bcnt"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Bitcnt.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Bitcnt.java new file mode 100644 index 0000000..d945f40 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Bitcnt.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Bitcnt extends ASMOp { + public Bitcnt(byte data) { + super(data, "bitcnt"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Bitrevnbits.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Bitrevnbits.java new file mode 100644 index 0000000..8398d51 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Bitrevnbits.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Bitrevnbits extends ASMOp { + public Bitrevnbits(byte data) { + super(data, "bitrevnbits"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Bitrevword.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Bitrevword.java new file mode 100644 index 0000000..04d0695 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Bitrevword.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Bitrevword extends ASMOp { + public Bitrevword(byte data) { + super(data, "bitrevword"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Bsub.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Bsub.java new file mode 100644 index 0000000..869d6ad --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Bsub.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Bsub extends ASMOp { + public Bsub(byte data) { + super(data, "bsub"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Call.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Call.java new file mode 100644 index 0000000..d192ea0 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Call.java @@ -0,0 +1,8 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + + +public class Call extends ASMOp { + public Call(String targetName) { + super(targetName, "call"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Ccnt1.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Ccnt1.java new file mode 100644 index 0000000..a34ed2f --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Ccnt1.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Ccnt1 extends ASMOp { + public Ccnt1(byte data) { + super(data, "ccnt1"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Cflerr.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Cflerr.java new file mode 100644 index 0000000..d0840d0 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Cflerr.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Cflerr extends ASMOp { + public Cflerr(byte data) { + super(data, "cflerr"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Channel.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Channel.java new file mode 100644 index 0000000..fad6458 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Channel.java @@ -0,0 +1,10 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +/** + * Created by Edward on 02/05/2016. + */ +public class Channel extends ASMOp { + public Channel(String name) { + super(name, "#chan"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Cj.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Cj.java new file mode 100644 index 0000000..016ec56 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Cj.java @@ -0,0 +1,8 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + + +public class Cj extends ASMOp { + public Cj(String target) { + super(target, "cj"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Clrhalterr.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Clrhalterr.java new file mode 100644 index 0000000..b69970e --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Clrhalterr.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Clrhalterr extends ASMOp { + public Clrhalterr(byte data) { + super(data, "clrhalterr"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Crcbyte.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Crcbyte.java new file mode 100644 index 0000000..c58fec4 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Crcbyte.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Crcbyte extends ASMOp { + public Crcbyte(byte data) { + super(data, "crcbyte"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Crcword.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Crcword.java new file mode 100644 index 0000000..b65f3b7 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Crcword.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Crcword extends ASMOp { + public Crcword(byte data) { + super(data, "crcword"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Csngl.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Csngl.java new file mode 100644 index 0000000..74fa547 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Csngl.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Csngl extends ASMOp { + public Csngl(byte data) { + super(data, "csngl"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Csub0.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Csub0.java new file mode 100644 index 0000000..cd0eb5a --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Csub0.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Csub0 extends ASMOp { + public Csub0(byte data) { + super(data, "csub0"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Cword.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Cword.java new file mode 100644 index 0000000..bd0e039 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Cword.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Cword extends ASMOp { + public Cword(byte data) { + super(data, "cword"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Data.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Data.java new file mode 100644 index 0000000..daff708 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Data.java @@ -0,0 +1,8 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + + +public class Data extends ASMOp { + public Data(int words) { + super(words, "#data"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Diff.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Diff.java new file mode 100644 index 0000000..5d19520 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Diff.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Diff extends ASMOp { + public Diff() { + super(null, "diff"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Disc.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Disc.java new file mode 100644 index 0000000..aa6fcd1 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Disc.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Disc extends ASMOp { + public Disc() { + super(null, "disc"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Diss.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Diss.java new file mode 100644 index 0000000..fd4b799 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Diss.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Diss extends ASMOp { + public Diss() { + super(null, "diss"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Dist.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Dist.java new file mode 100644 index 0000000..680b24e --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Dist.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Dist extends ASMOp { + public Dist() { + super(null, "dist"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Div.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Div.java new file mode 100644 index 0000000..496564e --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Div.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Div extends ASMOp { + public Div() { + super(null, "div"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Dup.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Dup.java new file mode 100644 index 0000000..d82cd87 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Dup.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Dup extends ASMOp { + public Dup() { + super(null, "dup"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Enbc.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Enbc.java new file mode 100644 index 0000000..00a3e92 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Enbc.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Enbc extends ASMOp { + public Enbc() { + super(null, "enbc"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Enbs.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Enbs.java new file mode 100644 index 0000000..7d9afd5 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Enbs.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Enbs extends ASMOp { + public Enbs() { + super(null, "enbs"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Enbt.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Enbt.java new file mode 100644 index 0000000..e3a2030 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Enbt.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Enbt extends ASMOp { + public Enbt() { + super(null, "enbt"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Endp.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Endp.java new file mode 100644 index 0000000..ac89ca8 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Endp.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Endp extends ASMOp { + public Endp() { + super(null, "endp"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Eqc.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Eqc.java new file mode 100644 index 0000000..ad50368 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Eqc.java @@ -0,0 +1,8 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + + +public class Eqc extends ASMOp { + public Eqc(int data) { + super(data, "eqc"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Fmul.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Fmul.java new file mode 100644 index 0000000..d5e0490 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Fmul.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Fmul extends ASMOp { + public Fmul(byte data) { + super(data, "fmul"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Gajw.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Gajw.java new file mode 100644 index 0000000..89922f7 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Gajw.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Gajw extends ASMOp { + public Gajw(byte data) { + super(data, "gajw"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Gcall.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Gcall.java new file mode 100644 index 0000000..5f33685 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Gcall.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Gcall extends ASMOp { + public Gcall(byte data) { + super(data, "gcall"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Gt.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Gt.java new file mode 100644 index 0000000..aae59a6 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Gt.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Gt extends ASMOp { + public Gt() { + super(null, "gt"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/In.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/In.java new file mode 100644 index 0000000..f1df608 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/In.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class In extends ASMOp { + public In() { + super(null, "In"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/J.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/J.java new file mode 100644 index 0000000..e260458 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/J.java @@ -0,0 +1,8 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + + +public class J extends ASMOp { + public J(byte data) { + super(data, "J"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Label.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Label.java new file mode 100644 index 0000000..d2d98a9 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Label.java @@ -0,0 +1,16 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +/** + * Create a label marker + */ +public class Label extends ASMOp { + public String id; + public Label ( int id) { + super("", id+":"); + this.id = "L" + Integer.toString(id); + } + public Label ( String id ) { + super("", id+":"); + this.id = id; + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Ladd.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Ladd.java new file mode 100644 index 0000000..22c9c88 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Ladd.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Ladd extends ASMOp { + public Ladd(byte data) { + super(data, "Ladd"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Lb.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Lb.java new file mode 100644 index 0000000..8950f32 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Lb.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Lb extends ASMOp { + public Lb(byte data) { + super(data, "Lb"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Ldc.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Ldc.java new file mode 100644 index 0000000..199a235 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Ldc.java @@ -0,0 +1,17 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Ldc extends ASMOp { + + public String valueExpression = null; + + public Ldc(int data) { + super(data, "ldc"); + } + public Ldc(long data) { + super(data, "ldc"); + } + + public Ldc(String valueExpression) { + super(valueExpression, "ldc"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Ldiff.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Ldiff.java new file mode 100644 index 0000000..2949d83 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Ldiff.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Ldiff extends ASMOp { + public Ldiff(byte data) { + super(data, "ldiff"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Ldinf.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Ldinf.java new file mode 100644 index 0000000..6dc50d8 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Ldinf.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Ldinf extends ASMOp { + public Ldinf(byte data) { + super(data, "ldinf"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Ldiv.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Ldiv.java new file mode 100644 index 0000000..8f1edae --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Ldiv.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Ldiv extends ASMOp { + public Ldiv(byte data) { + super(data, "ldiv"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Ldl.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Ldl.java new file mode 100644 index 0000000..4084df6 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Ldl.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Ldl extends ASMOp { + public Ldl(int data) { + super(data, "ldl"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Ldlp.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Ldlp.java new file mode 100644 index 0000000..a69b5ef --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Ldlp.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Ldlp extends ASMOp { + public Ldlp(int data) { + super(data, "ldlp"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Ldnl.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Ldnl.java new file mode 100644 index 0000000..a4db8e7 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Ldnl.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Ldnl extends ASMOp { + public Ldnl(int data) { + super(data, "ldnl"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Ldnlp.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Ldnlp.java new file mode 100644 index 0000000..4893c09 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Ldnlp.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Ldnlp extends ASMOp { + public Ldnlp(int data) { + super(data, "ldnlp"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Ldpi.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Ldpi.java new file mode 100644 index 0000000..ed22941 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Ldpi.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Ldpi extends ASMOp { + public Ldpi() { + super(null, "ldpi"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Ldpri.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Ldpri.java new file mode 100644 index 0000000..36a9bcf --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Ldpri.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Ldpri extends ASMOp { + public Ldpri(byte data) { + super(data, "ldpri"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Ldtimer.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Ldtimer.java new file mode 100644 index 0000000..cba388a --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Ldtimer.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Ldtimer extends ASMOp { + public Ldtimer() { + super(null, "ldtimer"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Lend.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Lend.java new file mode 100644 index 0000000..300846e --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Lend.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Lend extends ASMOp { + public Lend(byte data) { + super(data, "lend"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Lmul.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Lmul.java new file mode 100644 index 0000000..2c84469 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Lmul.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Lmul extends ASMOp { + public Lmul(byte data) { + super(data, "lmul"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Lshl.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Lshl.java new file mode 100644 index 0000000..8562889 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Lshl.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Lshl extends ASMOp { + public Lshl(byte data) { + super(data, "lshl"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Lshr.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Lshr.java new file mode 100644 index 0000000..809f45e --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Lshr.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Lshr extends ASMOp { + public Lshr(byte data) { + super(data, "lshr"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Lsub.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Lsub.java new file mode 100644 index 0000000..104566f --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Lsub.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Lsub extends ASMOp { + public Lsub(byte data) { + super(data, "lsub"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Lsum.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Lsum.java new file mode 100644 index 0000000..bfbb7f0 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Lsum.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Lsum extends ASMOp { + public Lsum(byte data) { + super(data, "lsum"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Mint.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Mint.java new file mode 100644 index 0000000..a6a940a --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Mint.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Mint extends ASMOp { + public Mint(byte data) { + super(data, "mint"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Move.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Move.java new file mode 100644 index 0000000..5f6d7bc --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Move.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Move extends ASMOp { + public Move(byte data) { + super(data, "move"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Move2dall.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Move2dall.java new file mode 100644 index 0000000..d0c3c07 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Move2dall.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Move2dall extends ASMOp { + public Move2dall(byte data) { + super(data, "move2dall"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Move2dinit.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Move2dinit.java new file mode 100644 index 0000000..f86a352 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Move2dinit.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Move2dinit extends ASMOp { + public Move2dinit(byte data) { + super(data, "move2dinit"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Move2dnonzero.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Move2dnonzero.java new file mode 100644 index 0000000..cfa0de1 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Move2dnonzero.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Move2dnonzero extends ASMOp { + public Move2dnonzero(byte data) { + super(data, "move2dnonzero"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Move2dzero.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Move2dzero.java new file mode 100644 index 0000000..cbe8266 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Move2dzero.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Move2dzero extends ASMOp { + public Move2dzero(byte data) { + super(data, "move2dzero"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Mul.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Mul.java new file mode 100644 index 0000000..038aa76 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Mul.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Mul extends ASMOp { + public Mul() { + super(null, "mul"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Nfix.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Nfix.java new file mode 100644 index 0000000..47f0584 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Nfix.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Nfix extends ASMOp { + public Nfix(byte data) { + super(data, "nfix"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Norm.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Norm.java new file mode 100644 index 0000000..4ace7ee --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Norm.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Norm extends ASMOp { + public Norm(byte data) { + super(data, "norm"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Not.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Not.java new file mode 100644 index 0000000..78b7e15 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Not.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Not extends ASMOp { + public Not() { + super(null, "not"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Opr.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Opr.java new file mode 100644 index 0000000..ff747a1 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Opr.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Opr extends ASMOp { + public Opr(byte data) { + super(data, "opr"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Or.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Or.java new file mode 100644 index 0000000..282c599 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Or.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Or extends ASMOp { + public Or() { + super(null, "or"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Out.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Out.java new file mode 100644 index 0000000..fb0b8b6 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Out.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Out extends ASMOp { + public Out() { + super(null, "out"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Outbyte.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Outbyte.java new file mode 100644 index 0000000..0ddf6b4 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Outbyte.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Outbyte extends ASMOp { + public Outbyte(byte data) { + super(data, "outbyte"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Outword.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Outword.java new file mode 100644 index 0000000..91bc709 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Outword.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Outword extends ASMOp { + public Outword(byte data) { + super(data, "outword"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Pfix.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Pfix.java new file mode 100644 index 0000000..0649389 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Pfix.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Pfix extends ASMOp { + public Pfix(byte data) { + super(data, "pfix"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Postnormsn.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Postnormsn.java new file mode 100644 index 0000000..4a710a1 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Postnormsn.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Postnormsn extends ASMOp { + public Postnormsn(byte data) { + super(data, "postnormsn"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Prod.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Prod.java new file mode 100644 index 0000000..9b087d0 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Prod.java @@ -0,0 +1,11 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Prod extends ASMOp { + + //TODO: OpenTransputer doesn't support unchecked multiplication + // so we're just going to override use of PROD to being MUL + // and hope that nothing blows up in our faces. Haha. + public Prod() { + super(null, "mul"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Rem.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Rem.java new file mode 100644 index 0000000..ecc2a2e --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Rem.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Rem extends ASMOp { + public Rem() { + super(null, "rem"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Resetch.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Resetch.java new file mode 100644 index 0000000..0e8b038 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Resetch.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Resetch extends ASMOp { + public Resetch(byte data) { + super(data, "resetch"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Ret.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Ret.java new file mode 100644 index 0000000..8185b20 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Ret.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Ret extends ASMOp { + public Ret() { + super(null, "ret"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Rev.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Rev.java new file mode 100644 index 0000000..86ce474 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Rev.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Rev extends ASMOp { + public Rev() { + super(null, "rev"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Roundsn.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Roundsn.java new file mode 100644 index 0000000..f00f6cf --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Roundsn.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Roundsn extends ASMOp { + public Roundsn(byte data) { + super(data, "roundsn"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Runp.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Runp.java new file mode 100644 index 0000000..a553d1a --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Runp.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Runp extends ASMOp { + public Runp(byte data) { + super(data, "runp"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Saveh.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Saveh.java new file mode 100644 index 0000000..584ca21 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Saveh.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Saveh extends ASMOp { + public Saveh(byte data) { + super(data, "saveh"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Savel.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Savel.java new file mode 100644 index 0000000..60f3e68 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Savel.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Savel extends ASMOp { + public Savel(byte data) { + super(data, "savel"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Sb.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Sb.java new file mode 100644 index 0000000..4ec1a4f --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Sb.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Sb extends ASMOp { + public Sb(byte data) { + super(data, "sb"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Seterr.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Seterr.java new file mode 100644 index 0000000..4589c70 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Seterr.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Seterr extends ASMOp { + public Seterr(byte data) { + super(data, "seterr"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Sethalterr.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Sethalterr.java new file mode 100644 index 0000000..3666ec4 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Sethalterr.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Sethalterr extends ASMOp { + public Sethalterr(byte data) { + super(data, "sethalterr"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Shl.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Shl.java new file mode 100644 index 0000000..b9c8d16 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Shl.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Shl extends ASMOp { + public Shl() { + super(null, "shl"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Shr.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Shr.java new file mode 100644 index 0000000..547ccfd --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Shr.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Shr extends ASMOp { + public Shr() { + super(null, "shr"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Startp.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Startp.java new file mode 100644 index 0000000..fa1c6be --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Startp.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Startp extends ASMOp { + public Startp() { + super(null, "startp"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Sthb.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Sthb.java new file mode 100644 index 0000000..7f9278b --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Sthb.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Sthb extends ASMOp { + public Sthb(byte data) { + super(data, "sthb"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Sthf.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Sthf.java new file mode 100644 index 0000000..b4f2034 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Sthf.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Sthf extends ASMOp { + public Sthf(byte data) { + super(data, "sthf"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Stl.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Stl.java new file mode 100644 index 0000000..9612333 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Stl.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Stl extends ASMOp { + public Stl(int data) { + super(data, "stl"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Stlb.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Stlb.java new file mode 100644 index 0000000..8dc1d8c --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Stlb.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Stlb extends ASMOp { + public Stlb(byte data) { + super(data, "stlb"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Stlf.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Stlf.java new file mode 100644 index 0000000..a125acf --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Stlf.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Stlf extends ASMOp { + public Stlf(byte data) { + super(data, "stlf"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Stnl.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Stnl.java new file mode 100644 index 0000000..f716f2f --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Stnl.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Stnl extends ASMOp { + public Stnl(int data) { + super(data, "stnl"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Stoperr.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Stoperr.java new file mode 100644 index 0000000..988ed29 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Stoperr.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Stoperr extends ASMOp { + public Stoperr(byte data) { + super(data, "stoperr"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Stopp.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Stopp.java new file mode 100644 index 0000000..7463366 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Stopp.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Stopp extends ASMOp { + public Stopp(byte data) { + super(data, "stopp"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Sttimer.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Sttimer.java new file mode 100644 index 0000000..650005d --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Sttimer.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Sttimer extends ASMOp { + public Sttimer(byte data) { + super(data, "sttimer"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Sub.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Sub.java new file mode 100644 index 0000000..6c9ff80 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Sub.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Sub extends ASMOp { + public Sub() { + super(null, "sub"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Sum.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Sum.java new file mode 100644 index 0000000..e46adfe --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Sum.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Sum extends ASMOp { + public Sum() { + super(null, "sum"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Talt.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Talt.java new file mode 100644 index 0000000..f3dd713 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Talt.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Talt extends ASMOp { + public Talt(byte data) { + super(data, "talt"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Taltwt.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Taltwt.java new file mode 100644 index 0000000..7fd748b --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Taltwt.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Taltwt extends ASMOp { + public Taltwt(byte data) { + super(data, "taltwt"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Testerr.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Testerr.java new file mode 100644 index 0000000..4af2668 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Testerr.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Testerr extends ASMOp { + public Testerr(byte data) { + super(data, "testerr"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Testhalterr.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Testhalterr.java new file mode 100644 index 0000000..94b2108 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Testhalterr.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Testhalterr extends ASMOp { + public Testhalterr(byte data) { + super(data, "testhalterr"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Testpranal.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Testpranal.java new file mode 100644 index 0000000..c7d0838 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Testpranal.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Testpranal extends ASMOp { + public Testpranal(byte data) { + super(data, "testpranal"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Tin.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Tin.java new file mode 100644 index 0000000..f332409 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Tin.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Tin extends ASMOp { + public Tin() { + super(null, "tin"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Unpacksn.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Unpacksn.java new file mode 100644 index 0000000..4a99d64 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Unpacksn.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Unpacksn extends ASMOp { + public Unpacksn(byte data) { + super(data, "unpacksn"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Wcnt.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Wcnt.java new file mode 100644 index 0000000..206a3e5 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Wcnt.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Wcnt extends ASMOp { + public Wcnt(byte data) { + super(data, "wcnt"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Wsub.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Wsub.java new file mode 100644 index 0000000..a190d75 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Wsub.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Wsub extends ASMOp { + public Wsub(byte data) { + super(data, "wsub"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Wsubdb.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Wsubdb.java new file mode 100644 index 0000000..ef1af7e --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Wsubdb.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Wsubdb extends ASMOp { + public Wsubdb(byte data) { + super(data, "wsubdb"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Xdble.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Xdble.java new file mode 100644 index 0000000..9c5c982 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Xdble.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Xdble extends ASMOp { + public Xdble(byte data) { + super(data, "xdble"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Xor.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Xor.java new file mode 100644 index 0000000..3740195 --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Xor.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Xor extends ASMOp { + public Xor() { + super(null, "xor"); + } +} diff --git a/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Xword.java b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Xword.java new file mode 100644 index 0000000..dce302a --- /dev/null +++ b/tss-occam-compiler/src/main/java/uk/co/transputersystems/occam/open_transputer/assembly/Xword.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer.assembly; + +public class Xword extends ASMOp { + public Xword(byte data) { + super(data, "xword"); + } +} diff --git a/tss-occam-compiler/src/test/java/uk/co/transputersystems/occam/TSILGeneratorHelpersTest.java b/tss-occam-compiler/src/test/java/uk/co/transputersystems/occam/TSILGeneratorHelpersTest.java new file mode 100644 index 0000000..8b5415b --- /dev/null +++ b/tss-occam-compiler/src/test/java/uk/co/transputersystems/occam/TSILGeneratorHelpersTest.java @@ -0,0 +1,49 @@ +package uk.co.transputersystems.occam; + +import org.junit.Assert; +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +public class TSILGeneratorHelpersTest { + + @Test + public void testParseCharacterLiteral() { + // Make sure the standard escape sequences return the correct ASCII values + Assert.assertEquals(TSILGeneratorHelpers.parseCharacterLiteral("*c"), (int)'\r'); + Assert.assertEquals(TSILGeneratorHelpers.parseCharacterLiteral("*C"), (int)'\r'); + Assert.assertEquals(TSILGeneratorHelpers.parseCharacterLiteral("*n"), (int)'\n'); + Assert.assertEquals(TSILGeneratorHelpers.parseCharacterLiteral("*N"), (int)'\n'); + Assert.assertEquals(TSILGeneratorHelpers.parseCharacterLiteral("*t"), (int)'\t'); + Assert.assertEquals(TSILGeneratorHelpers.parseCharacterLiteral("*T"), (int)'\t'); + Assert.assertEquals(TSILGeneratorHelpers.parseCharacterLiteral("*s"), (int)' '); + Assert.assertEquals(TSILGeneratorHelpers.parseCharacterLiteral("*S"), (int)' '); + Assert.assertEquals(TSILGeneratorHelpers.parseCharacterLiteral("*'"), (int)'\''); + Assert.assertEquals(TSILGeneratorHelpers.parseCharacterLiteral("*\""), (int)'"'); + Assert.assertEquals(TSILGeneratorHelpers.parseCharacterLiteral("**"), (int)'*'); + + // Test some hex numbers + Assert.assertEquals(TSILGeneratorHelpers.parseCharacterLiteral("*#00"), 0); + Assert.assertEquals(TSILGeneratorHelpers.parseCharacterLiteral("*#01"), 1); + Assert.assertEquals(TSILGeneratorHelpers.parseCharacterLiteral("*#6C"), 108); + Assert.assertEquals(TSILGeneratorHelpers.parseCharacterLiteral("*#7F"), 127); + + // Test some normal characters + Assert.assertEquals(TSILGeneratorHelpers.parseCharacterLiteral("a"), 97); + Assert.assertEquals(TSILGeneratorHelpers.parseCharacterLiteral("A"), 65); + Assert.assertEquals(TSILGeneratorHelpers.parseCharacterLiteral("}"), 125); + Assert.assertEquals(TSILGeneratorHelpers.parseCharacterLiteral(" "), 32); + + // Test for throwing exceptions on some illegal input + assertThatThrownBy(() -> TSILGeneratorHelpers.parseCharacterLiteral("")).isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy(() -> TSILGeneratorHelpers.parseCharacterLiteral("***")).isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy(() -> TSILGeneratorHelpers.parseCharacterLiteral("*")).isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy(() -> TSILGeneratorHelpers.parseCharacterLiteral("*nn")).isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy(() -> TSILGeneratorHelpers.parseCharacterLiteral("*a")).isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy(() -> TSILGeneratorHelpers.parseCharacterLiteral("*#")).isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy(() -> TSILGeneratorHelpers.parseCharacterLiteral("*#123")).isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy(() -> TSILGeneratorHelpers.parseCharacterLiteral("*#1")).isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy(() -> TSILGeneratorHelpers.parseCharacterLiteral("'*#01'")).isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy(() -> TSILGeneratorHelpers.parseCharacterLiteral("\n")).isInstanceOf(IllegalArgumentException.class); + } +} diff --git a/tss-occam-compiler/src/test/java/uk/co/transputersystems/occam/il/ILOpTest.java b/tss-occam-compiler/src/test/java/uk/co/transputersystems/occam/il/ILOpTest.java new file mode 100644 index 0000000..035d33e --- /dev/null +++ b/tss-occam-compiler/src/test/java/uk/co/transputersystems/occam/il/ILOpTest.java @@ -0,0 +1,50 @@ +package uk.co.transputersystems.occam.il; + +import uk.co.transputersystems.occam.ILOpFormatter; +import org.junit.Assert; +import org.junit.Test; + +import java.util.Arrays; +import java.util.UUID; + +public class ILOpTest { + + @Test + public void testFormatOp() { + // Test a normal IL Op without a calculated offset + Assert.assertEquals( + "00000000-0000-0000-0000-000000000000 : Branch (10000000-0000-0000-0000-000000000000) // This is a comment", + ILOpFormatter.formatOp( + new Branch<>(UUID.fromString("00000000-0000-0000-0000-000000000000"), UUID.fromString("10000000-0000-0000-0000-000000000000"), "This is a comment"), + new ILBlock<>() + ) + ); + + // Test an IL Op with a set of arguments that exceeds the padding for the comment without a calculated offset + Assert.assertEquals("00000000-0000-0000-0000-000000000000 : InitProcesses (10, 10000000-0000-0000-0000-000000000000, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) // aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + ILOpFormatter.formatOp( + new InitProcesses<>(UUID.fromString("00000000-0000-0000-0000-000000000000"), 10, UUID.fromString("10000000-0000-0000-0000-000000000000"), Arrays.asList(1,2,3,4,5,6,7,8,9,10), "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + new ILBlock<>() + ) + ); + + // Test an IL Op with a name that exceeds the expected padding width without a calculated offset + Assert.assertEquals("00000000-0000-0000-0000-000000000000 : CompareGreaterThan () // aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + ILOpFormatter.formatOp( + new CompareGreaterThan<>(UUID.fromString("00000000-0000-0000-0000-000000000000"), "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + new ILBlock<>() + ) + ); + + // Test a normal IL Op with an integer identifier + Assert.assertEquals("15 : Branch (20) // aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + ILOpFormatter.formatOp( + new Branch<>(15, 20, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + new ILBlock<>() + ) + ); + + } + +} + diff --git a/tss-occam-compiler/src/test/java/uk/co/transputersystems/occam/open_transputer/ASMGeneratorHelpersTest.java b/tss-occam-compiler/src/test/java/uk/co/transputersystems/occam/open_transputer/ASMGeneratorHelpersTest.java new file mode 100644 index 0000000..80dcbc8 --- /dev/null +++ b/tss-occam-compiler/src/test/java/uk/co/transputersystems/occam/open_transputer/ASMGeneratorHelpersTest.java @@ -0,0 +1,7 @@ +package uk.co.transputersystems.occam.open_transputer; + +import static org.junit.Assert.assertEquals; + +public class ASMGeneratorHelpersTest { + +} diff --git a/tss-occam-test-resources/pom.xml b/tss-occam-test-resources/pom.xml new file mode 100644 index 0000000..25f45c6 --- /dev/null +++ b/tss-occam-test-resources/pom.xml @@ -0,0 +1,53 @@ + + 4.0.0 + + uk.co.transputersystems + tss-occam-test-resources + 1.0-SNAPSHOT + + jar + tss-occam-test-resources + + + UTF-8 + + + + + + + install + + + maven-remote-resources-plugin + 1.5 + + + + bundle + + + + **/*.occ + + + + + + + org.apache.maven.plugins + maven-assembly-plugin + 2.6 + + + jar-with-dependencies + + + + + + + + \ No newline at end of file diff --git a/tss-occam-test-resources/src/main/resources/basic-tests/test01.occ b/tss-occam-test-resources/src/main/resources/basic-tests/test01.occ new file mode 100644 index 0000000..ac27f84 --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/basic-tests/test01.occ @@ -0,0 +1,17 @@ +PROC init ([4]BYTE x) + PAR + SKIP + SKIP + PAR + SKIP + SKIP + SKIP + SKIP + PAR + SKIP + SKIP + PAR + SKIP + SKIP + SKIP +: \ No newline at end of file diff --git a/tss-occam-test-resources/src/main/resources/basic-tests/test02.occ b/tss-occam-test-resources/src/main/resources/basic-tests/test02.occ new file mode 100644 index 0000000..304b32b --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/basic-tests/test02.occ @@ -0,0 +1,6 @@ +PROC init () + INT x, y: + SEQ + x := 4 + y := x +: \ No newline at end of file diff --git a/tss-occam-test-resources/src/main/resources/basic-tests/test03.occ b/tss-occam-test-resources/src/main/resources/basic-tests/test03.occ new file mode 100644 index 0000000..019033e --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/basic-tests/test03.occ @@ -0,0 +1,15 @@ +PROC init() + INT t,u , p : + SEQ + IF + TRUE AND (((t > u) OR (t < u)) AND (t < u)) + IF + u > p + SKIP + u > p + SKIP + t > u + SKIP + + +: \ No newline at end of file diff --git a/tss-occam-test-resources/src/main/resources/basic-tests/test04.occ b/tss-occam-test-resources/src/main/resources/basic-tests/test04.occ new file mode 100644 index 0000000..afdba5e --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/basic-tests/test04.occ @@ -0,0 +1,8 @@ +PROC init() + SEQ + SKIP + PAR + SKIP + SKIP + SKIP +: \ No newline at end of file diff --git a/tss-occam-test-resources/src/main/resources/basic-tests/test05.occ b/tss-occam-test-resources/src/main/resources/basic-tests/test05.occ new file mode 100644 index 0000000..4ec062d --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/basic-tests/test05.occ @@ -0,0 +1,8 @@ +PROC init() + WHILE TRUE + INT v: + SEQ + SKIP + INT j: + SKIP +: diff --git a/tss-occam-test-resources/src/main/resources/basic-tests/test06.occ b/tss-occam-test-resources/src/main/resources/basic-tests/test06.occ new file mode 100644 index 0000000..7c78ffc --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/basic-tests/test06.occ @@ -0,0 +1,8 @@ +PROC writer (CHAN OF INT out) + SEQ + out ! clear.screen + SEQ i = 0 FOR 10 + out ! int.x.y; 1; (BYTE i) + 1; i + VAL []BYTE str IS "hello, new world!": + out ! string.x.y; 1; 11; (SIZE str)::str +: \ No newline at end of file diff --git a/tss-occam-test-resources/src/main/resources/basic-tests/test07.occ b/tss-occam-test-resources/src/main/resources/basic-tests/test07.occ new file mode 100644 index 0000000..a3623a1 --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/basic-tests/test07.occ @@ -0,0 +1,24 @@ +PROC do.delay (VAL INT us) + PROC C1 () + X := 42 + : + SEQ + tim ? t -- read current time + t := t PLUS us -- add delay + tim ? AFTER t -- wait until time "t" +: + +PROC writer (CHAN OF INT out) + SEQ + out ! clear.screen + SEQ i = 0 FOR 10 + out ! int.x.y; 1; (BYTE i) + 1; i + VAL []BYTE str IS "hello, new world!": + out ! string.x.y; 1; 11; (SIZE str)::str +: + +PROC init () + SEQ + writer() + writer() +: diff --git a/tss-occam-test-resources/src/main/resources/basic-tests/test08.occ b/tss-occam-test-resources/src/main/resources/basic-tests/test08.occ new file mode 100644 index 0000000..ef87920 --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/basic-tests/test08.occ @@ -0,0 +1,7 @@ +PROC test0 () + [2]INT a: + [2]INT c: + SEQ + c[0] := -a + check.INT (c[1],2,"test0") +: \ No newline at end of file diff --git a/tss-occam-test-resources/src/main/resources/basic-tests/test09.occ b/tss-occam-test-resources/src/main/resources/basic-tests/test09.occ new file mode 100644 index 0000000..b7727ed --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/basic-tests/test09.occ @@ -0,0 +1,7 @@ +PROC init() + INT y,y,z: + SEQ + x := 0 + y := 1 + z := x + y +: diff --git a/tss-occam-test-resources/src/main/resources/basic-tests/test10.occ b/tss-occam-test-resources/src/main/resources/basic-tests/test10.occ new file mode 100644 index 0000000..c21453d --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/basic-tests/test10.occ @@ -0,0 +1,12 @@ +PROC init () + INT x, y: + SEQ + six(x+1) + x := 4 + y := (x + 1) + CHAN OF INT c: + PAR + some.procedure (x, y, c) + another.procedure (c) + y := 5 +: \ No newline at end of file diff --git a/tss-occam-test-resources/src/main/resources/basic-tests/test11.occ b/tss-occam-test-resources/src/main/resources/basic-tests/test11.occ new file mode 100644 index 0000000..3eef01e --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/basic-tests/test11.occ @@ -0,0 +1,25 @@ +INT global1,global2: + +PROC init () + INT a,b,c,x: + SEQ + global1 := 10 + global2 := 11 + PAR + INT y,z: + SEQ + a := 4 + y := x + z := y + INT y,z: + SEQ + b := 5 + y := x + z := y + INT w,y,z: + SEQ + c := 6 + y := x + z := y + w := z +: \ No newline at end of file diff --git a/tss-occam-test-resources/src/main/resources/feature-tests/alternatives.occ b/tss-occam-test-resources/src/main/resources/feature-tests/alternatives.occ new file mode 100644 index 0000000..a1e3192 --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/feature-tests/alternatives.occ @@ -0,0 +1,24 @@ +--prereq declaration, assignment +--Goal +--Alternatives +PROC init() + CHAN OF INT c1, c2 : + INT a,b : + TIMER t : + SEQ + a := 2 + ALT + c1 ? a + SEQ + b := 1 + TRUE & c2 ? a + SEQ + b := 2 + t ? AFTER (1000 + 2) + SEQ + b := 3 + TRUE & SKIP + SEQ + b := 4 + +: diff --git a/tss-occam-test-resources/src/main/resources/feature-tests/array.occ b/tss-occam-test-resources/src/main/resources/feature-tests/array.occ new file mode 100644 index 0000000..4ed07fb --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/feature-tests/array.occ @@ -0,0 +1,28 @@ +-- prereq - assignment + +-- Goal +-- Array can be declared and assigned values +-- Array value can be copied to another variable +-- Array size +PROC init() + [2][4]INT ints: + INT a: + SEQ + ints[0][0] := 1 + ints[0][1] := 2 + ints[0][2] := 3 + ints[0][3] := 4 + + ints[1][0] := 1 + ints[1][1] := 2 + ints[1][2] := 3 + ints[1][3] := 4 + + a := ints[1][1] + + a := SIZE ints[1] + a := SIZE ints[0] + +: + + diff --git a/tss-occam-test-resources/src/main/resources/feature-tests/array_abbreviations.occ b/tss-occam-test-resources/src/main/resources/feature-tests/array_abbreviations.occ new file mode 100644 index 0000000..110c52f --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/feature-tests/array_abbreviations.occ @@ -0,0 +1,22 @@ +--prereq declaration, array declarations, variable abbreviations +--Goal +--Correctly handle abbreviation of arrays + +PROC initArrays() + INT a: + [2] INT pages: + SEQ + INT first IS pages[0]: + INT last IS pages[1]: + a := 1 + first := a + last := 10 + + PAR + SEQ + INT f0: + f0 := first + SEQ + INT f1: + f1 := last +: \ No newline at end of file diff --git a/tss-occam-test-resources/src/main/resources/feature-tests/array_segments.occ b/tss-occam-test-resources/src/main/resources/feature-tests/array_segments.occ new file mode 100644 index 0000000..283d1b5 --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/feature-tests/array_segments.occ @@ -0,0 +1,34 @@ +--prereq array declaration +--Goal +--Array segment feature works correctly +PROC init () + [5]INT height, widths: + [2]INT selection: + SEQ + height[0] := 0 + height[1] := 1 + height[2] := 2 + height[3] := 3 + height[4] := 4 + + + width[0] := 10 + width[1] := 9 + width[2] := 8 + width[3] := 7 + width[4] := 6 + + + selection := [height FROM 0 FOR 2] + selection := [height FROM 3] + selection := [height FOR 2] + + + [height FOR 5] := [width FOR 5] + + +: + + + + diff --git a/tss-occam-test-resources/src/main/resources/feature-tests/assignment.occ b/tss-occam-test-resources/src/main/resources/feature-tests/assignment.occ new file mode 100644 index 0000000..e273ec3 --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/feature-tests/assignment.occ @@ -0,0 +1,11 @@ +--Prereq sequential +--Goal +--Integer variables can be assigned values +PROC init() + INT a,b,c: + SEQ + a := 1 + b := 2 + c := 3 + a := c +: \ No newline at end of file diff --git a/tss-occam-test-resources/src/main/resources/feature-tests/byte_literal.occ b/tss-occam-test-resources/src/main/resources/feature-tests/byte_literal.occ new file mode 100644 index 0000000..f139d92 --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/feature-tests/byte_literal.occ @@ -0,0 +1,10 @@ +--Goal +--Correctly handle various types of byte literal +PROC init() + BYTE a, b, c, d: + SEQ + a := '*#7F' + b := '*T' + c := '*'' + d := '**' +: \ No newline at end of file diff --git a/tss-occam-test-resources/src/main/resources/feature-tests/channel_abbreviations.occ b/tss-occam-test-resources/src/main/resources/feature-tests/channel_abbreviations.occ new file mode 100644 index 0000000..4439a91 --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/feature-tests/channel_abbreviations.occ @@ -0,0 +1,12 @@ +--prereq declaration +--Goal +--Correctly handle abbreviation of channels + +PROC init() + CHAN OF INT a: + SEQ + b IS a: + b ! 5 + CHAN OF BYTE c IS b: + c ! 10 +: \ No newline at end of file diff --git a/tss-occam-test-resources/src/main/resources/feature-tests/channels.occ b/tss-occam-test-resources/src/main/resources/feature-tests/channels.occ new file mode 100644 index 0000000..2fa478d --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/feature-tests/channels.occ @@ -0,0 +1,14 @@ +--prereq declaration, assignment +--Goal +--Channel declared +--Write a value to a channel +--Read a value from a channel +PROC init() + CHAN OF INT c : + INT a,b: + SEQ + a := 2 + PAR + c ! a + c ? b +: diff --git a/tss-occam-test-resources/src/main/resources/feature-tests/conditional.occ b/tss-occam-test-resources/src/main/resources/feature-tests/conditional.occ new file mode 100644 index 0000000..1666ebe --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/feature-tests/conditional.occ @@ -0,0 +1,19 @@ +-- prereq - declaration +-- Goal +-- Handle conditional statements +PROC init() + INT a,b,c,d: + SEQ + a := 1 + b := 2 + c := 3 + IF + a< a + l := b BITAND a + m := b BITOR a + n := b AND a + o := b OR a + p := b = a + q := b <> a + r := b > a + s := b < a + t := b <= a + u := b >= a + v := b AFTER a +: \ No newline at end of file diff --git a/tss-occam-test-resources/src/main/resources/feature-tests/expression_features_nested.occ b/tss-occam-test-resources/src/main/resources/feature-tests/expression_features_nested.occ new file mode 100644 index 0000000..7b6e0d4 --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/feature-tests/expression_features_nested.occ @@ -0,0 +1,11 @@ +--prereq monadic expressions +--Goal +--Correctly swap variables a,b := b,c +--Handle nested expressions +PROC init() + INT a,b,c,d,e : + SEQ + a,b,c,d,e := 1,2,3,4,5 + a, b := b , a + a := b + (( (c / d) * (a + b)) + 2 ) +: \ No newline at end of file diff --git a/tss-occam-test-resources/src/main/resources/feature-tests/monadic_expressions.occ b/tss-occam-test-resources/src/main/resources/feature-tests/monadic_expressions.occ new file mode 100644 index 0000000..10b80ba --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/feature-tests/monadic_expressions.occ @@ -0,0 +1,20 @@ +--prereq sequential, assignment, declaration +--Goal +--Correctly handle monadic expressions +PROC init() + INT a,b,c,d,e,f,g,h,i,j: + SEQ + a := 2 + b := 9 + c := -a + d := MINUS a + e := ~a + f := BITNOT a + g := NOT a + --h := SIZE a -- Note: This applies to array types only + --h := BYTESIN a -- Note: This applies to value types only + i := b >> a + j := b << a + i := MOSTPOS INT + j := MOSTNEG INT +: \ No newline at end of file diff --git a/tss-occam-test-resources/src/main/resources/feature-tests/operations_types.occ b/tss-occam-test-resources/src/main/resources/feature-tests/operations_types.occ new file mode 100644 index 0000000..43fc02e --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/feature-tests/operations_types.occ @@ -0,0 +1,21 @@ +--prereq +--Goals +--SIZEOF +--MOSTPOS + +PROC init() + INT a: + SEQ + + a := MOSTPOS INT16 + a := MOSTPOS INT32 + a := MOSTPOS INT64 + a := MOSTPOS BYTE + + a := MOSTNEG INT16 + a := MOSTNEG INT32 + a := MOSTNEG INT64 + a := MOSTNEG BYTE + +: + diff --git a/tss-occam-test-resources/src/main/resources/feature-tests/par.occ b/tss-occam-test-resources/src/main/resources/feature-tests/par.occ new file mode 100644 index 0000000..f9080da --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/feature-tests/par.occ @@ -0,0 +1,11 @@ +--Goal +--Correctly handle parallel processes +PROC init() + PAR + SKIP + SKIP + SKIP + SKIP + SKIP + SKIP +: \ No newline at end of file diff --git a/tss-occam-test-resources/src/main/resources/feature-tests/par_advanced.occ b/tss-occam-test-resources/src/main/resources/feature-tests/par_advanced.occ new file mode 100644 index 0000000..6df474d --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/feature-tests/par_advanced.occ @@ -0,0 +1,24 @@ +--Goal +--Correctly handle parallel processes +PROC init() + PAR + INT a,b,c: + SEQ + a:=2 + b:=1 + c:=3 + INT d,e,f: + SEQ + d:=2 + e:=1 + f:=0 + PAR + SKIP + INT h,i: + CHAN OF INT c : + SEQ + h:=2 + i:=1 + i:=h + +: \ No newline at end of file diff --git a/tss-occam-test-resources/src/main/resources/feature-tests/port.occ b/tss-occam-test-resources/src/main/resources/feature-tests/port.occ new file mode 100644 index 0000000..3a074b2 --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/feature-tests/port.occ @@ -0,0 +1,14 @@ +--prereq declaration, assignment +--Goal +--Channel declared +--Write a value to a channel +--Read a value from a channel +PROC init() + PORT OF INT c1 : + INT a,b: + SEQ + a := 2 + PAR + c1 ! a + c1 ? b +: diff --git a/tss-occam-test-resources/src/main/resources/feature-tests/proc_arguments.occ b/tss-occam-test-resources/src/main/resources/feature-tests/proc_arguments.occ new file mode 100644 index 0000000..310b0b9 --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/feature-tests/proc_arguments.occ @@ -0,0 +1,14 @@ +--Goal +--Correctly handle a process with arguments +PROC a(VAL INT a, INT b) + SEQ + b := a +: + + +PROC init() + INT my.int: + SEQ + my.int := 2 + a(0, my.int) +: diff --git a/tss-occam-test-resources/src/main/resources/feature-tests/proc_par_arguments.occ b/tss-occam-test-resources/src/main/resources/feature-tests/proc_par_arguments.occ new file mode 100644 index 0000000..e99fb62 --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/feature-tests/proc_par_arguments.occ @@ -0,0 +1,14 @@ +--Goal +--Correctly handle a process with arguments +PROC a(INT a, INT b) + PAR + SKIP + SKIP +: + + +PROC init() + PAR + a(0,0) + b(1,1) +: diff --git a/tss-occam-test-resources/src/main/resources/feature-tests/procedure_static_assignment.occ b/tss-occam-test-resources/src/main/resources/feature-tests/procedure_static_assignment.occ new file mode 100644 index 0000000..9059d4d --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/feature-tests/procedure_static_assignment.occ @@ -0,0 +1,16 @@ +--prereq proc_argument , declaration +--Goals to assign a static variable to a procedure] + +PROC init() + INT step: + SEQ + step := 39 + PROC next.item(INT next, VAL INT this) + next := this + step + : + INT g, step: + SEQ + step := 7 + next.item(g, 3) + --g should have value 42 +: \ No newline at end of file diff --git a/tss-occam-test-resources/src/main/resources/feature-tests/record_declaration.occ b/tss-occam-test-resources/src/main/resources/feature-tests/record_declaration.occ new file mode 100644 index 0000000..885e87b --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/feature-tests/record_declaration.occ @@ -0,0 +1,16 @@ +--preq declaration +--Goal +--Correctly declare a record data structure +DATA TYPE RECTANGLE + RECORD + INT width, height: +: +DATA TYPE HEATER + RECORD + RECTANGLE size: + INT power: +: + +PROC init() + SKIP +: \ No newline at end of file diff --git a/tss-occam-test-resources/src/main/resources/feature-tests/record_operations.occ b/tss-occam-test-resources/src/main/resources/feature-tests/record_operations.occ new file mode 100644 index 0000000..9376498 --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/feature-tests/record_operations.occ @@ -0,0 +1,28 @@ +--prereq record_declarations +--Goal BYTESIN & OFFSETOF operators on a record + +DATA TYPE MIXED + PACKED RECORD + BYTE b1, b2: + INT16 i16: + INT i: +: + + + +PROC init() + MIXED m1: + INT a , b , c , d , e , ob1 , ob2 , ob3: + + SEQ + a := BYTESIN(MIXED) + b := BYTESIN(m1) + c := BYTESIN(m1[b1]) + d := BYTESIN(m1[i16]) + e := BYTESIN(m1[i]) + + ob1 := OFFSETOF(MIXED,b1) + ob2 := OFFSETOF(MIXED,i16) + ob3 := OFFSETOF(MIXED,i) +: + diff --git a/tss-occam-test-resources/src/main/resources/feature-tests/replicated_conditionals.occ b/tss-occam-test-resources/src/main/resources/feature-tests/replicated_conditionals.occ new file mode 100644 index 0000000..b5f957a --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/feature-tests/replicated_conditionals.occ @@ -0,0 +1,13 @@ +--prereq conditionals , replicators , conditional +--Goal +--Correctly handle replicated conditionals +PROC init() + INT u , v: + IF + u <= v + IF i = 2 FOR 10 + i = 10 + SKIP + TRUE + SKIP +: diff --git a/tss-occam-test-resources/src/main/resources/feature-tests/replicator.occ b/tss-occam-test-resources/src/main/resources/feature-tests/replicator.occ new file mode 100644 index 0000000..4bce3ca --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/feature-tests/replicator.occ @@ -0,0 +1,10 @@ +--prereq par +--Goal +--Correctly create replicated parallel statements + +PROC init() + PAR i = 0 FOR 4 + PAR k = 0 FOR 10 + SKIP +: + diff --git a/tss-occam-test-resources/src/main/resources/feature-tests/selection.occ b/tss-occam-test-resources/src/main/resources/feature-tests/selection.occ new file mode 100644 index 0000000..4673ffd --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/feature-tests/selection.occ @@ -0,0 +1,15 @@ +-- prereq - declaration +-- Goal +-- Handle selection +PROC init() + INT a,b,c: + SEQ + a := 2 + CASE a + 3 + c := 1 + 4 + c := 2 + ELSE + c := 3 +: \ No newline at end of file diff --git a/tss-occam-test-resources/src/main/resources/feature-tests/sequential.occ b/tss-occam-test-resources/src/main/resources/feature-tests/sequential.occ new file mode 100644 index 0000000..4a51d72 --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/feature-tests/sequential.occ @@ -0,0 +1,16 @@ +--Goal +--Correctly handle sequential statements +PROC init() + PAR + SEQ + SKIP + SKIP + SEQ + PAR + SKIP + SKIP + SKIP + SEQ + SKIP + SKIP +: \ No newline at end of file diff --git a/tss-occam-test-resources/src/main/resources/feature-tests/variable_abbreviations.occ b/tss-occam-test-resources/src/main/resources/feature-tests/variable_abbreviations.occ new file mode 100644 index 0000000..d775ce2 --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/feature-tests/variable_abbreviations.occ @@ -0,0 +1,19 @@ +--prereq declaration +--Goal +--Correctly handle abbreviation of variables + +PROC init() + INT a: + BOOL x: + b IS a: + SEQ + b := 1 + x := TRUE + INT y IS x: + BOOL c: + SEQ + y := 1 + VAL BOOL z IS y + b: + c := z + y := 0 +: \ No newline at end of file diff --git a/tss-occam-test-resources/src/main/resources/feature-tests/while_loops.occ b/tss-occam-test-resources/src/main/resources/feature-tests/while_loops.occ new file mode 100644 index 0000000..24e274c --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/feature-tests/while_loops.occ @@ -0,0 +1,20 @@ +-- prereq declaration, assignment +--Goal +--Correctly handle a while loop and a nested whi +PROC init() + INT a, b, c, d: + SEQ + a := 1 + b := 10 + d := 1 + + WHILE b < (d + 1) + SEQ + a := a + 1 + c := a + d := 1 + WHILE d < b + SEQ + SKIP + d := d + 1 +: \ No newline at end of file diff --git a/tss-occam-test-resources/src/main/resources/function-tests/function_el_0_in_1_out.occ b/tss-occam-test-resources/src/main/resources/function-tests/function_el_0_in_1_out.occ new file mode 100644 index 0000000..e379949 --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/function-tests/function_el_0_in_1_out.occ @@ -0,0 +1,8 @@ +INT FUNCTION test() IS 10: + + +PROC init() + INT a : + SEQ + a := test() +: \ No newline at end of file diff --git a/tss-occam-test-resources/src/main/resources/function-tests/function_el_0_in_2_out.occ b/tss-occam-test-resources/src/main/resources/function-tests/function_el_0_in_2_out.occ new file mode 100644 index 0000000..bd1c425 --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/function-tests/function_el_0_in_2_out.occ @@ -0,0 +1,8 @@ +INT,INT FUNCTION test() IS 10,15: + + +PROC init() + INT a,b: + SEQ + a,b := test() +: \ No newline at end of file diff --git a/tss-occam-test-resources/src/main/resources/function-tests/function_el_0_in_3_out.occ b/tss-occam-test-resources/src/main/resources/function-tests/function_el_0_in_3_out.occ new file mode 100644 index 0000000..264adcc --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/function-tests/function_el_0_in_3_out.occ @@ -0,0 +1,8 @@ +INT,INT,INT FUNCTION test() IS 10,15,20: + + +PROC init() + INT a,b,c: + SEQ + a,b,c := test() +: \ No newline at end of file diff --git a/tss-occam-test-resources/src/main/resources/function-tests/function_el_0_in_4_out.occ b/tss-occam-test-resources/src/main/resources/function-tests/function_el_0_in_4_out.occ new file mode 100644 index 0000000..1099857 --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/function-tests/function_el_0_in_4_out.occ @@ -0,0 +1,8 @@ +INT,INT,INT,INT FUNCTION test() IS 10,15,20,25: + + +PROC init() + INT a,b,c,d: + SEQ + a,b,c,d := test() +: \ No newline at end of file diff --git a/tss-occam-test-resources/src/main/resources/function-tests/function_el_1_in_1_out.occ b/tss-occam-test-resources/src/main/resources/function-tests/function_el_1_in_1_out.occ new file mode 100644 index 0000000..c7f0e3c --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/function-tests/function_el_1_in_1_out.occ @@ -0,0 +1,8 @@ +INT FUNCTION test(VAL INT z) IS z: + + +PROC init() + INT a: + SEQ + a := test(5) +: \ No newline at end of file diff --git a/tss-occam-test-resources/src/main/resources/function-tests/function_el_1_in_2_out.occ b/tss-occam-test-resources/src/main/resources/function-tests/function_el_1_in_2_out.occ new file mode 100644 index 0000000..b8f17c9 --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/function-tests/function_el_1_in_2_out.occ @@ -0,0 +1,8 @@ +INT,INT FUNCTION test(VAL INT z) IS z,10: + + +PROC init() + INT a,b: + SEQ + a,b := test(5) +: \ No newline at end of file diff --git a/tss-occam-test-resources/src/main/resources/function-tests/function_el_1_in_3_out.occ b/tss-occam-test-resources/src/main/resources/function-tests/function_el_1_in_3_out.occ new file mode 100644 index 0000000..0614db0 --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/function-tests/function_el_1_in_3_out.occ @@ -0,0 +1,8 @@ +INT,INT,INT FUNCTION test(VAL INT z) IS z,15,20: + + +PROC init() + INT a,b,c: + SEQ + a,b,c := test(5) +: \ No newline at end of file diff --git a/tss-occam-test-resources/src/main/resources/function-tests/function_el_1_in_4_out.occ b/tss-occam-test-resources/src/main/resources/function-tests/function_el_1_in_4_out.occ new file mode 100644 index 0000000..a5068fe --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/function-tests/function_el_1_in_4_out.occ @@ -0,0 +1,8 @@ +INT,INT,INT,INT FUNCTION test(VAL INT z) IS z,15,20,25: + + +PROC init() + INT a,b,c,d: + SEQ + a,b,c,d := test(5) +: \ No newline at end of file diff --git a/tss-occam-test-resources/src/main/resources/function-tests/function_el_2_in_1_out.occ b/tss-occam-test-resources/src/main/resources/function-tests/function_el_2_in_1_out.occ new file mode 100644 index 0000000..74fad00 --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/function-tests/function_el_2_in_1_out.occ @@ -0,0 +1,8 @@ +INT FUNCTION test(VAL INT z, VAL INT y) IS z: + + +PROC init() + INT a: + SEQ + a := test(5,10) +: \ No newline at end of file diff --git a/tss-occam-test-resources/src/main/resources/function-tests/function_el_2_in_2_out.occ b/tss-occam-test-resources/src/main/resources/function-tests/function_el_2_in_2_out.occ new file mode 100644 index 0000000..a93fdd8 --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/function-tests/function_el_2_in_2_out.occ @@ -0,0 +1,8 @@ +INT,INT FUNCTION test(VAL INT z, VAL INT y) IS z,y: + + +PROC init() + INT a,b: + SEQ + a,b := test(5,10) +: \ No newline at end of file diff --git a/tss-occam-test-resources/src/main/resources/function-tests/function_el_2_in_3_out.occ b/tss-occam-test-resources/src/main/resources/function-tests/function_el_2_in_3_out.occ new file mode 100644 index 0000000..449ad86 --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/function-tests/function_el_2_in_3_out.occ @@ -0,0 +1,8 @@ +INT,INT,INT FUNCTION test(VAL INT z, VAL INT y) IS z,y,20: + + +PROC init() + INT a,b,c: + SEQ + a,b,c := test(5,10) +: \ No newline at end of file diff --git a/tss-occam-test-resources/src/main/resources/function-tests/function_el_2_in_4_out.occ b/tss-occam-test-resources/src/main/resources/function-tests/function_el_2_in_4_out.occ new file mode 100644 index 0000000..6af7142 --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/function-tests/function_el_2_in_4_out.occ @@ -0,0 +1,8 @@ +INT,INT,INT,INT FUNCTION test(VAL INT z, VAL INT y) IS z,y,20,25: + + +PROC init() + INT a,b,c,d: + SEQ + a,b,c,d := test(5,10) +: \ No newline at end of file diff --git a/tss-occam-test-resources/src/main/resources/function-tests/function_el_3_in_1_out.occ b/tss-occam-test-resources/src/main/resources/function-tests/function_el_3_in_1_out.occ new file mode 100644 index 0000000..b700e3e --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/function-tests/function_el_3_in_1_out.occ @@ -0,0 +1,8 @@ +INT FUNCTION test(VAL INT z, VAL INT y, VAL INT x) IS z: + + +PROC init() + INT a: + SEQ + a := test(5,10,15) +: \ No newline at end of file diff --git a/tss-occam-test-resources/src/main/resources/function-tests/function_el_3_in_2_out.occ b/tss-occam-test-resources/src/main/resources/function-tests/function_el_3_in_2_out.occ new file mode 100644 index 0000000..bc3a411 --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/function-tests/function_el_3_in_2_out.occ @@ -0,0 +1,8 @@ +INT,INT FUNCTION test(VAL INT z, VAL INT y, VAL INT x) IS z,y: + + +PROC init() + INT a,b: + SEQ + a,b := test(5,10,15) +: \ No newline at end of file diff --git a/tss-occam-test-resources/src/main/resources/function-tests/function_el_3_in_3_out.occ b/tss-occam-test-resources/src/main/resources/function-tests/function_el_3_in_3_out.occ new file mode 100644 index 0000000..c329b57 --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/function-tests/function_el_3_in_3_out.occ @@ -0,0 +1,8 @@ +INT,INT,INT FUNCTION test(VAL INT z, VAL INT y, VAL INT x) IS z,y,x: + + +PROC init() + INT a,b,c: + SEQ + a,b,c := test(5,10,15) +: \ No newline at end of file diff --git a/tss-occam-test-resources/src/main/resources/function-tests/function_el_3_in_4_out.occ b/tss-occam-test-resources/src/main/resources/function-tests/function_el_3_in_4_out.occ new file mode 100644 index 0000000..477d7bb --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/function-tests/function_el_3_in_4_out.occ @@ -0,0 +1,8 @@ +INT,INT,INT,INT FUNCTION test(VAL INT z, VAL INT y, VAL INT x) IS z,y,x,25: + + +PROC init() + INT a,b,c,d: + SEQ + a,b,c,d := test(5,10,15) +: \ No newline at end of file diff --git a/tss-occam-test-resources/src/main/resources/function-tests/function_el_4_in_1_out.occ b/tss-occam-test-resources/src/main/resources/function-tests/function_el_4_in_1_out.occ new file mode 100644 index 0000000..89c0fbc --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/function-tests/function_el_4_in_1_out.occ @@ -0,0 +1,8 @@ +INT FUNCTION test(VAL INT z, VAL INT y, VAL INT x, VAL INT w) IS z: + + +PROC init() + INT a: + SEQ + a := test(5,10,15,20) +: \ No newline at end of file diff --git a/tss-occam-test-resources/src/main/resources/function-tests/function_el_4_in_2_out.occ b/tss-occam-test-resources/src/main/resources/function-tests/function_el_4_in_2_out.occ new file mode 100644 index 0000000..d102def --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/function-tests/function_el_4_in_2_out.occ @@ -0,0 +1,8 @@ +INT,INT FUNCTION test(VAL INT z, VAL INT y, VAL INT x, VAL INT w) IS z,y: + + +PROC init() + INT a,b: + SEQ + a,b := test(5,10,15,20) +: \ No newline at end of file diff --git a/tss-occam-test-resources/src/main/resources/function-tests/function_el_4_in_3_out.occ b/tss-occam-test-resources/src/main/resources/function-tests/function_el_4_in_3_out.occ new file mode 100644 index 0000000..4bb7a1e --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/function-tests/function_el_4_in_3_out.occ @@ -0,0 +1,8 @@ +INT,INT,INT FUNCTION test(VAL INT z, VAL INT y, VAL INT x, VAL INT w) IS z,y,x: + + +PROC init() + INT a,b,c: + SEQ + a,b,c := test(5,10,15,20) +: \ No newline at end of file diff --git a/tss-occam-test-resources/src/main/resources/function-tests/function_el_4_in_4_out.occ b/tss-occam-test-resources/src/main/resources/function-tests/function_el_4_in_4_out.occ new file mode 100644 index 0000000..5561f98 --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/function-tests/function_el_4_in_4_out.occ @@ -0,0 +1,8 @@ +INT,INT,INT,INT FUNCTION test(VAL INT z, VAL INT y, VAL INT x, VAL INT w) IS z,y,x,w: + + +PROC init() + INT a,b,c,d: + SEQ + a,b,c,d := test(5,10,15,20) +: \ No newline at end of file diff --git a/tss-occam-test-resources/src/main/resources/function-tests/function_expression_list.occ b/tss-occam-test-resources/src/main/resources/function-tests/function_expression_list.occ new file mode 100644 index 0000000..dfa4e21 --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/function-tests/function_expression_list.occ @@ -0,0 +1,10 @@ +--prereq assignment +--Goals - Declare and call a function that is an expression list + +BOOL FUNCTION isupper(VAL BYTE ch) IS (ch >= 'A') AND (ch <= 'Z'): + +PROC init() + BOOL upper: + SEQ + upper := isupper('Z') +: \ No newline at end of file diff --git a/tss-occam-test-resources/src/main/resources/function-tests/function_value_process.occ b/tss-occam-test-resources/src/main/resources/function-tests/function_value_process.occ new file mode 100644 index 0000000..fa469b0 --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/function-tests/function_value_process.occ @@ -0,0 +1,20 @@ +--prereq assignment +--Goals - Declare and call a function that is a value process + +INT FUNCTION increase (VAL INT a) + INT b: + VALOF + SEQ + b := 10 + b := a * (b+2) + + RESULT b +: + + +PROC init() + INT v,o : + SEQ + v := 5 + o := increase(v) +: \ No newline at end of file diff --git a/tss-occam-test-resources/src/main/resources/function-tests/function_vp_0_in_1_out.occ b/tss-occam-test-resources/src/main/resources/function-tests/function_vp_0_in_1_out.occ new file mode 100644 index 0000000..149fc80 --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/function-tests/function_vp_0_in_1_out.occ @@ -0,0 +1,14 @@ +INT FUNCTION test () + INT a: + VALOF + SEQ + a := 10 + RESULT a +: + + +PROC init() + INT a : + SEQ + a := test() +: \ No newline at end of file diff --git a/tss-occam-test-resources/src/main/resources/function-tests/function_vp_0_in_2_out.occ b/tss-occam-test-resources/src/main/resources/function-tests/function_vp_0_in_2_out.occ new file mode 100644 index 0000000..b548519 --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/function-tests/function_vp_0_in_2_out.occ @@ -0,0 +1,15 @@ +INT,INT FUNCTION test () + INT a,b: + VALOF + SEQ + a := 10 + b := 15 + RESULT a,b +: + + +PROC init() + INT a,b: + SEQ + a,b := test() +: \ No newline at end of file diff --git a/tss-occam-test-resources/src/main/resources/function-tests/function_vp_0_in_3_out.occ b/tss-occam-test-resources/src/main/resources/function-tests/function_vp_0_in_3_out.occ new file mode 100644 index 0000000..205f4f6 --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/function-tests/function_vp_0_in_3_out.occ @@ -0,0 +1,16 @@ +INT,INT,INT FUNCTION test () + INT a,b,c: + VALOF + SEQ + a := 10 + b := 15 + c := 20 + RESULT a,b,c +: + + +PROC init() + INT a,b,c: + SEQ + a,b,c := test() +: \ No newline at end of file diff --git a/tss-occam-test-resources/src/main/resources/function-tests/function_vp_0_in_4_out.occ b/tss-occam-test-resources/src/main/resources/function-tests/function_vp_0_in_4_out.occ new file mode 100644 index 0000000..73ab8be --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/function-tests/function_vp_0_in_4_out.occ @@ -0,0 +1,17 @@ +INT,INT,INT,INT FUNCTION test () + INT a,b,c,d: + VALOF + SEQ + a := 10 + b := 15 + c := 20 + d := 25 + RESULT a,b,c,d +: + + +PROC init() + INT a,b,c,d: + SEQ + a,b,c,d := test() +: \ No newline at end of file diff --git a/tss-occam-test-resources/src/main/resources/function-tests/function_vp_1_in_1_out.occ b/tss-occam-test-resources/src/main/resources/function-tests/function_vp_1_in_1_out.occ new file mode 100644 index 0000000..27d8a14 --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/function-tests/function_vp_1_in_1_out.occ @@ -0,0 +1,14 @@ +INT FUNCTION test (VAL INT z) + INT a: + VALOF + SEQ + a := z + RESULT a +: + + +PROC init() + INT a: + SEQ + a := test(5) +: \ No newline at end of file diff --git a/tss-occam-test-resources/src/main/resources/function-tests/function_vp_1_in_2_out.occ b/tss-occam-test-resources/src/main/resources/function-tests/function_vp_1_in_2_out.occ new file mode 100644 index 0000000..5be773b --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/function-tests/function_vp_1_in_2_out.occ @@ -0,0 +1,15 @@ +INT,INT FUNCTION test (VAL INT z) + INT a,b: + VALOF + SEQ + a := z + b := 10 + RESULT a,b +: + + +PROC init() + INT a,b: + SEQ + a,b := test(5) +: \ No newline at end of file diff --git a/tss-occam-test-resources/src/main/resources/function-tests/function_vp_1_in_3_out.occ b/tss-occam-test-resources/src/main/resources/function-tests/function_vp_1_in_3_out.occ new file mode 100644 index 0000000..b1afe0a --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/function-tests/function_vp_1_in_3_out.occ @@ -0,0 +1,16 @@ +INT,INT,INT FUNCTION test (VAL INT z) + INT a,b,c: + VALOF + SEQ + a := z + b := 10 + c := 15 + RESULT a,b,c +: + + +PROC init() + INT a,b,c: + SEQ + a,b,c := test(5) +: \ No newline at end of file diff --git a/tss-occam-test-resources/src/main/resources/function-tests/function_vp_1_in_4_out.occ b/tss-occam-test-resources/src/main/resources/function-tests/function_vp_1_in_4_out.occ new file mode 100644 index 0000000..f9b80f7 --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/function-tests/function_vp_1_in_4_out.occ @@ -0,0 +1,17 @@ +INT,INT,INT,INT FUNCTION test (VAL INT z) + INT a,b,c,d: + VALOF + SEQ + a := z + b := 10 + c := 15 + d := 20 + RESULT a,b,c,d +: + + +PROC init() + INT a,b,c,d: + SEQ + a,b,c,d := test(5) +: \ No newline at end of file diff --git a/tss-occam-test-resources/src/main/resources/function-tests/function_vp_2_in_1_out.occ b/tss-occam-test-resources/src/main/resources/function-tests/function_vp_2_in_1_out.occ new file mode 100644 index 0000000..e786817 --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/function-tests/function_vp_2_in_1_out.occ @@ -0,0 +1,14 @@ +INT FUNCTION test (VAL INT z, VAL INT y) + INT a: + VALOF + SEQ + a := z + RESULT a +: + + +PROC init() + INT a: + SEQ + a := test(5,10) +: \ No newline at end of file diff --git a/tss-occam-test-resources/src/main/resources/function-tests/function_vp_2_in_2_out.occ b/tss-occam-test-resources/src/main/resources/function-tests/function_vp_2_in_2_out.occ new file mode 100644 index 0000000..da50dee --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/function-tests/function_vp_2_in_2_out.occ @@ -0,0 +1,15 @@ +INT,INT FUNCTION test (VAL INT z, VAL INT y) + INT a,b: + VALOF + SEQ + a := z + b := y + RESULT a,b +: + + +PROC init() + INT a,b: + SEQ + a,b := test(5,10) +: \ No newline at end of file diff --git a/tss-occam-test-resources/src/main/resources/function-tests/function_vp_2_in_3_out.occ b/tss-occam-test-resources/src/main/resources/function-tests/function_vp_2_in_3_out.occ new file mode 100644 index 0000000..344f0f6 --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/function-tests/function_vp_2_in_3_out.occ @@ -0,0 +1,16 @@ +INT,INT,INT FUNCTION test (VAL INT z, VAL INT y) + INT a,b,c: + VALOF + SEQ + a := z + b := y + c := 10 + RESULT a,b,c +: + + +PROC init() + INT a,b,c: + SEQ + a,b,c := test(5,10) +: \ No newline at end of file diff --git a/tss-occam-test-resources/src/main/resources/function-tests/function_vp_2_in_4_out.occ b/tss-occam-test-resources/src/main/resources/function-tests/function_vp_2_in_4_out.occ new file mode 100644 index 0000000..c024258 --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/function-tests/function_vp_2_in_4_out.occ @@ -0,0 +1,17 @@ +INT,INT,INT,INT FUNCTION test (VAL INT z, VAL INT y) + INT a,b,c,d: + VALOF + SEQ + a := z + b := y + c := 10 + d := 15 + RESULT a,b,c,d +: + + +PROC init() + INT a,b,c,d: + SEQ + a,b,c,d := test(5,10) +: \ No newline at end of file diff --git a/tss-occam-test-resources/src/main/resources/function-tests/function_vp_3_in_1_out.occ b/tss-occam-test-resources/src/main/resources/function-tests/function_vp_3_in_1_out.occ new file mode 100644 index 0000000..c68c308 --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/function-tests/function_vp_3_in_1_out.occ @@ -0,0 +1,14 @@ +INT FUNCTION test (VAL INT z, VAL INT y, VAL INT x) + INT a: + VALOF + SEQ + a := z + RESULT a +: + + +PROC init() + INT a: + SEQ + a := test(5,10,15) +: \ No newline at end of file diff --git a/tss-occam-test-resources/src/main/resources/function-tests/function_vp_3_in_2_out.occ b/tss-occam-test-resources/src/main/resources/function-tests/function_vp_3_in_2_out.occ new file mode 100644 index 0000000..99ccb67 --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/function-tests/function_vp_3_in_2_out.occ @@ -0,0 +1,15 @@ +INT,INT FUNCTION test (VAL INT z, VAL INT y, VAL INT x) + INT a,b: + VALOF + SEQ + a := z + b := y + RESULT a,b +: + + +PROC init() + INT a,b: + SEQ + a,b := test(5,10,15) +: \ No newline at end of file diff --git a/tss-occam-test-resources/src/main/resources/function-tests/function_vp_3_in_3_out.occ b/tss-occam-test-resources/src/main/resources/function-tests/function_vp_3_in_3_out.occ new file mode 100644 index 0000000..15afd1e --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/function-tests/function_vp_3_in_3_out.occ @@ -0,0 +1,16 @@ +INT,INT,INT FUNCTION test (VAL INT z, VAL INT y, VAL INT x) + INT a,b,c: + VALOF + SEQ + a := z + b := y + c := x + RESULT a,b,c +: + + +PROC init() + INT a,b,c: + SEQ + a,b,c := test(5,10,15) +: \ No newline at end of file diff --git a/tss-occam-test-resources/src/main/resources/function-tests/function_vp_3_in_4_out.occ b/tss-occam-test-resources/src/main/resources/function-tests/function_vp_3_in_4_out.occ new file mode 100644 index 0000000..bf89c25 --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/function-tests/function_vp_3_in_4_out.occ @@ -0,0 +1,17 @@ +INT,INT,INT,INT FUNCTION test (VAL INT z, VAL INT y, VAL INT x) + INT a,b,c,d: + VALOF + SEQ + a := z + b := y + c := x + d := 10 + RESULT a,b,c,d +: + + +PROC init() + INT a,b,c,d: + SEQ + a,b,c,d := test(5,10,15) +: \ No newline at end of file diff --git a/tss-occam-test-resources/src/main/resources/function-tests/function_vp_4_in_1_out.occ b/tss-occam-test-resources/src/main/resources/function-tests/function_vp_4_in_1_out.occ new file mode 100644 index 0000000..543b642 --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/function-tests/function_vp_4_in_1_out.occ @@ -0,0 +1,14 @@ +INT FUNCTION test (VAL INT z, VAL INT y, VAL INT x, VAL INT w) + INT a: + VALOF + SEQ + a := z + RESULT a +: + + +PROC init() + INT a: + SEQ + a := test(5,10,15,20) +: \ No newline at end of file diff --git a/tss-occam-test-resources/src/main/resources/function-tests/function_vp_4_in_2_out.occ b/tss-occam-test-resources/src/main/resources/function-tests/function_vp_4_in_2_out.occ new file mode 100644 index 0000000..d4fd4e5 --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/function-tests/function_vp_4_in_2_out.occ @@ -0,0 +1,15 @@ +INT,INT FUNCTION test (VAL INT z, VAL INT y, VAL INT x, VAL INT w) + INT a,b: + VALOF + SEQ + a := z + b := 10 + RESULT a,b +: + + +PROC init() + INT a,b: + SEQ + a,b := test(5,10,15,20) +: \ No newline at end of file diff --git a/tss-occam-test-resources/src/main/resources/function-tests/function_vp_4_in_3_out.occ b/tss-occam-test-resources/src/main/resources/function-tests/function_vp_4_in_3_out.occ new file mode 100644 index 0000000..e9e5f0b --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/function-tests/function_vp_4_in_3_out.occ @@ -0,0 +1,16 @@ +INT,INT,INT FUNCTION test (VAL INT z, VAL INT y, VAL INT x, VAL INT w) + INT a,b,c: + VALOF + SEQ + a := z + b := 10 + c := 15 + RESULT a,b,c +: + + +PROC init() + INT a,b,c: + SEQ + a,b,c := test(5,10,15,20) +: \ No newline at end of file diff --git a/tss-occam-test-resources/src/main/resources/function-tests/function_vp_4_in_4_out.occ b/tss-occam-test-resources/src/main/resources/function-tests/function_vp_4_in_4_out.occ new file mode 100644 index 0000000..ffcd9ce --- /dev/null +++ b/tss-occam-test-resources/src/main/resources/function-tests/function_vp_4_in_4_out.occ @@ -0,0 +1,20 @@ +INT,INT,INT,INT FUNCTION test (VAL INT z, VAL INT y, VAL INT x, VAL INT w) + INT a,b,c,d: + VALOF + SEQ + a := z + b := y + c := 60 + d := w + RESULT a,b,c,d +: + + +PROC init() + INT a,b,c,d,e: + SEQ + a,b,c,d := test(5,10,15,20) + e := a + a := c + c := e +: \ No newline at end of file diff --git a/tss-transputer-assembler-test/pom.xml b/tss-transputer-assembler-test/pom.xml new file mode 100644 index 0000000..ef9a18c --- /dev/null +++ b/tss-transputer-assembler-test/pom.xml @@ -0,0 +1,121 @@ + + 4.0.0 + + uk.co.transputersystems + tss-transputer-assembler-test + 1.0-SNAPSHOT + + jar + tss-transputer-assembler-test + + + UTF-8 + + + + + junit + junit + 4.12 + + + + org.assertj + assertj-core + 3.3.0 + test + + + + com.google.code.findbugs + jsr305 + 2.0.1 + + + + uk.co.transputersystems + tss-transputer-assembler + 1.0-SNAPSHOT + + + + uk.co.transputersystems + tss-occam-test-resources + 1.0-SNAPSHOT + test + + + + uk.co.transputersystems + tss-occam-compiler + 1.0-SNAPSHOT + test + + + + + + ${project.basedir}/src/test/resources + + + ${project.build.directory}/maven-shared-archive-resources + + **/*.occ + + + + install + + + org.apache.maven.plugins + maven-surefire-plugin + 2.19.1 + + 0 + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.5.1 + + 1.8 + 1.8 + + + + maven-remote-resources-plugin + 1.5 + + + + process + + + + uk.co.transputersystems:tss-occam-test-resources:1.0-SNAPSHOT + + + + + + + maven-javadoc-plugin + 2.10.3 + + ch.raffael.doclets.pegdown.PegdownDoclet + + ch.raffael.pegdown-doclet + pegdown-doclet + 1.2.1 + + true + + + + + + + \ No newline at end of file diff --git a/tss-transputer-assembler-test/src/test/java/uk/co/transputersystems/transputer/assembler/AssembleFileTest.java b/tss-transputer-assembler-test/src/test/java/uk/co/transputersystems/transputer/assembler/AssembleFileTest.java new file mode 100644 index 0000000..008b6d8 --- /dev/null +++ b/tss-transputer-assembler-test/src/test/java/uk/co/transputersystems/transputer/assembler/AssembleFileTest.java @@ -0,0 +1,614 @@ +package uk.co.transputersystems.transputer.assembler; + +import uk.co.transputersystems.occam.*; +import uk.co.transputersystems.occam.il.ILBlock; +import uk.co.transputersystems.occam.il.ILOp; +import uk.co.transputersystems.occam.metadata.LibraryInformation; +import uk.co.transputersystems.occam.open_transputer.ASMBlock; +import uk.co.transputersystems.occam.open_transputer.ASMGenerator; +import uk.co.transputersystems.occam.open_transputer.ASMGeneratorContext; +import org.antlr.v4.runtime.tree.ParseTree; +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; + +import java.io.*; +import java.nio.file.Files; +import java.util.List; +import java.util.UUID; + +import static org.junit.Assert.assertTrue; + +/** + * Created by Edward on 01/05/2016. + */ +public class AssembleFileTest { + + @Before + public void before() throws Exception { + File dir = new File("target/test-output/assemble-file-test/function-tests"); + File dir2 = new File("target/test-output/assemble-file-test/feature-tests"); + File dir3 = new File("target/test-output/assemble-file-test/basic-tests"); + dir.mkdirs(); + dir2.mkdirs(); + dir3.mkdirs(); + } + + public InputStream getResource(String name) { + return getClass().getResourceAsStream(name); + } + + /** + * Given a file, attempt to parse and compile it to TSIL. + * @param file The file to be compiled + * @return true if the compilation appears to have succeeded, otherwise false. + */ + public boolean testAssemblingFile(File file) throws Exception { + return testAssemblingFile(file, true); + } + /** + * Given a file, attempt to parse and compile it to TSIL. Checks that the + * compiled code is not null or empty. + * TODO: find a way to test the output other than checking nullity + * @param file The file to be compiled + * @param verbose Whether to print debug output or not. + * @return true if the compilation appears to have succeeded, otherwise false. + */ + public boolean testAssemblingFile(File file, boolean verbose) throws Exception { + PrintStream out = new PrintStream(System.out); + + if (verbose) { + out.println("TEST: " + file); + out.flush(); + } + + String input = new String(Files.readAllBytes(file.toPath())); + List output = Assembler.assemble(input, Assembler.loadConfig(null), out); + + assertTrue(output != null); + assertTrue(output.size() > 0); + + FileWriter outputWriter = new FileWriter(new File(file.getPath().replace(".auto.", ".").replace(".s",".auto.o"))); + for (String line : output) { + outputWriter.append(line); + outputWriter.append('\n'); + } + outputWriter.close(); + + return true; + } + + /** + * Given a file, attempt to parse and compile it to TSIL. + * + * @param file The file to be compiled + * @return true if the compilation appears to have succeeded, otherwise false. + */ + public File testCompilingFile(InputStream file, String filePath, String fileName) throws Exception { + return testCompilingFile(file, filePath, fileName, true); + } + + /** + * Given a file, attempt to parse and compile it to TSIL. Checks that the + * compiled code is not null or empty. + * TODO: find a way to test the output other than checking nullity + * + * @param inputStream The file to be compiled + * @param verbose Whether to print debug output or not. + * @return true if the compilation appears to have succeeded, otherwise false. + */ + public File testCompilingFile(InputStream inputStream, String filePath, String fileName, boolean verbose) throws Exception { + ErrorListener errorListener = new ErrorListener(); + OccamCompiler compiler = new OccamCompiler(); + + PrintWriter out = new PrintWriter(System.out); + + if (verbose) { + out.println("TEST: " + inputStream); + } + + ParseTree tree = compiler.makeParseTree(inputStream, OccamParser::file_input, errorListener); + + if (verbose) { + compiler.printParseTree(out, tree); + } + + LibraryInformation libraryInfo = new LibraryInformation("TEST"); + List>> intermediate = compiler.generateTSIL(new TSILGenerator(libraryInfo), tree, filePath, fileName); + + assertTrue(intermediate != null); + assertTrue(intermediate.size() > 0); + + // Convert UUID IL to sequential integer-labelled IL + List>> intermediateRef = compiler.generateReferencedTSIL(new ReferencedTSILGenerator<>(), intermediate); + + ASMGeneratorContext asmGeneratorContext = new ASMGeneratorContext(libraryInfo); + + List asmBlocks = compiler.generateASM(new ASMGenerator(), intermediateRef, asmGeneratorContext, false); + + assertTrue(asmBlocks != null); + assertTrue(asmBlocks.size() > 0); + + if (verbose) { + compiler.writeDivider(out); + compiler.writeASMBlocks(out, asmBlocks); + compiler.writeDivider(out); + out.flush(); + } + + File outputFile = new File("target/test-output/assemble-file-test" + filePath.replace(".occ", ".auto.s")); + FileWriter outputWriter = new FileWriter(outputFile); + compiler.writeASMBlocks(outputWriter, asmBlocks); + outputWriter.flush(); + outputWriter.close(); + + return outputFile; + } + + @Ignore("Not yet fully implemented") + @Test + public void testArrays() throws Exception { + String path = "/feature-tests/array.occ"; + File asmFile = testCompilingFile(getResource(path), path, "array.occ"); + assertTrue(testAssemblingFile(asmFile)); + } + + @Ignore("Not yet fully implemented") + @Test + public void testArraySegments() throws Exception { + String path = "/feature-tests/array_segment.occ"; + File asmFile = testCompilingFile(getResource(path), path, "array_segment.occ"); + assertTrue(testAssemblingFile(asmFile)); + } + + @Test + public void testAssignment() throws Exception { + String path = "/feature-tests/assignment.occ"; + File asmFile = testCompilingFile(getResource(path), path, "assignment.occ"); + assertTrue(testAssemblingFile(asmFile)); + } + + @Test + public void testByteLiterals() throws Exception { + String path = "/feature-tests/byte_literal.occ"; + File asmFile = testCompilingFile(getResource(path), path, "byte_literal.occ"); + assertTrue(testAssemblingFile(asmFile)); + } + + @Test + public void testChannels() throws Exception { + String path = "/feature-tests/channels.occ"; + File asmFile = testCompilingFile(getResource(path), path, "channels.occ"); + assertTrue(testAssemblingFile(asmFile)); + } + + @Test + public void testConditionals() throws Exception { + String path = "/feature-tests/conditional.occ"; + File asmFile = testCompilingFile(getResource(path), path, "conditional.occ"); + assertTrue(testAssemblingFile(asmFile)); + } + + @Test + public void testDeclarations() throws Exception { + String path = "/feature-tests/declarations.occ"; + File asmFile = testCompilingFile(getResource(path), path, "declarations.occ"); + assertTrue(testAssemblingFile(asmFile)); + } + + @Test + public void testDyadicExpressions() throws Exception { + String path = "/feature-tests/dyadic_expression.occ"; + File asmFile = testCompilingFile(getResource(path), path, "dyadic_expression.occ"); + assertTrue(testAssemblingFile(asmFile)); + } + + @Test + public void testNestedExpressionFeatures() throws Exception { + String path = "/feature-tests/expression_features_nested.occ"; + File asmFile = testCompilingFile(getResource(path), path, "expression_features_nested.occ"); + assertTrue(testAssemblingFile(asmFile)); + } + + @Test + public void testFunctionsOfExpressionList() throws Exception { + String path = "/function-tests/function_expression_list.occ"; + File asmFile = testCompilingFile(getResource(path), path, "function_expression_list.occ"); + assertTrue(testAssemblingFile(asmFile)); + } + + @Test + public void testFunctionsOfValueProcess() throws Exception { + String path = "/function-tests/function_value_process.occ"; + File asmFile = testCompilingFile(getResource(path), path, "function_value_process.occ"); + assertTrue(testAssemblingFile(asmFile)); + } + + @Test + public void testFunctionsVp0In1Out() throws Exception { + String path = "/function-tests/function_vp_0_in_1_out.occ"; + File asmFile = testCompilingFile(getResource(path), path, "function_vp_0_in_1_out.occ"); + assertTrue(testAssemblingFile(asmFile)); + } + + @Test + public void testFunctionsVp0In2Out() throws Exception { + String path = "/function-tests/function_vp_0_in_2_out.occ"; + File asmFile = testCompilingFile(getResource(path), path, "function_vp_0_in_2_out.occ"); + assertTrue(testAssemblingFile(asmFile)); + } + + @Test + public void testFunctionsVp0In3Out() throws Exception { + String path = "/function-tests/function_vp_0_in_3_out.occ"; + File asmFile = testCompilingFile(getResource(path), path, "function_vp_0_in_3_out.occ"); + assertTrue(testAssemblingFile(asmFile)); + } + + @Test + public void testFunctionsVp0In4Out() throws Exception { + String path = "/function-tests/function_vp_0_in_4_out.occ"; + File asmFile = testCompilingFile(getResource(path), path, "function_vp_0_in_4_out.occ"); + assertTrue(testAssemblingFile(asmFile)); + } + + @Test + public void testFunctionsVp1In1Out() throws Exception { + String path = "/function-tests/function_vp_1_in_1_out.occ"; + File asmFile = testCompilingFile(getResource(path), path, "function_vp_1_in_1_out.occ"); + assertTrue(testAssemblingFile(asmFile)); + } + + @Test + public void testFunctionsVp1In2Out() throws Exception { + String path = "/function-tests/function_vp_1_in_2_out.occ"; + File asmFile = testCompilingFile(getResource(path), path, "function_vp_1_in_2_out.occ"); + assertTrue(testAssemblingFile(asmFile)); + } + + @Test + public void testFunctionsVp1In3Out() throws Exception { + String path = "/function-tests/function_vp_1_in_3_out.occ"; + File asmFile = testCompilingFile(getResource(path), path, "function_vp_1_in_3_out.occ"); + assertTrue(testAssemblingFile(asmFile)); + } + + @Test + public void testFunctionsVp1In4Out() throws Exception { + String path = "/function-tests/function_vp_1_in_4_out.occ"; + File asmFile = testCompilingFile(getResource(path), path, "function_vp_1_in_4_out.occ"); + assertTrue(testAssemblingFile(asmFile)); + } + + @Test + public void testFunctionsVp2In1Out() throws Exception { + String path = "/function-tests/function_vp_2_in_1_out.occ"; + File asmFile = testCompilingFile(getResource(path), path, "function_vp_2_in_1_out.occ"); + assertTrue(testAssemblingFile(asmFile)); + } + + @Test + public void testFunctionsVp2In2Out() throws Exception { + String path = "/function-tests/function_vp_2_in_2_out.occ"; + File asmFile = testCompilingFile(getResource(path), path, "function_vp_2_in_2_out.occ"); + assertTrue(testAssemblingFile(asmFile)); + } + + @Test + public void testFunctionsVp2In3Out() throws Exception { + String path = "/function-tests/function_vp_2_in_3_out.occ"; + File asmFile = testCompilingFile(getResource(path), path, "function_vp_2_in_3_out.occ"); + assertTrue(testAssemblingFile(asmFile)); + } + + @Test + public void testFunctionsVp2In4Out() throws Exception { + String path = "/function-tests/function_vp_2_in_4_out.occ"; + File asmFile = testCompilingFile(getResource(path), path, "function_vp_2_in_4_out.occ"); + assertTrue(testAssemblingFile(asmFile)); + } + + @Test + public void testFunctionsVp3In1Out() throws Exception { + String path = "/function-tests/function_vp_3_in_1_out.occ"; + File asmFile = testCompilingFile(getResource(path), path, "function_vp_3_in_1_out.occ"); + assertTrue(testAssemblingFile(asmFile)); + } + + @Test + public void testFunctionsVp3In2Out() throws Exception { + String path = "/function-tests/function_vp_3_in_2_out.occ"; + File asmFile = testCompilingFile(getResource(path), path, "function_vp_3_in_2_out.occ"); + assertTrue(testAssemblingFile(asmFile)); + } + + @Test + public void testFunctionsVp3In3Out() throws Exception { + String path = "/function-tests/function_vp_3_in_3_out.occ"; + File asmFile = testCompilingFile(getResource(path), path, "function_vp_3_in_3_out.occ"); + assertTrue(testAssemblingFile(asmFile)); + } + + @Test + public void testFunctionsVp3In4Out() throws Exception { + String path = "/function-tests/function_vp_3_in_4_out.occ"; + File asmFile = testCompilingFile(getResource(path), path, "function_vp_3_in_4_out.occ"); + assertTrue(testAssemblingFile(asmFile)); + } + + @Test + public void testFunctionsVp4In1Out() throws Exception { + String path = "/function-tests/function_vp_4_in_1_out.occ"; + File asmFile = testCompilingFile(getResource(path), path, "function_vp_4_in_1_out.occ"); + assertTrue(testAssemblingFile(asmFile)); + } + + @Test + public void testFunctionsVp4In2Out() throws Exception { + String path = "/function-tests/function_vp_4_in_2_out.occ"; + File asmFile = testCompilingFile(getResource(path), path, "function_vp_4_in_2_out.occ"); + assertTrue(testAssemblingFile(asmFile)); + } + + @Test + public void testFunctionsVp4In3Out() throws Exception { + String path = "/function-tests/function_vp_4_in_3_out.occ"; + File asmFile = testCompilingFile(getResource(path), path, "function_vp_4_in_3_out.occ"); + assertTrue(testAssemblingFile(asmFile)); + } + + @Test + public void testFunctionsVp4In4Out() throws Exception { + String path = "/function-tests/function_vp_4_in_4_out.occ"; + File asmFile = testCompilingFile(getResource(path), path, "function_vp_4_in_4_out.occ"); + assertTrue(testAssemblingFile(asmFile)); + } + + @Test + public void testFunctionsEl0In1Out() throws Exception { + String path = "/function-tests/function_el_0_in_1_out.occ"; + File asmFile = testCompilingFile(getResource(path), path, "function_el_0_in_1_out.occ"); + assertTrue(testAssemblingFile(asmFile)); + } + + @Test + public void testFunctionsEl0In2Out() throws Exception { + String path = "/function-tests/function_el_0_in_2_out.occ"; + File asmFile = testCompilingFile(getResource(path), path, "function_el_0_in_2_out.occ"); + assertTrue(testAssemblingFile(asmFile)); + } + + @Test + public void testFunctionsEl0In3Out() throws Exception { + String path = "/function-tests/function_el_0_in_3_out.occ"; + File asmFile = testCompilingFile(getResource(path), path, "function_el_0_in_3_out.occ"); + assertTrue(testAssemblingFile(asmFile)); + } + + @Test + public void testFunctionsEl0In4Out() throws Exception { + String path = "/function-tests/function_el_0_in_4_out.occ"; + File asmFile = testCompilingFile(getResource(path), path, "function_el_0_in_4_out.occ"); + assertTrue(testAssemblingFile(asmFile)); + } + + @Test + public void testFunctionsEl1In1Out() throws Exception { + String path = "/function-tests/function_el_1_in_1_out.occ"; + File asmFile = testCompilingFile(getResource(path), path, "function_el_1_in_1_out.occ"); + assertTrue(testAssemblingFile(asmFile)); + } + + @Test + public void testFunctionsEl1In2Out() throws Exception { + String path = "/function-tests/function_el_1_in_2_out.occ"; + File asmFile = testCompilingFile(getResource(path), path, "function_el_1_in_2_out.occ"); + assertTrue(testAssemblingFile(asmFile)); + } + + @Test + public void testFunctionsEl1In3Out() throws Exception { + String path = "/function-tests/function_el_1_in_3_out.occ"; + File asmFile = testCompilingFile(getResource(path), path, "function_el_1_in_3_out.occ"); + assertTrue(testAssemblingFile(asmFile)); + } + + @Test + public void testFunctionsEl1In4Out() throws Exception { + String path = "/function-tests/function_el_1_in_4_out.occ"; + File asmFile = testCompilingFile(getResource(path), path, "function_el_1_in_4_out.occ"); + assertTrue(testAssemblingFile(asmFile)); + } + + @Test + public void testFunctionsEl2In1Out() throws Exception { + String path = "/function-tests/function_el_2_in_1_out.occ"; + File asmFile = testCompilingFile(getResource(path), path, "function_el_2_in_1_out.occ"); + assertTrue(testAssemblingFile(asmFile)); + } + + @Test + public void testFunctionsEl2In2Out() throws Exception { + String path = "/function-tests/function_el_2_in_2_out.occ"; + File asmFile = testCompilingFile(getResource(path), path, "function_el_2_in_2_out.occ"); + assertTrue(testAssemblingFile(asmFile)); + } + + @Test + public void testFunctionsEl2In3Out() throws Exception { + String path = "/function-tests/function_el_2_in_3_out.occ"; + File asmFile = testCompilingFile(getResource(path), path, "function_el_2_in_3_out.occ"); + assertTrue(testAssemblingFile(asmFile)); + } + + @Test + public void testFunctionsEl2In4Out() throws Exception { + String path = "/function-tests/function_el_2_in_4_out.occ"; + File asmFile = testCompilingFile(getResource(path), path, "function_el_2_in_4_out.occ"); + assertTrue(testAssemblingFile(asmFile)); + } + + @Test + public void testFunctionsEl3In1Out() throws Exception { + String path = "/function-tests/function_el_3_in_1_out.occ"; + File asmFile = testCompilingFile(getResource(path), path, "function_el_3_in_1_out.occ"); + assertTrue(testAssemblingFile(asmFile)); + } + + @Test + public void testFunctionsEl3In2Out() throws Exception { + String path = "/function-tests/function_el_3_in_2_out.occ"; + File asmFile = testCompilingFile(getResource(path), path, "function_el_3_in_2_out.occ"); + assertTrue(testAssemblingFile(asmFile)); + } + + @Test + public void testFunctionsEl3In3Out() throws Exception { + String path = "/function-tests/function_el_3_in_3_out.occ"; + File asmFile = testCompilingFile(getResource(path), path, "function_el_3_in_3_out.occ"); + assertTrue(testAssemblingFile(asmFile)); + } + + @Test + public void testFunctionsEl3In4Out() throws Exception { + String path = "/function-tests/function_el_3_in_4_out.occ"; + File asmFile = testCompilingFile(getResource(path), path, "function_el_3_in_4_out.occ"); + assertTrue(testAssemblingFile(asmFile)); + } + + @Test + public void testFunctionsEl4In1Out() throws Exception { + String path = "/function-tests/function_el_4_in_1_out.occ"; + File asmFile = testCompilingFile(getResource(path), path, "function_el_4_in_1_out.occ"); + assertTrue(testAssemblingFile(asmFile)); + } + + @Test + public void testFunctionsEl4In2Out() throws Exception { + String path = "/function-tests/function_el_4_in_2_out.occ"; + File asmFile = testCompilingFile(getResource(path), path, "function_el_4_in_2_out.occ"); + assertTrue(testAssemblingFile(asmFile)); + } + + @Test + public void testFunctionsEl4In3Out() throws Exception { + String path = "/function-tests/function_el_4_in_3_out.occ"; + File asmFile = testCompilingFile(getResource(path), path, "function_el_4_in_3_out.occ"); + assertTrue(testAssemblingFile(asmFile)); + } + + @Test + public void testFunctionsEl4In4Out() throws Exception { + String path = "/function-tests/function_el_4_in_4_out.occ"; + File asmFile = testCompilingFile(getResource(path), path, "function_el_4_in_4_out.occ"); + assertTrue(testAssemblingFile(asmFile)); + } + + @Test + public void testMonadicExpressions() throws Exception { + String path = "/feature-tests/monadic_expressions.occ"; + File asmFile = testCompilingFile(getResource(path), path, "monadic_expressions.occ"); + assertTrue(testAssemblingFile(asmFile)); + } + + @Test + public void testTypeOperations() throws Exception { + String path = "/feature-tests/operations_types.occ"; + File asmFile = testCompilingFile(getResource(path), path, "operations_types.occ"); + assertTrue(testAssemblingFile(asmFile)); + } + + @Test + public void testPars() throws Exception { + String path = "/feature-tests/par.occ"; + File asmFile = testCompilingFile(getResource(path), path, "par.occ"); + assertTrue(testAssemblingFile(asmFile)); + } + + @Test + public void testParAdvanced() throws Exception { + String path = "/feature-tests/par_advanced.occ"; + File asmFile = testCompilingFile(getResource(path), path, "par_advanced.occ"); + assertTrue(testAssemblingFile(asmFile)); + } + + @Test + public void testProcArguments() throws Exception { + String path = "/feature-tests/proc_arguments.occ"; + File asmFile = testCompilingFile(getResource(path), path, "proc_arguments.occ"); + assertTrue(testAssemblingFile(asmFile)); + } + + @Test + public void testProcedureStaticAssignment() throws Exception { + String path = "/feature-tests/procedure_static_assignment.occ"; + File asmFile = testCompilingFile(getResource(path), path, "procedure_static_assignment.occ"); + assertTrue(testAssemblingFile(asmFile)); + } + + @Ignore("Not yet fully implemented") + @Test + public void testRecordDeclarations() throws Exception { + String path = "/feature-tests/record_declaration.occ"; + File asmFile = testCompilingFile(getResource(path), path, "record_declaration.occ"); + assertTrue(testAssemblingFile(asmFile)); + } + + @Ignore("Not yet fully implemented") + @Test + public void testRecordOperations() throws Exception { + String path = "/feature-tests/record_operations.occ"; + File asmFile = testCompilingFile(getResource(path), path, "record_operations.occ"); + assertTrue(testAssemblingFile(asmFile)); + } + + @Test + public void testReplicatedConditionals() throws Exception { + String path = "/feature-tests/replicated_conditionals.occ"; + File asmFile = testCompilingFile(getResource(path), path, "replicated_conditionals.occ"); + assertTrue(testAssemblingFile(asmFile)); + } + + @Test + public void testReplicators() throws Exception { + String path = "/feature-tests/replicator.occ"; + File asmFile = testCompilingFile(getResource(path), path, "replicator.occ"); + assertTrue(testAssemblingFile(asmFile)); + } + + @Test + public void testSequentials() throws Exception { + String path = "/feature-tests/sequential.occ"; + File asmFile = testCompilingFile(getResource(path), path, "sequential.occ"); + assertTrue(testAssemblingFile(asmFile)); + } + + @Test + public void testVariableAbbreviations() throws Exception { + String path = "/feature-tests/variable_abbreviations.occ"; + File asmFile = testCompilingFile(getResource(path), path, "variable_abbreviations.occ"); + assertTrue(testAssemblingFile(asmFile)); + } + + @Test + public void testChannelAbbreviations() throws Exception { + String path = "/feature-tests/channel_abbreviations.occ"; + File asmFile = testCompilingFile(getResource(path), path, "channel_abbreviations.occ"); + assertTrue(testAssemblingFile(asmFile)); + } + + @Ignore("Not yet fully implemented") + @Test + public void testArrayAbbreviations() throws Exception { + String path = "/feature-tests/array.occ"; + File asmFile = testCompilingFile(getResource(path), path, "array.occ"); + assertTrue(testAssemblingFile(asmFile)); + } + + @Test + public void testWhileLoops() throws Exception { + String path = "/feature-tests/while_loops.occ"; + File asmFile = testCompilingFile(getResource(path), path, "while_loops.occ"); + assertTrue(testAssemblingFile(asmFile)); + } +} diff --git a/tss-transputer-assembler/etc/tas b/tss-transputer-assembler/etc/tas new file mode 100644 index 0000000..6f28fd2 --- /dev/null +++ b/tss-transputer-assembler/etc/tas @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +java -jar "tss-transputer-assembler-1.0-SNAPSHOT-jfx.jar" "$@" \ No newline at end of file diff --git a/tss-transputer-assembler/pom.xml b/tss-transputer-assembler/pom.xml new file mode 100644 index 0000000..0645f76 --- /dev/null +++ b/tss-transputer-assembler/pom.xml @@ -0,0 +1,181 @@ + + 4.0.0 + + uk.co.transputersystems + tss-transputer-assembler + 1.0-SNAPSHOT + + jar + tss-transputer-assembler + + + UTF-8 + tss + tss-transputer-assembler + + + + + org.antlr + antlr4-runtime + 4.5.2 + + + + junit + junit + 4.12 + + + + org.assertj + assertj-core + 3.3.0 + test + + + + com.google.code.findbugs + jsr305 + 2.0.1 + + + + net.sf.jopt-simple + jopt-simple + 5.0 + + + + org.yaml + snakeyaml + 1.17 + + + + uk.co.transputersystems + tss-occam-compiler + 1.0-SNAPSHOT + + + + + + + + ${project.basedir}/src/test/resources + + + ${project.build.directory}/maven-shared-archive-resources + + **/*.occ + + + + src/main/java + install + + + org.apache.maven.plugins + maven-surefire-plugin + 2.19.1 + + 0 + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.5.1 + + 1.8 + 1.8 + + + + org.antlr + antlr4-maven-plugin + 4.5.2 + + true + true + UTF-8 + + + + + antlr4 + + + + + + maven-assembly-plugin + + + + make-compiler-assembly + + occam-compiler + + jar-with-dependencies + + + + uk.co.transputersystems.transputer.assembler.AssemblerApplication + + + + package + + attached + + + + + + maven-remote-resources-plugin + 1.5 + + + + process + + + + uk.co.transputersystems:tss-occam-test-resources:1.0-SNAPSHOT + + + + + + + maven-javadoc-plugin + 2.10.3 + + ch.raffael.doclets.pegdown.PegdownDoclet + + ch.raffael.pegdown-doclet + pegdown-doclet + 1.2.1 + + true + + + + com.zenjava + javafx-maven-plugin + 8.4.0 + + uk.co.transputersystems.transputer.assembler.AssemblerApplication + true + etc + + + + + + + \ No newline at end of file diff --git a/tss-transputer-assembler/src/main/antlr4/uk/co/transputersystems/transputer/assembler/AssemblerExpression.g4 b/tss-transputer-assembler/src/main/antlr4/uk/co/transputersystems/transputer/assembler/AssemblerExpression.g4 new file mode 100644 index 0000000..006edfc --- /dev/null +++ b/tss-transputer-assembler/src/main/antlr4/uk/co/transputersystems/transputer/assembler/AssemblerExpression.g4 @@ -0,0 +1,26 @@ +grammar AssemblerExpression; + +expression: '(' expression ')' #parenExp + | MINUS expression #negExp + | expression '*' expression #mulExp + | expression (MINUS|PLUS) expression #addSubExp + | LABEL #labelExp + | NUMBER #numberExp + ; + +NUMBER: DIGIT+ ; + +LABEL: ( LABEL_SYMBOL | DIGIT | LETTER )+; + +fragment LABEL_SYMBOL: '~' | '_' | '.' ; + +fragment LETTER: ('a' .. 'z') + | ('A' .. 'Z') + ; + +fragment DIGIT: ('0' .. '9') ; + +MINUS: '-' ; +PLUS: '+' ; + +WS : [ \r\n\t] + -> channel (HIDDEN) ; \ No newline at end of file diff --git a/tss-transputer-assembler/src/main/java/uk/co/transputersystems/transputer/assembler/Assembler.java b/tss-transputer-assembler/src/main/java/uk/co/transputersystems/transputer/assembler/Assembler.java new file mode 100644 index 0000000..c0adcd8 --- /dev/null +++ b/tss-transputer-assembler/src/main/java/uk/co/transputersystems/transputer/assembler/Assembler.java @@ -0,0 +1,670 @@ +package uk.co.transputersystems.transputer.assembler; + +import uk.co.transputersystems.transputer.assembler.config.AssemblerConfig; +import uk.co.transputersystems.transputer.assembler.config.IOPin; +import uk.co.transputersystems.transputer.assembler.expression.ExpressionEvaluator; +import org.antlr.v4.runtime.ANTLRInputStream; +import org.antlr.v4.runtime.CommonTokenStream; +import org.antlr.v4.runtime.misc.Pair; +import org.antlr.v4.runtime.tree.ParseTree; +import org.yaml.snakeyaml.Yaml; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.io.PrintStream; +import java.io.Reader; +import java.util.*; +import java.util.function.Function; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +public class Assembler { + + public final static long maxInt = (1L << 31) - 1; + public final static long minInt = -(1L << 31); + + public final static Pattern inputComment = Pattern.compile("^\\h*--\\h*(?\\V*)$"); + // TODO: test underscores, . and ~ in labels + public final static Pattern instructionPattern = Pattern.compile( + "^\\h*((?