├── .antlr-eclipse ├── .checkstyle ├── .checkstyle_checks.xml ├── .checkstyle_suppressions.xml ├── .classpath ├── .github └── workflows │ └── ci.yml ├── .gitignore ├── .gitlab-ci.yml ├── .gitmodules ├── .project ├── .settings ├── org.deved.antlride.core.prefs ├── org.eclipse.jdt.core.prefs └── org.eclipse.jdt.ui.prefs ├── AUTHORS ├── Examples ├── LICENSE ├── Makefile ├── README.md ├── Smalltalk ├── TestSuite ├── awfy-test.conf ├── build.xml ├── rebench.conf ├── som.sh ├── src └── som │ ├── compiler │ ├── BytecodeGenerator.java │ ├── ClassGenerationContext.java │ ├── Disassembler.java │ ├── Lexer.java │ ├── MethodGenerationContext.java │ ├── Parser.java │ ├── ProgramDefinitionError.java │ ├── SourcecodeCompiler.java │ ├── Symbol.java │ └── Triplet.java │ ├── interpreter │ ├── Bytecodes.java │ ├── Frame.java │ └── Interpreter.java │ ├── primitives │ ├── ArrayPrimitives.java │ ├── BlockPrimitives.java │ ├── ClassPrimitives.java │ ├── DoublePrimitives.java │ ├── IntegerPrimitives.java │ ├── MethodPrimitives.java │ ├── ObjectPrimitives.java │ ├── PrimitivePrimitives.java │ ├── Primitives.java │ ├── StringPrimitives.java │ ├── SymbolPrimitives.java │ └── SystemPrimitives.java │ ├── vm │ ├── Shell.java │ └── Universe.java │ └── vmobjects │ ├── SAbstractObject.java │ ├── SArray.java │ ├── SBigInteger.java │ ├── SBlock.java │ ├── SClass.java │ ├── SDouble.java │ ├── SInteger.java │ ├── SInvokable.java │ ├── SMethod.java │ ├── SNumber.java │ ├── SObject.java │ ├── SPrimitive.java │ ├── SString.java │ └── SSymbol.java └── tests └── som ├── compiler └── LexerTests.java └── tests ├── BasicInterpreterTests.java └── SomTests.java /.antlr-eclipse: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /.checkstyle: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /.checkstyle_checks.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | -------------------------------------------------------------------------------- /.checkstyle_suppressions.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: Tests 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | test_som: 7 | runs-on: ubuntu-24.04 # ubuntu-latest 8 | steps: 9 | - name: Checkout 10 | uses: actions/checkout@v4 11 | with: 12 | submodules: true 13 | 14 | - name: Tests 15 | run: | 16 | ant test 17 | 18 | - name: SomSom Tests 19 | run: | 20 | ./som.sh -cp core-lib/Smalltalk:core-lib/TestSuite:core-lib/SomSom/src/compiler:core-lib/SomSom/src/vm:core-lib/SomSom/src/vmobjects:core-lib/SomSom/src/interpreter:core-lib/SomSom/src/primitives \ 21 | core-lib/SomSom/tests/SomSomTests.som 22 | 23 | - name: CheckStyle 24 | run: | 25 | ant checkstyle 26 | 27 | - name: Download Eclipse 28 | run: | 29 | export ECLIPSE_TAR=eclipse.tar.gz 30 | export ECLIPSE_URL=https://www.eclipse.org/downloads/download.php?file=/eclipse/downloads/drops4/R-4.22-202111241800/eclipse-SDK-4.22-linux-gtk-x86_64.tar.gz 31 | wget ${ECLIPSE_URL} -O ${ECLIPSE_TAR} 32 | tar -C ${GITHUB_WORKSPACE}/.. -xzf ${ECLIPSE_TAR} 33 | 34 | - name: Check Eclipse Format 35 | run: | 36 | export ECLIPSE_EXE=${GITHUB_WORKSPACE}/../eclipse/eclipse 37 | ant eclipseformat 38 | 39 | - name: Checkout AWFY 40 | uses: actions/checkout@v4 41 | with: 42 | repository: smarr/are-we-fast-yet 43 | path: are-we-fast-yet 44 | 45 | - name: AWFY Test Run 46 | run: | 47 | pwd 48 | export JAVA_HOME=$JAVA_HOME_8_X64 49 | pip install ReBench 50 | rebench awfy-test.conf 51 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | 3 | -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | stages: 2 | - test-benchmark 3 | 4 | variables: 5 | PYTHONUNBUFFERED: "true" 6 | 7 | before_script: 8 | - git submodule update --init 9 | 10 | som: 11 | stage: test-benchmark 12 | tags: [benchmarks, infinity] 13 | script: 14 | - ant test 15 | - ./som.sh -cp ./Smalltalk ./TestSuite/TestHarness.som 16 | - ./som.sh -cp core-lib/Smalltalk:core-lib/TestSuite:core-lib/SomSom/src/compiler:core-lib/SomSom/src/vm:core-lib/SomSom/src/vmobjects:core-lib/SomSom/src/interpreter:core-lib/SomSom/src/primitives core-lib/SomSom/tests/SomSomTests.som 17 | - ant checkstyle 18 | 19 | - rebench --experiment="CI ID $CI_PIPELINE_ID" --branch="$CI_COMMIT_REF_NAME" -c rebench.conf all 20 | - rebench --experiment="CI ID $CI_PIPELINE_ID" --report-completion rebench.conf 21 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "core-lib"] 2 | path = core-lib 3 | url = https://github.com/SOM-st/SOM.git 4 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | SOM-java 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.dltk.core.scriptbuilder 10 | 11 | 12 | 13 | 14 | org.eclipse.jdt.core.javabuilder 15 | 16 | 17 | 18 | 19 | net.sf.eclipsecs.core.CheckstyleBuilder 20 | 21 | 22 | 23 | 24 | 25 | org.eclipse.jdt.core.javanature 26 | net.sf.eclipsecs.core.CheckstyleNature 27 | 28 | 29 | -------------------------------------------------------------------------------- /.settings/org.deved.antlride.core.prefs: -------------------------------------------------------------------------------- 1 | #Thu Jul 23 08:49:05 CEST 2009 2 | antlr_core_mark_generated_resources_as_derived=false 3 | eclipse.preferences.version=1 4 | -------------------------------------------------------------------------------- /.settings/org.eclipse.jdt.ui.prefs: -------------------------------------------------------------------------------- 1 | cleanup.add_default_serial_version_id=true 2 | cleanup.add_generated_serial_version_id=false 3 | cleanup.add_missing_annotations=true 4 | cleanup.add_missing_deprecated_annotations=true 5 | cleanup.add_missing_methods=false 6 | cleanup.add_missing_nls_tags=false 7 | cleanup.add_missing_override_annotations=true 8 | cleanup.add_missing_override_annotations_interface_methods=true 9 | cleanup.add_serial_version_id=false 10 | cleanup.always_use_blocks=true 11 | cleanup.always_use_parentheses_in_expressions=false 12 | cleanup.always_use_this_for_non_static_field_access=false 13 | cleanup.always_use_this_for_non_static_method_access=false 14 | cleanup.convert_functional_interfaces=false 15 | cleanup.convert_to_enhanced_for_loop=false 16 | cleanup.correct_indentation=false 17 | cleanup.format_source_code=true 18 | cleanup.format_source_code_changes_only=false 19 | cleanup.insert_inferred_type_arguments=false 20 | cleanup.make_local_variable_final=true 21 | cleanup.make_parameters_final=false 22 | cleanup.make_private_fields_final=true 23 | cleanup.make_type_abstract_if_missing_method=false 24 | cleanup.make_variable_declarations_final=false 25 | cleanup.never_use_blocks=false 26 | cleanup.never_use_parentheses_in_expressions=true 27 | cleanup.organize_imports=true 28 | cleanup.qualify_static_field_accesses_with_declaring_class=false 29 | cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true 30 | cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true 31 | cleanup.qualify_static_member_accesses_with_declaring_class=true 32 | cleanup.qualify_static_method_accesses_with_declaring_class=false 33 | cleanup.remove_private_constructors=true 34 | cleanup.remove_redundant_type_arguments=false 35 | cleanup.remove_trailing_whitespaces=true 36 | cleanup.remove_trailing_whitespaces_all=true 37 | cleanup.remove_trailing_whitespaces_ignore_empty=false 38 | cleanup.remove_unnecessary_casts=true 39 | cleanup.remove_unnecessary_nls_tags=true 40 | cleanup.remove_unused_imports=true 41 | cleanup.remove_unused_local_variables=false 42 | cleanup.remove_unused_private_fields=true 43 | cleanup.remove_unused_private_members=false 44 | cleanup.remove_unused_private_methods=true 45 | cleanup.remove_unused_private_types=true 46 | cleanup.sort_members=false 47 | cleanup.sort_members_all=false 48 | cleanup.use_anonymous_class_creation=false 49 | cleanup.use_blocks=false 50 | cleanup.use_blocks_only_for_return_and_throw=false 51 | cleanup.use_lambda=true 52 | cleanup.use_parentheses_in_expressions=false 53 | cleanup.use_this_for_non_static_field_access=false 54 | cleanup.use_this_for_non_static_field_access_only_if_necessary=true 55 | cleanup.use_this_for_non_static_method_access=false 56 | cleanup.use_this_for_non_static_method_access_only_if_necessary=true 57 | cleanup_profile=_SOM 58 | cleanup_settings_version=2 59 | eclipse.preferences.version=1 60 | editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true 61 | formatter_profile=_SOM 62 | formatter_settings_version=12 63 | internal.default.compliance=default 64 | sp_cleanup.add_default_serial_version_id=true 65 | sp_cleanup.add_generated_serial_version_id=false 66 | sp_cleanup.add_missing_annotations=true 67 | sp_cleanup.add_missing_deprecated_annotations=true 68 | sp_cleanup.add_missing_methods=false 69 | sp_cleanup.add_missing_nls_tags=false 70 | sp_cleanup.add_missing_override_annotations=true 71 | sp_cleanup.add_missing_override_annotations_interface_methods=true 72 | sp_cleanup.add_serial_version_id=false 73 | sp_cleanup.always_use_blocks=true 74 | sp_cleanup.always_use_parentheses_in_expressions=false 75 | sp_cleanup.always_use_this_for_non_static_field_access=false 76 | sp_cleanup.always_use_this_for_non_static_method_access=false 77 | sp_cleanup.convert_functional_interfaces=false 78 | sp_cleanup.convert_to_enhanced_for_loop=false 79 | sp_cleanup.correct_indentation=false 80 | sp_cleanup.format_source_code=false 81 | sp_cleanup.format_source_code_changes_only=false 82 | sp_cleanup.insert_inferred_type_arguments=false 83 | sp_cleanup.make_local_variable_final=false 84 | sp_cleanup.make_parameters_final=true 85 | sp_cleanup.make_private_fields_final=false 86 | sp_cleanup.make_type_abstract_if_missing_method=false 87 | sp_cleanup.make_variable_declarations_final=true 88 | sp_cleanup.never_use_blocks=false 89 | sp_cleanup.never_use_parentheses_in_expressions=true 90 | sp_cleanup.on_save_use_additional_actions=true 91 | sp_cleanup.organize_imports=true 92 | sp_cleanup.qualify_static_field_accesses_with_declaring_class=false 93 | sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true 94 | sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true 95 | sp_cleanup.qualify_static_member_accesses_with_declaring_class=false 96 | sp_cleanup.qualify_static_method_accesses_with_declaring_class=false 97 | sp_cleanup.remove_private_constructors=true 98 | sp_cleanup.remove_redundant_type_arguments=false 99 | sp_cleanup.remove_trailing_whitespaces=true 100 | sp_cleanup.remove_trailing_whitespaces_all=true 101 | sp_cleanup.remove_trailing_whitespaces_ignore_empty=false 102 | sp_cleanup.remove_unnecessary_casts=true 103 | sp_cleanup.remove_unnecessary_nls_tags=false 104 | sp_cleanup.remove_unused_imports=true 105 | sp_cleanup.remove_unused_local_variables=false 106 | sp_cleanup.remove_unused_private_fields=true 107 | sp_cleanup.remove_unused_private_members=false 108 | sp_cleanup.remove_unused_private_methods=true 109 | sp_cleanup.remove_unused_private_types=true 110 | sp_cleanup.sort_members=false 111 | sp_cleanup.sort_members_all=false 112 | sp_cleanup.use_anonymous_class_creation=false 113 | sp_cleanup.use_blocks=true 114 | sp_cleanup.use_blocks_only_for_return_and_throw=false 115 | sp_cleanup.use_lambda=false 116 | sp_cleanup.use_parentheses_in_expressions=false 117 | sp_cleanup.use_this_for_non_static_field_access=false 118 | sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true 119 | sp_cleanup.use_this_for_non_static_method_access=false 120 | sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true 121 | sp_cleanup.use_type_arguments=false 122 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | This file lists all people who have contributed to the SOM VM. 2 | 3 | SOM was originally implemented at the University of Aarhus (Denmark) in 4 | 2001/2002. The implementation of SOM was done by Jakob Roland Andersen, Kasper 5 | Verdich Lund, Lars Bak, Mads Torgersen, and Ulrik Pagh Schultz. They also 6 | wrote the original versions of the SOM Smalltalk libraries, test suites, and 7 | benchmarks, that are (in extended versions) bundled with SOM. 8 | 9 | SOM was used by Michael Haupt in courses on virtual machines at Lancaster 10 | University and Technische Universitaet Darmstadt (Germany) in VM courses in 11 | 2006. During that time, some changes were applied to SOM by Michael Haupt and 12 | Sebastian Kanthak. 13 | 14 | SOM is currently maintained by Michael Haupt at the Hasso-Plattner-Institut, 15 | University of Potsdam, Germany. 16 | 17 | 2009-08-14, Michael Haupt 18 | michael.haupt@hpi.uni-potsdam.de -------------------------------------------------------------------------------- /Examples: -------------------------------------------------------------------------------- 1 | core-lib/Examples -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009 Michael Haupt, michael.haupt@hpi.uni-potsdam.de 2 | Software Architecture Group, Hasso Plattner Institute, Potsdam, Germany 3 | http://www.hpi.uni-potsdam.de/swa/ 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env make -f 2 | 3 | all: compile 4 | 5 | clean: 6 | ant clean 7 | 8 | compile: build/som.jar 9 | 10 | build/som.jar: 11 | ant jar 12 | 13 | test: 14 | ant test 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | SOM - Simple Object Machine 2 | =========================== 3 | 4 | SOM is a minimal Smalltalk dialect used to teach VM construction at the [Hasso 5 | Plattner Institute][SOM]. It was originally built at the University of Århus 6 | (Denmark) where it was also used for teaching. 7 | 8 | Currently, implementations exist for Java (SOM), C (CSOM), C++ (SOM++), and 9 | Squeak/Pharo Smalltalk (AweSOM). 10 | 11 | A simple SOM Hello World looks like: 12 | 13 | ```Smalltalk 14 | Hello = ( 15 | run = ( 16 | 'Hello World!' println. 17 | ) 18 | ) 19 | ``` 20 | 21 | This repository contains a plain Java implementation of SOM, including an implementation of the SOM standard library. Please see the [main project page][SOMst] for links to the VM implementation. 22 | 23 | Make sure to initialize the shared Smalltalk standard library, tests, and examples by importing the git submodule: 24 | 25 | $ git submodule update --init 26 | 27 | To build and run SOM, Java 8 or newer is required. 28 | 29 | SOM can be built with Ant: 30 | 31 | $ ant jar 32 | 33 | Afterwards, the tests can be executed with: 34 | 35 | $ ./som.sh -cp Smalltalk TestSuite/TestHarness.som 36 | 37 | or with: 38 | 39 | $ ant test 40 | 41 | A simple Hello World program is executed with: 42 | 43 | $ ./som.sh -cp Smalltalk Examples/Hello.som 44 | 45 | 46 | Information on previous authors are included in the AUTHORS file. This code is 47 | distributed under the MIT License. Please see the LICENSE file for details. 48 | 49 | Build Status 50 | ------------ 51 | 52 | Thanks to Travis CI, all commits of this repository are tested. 53 | The current build status is: [![Build Status](https://travis-ci.org/SOM-st/som-java.png?branch=master)](https://travis-ci.org/SOM-st/som-java) 54 | 55 | [SOM]: http://www.hpi.uni-potsdam.de/hirschfeld/projects/som/ 56 | [SOMst]: https://travis-ci.org/SOM-st/ 57 | -------------------------------------------------------------------------------- /Smalltalk: -------------------------------------------------------------------------------- 1 | core-lib/Smalltalk -------------------------------------------------------------------------------- /TestSuite: -------------------------------------------------------------------------------- 1 | core-lib/TestSuite -------------------------------------------------------------------------------- /awfy-test.conf: -------------------------------------------------------------------------------- 1 | # -*- mode: yaml -*- 2 | # Config file for ReBench 3 | default_experiment: all 4 | default_data_file: 'benchmark.data' 5 | 6 | runs: 7 | iterations: 1 8 | invocations: 1 9 | 10 | # definition of benchmark suites 11 | benchmark_suites: 12 | test-som: 13 | gauge_adapter: RebenchLog 14 | command: " -cp .:Core:CD:DeltaBlue:Havlak:Json:NBody:Richards:../../../core-lib/Smalltalk Harness.som %(benchmark)s 1 " 15 | location: are-we-fast-yet/benchmarks/SOM 16 | max_invocation_time: 240 17 | benchmarks: &BENCHMARKS 18 | - DeltaBlue: 19 | extra_args: 1 20 | - Richards: 21 | extra_args: 1 22 | - Json: 23 | extra_args: 1 24 | - CD: 25 | extra_args: 10 26 | - Havlak: 27 | extra_args: 1 28 | 29 | - Bounce: 30 | extra_args: 1 31 | - List: 32 | extra_args: 1 33 | - Mandelbrot: 34 | extra_args: 1 35 | - NBody: 36 | extra_args: 1 37 | - Permute: 38 | extra_args: 1 39 | - Queens: 40 | extra_args: 1 41 | - Sieve: 42 | extra_args: 1 43 | - Storage: 44 | extra_args: 1 45 | - Towers: 46 | extra_args: 1 47 | 48 | executors: 49 | SOM: 50 | path: . 51 | executable: som.sh 52 | 53 | experiments: 54 | test-awfy: 55 | description: | 56 | This is a test run of the Are We Fast Yet benchmarks. 57 | It's expected that the repository is located in the are-we-fast-yet folder. 58 | suites: 59 | - test-som 60 | executions: 61 | - SOM 62 | -------------------------------------------------------------------------------- /build.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 63 | 66 | 67 | 68 | 69 | 70 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | -------------------------------------------------------------------------------- /rebench.conf: -------------------------------------------------------------------------------- 1 | # -*- mode: yaml -*- 2 | # Config file for ReBench 3 | default_experiment: all 4 | default_data_file: 'rebench.data' 5 | 6 | reporting: 7 | # Benchmark results will be reported to ReBenchDB 8 | rebenchdb: 9 | # this url needs to point to the API endpoint 10 | db_url: https://rebench.stefan-marr.de/rebenchdb 11 | repo_url: https://github.com/smarr/SOM-java 12 | record_all: true # make sure everything is recorded 13 | project_name: SOM 14 | 15 | runs: 16 | max_invocation_time: 120 17 | 18 | benchmark_suites: 19 | macro: 20 | gauge_adapter: RebenchLog 21 | command: &MACRO_CMD "-cp Smalltalk:Examples/Benchmarks/Richards:Examples/Benchmarks/DeltaBlue:Examples/Benchmarks/NBody:Examples/Benchmarks/Json:Examples/Benchmarks/GraphSearch Examples/Benchmarks/BenchmarkHarness.som %(benchmark)s %(iterations)s " 22 | iterations: 10 23 | benchmarks: 24 | - Richards: {extra_args: 1} 25 | - DeltaBlue: {extra_args: 50} 26 | - NBody: {extra_args: 500} 27 | - JsonSmall: {extra_args: 1} 28 | - GraphSearch: {extra_args: 4} 29 | - PageRank: {extra_args: 40} 30 | 31 | micro: 32 | gauge_adapter: RebenchLog 33 | command: "-cp Smalltalk:Examples/Benchmarks/LanguageFeatures Examples/Benchmarks/BenchmarkHarness.som %(benchmark)s %(iterations)s " 34 | iterations: 10 35 | benchmarks: 36 | - Fannkuch: {extra_args: 6} 37 | - Fibonacci: {extra_args: 3} 38 | - Dispatch: {extra_args: 2} 39 | - Bounce: {extra_args: 2} 40 | - Loop: {extra_args: 5} 41 | - Permute: {extra_args: 3} 42 | - Queens: {extra_args: 2} 43 | - List: {extra_args: 2} 44 | - Recurse: {extra_args: 3} 45 | - Storage: {extra_args: 1} 46 | - Sieve: {extra_args: 4} 47 | - BubbleSort: {extra_args: 3} 48 | - QuickSort: {extra_args: 1} 49 | - Sum: {extra_args: 2} 50 | - Towers: {extra_args: 2} 51 | - TreeSort: {extra_args: 1} 52 | - IntegerLoop: {extra_args: 2} 53 | - FieldLoop: {extra_args: 1} 54 | - WhileLoop: {extra_args: 10} 55 | - Mandelbrot: {extra_args: 30} 56 | 57 | micro-somsom: 58 | gauge_adapter: RebenchLog 59 | command: "-cp Smalltalk:Examples/Benchmarks/LanguageFeatures Examples/Benchmarks/BenchmarkHarness.som %(benchmark)s %(iterations)s 0 " 60 | iterations: 1 61 | benchmarks: 62 | - Loop: {extra_args: 1} 63 | - Queens: {extra_args: 1} 64 | - List: {extra_args: 1} 65 | - Recurse: {extra_args: 1} 66 | - Mandelbrot: {extra_args: 3} 67 | 68 | interpreter: 69 | description: Basic interpreter benchmarks for comparing performance of most basic concepts. 70 | gauge_adapter: RebenchLog 71 | invocations: 5 72 | command: "-cp Smalltalk:Examples/Benchmarks/Interpreter Examples/Benchmarks/BenchmarkHarness.som %(benchmark)s %(iterations)s 1" 73 | benchmarks: 74 | - ArgRead 75 | - ArrayReadConst 76 | - ArrayWriteConstConst 77 | - BlockSend0ConstReturn 78 | - Const 79 | - FieldConstWrite 80 | - FieldRead 81 | - FieldReadIncWrite 82 | - FieldReadWrite 83 | - GlobalRead 84 | - LocalConstWrite 85 | - LocalRead 86 | - LocalReadIncWrite 87 | - LocalReadWrite 88 | - SelfSend0 89 | - SelfSend0BlockConstNonLocalReturn 90 | 91 | executors: 92 | som: {path: ., executable: som.sh} 93 | somsom: 94 | path: . 95 | executable: som.sh 96 | args: "-cp core-lib/Smalltalk:core-lib/TestSuite:core-lib/SomSom/src/compiler:core-lib/SomSom/src/vm:core-lib/SomSom/src/vmobjects:core-lib/SomSom/src/interpreter:core-lib/SomSom/src/primitives core-lib/SomSom/src/vm/Main.som" 97 | 98 | 99 | # define the benchmarks to be executed for a re-executable benchmark run 100 | experiments: 101 | SOM-java: 102 | description: All benchmarks on SOM (Java) 103 | suites: 104 | - micro 105 | - macro 106 | - interpreter 107 | executions: 108 | - som 109 | SomSom: 110 | description: Running a few SomSom benchmarks on SOM (Java) 111 | suites: 112 | - micro-somsom 113 | executions: 114 | - somsom 115 | -------------------------------------------------------------------------------- /som.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | pushd `dirname $0` > /dev/null 3 | SCRIPT_PATH=`pwd` 4 | popd > /dev/null 5 | 6 | java -server -cp "${SCRIPT_PATH}/build/classes":"${SCRIPT_PATH}/build/som.jar" som.vm.Universe "$@" 7 | -------------------------------------------------------------------------------- /src/som/compiler/BytecodeGenerator.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2017 Michael Haupt, github@haupz.de 3 | * Copyright (c) 2009 Michael Haupt, michael.haupt@hpi.uni-potsdam.de 4 | * Software Architecture Group, Hasso Plattner Institute, Potsdam, Germany 5 | * http://www.hpi.uni-potsdam.de/swa/ 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | package som.compiler; 27 | 28 | import static som.interpreter.Bytecodes.*; 29 | 30 | import som.vmobjects.SAbstractObject; 31 | import som.vmobjects.SMethod; 32 | import som.vmobjects.SSymbol; 33 | 34 | 35 | public class BytecodeGenerator { 36 | 37 | public void emitPOP(final MethodGenerationContext mgenc) { 38 | emit1(mgenc, POP); 39 | } 40 | 41 | public void emitPUSHARGUMENT(final MethodGenerationContext mgenc, final byte idx, 42 | final byte ctx) { 43 | emit3(mgenc, PUSH_ARGUMENT, idx, ctx); 44 | } 45 | 46 | public void emitRETURNLOCAL(final MethodGenerationContext mgenc) { 47 | emit1(mgenc, RETURN_LOCAL); 48 | } 49 | 50 | public void emitRETURNNONLOCAL(final MethodGenerationContext mgenc) { 51 | emit1(mgenc, RETURN_NON_LOCAL); 52 | } 53 | 54 | public void emitDUP(final MethodGenerationContext mgenc) { 55 | emit1(mgenc, DUP); 56 | } 57 | 58 | public void emitPUSHBLOCK(final MethodGenerationContext mgenc, final SMethod blockMethod) { 59 | emit2(mgenc, PUSH_BLOCK, mgenc.findLiteralIndex(blockMethod)); 60 | } 61 | 62 | public void emitPUSHLOCAL(final MethodGenerationContext mgenc, final byte idx, 63 | final byte ctx) { 64 | assert idx >= 0; 65 | emit3(mgenc, PUSH_LOCAL, idx, ctx); 66 | } 67 | 68 | public void emitPUSHFIELD(final MethodGenerationContext mgenc, final SSymbol fieldName) { 69 | assert mgenc.hasField(fieldName); 70 | emit2(mgenc, PUSH_FIELD, mgenc.getFieldIndex(fieldName)); 71 | } 72 | 73 | public void emitPUSHGLOBAL(final MethodGenerationContext mgenc, final SSymbol global) { 74 | emit2(mgenc, PUSH_GLOBAL, mgenc.findLiteralIndex(global)); 75 | } 76 | 77 | public void emitPOPARGUMENT(final MethodGenerationContext mgenc, final byte idx, 78 | final byte ctx) { 79 | emit3(mgenc, POP_ARGUMENT, idx, ctx); 80 | } 81 | 82 | public void emitPOPLOCAL(final MethodGenerationContext mgenc, final byte idx, 83 | final byte ctx) { 84 | emit3(mgenc, POP_LOCAL, idx, ctx); 85 | } 86 | 87 | public void emitPOPFIELD(final MethodGenerationContext mgenc, final SSymbol fieldName) { 88 | assert mgenc.hasField(fieldName); 89 | emit2(mgenc, POP_FIELD, mgenc.getFieldIndex(fieldName)); 90 | } 91 | 92 | public void emitSUPERSEND(final MethodGenerationContext mgenc, final SSymbol msg) { 93 | emit2(mgenc, SUPER_SEND, mgenc.findLiteralIndex(msg)); 94 | } 95 | 96 | public void emitSEND(final MethodGenerationContext mgenc, final SSymbol msg) { 97 | emit2(mgenc, SEND, mgenc.findLiteralIndex(msg)); 98 | } 99 | 100 | public void emitPUSHCONSTANT(final MethodGenerationContext mgenc, 101 | final SAbstractObject lit) { 102 | emit2(mgenc, PUSH_CONSTANT, mgenc.findLiteralIndex(lit)); 103 | } 104 | 105 | public void emitPUSHCONSTANT(final MethodGenerationContext mgenc, final byte literalIndex) { 106 | emit2(mgenc, PUSH_CONSTANT, literalIndex); 107 | } 108 | 109 | private void emit1(final MethodGenerationContext mgenc, final byte code) { 110 | mgenc.addBytecode(code); 111 | } 112 | 113 | private void emit2(final MethodGenerationContext mgenc, final byte code, final byte idx) { 114 | mgenc.addBytecode(code); 115 | mgenc.addBytecode(idx); 116 | } 117 | 118 | private void emit3(final MethodGenerationContext mgenc, final byte code, final byte idx, 119 | final byte ctx) { 120 | mgenc.addBytecode(code); 121 | mgenc.addBytecode(idx); 122 | mgenc.addBytecode(ctx); 123 | } 124 | 125 | } 126 | -------------------------------------------------------------------------------- /src/som/compiler/ClassGenerationContext.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2013 Stefan Marr, stefan.marr@vub.ac.be 3 | * Copyright (c) 2009 Michael Haupt, michael.haupt@hpi.uni-potsdam.de 4 | * Software Architecture Group, Hasso Plattner Institute, Potsdam, Germany 5 | * http://www.hpi.uni-potsdam.de/swa/ 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | package som.compiler; 26 | 27 | import java.util.ArrayList; 28 | import java.util.List; 29 | 30 | import som.vm.Universe; 31 | import som.vmobjects.SArray; 32 | import som.vmobjects.SClass; 33 | import som.vmobjects.SInvokable; 34 | import som.vmobjects.SSymbol; 35 | 36 | 37 | public class ClassGenerationContext { 38 | 39 | private final Universe universe; 40 | 41 | public ClassGenerationContext(final Universe universe) { 42 | this.universe = universe; 43 | } 44 | 45 | private SSymbol name; 46 | private SSymbol superName; 47 | private boolean classSide; 48 | private final List instanceFields = new ArrayList(); 49 | private final List instanceMethods = new ArrayList(); 50 | private final List classFields = new ArrayList(); 51 | private final List classMethods = new ArrayList(); 52 | 53 | public SSymbol getName() { 54 | return name; 55 | } 56 | 57 | public void setName(final SSymbol name) { 58 | this.name = name; 59 | } 60 | 61 | public void setSuperName(final SSymbol superName) { 62 | this.superName = superName; 63 | } 64 | 65 | public void setInstanceFieldsOfSuper(final SArray fieldNames) { 66 | int numFields = fieldNames.getNumberOfIndexableFields(); 67 | for (int i = 0; i < numFields; i++) { 68 | instanceFields.add((SSymbol) fieldNames.getIndexableField(i)); 69 | } 70 | } 71 | 72 | public void setClassFieldsOfSuper(final SArray fieldNames) { 73 | int numFields = fieldNames.getNumberOfIndexableFields(); 74 | for (int i = 0; i < numFields; i++) { 75 | classFields.add((SSymbol) fieldNames.getIndexableField(i)); 76 | } 77 | } 78 | 79 | public void addMethod(final som.vmobjects.SInvokable meth) { 80 | if (classSide) { 81 | classMethods.add(meth); 82 | } else { 83 | instanceMethods.add(meth); 84 | } 85 | } 86 | 87 | public void startClassSide() { 88 | classSide = true; 89 | } 90 | 91 | public void addField(final SSymbol field) { 92 | if (classSide) { 93 | classFields.add(field); 94 | } else { 95 | instanceFields.add(field); 96 | } 97 | } 98 | 99 | public boolean hasField(final SSymbol field) { 100 | return (isClassSide() ? classFields : instanceFields).contains(field); 101 | } 102 | 103 | public byte getFieldIndex(final SSymbol field) { 104 | if (isClassSide()) { 105 | return (byte) classFields.indexOf(field); 106 | } else { 107 | return (byte) instanceFields.indexOf(field); 108 | } 109 | } 110 | 111 | public boolean isClassSide() { 112 | return classSide; 113 | } 114 | 115 | public SClass assemble() throws ProgramDefinitionError { 116 | // build class class name 117 | String ccname = name.getEmbeddedString() + " class"; 118 | 119 | // Load the super class 120 | SClass superClass = universe.loadClass(superName); 121 | 122 | // Allocate the class of the resulting class 123 | SClass resultClass = universe.newClass(universe.metaclassClass); 124 | 125 | // Initialize the class of the resulting class 126 | resultClass.setInstanceFields(universe.newArray(classFields)); 127 | resultClass.setInstanceInvokables(universe.newArray(classMethods)); 128 | resultClass.setName(universe.symbolFor(ccname)); 129 | 130 | SClass superMClass = superClass.getSOMClass(); 131 | resultClass.setSuperClass(superMClass); 132 | 133 | // Allocate the resulting class 134 | SClass result = universe.newClass(resultClass); 135 | 136 | // Initialize the resulting class 137 | result.setName(name); 138 | result.setSuperClass(superClass); 139 | result.setInstanceFields(universe.newArray(instanceFields)); 140 | result.setInstanceInvokables(universe.newArray(instanceMethods)); 141 | 142 | return result; 143 | } 144 | 145 | public SClass assembleSystemClass(final SClass systemClass) { 146 | systemClass.setInstanceInvokables(universe.newArray(instanceMethods)); 147 | systemClass.setInstanceFields(universe.newArray(instanceFields)); 148 | // class-bound == class-instance-bound 149 | SClass superMClass = systemClass.getSOMClass(); 150 | superMClass.setInstanceInvokables(universe.newArray(classMethods)); 151 | superMClass.setInstanceFields(universe.newArray(classFields)); 152 | return systemClass; 153 | } 154 | 155 | } 156 | -------------------------------------------------------------------------------- /src/som/compiler/Disassembler.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2017 Michael Haupt, github@haupz.de 3 | * Copyright (c) 2013 Stefan Marr, stefan.marr@vub.ac.be 4 | * Copyright (c) 2009 Michael Haupt, michael.haupt@hpi.uni-potsdam.de 5 | * Software Architecture Group, Hasso Plattner Institute, Potsdam, Germany 6 | * http://www.hpi.uni-potsdam.de/swa/ 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | package som.compiler; 28 | 29 | import static som.interpreter.Bytecodes.POP_ARGUMENT; 30 | import static som.interpreter.Bytecodes.POP_FIELD; 31 | import static som.interpreter.Bytecodes.POP_LOCAL; 32 | import static som.interpreter.Bytecodes.PUSH_ARGUMENT; 33 | import static som.interpreter.Bytecodes.PUSH_BLOCK; 34 | import static som.interpreter.Bytecodes.PUSH_CONSTANT; 35 | import static som.interpreter.Bytecodes.PUSH_FIELD; 36 | import static som.interpreter.Bytecodes.PUSH_GLOBAL; 37 | import static som.interpreter.Bytecodes.PUSH_LOCAL; 38 | import static som.interpreter.Bytecodes.SEND; 39 | import static som.interpreter.Bytecodes.SUPER_SEND; 40 | import static som.interpreter.Bytecodes.getBytecodeLength; 41 | import static som.interpreter.Bytecodes.getPaddedBytecodeName; 42 | 43 | import som.vm.Universe; 44 | import som.vmobjects.SAbstractObject; 45 | import som.vmobjects.SClass; 46 | import som.vmobjects.SInvokable; 47 | import som.vmobjects.SMethod; 48 | import som.vmobjects.SSymbol; 49 | 50 | 51 | public class Disassembler { 52 | 53 | public static void dump(final SClass cl, final Universe universe) { 54 | for (int i = 0; i < cl.getNumberOfInstanceInvokables(); i++) { 55 | SInvokable inv = cl.getInstanceInvokable(i); 56 | 57 | // output header and skip if the Invokable is a Primitive 58 | Universe.errorPrint(cl.getName().toString() + ">>" 59 | + inv.getSignature().toString() + " = "); 60 | 61 | if (inv.isPrimitive()) { 62 | Universe.errorPrintln(""); 63 | continue; 64 | } 65 | // output actual method 66 | dumpMethod((SMethod) inv, "\t", universe); 67 | } 68 | } 69 | 70 | public static void dumpMethod(final SMethod m, final String indent, 71 | final Universe universe) { 72 | Universe.errorPrintln("("); 73 | 74 | // output stack information 75 | Universe.errorPrintln(indent + "<" + m.getNumberOfLocals() + " locals, " 76 | + m.getMaximumNumberOfStackElements() + " stack, " 77 | + m.getNumberOfBytecodes() + " bc_count>"); 78 | 79 | // output bytecodes 80 | for (int b = 0; b < m.getNumberOfBytecodes(); b += 81 | getBytecodeLength(m.getBytecode(b))) { 82 | 83 | Universe.errorPrint(indent); 84 | 85 | // bytecode index 86 | if (b < 10) { 87 | Universe.errorPrint(" "); 88 | } 89 | if (b < 100) { 90 | Universe.errorPrint(" "); 91 | } 92 | Universe.errorPrint(" " + b + ":"); 93 | 94 | // mnemonic 95 | byte bytecode = m.getBytecode(b); 96 | Universe.errorPrint(getPaddedBytecodeName(bytecode) + " "); 97 | 98 | // parameters (if any) 99 | if (getBytecodeLength(bytecode) == 1) { 100 | Universe.errorPrintln(); 101 | continue; 102 | } 103 | switch (bytecode) { 104 | case PUSH_LOCAL: 105 | Universe.errorPrintln("local: " + m.getBytecode(b + 1) + ", context: " 106 | + m.getBytecode(b + 2)); 107 | break; 108 | case PUSH_ARGUMENT: 109 | Universe.errorPrintln("argument: " + m.getBytecode(b + 1) + ", context " 110 | + m.getBytecode(b + 2)); 111 | break; 112 | case PUSH_FIELD: { 113 | int idx = m.getBytecode(b + 1); 114 | String fieldName = ((SSymbol) m.getHolder().getInstanceFields() 115 | .getIndexableField(idx)).getEmbeddedString(); 116 | Universe.errorPrintln("(index: " + idx + ") field: " + fieldName); 117 | break; 118 | } 119 | case PUSH_BLOCK: 120 | Universe.errorPrint("block: (index: " + m.getBytecode(b + 1) + ") "); 121 | dumpMethod((SMethod) m.getConstant(b), indent + "\t", universe); 122 | break; 123 | case PUSH_CONSTANT: 124 | SAbstractObject constant = m.getConstant(b); 125 | Universe.errorPrintln("(index: " + m.getBytecode(b + 1) + ") value: " 126 | + "(" + constant.getSOMClass(universe).getName().toString() + ") " 127 | + constant.toString()); 128 | break; 129 | case PUSH_GLOBAL: 130 | Universe.errorPrintln("(index: " + m.getBytecode(b + 1) + ") value: " 131 | + ((SSymbol) m.getConstant(b)).toString()); 132 | break; 133 | case POP_LOCAL: 134 | Universe.errorPrintln("local: " + m.getBytecode(b + 1) + ", context: " 135 | + m.getBytecode(b + 2)); 136 | break; 137 | case POP_ARGUMENT: 138 | Universe.errorPrintln("argument: " + m.getBytecode(b + 1) 139 | + ", context: " + m.getBytecode(b + 2)); 140 | break; 141 | case POP_FIELD: { 142 | int idx = m.getBytecode(b + 1); 143 | String fieldName = ((SSymbol) m.getHolder().getInstanceFields() 144 | .getIndexableField(idx)).getEmbeddedString(); 145 | Universe.errorPrintln("(index: " + idx + ") field: " + fieldName); 146 | break; 147 | } 148 | case SEND: 149 | Universe.errorPrintln("(index: " + m.getBytecode(b + 1) 150 | + ") signature: " + ((SSymbol) m.getConstant(b)).toString()); 151 | break; 152 | case SUPER_SEND: 153 | Universe.errorPrintln("(index: " + m.getBytecode(b + 1) 154 | + ") signature: " + ((SSymbol) m.getConstant(b)).toString()); 155 | break; 156 | default: 157 | Universe.errorPrintln(""); 158 | } 159 | } 160 | Universe.errorPrintln(indent + ")"); 161 | } 162 | 163 | } 164 | -------------------------------------------------------------------------------- /src/som/compiler/MethodGenerationContext.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2017 Michael Haupt, github@haupz.de 3 | * Copyright (c) 2009 Michael Haupt, michael.haupt@hpi.uni-potsdam.de 4 | * Software Architecture Group, Hasso Plattner Institute, Potsdam, Germany 5 | * http://www.hpi.uni-potsdam.de/swa/ 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | package som.compiler; 27 | 28 | import static som.interpreter.Bytecodes.DUP; 29 | import static som.interpreter.Bytecodes.HALT; 30 | import static som.interpreter.Bytecodes.POP; 31 | import static som.interpreter.Bytecodes.POP_ARGUMENT; 32 | import static som.interpreter.Bytecodes.POP_FIELD; 33 | import static som.interpreter.Bytecodes.POP_LOCAL; 34 | import static som.interpreter.Bytecodes.PUSH_ARGUMENT; 35 | import static som.interpreter.Bytecodes.PUSH_BLOCK; 36 | import static som.interpreter.Bytecodes.PUSH_CONSTANT; 37 | import static som.interpreter.Bytecodes.PUSH_FIELD; 38 | import static som.interpreter.Bytecodes.PUSH_GLOBAL; 39 | import static som.interpreter.Bytecodes.PUSH_LOCAL; 40 | import static som.interpreter.Bytecodes.RETURN_LOCAL; 41 | import static som.interpreter.Bytecodes.RETURN_NON_LOCAL; 42 | import static som.interpreter.Bytecodes.SEND; 43 | import static som.interpreter.Bytecodes.SUPER_SEND; 44 | 45 | import java.util.ArrayList; 46 | import java.util.List; 47 | 48 | import som.compiler.Parser.ParseError; 49 | import som.vm.Universe; 50 | import som.vmobjects.SAbstractObject; 51 | import som.vmobjects.SInvokable; 52 | import som.vmobjects.SMethod; 53 | import som.vmobjects.SPrimitive; 54 | import som.vmobjects.SSymbol; 55 | 56 | 57 | public class MethodGenerationContext { 58 | 59 | private final ClassGenerationContext holderGenc; 60 | private final MethodGenerationContext outerGenc; 61 | private final boolean blockMethod; 62 | 63 | private SSymbol signature; 64 | private final List arguments = new ArrayList(); 65 | private boolean primitive; 66 | private final List locals = new ArrayList(); 67 | private final List literals = new ArrayList(); 68 | private boolean finished; 69 | private final ArrayList bytecode = new ArrayList<>(); 70 | 71 | /** 72 | * Constructor used for block methods. 73 | */ 74 | public MethodGenerationContext(final ClassGenerationContext holderGenc, 75 | final MethodGenerationContext outerGenc) { 76 | this.holderGenc = holderGenc; 77 | this.outerGenc = outerGenc; 78 | blockMethod = outerGenc != null; 79 | } 80 | 81 | /** 82 | * Constructor used for normal methods. 83 | */ 84 | public MethodGenerationContext(final ClassGenerationContext holderGenc) { 85 | this(holderGenc, null); 86 | } 87 | 88 | public void addArgument(final String arg) { 89 | arguments.add(arg); 90 | } 91 | 92 | public boolean isPrimitive() { 93 | return primitive; 94 | } 95 | 96 | public SInvokable assemble(final Universe universe) { 97 | if (primitive) { 98 | return SPrimitive.getEmptyPrimitive(signature.getEmbeddedString(), universe); 99 | } else { 100 | return assembleMethod(universe); 101 | } 102 | } 103 | 104 | public SMethod assembleMethod(final Universe universe) { 105 | // create a method instance with the given number of bytecodes 106 | int numLocals = locals.size(); 107 | 108 | SMethod meth = universe.newMethod(signature, bytecode.size(), 109 | numLocals, computeStackDepth(), 110 | literals); 111 | 112 | // copy bytecodes into method 113 | int i = 0; 114 | for (byte bc : bytecode) { 115 | meth.setBytecode(i++, bc); 116 | } 117 | 118 | // return the method - the holder field is to be set later on! 119 | return meth; 120 | } 121 | 122 | private int computeStackDepth() { 123 | int depth = 0; 124 | int maxDepth = 0; 125 | int i = 0; 126 | 127 | while (i < bytecode.size()) { 128 | switch (bytecode.get(i)) { 129 | case HALT: 130 | i++; 131 | break; 132 | case DUP: 133 | depth++; 134 | i++; 135 | break; 136 | case PUSH_LOCAL: 137 | case PUSH_ARGUMENT: 138 | depth++; 139 | i += 3; 140 | break; 141 | case PUSH_FIELD: 142 | case PUSH_BLOCK: 143 | case PUSH_CONSTANT: 144 | case PUSH_GLOBAL: 145 | depth++; 146 | i += 2; 147 | break; 148 | case POP: 149 | depth--; 150 | i++; 151 | break; 152 | case POP_LOCAL: 153 | case POP_ARGUMENT: 154 | depth--; 155 | i += 3; 156 | break; 157 | case POP_FIELD: 158 | depth--; 159 | i += 2; 160 | break; 161 | case SEND: 162 | case SUPER_SEND: { 163 | // these are special: they need to look at the number of 164 | // arguments (extractable from the signature) 165 | SSymbol sig = (SSymbol) literals.get(bytecode.get(i + 1)); 166 | 167 | depth -= sig.getNumberOfSignatureArguments(); 168 | 169 | depth++; // return value 170 | i += 2; 171 | break; 172 | } 173 | case RETURN_LOCAL: 174 | case RETURN_NON_LOCAL: 175 | i++; 176 | break; 177 | default: 178 | throw new IllegalStateException("Illegal bytecode " 179 | + bytecode.get(i)); 180 | } 181 | 182 | if (depth > maxDepth) { 183 | maxDepth = depth; 184 | } 185 | } 186 | 187 | return maxDepth; 188 | } 189 | 190 | public void markAsPrimitive() { 191 | primitive = true; 192 | } 193 | 194 | public void setSignature(final SSymbol sig) { 195 | signature = sig; 196 | } 197 | 198 | public boolean addArgumentIfAbsent(final String arg) { 199 | if (arguments.contains(arg)) { 200 | return false; 201 | } 202 | 203 | arguments.add(arg); 204 | return true; 205 | } 206 | 207 | public boolean isFinished() { 208 | return finished; 209 | } 210 | 211 | public void markAsFinished() { 212 | this.finished = false; 213 | } 214 | 215 | public boolean addLocalIfAbsent(final String local) { 216 | if (locals.contains(local)) { 217 | return false; 218 | } 219 | 220 | locals.add(local); 221 | return true; 222 | } 223 | 224 | public void addLocal(final String local) { 225 | locals.add(local); 226 | } 227 | 228 | public boolean hasBytecodes() { 229 | return !bytecode.isEmpty(); 230 | } 231 | 232 | public void removeLastBytecode() { 233 | bytecode.remove(bytecode.size() - 1); 234 | } 235 | 236 | public boolean isBlockMethod() { 237 | return blockMethod; 238 | } 239 | 240 | public void setFinished() { 241 | finished = true; 242 | } 243 | 244 | public boolean addLiteralIfAbsent(final SAbstractObject lit, final Parser parser) 245 | throws ParseError { 246 | if (literals.contains(lit)) { 247 | return false; 248 | } 249 | 250 | addLiteral(lit, parser); 251 | return true; 252 | } 253 | 254 | public ClassGenerationContext getHolder() { 255 | return holderGenc; 256 | } 257 | 258 | public byte addLiteral(final SAbstractObject lit, final Parser parser) throws ParseError { 259 | int i = literals.size(); 260 | if (i > Byte.MAX_VALUE) { 261 | String methodSignature = holderGenc.getName().getEmbeddedString() + ">>" + signature; 262 | throw new ParseError( 263 | "The method " + methodSignature + " has more than the supported " + 264 | Byte.MAX_VALUE 265 | + " literal values. Please split the method. The literal to be added is: " + lit, 266 | Symbol.NONE, parser); 267 | } 268 | literals.add(lit); 269 | return (byte) i; 270 | } 271 | 272 | public void updateLiteral(final SAbstractObject oldVal, final byte index, 273 | final SAbstractObject newVal) { 274 | assert literals.get(index) == oldVal; 275 | literals.set(index, newVal); 276 | } 277 | 278 | public boolean findVar(final String var, final Triplet tri) { 279 | // triplet: index, context, isArgument 280 | tri.setX((byte) locals.indexOf(var)); 281 | if (tri.getX() == -1) { 282 | tri.setX((byte) arguments.indexOf(var)); 283 | if (tri.getX() == -1) { 284 | if (outerGenc == null) { 285 | return false; 286 | } else { 287 | tri.setY((byte) (tri.getY() + 1)); 288 | return outerGenc.findVar(var, tri); 289 | } 290 | } else { 291 | tri.setZ(true); 292 | } 293 | } 294 | 295 | return true; 296 | } 297 | 298 | public boolean hasField(final SSymbol field) { 299 | return holderGenc.hasField(field); 300 | } 301 | 302 | public byte getFieldIndex(final SSymbol field) { 303 | return holderGenc.getFieldIndex(field); 304 | } 305 | 306 | public int getNumberOfArguments() { 307 | return arguments.size(); 308 | } 309 | 310 | public void addBytecode(final byte code) { 311 | bytecode.add(code); 312 | } 313 | 314 | public byte findLiteralIndex(final SAbstractObject lit) { 315 | return (byte) literals.indexOf(lit); 316 | } 317 | 318 | public MethodGenerationContext getOuter() { 319 | return outerGenc; 320 | } 321 | } 322 | -------------------------------------------------------------------------------- /src/som/compiler/ProgramDefinitionError.java: -------------------------------------------------------------------------------- 1 | package som.compiler; 2 | 3 | public class ProgramDefinitionError extends Exception { 4 | private static final long serialVersionUID = -2555195397219550779L; 5 | 6 | public ProgramDefinitionError(final String message) { 7 | super(message); 8 | } 9 | 10 | @Override 11 | public String toString() { 12 | return "ProgramDefinitionError: " + getMessage(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/som/compiler/SourcecodeCompiler.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2009 Michael Haupt, michael.haupt@hpi.uni-potsdam.de 3 | * Software Architecture Group, Hasso Plattner Institute, Potsdam, Germany 4 | * http://www.hpi.uni-potsdam.de/swa/ 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | package som.compiler; 26 | 27 | import java.io.FileReader; 28 | import java.io.IOException; 29 | import java.io.StringReader; 30 | 31 | import som.vm.Universe; 32 | import som.vmobjects.SClass; 33 | import som.vmobjects.SSymbol; 34 | 35 | 36 | public class SourcecodeCompiler { 37 | 38 | private Parser parser; 39 | 40 | public static SClass compileClass(final String path, final String file, 41 | final SClass systemClass, final Universe universe) 42 | throws IOException, ProgramDefinitionError { 43 | return new SourcecodeCompiler().compile(path, file, systemClass, universe); 44 | } 45 | 46 | public static SClass compileClass(final String stmt, final SClass systemClass, 47 | final Universe universe) throws ProgramDefinitionError { 48 | return new SourcecodeCompiler().compileClassString(stmt, systemClass, 49 | universe); 50 | } 51 | 52 | private SClass compile(final String path, final String file, 53 | final SClass systemClass, final Universe universe) 54 | throws IOException, ProgramDefinitionError { 55 | String fname = path + Universe.fileSeparator + file + ".som"; 56 | 57 | parser = new Parser(new FileReader(fname), universe, fname); 58 | 59 | SClass result = compile(systemClass); 60 | 61 | SSymbol cname = result.getName(); 62 | String cnameC = cname.getEmbeddedString(); 63 | 64 | if (file != cnameC) { 65 | throw new ProgramDefinitionError("File name " + fname 66 | + " does not match class name (" + cnameC + ") in it."); 67 | } 68 | 69 | return result; 70 | } 71 | 72 | private SClass compileClassString(final String stream, 73 | final SClass systemClass, final Universe universe) 74 | throws ProgramDefinitionError { 75 | parser = new Parser(new StringReader(stream), universe, "$string$"); 76 | 77 | SClass result = compile(systemClass); 78 | return result; 79 | } 80 | 81 | private SClass compile(final SClass systemClass) throws ProgramDefinitionError { 82 | ClassGenerationContext cgc = parser.classdef(); 83 | 84 | if (systemClass == null) { 85 | return cgc.assemble(); 86 | } else { 87 | return cgc.assembleSystemClass(systemClass); 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/som/compiler/Symbol.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2009 Michael Haupt, michael.haupt@hpi.uni-potsdam.de 3 | * Software Architecture Group, Hasso Plattner Institute, Potsdam, Germany 4 | * http://www.hpi.uni-potsdam.de/swa/ 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | package som.compiler; 26 | 27 | enum Symbol { 28 | NONE, Integer, Double, Not, And, Or, Star, Div, Mod, Plus, Minus, Equal, More, 29 | Less, Comma, At, Per, NewBlock, EndBlock, Colon, Period, Exit, Assign, NewTerm, 30 | EndTerm, Pound, Primitive, Separator, STString, Identifier, Keyword, 31 | KeywordSequence, OperatorSequence 32 | } 33 | -------------------------------------------------------------------------------- /src/som/compiler/Triplet.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2009 Michael Haupt, michael.haupt@hpi.uni-potsdam.de 3 | * Software Architecture Group, Hasso Plattner Institute, Potsdam, Germany 4 | * http://www.hpi.uni-potsdam.de/swa/ 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | package som.compiler; 26 | 27 | public class Triplet { 28 | 29 | X x; 30 | Y y; 31 | Z z; 32 | 33 | public Triplet(X x, Y y, Z z) { 34 | setX(x); 35 | setY(y); 36 | setZ(z); 37 | } 38 | 39 | public void setX(X x) { 40 | this.x = x; 41 | } 42 | 43 | public void setY(Y y) { 44 | this.y = y; 45 | } 46 | 47 | public void setZ(Z z) { 48 | this.z = z; 49 | } 50 | 51 | public X getX() { 52 | return x; 53 | } 54 | 55 | public Y getY() { 56 | return y; 57 | } 58 | 59 | public Z getZ() { 60 | return z; 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /src/som/interpreter/Bytecodes.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2017 Michael Haupt, github@haupz.de 3 | * Copyright (c) 2009 Michael Haupt, michael.haupt@hpi.uni-potsdam.de 4 | * Software Architecture Group, Hasso Plattner Institute, Potsdam, Germany 5 | * http://www.hpi.uni-potsdam.de/swa/ 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | package som.interpreter; 27 | 28 | import java.util.stream.Stream; 29 | 30 | 31 | public class Bytecodes { 32 | 33 | // Bytecodes used by the simple object machine 34 | public static final byte HALT = 0; 35 | public static final byte DUP = 1; 36 | public static final byte PUSH_LOCAL = 2; 37 | public static final byte PUSH_ARGUMENT = 3; 38 | public static final byte PUSH_FIELD = 4; 39 | public static final byte PUSH_BLOCK = 5; 40 | public static final byte PUSH_CONSTANT = 6; 41 | public static final byte PUSH_GLOBAL = 7; 42 | public static final byte POP = 8; 43 | public static final byte POP_LOCAL = 9; 44 | public static final byte POP_ARGUMENT = 10; 45 | public static final byte POP_FIELD = 11; 46 | public static final byte SEND = 12; 47 | public static final byte SUPER_SEND = 13; 48 | public static final byte RETURN_LOCAL = 14; 49 | public static final byte RETURN_NON_LOCAL = 15; 50 | 51 | private static final String[] PADDED_BYTECODE_NAMES = new String[] { 52 | "HALT ", "DUP ", "PUSH_LOCAL ", 53 | "PUSH_ARGUMENT ", "PUSH_FIELD ", "PUSH_BLOCK ", 54 | "PUSH_CONSTANT ", "PUSH_GLOBAL ", "POP ", 55 | "POP_LOCAL ", "POP_ARGUMENT ", "POP_FIELD ", 56 | "SEND ", "SUPER_SEND ", "RETURN_LOCAL ", 57 | "RETURN_NON_LOCAL" 58 | }; 59 | 60 | private static final String[] BYTECODE_NAMES = 61 | Stream.of(PADDED_BYTECODE_NAMES).map(String::trim).toArray(String[]::new); 62 | 63 | private static final byte NUM_BYTECODES = (byte) BYTECODE_NAMES.length; 64 | 65 | private static void checkBytecodeIndex(byte bytecode) { 66 | if (bytecode < 0 || bytecode >= NUM_BYTECODES) { 67 | throw new IllegalArgumentException("illegal bytecode: " + bytecode); 68 | } 69 | } 70 | 71 | public static String getBytecodeName(byte bytecode) { 72 | checkBytecodeIndex(bytecode); 73 | return BYTECODE_NAMES[bytecode]; 74 | } 75 | 76 | public static String getPaddedBytecodeName(byte bytecode) { 77 | checkBytecodeIndex(bytecode); 78 | return PADDED_BYTECODE_NAMES[bytecode]; 79 | } 80 | 81 | public static int getBytecodeLength(byte bytecode) { 82 | // Return the length of the given bytecode 83 | return BYTECODE_LENGTH[bytecode]; 84 | } 85 | 86 | // Static array holding lengths of each bytecode 87 | private static final int[] BYTECODE_LENGTH = new int[] { 88 | 1, // HALT 89 | 1, // DUP 90 | 3, // PUSH_LOCAL 91 | 3, // PUSH_ARGUMENT 92 | 2, // PUSH_FIELD 93 | 2, // PUSH_BLOCK 94 | 2, // PUSH_CONSTANT 95 | 2, // PUSH_GLOBAL 96 | 1, // POP 97 | 3, // POP_LOCAL 98 | 3, // POP_ARGUMENT 99 | 2, // POP_FIELD 100 | 2, // SEND 101 | 2, // SUPER_SEND 102 | 1, // RETURN_LOCAL 103 | 1 // RETURN_NON_LOCAL 104 | }; 105 | 106 | } 107 | -------------------------------------------------------------------------------- /src/som/interpreter/Frame.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2009 Michael Haupt, michael.haupt@hpi.uni-potsdam.de 3 | * Software Architecture Group, Hasso Plattner Institute, Potsdam, Germany 4 | * http://www.hpi.uni-potsdam.de/swa/ 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | package som.interpreter; 26 | 27 | import som.vm.Universe; 28 | import som.vmobjects.SAbstractObject; 29 | import som.vmobjects.SMethod; 30 | import som.vmobjects.SObject; 31 | 32 | 33 | /** 34 | * @formatter:off 35 | * Frame layout: 36 | * 37 | * +-----------------+ 38 | * | Arguments | 0 39 | * +-----------------+ 40 | * | Local Variables | <-- localOffset 41 | * +-----------------+ 42 | * | Stack | <-- stackPointer 43 | * | ... | 44 | * +-----------------+ 45 | * @formatter:on 46 | */ 47 | public class Frame { 48 | 49 | public Frame(final SObject nilObject, final Frame previousFrame, 50 | final Frame context, final SMethod method, final long stackElements) { 51 | this.previousFrame = previousFrame; 52 | this.context = context; 53 | this.method = method; 54 | this.stack = new SAbstractObject[(int) stackElements]; 55 | 56 | for (int i = 0; i < stackElements; i++) { 57 | stack[i] = nilObject; 58 | } 59 | 60 | // Reset the stack pointer and the bytecode index 61 | resetStackPointer(); 62 | bytecodeIndex = 0; 63 | } 64 | 65 | public Frame getPreviousFrame() { 66 | return previousFrame; 67 | } 68 | 69 | public void clearPreviousFrame() { 70 | previousFrame = null; 71 | } 72 | 73 | public boolean hasPreviousFrame() { 74 | return previousFrame != null; 75 | } 76 | 77 | public boolean isBootstrapFrame() { 78 | return !hasPreviousFrame(); 79 | } 80 | 81 | public Frame getContext() { 82 | return context; 83 | } 84 | 85 | public boolean hasContext() { 86 | return context != null; 87 | } 88 | 89 | public Frame getContext(int level) { 90 | // Get the context frame at the given level 91 | Frame frame = this; 92 | 93 | // Iterate through the context chain until the given level is reached 94 | while (level > 0) { 95 | // Get the context of the current frame 96 | frame = frame.getContext(); 97 | 98 | // Go to the next level 99 | level = level - 1; 100 | } 101 | 102 | // Return the found context 103 | return frame; 104 | } 105 | 106 | public Frame getOuterContext() { 107 | // Compute the outer context of this frame 108 | Frame frame = this; 109 | 110 | // Iterate through the context chain until null is reached 111 | while (frame.hasContext()) { 112 | frame = frame.getContext(); 113 | } 114 | 115 | // Return the outer context 116 | return frame; 117 | } 118 | 119 | public SMethod getMethod() { 120 | return method; 121 | } 122 | 123 | public SAbstractObject pop() { 124 | // Pop an object from the expression stack and return it 125 | int sp = stackPointer; 126 | stackPointer -= 1; 127 | return stack[sp]; 128 | } 129 | 130 | public void push(final SAbstractObject value) { 131 | // Push an object onto the expression stack 132 | int sp = stackPointer + 1; 133 | stack[sp] = value; 134 | stackPointer = sp; 135 | } 136 | 137 | public void resetStackPointer() { 138 | // arguments are stored in front of local variables 139 | localOffset = getMethod().getNumberOfArguments(); 140 | 141 | // Set the stack pointer to its initial value thereby clearing the stack 142 | stackPointer = localOffset + getMethod().getNumberOfLocals() - 1; 143 | } 144 | 145 | public int getBytecodeIndex() { 146 | // Get the current bytecode index for this frame 147 | return bytecodeIndex; 148 | } 149 | 150 | public void setBytecodeIndex(final int value) { 151 | // Set the current bytecode index for this frame 152 | bytecodeIndex = value; 153 | } 154 | 155 | public SAbstractObject getStackElement(final int index) { 156 | // Get the stack element with the given index 157 | // (an index of zero yields the top element) 158 | return stack[stackPointer - index]; 159 | } 160 | 161 | public void setStackElement(final int index, final SAbstractObject value) { 162 | // Set the stack element with the given index to the given value 163 | // (an index of zero yields the top element) 164 | stack[stackPointer - index] = value; 165 | } 166 | 167 | private SAbstractObject getLocal(final int index) { 168 | return stack[localOffset + index]; 169 | } 170 | 171 | private void setLocal(final int index, final SAbstractObject value) { 172 | stack[localOffset + index] = value; 173 | } 174 | 175 | public SAbstractObject getLocal(final int index, final int contextLevel) { 176 | // Get the local with the given index in the given context 177 | return getContext(contextLevel).getLocal(index); 178 | } 179 | 180 | public void setLocal(final int index, final int contextLevel, final SAbstractObject value) { 181 | // Set the local with the given index in the given context to the given 182 | // value 183 | getContext(contextLevel).setLocal(index, value); 184 | } 185 | 186 | public SAbstractObject getArgument(final int index, final int contextLevel) { 187 | // Get the context 188 | Frame context = getContext(contextLevel); 189 | 190 | // Get the argument with the given index 191 | return context.stack[index]; 192 | } 193 | 194 | public void setArgument(final int index, final int contextLevel, 195 | final SAbstractObject value) { 196 | // Get the context 197 | Frame context = getContext(contextLevel); 198 | 199 | // Set the argument with the given index to the given value 200 | context.stack[index] = value; 201 | } 202 | 203 | public void copyArgumentsFrom(final Frame frame) { 204 | // copy arguments from frame: 205 | // - arguments are at the top of the stack of frame. 206 | // - copy them into the argument area of the current frame 207 | int numArgs = getMethod().getNumberOfArguments(); 208 | for (int i = 0; i < numArgs; ++i) { 209 | stack[i] = frame.getStackElement(numArgs - 1 - i); 210 | } 211 | } 212 | 213 | public void printStackTrace() { 214 | // Print a stack trace starting in this frame 215 | if (hasPreviousFrame()) { 216 | getPreviousFrame().printStackTrace(); 217 | } 218 | 219 | String className = getMethod().getHolder().getName().getEmbeddedString(); 220 | String methodName = getMethod().getSignature().getEmbeddedString(); 221 | Universe.println(className + ">>#" + methodName + " @bi: " + bytecodeIndex); 222 | } 223 | 224 | // Private variables holding the stack pointer and the bytecode index 225 | private int stackPointer; 226 | private int bytecodeIndex; 227 | 228 | // the offset at which local variables start 229 | private int localOffset; 230 | 231 | private final SMethod method; 232 | private final Frame context; 233 | private Frame previousFrame; 234 | private final SAbstractObject[] stack; 235 | } 236 | -------------------------------------------------------------------------------- /src/som/primitives/ArrayPrimitives.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2009 Michael Haupt, michael.haupt@hpi.uni-potsdam.de 3 | * Software Architecture Group, Hasso Plattner Institute, Potsdam, Germany 4 | * http://www.hpi.uni-potsdam.de/swa/ 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | package som.primitives; 26 | 27 | import som.vm.Universe; 28 | import som.vmobjects.SArray; 29 | import som.vmobjects.SInteger; 30 | import som.vmobjects.SAbstractObject; 31 | import som.vmobjects.SPrimitive; 32 | import som.interpreter.Interpreter; 33 | import som.interpreter.Frame; 34 | 35 | 36 | public class ArrayPrimitives extends Primitives { 37 | 38 | public ArrayPrimitives(final Universe universe) { 39 | super(universe); 40 | } 41 | 42 | public void installPrimitives() { 43 | installInstancePrimitive(new SPrimitive("at:", universe) { 44 | 45 | public void invoke(final Frame frame, final Interpreter interpreter) { 46 | SInteger index = (SInteger) frame.pop(); 47 | SArray self = (SArray) frame.pop(); 48 | frame.push(self.getIndexableField(index.getEmbeddedInteger() - 1)); 49 | } 50 | }); 51 | 52 | installInstancePrimitive(new SPrimitive("at:put:", universe) { 53 | 54 | public void invoke(final Frame frame, final Interpreter interpreter) { 55 | SAbstractObject value = frame.pop(); 56 | SInteger index = (SInteger) frame.pop(); 57 | SArray self = (SArray) frame.getStackElement(0); 58 | self.setIndexableField(index.getEmbeddedInteger() - 1, value); 59 | } 60 | }); 61 | 62 | installInstancePrimitive(new SPrimitive("length", universe) { 63 | 64 | public void invoke(final Frame frame, final Interpreter interpreter) { 65 | SArray self = (SArray) frame.pop(); 66 | frame.push(universe.newInteger(self.getNumberOfIndexableFields())); 67 | } 68 | }); 69 | 70 | installClassPrimitive(new SPrimitive("new:", universe) { 71 | 72 | public void invoke(final Frame frame, final Interpreter interpreter) { 73 | SInteger length = (SInteger) frame.pop(); 74 | frame.pop(); // not required 75 | frame.push(universe.newArray(length.getEmbeddedInteger())); 76 | } 77 | }); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/som/primitives/BlockPrimitives.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2009 Michael Haupt, michael.haupt@hpi.uni-potsdam.de 3 | * Software Architecture Group, Hasso Plattner Institute, Potsdam, Germany 4 | * http://www.hpi.uni-potsdam.de/swa/ 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | package som.primitives; 26 | 27 | import som.vm.Universe; 28 | import som.interpreter.Interpreter; 29 | import som.interpreter.Frame; 30 | import som.vmobjects.SPrimitive; 31 | 32 | 33 | public class BlockPrimitives extends Primitives { 34 | 35 | public BlockPrimitives(final Universe universe) { 36 | super(universe); 37 | } 38 | 39 | public void installPrimitives() { 40 | installInstancePrimitive(new SPrimitive("restart", universe) { 41 | 42 | public void invoke(final Frame frame, final Interpreter interpreter) { 43 | frame.setBytecodeIndex(0); 44 | frame.resetStackPointer(); 45 | } 46 | }); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/som/primitives/ClassPrimitives.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2009 Michael Haupt, michael.haupt@hpi.uni-potsdam.de 3 | * Software Architecture Group, Hasso Plattner Institute, Potsdam, Germany 4 | * http://www.hpi.uni-potsdam.de/swa/ 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | package som.primitives; 26 | 27 | import som.interpreter.Frame; 28 | import som.interpreter.Interpreter; 29 | import som.vm.Universe; 30 | import som.vmobjects.SClass; 31 | import som.vmobjects.SPrimitive; 32 | 33 | 34 | public class ClassPrimitives extends Primitives { 35 | 36 | public ClassPrimitives(final Universe universe) { 37 | super(universe); 38 | } 39 | 40 | @Override 41 | public void installPrimitives() { 42 | installInstancePrimitive(new SPrimitive("new", universe) { 43 | 44 | @Override 45 | public void invoke(final Frame frame, final Interpreter interpreter) { 46 | SClass self = (SClass) frame.pop(); 47 | frame.push(universe.newInstance(self)); 48 | } 49 | }); 50 | 51 | installInstancePrimitive(new SPrimitive("name", universe) { 52 | 53 | @Override 54 | public void invoke(final Frame frame, final Interpreter interpreter) { 55 | SClass self = (SClass) frame.pop(); 56 | frame.push(self.getName()); 57 | } 58 | }); 59 | 60 | installInstancePrimitive(new SPrimitive("superclass", universe) { 61 | 62 | @Override 63 | public void invoke(final Frame frame, final Interpreter interpreter) { 64 | SClass self = (SClass) frame.pop(); 65 | frame.push(self.getSuperClass()); 66 | } 67 | }); 68 | 69 | installInstancePrimitive(new SPrimitive("fields", universe) { 70 | 71 | @Override 72 | public void invoke(final Frame frame, final Interpreter interpreter) { 73 | SClass self = (SClass) frame.pop(); 74 | frame.push(self.getInstanceFields()); 75 | } 76 | }); 77 | 78 | installInstancePrimitive(new SPrimitive("methods", universe) { 79 | 80 | @Override 81 | public void invoke(final Frame frame, final Interpreter interpreter) { 82 | SClass self = (SClass) frame.pop(); 83 | frame.push(self.getInstanceInvokables()); 84 | } 85 | }); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/som/primitives/DoublePrimitives.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2009 Michael Haupt, michael.haupt@hpi.uni-potsdam.de 3 | * Software Architecture Group, Hasso Plattner Institute, Potsdam, Germany 4 | * http://www.hpi.uni-potsdam.de/swa/ 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | package som.primitives; 26 | 27 | import som.interpreter.Frame; 28 | import som.interpreter.Interpreter; 29 | import som.vm.Universe; 30 | import som.vmobjects.SAbstractObject; 31 | import som.vmobjects.SDouble; 32 | import som.vmobjects.SNumber; 33 | import som.vmobjects.SPrimitive; 34 | import som.vmobjects.SString; 35 | 36 | 37 | public class DoublePrimitives extends Primitives { 38 | 39 | public DoublePrimitives(final Universe universe) { 40 | super(universe); 41 | } 42 | 43 | @Override 44 | public void installPrimitives() { 45 | installInstancePrimitive(new SPrimitive("asString", universe) { 46 | @Override 47 | public void invoke(final Frame frame, final Interpreter interpreter) { 48 | SDouble self = (SDouble) frame.pop(); 49 | frame.push(self.primAsString(universe)); 50 | } 51 | }); 52 | 53 | installInstancePrimitive(new SPrimitive("asInteger", universe) { 54 | @Override 55 | public void invoke(final Frame frame, final Interpreter interpreter) { 56 | SDouble self = (SDouble) frame.pop(); 57 | frame.push(self.primAsInteger(universe)); 58 | } 59 | }); 60 | 61 | installInstancePrimitive(new SPrimitive("sqrt", universe) { 62 | @Override 63 | public void invoke(final Frame frame, final Interpreter interpreter) { 64 | SDouble self = (SDouble) frame.pop(); 65 | frame.push(self.primSqrt(universe)); 66 | } 67 | }); 68 | 69 | installInstancePrimitive(new SPrimitive("+", universe) { 70 | @Override 71 | public void invoke(final Frame frame, final Interpreter interpreter) { 72 | SNumber op1 = (SNumber) frame.pop(); 73 | SDouble op2 = (SDouble) frame.pop(); 74 | frame.push(op2.primAdd(op1, universe)); 75 | } 76 | }); 77 | 78 | installInstancePrimitive(new SPrimitive("-", universe) { 79 | @Override 80 | public void invoke(final Frame frame, final Interpreter interpreter) { 81 | SNumber op1 = (SNumber) frame.pop(); 82 | SDouble op2 = (SDouble) frame.pop(); 83 | frame.push(op2.primSubtract(op1, universe)); 84 | } 85 | }); 86 | 87 | installInstancePrimitive(new SPrimitive("*", universe) { 88 | @Override 89 | public void invoke(final Frame frame, final Interpreter interpreter) { 90 | SNumber op1 = (SNumber) frame.pop(); 91 | SDouble op2 = (SDouble) frame.pop(); 92 | frame.push(op2.primMultiply(op1, universe)); 93 | } 94 | }); 95 | 96 | installInstancePrimitive(new SPrimitive("//", universe) { 97 | @Override 98 | public void invoke(final Frame frame, final Interpreter interpreter) { 99 | SNumber op1 = (SNumber) frame.pop(); 100 | SDouble op2 = (SDouble) frame.pop(); 101 | frame.push(op2.primDoubleDivide(op1, universe)); 102 | } 103 | }); 104 | 105 | installInstancePrimitive(new SPrimitive("%", universe) { 106 | @Override 107 | public void invoke(final Frame frame, final Interpreter interpreter) { 108 | SNumber op1 = (SNumber) frame.pop(); 109 | SDouble op2 = (SDouble) frame.pop(); 110 | frame.push(op2.primModulo(op1, universe)); 111 | } 112 | }); 113 | 114 | installInstancePrimitive(new SPrimitive("=", universe) { 115 | @Override 116 | public void invoke(final Frame frame, final Interpreter interpreter) { 117 | SAbstractObject op1 = frame.pop(); 118 | SDouble op2 = (SDouble) frame.pop(); 119 | frame.push(op2.primEqual(op1, universe)); 120 | } 121 | }); 122 | 123 | installInstancePrimitive(new SPrimitive("<", universe) { 124 | @Override 125 | public void invoke(final Frame frame, final Interpreter interpreter) { 126 | SNumber op1 = (SNumber) frame.pop(); 127 | SDouble op2 = (SDouble) frame.pop(); 128 | frame.push(op2.primLessThan(op1, universe)); 129 | } 130 | }); 131 | 132 | installInstancePrimitive(new SPrimitive("round", universe) { 133 | @Override 134 | public void invoke(final Frame frame, final Interpreter interpreter) { 135 | SDouble rcvr = (SDouble) frame.pop(); 136 | long result = Math.round(rcvr.getEmbeddedDouble()); 137 | frame.push(universe.newInteger(result)); 138 | } 139 | }); 140 | 141 | installInstancePrimitive(new SPrimitive("sin", universe) { 142 | @Override 143 | public void invoke(final Frame frame, final Interpreter interpreter) { 144 | SDouble rcvr = (SDouble) frame.pop(); 145 | double result = Math.sin(rcvr.getEmbeddedDouble()); 146 | frame.push(universe.newDouble(result)); 147 | } 148 | }); 149 | 150 | installInstancePrimitive(new SPrimitive("cos", universe) { 151 | @Override 152 | public void invoke(final Frame frame, final Interpreter interpreter) { 153 | SDouble rcvr = (SDouble) frame.pop(); 154 | double result = Math.cos(rcvr.getEmbeddedDouble()); 155 | frame.push(universe.newDouble(result)); 156 | } 157 | }); 158 | 159 | installClassPrimitive(new SPrimitive("PositiveInfinity", universe) { 160 | @Override 161 | public void invoke(final Frame frame, final Interpreter interpreter) { 162 | frame.pop(); 163 | frame.push(universe.newDouble(Double.POSITIVE_INFINITY)); 164 | } 165 | }); 166 | 167 | installClassPrimitive(new SPrimitive("fromString:", universe) { 168 | @Override 169 | public void invoke(final Frame frame, final Interpreter interpreter) { 170 | SString arg = (SString) frame.pop(); 171 | frame.pop(); 172 | 173 | double d; 174 | 175 | try { 176 | d = Double.parseDouble(arg.getEmbeddedString()); 177 | } catch (NumberFormatException e) { 178 | d = Double.NaN; 179 | } 180 | 181 | frame.push(universe.newDouble(d)); 182 | } 183 | }); 184 | } 185 | } 186 | -------------------------------------------------------------------------------- /src/som/primitives/IntegerPrimitives.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2009 Michael Haupt, michael.haupt@hpi.uni-potsdam.de 3 | * Software Architecture Group, Hasso Plattner Institute, Potsdam, Germany 4 | * http://www.hpi.uni-potsdam.de/swa/ 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | package som.primitives; 26 | 27 | import java.math.BigInteger; 28 | 29 | import som.interpreter.Frame; 30 | import som.interpreter.Interpreter; 31 | import som.vm.Universe; 32 | import som.vmobjects.SAbstractObject; 33 | import som.vmobjects.SBigInteger; 34 | import som.vmobjects.SInteger; 35 | import som.vmobjects.SNumber; 36 | import som.vmobjects.SPrimitive; 37 | import som.vmobjects.SString; 38 | 39 | 40 | public class IntegerPrimitives extends Primitives { 41 | 42 | public IntegerPrimitives(final Universe universe) { 43 | super(universe); 44 | } 45 | 46 | @Override 47 | public void installPrimitives() { 48 | installInstancePrimitive(new SPrimitive("asString", universe) { 49 | @Override 50 | public void invoke(final Frame frame, final Interpreter interpreter) { 51 | SNumber self = (SNumber) frame.pop(); 52 | frame.push(self.primAsString(universe)); 53 | } 54 | }); 55 | 56 | installInstancePrimitive(new SPrimitive("asDouble", universe) { 57 | @Override 58 | public void invoke(final Frame frame, final Interpreter interpreter) { 59 | SNumber self = (SNumber) frame.pop(); 60 | frame.push(self.primAsDouble(universe)); 61 | } 62 | }); 63 | 64 | installInstancePrimitive(new SPrimitive("sqrt", universe) { 65 | @Override 66 | public void invoke(final Frame frame, final Interpreter interpreter) { 67 | SInteger self = (SInteger) frame.pop(); 68 | frame.push(self.primSqrt(universe)); 69 | } 70 | }); 71 | 72 | installInstancePrimitive(new SPrimitive("atRandom", universe) { 73 | @Override 74 | public void invoke(final Frame frame, final Interpreter interpreter) { 75 | SInteger self = (SInteger) frame.pop(); 76 | frame.push(universe.newInteger( 77 | (long) (self.getEmbeddedInteger() * Math.random()))); 78 | } 79 | }); 80 | 81 | installInstancePrimitive(new SPrimitive("+", universe) { 82 | @Override 83 | public void invoke(final Frame frame, final Interpreter interpreter) { 84 | SNumber right = (SNumber) frame.pop(); 85 | SNumber left = (SNumber) frame.pop(); 86 | frame.push(left.primAdd(right, universe)); 87 | } 88 | }); 89 | 90 | installInstancePrimitive(new SPrimitive("-", universe) { 91 | @Override 92 | public void invoke(final Frame frame, final Interpreter interpreter) { 93 | SNumber right = (SNumber) frame.pop(); 94 | SNumber left = (SNumber) frame.pop(); 95 | frame.push(left.primSubtract(right, universe)); 96 | } 97 | }); 98 | 99 | installInstancePrimitive(new SPrimitive("*", universe) { 100 | @Override 101 | public void invoke(final Frame frame, final Interpreter interpreter) { 102 | SNumber right = (SNumber) frame.pop(); 103 | SNumber left = (SNumber) frame.pop(); 104 | frame.push(left.primMultiply(right, universe)); 105 | } 106 | }); 107 | 108 | installInstancePrimitive(new SPrimitive("//", universe) { 109 | @Override 110 | public void invoke(final Frame frame, final Interpreter interpreter) { 111 | SNumber right = (SNumber) frame.pop(); 112 | SNumber left = (SNumber) frame.pop(); 113 | frame.push(left.primDoubleDivide(right, universe)); 114 | } 115 | }); 116 | 117 | installInstancePrimitive(new SPrimitive("/", universe) { 118 | @Override 119 | public void invoke(final Frame frame, final Interpreter interpreter) { 120 | SNumber right = (SNumber) frame.pop(); 121 | SNumber left = (SNumber) frame.pop(); 122 | frame.push(left.primIntegerDivide(right, universe)); 123 | } 124 | }); 125 | 126 | installInstancePrimitive(new SPrimitive("%", universe) { 127 | @Override 128 | public void invoke(final Frame frame, final Interpreter interpreter) { 129 | SNumber right = (SNumber) frame.pop(); 130 | SNumber left = (SNumber) frame.pop(); 131 | frame.push(left.primModulo(right, universe)); 132 | } 133 | }); 134 | 135 | installInstancePrimitive(new SPrimitive("rem:", universe) { 136 | @Override 137 | public void invoke(final Frame frame, final Interpreter interpreter) { 138 | SNumber right = (SNumber) frame.pop(); 139 | SInteger left = (SInteger) frame.pop(); 140 | frame.push(left.primRemainder(right, universe)); 141 | } 142 | }); 143 | 144 | installInstancePrimitive(new SPrimitive("&", universe) { 145 | @Override 146 | public void invoke(final Frame frame, final Interpreter interpreter) { 147 | SNumber right = (SNumber) frame.pop(); 148 | SNumber left = (SNumber) frame.pop(); 149 | frame.push(left.primBitAnd(right, universe)); 150 | } 151 | }); 152 | 153 | installInstancePrimitive(new SPrimitive("=", universe) { 154 | @Override 155 | public void invoke(final Frame frame, final Interpreter interpreter) { 156 | SAbstractObject right = frame.pop(); 157 | SNumber left = (SNumber) frame.pop(); 158 | frame.push(left.primEqual(right, universe)); 159 | } 160 | }); 161 | 162 | installInstancePrimitive(new SPrimitive("<", universe) { 163 | @Override 164 | public void invoke(final Frame frame, final Interpreter interpreter) { 165 | SNumber right = (SNumber) frame.pop(); 166 | SNumber left = (SNumber) frame.pop(); 167 | frame.push(left.primLessThan(right, universe)); 168 | } 169 | }); 170 | 171 | installInstancePrimitive(new SPrimitive("<<", universe) { 172 | @Override 173 | public void invoke(final Frame frame, final Interpreter interpreter) { 174 | SNumber right = (SNumber) frame.pop(); 175 | SNumber left = (SNumber) frame.pop(); 176 | frame.push(left.primLeftShift(right, universe)); 177 | } 178 | }); 179 | 180 | installInstancePrimitive(new SPrimitive("bitXor:", universe) { 181 | @Override 182 | public void invoke(final Frame frame, final Interpreter interpreter) { 183 | SNumber right = (SNumber) frame.pop(); 184 | SNumber left = (SNumber) frame.pop(); 185 | frame.push(left.primBitXor(right, universe)); 186 | } 187 | }); 188 | 189 | installInstancePrimitive(new SPrimitive("as32BitSignedValue", universe) { 190 | @Override 191 | public void invoke(final Frame frame, final Interpreter interpreter) { 192 | SNumber rcvr = (SNumber) frame.pop(); 193 | 194 | int result; 195 | if (rcvr instanceof SInteger) { 196 | result = (int) ((SInteger) rcvr).getEmbeddedInteger(); 197 | } else { 198 | result = ((SBigInteger) rcvr).getEmbeddedBiginteger().intValue(); 199 | } 200 | frame.push(universe.newInteger(result)); 201 | } 202 | }); 203 | 204 | installInstancePrimitive(new SPrimitive("as32BitUnsignedValue", universe) { 205 | @Override 206 | public void invoke(final Frame frame, final Interpreter interpreter) { 207 | SInteger rcvr = (SInteger) frame.pop(); 208 | frame.push( 209 | universe.newInteger(Integer.toUnsignedLong((int) rcvr.getEmbeddedInteger()))); 210 | } 211 | }); 212 | 213 | installInstancePrimitive(new SPrimitive(">>>", universe) { 214 | @Override 215 | public void invoke(final Frame frame, final Interpreter interpreter) { 216 | SInteger right = (SInteger) frame.pop(); 217 | SInteger rcvr = (SInteger) frame.pop(); 218 | frame.push( 219 | universe.newInteger(rcvr.getEmbeddedInteger() >>> right.getEmbeddedInteger())); 220 | } 221 | }); 222 | 223 | installClassPrimitive(new SPrimitive("fromString:", universe) { 224 | @Override 225 | public void invoke(final Frame frame, final Interpreter interpreter) { 226 | SString param = (SString) frame.pop(); 227 | frame.pop(); 228 | 229 | try { 230 | long result = Long.parseLong(param.getEmbeddedString()); 231 | frame.push(universe.newInteger(result)); 232 | } catch (NumberFormatException e) { 233 | BigInteger result = new BigInteger(param.getEmbeddedString()); 234 | frame.push(new SBigInteger(result)); 235 | } 236 | } 237 | }); 238 | } 239 | } 240 | -------------------------------------------------------------------------------- /src/som/primitives/MethodPrimitives.java: -------------------------------------------------------------------------------- 1 | package som.primitives; 2 | 3 | import som.interpreter.Interpreter; 4 | import som.interpreter.Frame; 5 | import som.vm.Universe; 6 | import som.vmobjects.SMethod; 7 | import som.vmobjects.SPrimitive; 8 | 9 | 10 | public class MethodPrimitives extends Primitives { 11 | public MethodPrimitives(final Universe universe) { 12 | super(universe); 13 | } 14 | 15 | @Override 16 | public void installPrimitives() { 17 | installInstancePrimitive(new SPrimitive("holder", universe) { 18 | 19 | @Override 20 | public void invoke(Frame frame, Interpreter interpreter) { 21 | SMethod self = (SMethod) frame.pop(); 22 | frame.push(self.getHolder()); 23 | } 24 | }); 25 | 26 | installInstancePrimitive(new SPrimitive("signature", universe) { 27 | 28 | @Override 29 | public void invoke(Frame frame, Interpreter interpreter) { 30 | SMethod self = (SMethod) frame.pop(); 31 | frame.push(self.getSignature()); 32 | } 33 | }); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/som/primitives/ObjectPrimitives.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2016 Michael Haupt, github@haupz.de 3 | * Copyright (c) 2009 Michael Haupt, michael.haupt@hpi.uni-potsdam.de 4 | * Software Architecture Group, Hasso Plattner Institute, Potsdam, Germany 5 | * http://www.hpi.uni-potsdam.de/swa/ 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | package som.primitives; 27 | 28 | import som.interpreter.Frame; 29 | import som.interpreter.Interpreter; 30 | import som.vm.Universe; 31 | import som.vmobjects.SAbstractObject; 32 | import som.vmobjects.SArray; 33 | import som.vmobjects.SClass; 34 | import som.vmobjects.SInteger; 35 | import som.vmobjects.SInvokable; 36 | import som.vmobjects.SObject; 37 | import som.vmobjects.SPrimitive; 38 | import som.vmobjects.SSymbol; 39 | 40 | 41 | public class ObjectPrimitives extends Primitives { 42 | 43 | public ObjectPrimitives(final Universe universe) { 44 | super(universe); 45 | } 46 | 47 | @Override 48 | public void installPrimitives() { 49 | 50 | installInstancePrimitive(new SPrimitive("==", universe) { 51 | @Override 52 | public void invoke(final Frame frame, final Interpreter interpreter) { 53 | SAbstractObject op1 = frame.pop(); 54 | SAbstractObject op2 = frame.pop(); 55 | if (op1 == op2) { 56 | frame.push(universe.trueObject); 57 | } else { 58 | frame.push(universe.falseObject); 59 | } 60 | } 61 | }); 62 | 63 | installInstancePrimitive(new SPrimitive("hashcode", universe) { 64 | @Override 65 | public void invoke(final Frame frame, final Interpreter interpreter) { 66 | SAbstractObject self = frame.pop(); 67 | frame.push(universe.newInteger(self.hashCode())); 68 | } 69 | }); 70 | 71 | installInstancePrimitive(new SPrimitive("objectSize", universe) { 72 | @Override 73 | public void invoke(final Frame frame, final Interpreter interpreter) { 74 | SAbstractObject self = frame.pop(); 75 | 76 | // each object holds its class as an implicit member that contributes to its size 77 | int size = 1; 78 | if (self instanceof SArray) { 79 | size += ((SArray) self).getNumberOfIndexableFields(); 80 | } 81 | if (self instanceof SObject) { 82 | size += ((SObject) self).getNumberOfFields(); 83 | } 84 | frame.push(universe.newInteger(size)); 85 | } 86 | }); 87 | 88 | installInstancePrimitive(new SPrimitive("perform:", universe) { 89 | @Override 90 | public void invoke(final Frame frame, final Interpreter interpreter) { 91 | SAbstractObject arg = frame.pop(); 92 | SAbstractObject self = frame.getStackElement(0); 93 | SSymbol selector = (SSymbol) arg; 94 | 95 | SInvokable invokable = self.getSOMClass(universe).lookupInvokable(selector); 96 | invokable.invoke(frame, interpreter); 97 | } 98 | }); 99 | 100 | installInstancePrimitive(new SPrimitive("perform:inSuperclass:", universe) { 101 | @Override 102 | public void invoke(final Frame frame, final Interpreter interpreter) { 103 | SAbstractObject arg2 = frame.pop(); 104 | SAbstractObject arg = frame.pop(); 105 | // Object self = frame.getStackElement(0); 106 | 107 | SSymbol selector = (SSymbol) arg; 108 | SClass clazz = (SClass) arg2; 109 | 110 | SInvokable invokable = clazz.lookupInvokable(selector); 111 | invokable.invoke(frame, interpreter); 112 | } 113 | }); 114 | 115 | installInstancePrimitive(new SPrimitive("perform:withArguments:", universe) { 116 | @Override 117 | public void invoke(final Frame frame, final Interpreter interpreter) { 118 | SAbstractObject arg2 = frame.pop(); 119 | SAbstractObject arg = frame.pop(); 120 | SAbstractObject self = frame.getStackElement(0); 121 | 122 | SSymbol selector = (SSymbol) arg; 123 | SArray args = (SArray) arg2; 124 | 125 | for (int i = 0; i < args.getNumberOfIndexableFields(); i++) { 126 | frame.push(args.getIndexableField(i)); 127 | } 128 | 129 | SInvokable invokable = self.getSOMClass(universe).lookupInvokable(selector); 130 | invokable.invoke(frame, interpreter); 131 | } 132 | }); 133 | 134 | installInstancePrimitive(new SPrimitive("instVarAt:", universe) { 135 | @Override 136 | public void invoke(final Frame frame, final Interpreter interpreter) { 137 | SAbstractObject arg = frame.pop(); 138 | SObject self = (SObject) frame.pop(); 139 | SInteger idx = (SInteger) arg; 140 | 141 | frame.push(self.getField(idx.getEmbeddedInteger() - 1)); 142 | } 143 | }); 144 | 145 | installInstancePrimitive(new SPrimitive("instVarAt:put:", universe) { 146 | @Override 147 | public void invoke(final Frame frame, final Interpreter interpreter) { 148 | SAbstractObject val = frame.pop(); 149 | SAbstractObject arg = frame.pop(); 150 | SObject self = (SObject) frame.getStackElement(0); 151 | 152 | SInteger idx = (SInteger) arg; 153 | 154 | self.setField(idx.getEmbeddedInteger() - 1, val); 155 | } 156 | }); 157 | 158 | installInstancePrimitive(new SPrimitive("class", universe) { 159 | @Override 160 | public void invoke(final Frame frame, final Interpreter interpreter) { 161 | SAbstractObject self = frame.pop(); 162 | frame.push(self.getSOMClass(universe)); 163 | } 164 | }); 165 | 166 | installInstancePrimitive(new SPrimitive("halt", universe) { 167 | @Override 168 | public void invoke(final Frame frame, final Interpreter interpreter) { 169 | Universe.errorPrintln("BREAKPOINT"); 170 | } 171 | }); 172 | } 173 | } 174 | -------------------------------------------------------------------------------- /src/som/primitives/PrimitivePrimitives.java: -------------------------------------------------------------------------------- 1 | package som.primitives; 2 | 3 | import som.interpreter.Interpreter; 4 | import som.interpreter.Frame; 5 | import som.vm.Universe; 6 | import som.vmobjects.SPrimitive; 7 | 8 | 9 | public class PrimitivePrimitives extends Primitives { 10 | public PrimitivePrimitives(final Universe universe) { 11 | super(universe); 12 | } 13 | 14 | @Override 15 | public void installPrimitives() { 16 | installInstancePrimitive(new SPrimitive("holder", universe) { 17 | 18 | @Override 19 | public void invoke(Frame frame, Interpreter interpreter) { 20 | SPrimitive self = (SPrimitive) frame.pop(); 21 | frame.push(self.getHolder()); 22 | } 23 | }); 24 | 25 | installInstancePrimitive(new SPrimitive("signature", universe) { 26 | 27 | @Override 28 | public void invoke(Frame frame, Interpreter interpreter) { 29 | SPrimitive self = (SPrimitive) frame.pop(); 30 | frame.push(self.getSignature()); 31 | } 32 | }); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/som/primitives/Primitives.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2013 Stefan Marr, stefan.marr@vub.ac.be 3 | * Copyright (c) 2009 Michael Haupt, michael.haupt@hpi.uni-potsdam.de 4 | * Software Architecture Group, Hasso Plattner Institute, Potsdam, Germany 5 | * http://www.hpi.uni-potsdam.de/swa/ 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | package som.primitives; 27 | 28 | import som.vm.Universe; 29 | import som.vmobjects.SClass; 30 | import som.vmobjects.SPrimitive; 31 | 32 | 33 | public abstract class Primitives { 34 | 35 | protected final Universe universe; 36 | 37 | public Primitives(final Universe universe) { 38 | this.universe = universe; 39 | } 40 | 41 | public final void installPrimitivesIn(final SClass value) { 42 | // Save a reference to the holder class 43 | holder = value; 44 | 45 | // Install the primitives from this primitives class 46 | installPrimitives(); 47 | } 48 | 49 | public abstract void installPrimitives(); 50 | 51 | protected void installInstancePrimitive(final SPrimitive primitive) { 52 | installInstancePrimitive(primitive, false); 53 | } 54 | 55 | protected void installInstancePrimitive(final SPrimitive primitive, 56 | final boolean suppressWarning) { 57 | // Install the given primitive as an instance primitive in the holder 58 | // class 59 | holder.addInstancePrimitive(primitive, suppressWarning); 60 | } 61 | 62 | protected void installClassPrimitive(final SPrimitive primitive) { 63 | // Install the given primitive as an instance primitive in the class of 64 | // the holder class 65 | holder.getSOMClass().addInstancePrimitive(primitive); 66 | } 67 | 68 | private SClass holder; 69 | } 70 | -------------------------------------------------------------------------------- /src/som/primitives/StringPrimitives.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2013 Stefan Marr, stefan.marr@vub.ac.be 3 | * Copyright (c) 2009 Michael Haupt, michael.haupt@hpi.uni-potsdam.de 4 | * Software Architecture Group, Hasso Plattner Institute, Potsdam, Germany 5 | * http://www.hpi.uni-potsdam.de/swa/ 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | package som.primitives; 27 | 28 | import som.interpreter.Frame; 29 | import som.interpreter.Interpreter; 30 | import som.vm.Universe; 31 | import som.vmobjects.SAbstractObject; 32 | import som.vmobjects.SInteger; 33 | import som.vmobjects.SPrimitive; 34 | import som.vmobjects.SString; 35 | 36 | 37 | public class StringPrimitives extends Primitives { 38 | 39 | public StringPrimitives(final Universe universe) { 40 | super(universe); 41 | } 42 | 43 | @Override 44 | public void installPrimitives() { 45 | installInstancePrimitive(new SPrimitive("concatenate:", universe) { 46 | 47 | @Override 48 | public void invoke(final Frame frame, final Interpreter interpreter) { 49 | SString argument = (SString) frame.pop(); 50 | SString self = (SString) frame.pop(); 51 | frame.push(universe.newString(self.getEmbeddedString() 52 | + argument.getEmbeddedString())); 53 | } 54 | }); 55 | 56 | installInstancePrimitive(new SPrimitive("asSymbol", universe) { 57 | 58 | @Override 59 | public void invoke(final Frame frame, final Interpreter interpreter) { 60 | SString self = (SString) frame.pop(); 61 | frame.push(universe.symbolFor(self.getEmbeddedString())); 62 | } 63 | }); 64 | 65 | installInstancePrimitive(new SPrimitive("length", universe) { 66 | 67 | @Override 68 | public void invoke(final Frame frame, final Interpreter interpreter) { 69 | SString self = (SString) frame.pop(); 70 | frame.push(universe.newInteger(self.getEmbeddedString().length())); 71 | } 72 | }); 73 | 74 | installInstancePrimitive(new SPrimitive("=", universe) { 75 | 76 | @Override 77 | public void invoke(final Frame frame, final Interpreter interpreter) { 78 | SAbstractObject op2 = frame.pop(); 79 | SString op1 = (SString) frame.pop(); // self 80 | if (op2 instanceof SString) { 81 | SString s = (SString) op2; 82 | if (s.getEmbeddedString().equals(op1.getEmbeddedString())) { 83 | frame.push(universe.trueObject); 84 | return; 85 | } 86 | } 87 | 88 | frame.push(universe.falseObject); 89 | } 90 | }); 91 | 92 | installInstancePrimitive(new SPrimitive("primSubstringFrom:to:", universe) { 93 | 94 | @Override 95 | public void invoke(final Frame frame, final Interpreter interpreter) { 96 | SInteger end = (SInteger) frame.pop(); 97 | SInteger start = (SInteger) frame.pop(); 98 | 99 | SString self = (SString) frame.pop(); 100 | 101 | try { 102 | frame.push(universe.newString(self.getEmbeddedString().substring( 103 | (int) start.getEmbeddedInteger() - 1, 104 | (int) end.getEmbeddedInteger()))); 105 | } catch (IndexOutOfBoundsException e) { 106 | frame.push(universe.newString(new java.lang.String( 107 | "Error - index out of bounds"))); 108 | } 109 | } 110 | }); 111 | 112 | installInstancePrimitive(new SPrimitive("hashcode", universe) { 113 | 114 | @Override 115 | public void invoke(final Frame frame, final Interpreter interpreter) { 116 | SString self = (SString) frame.pop(); 117 | frame.push(universe.newInteger(self.getEmbeddedString().hashCode())); 118 | } 119 | }); 120 | 121 | installInstancePrimitive(new SPrimitive("isWhiteSpace", universe) { 122 | 123 | @Override 124 | public void invoke(final Frame frame, final Interpreter interpreter) { 125 | SString self = (SString) frame.pop(); 126 | String embedded = self.getEmbeddedString(); 127 | 128 | for (int i = 0; i < embedded.length(); i++) { 129 | if (!Character.isWhitespace(embedded.charAt(i))) { 130 | frame.push(universe.falseObject); 131 | return; 132 | } 133 | } 134 | 135 | if (embedded.length() > 0) { 136 | frame.push(universe.trueObject); 137 | } else { 138 | frame.push(universe.falseObject); 139 | } 140 | } 141 | }); 142 | 143 | installInstancePrimitive(new SPrimitive("isLetters", universe) { 144 | 145 | @Override 146 | public void invoke(final Frame frame, final Interpreter interpreter) { 147 | SString self = (SString) frame.pop(); 148 | String embedded = self.getEmbeddedString(); 149 | 150 | for (int i = 0; i < embedded.length(); i++) { 151 | if (!Character.isLetter(embedded.charAt(i))) { 152 | frame.push(universe.falseObject); 153 | return; 154 | } 155 | } 156 | 157 | if (embedded.length() > 0) { 158 | frame.push(universe.trueObject); 159 | } else { 160 | frame.push(universe.falseObject); 161 | } 162 | } 163 | }); 164 | 165 | installInstancePrimitive(new SPrimitive("isDigits", universe) { 166 | 167 | @Override 168 | public void invoke(final Frame frame, final Interpreter interpreter) { 169 | SString self = (SString) frame.pop(); 170 | String embedded = self.getEmbeddedString(); 171 | 172 | for (int i = 0; i < embedded.length(); i++) { 173 | if (!Character.isDigit(embedded.charAt(i))) { 174 | frame.push(universe.falseObject); 175 | return; 176 | } 177 | } 178 | 179 | if (embedded.length() > 0) { 180 | frame.push(universe.trueObject); 181 | } else { 182 | frame.push(universe.falseObject); 183 | } 184 | } 185 | }); 186 | } 187 | } 188 | -------------------------------------------------------------------------------- /src/som/primitives/SymbolPrimitives.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2009 Michael Haupt, michael.haupt@hpi.uni-potsdam.de 3 | * Software Architecture Group, Hasso Plattner Institute, Potsdam, Germany 4 | * http://www.hpi.uni-potsdam.de/swa/ 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | package som.primitives; 26 | 27 | import som.interpreter.Frame; 28 | import som.interpreter.Interpreter; 29 | import som.vm.Universe; 30 | import som.vmobjects.SAbstractObject; 31 | import som.vmobjects.SPrimitive; 32 | import som.vmobjects.SString; 33 | import som.vmobjects.SSymbol; 34 | 35 | 36 | public class SymbolPrimitives extends Primitives { 37 | 38 | public SymbolPrimitives(final Universe universe) { 39 | super(universe); 40 | } 41 | 42 | @Override 43 | public void installPrimitives() { 44 | installInstancePrimitive(new SPrimitive("asString", universe) { 45 | 46 | @Override 47 | public void invoke(final Frame frame, final Interpreter interpreter) { 48 | SSymbol self = (SSymbol) frame.pop(); 49 | frame.push(universe.newString(self.getEmbeddedString())); 50 | } 51 | }); 52 | 53 | installInstancePrimitive(new SPrimitive("=", universe) { 54 | 55 | @Override 56 | public void invoke(final Frame frame, final Interpreter interpreter) { 57 | SAbstractObject op1 = frame.pop(); 58 | SSymbol op2 = (SSymbol) frame.pop(); // self 59 | if (op1 == op2) { 60 | frame.push(universe.trueObject); 61 | return; 62 | } 63 | 64 | if (op1 instanceof SString) { 65 | SString s = (SString) op1; 66 | if (s.getEmbeddedString().equals(op2.getEmbeddedString())) { 67 | frame.push(universe.trueObject); 68 | return; 69 | } 70 | } 71 | frame.push(universe.falseObject); 72 | } 73 | }, true); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/som/primitives/SystemPrimitives.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2009 Michael Haupt, michael.haupt@hpi.uni-potsdam.de 3 | * Software Architecture Group, Hasso Plattner Institute, Potsdam, Germany 4 | * http://www.hpi.uni-potsdam.de/swa/ 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | package som.primitives; 26 | 27 | import java.io.IOException; 28 | import java.lang.management.GarbageCollectorMXBean; 29 | import java.lang.management.ManagementFactory; 30 | import java.nio.file.Files; 31 | import java.nio.file.Path; 32 | import java.nio.file.Paths; 33 | import java.util.List; 34 | 35 | import com.sun.management.ThreadMXBean; 36 | import som.compiler.ProgramDefinitionError; 37 | import som.interpreter.Frame; 38 | import som.interpreter.Interpreter; 39 | import som.vm.Universe; 40 | import som.vmobjects.SAbstractObject; 41 | import som.vmobjects.SArray; 42 | import som.vmobjects.SClass; 43 | import som.vmobjects.SInteger; 44 | import som.vmobjects.SPrimitive; 45 | import som.vmobjects.SString; 46 | import som.vmobjects.SSymbol; 47 | 48 | 49 | public class SystemPrimitives extends Primitives { 50 | 51 | public SystemPrimitives(final Universe universe) { 52 | super(universe); 53 | } 54 | 55 | @Override 56 | public void installPrimitives() { 57 | installInstancePrimitive(new SPrimitive("load:", universe) { 58 | 59 | @Override 60 | public void invoke(final Frame frame, final Interpreter interpreter) { 61 | SSymbol argument = (SSymbol) frame.pop(); 62 | frame.pop(); // not required 63 | SClass result = null; 64 | try { 65 | result = universe.loadClass(argument); 66 | } catch (ProgramDefinitionError e) { 67 | universe.errorExit(e.toString()); 68 | } 69 | frame.push(result != null ? result : universe.nilObject); 70 | } 71 | }); 72 | 73 | installInstancePrimitive(new SPrimitive("exit:", universe) { 74 | 75 | @Override 76 | public void invoke(final Frame frame, final Interpreter interpreter) { 77 | SInteger error = (SInteger) frame.pop(); 78 | universe.exit(error.getEmbeddedInteger()); 79 | } 80 | }); 81 | 82 | installInstancePrimitive(new SPrimitive("global:", universe) { 83 | 84 | @Override 85 | public void invoke(final Frame frame, final Interpreter interpreter) { 86 | SSymbol argument = (SSymbol) frame.pop(); 87 | frame.pop(); // not required 88 | SAbstractObject result = universe.getGlobal(argument); 89 | frame.push(result != null ? result : universe.nilObject); 90 | } 91 | }); 92 | 93 | installInstancePrimitive(new SPrimitive("global:put:", universe) { 94 | 95 | @Override 96 | public void invoke(final Frame frame, final Interpreter interpreter) { 97 | SAbstractObject value = frame.pop(); 98 | SSymbol argument = (SSymbol) frame.pop(); 99 | universe.setGlobal(argument, value); 100 | } 101 | }); 102 | 103 | installInstancePrimitive(new SPrimitive("printString:", universe) { 104 | 105 | @Override 106 | public void invoke(final Frame frame, final Interpreter interpreter) { 107 | SString argument = (SString) frame.pop(); 108 | Universe.print(argument.getEmbeddedString()); 109 | } 110 | }); 111 | 112 | installInstancePrimitive(new SPrimitive("printNewline", universe) { 113 | 114 | @Override 115 | public void invoke(final Frame frame, final Interpreter interpreter) { 116 | Universe.println(""); 117 | } 118 | }); 119 | 120 | installInstancePrimitive(new SPrimitive("errorPrint:", universe) { 121 | 122 | @Override 123 | public void invoke(final Frame frame, final Interpreter interpreter) { 124 | SString argument = (SString) frame.pop(); 125 | Universe.errorPrint(argument.getEmbeddedString()); 126 | } 127 | }); 128 | 129 | installInstancePrimitive(new SPrimitive("errorPrintln:", universe) { 130 | 131 | @Override 132 | public void invoke(final Frame frame, final Interpreter interpreter) { 133 | SString argument = (SString) frame.pop(); 134 | Universe.errorPrintln(argument.getEmbeddedString()); 135 | } 136 | }); 137 | 138 | startMicroTime = System.nanoTime() / 1000L; 139 | startTime = startMicroTime / 1000L; 140 | installInstancePrimitive(new SPrimitive("time", universe) { 141 | 142 | @Override 143 | public void invoke(final Frame frame, final Interpreter interpreter) { 144 | frame.pop(); // ignore 145 | int time = (int) (System.currentTimeMillis() - startTime); 146 | frame.push(universe.newInteger(time)); 147 | } 148 | }); 149 | 150 | installInstancePrimitive(new SPrimitive("ticks", universe) { 151 | 152 | @Override 153 | public void invoke(final Frame frame, final Interpreter interpreter) { 154 | frame.pop(); // ignore 155 | int time = (int) (System.nanoTime() / 1000L - startMicroTime); 156 | frame.push(universe.newInteger(time)); 157 | } 158 | }); 159 | 160 | installInstancePrimitive(new SPrimitive("fullGC", universe) { 161 | 162 | @Override 163 | public void invoke(final Frame frame, final Interpreter interpreter) { 164 | frame.pop(); 165 | System.gc(); 166 | frame.push(universe.trueObject); 167 | } 168 | }); 169 | 170 | installInstancePrimitive(new SPrimitive("gcStats", universe) { 171 | 172 | @Override 173 | public void invoke(Frame frame, Interpreter interpreter) { 174 | frame.pop(); 175 | 176 | final List gcBeans = 177 | ManagementFactory.getGarbageCollectorMXBeans(); 178 | final ThreadMXBean threadBean = (ThreadMXBean) ManagementFactory.getThreadMXBean(); 179 | threadBean.setThreadAllocatedMemoryEnabled(true); 180 | 181 | final long allocatedBytes = threadBean.getCurrentThreadAllocatedBytes(); 182 | long counts = 0; 183 | long time = 0; 184 | 185 | for (GarbageCollectorMXBean b : gcBeans) { 186 | long c = b.getCollectionCount(); 187 | if (c != -1) { 188 | counts += c; 189 | } 190 | 191 | long t = b.getCollectionTime(); 192 | if (t != -1) { 193 | time += t; 194 | } 195 | } 196 | 197 | final SArray arr = new SArray(universe.nilObject, 3L); 198 | arr.setIndexableField(0L, SInteger.getInteger(counts)); 199 | arr.setIndexableField(1L, SInteger.getInteger(time)); 200 | arr.setIndexableField(2L, SInteger.getInteger(allocatedBytes)); 201 | 202 | frame.push(arr); 203 | } 204 | }); 205 | 206 | installInstancePrimitive(new SPrimitive("loadFile:", universe) { 207 | 208 | @Override 209 | public void invoke(final Frame frame, final Interpreter interpreter) { 210 | SString fileName = (SString) frame.pop(); 211 | frame.pop(); 212 | 213 | Path p = Paths.get(fileName.getEmbeddedString()); 214 | try { 215 | String content = new String(Files.readAllBytes(p)); 216 | frame.push(universe.newString(content)); 217 | } catch (IOException e) { 218 | frame.push(universe.nilObject); 219 | } 220 | } 221 | }); 222 | 223 | installInstancePrimitive(new SPrimitive("printStackTrace", universe) { 224 | 225 | @Override 226 | public void invoke(final Frame frame, final Interpreter interpreter) { 227 | frame.pop(); 228 | frame.printStackTrace(); 229 | frame.push(universe.trueObject); 230 | } 231 | }); 232 | } 233 | 234 | private long startTime; 235 | private long startMicroTime; 236 | } 237 | -------------------------------------------------------------------------------- /src/som/vm/Shell.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2017 Michael Haupt, github@haupz.de 3 | * Copyright (c) 2009 Michael Haupt, michael.haupt@hpi.uni-potsdam.de 4 | * Software Architecture Group, Hasso Plattner Institute, Potsdam, Germany 5 | * http://www.hpi.uni-potsdam.de/swa/ 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | package som.vm; 27 | 28 | import java.io.BufferedReader; 29 | import java.io.InputStreamReader; 30 | 31 | import som.interpreter.Frame; 32 | import som.interpreter.Interpreter; 33 | import som.vmobjects.SAbstractObject; 34 | import som.vmobjects.SClass; 35 | import som.vmobjects.SInvokable; 36 | import som.vmobjects.SMethod; 37 | 38 | 39 | public class Shell { 40 | 41 | private final Universe universe; 42 | private final Interpreter interpreter; 43 | 44 | public Shell(final Universe universe, final Interpreter interpreter) { 45 | this.universe = universe; 46 | this.interpreter = interpreter; 47 | } 48 | 49 | private SMethod bootstrapMethod; 50 | 51 | public void setBootstrapMethod(SMethod method) { 52 | bootstrapMethod = method; 53 | } 54 | 55 | public SAbstractObject start() { 56 | 57 | BufferedReader in; 58 | String stmt; 59 | int counter; 60 | int bytecodeIndex; 61 | SClass myClass; 62 | SAbstractObject myObject; 63 | SAbstractObject it; 64 | Frame currentFrame; 65 | 66 | counter = 0; 67 | in = new BufferedReader(new InputStreamReader(System.in)); 68 | it = universe.nilObject; 69 | 70 | Universe.println("SOM Shell. Type \"quit\" to exit.\n"); 71 | 72 | // Create a fake bootstrap frame 73 | currentFrame = interpreter.pushNewFrame(bootstrapMethod); 74 | 75 | // Remember the first bytecode index, e.g. index of the HALT instruction 76 | bytecodeIndex = currentFrame.getBytecodeIndex(); 77 | 78 | while (true) { 79 | try { 80 | Universe.print("---> "); 81 | 82 | // Read a statement from the keyboard 83 | stmt = in.readLine(); 84 | if (stmt.equals("quit")) { 85 | return it; 86 | } 87 | 88 | // Generate a temporary class with a run method 89 | stmt = "Shell_Class_" + counter++ + " = ( run: it = ( | tmp | tmp := (" 90 | + stmt + " ). 'it = ' print. ^tmp println ) )"; 91 | 92 | // Compile and load the newly generated class 93 | myClass = universe.loadShellClass(stmt); 94 | 95 | // If success 96 | if (myClass != null) { 97 | currentFrame = interpreter.getFrame(); 98 | 99 | // Go back, so we will evaluate the bootstrap frames halt 100 | // instruction again 101 | currentFrame.setBytecodeIndex(bytecodeIndex); 102 | 103 | // Create and push a new instance of our class on the stack 104 | myObject = universe.newInstance(myClass); 105 | currentFrame.push(myObject); 106 | 107 | // Push the old value of "it" on the stack 108 | currentFrame.push(it); 109 | 110 | // Lookup the run: method 111 | SInvokable initialize = myClass.lookupInvokable( 112 | universe.symbolFor("run:")); 113 | 114 | // Invoke the run method 115 | initialize.invoke(currentFrame, interpreter); 116 | 117 | // Start the interpreter 118 | interpreter.start(); 119 | 120 | // Save the result of the run method 121 | it = currentFrame.pop(); 122 | } 123 | } catch (Exception e) { 124 | Universe.errorPrintln("Caught exception: " + e.getMessage()); 125 | Universe.errorPrintln("" + interpreter.getFrame().getPreviousFrame()); 126 | } 127 | } 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /src/som/vmobjects/SAbstractObject.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2009 Michael Haupt, michael.haupt@hpi.uni-potsdam.de 3 | * Software Architecture Group, Hasso Plattner Institute, Potsdam, Germany 4 | * http://www.hpi.uni-potsdam.de/swa/ 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | package som.vmobjects; 26 | 27 | import som.interpreter.Frame; 28 | import som.interpreter.Interpreter; 29 | import som.vm.Universe; 30 | 31 | 32 | public abstract class SAbstractObject { 33 | 34 | public abstract SClass getSOMClass(Universe universe); 35 | 36 | public void send(final String selectorString, final SAbstractObject[] arguments, 37 | final Universe universe, final Interpreter interpreter) { 38 | // Turn the selector string into a selector 39 | SSymbol selector = universe.symbolFor(selectorString); 40 | 41 | // Push the receiver onto the stack 42 | interpreter.getFrame().push(this); 43 | 44 | // Push the arguments onto the stack 45 | for (SAbstractObject arg : arguments) { 46 | interpreter.getFrame().push(arg); 47 | } 48 | 49 | // Lookup the invokable 50 | SInvokable invokable = getSOMClass(universe).lookupInvokable(selector); 51 | 52 | // Invoke the invokable 53 | invokable.invoke(interpreter.getFrame(), interpreter); 54 | } 55 | 56 | public void sendDoesNotUnderstand(final SSymbol selector, 57 | final Universe universe, final Interpreter interpreter) { 58 | // Compute the number of arguments 59 | int numberOfArguments = selector.getNumberOfSignatureArguments(); 60 | 61 | Frame frame = interpreter.getFrame(); 62 | 63 | // Allocate an array with enough room to hold all arguments 64 | // except for the receiver, which is passed implicitly, as receiver of #dnu. 65 | SArray argumentsArray = universe.newArray(numberOfArguments - 1); 66 | 67 | // Remove all arguments and put them in the freshly allocated array 68 | for (int i = numberOfArguments - 2; i >= 0; i--) { 69 | argumentsArray.setIndexableField(i, frame.pop()); 70 | } 71 | 72 | frame.pop(); // pop receiver 73 | 74 | SAbstractObject[] args = {selector, argumentsArray}; 75 | send("doesNotUnderstand:arguments:", args, universe, interpreter); 76 | } 77 | 78 | public void sendUnknownGlobal(final SSymbol globalName, 79 | final Universe universe, final Interpreter interpreter) { 80 | SAbstractObject[] arguments = {globalName}; 81 | send("unknownGlobal:", arguments, universe, interpreter); 82 | } 83 | 84 | public void sendEscapedBlock(final SBlock block, final Universe universe, 85 | final Interpreter interpreter) { 86 | SAbstractObject[] arguments = {block}; 87 | send("escapedBlock:", arguments, universe, interpreter); 88 | } 89 | 90 | @Override 91 | public String toString() { 92 | return "a " + getSOMClass(Universe.current()).getName().getEmbeddedString(); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/som/vmobjects/SArray.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2009 Michael Haupt, michael.haupt@hpi.uni-potsdam.de 3 | * Software Architecture Group, Hasso Plattner Institute, Potsdam, Germany 4 | * http://www.hpi.uni-potsdam.de/swa/ 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | package som.vmobjects; 26 | 27 | import som.vm.Universe; 28 | 29 | 30 | public class SArray extends SAbstractObject { 31 | 32 | public SArray(final SObject nilObject, long numElements) { 33 | indexableFields = new SAbstractObject[(int) numElements]; 34 | 35 | // Clear each and every field by putting nil into them 36 | for (int i = 0; i < getNumberOfIndexableFields(); i++) { 37 | setIndexableField(i, nilObject); 38 | } 39 | } 40 | 41 | public SAbstractObject getIndexableField(long index) { 42 | return indexableFields[(int) index]; 43 | } 44 | 45 | public void setIndexableField(long index, SAbstractObject value) { 46 | indexableFields[(int) index] = value; 47 | } 48 | 49 | public int getNumberOfIndexableFields() { 50 | return indexableFields.length; 51 | } 52 | 53 | public SArray copyAndExtendWith(SAbstractObject value, final Universe universe) { 54 | // Allocate a new array which has one indexable field more than this 55 | // array 56 | SArray result = universe.newArray(getNumberOfIndexableFields() + 1); 57 | 58 | // Copy the indexable fields from this array to the new array 59 | copyIndexableFieldsTo(result); 60 | 61 | // Insert the given object as the last indexable field in the new array 62 | result.setIndexableField(getNumberOfIndexableFields(), value); 63 | 64 | return result; 65 | } 66 | 67 | protected void copyIndexableFieldsTo(SArray destination) { 68 | // Copy all indexable fields from this array to the destination array 69 | for (int i = 0; i < getNumberOfIndexableFields(); i++) { 70 | destination.setIndexableField(i, getIndexableField(i)); 71 | } 72 | } 73 | 74 | @Override 75 | public SClass getSOMClass(final Universe universe) { 76 | return universe.arrayClass; 77 | } 78 | 79 | // Private array of indexable fields 80 | private final SAbstractObject[] indexableFields; 81 | } 82 | -------------------------------------------------------------------------------- /src/som/vmobjects/SBigInteger.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2009 Michael Haupt, michael.haupt@hpi.uni-potsdam.de 3 | * Software Architecture Group, Hasso Plattner Institute, Potsdam, Germany 4 | * http://www.hpi.uni-potsdam.de/swa/ 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | package som.vmobjects; 26 | 27 | import java.math.BigInteger; 28 | 29 | import som.vm.Universe; 30 | 31 | 32 | public final class SBigInteger extends SNumber { 33 | 34 | // Private variable holding the embedded big integer 35 | private final BigInteger embeddedBiginteger; 36 | 37 | public SBigInteger(final BigInteger value) { 38 | embeddedBiginteger = value; 39 | } 40 | 41 | public BigInteger getEmbeddedBiginteger() { 42 | // Get the embedded big integer 43 | return embeddedBiginteger; 44 | } 45 | 46 | @Override 47 | public String toString() { 48 | return super.toString() + "(" + embeddedBiginteger + ")"; 49 | } 50 | 51 | @Override 52 | public SClass getSOMClass(final Universe universe) { 53 | return universe.integerClass; 54 | } 55 | 56 | @Override 57 | public SString primAsString(final Universe universe) { 58 | return universe.newString(embeddedBiginteger.toString()); 59 | } 60 | 61 | @Override 62 | public SNumber primAsDouble(final Universe universe) { 63 | return universe.newDouble(embeddedBiginteger.doubleValue()); 64 | } 65 | 66 | private SNumber asSNumber(final BigInteger result, final Universe universe) { 67 | if (result.bitLength() >= Long.SIZE) { 68 | return universe.newBigInteger(result); 69 | } else { 70 | return universe.newInteger(result.longValue()); 71 | } 72 | } 73 | 74 | private BigInteger asBigInteger(final SNumber right) { 75 | BigInteger r; 76 | if (right instanceof SInteger) { 77 | r = BigInteger.valueOf(((SInteger) right).getEmbeddedInteger()); 78 | } else { 79 | r = ((SBigInteger) right).embeddedBiginteger; 80 | } 81 | return r; 82 | } 83 | 84 | @Override 85 | public SNumber primAdd(final SNumber right, final Universe universe) { 86 | if (right instanceof SDouble) { 87 | return universe.newDouble( 88 | embeddedBiginteger.doubleValue() + ((SDouble) right).getEmbeddedDouble()); 89 | } 90 | BigInteger r = asBigInteger(right); 91 | BigInteger result = embeddedBiginteger.add(r); 92 | return asSNumber(result, universe); 93 | } 94 | 95 | @Override 96 | public SNumber primSubtract(final SNumber right, final Universe universe) { 97 | if (right instanceof SDouble) { 98 | return universe.newDouble( 99 | embeddedBiginteger.doubleValue() - ((SDouble) right).getEmbeddedDouble()); 100 | } 101 | BigInteger r = asBigInteger(right); 102 | BigInteger result = embeddedBiginteger.subtract(r); 103 | return asSNumber(result, universe); 104 | } 105 | 106 | @Override 107 | public SNumber primMultiply(final SNumber right, final Universe universe) { 108 | if (right instanceof SDouble) { 109 | return universe.newDouble( 110 | embeddedBiginteger.doubleValue() * ((SDouble) right).getEmbeddedDouble()); 111 | } 112 | BigInteger r = asBigInteger(right); 113 | BigInteger result = embeddedBiginteger.multiply(r); 114 | return asSNumber(result, universe); 115 | } 116 | 117 | @Override 118 | public SNumber primDoubleDivide(final SNumber right, final Universe universe) { 119 | double r; 120 | if (right instanceof SInteger) { 121 | r = ((SInteger) right).getEmbeddedInteger(); 122 | } else { 123 | r = ((SBigInteger) right).embeddedBiginteger.doubleValue(); 124 | } 125 | double result = embeddedBiginteger.doubleValue() / r; 126 | return universe.newDouble(result); 127 | } 128 | 129 | @Override 130 | public SNumber primIntegerDivide(final SNumber right, final Universe universe) { 131 | BigInteger r = asBigInteger(right); 132 | BigInteger result = embeddedBiginteger.divide(r); 133 | return asSNumber(result, universe); 134 | } 135 | 136 | @Override 137 | public SNumber primModulo(final SNumber right, final Universe universe) { 138 | BigInteger r = asBigInteger(right); 139 | BigInteger result = embeddedBiginteger.mod(r); 140 | return asSNumber(result, universe); 141 | } 142 | 143 | @Override 144 | public SNumber primSqrt(final Universe universe) { 145 | double result = Math.sqrt(embeddedBiginteger.doubleValue()); 146 | 147 | if (result == Math.rint(result)) { 148 | return intOrBigInt(result, universe); 149 | } else { 150 | return universe.newDouble(result); 151 | } 152 | } 153 | 154 | @Override 155 | public SNumber primBitAnd(final SNumber right, final Universe universe) { 156 | BigInteger r = asBigInteger(right); 157 | BigInteger result = embeddedBiginteger.and(r); 158 | return asSNumber(result, universe); 159 | } 160 | 161 | @Override 162 | public SObject primEqual(final SAbstractObject right, final Universe universe) { 163 | if (!(right instanceof SNumber)) { 164 | return universe.falseObject; 165 | } 166 | 167 | BigInteger r = asBigInteger((SNumber) right); 168 | 169 | if (embeddedBiginteger.compareTo(r) == 0) { 170 | return universe.trueObject; 171 | } else { 172 | return universe.falseObject; 173 | } 174 | } 175 | 176 | @Override 177 | public SObject primLessThan(final SNumber right, final Universe universe) { 178 | BigInteger r = asBigInteger(right); 179 | if (embeddedBiginteger.compareTo(r) < 0) { 180 | return universe.trueObject; 181 | } else { 182 | return universe.falseObject; 183 | } 184 | } 185 | 186 | @Override 187 | public SNumber primLeftShift(final SNumber right, final Universe universe) { 188 | BigInteger r = asBigInteger(right); 189 | return universe.newBigInteger(embeddedBiginteger.shiftLeft(r.intValue())); 190 | } 191 | 192 | @Override 193 | public SNumber primBitXor(final SNumber right, final Universe universe) { 194 | BigInteger r = asBigInteger(right); 195 | BigInteger result = embeddedBiginteger.xor(r); 196 | return asSNumber(result, universe); 197 | } 198 | } 199 | -------------------------------------------------------------------------------- /src/som/vmobjects/SBlock.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2009 Michael Haupt, michael.haupt@hpi.uni-potsdam.de 3 | * Software Architecture Group, Hasso Plattner Institute, Potsdam, Germany 4 | * http://www.hpi.uni-potsdam.de/swa/ 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | package som.vmobjects; 26 | 27 | import som.interpreter.Frame; 28 | import som.interpreter.Interpreter; 29 | import som.vm.Universe; 30 | 31 | 32 | public class SBlock extends SAbstractObject { 33 | 34 | public SBlock(final SMethod method, final Frame context, final SClass blockClass) { 35 | this.method = method; 36 | this.context = context; 37 | this.blockClass = blockClass; 38 | } 39 | 40 | public SMethod getMethod() { 41 | return method; 42 | } 43 | 44 | public Frame getContext() { 45 | return context; 46 | } 47 | 48 | @Override 49 | public SClass getSOMClass(final Universe universe) { 50 | return blockClass; 51 | } 52 | 53 | public static SPrimitive getEvaluationPrimitive(final int numberOfArguments, 54 | final Universe universe) { 55 | return new Evaluation(numberOfArguments, universe); 56 | } 57 | 58 | public static class Evaluation extends SPrimitive { 59 | 60 | public Evaluation(final int numberOfArguments, final Universe universe) { 61 | super(computeSignatureString(numberOfArguments), universe); 62 | this.numberOfArguments = numberOfArguments; 63 | } 64 | 65 | @Override 66 | public void invoke(final Frame frame, final Interpreter interpreter) { 67 | // Get the block (the receiver) from the stack 68 | SBlock self = (SBlock) frame.getStackElement(numberOfArguments - 1); 69 | 70 | // Get the context of the block... 71 | Frame context = self.getContext(); 72 | 73 | // Push a new frame and set its context to be the one specified in 74 | // the block 75 | Frame newFrame = interpreter.pushNewFrame(self.getMethod(), context); 76 | newFrame.copyArgumentsFrom(frame); 77 | } 78 | 79 | private static String computeSignatureString(final int numberOfArguments) { 80 | // Compute the signature string 81 | String signatureString = "value"; 82 | if (numberOfArguments > 1) { 83 | signatureString += ":"; 84 | } 85 | 86 | // Add extra value: selector elements if necessary 87 | for (int i = 2; i < numberOfArguments; i++) { 88 | signatureString += "with:"; 89 | } 90 | 91 | // Return the signature string 92 | return signatureString; 93 | } 94 | 95 | private final int numberOfArguments; 96 | } 97 | 98 | private final SMethod method; 99 | private final Frame context; 100 | private final SClass blockClass; 101 | } 102 | -------------------------------------------------------------------------------- /src/som/vmobjects/SClass.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2009 Michael Haupt, michael.haupt@hpi.uni-potsdam.de 3 | * Software Architecture Group, Hasso Plattner Institute, Potsdam, Germany 4 | * http://www.hpi.uni-potsdam.de/swa/ 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | package som.vmobjects; 26 | 27 | import java.lang.reflect.Constructor; 28 | import java.util.HashMap; 29 | 30 | import som.primitives.Primitives; 31 | import som.vm.Universe; 32 | 33 | 34 | public class SClass extends SObject { 35 | 36 | private final Universe universe; 37 | 38 | public SClass(final Universe universe) { 39 | // Initialize this class by calling the super constructor 40 | super(universe.nilObject); 41 | invokablesTable = new HashMap(); 42 | this.universe = universe; 43 | } 44 | 45 | public SClass(final int numberOfFields, final Universe universe) { 46 | // Initialize this class by calling the super constructor with the given 47 | // value 48 | super(numberOfFields, universe.nilObject); 49 | invokablesTable = new HashMap(); 50 | this.universe = universe; 51 | } 52 | 53 | public SObject getSuperClass() { 54 | // Get the super class by reading the field with super class index 55 | return superclass; 56 | } 57 | 58 | public void setSuperClass(final SObject value) { 59 | // Set the super class by writing to the field with super class index 60 | superclass = value; 61 | } 62 | 63 | public boolean hasSuperClass() { 64 | // Check whether or not this class has a super class 65 | return superclass != universe.nilObject; 66 | } 67 | 68 | public SSymbol getName() { 69 | // Get the name of this class by reading the field with name index 70 | return name; 71 | } 72 | 73 | public void setName(final SSymbol value) { 74 | // Set the name of this class by writing to the field with name index 75 | name = value; 76 | } 77 | 78 | public SArray getInstanceFields() { 79 | // Get the instance fields by reading the field with the instance fields 80 | // index 81 | return instanceFields; 82 | } 83 | 84 | public void setInstanceFields(final SArray value) { 85 | // Set the instance fields by writing to the field with the instance 86 | // fields index 87 | instanceFields = value; 88 | } 89 | 90 | public SArray getInstanceInvokables() { 91 | // Get the instance invokables by reading the field with the instance 92 | // invokables index 93 | return instanceInvokables; 94 | } 95 | 96 | public void setInstanceInvokables(final SArray value) { 97 | // Set the instance invokables by writing to the field with the instance 98 | // invokables index 99 | instanceInvokables = value; 100 | 101 | // Make sure this class is the holder of all invokables in the array 102 | for (int i = 0; i < getNumberOfInstanceInvokables(); i++) { 103 | getInstanceInvokable(i).setHolder(this); 104 | } 105 | } 106 | 107 | public int getNumberOfInstanceInvokables() { 108 | // Return the number of instance invokables in this class 109 | return getInstanceInvokables().getNumberOfIndexableFields(); 110 | } 111 | 112 | public SInvokable getInstanceInvokable(final int index) { 113 | // Get the instance invokable with the given index 114 | return (SInvokable) getInstanceInvokables().getIndexableField(index); 115 | } 116 | 117 | public void setInstanceInvokable(final int index, final SInvokable value) { 118 | // Set this class as the holder of the given invokable 119 | value.setHolder(this); 120 | 121 | // Set the instance method with the given index to the given value 122 | getInstanceInvokables().setIndexableField(index, (SAbstractObject) value); 123 | } 124 | 125 | @Override 126 | public int getDefaultNumberOfFields() { 127 | // Return the default number of fields in a class 128 | return numberOfClassFields; 129 | } 130 | 131 | public SInvokable lookupInvokable(final SSymbol signature) { 132 | SInvokable invokable; 133 | 134 | // Lookup invokable and return if found 135 | invokable = invokablesTable.get(signature); 136 | if (invokable != null) { 137 | return invokable; 138 | } 139 | 140 | // Lookup invokable with given signature in array of instance invokables 141 | for (int i = 0; i < getNumberOfInstanceInvokables(); i++) { 142 | // Get the next invokable in the instance invokable array 143 | invokable = getInstanceInvokable(i); 144 | 145 | // Return the invokable if the signature matches 146 | if (invokable.getSignature() == signature) { 147 | invokablesTable.put(signature, invokable); 148 | return invokable; 149 | } 150 | } 151 | 152 | // Traverse the super class chain by calling lookup on the super class 153 | if (hasSuperClass()) { 154 | invokable = ((SClass) getSuperClass()).lookupInvokable(signature); 155 | if (invokable != null) { 156 | invokablesTable.put(signature, invokable); 157 | return invokable; 158 | } 159 | } 160 | 161 | // Invokable not found 162 | return null; 163 | } 164 | 165 | public int lookupFieldIndex(final SSymbol fieldName) { 166 | // Lookup field with given name in array of instance fields 167 | for (int i = getNumberOfInstanceFields() - 1; i >= 0; i--) { 168 | // Return the current index if the name matches 169 | if (fieldName == getInstanceFieldName(i)) { 170 | return i; 171 | } 172 | } 173 | 174 | // Field not found 175 | return -1; 176 | } 177 | 178 | public boolean addInstanceInvokable(final SInvokable value) { 179 | // Add the given invokable to the array of instance invokables 180 | for (int i = 0; i < getNumberOfInstanceInvokables(); i++) { 181 | // Get the next invokable in the instance invokable array 182 | SInvokable invokable = getInstanceInvokable(i); 183 | 184 | // Replace the invokable with the given one if the signature matches 185 | if (invokable.getSignature() == value.getSignature()) { 186 | setInstanceInvokable(i, value); 187 | return false; 188 | } 189 | } 190 | 191 | // Append the given method to the array of instance methods 192 | setInstanceInvokables(getInstanceInvokables().copyAndExtendWith( 193 | (SAbstractObject) value, universe)); 194 | return true; 195 | } 196 | 197 | public void addInstancePrimitive(final SPrimitive value) { 198 | addInstancePrimitive(value, false); 199 | } 200 | 201 | public void addInstancePrimitive(final SPrimitive value, final boolean suppressWarning) { 202 | if (addInstanceInvokable(value) && !suppressWarning) { 203 | Universe.print("Warning: Primitive " + value.getSignature().getEmbeddedString()); 204 | Universe.println(" is not in class definition for class " 205 | + getName().getEmbeddedString()); 206 | } 207 | } 208 | 209 | public SSymbol getInstanceFieldName(int index) { 210 | // Get the name of the instance field with the given index 211 | if (index >= getNumberOfSuperInstanceFields()) { 212 | // Adjust the index to account for fields defined in the super class 213 | index -= getNumberOfSuperInstanceFields(); 214 | 215 | // Return the symbol representing the instance fields name 216 | return (SSymbol) getInstanceFields().getIndexableField(index); 217 | } else { 218 | // Ask the super class to return the name of the instance field 219 | return ((SClass) getSuperClass()).getInstanceFieldName(index); 220 | } 221 | } 222 | 223 | public int getNumberOfInstanceFields() { 224 | // Get the total number of instance fields in this class 225 | return instanceFields.getNumberOfIndexableFields() 226 | + getNumberOfSuperInstanceFields(); 227 | } 228 | 229 | private int getNumberOfSuperInstanceFields() { 230 | // Get the total number of instance fields defined in super classes 231 | if (hasSuperClass()) { 232 | return ((SClass) getSuperClass()).getNumberOfInstanceFields(); 233 | } else { 234 | return 0; 235 | } 236 | } 237 | 238 | public boolean hasPrimitives() { 239 | // Lookup invokable with given signature in array of instance invokables 240 | for (int i = 0; i < getNumberOfInstanceInvokables(); i++) { 241 | // Get the next invokable in the instance invokable array 242 | if (getInstanceInvokable(i).isPrimitive()) { 243 | return true; 244 | } 245 | } 246 | return false; 247 | } 248 | 249 | public void loadPrimitives() { 250 | // Compute the class name of the Java(TM) class containing the 251 | // primitives 252 | String className = "som.primitives." + getName().getEmbeddedString() 253 | + "Primitives"; 254 | 255 | // Try loading the primitives 256 | try { 257 | Class primitivesClass = Class.forName(className); 258 | try { 259 | Constructor ctor = primitivesClass.getConstructor(Universe.class); 260 | ((Primitives) ctor.newInstance(universe)).installPrimitivesIn(this); 261 | } catch (Exception e) { 262 | Universe.println("Primitives class " + className 263 | + " cannot be instantiated"); 264 | } 265 | } catch (ClassNotFoundException e) { 266 | Universe.println("Primitives class " + className + " not found"); 267 | } 268 | } 269 | 270 | @Override 271 | public String toString() { 272 | return "Class(" + getName().getEmbeddedString() + ")"; 273 | } 274 | 275 | // Implementation specific fields 276 | private SObject superclass; 277 | private SSymbol name; 278 | private SArray instanceInvokables; 279 | private SArray instanceFields; 280 | 281 | // Mapping of symbols to invokables 282 | private final HashMap invokablesTable; 283 | 284 | // Static field indices and number of class fields 285 | static final int numberOfClassFields = numberOfObjectFields; 286 | } 287 | -------------------------------------------------------------------------------- /src/som/vmobjects/SDouble.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2009 Michael Haupt, michael.haupt@hpi.uni-potsdam.de 3 | * Software Architecture Group, Hasso Plattner Institute, Potsdam, Germany 4 | * http://www.hpi.uni-potsdam.de/swa/ 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | package som.vmobjects; 26 | 27 | import som.vm.Universe; 28 | 29 | 30 | public final class SDouble extends SNumber { 31 | 32 | private final double embeddedDouble; 33 | 34 | public SDouble(final double value) { 35 | embeddedDouble = value; 36 | } 37 | 38 | public double getEmbeddedDouble() { 39 | // Get the embedded double 40 | return embeddedDouble; 41 | } 42 | 43 | @Override 44 | public String toString() { 45 | return super.toString() + "(" + embeddedDouble + ")"; 46 | } 47 | 48 | @Override 49 | public SClass getSOMClass(final Universe universe) { 50 | return universe.doubleClass; 51 | } 52 | 53 | private double coerceToDouble(final SNumber o, final Universe universe) { 54 | if (o instanceof SDouble) { 55 | return ((SDouble) o).embeddedDouble; 56 | } 57 | if (o instanceof SInteger) { 58 | return ((SInteger) o).getEmbeddedInteger(); 59 | } 60 | if (o instanceof SBigInteger) { 61 | return ((SBigInteger) o).getEmbeddedBiginteger().doubleValue(); 62 | } 63 | throw new ClassCastException("Cannot coerce to Double!"); 64 | } 65 | 66 | @Override 67 | public SString primAsString(final Universe universe) { 68 | return universe.newString(Double.toString(embeddedDouble)); 69 | } 70 | 71 | @Override 72 | public SDouble primAsDouble(final Universe universe) { 73 | return this; 74 | } 75 | 76 | public SInteger primAsInteger(final Universe universe) { 77 | return universe.newInteger((long) embeddedDouble); 78 | } 79 | 80 | @Override 81 | public SNumber primSqrt(final Universe universe) { 82 | return universe.newDouble(Math.sqrt(embeddedDouble)); 83 | } 84 | 85 | @Override 86 | public SNumber primAdd(final SNumber right, final Universe universe) { 87 | double r = coerceToDouble(right, universe); 88 | return universe.newDouble(embeddedDouble + r); 89 | } 90 | 91 | @Override 92 | public SNumber primSubtract(final SNumber right, final Universe universe) { 93 | double r = coerceToDouble(right, universe); 94 | return universe.newDouble(embeddedDouble - r); 95 | } 96 | 97 | @Override 98 | public SNumber primMultiply(final SNumber right, final Universe universe) { 99 | double r = coerceToDouble(right, universe); 100 | return universe.newDouble(embeddedDouble * r); 101 | } 102 | 103 | @Override 104 | public SNumber primDoubleDivide(final SNumber right, final Universe universe) { 105 | double r = coerceToDouble(right, universe); 106 | return universe.newDouble(embeddedDouble / r); 107 | } 108 | 109 | @Override 110 | public SNumber primIntegerDivide(final SNumber right, final Universe universe) { 111 | throw new RuntimeException("not yet implemented, SOM doesn't offer it"); 112 | } 113 | 114 | @Override 115 | public SNumber primModulo(final SNumber right, final Universe universe) { 116 | double r = coerceToDouble(right, universe); 117 | return universe.newDouble(embeddedDouble % r); 118 | } 119 | 120 | @Override 121 | public SNumber primBitAnd(final SNumber right, final Universe universe) { 122 | throw new RuntimeException("Not supported for doubles"); 123 | } 124 | 125 | @Override 126 | public SNumber primBitXor(final SNumber right, final Universe universe) { 127 | throw new RuntimeException("Not supported for doubles"); 128 | } 129 | 130 | @Override 131 | public SNumber primLeftShift(final SNumber right, final Universe universe) { 132 | throw new RuntimeException("Not supported for doubles"); 133 | } 134 | 135 | @Override 136 | public SObject primEqual(final SAbstractObject right, final Universe universe) { 137 | if (!(right instanceof SNumber)) { 138 | return universe.falseObject; 139 | } 140 | 141 | double r = coerceToDouble((SNumber) right, universe); 142 | return asSBoolean(embeddedDouble == r, universe); 143 | } 144 | 145 | @Override 146 | public SObject primLessThan(final SNumber right, final Universe universe) { 147 | double r = coerceToDouble(right, universe); 148 | return asSBoolean(embeddedDouble < r, universe); 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /src/som/vmobjects/SInteger.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2016 Michael Haupt, github@haupz.de 3 | * Copyright (c) 2009 Michael Haupt, michael.haupt@hpi.uni-potsdam.de 4 | * Software Architecture Group, Hasso Plattner Institute, Potsdam, Germany 5 | * http://www.hpi.uni-potsdam.de/swa/ 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | package som.vmobjects; 27 | 28 | import java.math.BigInteger; 29 | import java.util.HashMap; 30 | import java.util.Map; 31 | 32 | import som.vm.Universe; 33 | 34 | 35 | public final class SInteger extends SNumber { 36 | 37 | /** 38 | * Language convention requires integers up to this value to be identical. 39 | */ 40 | private static final long MAX_IDENTICAL_INT = 1073741823L; 41 | 42 | /** 43 | * Cache to store integers up to {@link #MAX_IDENTICAL_INT}. 44 | */ 45 | private static Map CACHE = new HashMap<>(); 46 | 47 | // Private variable holding the embedded integer 48 | private final long embeddedInteger; 49 | 50 | private SInteger(final long value) { 51 | embeddedInteger = value; 52 | } 53 | 54 | public static SInteger getInteger(final long value) { 55 | if (value > MAX_IDENTICAL_INT) { 56 | return new SInteger(value); 57 | } 58 | return CACHE.computeIfAbsent(value, SInteger::new); 59 | } 60 | 61 | public long getEmbeddedInteger() { 62 | // Get the embedded integer 63 | return embeddedInteger; 64 | } 65 | 66 | @Override 67 | public String toString() { 68 | return super.toString() + "(" + embeddedInteger + ")"; 69 | } 70 | 71 | @Override 72 | public SClass getSOMClass(final Universe universe) { 73 | return universe.integerClass; 74 | } 75 | 76 | @Override 77 | public SString primAsString(final Universe universe) { 78 | return universe.newString(Long.toString(embeddedInteger)); 79 | } 80 | 81 | @Override 82 | public SNumber primAsDouble(final Universe universe) { 83 | return universe.newDouble(embeddedInteger); 84 | } 85 | 86 | @Override 87 | public SNumber primSqrt(final Universe universe) { 88 | double result = Math.sqrt(embeddedInteger); 89 | 90 | if (result == Math.rint(result)) { 91 | return intOrBigInt(result, universe); 92 | } else { 93 | return universe.newDouble(result); 94 | } 95 | } 96 | 97 | @Override 98 | public SNumber primAdd(final SNumber right, final Universe universe) { 99 | if (right instanceof SBigInteger) { 100 | BigInteger result = BigInteger.valueOf(embeddedInteger).add( 101 | ((SBigInteger) right).getEmbeddedBiginteger()); 102 | return universe.newBigInteger(result); 103 | } else if (right instanceof SDouble) { 104 | double result = embeddedInteger + ((SDouble) right).getEmbeddedDouble(); 105 | return universe.newDouble(result); 106 | } else { 107 | SInteger r = (SInteger) right; 108 | 109 | try { 110 | long result = Math.addExact(embeddedInteger, r.getEmbeddedInteger()); 111 | return universe.newInteger(result); 112 | } catch (ArithmeticException e) { 113 | BigInteger result = BigInteger.valueOf(embeddedInteger).add( 114 | BigInteger.valueOf(r.getEmbeddedInteger())); 115 | return universe.newBigInteger(result); 116 | } 117 | } 118 | } 119 | 120 | @Override 121 | public SNumber primSubtract(final SNumber right, final Universe universe) { 122 | if (right instanceof SBigInteger) { 123 | BigInteger result = BigInteger.valueOf(embeddedInteger).subtract( 124 | ((SBigInteger) right).getEmbeddedBiginteger()); 125 | return universe.newBigInteger(result); 126 | } else if (right instanceof SDouble) { 127 | double result = embeddedInteger - ((SDouble) right).getEmbeddedDouble(); 128 | return universe.newDouble(result); 129 | } else { 130 | SInteger r = (SInteger) right; 131 | 132 | try { 133 | long result = Math.subtractExact(embeddedInteger, r.getEmbeddedInteger()); 134 | return universe.newInteger(result); 135 | } catch (ArithmeticException e) { 136 | BigInteger result = BigInteger.valueOf(embeddedInteger).subtract( 137 | BigInteger.valueOf(r.getEmbeddedInteger())); 138 | return universe.newBigInteger(result); 139 | } 140 | } 141 | } 142 | 143 | @Override 144 | public SNumber primMultiply(final SNumber right, final Universe universe) { 145 | if (right instanceof SBigInteger) { 146 | BigInteger result = BigInteger.valueOf(embeddedInteger).multiply( 147 | ((SBigInteger) right).getEmbeddedBiginteger()); 148 | return universe.newBigInteger(result); 149 | } else if (right instanceof SDouble) { 150 | double result = embeddedInteger * ((SDouble) right).getEmbeddedDouble(); 151 | return universe.newDouble(result); 152 | } else { 153 | SInteger r = (SInteger) right; 154 | 155 | try { 156 | long result = Math.multiplyExact(embeddedInteger, r.getEmbeddedInteger()); 157 | return universe.newInteger(result); 158 | } catch (ArithmeticException e) { 159 | BigInteger result = BigInteger.valueOf(embeddedInteger).multiply( 160 | BigInteger.valueOf(r.getEmbeddedInteger())); 161 | return universe.newBigInteger(result); 162 | } 163 | } 164 | } 165 | 166 | @Override 167 | public SNumber primDoubleDivide(final SNumber right, final Universe universe) { 168 | double result; 169 | 170 | if (right instanceof SBigInteger) { 171 | result = embeddedInteger / ((SBigInteger) right).getEmbeddedBiginteger().doubleValue(); 172 | } else if (right instanceof SDouble) { 173 | result = embeddedInteger / ((SDouble) right).getEmbeddedDouble(); 174 | } else { 175 | result = (double) embeddedInteger / ((SInteger) right).getEmbeddedInteger(); 176 | } 177 | 178 | return universe.newDouble(result); 179 | } 180 | 181 | @Override 182 | public SNumber primIntegerDivide(final SNumber right, final Universe universe) { 183 | if (right instanceof SBigInteger) { 184 | BigInteger result = BigInteger.valueOf(embeddedInteger).divide( 185 | ((SBigInteger) right).getEmbeddedBiginteger()); 186 | return universe.newBigInteger(result); 187 | } else if (right instanceof SDouble) { 188 | long result = (long) (embeddedInteger / ((SDouble) right).getEmbeddedDouble()); 189 | return universe.newInteger(result); 190 | } else { 191 | long result = embeddedInteger / ((SInteger) right).getEmbeddedInteger(); 192 | return universe.newInteger(result); 193 | } 194 | } 195 | 196 | @Override 197 | public SNumber primModulo(final SNumber right, final Universe universe) { 198 | if (right instanceof SBigInteger) { 199 | // Note: modulo semantics of SOM differ from Java, with respect to 200 | // negative operands, but BigInteger doesn't support a negative 201 | // second operand, so, we should get an exception, which we can 202 | // properly handle once an application actually needs it. 203 | BigInteger result = BigInteger.valueOf(embeddedInteger).mod( 204 | ((SBigInteger) right).getEmbeddedBiginteger()); 205 | return universe.newBigInteger(result); 206 | } else if (right instanceof SDouble) { 207 | double result = embeddedInteger % ((SDouble) right).getEmbeddedDouble(); 208 | return universe.newDouble(result); 209 | } else { 210 | long r = ((SInteger) right).getEmbeddedInteger(); 211 | long result = Math.floorMod(embeddedInteger, r); 212 | return universe.newInteger(result); 213 | } 214 | } 215 | 216 | public SInteger primRemainder(final SNumber right, final Universe universe) { 217 | if (right instanceof SInteger) { 218 | return universe.newInteger(embeddedInteger % ((SInteger) right).embeddedInteger); 219 | } else { 220 | throw new RuntimeException("TODO"); 221 | } 222 | } 223 | 224 | @Override 225 | public SNumber primBitAnd(final SNumber right, final Universe universe) { 226 | if (right instanceof SBigInteger) { 227 | BigInteger result = BigInteger.valueOf(embeddedInteger).and( 228 | ((SBigInteger) right).getEmbeddedBiginteger()); 229 | return universe.newBigInteger(result); 230 | } else { 231 | long result = embeddedInteger & ((SInteger) right).embeddedInteger; 232 | return universe.newInteger(result); 233 | } 234 | } 235 | 236 | @Override 237 | public SNumber primBitXor(final SNumber right, final Universe universe) { 238 | if (right instanceof SBigInteger) { 239 | BigInteger result = BigInteger.valueOf(embeddedInteger).xor( 240 | ((SBigInteger) right).getEmbeddedBiginteger()); 241 | return universe.newBigInteger(result); 242 | } else { 243 | long result = embeddedInteger ^ ((SInteger) right).embeddedInteger; 244 | return universe.newInteger(result); 245 | } 246 | } 247 | 248 | @Override 249 | public SNumber primLeftShift(final SNumber right, final Universe universe) { 250 | long r = ((SInteger) right).embeddedInteger; 251 | assert r > 0; 252 | 253 | if (Long.SIZE - Long.numberOfLeadingZeros(embeddedInteger) + r > Long.SIZE - 1) { 254 | BigInteger result = BigInteger.valueOf(embeddedInteger).shiftLeft((int) r); 255 | return universe.newBigInteger(result); 256 | } 257 | 258 | long result = embeddedInteger << r; 259 | return universe.newInteger(result); 260 | } 261 | 262 | @Override 263 | public SObject primEqual(final SAbstractObject right, final Universe universe) { 264 | boolean result; 265 | 266 | if (right instanceof SBigInteger) { 267 | result = BigInteger.valueOf(embeddedInteger).equals( 268 | ((SBigInteger) right).getEmbeddedBiginteger()); 269 | } else if (right instanceof SDouble) { 270 | result = embeddedInteger == ((SDouble) right).getEmbeddedDouble(); 271 | } else if (right instanceof SInteger) { 272 | result = embeddedInteger == ((SInteger) right).getEmbeddedInteger(); 273 | } else { 274 | result = false; 275 | } 276 | 277 | return asSBoolean(result, universe); 278 | } 279 | 280 | @Override 281 | public SObject primLessThan(final SNumber right, final Universe universe) { 282 | boolean result; 283 | if (right instanceof SBigInteger) { 284 | result = BigInteger.valueOf(embeddedInteger).compareTo( 285 | ((SBigInteger) right).getEmbeddedBiginteger()) < 0; 286 | } else if (right instanceof SDouble) { 287 | result = embeddedInteger < ((SDouble) right).getEmbeddedDouble(); 288 | } else { 289 | result = embeddedInteger < ((SInteger) right).getEmbeddedInteger(); 290 | } 291 | 292 | return asSBoolean(result, universe); 293 | } 294 | } 295 | -------------------------------------------------------------------------------- /src/som/vmobjects/SInvokable.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2009 Michael Haupt, michael.haupt@hpi.uni-potsdam.de 3 | * Software Architecture Group, Hasso Plattner Institute, Potsdam, Germany 4 | * http://www.hpi.uni-potsdam.de/swa/ 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | package som.vmobjects; 26 | 27 | import som.interpreter.Frame; 28 | import som.interpreter.Interpreter; 29 | 30 | 31 | public interface SInvokable { 32 | 33 | // Tells whether this is a primitive 34 | boolean isPrimitive(); 35 | 36 | // Invoke this invokable object in a given frame 37 | void invoke(Frame frame, Interpreter interpreter); 38 | 39 | // Get the signature for this invokable object 40 | SSymbol getSignature(); 41 | 42 | // Get the holder for this invokable object 43 | SClass getHolder(); 44 | 45 | // Set the holder for this invokable object 46 | void setHolder(SClass value); 47 | } 48 | -------------------------------------------------------------------------------- /src/som/vmobjects/SMethod.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2009 Michael Haupt, michael.haupt@hpi.uni-potsdam.de 3 | * Software Architecture Group, Hasso Plattner Institute, Potsdam, Germany 4 | * http://www.hpi.uni-potsdam.de/swa/ 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | package som.vmobjects; 26 | 27 | import java.util.List; 28 | 29 | import som.interpreter.Frame; 30 | import som.interpreter.Interpreter; 31 | import som.vm.Universe; 32 | 33 | 34 | public class SMethod extends SAbstractObject implements SInvokable { 35 | 36 | public SMethod(final SSymbol signature, final int numberOfBytecodes, 37 | final int numberOfLocals, final int maxNumStackElements, 38 | final List literals) { 39 | this.signature = signature; 40 | this.numberOfLocals = numberOfLocals; 41 | this.bytecodes = new byte[numberOfBytecodes]; 42 | inlineCacheClass = new SClass[numberOfBytecodes]; 43 | inlineCacheInvokable = new SInvokable[numberOfBytecodes]; 44 | maximumNumberOfStackElements = maxNumStackElements; 45 | this.literals = 46 | literals == null ? null : literals.toArray(new SAbstractObject[literals.size()]); 47 | } 48 | 49 | @Override 50 | public boolean isPrimitive() { 51 | return false; 52 | } 53 | 54 | public int getNumberOfLocals() { 55 | return numberOfLocals; 56 | } 57 | 58 | public int getMaximumNumberOfStackElements() { 59 | return maximumNumberOfStackElements; 60 | } 61 | 62 | @Override 63 | public SSymbol getSignature() { 64 | return signature; 65 | } 66 | 67 | @Override 68 | public SClass getHolder() { 69 | return holder; 70 | } 71 | 72 | @Override 73 | public void setHolder(final SClass value) { 74 | holder = value; 75 | 76 | if (literals == null) { 77 | return; 78 | } 79 | 80 | // Make sure all nested invokables have the same holder 81 | for (int i = 0; i < literals.length; i++) { 82 | if (literals[i] instanceof SInvokable) { 83 | ((SInvokable) literals[i]).setHolder(value); 84 | } 85 | } 86 | } 87 | 88 | public SAbstractObject getConstant(final int bytecodeIndex) { 89 | // Get the constant associated to a given bytecode index 90 | return literals[bytecodes[bytecodeIndex + 1]]; 91 | } 92 | 93 | public int getNumberOfArguments() { 94 | // Get the number of arguments of this method 95 | return getSignature().getNumberOfSignatureArguments(); 96 | } 97 | 98 | public int getNumberOfBytecodes() { 99 | // Get the number of bytecodes in this method 100 | return bytecodes.length; 101 | } 102 | 103 | public byte getBytecode(final int index) { 104 | // Get the bytecode at the given index 105 | return bytecodes[index]; 106 | } 107 | 108 | public void setBytecode(final int index, final byte value) { 109 | // Set the bytecode at the given index to the given value 110 | bytecodes[index] = value; 111 | } 112 | 113 | @Override 114 | public void invoke(final Frame frame, final Interpreter interpreter) { 115 | // Allocate and push a new frame on the interpreter stack 116 | Frame newFrame = interpreter.pushNewFrame(this); 117 | newFrame.copyArgumentsFrom(frame); 118 | } 119 | 120 | @Override 121 | public String toString() { 122 | return "Method(" + getHolder().getName().getEmbeddedString() + ">>" 123 | + getSignature().toString() + ")"; 124 | } 125 | 126 | public SClass getInlineCacheClass(final int bytecodeIndex) { 127 | return inlineCacheClass[bytecodeIndex]; 128 | } 129 | 130 | public SInvokable getInlineCacheInvokable(final int bytecodeIndex) { 131 | return inlineCacheInvokable[bytecodeIndex]; 132 | } 133 | 134 | public void setInlineCache(final int bytecodeIndex, final SClass receiverClass, 135 | final SInvokable invokable) { 136 | inlineCacheClass[bytecodeIndex] = receiverClass; 137 | inlineCacheInvokable[bytecodeIndex] = invokable; 138 | } 139 | 140 | @Override 141 | public SClass getSOMClass(final Universe universe) { 142 | return universe.methodClass; 143 | } 144 | 145 | // Private variable holding byte array of bytecodes 146 | private final byte[] bytecodes; 147 | private final SClass[] inlineCacheClass; 148 | private final SInvokable[] inlineCacheInvokable; 149 | 150 | private final SAbstractObject[] literals; 151 | 152 | private final SSymbol signature; 153 | private SClass holder; 154 | 155 | // Meta information 156 | private final int numberOfLocals; 157 | private final int maximumNumberOfStackElements; 158 | } 159 | -------------------------------------------------------------------------------- /src/som/vmobjects/SNumber.java: -------------------------------------------------------------------------------- 1 | package som.vmobjects; 2 | 3 | import java.math.BigInteger; 4 | 5 | import som.vm.Universe; 6 | 7 | 8 | public abstract class SNumber extends SAbstractObject { 9 | public abstract SString primAsString(Universe universe); 10 | 11 | public abstract SNumber primAsDouble(Universe universe); 12 | 13 | public abstract SNumber primSqrt(Universe universe); 14 | 15 | public abstract SNumber primAdd(SNumber right, Universe universe); 16 | 17 | public abstract SNumber primSubtract(SNumber right, Universe universe); 18 | 19 | public abstract SNumber primMultiply(SNumber right, Universe universe); 20 | 21 | public abstract SNumber primDoubleDivide(SNumber right, Universe universe); 22 | 23 | public abstract SNumber primIntegerDivide(SNumber right, Universe universe); 24 | 25 | public abstract SNumber primModulo(SNumber right, Universe universe); 26 | 27 | public abstract SNumber primBitAnd(SNumber right, Universe universe); 28 | 29 | public abstract SNumber primBitXor(SNumber right, Universe universe); 30 | 31 | public abstract SNumber primLeftShift(SNumber right, Universe universe); 32 | 33 | public abstract SObject primEqual(SAbstractObject right, Universe universe); 34 | 35 | public abstract SObject primLessThan(SNumber right, Universe universe); 36 | 37 | protected final SNumber intOrBigInt(final double value, final Universe universe) { 38 | if (value > Long.MAX_VALUE || value < Long.MIN_VALUE) { 39 | return universe.newBigInteger(new BigInteger(Double.toString(Math.rint(value)))); 40 | } else { 41 | return universe.newInteger((long) Math.rint(value)); 42 | } 43 | } 44 | 45 | protected final SObject asSBoolean(final boolean result, final Universe universe) { 46 | if (result) { 47 | return universe.trueObject; 48 | } else { 49 | return universe.falseObject; 50 | } 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/som/vmobjects/SObject.java: -------------------------------------------------------------------------------- 1 | package som.vmobjects; 2 | 3 | import som.vm.Universe; 4 | 5 | 6 | public class SObject extends SAbstractObject { 7 | 8 | public SObject(final SObject nilObject) { 9 | fields = new SAbstractObject[getDefaultNumberOfFields()]; 10 | 11 | // Clear each and every field by putting nil into them 12 | for (int i = 0; i < getNumberOfFields(); i++) { 13 | setField(i, nilObject); 14 | } 15 | } 16 | 17 | public SObject(final int numberOfFields, final SObject nilObject) { 18 | fields = new SAbstractObject[numberOfFields]; 19 | 20 | // Clear each and every field by putting nil into them 21 | for (int i = 0; i < getNumberOfFields(); i++) { 22 | setField(i, nilObject); 23 | } 24 | } 25 | 26 | public SClass getSOMClass() { 27 | return clazz; 28 | } 29 | 30 | public void setClass(final SClass value) { 31 | // Set the class of this object by writing to the field with class index 32 | clazz = value; 33 | } 34 | 35 | public SSymbol getFieldName(final int index) { 36 | // Get the name of the field with the given index 37 | return getSOMClass().getInstanceFieldName(index); 38 | } 39 | 40 | public int getFieldIndex(final SSymbol name) { 41 | // Get the index for the field with the given name 42 | return getSOMClass().lookupFieldIndex(name); 43 | } 44 | 45 | public int getNumberOfFields() { 46 | // Get the number of fields in this object 47 | return fields.length; 48 | } 49 | 50 | public int getDefaultNumberOfFields() { 51 | // Return the default number of fields in an object 52 | return numberOfObjectFields; 53 | } 54 | 55 | public SAbstractObject getField(final long index) { 56 | // Get the field with the given index 57 | return fields[(int) index]; 58 | } 59 | 60 | public void setField(final long index, final SAbstractObject value) { 61 | // Set the field with the given index to the given value 62 | fields[(int) index] = value; 63 | } 64 | 65 | @Override 66 | public SClass getSOMClass(final Universe universe) { 67 | return clazz; 68 | } 69 | 70 | @Override 71 | public String toString() { 72 | if (clazz.getName().getEmbeddedString().equals("SObject")) { 73 | if (fields[1] instanceof SObject) { 74 | SObject somClazz = (SObject) fields[1]; 75 | SObject nameSymbolObj = (SObject) somClazz.fields[4]; 76 | SString nameString = (SString) nameSymbolObj.fields[0]; 77 | return "SomSom: a " + nameString.getEmbeddedString(); 78 | } 79 | } 80 | return "a " + getSOMClass(Universe.current()).getName().getEmbeddedString(); 81 | } 82 | 83 | // Private array of fields 84 | private final SAbstractObject[] fields; 85 | private SClass clazz; 86 | 87 | // Static field indices and number of object fields 88 | static final int numberOfObjectFields = 0; 89 | } 90 | -------------------------------------------------------------------------------- /src/som/vmobjects/SPrimitive.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2013 Stefan Marr, stefan.marr@vub.ac.be 3 | * Copyright (c) 2009 Michael Haupt, michael.haupt@hpi.uni-potsdam.de 4 | * Software Architecture Group, Hasso Plattner Institute, Potsdam, Germany 5 | * http://www.hpi.uni-potsdam.de/swa/ 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | package som.vmobjects; 27 | 28 | import som.interpreter.Frame; 29 | import som.interpreter.Interpreter; 30 | import som.vm.Universe; 31 | 32 | 33 | public abstract class SPrimitive extends SAbstractObject implements SInvokable { 34 | 35 | @Override 36 | public boolean isPrimitive() { 37 | return true; 38 | } 39 | 40 | public SPrimitive(String signatureString, final Universe universe) { 41 | signature = universe.symbolFor(signatureString); 42 | } 43 | 44 | @Override 45 | public SSymbol getSignature() { 46 | return signature; 47 | } 48 | 49 | @Override 50 | public SClass getHolder() { 51 | return holder; 52 | } 53 | 54 | @Override 55 | public void setHolder(SClass value) { 56 | holder = value; 57 | } 58 | 59 | public boolean isEmpty() { 60 | // By default a primitive is not empty 61 | return false; 62 | } 63 | 64 | @Override 65 | public SClass getSOMClass(final Universe universe) { 66 | return universe.primitiveClass; 67 | } 68 | 69 | public static SPrimitive getEmptyPrimitive(java.lang.String signatureString, 70 | final Universe universe) { 71 | // Return an empty primitive with the given signature 72 | return (new SPrimitive(signatureString, universe) { 73 | 74 | @Override 75 | public void invoke(final Frame frame, final Interpreter interpreter) { 76 | // Write a warning to the screen 77 | Universe.println("Warning: undefined primitive " 78 | + this.getSignature().getEmbeddedString() + " called"); 79 | } 80 | 81 | @Override 82 | public boolean isEmpty() { 83 | // The empty primitives are empty 84 | return true; 85 | } 86 | }); 87 | } 88 | 89 | private final SSymbol signature; 90 | private SClass holder; 91 | } 92 | -------------------------------------------------------------------------------- /src/som/vmobjects/SString.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2009 Michael Haupt, michael.haupt@hpi.uni-potsdam.de 3 | * Software Architecture Group, Hasso Plattner Institute, Potsdam, Germany 4 | * http://www.hpi.uni-potsdam.de/swa/ 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | package som.vmobjects; 26 | 27 | import som.vm.Universe; 28 | 29 | 30 | public class SString extends SAbstractObject { 31 | 32 | public SString(final String value) { 33 | string = value; 34 | } 35 | 36 | public String getEmbeddedString() { 37 | return string; 38 | } 39 | 40 | @Override 41 | public String toString() { 42 | return "\"" + string + "\""; 43 | } 44 | 45 | @Override 46 | public SClass getSOMClass(final Universe universe) { 47 | return universe.stringClass; 48 | } 49 | 50 | // Private variable holding the string associated to this symbol 51 | private final String string; 52 | } 53 | -------------------------------------------------------------------------------- /src/som/vmobjects/SSymbol.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2009 Michael Haupt, michael.haupt@hpi.uni-potsdam.de 3 | * Software Architecture Group, Hasso Plattner Institute, Potsdam, Germany 4 | * http://www.hpi.uni-potsdam.de/swa/ 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | package som.vmobjects; 26 | 27 | import som.compiler.Lexer; 28 | import som.vm.Universe; 29 | 30 | 31 | public class SSymbol extends SString { 32 | 33 | public SSymbol(final String value) { 34 | super(value); 35 | numberOfSignatureArguments = determineNumberOfSignatureArguments(); 36 | } 37 | 38 | private int determineNumberOfSignatureArguments() { 39 | // Check for binary signature 40 | if (isBinarySignature()) { 41 | return 2; 42 | } else { 43 | // Count the colons in the signature string 44 | int numberOfColons = 0; 45 | 46 | // Iterate through every character in the signature string 47 | for (char c : getEmbeddedString().toCharArray()) { 48 | if (c == ':') { 49 | numberOfColons++; 50 | } 51 | } 52 | 53 | // The number of arguments is equal to the number of colons plus one 54 | return numberOfColons + 1; 55 | } 56 | } 57 | 58 | @Override 59 | public String toString() { 60 | return "#" + getEmbeddedString(); 61 | } 62 | 63 | public int getNumberOfSignatureArguments() { 64 | return numberOfSignatureArguments; 65 | } 66 | 67 | public boolean isBinarySignature() { 68 | // Check the individual characters of the string 69 | for (char c : getEmbeddedString().toCharArray()) { 70 | if (!Lexer.isOperator(c)) { 71 | return false; 72 | } 73 | } 74 | return true; 75 | } 76 | 77 | @Override 78 | public SClass getSOMClass(final Universe universe) { 79 | return universe.symbolClass; 80 | } 81 | 82 | private final int numberOfSignatureArguments; 83 | } 84 | -------------------------------------------------------------------------------- /tests/som/compiler/LexerTests.java: -------------------------------------------------------------------------------- 1 | package som.compiler; 2 | 3 | import static org.junit.Assert.assertEquals; 4 | 5 | import java.io.StringReader; 6 | 7 | import org.junit.Test; 8 | 9 | 10 | /** 11 | * A small set of tests for the SOM lexer to demonstrate it's basic functionality. 12 | */ 13 | public class LexerTests { 14 | @Test 15 | public void emptyClass() { 16 | Lexer l = new Lexer(new StringReader("Foo = ()")); 17 | 18 | assertEquals(Symbol.Identifier, l.getSym()); 19 | assertEquals("Foo", l.getText()); 20 | 21 | assertEquals(Symbol.Equal, l.getSym()); 22 | assertEquals("=", l.getText()); 23 | 24 | assertEquals(Symbol.NewTerm, l.getSym()); 25 | assertEquals("(", l.getText()); 26 | 27 | assertEquals(Symbol.EndTerm, l.getSym()); 28 | assertEquals(")", l.getText()); 29 | 30 | assertEquals(Symbol.NONE, l.getSym()); 31 | } 32 | 33 | @Test 34 | public void keywordSymbol() { 35 | Lexer l = new Lexer(new StringReader("#key:word:")); 36 | 37 | assertEquals(Symbol.Pound, l.getSym()); 38 | assertEquals("#", l.getText()); 39 | 40 | assertEquals(Symbol.KeywordSequence, l.getSym()); 41 | assertEquals("key:word:", l.getText()); 42 | 43 | assertEquals(Symbol.NONE, l.getSym()); 44 | } 45 | 46 | @Test 47 | public void assignDouble() { 48 | Lexer l = new Lexer(new StringReader("var := 3.14.")); 49 | 50 | assertEquals(Symbol.Identifier, l.getSym()); 51 | assertEquals("var", l.getText()); 52 | 53 | assertEquals(Symbol.Assign, l.getSym()); 54 | assertEquals(":=", l.getText()); 55 | 56 | assertEquals(Symbol.Double, l.getSym()); 57 | assertEquals("3.14", l.getText()); 58 | 59 | assertEquals(Symbol.Period, l.getSym()); 60 | assertEquals(".", l.getText()); 61 | 62 | assertEquals(Symbol.NONE, l.getSym()); 63 | } 64 | 65 | @Test 66 | public void string() { 67 | Lexer l = new Lexer(new StringReader("'some string with new\nline'")); 68 | 69 | assertEquals(Symbol.STString, l.getSym()); 70 | assertEquals("some string with new\nline", l.getText()); 71 | 72 | assertEquals(Symbol.NONE, l.getSym()); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /tests/som/tests/BasicInterpreterTests.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2013 Stefan Marr, stefan.marr@vub.ac.be 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE. 21 | */ 22 | package som.tests; 23 | 24 | import static org.junit.Assert.assertEquals; 25 | import static org.junit.Assert.fail; 26 | 27 | import java.util.Arrays; 28 | 29 | import org.junit.Test; 30 | import org.junit.runner.RunWith; 31 | import org.junit.runners.Parameterized; 32 | import org.junit.runners.Parameterized.Parameters; 33 | 34 | import som.compiler.ProgramDefinitionError; 35 | import som.vm.Universe; 36 | import som.vmobjects.SClass; 37 | import som.vmobjects.SDouble; 38 | import som.vmobjects.SInteger; 39 | import som.vmobjects.SSymbol; 40 | 41 | 42 | @RunWith(Parameterized.class) 43 | public class BasicInterpreterTests { 44 | 45 | @Parameters(name = "{0}.{1} [{index}]") 46 | public static Iterable data() { 47 | return Arrays.asList(new Object[][] { 48 | // {"Self", "assignSuper", 42, ProgramDefinitionError.class}, 49 | 50 | {"MethodCall", "test", 42, SInteger.class}, 51 | {"MethodCall", "test2", 42, SInteger.class}, 52 | 53 | {"NonLocalReturn", "test1", 42, SInteger.class}, 54 | {"NonLocalReturn", "test2", 43, SInteger.class}, 55 | {"NonLocalReturn", "test3", 3, SInteger.class}, 56 | {"NonLocalReturn", "test4", 42, SInteger.class}, 57 | {"NonLocalReturn", "test5", 22, SInteger.class}, 58 | 59 | {"Blocks", "testArg1", 42, SInteger.class}, 60 | {"Blocks", "testArg2", 77, SInteger.class}, 61 | {"Blocks", "testArgAndLocal", 8, SInteger.class}, 62 | {"Blocks", "testArgAndContext", 8, SInteger.class}, 63 | {"Blocks", "testEmptyZeroArg", 1, SInteger.class}, 64 | {"Blocks", "testEmptyOneArg", 1, SInteger.class}, 65 | {"Blocks", "testEmptyTwoArg", 1, SInteger.class}, 66 | 67 | {"Return", "testReturnSelf", "Return", SClass.class}, 68 | {"Return", "testReturnSelfImplicitly", "Return", SClass.class}, 69 | {"Return", "testNoReturnReturnsSelf", "Return", SClass.class}, 70 | {"Return", "testBlockReturnsImplicitlyLastValue", 4, SInteger.class}, 71 | 72 | {"IfTrueIfFalse", "test", 42, SInteger.class}, 73 | {"IfTrueIfFalse", "test2", 33, SInteger.class}, 74 | {"IfTrueIfFalse", "test3", 4, SInteger.class}, 75 | 76 | {"IfTrueIfFalse", "testIfTrueTrueResult", "Integer", SClass.class}, 77 | {"IfTrueIfFalse", "testIfTrueFalseResult", "Nil", SClass.class}, 78 | {"IfTrueIfFalse", "testIfFalseTrueResult", "Nil", SClass.class}, 79 | {"IfTrueIfFalse", "testIfFalseFalseResult", "Integer", SClass.class}, 80 | 81 | {"CompilerSimplification", "testReturnConstantSymbol", "constant", SSymbol.class}, 82 | {"CompilerSimplification", "testReturnConstantInt", 42, SInteger.class}, 83 | {"CompilerSimplification", "testReturnSelf", "CompilerSimplification", SClass.class}, 84 | {"CompilerSimplification", "testReturnSelfImplicitly", "CompilerSimplification", 85 | SClass.class}, 86 | {"CompilerSimplification", "testReturnArgumentN", 55, SInteger.class}, 87 | {"CompilerSimplification", "testReturnArgumentA", 44, SInteger.class}, 88 | {"CompilerSimplification", "testSetField", "foo", SSymbol.class}, 89 | {"CompilerSimplification", "testGetField", 40, SInteger.class}, 90 | 91 | {"Hash", "testHash", 444, SInteger.class}, 92 | 93 | {"Arrays", "testEmptyToInts", 3, SInteger.class}, 94 | {"Arrays", "testPutAllInt", 5, SInteger.class}, 95 | {"Arrays", "testPutAllNil", "Nil", SClass.class}, 96 | {"Arrays", "testPutAllBlock", 3, SInteger.class}, 97 | {"Arrays", "testNewWithAll", 1, SInteger.class}, 98 | 99 | {"BlockInlining", "testNoInlining", 1, SInteger.class}, 100 | {"BlockInlining", "testOneLevelInlining", 1, SInteger.class}, 101 | {"BlockInlining", "testOneLevelInliningWithLocalShadowTrue", 2, SInteger.class}, 102 | {"BlockInlining", "testOneLevelInliningWithLocalShadowFalse", 1, SInteger.class}, 103 | 104 | {"BlockInlining", "testShadowDoesntStoreWrongLocal", 33, SInteger.class}, 105 | {"BlockInlining", "testShadowDoesntReadUnrelated", "Nil", SClass.class}, 106 | 107 | {"BlockInlining", "testBlockNestedInIfTrue", 2, SInteger.class}, 108 | {"BlockInlining", "testBlockNestedInIfFalse", 42, SInteger.class}, 109 | 110 | {"BlockInlining", "testStackDisciplineTrue", 1, SInteger.class}, 111 | {"BlockInlining", "testStackDisciplineFalse", 2, SInteger.class}, 112 | 113 | {"BlockInlining", "testDeepNestedInlinedIfTrue", 3, SInteger.class}, 114 | {"BlockInlining", "testDeepNestedInlinedIfFalse", 42, SInteger.class}, 115 | 116 | {"BlockInlining", "testDeepNestedBlocksInInlinedIfTrue", 5, SInteger.class}, 117 | {"BlockInlining", "testDeepNestedBlocksInInlinedIfFalse", 43, SInteger.class}, 118 | 119 | {"BlockInlining", "testDeepDeepNestedTrue", 9, SInteger.class}, 120 | {"BlockInlining", "testDeepDeepNestedFalse", 43, SInteger.class}, 121 | 122 | {"BlockInlining", "testToDoNestDoNestIfTrue", 2, SInteger.class}, 123 | 124 | {"NonLocalVars", "testWriteDifferentTypes", 3.75, SDouble.class}, 125 | 126 | {"ObjectCreation", "test", 1000000, SInteger.class}, 127 | 128 | {"Regressions", "testSymbolEquality", 1, SInteger.class}, 129 | {"Regressions", "testSymbolReferenceEquality", 1, SInteger.class}, 130 | {"Regressions", "testUninitializedLocal", 1, SInteger.class}, 131 | {"Regressions", "testUninitializedLocalInBlock", 1, SInteger.class}, 132 | 133 | {"BinaryOperation", "test", 3 + 8, SInteger.class}, 134 | 135 | {"NumberOfTests", "numberOfTests", 65, SInteger.class} 136 | }); 137 | } 138 | 139 | private final String testClass; 140 | private final String testSelector; 141 | private final Object expectedResult; 142 | private final Class resultType; 143 | 144 | public BasicInterpreterTests(final String testClass, 145 | final String testSelector, 146 | final Object expectedResult, 147 | final Class resultType) { 148 | this.testClass = testClass; 149 | this.testSelector = testSelector; 150 | this.expectedResult = expectedResult; 151 | this.resultType = resultType; 152 | } 153 | 154 | protected void assertExpectedEqualsSOMValue(final Object actualResult) { 155 | if (resultType == SInteger.class) { 156 | long expected = (int) expectedResult; 157 | long actual = ((SInteger) actualResult).getEmbeddedInteger(); 158 | assertEquals(expected, actual); 159 | return; 160 | } 161 | 162 | if (resultType == SDouble.class) { 163 | double expected = (double) expectedResult; 164 | double actual = ((SDouble) actualResult).getEmbeddedDouble(); 165 | assertEquals(expected, actual, 1e-15); 166 | return; 167 | } 168 | 169 | if (resultType == SClass.class) { 170 | String expected = (String) expectedResult; 171 | String actual = ((SClass) actualResult).getName().getEmbeddedString(); 172 | assertEquals(expected, actual); 173 | return; 174 | } 175 | 176 | if (resultType == SClass.class) { 177 | String expected = (String) expectedResult; 178 | String actual = ((SClass) actualResult).getName().getEmbeddedString(); 179 | assertEquals(expected, actual); 180 | return; 181 | } 182 | 183 | if (resultType == SSymbol.class) { 184 | String expected = (String) expectedResult; 185 | String actual = ((SSymbol) actualResult).getEmbeddedString(); 186 | assertEquals(expected, actual); 187 | return; 188 | } 189 | fail("SOM Value handler missing for " + resultType); 190 | } 191 | 192 | @Test 193 | public void testBasicInterpreterBehavior() throws ProgramDefinitionError { 194 | Universe u = new Universe(true); 195 | u.setupClassPath("Smalltalk:TestSuite/BasicInterpreterTests"); 196 | 197 | try { 198 | Object actualResult = u.interpret(testClass, testSelector); 199 | assertExpectedEqualsSOMValue(actualResult); 200 | } catch (ProgramDefinitionError e) { 201 | if (resultType != ProgramDefinitionError.class) { 202 | throw e; 203 | } 204 | } 205 | } 206 | } 207 | -------------------------------------------------------------------------------- /tests/som/tests/SomTests.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2013 Stefan Marr, stefan.marr@vub.ac.be 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE. 21 | */ 22 | package som.tests; 23 | 24 | import static org.junit.Assert.assertEquals; 25 | 26 | import java.util.Arrays; 27 | 28 | import org.junit.Test; 29 | import org.junit.runner.RunWith; 30 | import org.junit.runners.Parameterized; 31 | import org.junit.runners.Parameterized.Parameters; 32 | 33 | import som.compiler.ProgramDefinitionError; 34 | import som.vm.Universe; 35 | 36 | 37 | @RunWith(Parameterized.class) 38 | public class SomTests { 39 | 40 | @Parameters(name = "{0} [{index}]") 41 | public static Iterable data() { 42 | return Arrays.asList(new Object[][] { 43 | {"Array"}, 44 | {"Block"}, 45 | {"ClassLoading"}, 46 | {"ClassStructure"}, 47 | 48 | {"Closure"}, 49 | {"Coercion"}, 50 | {"CompilerReturn"}, 51 | {"DoesNotUnderstand"}, 52 | {"Double"}, 53 | 54 | {"Empty"}, 55 | {"Global"}, 56 | {"Hash"}, 57 | {"Integer"}, 58 | 59 | {"Preliminary"}, 60 | {"Reflection"}, 61 | {"SelfBlock"}, 62 | {"SpecialSelectorsTest"}, 63 | {"Super"}, 64 | 65 | {"Set"}, 66 | {"String"}, 67 | {"Symbol"}, 68 | {"System"}, 69 | {"Vector"} 70 | }); 71 | } 72 | 73 | private final String testName; 74 | 75 | public SomTests(final String testName) { 76 | this.testName = testName; 77 | } 78 | 79 | @Test 80 | public void testSomeTest() throws ProgramDefinitionError { 81 | String[] args = {"-cp", "Smalltalk", "TestSuite/TestHarness.som", testName}; 82 | 83 | // Create Universe 84 | Universe u = new Universe(true); 85 | 86 | // Start interpretation 87 | u.interpret(args); 88 | 89 | assertEquals(0, u.lastExitCode()); 90 | } 91 | 92 | } 93 | --------------------------------------------------------------------------------