├── .gitignore ├── CHANGELOG.md ├── Documentation ├── ForeignFunctionInterface.md ├── ProjectStructure.md └── ReadMe.md ├── Extension ├── .vscode │ └── launch.json ├── .vscodeignore ├── CHANGELOG.md ├── Deploy.cmd ├── README.md ├── Smalltalk.code-workspace ├── icons │ ├── file_type_smalltalk.png │ └── file_type_smalltalk.svg ├── info │ ├── dark_defaults.json │ ├── dark_plus.json │ └── dark_vs.json ├── language-configuration.json ├── package.json ├── syntaxes │ └── smalltalk.tmLanguage.json ├── test │ ├── ColorEditor.st │ └── Test.st └── vsc-extension-quickstart.md ├── GuiDesign ├── .idea │ ├── .gitignore │ ├── misc.xml │ ├── modules.xml │ ├── uiDesigner.xml │ └── vcs.xml ├── GuiDesign.iml ├── ReadMe.md ├── out │ └── production │ │ ├── Design │ │ └── SmallJIcon.png │ │ └── GuiDesign │ │ └── SmallJIcon.png ├── resources │ └── SmallJIcon.png └── src │ ├── ColorEditor.form │ ├── ColorEditor.java │ ├── Debugger.form │ ├── Debugger.java │ ├── EventBrokerNew.java │ ├── ImageEditor.form │ ├── ImageEditor.java │ ├── Inspector.form │ ├── Inspector.java │ ├── SystemBrowser.form │ └── SystemBrowser.java ├── LICENSE ├── README.md ├── SmallJ.code-workspace ├── Smalltalk ├── Base │ ├── Block.st │ ├── Boolean.st │ ├── Class.st │ ├── Context.st │ ├── False.st │ ├── Method.st │ ├── Object.st │ ├── True.st │ └── Undefined.st ├── Collection │ ├── Array.st │ ├── ByteArray.st │ ├── Collection.st │ ├── Indexed.st │ ├── Interval.st │ ├── List.st │ ├── Ordered.st │ └── String.st ├── Compiler │ ├── ArgumentNode.st │ ├── AssignNode.st │ ├── BlockNode.st │ ├── BodyNode.st │ ├── ClassParser.st │ ├── ClassVarNode.st │ ├── Encoder.st │ ├── InstNode.st │ ├── LiteralNode.st │ ├── MessageNode.st │ ├── Parser.st │ ├── ParserNode.st │ ├── PrimitiveNode.st │ ├── ReturnNode.st │ └── TemporaryNode.st ├── Component │ ├── Border.st │ ├── BorderLayout.st │ ├── Button.st │ ├── Color.st │ ├── Component.st │ ├── Font.st │ ├── Frame.st │ ├── GridBagConstraints.st │ ├── GridBagLayout.st │ ├── GridLayout.st │ ├── Image.st │ ├── Insets.st │ ├── JPoint.st │ ├── Label.st │ ├── ListComponent.st │ ├── Menu.st │ ├── MenuBar.st │ ├── Panel.st │ ├── Rectangle.st │ ├── ScrollBar.st │ ├── ScrollPane.st │ ├── SplitPane.st │ ├── TabbedPane.st │ ├── Table.st │ ├── TableModel.st │ ├── TextArea.st │ ├── TextComponent.st │ ├── TextField.st │ └── Viewport.st ├── Event │ ├── ActionEvent.st │ ├── AdjustmentEvent.st │ ├── JavaEvent.st │ ├── ListSelectionEvent.st │ ├── MouseEvent.st │ └── WindowEvent.st ├── Gui │ ├── ColorEditor.st │ ├── Debugger.st │ ├── FileChooser.st │ ├── ImageEditor.st │ ├── Inspector.st │ ├── InspectorTab.st │ ├── OptionPane.st │ └── SystemBrowser.st ├── Io │ ├── File.st │ ├── PrintStream.st │ └── System.st ├── Java │ ├── JavaArray.st │ ├── JavaObject.st │ ├── JavaVector.st │ └── Semaphore.st ├── Magnitude │ ├── Char.st │ ├── Float.st │ ├── Fraction.st │ ├── Integer.st │ ├── LargeNegative.st │ ├── LargePositive.st │ ├── Magnitude.st │ ├── Number.st │ ├── Point.st │ ├── SmallInt.st │ └── SmallLong.st ├── SmallJ.cmd ├── SmallJ.code-workspace ├── SmallJ.jar ├── SmallJ.png └── image.sjim └── VM ├── .vscode ├── launch.json ├── settings.json └── tasks.json ├── lib ├── commons-beanutils-1.9.4.jar ├── commons-lang3-3.12.0.jar └── commons-logging-1.2.jar ├── src ├── META-INF │ └── MANIFEST.MF └── smallj │ └── core │ ├── JavaArgs.java │ ├── MethodCache.java │ ├── SmallBlock.java │ ├── SmallByteArray.java │ ├── SmallClass.java │ ├── SmallContext.java │ ├── SmallException.java │ ├── SmallFloat.java │ ├── SmallImage.java │ ├── SmallImageReader.java │ ├── SmallImageWriter.java │ ├── SmallInt.java │ ├── SmallInterpreter.java │ ├── SmallJApp.java │ ├── SmallJavaObject.java │ ├── SmallLong.java │ ├── SmallObject.java │ └── SmallThread.java └── workspace.code-workspace /.gitignore: -------------------------------------------------------------------------------- 1 | # For now: Smallj.org Website 2 | Website/ 3 | 4 | # For now: Smalltalk Test folder, contains only scratch files 5 | Smalltalk/Test 6 | 7 | # Windows shortcuts, copies, scripts. 8 | *.lnk 9 | * - Copy* 10 | *.ps1 11 | 12 | # Compiled class files 13 | *.class 14 | 15 | # Log files 16 | *.log 17 | 18 | # BlueJ files 19 | *.ctxt 20 | 21 | # Mobile Tools for Java (J2ME) 22 | .mtj.tmp/ 23 | 24 | # Personal messages 25 | Feedback/ 26 | 27 | # Package Files # 28 | # We need these: *.jar 29 | *.war 30 | *.nar 31 | *.ear 32 | *.zip 33 | *.tar.gz 34 | *.rar 35 | 36 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 37 | hs_err_pid* 38 | -------------------------------------------------------------------------------- /Documentation/ForeignFunctionInterface.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Foreign Function Interface (FFI) to Java 4 | SmallJ has as a set of primitives dedicated for acessing Java laguage items 5 | classes, methods and field dynamiclly, so called at runtime by name. 6 | Return values of the FFI calls can be associated with a Smalltalk object, 7 | or nil is specifield if return type is void or the value is to be ignored. 8 | 9 | ## Basic FFI primitives 10 | 11 | #37 - javaObjectNew 12 | Propose: Invoke class contructor. 13 | Syntax: < 37 smalltalkClass javaClassName [ arg1 arg2 ... ] > 14 | Example: < 37 Color 'java.awt.Color' red green blue > 15 | 16 | #38 - javaObjectInvokeMethod 17 | Propose: Invoke method on object. 18 | Syntax: < 38 returnClass smallJavaObject javaMethodName [ arg1 arg2 ... ] > 19 | Example: < 38 String aTextComponent 'getText' > 20 | 21 | #39 - javaClassInvokeStaticMethod 22 | Propose: Invoke static method on class. 23 | Syntax: < 39 returnClass javaClassName javaMethodName [ arg1 arg2 ... ] > 24 | Example: < 39 Float 'java.lang.Math' 'sqrt' anInteger >. 25 | 26 | ## Smalltalk <-> Java type conversion 27 | Smalltalk arguments to these function calls are converted to java types as follows: 28 | 29 | SmallTalk -> Java 30 | ================== 31 | nil -> null 32 | true -> True / true 33 | false -> False / false 34 | SmallInt -> Integer / int 35 | String -> String 36 | Float -> Double / double 37 | -> Object. 38 | 39 | For converting Java return types back to Smalltalk, the conversions are reversed. 40 | 41 | ## FFI primitives with typed arguments 42 | 43 | Sometimes it is necessary to 'cast' Java arguments to specific types 44 | to match it to match the arguments of a specific (overloaded) function. 45 | For this reason there the primitives 37, 38 and 39 also have a typed version. 46 | Then each argument is preceded by the desired (cast) type of the argument. 47 | These are: 48 | 49 | #43 - javaObjectNewTyped 50 | Syntax: < 43 smalltalkClass javaClassName [ argType1 argValue1 argType2 argValue2 ... ] > 51 | Example: < todo > 52 | 53 | #44 - javaObjectInvokeMethodTyped 54 | Syntax: < 44 returnClass smallJavaObject javaMethodName [ argType1 argValue1 argType2 argValue2 ... ] > 55 | Example: < todo > 56 | 57 | #45 - javaClassInvokeStaticMethodTyped 58 | Syntax: < 45 returnClass javaClassName javaMethodName [ argType1 argValue1 argType2 argValue2 ... ] > 59 | Example: < 45 String 'javax.swing.JOptionPane' 'showMessageDialog' 'java.awt.Component' nil 'java.lang.String' message > 60 | 61 | The smalltalk class JavaArray can be used to pass an array of objects to a Java function, 62 | as it implements the Java class 'java.lang.reflect.Array'. 63 | Example: < 38 nil aListComponent 'setListData' ( JavaArray fromArray: listData ) > 64 | 65 | ## Accessing field variables 66 | 67 | There are also primitives for accessing fields (variables) in classes and objects: 68 | 69 | #40 - javaObjectReadField 70 | Propose: Read a field (variable) from an object. 71 | Syntax: < 40 returnClass javaObject javaFieldName > 72 | Example: < todo > 73 | 74 | #41 - javaClassReadStaticField 75 | Propose: Read a static field (variable) from a class. 76 | Syntax: < 41 returnClass javaClassName javaFieldName > 77 | Example: < 41 JavaObject 'java.lang.System' 'in' > 78 | 79 | ## Loading a Java class 80 | 81 | And finally, if you need to acces a Java class as an oject, you can use this primtive: 82 | 83 | #46 - javaLoadClass 84 | Syntax: < 46 returnClass javaClassName > 85 | Example: javaObjectClass := < 46 JavaObject 'java.lang.Object' >. 86 | 87 | ## Final thoughts 88 | 89 | Of course, these primitives are not very type safe and it is easy to make mistakes in their syntax, 90 | that will cause exception errors in the VM. 91 | That's why it is recommended to only implement every Java FFI call *only once*, 92 | in a Smalltalk method that matches the Java function name, 93 | that is a class that matches the Java class name. 94 | After that, you can safely use the Smalltalk method and forget about the primitive. 95 | -------------------------------------------------------------------------------- /Documentation/ProjectStructure.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Project Structure 4 | 5 | The SmallJ repostiory consists of the following folders: 6 | 7 | ## ./ (root folder) 8 | Contains the usual Git stuff like readme, changelog, license and gitignore. 9 | It also contains the file: SmallJ.code-workspace. 10 | This is the main project file for Visual Studio Code (VSCode). 11 | It's most convenient to associate VSCode startup with this extension. 12 | Starting Run or Debug starts the SmallJ VM, see below. 13 | 14 | ## [Documentation](/../README.md) 15 | This documentation. All files should be reachable through the index in ReadMe.md. 16 | 17 | ## [GuiDesign](../GuiDesign/README.md) 18 | Some Java mock-up programs for the various GUIs implemented in SmallJ. 19 | The programs are in an IntelliJ project and use its forms designer for WYSIWIG GUI editing. 20 | The gererated Java code can then be used as a base for creating the Smalltalk code. 21 | 22 | ## [Smalltalk](../Smalltalk) 23 | The Smalltalk development enviroment. 24 | VSCode is not needed to run SmallJ, allthough it is recommended for code editing. 25 | Important files are: 26 | - SmallJ.cmd - Starts up the SmallJ system, opening the SystemBrowser. 27 | - SmallJ.jar - Compiled Java code for the SmallJ VM. 28 | - SmallJ.sjim - Default Smalltalk image file containing the compiled Smalltalk code. 29 | When exiting SmallJ this file is overwritten. 30 | Make regular backups in case something gets broken and the system won't start anymore. 31 | 32 | ## [VM](../VM) 33 | The SmallJ VM written in Java. 34 | Use the VSCode SmallJ.code-workspace in the root folder to Run or Debug it. 35 | After the VM is altered, a new ../Smalltalk/SmallJ.jar file should be generated 36 | using the VSCode "Export JAR" function. 37 | (This process should be automated, but there does not seem te be a convenient way without having to resort to using to Maven.) 38 | 39 | ## [VSCode](../VSCode/README.md) 40 | Contains an extension for VSCode for Smalltalk syntax highlighting, that should be installed locally. It's recommended to do Smalltalk development in VSCode and only use the SmallJ SystemBrowser for compilation, testing and small code edits. 41 | 42 | 43 | ## [Website](../Website/Deploy/index.html) 44 | Contains the source of the very simple website running at https://smallj.org. 45 | This folder has purposely not been put on GitHub yet. 46 | Let's make it a more serious site first. 47 | -------------------------------------------------------------------------------- /Documentation/ReadMe.md: -------------------------------------------------------------------------------- 1 | # Documentation ReadMe 2 | This folder contains the SmallJ documentation. 3 | 4 | # Contents 5 | 6 | # [Foreign Function Interface (FFI) to Java](ForeignFunctionInterface.md) 7 | Describes how to add new functions from the Java framework to SmallJ 8 | by invoking the FFI primitives. 9 | 10 | # [Project structure](ProjectStructure.md) 11 | Describes use of the folders in SmallJ and how start run or debug software in them. 12 | -------------------------------------------------------------------------------- /Extension/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | // A launch configuration that launches the extension inside a new window 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | { 6 | "version": "0.2.0", 7 | "configurations": [ 8 | { 9 | "name": "Extension", 10 | "type": "extensionHost", 11 | "request": "launch", 12 | "runtimeExecutable": "${execPath}", 13 | "args": [ 14 | "--extensionDevelopmentPath=${workspaceFolder}" 15 | ] 16 | } 17 | ] 18 | } -------------------------------------------------------------------------------- /Extension/.vscodeignore: -------------------------------------------------------------------------------- 1 | .vscode/** 2 | .vscode-test/** 3 | .gitignore 4 | vsc-extension-quickstart.md 5 | -------------------------------------------------------------------------------- /Extension/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | All notable changes to the "smalltalk" extension will be documented in this file. 4 | 5 | Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how to structure this file. 6 | 7 | ## [Unreleased] 8 | 9 | - Initial release -------------------------------------------------------------------------------- /Extension/Deploy.cmd: -------------------------------------------------------------------------------- 1 | rem Copies this extension to VSCode extensions folder, where it is automatically used. 2 | set dest="%UserProfile%\.vscode\extensions\mysmalltalk" 3 | md %dest% 4 | xcopy /y /s /h . %dest% 5 | pause 6 | -------------------------------------------------------------------------------- /Extension/README.md: -------------------------------------------------------------------------------- 1 | # smalltalk README 2 | 3 | This is the README for your extension "smalltalk". After writing up a brief description, we recommend including the following sections. 4 | 5 | ## Features 6 | 7 | Describe specific features of your extension including screenshots of your extension in action. Image paths are relative to this README file. 8 | 9 | For example if there is an image subfolder under your extension project workspace: 10 | 11 | \!\[feature X\]\(images/feature-x.png\) 12 | 13 | > Tip: Many popular extensions utilize animations. This is an excellent way to show off your extension! We recommend short, focused animations that are easy to follow. 14 | 15 | ## Requirements 16 | 17 | If you have any requirements or dependencies, add a section describing those and how to install and configure them. 18 | 19 | ## Extension Settings 20 | 21 | Include if your extension adds any VS Code settings through the `contributes.configuration` extension point. 22 | 23 | For example: 24 | 25 | This extension contributes the following settings: 26 | 27 | * `myExtension.enable`: enable/disable this extension 28 | * `myExtension.thing`: set to `blah` to do something 29 | 30 | ## Known Issues 31 | 32 | Calling out known issues can help limit users opening duplicate issues against your extension. 33 | 34 | ## Release Notes 35 | 36 | Users appreciate release notes as you update your extension. 37 | 38 | ### 1.0.0 39 | 40 | Initial release of ... 41 | 42 | ### 1.0.1 43 | 44 | Fixed issue #. 45 | 46 | ### 1.1.0 47 | 48 | Added features X, Y, and Z. 49 | 50 | ----------------------------------------------------------------------------------------------------------- 51 | 52 | ## Working with Markdown 53 | 54 | **Note:** You can author your README using Visual Studio Code. Here are some useful editor keyboard shortcuts: 55 | 56 | * Split the editor (`Cmd+\` on macOS or `Ctrl+\` on Windows and Linux) 57 | * Toggle preview (`Shift+CMD+V` on macOS or `Shift+Ctrl+V` on Windows and Linux) 58 | * Press `Ctrl+Space` (Windows, Linux) or `Cmd+Space` (macOS) to see a list of Markdown snippets 59 | 60 | ### For more information 61 | 62 | * [Visual Studio Code's Markdown Support](http://code.visualstudio.com/docs/languages/markdown) 63 | * [Markdown Syntax Reference](https://help.github.com/articles/markdown-basics/) 64 | 65 | **Enjoy!** 66 | -------------------------------------------------------------------------------- /Extension/Smalltalk.code-workspace: -------------------------------------------------------------------------------- 1 | { 2 | "folders": [ 3 | { 4 | "path": "." 5 | } 6 | ], 7 | "settings": {} 8 | } -------------------------------------------------------------------------------- /Extension/icons/file_type_smalltalk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smalljvm/SmallJ/430990e4dd143db15fd78063258000bfe38c9b9c/Extension/icons/file_type_smalltalk.png -------------------------------------------------------------------------------- /Extension/info/dark_defaults.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "vscode://schemas/color-theme", 3 | "name": "Dark Default Colors", 4 | "colors": { 5 | "editor.background": "#1E1E1E", 6 | "editor.foreground": "#D4D4D4", 7 | "editor.inactiveSelectionBackground": "#3A3D41", 8 | "editorIndentGuide.background": "#404040", 9 | "editorIndentGuide.activeBackground": "#707070", 10 | "editor.selectionHighlightBackground": "#ADD6FF26", 11 | "list.dropBackground": "#383B3D", 12 | "activityBarBadge.background": "#007ACC", 13 | "sideBarTitle.foreground": "#BBBBBB", 14 | "input.placeholderForeground": "#A6A6A6", 15 | "settings.textInputBackground": "#292929", 16 | "settings.numberInputBackground": "#292929", 17 | "menu.background": "#252526", 18 | "menu.foreground": "#CCCCCC", 19 | "statusBarItem.remoteForeground": "#FFF", 20 | "statusBarItem.remoteBackground": "#16825D", 21 | "sideBarSectionHeader.background": "#0000", 22 | "sideBarSectionHeader.border": "#ccc3" 23 | }, 24 | "semanticHighlighting": true 25 | } 26 | -------------------------------------------------------------------------------- /Extension/info/dark_plus.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "vscode://schemas/color-theme", 3 | "name": "Dark+ (default dark)", 4 | "include": "./dark_vs.json", 5 | "tokenColors": [ 6 | { 7 | "name": "Function declarations", 8 | "scope": [ 9 | "entity.name.function", 10 | "support.function", 11 | "support.constant.handlebars", 12 | "source.powershell variable.other.member", 13 | "entity.name.operator.custom-literal" // See https://en.cppreference.com/w/cpp/language/user_literal 14 | ], 15 | "settings": { 16 | "foreground": "#DCDCAA" 17 | } 18 | }, 19 | { 20 | "name": "Types declaration and references", 21 | "scope": [ 22 | "meta.return-type", 23 | "support.class", 24 | "support.type", 25 | "entity.name.type", 26 | "entity.name.namespace", 27 | "entity.other.attribute", 28 | "entity.name.scope-resolution", 29 | "entity.name.class", 30 | "storage.type.numeric.go", 31 | "storage.type.byte.go", 32 | "storage.type.boolean.go", 33 | "storage.type.string.go", 34 | "storage.type.uintptr.go", 35 | "storage.type.error.go", 36 | "storage.type.rune.go", 37 | "storage.type.cs", 38 | "storage.type.generic.cs", 39 | "storage.type.modifier.cs", 40 | "storage.type.variable.cs", 41 | "storage.type.annotation.java", 42 | "storage.type.generic.java", 43 | "storage.type.java", 44 | "storage.type.object.array.java", 45 | "storage.type.primitive.array.java", 46 | "storage.type.primitive.java", 47 | "storage.type.token.java", 48 | "storage.type.groovy", 49 | "storage.type.annotation.groovy", 50 | "storage.type.parameters.groovy", 51 | "storage.type.generic.groovy", 52 | "storage.type.object.array.groovy", 53 | "storage.type.primitive.array.groovy", 54 | "storage.type.primitive.groovy" 55 | ], 56 | "settings": { 57 | "foreground": "#4EC9B0" 58 | } 59 | }, 60 | { 61 | "name": "Types declaration and references, TS grammar specific", 62 | "scope": [ 63 | "meta.type.cast.expr", 64 | "meta.type.new.expr", 65 | "support.constant.math", 66 | "support.constant.dom", 67 | "support.constant.json", 68 | "entity.other.inherited-class" 69 | ], 70 | "settings": { 71 | "foreground": "#4EC9B0" 72 | } 73 | }, 74 | { 75 | "name": "Control flow / Special keywords", 76 | "scope": [ 77 | "keyword.control", 78 | "source.cpp keyword.operator.new", 79 | "keyword.operator.delete", 80 | "keyword.other.using", 81 | "keyword.other.operator", 82 | "entity.name.operator" 83 | ], 84 | "settings": { 85 | "foreground": "#C586C0" 86 | } 87 | }, 88 | { 89 | "name": "Variable and parameter name", 90 | "scope": [ 91 | "variable", 92 | "meta.definition.variable.name", 93 | "support.variable", 94 | "entity.name.variable" 95 | ], 96 | "settings": { 97 | "foreground": "#9CDCFE" 98 | } 99 | }, 100 | { 101 | "name": "Constants and enums", 102 | "scope": [ 103 | "variable.other.constant", 104 | "variable.other.enummember" 105 | ], 106 | "settings": { 107 | "foreground": "#51B6C4", 108 | } 109 | }, 110 | { 111 | "name": "Object keys, TS grammar specific", 112 | "scope": [ 113 | "meta.object-literal.key" 114 | ], 115 | "settings": { 116 | "foreground": "#9CDCFE" 117 | } 118 | }, 119 | { 120 | "name": "CSS property value", 121 | "scope": [ 122 | "support.constant.property-value", 123 | "support.constant.font-name", 124 | "support.constant.media-type", 125 | "support.constant.media", 126 | "constant.other.color.rgb-value", 127 | "constant.other.rgb-value", 128 | "support.constant.color" 129 | ], 130 | "settings": { 131 | "foreground": "#CE9178" 132 | } 133 | }, 134 | { 135 | "name": "Regular expression groups", 136 | "scope": [ 137 | "punctuation.definition.group.regexp", 138 | "punctuation.definition.group.assertion.regexp", 139 | "punctuation.definition.character-class.regexp", 140 | "punctuation.character.set.begin.regexp", 141 | "punctuation.character.set.end.regexp", 142 | "keyword.operator.negation.regexp", 143 | "support.other.parenthesis.regexp" 144 | ], 145 | "settings": { 146 | "foreground": "#CE9178" 147 | } 148 | }, 149 | { 150 | "scope": [ 151 | "constant.character.character-class.regexp", 152 | "constant.other.character-class.set.regexp", 153 | "constant.other.character-class.regexp", 154 | "constant.character.set.regexp" 155 | ], 156 | "settings": { 157 | "foreground": "#d16969" 158 | } 159 | }, 160 | { 161 | "scope": [ 162 | "keyword.operator.or.regexp", 163 | "keyword.control.anchor.regexp" 164 | ], 165 | "settings": { 166 | "foreground": "#DCDCAA" 167 | } 168 | }, 169 | { 170 | "scope": "keyword.operator.quantifier.regexp", 171 | "settings": { 172 | "foreground": "#d7ba7d" 173 | } 174 | }, 175 | { 176 | "scope": "constant.character", 177 | "settings": { 178 | "foreground": "#569cd6" 179 | } 180 | }, 181 | { 182 | "scope": "constant.character.escape", 183 | "settings": { 184 | "foreground": "#d7ba7d" 185 | } 186 | }, 187 | { 188 | "scope": "entity.name.label", 189 | "settings": { 190 | "foreground": "#C8C8C8" 191 | } 192 | } 193 | ] 194 | } 195 | -------------------------------------------------------------------------------- /Extension/language-configuration.json: -------------------------------------------------------------------------------- 1 | { 2 | "comments": { 3 | // symbol used for single line comment. Remove this entry if your language does not support line comments 4 | "lineComment": "//", 5 | // symbols used for start and end a block comment. Remove this entry if your language does not support block comments 6 | "blockComment": [ "/*", "*/" ] 7 | }, 8 | // symbols used as brackets 9 | "brackets": [ 10 | ["{", "}"], 11 | ["[", "]"], 12 | ["(", ")"] 13 | ], 14 | // symbols that are auto closed when typing 15 | "autoClosingPairs": [ 16 | ["{", "}"], 17 | ["[", "]"], 18 | ["(", ")"], 19 | ["\"", "\""], 20 | ["'", "'"] 21 | ], 22 | // symbols that can be used to surround a selection 23 | "surroundingPairs": [ 24 | ["{", "}"], 25 | ["[", "]"], 26 | ["(", ")"], 27 | ["\"", "\""], 28 | ["'", "'"] 29 | ] 30 | } -------------------------------------------------------------------------------- /Extension/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "smalltalk", 3 | "displayName": "Smalltalk", 4 | "description": "Smalltalk", 5 | "version": "0.0.1", 6 | "engines": { 7 | "vscode": "^1.45.0" 8 | }, 9 | "categories": [ 10 | "Programming Languages" 11 | ], 12 | "contributes": { 13 | "languages": [{ 14 | "id": "smalltalk", 15 | "aliases": ["Smalltalk", "smalltalk"], 16 | "extensions": [".st"], 17 | "configuration": "./language-configuration.json" 18 | }], 19 | "grammars": [{ 20 | "language": "smalltalk", 21 | "scopeName": "source.smalltalk", 22 | "path": "./syntaxes/smalltalk.tmLanguage.json" 23 | }] 24 | } 25 | } -------------------------------------------------------------------------------- /Extension/syntaxes/smalltalk.tmLanguage.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json", 3 | "name": "Smalltalk", 4 | "patterns": [ 5 | { "include": "#strings" }, 6 | { "include": "#constants" }, 7 | { "include": "#keywords" }, 8 | { "include": "#classes" }, 9 | { "include": "#methods" }, 10 | { "include": "#comments" } 11 | ], 12 | "repository": { 13 | "constants": { 14 | "patterns": [ 15 | { "name": "constant.character.smalltalk", 16 | "match": "[$]." 17 | }, 18 | { "name": "constant.numeric.smalltalk", 19 | "match": "[.]*\\b[0-9]+\\b" 20 | } 21 | ] 22 | }, 23 | "strings": { 24 | "name": "string.quoted.single.smalltalk", 25 | "begin": "'", 26 | "end": "'" 27 | }, 28 | "keywords": { 29 | "patterns": [ 30 | { "name": "keyword.control.smalltalk", 31 | "match": "\\b(self|super|nil|true|false|CLASS|META|METHOD)\\b" 32 | } 33 | ] 34 | }, 35 | "classes": { 36 | "patterns": [ 37 | { "name": "entity.name.class.smalltalk", 38 | "match": "\\b[A-Z][A-Za-z0-9]*\\b" 39 | } 40 | ] 41 | }, 42 | "methods": { 43 | "patterns": [ 44 | { "name": "entity.name.function.smalltalk", 45 | "match": "\\b[A-Za-z0-9]+\\b:" 46 | } 47 | ] 48 | }, 49 | "comments": { 50 | "name": "comment.smalltalk", 51 | "begin": "\"", 52 | "end": "\"" 53 | } 54 | }, 55 | "scopeName": "source.smalltalk" 56 | } -------------------------------------------------------------------------------- /Extension/test/ColorEditor.st: -------------------------------------------------------------------------------- 1 | 3.14159256 2 | $ 3 | $' 4 | : 5 | EVAL Class addNewClass: ( Object subclass: 'ColorEditor' variables: 'color frame framePanel image imagePanel text textPanel scrollBarsPanel redScrollBar greenScrollBar blueScrollBar selectButton semaphore' classVariables: '') 6 | META Color 7 | edit: color 8 | ^ self new edit: color 9 | METHOD ColorEditor 10 | edit: aColor 11 | | scrollBarChangedBlock | 12 | "Display color selection window on argument. Answer selected new color." 13 | 14 | color := aColor. 15 | semaphore := Semaphore new. 16 | 17 | textPanel := TextField new. 18 | textPanel setText: color printString. 19 | 20 | image := Image size: 200 @ 200. 21 | image setColor: color. 22 | image at: 0 @ 0 fillRect: 200 @ 200. 23 | imagePanel := Label image: image. 24 | 25 | scrollBarChangedBlock := [ :unused | self scrollBarChanged ]. 26 | "ScrollBar max must also have room for the extent: 255 + 10. 27 | Otherwise scrollBar creation will fail in Java when the value is at max." 28 | redScrollBar := ScrollBar orientation: 1 value: color red extent: 10 min: 0 max: 265. 29 | redScrollBar onAdjust: scrollBarChangedBlock. 30 | greenScrollBar := ScrollBar orientation: 1 value: color green extent: 10 min: 0 max: 265. 31 | greenScrollBar onAdjust: scrollBarChangedBlock. 32 | blueScrollBar := ScrollBar orientation: 1 value: color blue extent: 10 min: 0 max: 265. 33 | blueScrollBar onAdjust: scrollBarChangedBlock. 34 | scrollBarsPanel := ( GridPanel rows: 1 columns: 3 ) addAll: #( redScrollBar greenScrollBar blueScrollBar ). 35 | 36 | selectButton := Button text: 'Select' action: [ self select ]. 37 | 38 | framePanel := BorderPanel new north: textPanel south: selectButton east: nil west: scrollBarsPanel center: imagePanel. 39 | frame := Frame new title: 'Color Editor'. 40 | frame setSize: 300 @ 250. 41 | frame add: framePanel. 42 | frame show. 43 | 44 | ^ semaphore wait. 45 | ! 46 | METHOD Color 47 | scrollBarChanged 48 | color := Color red: redScrollBar getValue green: greenScrollBar getValue blue: blueScrollBar getValue. 49 | image setColor: color. 50 | image at: 0 @ 0 fillRect: 200 @ 200. 51 | textPanel setText: color printString. 52 | frame repaint. 53 | ! 54 | METHOD Color 55 | select 56 | "Close frame and return selected color via semaphore." 57 | frame close. 58 | semaphore set: color. 59 | ! 60 | -------------------------------------------------------------------------------- /Extension/test/Test.st: -------------------------------------------------------------------------------- 1 | if { a } then ( b ) else [ c ] 2 | // sdsdsd 3 | 4 | // Comment 5 | 6 | /* sdsd */ 7 | 8 | // Test 9 | -------------------------------------------------------------------------------- /Extension/vsc-extension-quickstart.md: -------------------------------------------------------------------------------- 1 | # Welcome to your VS Code Extension 2 | 3 | ## What's in the folder 4 | 5 | * This folder contains all of the files necessary for your extension. 6 | * `package.json` - this is the manifest file in which you declare your language support and define the location of the grammar file that has been copied into your extension. 7 | * `syntaxes/smalltalk.tmLanguage.json` - this is the Text mate grammar file that is used for tokenization. 8 | * `language-configuration.json` - this is the language configuration, defining the tokens that are used for comments and brackets. 9 | 10 | ## Get up and running straight away 11 | 12 | * Make sure the language configuration settings in `language-configuration.json` are accurate. 13 | * Press `F5` to open a new window with your extension loaded. 14 | * Create a new file with a file name suffix matching your language. 15 | * Verify that syntax highlighting works and that the language configuration settings are working. 16 | 17 | ## Make changes 18 | 19 | * You can relaunch the extension from the debug toolbar after making changes to the files listed above. 20 | * You can also reload (`Ctrl+R` or `Cmd+R` on Mac) the VS Code window with your extension to load your changes. 21 | 22 | ## Add more language features 23 | 24 | * To add features such as intellisense, hovers and validators check out the VS Code extenders documentation at https://code.visualstudio.com/docs 25 | 26 | ## Install your extension 27 | 28 | * To start using your extension with Visual Studio Code copy it into the `/.vscode/extensions` folder and restart Code. 29 | * To share your extension with the world, read on https://code.visualstudio.com/docs about publishing an extension. 30 | -------------------------------------------------------------------------------- /GuiDesign/.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | -------------------------------------------------------------------------------- /GuiDesign/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /GuiDesign/.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /GuiDesign/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /GuiDesign/GuiDesign.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /GuiDesign/ReadMe.md: -------------------------------------------------------------------------------- 1 | # GuiDesign ReadMe 2 | This IntelliJ project is for convenient designing and testing of Smalltalk GUIs 3 | before coding them in Smalltalk. 4 | So the executable created here is a dummy and not needed to run SmallJ. 5 | If you change a GUI in Smalltalk, please also update its design here. 6 | 7 | Note: 8 | This project should only use components that are standard in the Java framework. 9 | So not IntelliJ specific components like GridLayoutManager. -------------------------------------------------------------------------------- /GuiDesign/out/production/Design/SmallJIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smalljvm/SmallJ/430990e4dd143db15fd78063258000bfe38c9b9c/GuiDesign/out/production/Design/SmallJIcon.png -------------------------------------------------------------------------------- /GuiDesign/out/production/GuiDesign/SmallJIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smalljvm/SmallJ/430990e4dd143db15fd78063258000bfe38c9b9c/GuiDesign/out/production/GuiDesign/SmallJIcon.png -------------------------------------------------------------------------------- /GuiDesign/resources/SmallJIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smalljvm/SmallJ/430990e4dd143db15fd78063258000bfe38c9b9c/GuiDesign/resources/SmallJIcon.png -------------------------------------------------------------------------------- /GuiDesign/src/ColorEditor.form: -------------------------------------------------------------------------------- 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 | 61 | 62 | 63 | 64 | 65 | 66 | 67 |
68 | -------------------------------------------------------------------------------- /GuiDesign/src/ColorEditor.java: -------------------------------------------------------------------------------- 1 | import javax.swing.*; 2 | import java.awt.*; 3 | 4 | public class ColorEditor 5 | { 6 | public static void main( String[] args ) 7 | { 8 | new ColorEditor().show(); 9 | } 10 | 11 | void show() 12 | { 13 | frame = new JFrame( "Color Editor" ); 14 | frame.setContentPane( framePanel ); 15 | ImageIcon icon = new ImageIcon( getClass().getResource( "/SmallJIcon.png" ) ); 16 | frame.setIconImage( icon.getImage() ); 17 | frame.pack(); 18 | frame.setLocationRelativeTo( null ); 19 | frame.setVisible( true ); 20 | } 21 | 22 | JFrame frame; 23 | JPanel framePanel; 24 | JTextField textField; 25 | JButton selectButton; 26 | JLabel imageLabel; 27 | JScrollBar redScrollBar; 28 | JScrollBar greenScrollBar; 29 | JScrollBar blueScrollBar; 30 | JPanel scrollBarsPane; 31 | 32 | { 33 | // GUI initializer generated by IntelliJ IDEA GUI Designer 34 | // >>> IMPORTANT!! <<< 35 | // DO NOT EDIT OR ADD ANY CODE HERE! 36 | $$$setupUI$$$(); 37 | } 38 | 39 | /** 40 | * Method generated by IntelliJ IDEA GUI Designer 41 | * >>> IMPORTANT!! <<< 42 | * DO NOT edit this method OR call it in your code! 43 | * 44 | * @noinspection ALL 45 | */ 46 | private void $$$setupUI$$$() 47 | { 48 | framePanel = new JPanel(); 49 | framePanel.setLayout( new BorderLayout( 0, 0 ) ); 50 | textField = new JTextField(); 51 | textField.setText( "Color[ 0, 0, 200 ]" ); 52 | framePanel.add( textField, BorderLayout.NORTH ); 53 | selectButton = new JButton(); 54 | selectButton.setText( "Select" ); 55 | framePanel.add( selectButton, BorderLayout.SOUTH ); 56 | imageLabel = new JLabel(); 57 | imageLabel.setHorizontalAlignment( 0 ); 58 | imageLabel.setIcon( new ImageIcon( getClass().getResource( "/Blue.png" ) ) ); 59 | imageLabel.setText( "" ); 60 | framePanel.add( imageLabel, BorderLayout.CENTER ); 61 | scrollBarsPane = new JPanel(); 62 | scrollBarsPane.setLayout( new GridBagLayout() ); 63 | framePanel.add( scrollBarsPane, BorderLayout.WEST ); 64 | redScrollBar = new JScrollBar(); 65 | redScrollBar.setMaximum( 265 ); 66 | GridBagConstraints gbc; 67 | gbc = new GridBagConstraints(); 68 | gbc.gridx = 0; 69 | gbc.gridy = 0; 70 | gbc.weighty = 1.0; 71 | gbc.fill = GridBagConstraints.VERTICAL; 72 | scrollBarsPane.add( redScrollBar, gbc ); 73 | greenScrollBar = new JScrollBar(); 74 | greenScrollBar.setMaximum( 265 ); 75 | gbc = new GridBagConstraints(); 76 | gbc.gridx = 1; 77 | gbc.gridy = 0; 78 | gbc.weighty = 1.0; 79 | gbc.fill = GridBagConstraints.VERTICAL; 80 | scrollBarsPane.add( greenScrollBar, gbc ); 81 | blueScrollBar = new JScrollBar(); 82 | blueScrollBar.setMaximum( 265 ); 83 | blueScrollBar.setValue( 200 ); 84 | gbc = new GridBagConstraints(); 85 | gbc.gridx = 2; 86 | gbc.gridy = 0; 87 | gbc.weighty = 1.0; 88 | gbc.fill = GridBagConstraints.VERTICAL; 89 | scrollBarsPane.add( blueScrollBar, gbc ); 90 | } 91 | 92 | /** 93 | * @noinspection ALL 94 | */ 95 | public JComponent $$$getRootComponent$$$() 96 | { 97 | return framePanel; 98 | } 99 | 100 | } 101 | -------------------------------------------------------------------------------- /GuiDesign/src/Debugger.form: -------------------------------------------------------------------------------- 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 | 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 | -------------------------------------------------------------------------------- /GuiDesign/src/Debugger.java: -------------------------------------------------------------------------------- 1 | import javax.swing.*; 2 | import javax.swing.border.TitledBorder; 3 | import javax.swing.table.DefaultTableModel; 4 | import java.awt.*; 5 | import java.awt.event.MouseAdapter; 6 | import java.awt.event.MouseEvent; 7 | 8 | public class Debugger 9 | { 10 | public static void main( String[] args ) 11 | { 12 | new Debugger().show(); 13 | } 14 | 15 | void show() 16 | { 17 | frame = new JFrame( "Debugger" ); 18 | frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); 19 | frame.setContentPane( notNeeded ); 20 | ImageIcon icon = new ImageIcon( getClass().getResource( "/SmallJIcon.png" ) ); 21 | frame.setIconImage( icon.getImage() ); 22 | frame.pack(); 23 | frame.setLocationRelativeTo( null ); 24 | frame.setVisible( true ); 25 | } 26 | 27 | JFrame frame; 28 | JPanel notNeeded; 29 | JPanel errorPanel; 30 | JLabel errorLabel; 31 | JTextField errorTextField; 32 | JList contextList; 33 | private JTable argumentTable; 34 | private JScrollPane contextScrollPane; 35 | private JScrollPane argumentScrollPane; 36 | private JList argumentList; 37 | private JTabbedPane frameTabbedPane; 38 | private JPanel contextTab; 39 | private JPanel inspectorTab; 40 | 41 | { 42 | // GUI initializer generated by IntelliJ IDEA GUI Designer 43 | // >>> IMPORTANT!! <<< 44 | // DO NOT EDIT OR ADD ANY CODE HERE! 45 | $$$setupUI$$$(); 46 | } 47 | 48 | /** 49 | * Method generated by IntelliJ IDEA GUI Designer 50 | * >>> IMPORTANT!! <<< 51 | * DO NOT edit this method OR call it in your code! 52 | * 53 | * @noinspection ALL 54 | */ 55 | private void $$$setupUI$$$() 56 | { 57 | notNeeded = new JPanel(); 58 | notNeeded.setLayout( new BorderLayout( 0, 4 ) ); 59 | notNeeded.setBorder( BorderFactory.createTitledBorder( BorderFactory.createEmptyBorder( 4, 4, 4, 4 ), null, TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, null, null ) ); 60 | frameTabbedPane = new JTabbedPane(); 61 | notNeeded.add( frameTabbedPane, BorderLayout.CENTER ); 62 | contextTab = new JPanel(); 63 | contextTab.setLayout( new BorderLayout( 0, 0 ) ); 64 | frameTabbedPane.addTab( "Context", contextTab ); 65 | errorPanel = new JPanel(); 66 | errorPanel.setLayout( new BorderLayout( 4, 0 ) ); 67 | contextTab.add( errorPanel, BorderLayout.NORTH ); 68 | errorLabel = new JLabel(); 69 | errorLabel.setText( "Error" ); 70 | errorPanel.add( errorLabel, BorderLayout.WEST ); 71 | errorTextField = new JTextField(); 72 | errorTextField.setBackground( new Color( - 328966 ) ); 73 | errorTextField.setEditable( false ); 74 | errorTextField.setText( "Illegal color value" ); 75 | errorPanel.add( errorTextField, BorderLayout.CENTER ); 76 | contextScrollPane = new JScrollPane(); 77 | contextTab.add( contextScrollPane, BorderLayout.WEST ); 78 | contextScrollPane.setBorder( BorderFactory.createTitledBorder( null, "Call Stack", TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, null, null ) ); 79 | contextList = new JList(); 80 | Font contextListFont = this.$$$getFont$$$( null, Font.PLAIN, - 1, contextList.getFont() ); 81 | if( contextListFont != null ) contextList.setFont( contextListFont ); 82 | final DefaultListModel defaultListModel1 = new DefaultListModel(); 83 | defaultListModel1.addElement( "error: - Color" ); 84 | defaultListModel1.addElement( "red:green:blue: - Color" ); 85 | defaultListModel1.addElement( "red:green:blue: - MetaColor" ); 86 | defaultListModel1.addElement( "doIt - Undefined" ); 87 | contextList.setModel( defaultListModel1 ); 88 | contextList.setSelectionForeground( new Color( - 16777216 ) ); 89 | contextScrollPane.setViewportView( contextList ); 90 | argumentScrollPane = new JScrollPane(); 91 | contextTab.add( argumentScrollPane, BorderLayout.CENTER ); 92 | argumentScrollPane.setBorder( BorderFactory.createTitledBorder( null, "Self & Arguments", TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, null, null ) ); 93 | argumentList = new JList(); 94 | Font argumentListFont = this.$$$getFont$$$( null, Font.PLAIN, - 1, argumentList.getFont() ); 95 | if( argumentListFont != null ) argumentList.setFont( argumentListFont ); 96 | final DefaultListModel defaultListModel2 = new DefaultListModel(); 97 | defaultListModel2.addElement( "Color( nil, nil, nil )" ); 98 | defaultListModel2.addElement( "1" ); 99 | defaultListModel2.addElement( "22" ); 100 | defaultListModel2.addElement( "333" ); 101 | argumentList.setModel( defaultListModel2 ); 102 | argumentScrollPane.setViewportView( argumentList ); 103 | inspectorTab = new JPanel(); 104 | inspectorTab.setLayout( new BorderLayout( 0, 0 ) ); 105 | frameTabbedPane.addTab( "Color", inspectorTab ); 106 | } 107 | 108 | /** 109 | * @noinspection ALL 110 | */ 111 | private Font $$$getFont$$$( String fontName, int style, int size, Font currentFont ) 112 | { 113 | if( currentFont == null ) return null; 114 | String resultName; 115 | if( fontName == null ) { 116 | resultName = currentFont.getName(); 117 | } else { 118 | Font testFont = new Font( fontName, Font.PLAIN, 10 ); 119 | if( testFont.canDisplay( 'a' ) && testFont.canDisplay( '1' ) ) { 120 | resultName = fontName; 121 | } else { 122 | resultName = currentFont.getName(); 123 | } 124 | } 125 | return new Font( resultName, style >= 0 ? style : currentFont.getStyle(), size >= 0 ? size : currentFont.getSize() ); 126 | } 127 | 128 | /** 129 | * @noinspection ALL 130 | */ 131 | public JComponent $$$getRootComponent$$$() 132 | { 133 | return notNeeded; 134 | } 135 | 136 | private void createUIComponents() 137 | { 138 | String[] columns = { "Variable", "Value" }; 139 | String[][] rows = { { "red", "1" }, { "green", "22" }, { "blue", "333" } }; 140 | 141 | // variablesTable = new JTable( rows, columns ); 142 | 143 | DefaultTableModel tableModel = new DefaultTableModel(); 144 | 145 | tableModel.addColumn( columns[ 0 ] ); 146 | tableModel.addColumn( columns[ 1 ] ); 147 | 148 | for( String[] row : rows ) { 149 | tableModel.addRow( row ); 150 | } 151 | 152 | argumentTable = new JTable( tableModel ); 153 | argumentTable.setDefaultEditor( Object.class, null ); 154 | 155 | argumentTable.addMouseListener( new MouseAdapter() 156 | { 157 | public void mouseClicked( MouseEvent mouseEvent ) 158 | { 159 | onTableClicked( mouseEvent ); 160 | } 161 | } ); 162 | } 163 | 164 | void onTableClicked( MouseEvent mouseEvent ) 165 | { 166 | if( mouseEvent.getClickCount() != 2 ) // to detect double click events 167 | return; 168 | 169 | int row = argumentTable.getSelectedRow(); 170 | int column = argumentTable.getSelectedColumn(); 171 | Object string = argumentTable.getValueAt( row, column ); 172 | JOptionPane.showMessageDialog( null, string ); 173 | } 174 | } 175 | -------------------------------------------------------------------------------- /GuiDesign/src/EventBrokerNew.java: -------------------------------------------------------------------------------- 1 | package smallj.test; 2 | 3 | import javax.swing.*; 4 | import java.awt.*; 5 | import java.beans.*; 6 | import java.util.EventObject; 7 | import java.awt.event.MouseEvent; 8 | 9 | // This class is for generic event handling in stead of hard coded. 10 | // Is not used at the moment. 11 | 12 | public class EventBrokerNew 13 | { 14 | public static void main( String[] args ) 15 | { 16 | new EventBrokerNew().start(); 17 | } 18 | 19 | void start() 20 | { 21 | JButton button = new JButton( "Click Me" ); 22 | listenToAllEvents( button, this, "myEventHandler" ); 23 | 24 | JFrame frame = new JFrame( "Generic Event Listener" ); 25 | frame.getContentPane().add( button, BorderLayout.PAGE_START ); 26 | frame.pack(); 27 | frame.setVisible( true ); 28 | } 29 | 30 | void listenToAllEvents( Object component, Object listener, String methodName ) 31 | { 32 | BeanInfo beanInfo; 33 | try { 34 | beanInfo = Introspector.getBeanInfo( component.getClass() ); 35 | } catch ( IntrospectionException ex ) { 36 | System.err.println( ex ); 37 | return; 38 | } 39 | 40 | for ( EventSetDescriptor eventSetDescriptor : beanInfo.getEventSetDescriptors() ) { 41 | try { 42 | Class listenerClass = eventSetDescriptor.getListenerType(); 43 | Object eventHandler = EventHandler.create( listenerClass, listener, methodName, "" ); 44 | eventSetDescriptor.getAddListenerMethod().invoke( component, eventHandler ); 45 | } catch ( ReflectiveOperationException ex ) { 46 | System.err.println( ex ); 47 | } 48 | } 49 | } 50 | 51 | public void myEventHandler( EventObject event ) 52 | { 53 | if( event instanceof MouseEvent ) 54 | System.out.println( event ); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /GuiDesign/src/ImageEditor.form: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /GuiDesign/src/ImageEditor.java: -------------------------------------------------------------------------------- 1 | import javax.swing.*; 2 | import javax.swing.border.TitledBorder; 3 | import java.awt.*; 4 | 5 | public class ImageEditor 6 | { 7 | public static void main( String[] args ) 8 | { 9 | new ImageEditor().show(); 10 | } 11 | 12 | void show() 13 | { 14 | frame = new JFrame( "Image Editor" ); 15 | frame.setContentPane( framePanel ); 16 | ImageIcon icon = new ImageIcon( getClass().getResource( "/SmallJIcon.png" ) ); 17 | frame.setIconImage( icon.getImage() ); 18 | frame.pack(); 19 | frame.setLocationRelativeTo( null ); 20 | frame.setVisible( true ); 21 | } 22 | 23 | JFrame frame; 24 | JPanel framePanel; 25 | JPanel colorPanel; 26 | JLabel imageLabel; 27 | JButton closeButton; 28 | JButton colorButton; 29 | JTextField colorTextField; 30 | private JScrollPane imageScrollPane; 31 | 32 | { 33 | // GUI initializer generated by IntelliJ IDEA GUI Designer 34 | // >>> IMPORTANT!! <<< 35 | // DO NOT EDIT OR ADD ANY CODE HERE! 36 | $$$setupUI$$$(); 37 | } 38 | 39 | /** 40 | * Method generated by IntelliJ IDEA GUI Designer 41 | * >>> IMPORTANT!! <<< 42 | * DO NOT edit this method OR call it in your code! 43 | * 44 | * @noinspection ALL 45 | */ 46 | private void $$$setupUI$$$() 47 | { 48 | framePanel = new JPanel(); 49 | framePanel.setLayout( new BorderLayout( 0, 4 ) ); 50 | framePanel.setBorder( BorderFactory.createTitledBorder( BorderFactory.createEmptyBorder( 4, 4, 4, 4 ), null, TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, null, null ) ); 51 | colorPanel = new JPanel(); 52 | colorPanel.setLayout( new BorderLayout( 4, 0 ) ); 53 | framePanel.add( colorPanel, BorderLayout.NORTH ); 54 | colorButton = new JButton(); 55 | colorButton.setText( "Color" ); 56 | colorPanel.add( colorButton, BorderLayout.WEST ); 57 | colorTextField = new JTextField(); 58 | colorTextField.setText( "Color[ 0, 0, 200 ]" ); 59 | colorPanel.add( colorTextField, BorderLayout.CENTER ); 60 | closeButton = new JButton(); 61 | closeButton.setText( "Close" ); 62 | framePanel.add( closeButton, BorderLayout.SOUTH ); 63 | imageScrollPane = new JScrollPane(); 64 | framePanel.add( imageScrollPane, BorderLayout.CENTER ); 65 | imageLabel = new JLabel(); 66 | imageLabel.setHorizontalAlignment( 0 ); 67 | imageLabel.setIcon( new ImageIcon( getClass().getResource( "/SmallJIcon.png" ) ) ); 68 | imageLabel.setText( "" ); 69 | imageScrollPane.setViewportView( imageLabel ); 70 | } 71 | 72 | /** 73 | * @noinspection ALL 74 | */ 75 | public JComponent $$$getRootComponent$$$() 76 | { 77 | return framePanel; 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /GuiDesign/src/Inspector.form: -------------------------------------------------------------------------------- 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 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 |
73 | -------------------------------------------------------------------------------- /GuiDesign/src/Inspector.java: -------------------------------------------------------------------------------- 1 | import javax.swing.*; 2 | import javax.swing.border.TitledBorder; 3 | import javax.swing.table.DefaultTableModel; 4 | import java.awt.*; 5 | import java.awt.event.MouseAdapter; 6 | import java.awt.event.MouseEvent; 7 | 8 | // Todo: Create TableModel es general as possible. 9 | public class Inspector 10 | { 11 | public static void main( String[] args ) 12 | { 13 | new Inspector().show(); 14 | } 15 | 16 | void show() 17 | { 18 | frame = new JFrame( "Inspector" ); 19 | frame.setContentPane( notNeeded ); 20 | ImageIcon icon = new ImageIcon( getClass().getResource( "/SmallJIcon.png" ) ); 21 | frame.setIconImage( icon.getImage() ); 22 | frame.pack(); 23 | frame.setLocationRelativeTo( null ); 24 | frame.setVisible( true ); 25 | } 26 | 27 | JFrame frame; 28 | JPanel notNeeded; 29 | JTable variablesTable; 30 | JScrollPane variablesScrollPane; 31 | private JLabel stringLabel; 32 | private JTextField stringTextField; 33 | private JTabbedPane objectsTabbedPane; 34 | private JPanel objectPanel; 35 | private JPanel stringPanel; 36 | private JButton closeButton; 37 | 38 | { 39 | // GUI initializer generated by IntelliJ IDEA GUI Designer 40 | // >>> IMPORTANT!! <<< 41 | // DO NOT EDIT OR ADD ANY CODE HERE! 42 | $$$setupUI$$$(); 43 | } 44 | 45 | /** 46 | * Method generated by IntelliJ IDEA GUI Designer 47 | * >>> IMPORTANT!! <<< 48 | * DO NOT edit this method OR call it in your code! 49 | * 50 | * @noinspection ALL 51 | */ 52 | private void $$$setupUI$$$() 53 | { 54 | createUIComponents(); 55 | notNeeded = new JPanel(); 56 | notNeeded.setLayout( new BorderLayout( 0, 0 ) ); 57 | objectsTabbedPane = new JTabbedPane(); 58 | notNeeded.add( objectsTabbedPane, BorderLayout.CENTER ); 59 | objectPanel = new JPanel(); 60 | objectPanel.setLayout( new BorderLayout( 0, 4 ) ); 61 | objectsTabbedPane.addTab( "Color", objectPanel ); 62 | objectPanel.setBorder( BorderFactory.createTitledBorder( BorderFactory.createEmptyBorder( 4, 4, 4, 4 ), null, TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, null, null ) ); 63 | variablesScrollPane = new JScrollPane(); 64 | objectPanel.add( variablesScrollPane, BorderLayout.CENTER ); 65 | variablesTable.setName( "variablesTable" ); 66 | variablesScrollPane.setViewportView( variablesTable ); 67 | stringPanel = new JPanel(); 68 | stringPanel.setLayout( new BorderLayout( 4, 0 ) ); 69 | objectPanel.add( stringPanel, BorderLayout.NORTH ); 70 | stringLabel = new JLabel(); 71 | stringLabel.setHorizontalAlignment( 2 ); 72 | stringLabel.setText( "String" ); 73 | stringPanel.add( stringLabel, BorderLayout.WEST ); 74 | stringTextField = new JTextField(); 75 | stringTextField.setEditable( false ); 76 | stringTextField.setText( "Color: [ 1, 22, 255 ]" ); 77 | stringPanel.add( stringTextField, BorderLayout.CENTER ); 78 | closeButton = new JButton(); 79 | closeButton.setText( "x" ); 80 | stringPanel.add( closeButton, BorderLayout.EAST ); 81 | } 82 | 83 | /** 84 | * @noinspection ALL 85 | */ 86 | public JComponent $$$getRootComponent$$$() 87 | { 88 | return notNeeded; 89 | } 90 | 91 | private void createUIComponents() 92 | { 93 | String[] columns = { "Variable", "Value" }; 94 | String[][] rows = { { "red", "1" }, { "green", "22" }, { "blue", "255" } }; 95 | 96 | // variablesTable = new JTable( rows, columns ); 97 | 98 | DefaultTableModel tableModel = new DefaultTableModel(); 99 | 100 | tableModel.addColumn( columns[ 0 ] ); 101 | tableModel.addColumn( columns[ 1 ] ); 102 | 103 | for( String[] row : rows ) { 104 | tableModel.addRow( row ); 105 | } 106 | 107 | variablesTable = new JTable( tableModel ); 108 | variablesTable.setDefaultEditor( Object.class, null ); 109 | 110 | variablesTable.addMouseListener( new MouseAdapter() 111 | { 112 | public void mouseClicked( MouseEvent mouseEvent ) 113 | { 114 | onTableClicked( mouseEvent ); 115 | } 116 | } ); 117 | } 118 | 119 | void onTableClicked( MouseEvent mouseEvent ) 120 | { 121 | if( mouseEvent.getClickCount() != 2 ) // to detect double click events 122 | return; 123 | 124 | int row = variablesTable.getSelectedRow(); 125 | int column = variablesTable.getSelectedColumn(); 126 | Object string = variablesTable.getValueAt( row, column ); 127 | JOptionPane.showMessageDialog( null, string ); 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 SmallJ 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 all 13 | 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 THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SmallJ ReadMe 2 | 3 | SmallJ is a simple Smalltalk virtual machine written in Java. 4 | It was originally created as SmallWorld by Timothy Budd (http://web.engr.oregonstate.edu/~budd/SmallWorld/). 5 | This specific version was built from Eric Scharff's update (https://github.com/ericscharff/SmallWorld) 6 | 7 | But a *lot* was changed and rewritten... in summary: 8 | - More OO Java code; more classes, longer variable names, fewer globals, smaller functions. 9 | - Use of modern Java features like lambda functions and method references. 10 | - More OO Smalltalk code; longer variable names, shorter statements, MVC separation, code formatting. 11 | - Created Smalltalk primitives for manipulating arbitrary Java objects (FFI) using reflection. 12 | So now, the full Java framework can be used from Smalltalk without modifying the VM. 13 | - Reimplemented the VM GUI classes in Smalltalk using the FFI, that now closely mirror the Java Swing framework. 14 | So now, all Java GUI operations can be easily added with one-line methods in Smalltalk. 15 | Further abstractions can be built on top of this, if desired. 16 | Removed now redundant GUI wrapper classes and associated primitives from the VM. 17 | - Changed the development workflow to be source file based, preferably using the rich Visual Studio Code IDE. 18 | Created a new class browser in Smalltalk for testing / debugging this way. 19 | Removed source code from the image, making it a lot smaller. 20 | 21 | With these changes, the interpreter will may run slower than it did before. 22 | Maybe, because adding primitive tables with direct function references probably helped performance a lot. 23 | Speed is not an issue for regular development operations, the system is snappy. 24 | Recompiling all sources takes about 8 seconds on my sub-top Core-i7 from 2017. 25 | Anyway, performance testing and hotspot optimizations are still to come... 26 | 27 | # Smalltalk startup & development 28 | - Use of Visual Studio Code (VSCode) is strongly recommended for Smalltalk development. 29 | - The folder "./VSCode" contains an extension with basic syntax coloring support. 30 | On Windows, run "Deploy.cmd" to deploy it in your VSCode IDE (it's a simple copy). 31 | - Smalltalk development is done in the "./Smalltalk" folder. 32 | - SmallJ can be started by selecting Run or Debug from the VSCode workspace in the ./VM folder, 33 | or by running SmallJ.jar from the ./Smalltalk folder. The .jar extension should be associated to the OpenJDK VM. 34 | - The default Smalltalk image file is 'Image.sjim'. 35 | - Smalltalk class source files (*.st) are organized in subfolders that could be called packages. 36 | - By default, the main development window, the System Browser, is shown. 37 | There, folders, classes and methods can be selected to edit their source. 38 | - The [ Save & Compile ] button saves and compiles the modified class. 39 | Note: If the source file was modifield outside SmallJ, e.g. in VSCode, that file will be compiled and loaded. 40 | - The image contains the compiled methods, so be sure to save it if you are happy with your changes. 41 | Make regular backups of the image, in case something breakes that prevents SmallJ from starting up. 42 | - At the bottom of the System Browser, you can evaluate any Smalltalk expression. 43 | [ Evaluate ] prints the result while [ Inspect ] additionally opens and object inspector on the result. 44 | Double-click on variables to inspect contained member variables in new window tabs. 45 | - When a Smalltalk runtime error occurs, the Debugger window is opened, 46 | displaying the method call stack and argument variables per method. 47 | Double-click on a variables to inspect it. 48 | 49 | # VM startup & development 50 | - The VM is located in the ./VM folder. 51 | - It is developed with OpenJDK v17, so install that first. 52 | Using for modern Java features is encouraged to keep the VM source code compact. 53 | - For VM development, using Visual Studio Code is recommended also. 54 | The VSCode workspace in the root folder contains the settings to build, run and debug the VM. 55 | This includes starting it in the ./Smalltalk folder, which is required. 56 | 57 | # Vision 58 | For now, SmallJ is an intended to be an educational system, as was SmallWorld. 59 | Is shows the beauty of the elegant, clean and fully object oriented Smalltalk programming language, 60 | to be compared to the many hybrid OO languages that are out there currently. 61 | In the future, SmallJ could be expanded to being a useful scripting language for smaller tasks 62 | and for creating quick GUIs. 63 | 64 | # Roadmap 65 | The development philosophy of SmallJ is to keep it tightly bound to the Java framework, 66 | to enable full use of its features when adding more parts of it to Smalltalk, using the FFI. 67 | On top of that, powerful Smalltalk abstractions of the, somewhat overdesigned, Java framework can be added. 68 | 69 | Other Java libraries could be encapsulated by Smalltalk, 70 | in stead of rewriting them in Smalltalk from the ground up. 71 | Support for databases / persistence is a todo. 72 | GUI wise, HTML support is desired, probably with its own web server. 73 | New: For browser client development, check out [SmallJS](https://github.com/Small-JS/SmallJS) ! 74 | 75 | Regression testing needs to added for maintaining stability with open source development. 76 | VM performance optimization is also needed to make it more suitable for CPU intensive tasks. 77 | 78 | For coding, the Smalltalk support within VSCode could be improved with a grammar parser. 79 | Source level step-debugging seems the ultimate goal there. 80 | 81 | # Personal 82 | For me personally, this is continuing to be a fun hobby development project. 83 | Working hours on it have to fit in with a busy daytime job and a social life :). 84 | If you have any questions, remarks, or would like to join SmallJ main development, 85 | you can contact me on as user FunctionPoint on GitHub. 86 | 87 | Cheers, RichardR 88 | -------------------------------------------------------------------------------- /SmallJ.code-workspace: -------------------------------------------------------------------------------- 1 | { 2 | "folders": [ 3 | { 4 | "path": "." 5 | } 6 | ], 7 | "settings": { 8 | "java.dependency.packagePresentation": "hierarchical" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Smalltalk/Base/Block.st: -------------------------------------------------------------------------------- 1 | CLASS Context subclass: 'Block' variables: 'argumentLocation creatingContext oldBytePointer' classVariables: '' 2 | METHOD fork 3 | "Block must not have arguments." 4 | < 19 self >. 5 | ! 6 | METHOD value 7 | "Execute block." 8 | < 8 self >. 9 | ! 10 | METHOD value: a 11 | "Execute block with 1 argument." 12 | < 8 a self >. 13 | ! 14 | METHOD value: a value: b 15 | "Execute block with 2 arguments." 16 | < 8 a b self >. 17 | ! 18 | METHOD whileFalse: aBlock 19 | self value ifFalse: [ 20 | aBlock value. 21 | ^ self whileFalse: aBlock ]. 22 | ! 23 | METHOD whileTrue: aBlock 24 | self value ifTrue: [ 25 | aBlock value. 26 | ^ self whileTrue: aBlock ]. 27 | ! 28 | -------------------------------------------------------------------------------- /Smalltalk/Base/Boolean.st: -------------------------------------------------------------------------------- 1 | CLASS Object subclass: 'Boolean' variables: '' classVariables: '' 2 | METHOD and: aBlock 3 | ^ self 4 | ifTrue: [ aBlock value ] 5 | ifFalse: [ false ] 6 | ! 7 | METHOD ifFalse: aBlock 8 | ^ self 9 | ifTrue: [ nil ] 10 | ifFalse: [ aBlock value ] 11 | ! 12 | METHOD ifFalse: falseBlock ifTrue: trueBlock 13 | ^ self 14 | ifTrue: [ trueBlock value ] 15 | ifFalse: [ falseBlock value ] 16 | ! 17 | METHOD ifTrue: aBlock 18 | ^ self 19 | ifTrue: [ aBlock value ] 20 | ifFalse: [ nil ] 21 | ! 22 | METHOD not 23 | ^ self 24 | ifTrue: [ false ] 25 | ifFalse: [ true ] 26 | ! 27 | METHOD or: aBlock 28 | ^ self 29 | ifTrue: [ true ] 30 | ifFalse: [ aBlock value ] 31 | ! 32 | -------------------------------------------------------------------------------- /Smalltalk/Base/Class.st: -------------------------------------------------------------------------------- 1 | CLASS Object subclass: 'Class' variables: 'name parentClass methods size variables sourceFileName' classVariables: 'classes' 2 | META addClass: aClass 3 | "Add new class or update existing one. 4 | Returns updated existing class or otherwise (new) argument class." 5 | | existingClass | 6 | existingClass := classes find: [ :class | class name = aClass name ] ifAbsent: [ 7 | "Not found, add new class." 8 | classes := ( ( classes add: aClass ) asOrdered: [ :a :b | a name < b name ] ) asArray. 9 | ^ aClass ]. 10 | 11 | "Update existing class." 12 | existingClass updateFrom: aClass. 13 | existingClass class updateFrom: aClass class. 14 | existingClass resetSizeAndSubs. 15 | ^ existingClass. 16 | ! 17 | META at: aName ifAbsent: noValue 18 | classes do: [ :class | 19 | class name = aName ifTrue: [ ^ class ] ]. 20 | ^ noValue value. 21 | ! 22 | META classes 23 | ^ classes 24 | ! 25 | META classes: aClasses 26 | "Dangerous - Set classes variable. Use only for repairing image." 27 | classes := aClasses. 28 | ! 29 | META recompileAllMethods 30 | "This is done to remove references to updated classes." 31 | classes do: [ :class | 32 | class class recompileMethods. 33 | class recompileMethods ]. 34 | ! 35 | META removeClass: className 36 | classes := ( classes reject: [ :class | class name = className ] ) asArray. 37 | ! 38 | META resetAllSizes 39 | "Recalculate and reset size variable of all classes, 40 | to repair a former bug and to accomodate for changed instance vars" 41 | classes do: [ :class | 42 | class class resetSize. 43 | class resetSize ]. 44 | ! 45 | METHOD addClassVariable: n 46 | "Dangereous - Put new class variable in class." 47 | Object in: self add: nil. 48 | Object in: self class at: 5 put: ( self class variables add: n ). 49 | size := size + 1 50 | ! 51 | METHOD addInstanceVariable: n 52 | variables := variables add: n. 53 | size := size + 1 54 | ! 55 | METHOD allMethods 56 | ^ parentClass isNil 57 | ifTrue: [ methods asList ] 58 | ifFalse: [ methods asList addAll: parentClass allMethods ]. 59 | ! 60 | METHOD compileMethod: aString 61 | "Compile aString into method. 62 | Return new method on success, otherwise raise error." 63 | | method | 64 | ( method := self parseMethod: aString ) ifNil: [ 65 | self error: 'Compile method failed.' ]. 66 | 67 | methods := ( ( ( methods select: [ :m | m name ~= method name ] ) add: method ) 68 | asOrdered: [ :a :b | a name < b name ] ) asArray. 69 | System out println: 'Compiled method: ' + self name + '.' + method name. 70 | ^ method. 71 | ! 72 | METHOD fileIn 73 | ClassParser fileIn: sourceFileName. 74 | ! 75 | METHOD hierarchy 76 | ^ self hierarchy: 0. 77 | ! 78 | METHOD hierarchy: level 79 | | result | 80 | result := ''. 81 | level timesRepeat: [ 82 | result := result + Char tab asString ]. 83 | result := result + name + Char newline asString. 84 | self subclasses do: [ :class | 85 | result := result + ( class hierarchy: level + 1 ) ]. 86 | ^ result. 87 | ! 88 | METHOD instanceVariables 89 | "Return variable names and those of our superclasses." 90 | | names | 91 | parentClass notNil 92 | ifTrue: [ names := parentClass instanceVariables ] 93 | ifFalse: [ names := Array new: 0 ]. 94 | variables notNil 95 | ifTrue: [ names := names + variables ]. 96 | ^ names. 97 | ! 98 | METHOD methods 99 | ^ methods 100 | ! 101 | METHOD methods: aMethods 102 | methods := aMethods. 103 | ! 104 | METHOD name 105 | ^ name 106 | ! 107 | METHOD name: aName 108 | name := aName. 109 | ! 110 | METHOD name: aName parent: aParent variables: aVariables 111 | " private method used for initialization " 112 | name := aName. 113 | parentClass := aParent. 114 | variables := aVariables asWords. 115 | methods := Array new: 0. 116 | size := parentClass size + variables size 117 | ! 118 | METHOD new 119 | "Return a new instance of ourselves." 120 | ^ < 7 self size >. 121 | ! 122 | METHOD parent: aParent 123 | parentClass := aParent. 124 | ! 125 | METHOD parseMethod: text 126 | ^ ( Parser new text: text instanceVars: self instanceVariables classVars: self class variables ) parse: self. 127 | ! 128 | METHOD printString 129 | ^ name printString 130 | ! 131 | METHOD recompileMethods 132 | "This is done to remove references to old, now replaced classes." 133 | self methods do: [ :method | 134 | self compileMethod: method text ]. 135 | ! 136 | METHOD removeMethod: aMethodName 137 | methods := ( methods select: [ :method | method name ~= aMethodName ] ) asArray. 138 | ! 139 | METHOD resetSize 140 | "Recalculate and reset size variable of this class and parent classes." 141 | | parent parentSize variablesSize | 142 | parent := self superclass. 143 | parentSize := parent isNil ifTrue: [ 0 ] ifFalse: [ parent resetSize ]. 144 | variablesSize := variables isNil ifTrue: [ 0 ] ifFalse: [ variables size ]. 145 | size := parentSize + variablesSize. 146 | < 25 self ( self class size ) >. 147 | ^ size. 148 | ! 149 | METHOD resetSizeAndSubs 150 | "Reset self size and size of subsclasses 151 | and also for self metaclass and its subclasses." 152 | self resetSize. 153 | self subclasses do: [ :class | 154 | class class resetSizeAndSubs. 155 | class resetSizeAndSubs ]. 156 | ! 157 | METHOD size 158 | ^ size. 159 | ! 160 | METHOD sourceFileName 161 | ^ sourceFileName. 162 | ! 163 | METHOD sourceFileName: aSourceFileName 164 | sourceFileName := File forwardSlashes: aSourceFileName. 165 | ! 166 | METHOD subclass: aName variables: aVariables classVariables: aClassVariables 167 | | metaClass class | 168 | metaClass := Class new name: 'Meta' + aName printString parent: self class variables: aClassVariables. 169 | class := metaClass new name: aName parent: self variables: aVariables. 170 | ^ Class addClass: class. 171 | ! 172 | METHOD subclasses 173 | ^ Class classes select: [ :class | class superclass = self ]. 174 | ! 175 | METHOD superclass 176 | ^ parentClass 177 | ! 178 | METHOD updateFrom: aClass 179 | "Private - Set class attributes of self to those of argument class. 180 | This is for changing existing classes on fileIn without." 181 | 182 | "Class name should be same already. 183 | So not: name := aClass name." 184 | parentClass := aClass superclass. 185 | "Leave current methods to enable filing-in critical base classes. 186 | So not: methods := aClass methods." 187 | size := aClass size. 188 | variables := aClass variables. 189 | ! 190 | METHOD variables 191 | ^ variables 192 | ! 193 | METHOD sourceFolderName 194 | "Return the folder part of the source file of this class. 195 | Return '.' if the file is stored locally. 196 | Return nil if the source file name is not set." 197 | | position | 198 | sourceFileName ifNil: [ ^ nil ]. 199 | "sourceFileName must be stored using forward slashes." 200 | position := sourceFileName indexOfLast: $/ ifAbsent: [ ^ '.' ]. 201 | position = 1 ifTrue: [ position := 2 ]. "If root folder, keep separator char." 202 | ^ sourceFileName from: 1 to: position - 1. 203 | ! 204 | -------------------------------------------------------------------------------- /Smalltalk/Base/Context.st: -------------------------------------------------------------------------------- 1 | CLASS Object subclass: 'Context' variables: 'method arguments temporaries stack bytePointer stackTop previousContext' classVariables: '' 2 | META current 3 | ^ < 35 >. 4 | ! 5 | METHOD backtrace 6 | ^ method name + 7 | ( arguments inject: '[' into: [ :r :a | r + a class printString + ',' ] ) + 8 | ']' + Char newline asString + 9 | ( previousContext notNil ifTrue: [ previousContext backtrace ] ifFalse: [ ' ' ] ). 10 | ! 11 | METHOD method: aMethod arguments: aAgruments 12 | method := aMethod. 13 | arguments := aAgruments. 14 | temporaries := Array new: aMethod tempSize. 15 | bytePointer := 0. 16 | stack := Array new: method stackSize. 17 | stackTop := 0. 18 | ! 19 | METHOD perform: aMethod withArguments: aAgruments 20 | method := aMethod. 21 | arguments := aAgruments. 22 | temporaries := Array new: aMethod tempSize. 23 | bytePointer := 0. 24 | stack := Array new: method stackSize. 25 | stackTop := 0. 26 | ^ < 6 self >. 27 | ! 28 | METHOD method 29 | ^ method. 30 | ! 31 | METHOD arguments 32 | ^ arguments. 33 | ! 34 | METHOD temporaries 35 | ^ temporaries. 36 | ! 37 | METHOD stack 38 | ^ stack. 39 | ! 40 | METHOD bytePointer 41 | ^ bytePointer. 42 | ! 43 | METHOD stackTop 44 | ^ stackTop. 45 | ! 46 | METHOD previousContext 47 | ^ previousContext. 48 | ! 49 | -------------------------------------------------------------------------------- /Smalltalk/Base/False.st: -------------------------------------------------------------------------------- 1 | CLASS Boolean subclass: 'False' variables: '' classVariables: '' 2 | META new 3 | " there is only one false value " 4 | ^ false. 5 | ! 6 | METHOD and: aBlock 7 | ^ false 8 | ! 9 | METHOD ifTrue: trueBlock ifFalse: falseBlock 10 | ^ falseBlock value. 11 | ! 12 | METHOD not 13 | ^ true. 14 | ! 15 | METHOD or: aBlock 16 | ^ aBlock value. 17 | ! 18 | METHOD printString 19 | ^ 'false'. 20 | ! 21 | -------------------------------------------------------------------------------- /Smalltalk/Base/Method.st: -------------------------------------------------------------------------------- 1 | CLASS Object subclass: 'Method' variables: 'name byteCodes literals stackSize temporarySize class lineNum' classVariables: '' 2 | META name: aName byteCodes: aByteCodes literals: aLiterals stackSize: aStackSize temporarySize: aTemporarySize class: aClass 3 | | newMethod | 4 | newMethod := self new. 5 | super in: newMethod at: 1 put: aName. 6 | super in: newMethod at: 2 put: aByteCodes. 7 | super in: newMethod at: 3 put: aLiterals. 8 | super in: newMethod at: 4 put: ( aStackSize max: 20 ). "To support primitives with upto 20 args." 9 | super in: newMethod at: 5 put: aTemporarySize. 10 | super in: newMethod at: 6 put: aClass. 11 | ^ newMethod 12 | ! 13 | METHOD name 14 | ^ name 15 | ! 16 | METHOD byteCodes 17 | ^ byteCodes 18 | ! 19 | METHOD literals 20 | ^ literals 21 | ! 22 | METHOD stackSize 23 | ^ stackSize 24 | ! 25 | METHOD tempSize 26 | ^ temporarySize 27 | ! 28 | METHOD lineNum 29 | ^ lineNum. 30 | ! 31 | METHOD lineNum: aLineNum 32 | lineNum := aLineNum. 33 | ! 34 | METHOD printString 35 | ^ name 36 | ! 37 | METHOD stackSize 38 | ^ stackSize 39 | ! 40 | -------------------------------------------------------------------------------- /Smalltalk/Base/Object.st: -------------------------------------------------------------------------------- 1 | CLASS Object 2 | "The Object class cannot be created as a subclass: 3 | nil subclass: 'Object' variables: '' classVariables: ''" 4 | META halt 5 | "Primitive thread death. 6 | Called after self error:." 7 | < 34 >. 8 | ! 9 | META in: object add: newValue 10 | "Add new data value to object." 11 | ^ < 32 object newValue > 12 | ! 13 | META in: object at: index 14 | "Get index-th data member from object." 15 | ^ < 30 object index > 16 | ! 17 | META in: object at: index put: value 18 | "Set index-th data member of object to value. 19 | Dangerous, use carefully." 20 | ^ < 18 object index value >. 21 | ! 22 | META in: object initialize: variable with: value 23 | "Set variable in object to value." 24 | | index | 25 | index := object class variables indexOf: variable ifAbsent: [ 26 | self error: 'Variable not found: ' + variable ]. 27 | ^ self in: object at: index put: value. 28 | ! 29 | METHOD = arg 30 | "Return true if object has the same value as arg. 31 | The default is the object identity test (same object). 32 | Value holding objects can overload this." 33 | ^ self == arg. 34 | ! 35 | METHOD == arg 36 | "Return true if self points to the same object as arg." 37 | ^ < 1 self arg >. 38 | ! 39 | METHOD ~= arg 40 | "Return true if object does *not* have the same value as arg." 41 | ^ ( self = arg ) not. 42 | ! 43 | METHOD class 44 | "Return class of self." 45 | ^ < 2 self >. 46 | ! 47 | METHOD error: message 48 | Debugger new show: message. 49 | Object halt. 50 | ! 51 | METHOD ifNil: block 52 | "Evaluate block if receiver is nil." 53 | ^ self isNil ifTrue: block. 54 | ! 55 | METHOD ifNotNil: block 56 | "Evaluate block if receiver is *not* nil." 57 | ^ self notNil ifTrue: block. 58 | ! 59 | METHOD inspect 60 | Inspector show: self. 61 | ! 62 | METHOD isKindOf: aClass 63 | "Return true if self is an instance of aClass or one of its parents." 64 | | class | 65 | class := self class. 66 | [ class notNil ] whileTrue: [ 67 | class == aClass ifTrue: [ ^ true ]. 68 | class := class superclass ]. 69 | ^ false. 70 | ! 71 | METHOD isNil 72 | ^ false. 73 | ! 74 | METHOD notNil 75 | ^ true. 76 | ! 77 | METHOD printString 78 | ^ 'a ' + self class printString. 79 | ! 80 | METHOD respondsTo: aMessage 81 | ^ self class allMethods includesTest: [ :m | m name = aMessage ] 82 | ! 83 | -------------------------------------------------------------------------------- /Smalltalk/Base/True.st: -------------------------------------------------------------------------------- 1 | CLASS Boolean subclass: 'True' variables: '' classVariables: '' 2 | META new 3 | " there is only one true value " 4 | ^ true. 5 | ! 6 | METHOD and: aBlock 7 | ^ aBlock value. 8 | ! 9 | METHOD ifTrue: trueBlock ifFalse: falseBlock 10 | ^ trueBlock value. 11 | ! 12 | METHOD not 13 | ^ false. 14 | ! 15 | METHOD printString 16 | ^ 'true'. 17 | ! 18 | METHOD or: aBlock 19 | ^ true. 20 | ! 21 | -------------------------------------------------------------------------------- /Smalltalk/Base/Undefined.st: -------------------------------------------------------------------------------- 1 | CLASS Object subclass: 'Undefined' variables: '' classVariables: '' 2 | META new 3 | " there is only one nil object " 4 | ^ nil. 5 | ! 6 | METHOD isNil 7 | " yes, we are nil " 8 | ^ true. 9 | ! 10 | METHOD notNil 11 | " no, we are not not-nil " 12 | ^ false. 13 | ! 14 | METHOD printString 15 | ^ 'nil'. 16 | ! 17 | -------------------------------------------------------------------------------- /Smalltalk/Collection/Array.st: -------------------------------------------------------------------------------- 1 | CLASS Indexed subclass: 'Array' variables: '' classVariables: '' 2 | META new 3 | ^ self error: 'Arrays cannot be created with new. Use new: .' 4 | ! 5 | META new: aSize 6 | ^ < 7 self aSize >. 7 | ! 8 | METHOD + argArray 9 | "Return new array with elements of self and argArray concatenated." 10 | | selfSize argSize newArray | 11 | selfSize := self size. 12 | argSize := argArray size. 13 | newArray := self class new: ( selfSize + argSize ). 14 | 1 to: selfSize do: [ :i | 15 | newArray at: i put: ( self at: i ) ]. 16 | 1 to: argSize do: [ :i | 17 | newArray at: ( selfSize + i ) put: ( argArray at: i ) ]. 18 | ^ newArray. 19 | ! 20 | METHOD add: newItem 21 | ^ < 31 self newItem >. 22 | ! 23 | METHOD asString 24 | ^ self inject: '' into: [ :string :element | 25 | string + element + ' ' ]. 26 | ! 27 | METHOD asStringArray 28 | ^ ( self collect: [ :n | n printString ] ) asArray. 29 | ! 30 | METHOD at: index ifAbsent: exceptionBlock 31 | ( self includesKey: index ) 32 | ifTrue: [ ^ < 30 self index > ] 33 | ifFalse: [ ^ exceptionBlock value ] 34 | ! 35 | METHOD at: index put: value 36 | ( self includesKey: index ) ifFalse: [ 37 | self error: 'Array index out of bounds: ' + self size + ', size: ' + index ]. 38 | < 18 self index value >. 39 | ! 40 | METHOD copy 41 | ^ self asArray 42 | ! 43 | METHOD from: start size: sz 44 | ^ self from: start to: ( start + sz - 1 ) 45 | ! 46 | METHOD from: low to: high | start size newArray | 47 | start := low max: 0. 48 | size := ( high min: self size ) + 1 - start max: 0. 49 | newArray := self class new: size. 50 | 1 to: size do: [ :i | 51 | newArray at: i put: ( self at: start ). 52 | start := start + 1 ]. 53 | ^ newArray 54 | ! 55 | METHOD printString 56 | ^ '#' + super printString. 57 | ! 58 | METHOD removeAt: i 59 | "Return new array with the item at index i removed." 60 | | result | 61 | ( i between: 1 and: self size ) ifFalse: [ ^ self ]. 62 | result := Array new: self size - 1. 63 | ( 1 to: i - 1 ) do: [ :j | 64 | result at: j put: ( self at: j ) ]. 65 | ( i + 1 to: self size ) do: [ :j | 66 | result at: j - 1 put: ( self at: j ) ]. 67 | ^ result. 68 | ! 69 | METHOD size 70 | "Return number of elements in array." 71 | ^ < 4 self >. 72 | ! 73 | -------------------------------------------------------------------------------- /Smalltalk/Collection/ByteArray.st: -------------------------------------------------------------------------------- 1 | CLASS Array subclass: 'ByteArray' variables: '' classVariables: '' 2 | META new: aSize 3 | "Create a new byte array of given size." 4 | ^ < 20 ByteArray aSize > 5 | ! 6 | METHOD asCode 7 | | result | 8 | result := '( '. 9 | self do: [ :element | 10 | result := result + ( element quo: 16 ) + ':' + ( element rem: 16 ) + ' ' ]. 11 | ^ result + ')'. 12 | ! 13 | METHOD at: index ifAbsent: exceptionBlock 14 | ( self includesKey: index ) ifFalse: [ 15 | ^ exceptionBlock value ]. 16 | ^ < 21 self index >. 17 | ! 18 | METHOD at: index put: value 19 | ( self includesKey: index ) ifFalse: [ 20 | self error: 'Byte array indexing error: ' + index ]. 21 | ( value between: 0 and: 255 ) ifFalse: [ 22 | self error: 'Illegal value insertion into byte array.' + value ]. 23 | ^ < 22 self index value >. 24 | ! 25 | -------------------------------------------------------------------------------- /Smalltalk/Collection/Collection.st: -------------------------------------------------------------------------------- 1 | CLASS Magnitude subclass: 'Collection' variables: '' classVariables: '' 2 | METHOD addAll: aCollection 3 | aCollection do: [ :element | self add: element ] 4 | ! 5 | METHOD asArray 6 | | newArray index | 7 | newArray := Array new: self size. 8 | index := 1. 9 | self do: [ :element | newArray at: index put: element. 10 | index := index + 1 ]. 11 | ^ newArray 12 | ! 13 | METHOD asByteArray 14 | | newArray index | 15 | newArray := ByteArray new: self size. 16 | index := 1. 17 | self do: [ :element | 18 | newArray at: index put: element. 19 | index := index + 1 ]. 20 | ^ newArray 21 | ! 22 | METHOD asList 23 | ^ List new addAll: self 24 | ! 25 | METHOD asOrdered 26 | ^ Ordered new addAll: self 27 | ! 28 | METHOD asOrdered: testBlock 29 | ^ ( Ordered new: testBlock ) addAll: self 30 | ! 31 | METHOD asString 32 | | newString index | 33 | newString := String new: self size. 34 | index := 1. 35 | self do: [ :element | newString at: index put: element. 36 | index := index + 1 ]. 37 | ^ newString 38 | ! 39 | METHOD collect: transformBlock 40 | ^ self inject: List new into: [ :list :element | 41 | list add: ( transformBlock value: element ) ] 42 | ! 43 | METHOD find: testBlock ifAbsent: exceptionBlock 44 | self do: [ :element | ( testBlock value: element ) ifTrue: [ ^ element ] ]. 45 | ^ exceptionBlock value 46 | ! 47 | METHOD includes: value 48 | self do: [ :element | element = value ifTrue: [ ^ true ] ]. 49 | ^ false 50 | ! 51 | METHOD includesTest: aBlock 52 | self do: [ :element | ( aBlock value: element ) ifTrue: [ ^ true ] ]. 53 | ^ false 54 | ! 55 | METHOD inject: value into: binaryBlock | result | 56 | result := value. 57 | self do: [ :element | result := binaryBlock value: result value: element ]. 58 | ^ result 59 | ! 60 | METHOD isEmpty 61 | "Return true if there are no elements." 62 | ^ self size = 0. 63 | ! 64 | METHOD printString 65 | ^ ( self inject: '( ' into: [ :str :element | str + element + ' ' ] ) + ' )' 66 | ! 67 | METHOD reject: testBlock 68 | ^ self select: [ :x | ( testBlock value: x ) not ] 69 | ! 70 | METHOD select: testBlock 71 | ^ self inject: List new into: [ :list :element | 72 | ( testBlock value: element ) ifTrue: [ list add: element ]. 73 | list ]. 74 | ! 75 | METHOD size 76 | ^ self inject: 0 into: [ :tally :element | tally + 1 ] 77 | ! 78 | -------------------------------------------------------------------------------- /Smalltalk/Collection/Indexed.st: -------------------------------------------------------------------------------- 1 | CLASS Collection subclass: 'Indexed' variables: '' classVariables: '' 2 | METHOD at: index 3 | ^ self at: index ifAbsent: [ self error: 'Index out of range.' ] 4 | ! 5 | METHOD first 6 | ^ self at: 1. 7 | ! 8 | METHOD last 9 | ^ self at: self size. 10 | ! 11 | METHOD do: aBlock 12 | ^ 1 to: self size do: [ :index | 13 | aBlock value: ( self at: index ) ] 14 | ! 15 | METHOD includesKey: index 16 | ^ index between: 1 and: self size 17 | ! 18 | METHOD indexOf: element ifAbsent: exceptionBlock 19 | "Return the index of the first occurance of element in self, 20 | or exceptionBlock value if not found." 21 | 1 to: self size do: [ :i | 22 | ( element = ( self at: i ) ) ifTrue: [ ^ i ] ]. 23 | ^ exceptionBlock value 24 | ! 25 | METHOD indexOfLast: element ifAbsent: exceptionBlock 26 | "Return the index of the *last* occurance of element in self, 27 | or exceptionBlock value if not found." 28 | | index | 29 | index := self size. 30 | [ index >= 1 ] whileTrue: [ 31 | ( self at: index ) = element ifTrue: [ ^ index ]. 32 | index := index - 1 ]. 33 | ^ exceptionBlock value 34 | ! 35 | METHOD indexOf: element match: matchBlock ifAbsent: exceptionBlock 36 | "Return index of the first element for which the matching block returns true. 37 | The block should have 2 arguments and is valued with arg1: search element arg2: collection element." 38 | 1 to: self size do: [ :i | 39 | ( matchBlock value: element value: ( self at: i ) ) ifTrue: [ ^ i ] ]. 40 | ^ exceptionBlock value 41 | ! 42 | METHOD reverseDo: aBlock 43 | ^ ( 1 to: self size ) reverseDo: [ :i | 44 | aBlock value: ( self at: i ) ]. 45 | ! 46 | METHOD with: aCollection pad: aValue do: aBlock 47 | | selfSize argSize | 48 | selfSize := self size. 49 | argSize := aCollection size. 50 | 1 to: ( selfSize max: argSize ) do: [ :index | 51 | aBlock 52 | value: ( index <= selfSize ifTrue: [ self at: index ] ifFalse: [ aValue ] ) 53 | value: ( index <= argSize ifTrue: [ aCollection at: index ] ifFalse: [ aValue ] ) ]. 54 | ! 55 | -------------------------------------------------------------------------------- /Smalltalk/Collection/Interval.st: -------------------------------------------------------------------------------- 1 | CLASS Collection subclass: 'Interval' variables: 'low high step' classVariables: '' 2 | META from: aLow to: aHigh by: aStep 3 | | newInterval | 4 | newInterval := self new. 5 | self in: newInterval at: 1 put: aLow. 6 | self in: newInterval at: 2 put: aHigh. 7 | self in: newInterval at: 3 put: aStep. 8 | ^ newInterval. 9 | ! 10 | METHOD do: aBlock 11 | | current | 12 | current := low. 13 | [ current <= high ] whileTrue: [ 14 | aBlock value: current. 15 | current := current + step ]. 16 | ! 17 | METHOD reverseDo: aBlock 18 | | current | 19 | current := high. 20 | [ current >= low ] whileTrue: [ 21 | aBlock value: current. 22 | current := current - step ]. 23 | ! 24 | -------------------------------------------------------------------------------- /Smalltalk/Collection/List.st: -------------------------------------------------------------------------------- 1 | CLASS Indexed subclass: 'List' variables: 'values current' classVariables: '' 2 | META new 3 | ^ self in: ( self in: super new at: 1 put: ( Array new: 5 ) ) at: 2 put: 0 4 | ! 5 | METHOD add: newElement 6 | ( current = values size ) ifTrue: [ self reallocate ]. 7 | current := current + 1. 8 | values at: current put: newElement 9 | ! 10 | METHOD addFirst: newElement 11 | self insert: newElement at: 1 12 | ! 13 | METHOD at: position ifAbsent: exceptionBlock 14 | ^ ( values includesKey: position ) 15 | ifTrue: [ values at: position ifAbsent: exceptionBlock ] 16 | ifFalse: [ exceptionBlock value ] 17 | ! 18 | METHOD at: position put: newElement 19 | ( values includesKey: position ) 20 | ifTrue: [ values at: position put: newElement ] 21 | ifFalse: [ self error: 'Index error' ] 22 | ! 23 | METHOD insert: value at: position 24 | ( ( position < 1 ) or: [ position > ( current + 1 ) ] ) 25 | ifTrue: [ self error: 'invalid index for insert:at:' ]. 26 | ( current = values size ) ifTrue: [ self reallocate ]. 27 | ( position to: current ) reverseDo: 28 | [ :i | values at: i+1 put: ( values at: i ) ]. 29 | current := current + 1. 30 | values at: position put: value 31 | ! 32 | METHOD printString 33 | ^ self class name + super printString 34 | ! 35 | METHOD reallocate 36 | | newArray | 37 | newArray := Array new: 2 * values size. 38 | 1 to: values size do: [ :i | newArray at: i put: ( values at: i ) ]. 39 | values := newArray 40 | ! 41 | METHOD remove: element 42 | self remove: element ifAbsent: [ nil ]. 43 | ! 44 | METHOD remove: element ifAbsent: exceptionBlock 45 | self removeAt: 46 | ( self indexOf: element ifAbsent: [ ^ exceptionBlock value ] ) 47 | ! 48 | METHOD removeAt: index 49 | ( index between: 1 and: current ) 50 | ifFalse: [ self error: 'invalid index for removeAt:' ]. 51 | current := current - 1. 52 | index to: current do: [ :i | values at: i put: ( values at: i+1 ) ] 53 | ! 54 | METHOD size 55 | ^ current 56 | ! 57 | -------------------------------------------------------------------------------- /Smalltalk/Collection/Ordered.st: -------------------------------------------------------------------------------- 1 | CLASS List subclass: 'Ordered' variables: 'testBlock' classVariables: '' 2 | META new 3 | ^ self new: [ :a :b | a < b ]. 4 | ! 5 | META new: testBlock 6 | ^ self in: super new at: 3 put: testBlock. 7 | ! 8 | METHOD add: newElement 9 | super add: newElement. 10 | (2 to: current) reverseDo: [:i | 11 | (testBlock value: newElement value: (values at: i-1)) 12 | ifTrue: [ values at: i put: (values at: i-1) ] 13 | ifFalse: [ ^ values at: i put: newElement] ]. 14 | values at: 1 put: newElement. 15 | ! 16 | METHOD at: index put: value 17 | self error: 'Cannot insert into ordered collection using at:' 18 | ! 19 | METHOD insert: value at: index 20 | self error: 'Cannot insert into ordered collection using insert:' 21 | ! 22 | -------------------------------------------------------------------------------- /Smalltalk/Collection/String.st: -------------------------------------------------------------------------------- 1 | CLASS Array subclass: 'String' variables: '' classVariables: '' 2 | META new: aSize 3 | ^ < 20 String aSize >. 4 | ! 5 | METHOD + arg 6 | " optimized by primitive for speed " 7 | ^ < 24 self ( arg printString ) >. 8 | ! 9 | METHOD < arg 10 | ^ < 26 self ( arg printString ) > < 0. 11 | ! 12 | METHOD = arg 13 | ^ < 26 self ( arg printString ) > = 0. 14 | ! 15 | METHOD at: index ifAbsent: exceptionBlock 16 | ( self includesKey: index ) 17 | ifTrue: [ ^ Char new: < 21 self index > ] 18 | ifFalse: [ ^ exceptionBlock value ] 19 | ! 20 | METHOD at: index put: char 21 | ( self includesKey: index ) ifFalse: [ 22 | ^ self error: 'String indexing error: ' + index ]. 23 | < 22 self index ( char value ) >. 24 | ! 25 | METHOD asWords 26 | "Return array of strings containing the words in self separated by spaces." 27 | ^ ( self asWords: ' ' ) asArray. 28 | ! 29 | METHOD asWords: separators 30 | "Return array of strings containing the words in self, 31 | separated by characters in separators string parameter." 32 | | words word | 33 | word := ''. 34 | words := List new. 35 | self do: [ :char | 36 | ( separators includes: char ) 37 | ifTrue: [ 38 | ( word size > 0 ) ifTrue: [ 39 | "Found a word." 40 | words add: word. 41 | word := '' ] ] 42 | ifFalse: [ 43 | word := word + char asString ] ]. 44 | "Add possible last word." 45 | word size > 0 ifTrue: [ 46 | words add: word ]. 47 | ^ words. 48 | ! 49 | METHOD copy 50 | "Make a clone of ourself." 51 | ^ < 23 self >. 52 | ! 53 | METHOD doIt 54 | | method | 55 | method := Object parseMethod: 'doItCommand ^ ' + self. 56 | method notNil ifTrue: [ 57 | ^ Context new perform: method withArguments: ( Array new: 0 ) ]. 58 | ! 59 | METHOD find: substr 60 | 1 to: ( self size - substr size + 1 ) do: [ :i | 61 | ( self from: i size: substr size ) = substr ifTrue: [ ^ i ] ]. 62 | ^ nil. 63 | ! 64 | METHOD last: n 65 | ^ self from: self size - n + 1 to: self size. 66 | ! 67 | METHOD printString 68 | ^ self. 69 | ! 70 | METHOD size 71 | ^ < 4 self >. 72 | ! 73 | METHOD trim 74 | "Answer new string with leading and trainling spaces removed." 75 | | startPos endPos | 76 | startPos := 1. 77 | [ startPos <= self size and: [ ( self at: startPos ) isBlank ] ] whileTrue: [ 78 | startPos := startPos + 1 ]. 79 | 80 | endPos := self size. 81 | [ endPos > startPos and: [ ( self at: endPos ) isBlank ] ] whileTrue: [ 82 | endPos := endPos - 1 ]. 83 | 84 | ^ self from: startPos to: endPos. 85 | ! 86 | METHOD asLowerCase 87 | "Return copy of string with uppercase characters converted tot lower case." 88 | | result | 89 | result := String new: self size. 90 | 1 to: self size do: [ :index | 91 | result at: index put: ( self at: index ) lowerCase ]. 92 | ^ result. 93 | ! 94 | -------------------------------------------------------------------------------- /Smalltalk/Compiler/ArgumentNode.st: -------------------------------------------------------------------------------- 1 | CLASS ParserNode subclass: 'ArgumentNode' variables: 'position' classVariables: '' 2 | METHOD position: p 3 | position := p 4 | ! 5 | METHOD isSuper 6 | ^ position = 0 7 | ! 8 | METHOD compile: encoder block: inBlock 9 | position = 0 10 | ifTrue: [ encoder genHigh: 2 low: 0 ] 11 | ifFalse: [ encoder genHigh: 2 low: position - 1 ] 12 | ! 13 | -------------------------------------------------------------------------------- /Smalltalk/Compiler/AssignNode.st: -------------------------------------------------------------------------------- 1 | CLASS ParserNode subclass: 'AssignNode' variables: 'target expression' classVariables: '' 2 | METHOD target: t expression: e 3 | target := t. 4 | expression := e. 5 | ! 6 | METHOD compile: encoder block: inBlock 7 | expression compile: encoder block: inBlock. 8 | target assign: encoder 9 | ! 10 | -------------------------------------------------------------------------------- /Smalltalk/Compiler/BlockNode.st: -------------------------------------------------------------------------------- 1 | CLASS ParserNode subclass: 'BlockNode' variables: 'statements temporaryLocation' classVariables: '' 2 | METHOD statements: s temporaryLocation: t 3 | statements := s. 4 | temporaryLocation := t 5 | ! 6 | METHOD compileInLine: encoder block: inBlock 7 | statements do: [ :stmt | 8 | stmt compile: encoder block: inBlock. 9 | encoder genHigh: 15 low: 5 " pop top " ]. 10 | encoder backUp 11 | ! 12 | METHOD isBlock 13 | ^ true 14 | ! 15 | METHOD compile: encoder block: inBlock 16 | | patchLocation | 17 | encoder genHigh: 12 low: temporaryLocation. 18 | patchLocation := encoder genCode: 0. 19 | self compileInLine: encoder block: true. 20 | encoder genHigh: 15 low: 2. " return top of stack " 21 | encoder patch: patchLocation. 22 | ! 23 | -------------------------------------------------------------------------------- /Smalltalk/Compiler/BodyNode.st: -------------------------------------------------------------------------------- 1 | CLASS ParserNode subclass: 'BodyNode' variables: 'statements' classVariables: '' 2 | METHOD statements: s 3 | statements := s. 4 | ! 5 | METHOD compile: encoder block: inBlock 6 | statements do: [ :stmt | 7 | stmt compile: encoder block: inBlock. 8 | encoder genHigh: 15 low: 5 " pop "]. 9 | encoder genHigh: 15 low: 1 " return self " 10 | ! 11 | -------------------------------------------------------------------------------- /Smalltalk/Compiler/ClassParser.st: -------------------------------------------------------------------------------- 1 | CLASS Object subclass: 'ClassParser' variables: 'file lineNum' classVariables: '' 2 | "Parse class from source file" 3 | META fileIn: fileName 4 | ^ self new fileIn: fileName. 5 | ! 6 | META fileInAll 7 | "File-in (update) all known classes from their source files." 8 | Class classes do: [ :class | 9 | self fileIn: class sourceFileName ]. 10 | ! 11 | METHOD error: message 12 | "Report parse error with some added info." 13 | super error: 'Class.fileIn: Line: ' + lineNum + ', error: ' + message. 14 | ! 15 | METHOD fileIn: fileName 16 | | line class classMethods instanceMethods method | 17 | "File-in the argument Smaltalk class. 18 | Raises error on parse failure." 19 | System out println: 'ClassParser.FileIn: ' + fileName. 20 | 21 | lineNum := 0. 22 | file := File openRead: fileName. 23 | 24 | class := self parseClass: self readLine. 25 | class sourceFileName: fileName. 26 | 27 | classMethods := Ordered new: [ :a :b | a name < b name ]. 28 | instanceMethods := Ordered new: [ :a :b | a name < b name ]. 29 | 30 | [ ( line := self readLine ) = nil ] whileFalse: [ 31 | method := self parseMethod: line type: 'META' class: class class. 32 | method ifNotNil: [ classMethods add: method ]. 33 | 34 | method := self parseMethod: line type: 'METHOD' class: class. 35 | method ifNotNil: [ instanceMethods add: method ] ]. 36 | 37 | "Set class methods to only those that were filed-in, removing others. 38 | Removing methods afterwards like this is needed to enable filing-in critical base- and compiler classes." 39 | class class methods: classMethods asArray. 40 | class methods: instanceMethods asArray. 41 | ! 42 | METHOD parseClass: line 43 | "Parse the CLASS line. 44 | This should be in the first line in the file. 45 | Raise error if parsing fails." 46 | | keyword | 47 | keyword := 'CLASS'. 48 | ( line isNil or: [ ( line from: 1 to: keyword size ) ~= keyword ] ) ifTrue: [ 49 | self error: 'CLASS keyword not found on start of first line' ]. 50 | 51 | ^ ( line from: keyword size + 1 to: line size ) doIt. 52 | ! 53 | METHOD parseMethod: line type: type class: class 54 | "Try to parse [ META | METHOD ] < method name and args > \n !. 55 | Return true on succesful parse, false otherwise." 56 | | methodLineNum methodHeader method | 57 | ( line from: 1 to: type size ) = type ifFalse: [ ^ nil ]. 58 | methodLineNum := lineNum. 59 | methodHeader := ( line from: type size + 1 to: line size ) trim + Char newline asString. 60 | method := class compileMethod: ( methodHeader + self readMethodBody ). 61 | method lineNum: methodLineNum. 62 | ^ method. 63 | ! 64 | METHOD readMethodBody 65 | "Read method source upto next '!' line." 66 | | newline methodSource line | 67 | newline := Char newline asString. 68 | methodSource := ''. 69 | [ ( line := self readLine ) = nil ] whileFalse: [ 70 | line = '!' ifTrue: [ ^ methodSource ]. 71 | methodSource := methodSource + line + newline ]. 72 | 73 | self error: 'Failed to find method end marker: "!"'. 74 | ! 75 | METHOD readLine 76 | "Read next line from file, increasing line number. 77 | Return nil on end of file." 78 | | line | 79 | line := file readLine. 80 | line ifNil: [ ^ nil ]. 81 | lineNum := lineNum + 1. 82 | ^ line. 83 | ! 84 | -------------------------------------------------------------------------------- /Smalltalk/Compiler/ClassVarNode.st: -------------------------------------------------------------------------------- 1 | CLASS ParserNode subclass: 'ClassVarNode' variables: 'position' classVariables: '' 2 | METHOD compile: encoder block: inBlock 3 | encoder genHigh: 14 low: position - 1. 4 | ! 5 | METHOD position: p 6 | position := p. 7 | ! 8 | -------------------------------------------------------------------------------- /Smalltalk/Compiler/Encoder.st: -------------------------------------------------------------------------------- 1 | CLASS Object subclass: 'Encoder' variables: 'name byteCodes literals stackSize maxStack' classVariables: '' 2 | METHOD backUp 3 | "Back up one instruction." 4 | byteCodes removeAt: byteCodes size 5 | ! 6 | METHOD currentLocation 7 | ^ byteCodes size 8 | ! 9 | METHOD genCode: byte 10 | byteCodes add: byte. 11 | ^ byteCodes size 12 | ! 13 | METHOD genHigh: high low: low 14 | ( low >= 16 ) 15 | ifTrue: [ self genHigh: 0 low: high. self genCode: low ] 16 | ifFalse: [ self genCode: high * 16 + low ] 17 | ! 18 | METHOD genLiteral: aValue 19 | literals := literals add: aValue. 20 | ^ literals size - 1 21 | ! 22 | METHOD method: maxTemps class: c 23 | "Stack size doesn't take into account primitives." 24 | ^ Method name: name byteCodes: byteCodes asByteArray literals: literals 25 | stackSize: maxStack + 5 temporarySize: maxTemps class: c. 26 | ! 27 | METHOD name: n 28 | name := n. 29 | byteCodes := List new. 30 | literals := Array new: 0. 31 | stackSize := 0. 32 | maxStack := 1. 33 | ! 34 | METHOD patch: loc 35 | "Patch a goto from a block." 36 | byteCodes at: loc put: self currentLocation 37 | ! 38 | METHOD popArgs: n 39 | stackSize := stackSize - n. 40 | ! 41 | METHOD pushArgs: n 42 | stackSize := stackSize + n. 43 | maxStack := stackSize max: maxStack 44 | ! 45 | -------------------------------------------------------------------------------- /Smalltalk/Compiler/InstNode.st: -------------------------------------------------------------------------------- 1 | CLASS ParserNode subclass: 'InstNode' variables: 'position' classVariables: '' 2 | METHOD position: aPosition 3 | position := aPosition. 4 | ! 5 | METHOD compile: encoder block: inBlock 6 | encoder genHigh: 1 low: position - 1. 7 | ! 8 | METHOD assign: encoder 9 | encoder genHigh: 6 low: position - 1. 10 | ! 11 | METHOD assignable 12 | ^ true. 13 | ! 14 | -------------------------------------------------------------------------------- /Smalltalk/Compiler/LiteralNode.st: -------------------------------------------------------------------------------- 1 | CLASS ParserNode subclass: 'LiteralNode' variables: 'value' classVariables: '' 2 | METHOD value: aValue 3 | value := aValue. 4 | ! 5 | METHOD compile: encoder block: inBlock 6 | value == nil ifTrue: [ ^ encoder genHigh: 5 low: 10 ]. 7 | value == true ifTrue: [ ^ encoder genHigh: 5 low: 11 ]. 8 | value == false ifTrue: [ ^ encoder genHigh: 5 low: 12 ]. 9 | ( value class == SmallInt and: [ value between: 0 and: 9 ] ) ifTrue: [ 10 | ^ encoder genHigh: 5 low: value ]. 11 | encoder genHigh: 4 low: ( encoder genLiteral: value ). 12 | ! 13 | -------------------------------------------------------------------------------- /Smalltalk/Compiler/MessageNode.st: -------------------------------------------------------------------------------- 1 | CLASS ParserNode subclass: 'MessageNode' variables: 'receiver name arguments lineNum' classVariables: '' 2 | METHOD receiver: r name: n arguments: a 3 | receiver := r. 4 | name := n. 5 | arguments := a 6 | ! 7 | METHOD compile: encoder block: inBlock 8 | receiver isNil 9 | ifTrue: [ ^ self cascade: encoder block: inBlock ]. 10 | ((receiver isBlock and: [ self argumentsAreBlock ]) 11 | and: [name = 'whileTrue:' or: [ name = 'whileFalse:' ] ] ) 12 | ifTrue: [ ^ self optimizeWhile: encoder block: inBlock ]. 13 | receiver compile: encoder block: inBlock. 14 | receiver isSuper 15 | ifTrue: [ ^ self sendToSuper: encoder block: inBlock ]. 16 | name = 'isNil' ifTrue: [ ^ encoder genHigh: 10 low: 0 ]. 17 | name = 'notNil' ifTrue: [ ^ encoder genHigh: 10 low: 1 ]. 18 | self compile2: encoder block: inBlock 19 | ! 20 | METHOD compile2: encoder block: inBlock 21 | self argumentsAreBlock ifTrue: [ 22 | name = 'ifTrue:' ifTrue: [ ^ self compile: encoder 23 | test: 8 constant: 10 block: inBlock ]. 24 | name = 'ifFalse:' ifTrue: [ ^ self compile: encoder 25 | test: 7 constant: 10 block: inBlock ]. 26 | name = 'and:' ifTrue: [ ^ self compile: encoder 27 | test: 8 constant: 12 block: inBlock ]. 28 | name = 'or:' ifTrue: [ ^ self compile: encoder 29 | test: 7 constant: 11 block: inBlock ]. 30 | name = 'ifTrue:ifFalse:' 31 | ifTrue: [ ^ self optimizeIf: encoder block: inBlock ]. 32 | ]. 33 | self evaluateArguments: encoder block: inBlock. 34 | name = '<' ifTrue: [ ^ encoder genHigh: 11 low: 0]. 35 | name = '<=' ifTrue: [ ^ encoder genHigh: 11 low: 1]. 36 | name = '+' ifTrue: [ ^ encoder genHigh: 11 low: 2]. 37 | self sendMessage: encoder block: inBlock 38 | ! 39 | METHOD sendToSuper: encoder block: inBlock 40 | self evaluateArguments: encoder block: inBlock. 41 | encoder genHigh: 8 low: 1 + arguments size. 42 | encoder genHigh: 15 low: 11. 43 | encoder genCode: ( encoder genLiteral: name ) 44 | ! 45 | METHOD cascade: encoder block: inBlock 46 | self evaluateArguments: encoder block: inBlock. 47 | self sendMessage: encoder block: inBlock 48 | ! 49 | METHOD evaluateArguments: encoder block: inBlock 50 | encoder pushArgs: 1 + arguments size. 51 | arguments do: [ :arg | 52 | arg compile: encoder block: inBlock ] 53 | ! 54 | METHOD sendMessage: encoder block: inBlock 55 | encoder popArgs: arguments size. 56 | " mark arguments, then send message " 57 | encoder genHigh: 8 low: 1 + arguments size. 58 | encoder genHigh: 9 low: (encoder genLiteral: name) 59 | ! 60 | METHOD argumentsAreBlock 61 | arguments do: [ :arg | arg isBlock ifFalse: [ ^ false ] ]. 62 | ^ true 63 | ! 64 | METHOD optimizeWhile: encoder block: inBlock 65 | | start save | 66 | start := encoder currentLocation. 67 | receiver compileInLine: encoder block: inBlock. 68 | name = 'whileTrue:' " branch if false/true " 69 | ifTrue: [ encoder genHigh: 15 low: 8 ] 70 | ifFalse: [ encoder genHigh: 15 low: 7 ]. 71 | save := encoder genCode: 0. 72 | (arguments at: 1) compileInLine: encoder block: inBlock. 73 | encoder genHigh: 15 low: 5. " pop from stack " 74 | encoder genHigh: 15 low: 6. " branch " 75 | encoder genCode: start. " branch target " 76 | encoder patch: save. 77 | encoder genHigh: 5 low: 10 " push nil " 78 | ! 79 | METHOD compile: encoder test: t constant: c block: inBlock 80 | | save ssave | 81 | encoder genHigh: 15 low: t. " branch test " 82 | save := encoder genCode: 0. 83 | (arguments at: 1) compileInLine: encoder block: inBlock. 84 | encoder genHigh: 15 low: 6. " branch " 85 | ssave := encoder genCode: 0. 86 | encoder patch: save. 87 | encoder genHigh: 5 low: c. " push constant " 88 | encoder patch: ssave 89 | ! 90 | METHOD optimizeIf: encoder block: inBlock 91 | | save ssave | 92 | encoder genHigh: 15 low: 8. " branch if false test " 93 | save := encoder genCode: 0. 94 | (arguments at: 1) compileInLine: encoder block: inBlock. 95 | encoder genHigh: 15 low: 6. " branch " 96 | ssave := encoder genCode: 0. 97 | encoder patch: save. 98 | (arguments at: 2) compileInLine: encoder block: inBlock. 99 | encoder patch: ssave 100 | ! 101 | -------------------------------------------------------------------------------- /Smalltalk/Compiler/ParserNode.st: -------------------------------------------------------------------------------- 1 | CLASS Object subclass: 'ParserNode' variables: '' classVariables: '' 2 | METHOD isSuper 3 | ^ false. 4 | ! 5 | METHOD isBlock 6 | ^ false. 7 | ! 8 | METHOD assignable 9 | ^ false. 10 | ! 11 | -------------------------------------------------------------------------------- /Smalltalk/Compiler/PrimitiveNode.st: -------------------------------------------------------------------------------- 1 | CLASS ParserNode subclass: 'PrimitiveNode' variables: 'number arguments' classVariables: '' 2 | METHOD number: n arguments: a 3 | number := n. 4 | arguments := a. 5 | ! 6 | METHOD compile: encoder block: inBlock 7 | arguments do: [ :a | a compile: encoder block: inBlock ]. 8 | encoder genHigh: 13 low: arguments size. 9 | encoder genCode: number. 10 | ! 11 | -------------------------------------------------------------------------------- /Smalltalk/Compiler/ReturnNode.st: -------------------------------------------------------------------------------- 1 | CLASS ParserNode subclass: 'ReturnNode' variables: 'expression' classVariables: '' 2 | METHOD expression: e 3 | expression := e 4 | ! 5 | METHOD compile: encoder block: inBlock 6 | expression compile: encoder block: inBlock. 7 | inBlock 8 | ifTrue: [ encoder genHigh: 15 low: 3 " block return " ] 9 | ifFalse: [ encoder genHigh: 15 low: 2 " stack return " ]. 10 | ! 11 | -------------------------------------------------------------------------------- /Smalltalk/Compiler/TemporaryNode.st: -------------------------------------------------------------------------------- 1 | CLASS ParserNode subclass: 'TemporaryNode' variables: 'position' classVariables: '' 2 | METHOD position: p 3 | position := p 4 | ! 5 | METHOD compile: encoder block: inBlock 6 | encoder genHigh: 3 low: position - 1 7 | ! 8 | METHOD assignable 9 | ^ true 10 | ! 11 | METHOD assign: encoder 12 | encoder genHigh: 7 low: position - 1 13 | ! 14 | -------------------------------------------------------------------------------- /Smalltalk/Component/Border.st: -------------------------------------------------------------------------------- 1 | CLASS JavaObject subclass: 'Border' variables: '' classVariables: '' 2 | "Implements javax.swing.border.AbstractBorder subclasses." 3 | META createTitledBorder: title 4 | "TitledBorder javax.swing.BorderFactory.createTitledBorder( String title )" 5 | ^ < 39 self 'javax.swing.BorderFactory' 'createTitledBorder' title >. 6 | ! 7 | -------------------------------------------------------------------------------- /Smalltalk/Component/BorderLayout.st: -------------------------------------------------------------------------------- 1 | CLASS JavaObject subclass: 'BorderLayout' variables: '' classVariables: '' 2 | "Implements java.awt.BorderLayout." 3 | META new 4 | "BorderLayout()" 5 | ^ < 37 self 'java.awt.BorderLayout' >. 6 | ! 7 | META gap: point 8 | "BorderLayout( int hgap, int vgap )" 9 | ^ < 37 self 'java.awt.BorderLayout' ( point x ) ( point y ) >. 10 | ! 11 | META center 12 | ^ 'Center'. 13 | ! 14 | META north 15 | ^ 'North'. 16 | ! 17 | META south 18 | ^ 'South'. 19 | ! 20 | META east 21 | ^ 'East'. 22 | ! 23 | META west 24 | ^ 'West'. 25 | ! 26 | META emptyBorder: insets 27 | "javax.swing.border.EmptyBorder( Insets insets )" 28 | ^ < 37 JavaObject 'javax.swing.border.EmptyBorder' insets >. 29 | ! 30 | -------------------------------------------------------------------------------- /Smalltalk/Component/Button.st: -------------------------------------------------------------------------------- 1 | CLASS Component subclass: 'Button' variables: '' classVariables: '' 2 | "Implements javax.swing.JButton." 3 | META new 4 | "JButton()" 5 | ^ < 37 self 'javax.swing.JButton' >. 6 | ! 7 | METHOD text: text action: action 8 | "Convenience method for setting text and action with one call." 9 | self text: text. 10 | self action: action. 11 | ! 12 | METHOD text: text 13 | "void setText( String text )" 14 | < 38 nil self 'setText' text >. 15 | 16 | "Set first character as default shortcut key, for now." 17 | self setMnemonic: ( text at: 1 ). 18 | ! 19 | METHOD action: block 20 | < 42 self 2 block ActionEvent >. 21 | ! 22 | METHOD setMnemonic: char 23 | "setMnemonic( int mnemonic )" 24 | < 38 nil self 'setMnemonic' ( char value ) >. 25 | ! 26 | -------------------------------------------------------------------------------- /Smalltalk/Component/Color.st: -------------------------------------------------------------------------------- 1 | CLASS JavaObject subclass: 'Color' variables: 'red green blue' classVariables: '' 2 | "Implements java.awt.Color. 3 | Also maintains red green and blue color components dor speed. 4 | Objects of this class are immutable." 5 | META new 6 | self error: 'Color instances cannot be created with new.'. 7 | ! 8 | META red: red green: green blue: blue 9 | "Color( int red, int green, int blue )" 10 | ^ < 37 Color 'java.awt.Color' red green blue > 11 | red: red green: green blue: blue. 12 | ! 13 | META black 14 | ^ self red: 0 green: 0 blue: 0. 15 | ! 16 | META blue 17 | ^ self red: 0 green: 0 blue: 255. 18 | ! 19 | META green 20 | ^ self red: 0 green: 255 blue: 0. 21 | ! 22 | META red 23 | ^ self red: 255 green: 0 blue: 0. 24 | ! 25 | META white 26 | ^ self red: 255 green: 255 blue: 255. 27 | ! 28 | METHOD red: aRed green: aGreen blue: aBlue 29 | "Private - Set interal color components. 30 | Should only be called in constructor because we are immutable." 31 | red := aRed. 32 | green := aGreen. 33 | blue := aBlue. 34 | ! 35 | METHOD asInteger 36 | "Note: Left to right evaluation order, no operator precedence." 37 | ^ red * 256 + green * 256 + blue. 38 | ! 39 | METHOD printString 40 | ^ 'Color [ red: ' + red + ', green: ' + green + ', blue: ' + blue + ' ]'. 41 | ! 42 | METHOD red 43 | ^ red. 44 | ! 45 | METHOD green 46 | ^ green. 47 | ! 48 | METHOD blue 49 | ^ blue. 50 | ! 51 | -------------------------------------------------------------------------------- /Smalltalk/Component/Component.st: -------------------------------------------------------------------------------- 1 | CLASS JavaObject subclass: 'Component' variables: '' classVariables: '' 2 | "Implements: java.awt.Component, java.awt.Container, javax.swing.JComponent. 3 | So is a base class for Smalltalk wrappers for Java GUI (J)Components." 4 | META new 5 | ^ self error: 'Component instances should be created with primitive 37 to pair them with Java objects.'. 6 | ! 7 | METHOD add: component 8 | "Component add( Component comp )" 9 | component ifNotNil: [ 10 | < 38 nil self 'add' component > ]. 11 | ! 12 | METHOD add: component constraints: constraints 13 | "public void add( Component comp, Object constraints )" 14 | component ifNotNil: [ 15 | < 38 nil self 'add' component constraints > ]. 16 | ! 17 | METHOD background: color 18 | "void setBackground( Color color )" 19 | < 38 nil self 'setBackground' color >. 20 | ! 21 | METHOD border: border 22 | "void setBorder( Border border )" 23 | < 38 nil self 'setBorder' border >. 24 | ! 25 | METHOD font 26 | "Font getFont()" 27 | ^ < 38 Font self 'getFont' >. 28 | ! 29 | METHOD font: font 30 | "void setFont( Font font )" 31 | < 38 nil self 'setFont' font >. 32 | ! 33 | METHOD onMousePressed: block 34 | < 42 self 4 block MouseEvent >. 35 | ! 36 | METHOD onMouseClicked: block 37 | < 42 self 8 block MouseEvent >. 38 | ! 39 | METHOD onMouseReleased: block 40 | < 42 self 5 block MouseEvent >. 41 | ! 42 | METHOD onMouseMoved: block 43 | < 42 self 6 block MouseEvent >. 44 | ! 45 | METHOD repaint 46 | "void repaint()" 47 | < 38 nil self 'repaint' >. 48 | ! 49 | METHOD requestFocus 50 | "void requestFocus()" 51 | < 38 nil self 'requestFocus' >. 52 | ! 53 | METHOD repaint 54 | "public void repaint()" 55 | < 38 nil self 'repaint' >. 56 | ! 57 | -------------------------------------------------------------------------------- /Smalltalk/Component/Font.st: -------------------------------------------------------------------------------- 1 | CLASS JavaObject subclass: 'Font' variables: '' classVariables: '' 2 | "Implements java.awt.Font. 3 | This class is immutable, so changes return new instances. 4 | Font styles: 0 = PLAIN, 1= BOLD, 3 = ITALIC" 5 | META name: aName style: aStyle size: aSize 6 | "Font( String name, int style, int size )" 7 | ^ < 37 self 'java.awt.Font' aName aStyle aSize >. 8 | ! 9 | METHOD style: style 10 | "Return copy of font with style set to argument. 11 | Font deriveFont( int style )" 12 | ^ < 38 Font self 'deriveFont' style >. 13 | ! 14 | -------------------------------------------------------------------------------- /Smalltalk/Component/Frame.st: -------------------------------------------------------------------------------- 1 | CLASS Component subclass: 'Frame' variables: '' classVariables: '' 2 | "Implements Java javax.swing.JFrame class." 3 | META new 4 | ^ < 37 self 'javax.swing.JFrame' > setDefaultIcon center 5 | ! 6 | METHOD menuBar: menuBar 7 | "void setJMenuBar( JMenuBar menuBar )" 8 | < 38 nil self 'setJMenuBar' menuBar >. 9 | ! 10 | METHOD center 11 | "void setLocationRelativeTo( null )" 12 | < 38 nil self 'setLocationRelativeTo' nil >. 13 | ! 14 | METHOD close 15 | self visible: false. 16 | ! 17 | METHOD visible: aBoolean 18 | "public void setVisible( boolean b )" 19 | < 38 nil self 'setVisible' aBoolean >. 20 | ! 21 | METHOD onClosing: block 22 | "void addWindowListener( WindowListener l ) 23 | WindowAdapter.windowClosing( WindowEvent e )" 24 | < 42 self 1 block WindowEvent >. 25 | ! 26 | METHOD add: component 27 | "Component.add( Component child )" 28 | < 38 nil ( self contentPane ) 'add' component >. 29 | ! 30 | METHOD contentPane 31 | "public Container getContentPane()" 32 | ^ < 38 JavaObject self 'getContentPane' >. 33 | ! 34 | METHOD show 35 | self center. 36 | self visible: true. 37 | ! 38 | METHOD pack 39 | "void pack()" 40 | < 38 nil self 'pack' >. 41 | ! 42 | METHOD setDefaultCloseOperation: operation 43 | "public void setDefaultCloseOperation( int operation ) 44 | 0 = DO_NOTHING_ON_CLOSE, 1 = HIDE_ON_CLOSE, 2 = DISPOSE_ON_CLOSE, 3 = EXIT_ON_CLOSE" 45 | < 38 nil self 'setDefaultCloseOperation' operation >. 46 | ! 47 | METHOD setSize: size 48 | "public void setSize( int width, int height )" 49 | < 38 nil self 'setSize' ( size x ) ( size y ) >. 50 | ! 51 | METHOD title: title 52 | "public void setTitle( String title )" 53 | < 38 nil self 'setTitle' title >. 54 | ! 55 | METHOD setDefaultIcon 56 | "Set frame icon to default icon from resources." 57 | | file image | 58 | file := File name: 'SmallJ.png'. 59 | file exists ifTrue: [ 60 | image := < 39 Image 'javax.imageio.ImageIO' 'read' file >. 61 | < 38 nil self 'setIconImage' image > ]. 62 | ! 63 | -------------------------------------------------------------------------------- /Smalltalk/Component/GridBagConstraints.st: -------------------------------------------------------------------------------- 1 | CLASS JavaObject subclass: 'GridBagConstraints' variables: '' classVariables: '' 2 | "Implements java.awt.GridBagConstraints." 3 | META new 4 | "GridBagConstraints()" 5 | ^ < 37 self 'java.awt.GridBagConstraints' >. 6 | ! 7 | META grid: grid size: aSize weight: weight anchor: anchor fill: fill insets: insets ipad: ipad 8 | "GridBagConstraints​( int gridX, int gridY, int gridWidth, int gridHeight, 9 | double weightX, double weightY, int anchor, int fill, Insets insets, int ipadx, int ipady )" 10 | ^ < 37 self 'java.awt.GridBagConstraints' ( grid x ) ( grid y ) ( aSize x ) ( aSize y ) 11 | ( weight x ) ( weight y ) anchor fill insets ( ipad x ) ( ipad y ) >. 12 | ! 13 | META west 14 | "GridBagConstraints.WEST" 15 | ^ 17. 16 | ! 17 | META horizontal 18 | "GridBagConstraints.HORIZONTAL" 19 | ^ 2. 20 | ! 21 | META none 22 | "GridBagConstraints.NONE" 23 | ^ 0. 24 | ! 25 | META both 26 | "GridBagConstraints.BOTH" 27 | ^ 1. 28 | ! 29 | -------------------------------------------------------------------------------- /Smalltalk/Component/GridBagLayout.st: -------------------------------------------------------------------------------- 1 | CLASS JavaObject subclass: 'GridBagLayout' variables: '' classVariables: '' 2 | "Implements java.awt.GridBagLayout." 3 | META new 4 | "GridBagLayout()" 5 | ^ < 37 GridBagLayout 'java.awt.GridBagLayout' >. 6 | ! 7 | -------------------------------------------------------------------------------- /Smalltalk/Component/GridLayout.st: -------------------------------------------------------------------------------- 1 | CLASS JavaObject subclass: 'GridLayout' variables: '' classVariables: '' 2 | "Implements java.awt.GridLayout." 3 | META size: point 4 | "JPanel( new java.awt.GridLayout( rows, columns ) )" 5 | ^ < 37 JavaObject 'java.awt.GridLayout' ( point y ) ( point x ) >. 6 | ! 7 | -------------------------------------------------------------------------------- /Smalltalk/Component/Image.st: -------------------------------------------------------------------------------- 1 | CLASS Component subclass: 'Image' variables: 'graphics' classVariables: '' 2 | "Implements java.awt.image.BufferedImage. 3 | Also encapsulates java.awt.Graphics2D for manipulating the image." 4 | META size: aSize 5 | "Initialize blank image with argument size." 6 | | width height | 7 | width := aSize x. 8 | height := aSize y. 9 | "BufferedImage( int width, int height, int imageType ) 10 | imageType: 1 = TYPE_INT_RGB, see others in Java documentation for ColorSpace." 11 | ^ < 37 Image 'java.awt.image.BufferedImage' width height 1 >. 12 | ! 13 | META fromFile: aFileName 14 | | fileInputStream | 15 | "public FileInputStream( String name )" 16 | fileInputStream := < 37 File 'java.io.FileInputStream' aFileName >. 17 | "public static BufferedImage read( InputStream input )" 18 | ^ < 39 Image 'javax.imageio.ImageIO' 'read' fileInputStream >. 19 | ! 20 | METHOD graphics 21 | "Private - Return graphics member for image manipulation. 22 | Create and remember it if it was not set yet." 23 | graphics ifNil: [ 24 | graphics := < 38 JavaObject self 'createGraphics' > ]. 25 | ^ graphics. 26 | ! 27 | METHOD at: loc drawLine: to 28 | < 38 nil ( self graphics ) 'drawLine' ( loc x ) ( loc y ) ( to x ) ( to y ) >. 29 | ! 30 | METHOD at: loc drawOval: size 31 | < 38 nil ( self graphics ) 'drawOval' ( loc x ) ( loc y ) ( size x ) ( size y ) >. 32 | ! 33 | METHOD at: loc drawRect: size 34 | < 38 nil ( self graphics ) 'drawRect' ( loc x ) ( loc y ) ( size x ) ( size y ) >. 35 | ! 36 | METHOD at: loc fillOval: size 37 | < 38 nil ( self graphics ) 'fillOval' ( loc x ) ( loc y ) ( size x ) ( size y ) >. 38 | ! 39 | METHOD at: loc fillRect: size 40 | < 38 nil ( self graphics ) 'fillRect' ( loc x ) ( loc y ) ( size x ) ( size y ) >. 41 | ! 42 | METHOD at: loc text: text 43 | < 38 nil ( self graphics ) 'drawString' text ( loc x ) ( loc y ) >. 44 | ! 45 | METHOD setColor: color 46 | < 38 nil ( self graphics ) 'setColor' color >. 47 | ! 48 | -------------------------------------------------------------------------------- /Smalltalk/Component/Insets.st: -------------------------------------------------------------------------------- 1 | CLASS JavaObject subclass: 'Insets' variables: 'top left bottom right' classVariables: '' 2 | "Implements java.awt.Insets" 3 | META top: top left: left bottom: bottom right: right 4 | "Insets​( int top, int left, int bottom, int right )" 5 | ^ < 37 self 'java.awt.Insets' top left bottom right >. 6 | ! 7 | -------------------------------------------------------------------------------- /Smalltalk/Component/JPoint.st: -------------------------------------------------------------------------------- 1 | CLASS JavaObject subclass: 'JPoint' variables: '' classVariables: '' 2 | "Implements java.awt.Point. 3 | Note: The @ operator constructs instances of the Point class." 4 | META x: x y: y 5 | ^ < 37 self 'java.awt.Point' x y >. 6 | ! 7 | METHOD printString 8 | ^ self x printString + ' @ ' + self y printString. 9 | ! 10 | METHOD x 11 | ^ < 40 SmallInt self 'x' >. 12 | ! 13 | METHOD y 14 | ^ < 40 SmallInt self 'y' >. 15 | ! 16 | -------------------------------------------------------------------------------- /Smalltalk/Component/Label.st: -------------------------------------------------------------------------------- 1 | CLASS Component subclass: 'Label' variables: '' classVariables: '' 2 | "Implements javax.swing.JLabel." 3 | META new 4 | "JLabel()" 5 | ^ < 37 self 'javax.swing.JLabel'>. 6 | ! 7 | METHOD text: text 8 | "void setText( String text )" 9 | < 38 nil self 'setText' text >. 10 | ! 11 | METHOD image: image 12 | "Set image in label using Java Icon." 13 | | imageIcon | 14 | 15 | "Must create intermediate ImageIcon first. 16 | ImageIcon( Image image )" 17 | imageIcon := < 37 JavaObject 'javax.swing.ImageIcon' image >. 18 | "void setIcon( Icon icon )" 19 | < 38 nil self 'setIcon' imageIcon >. 20 | 21 | "Align image top/left so that mouse coordinates for the label are equal to the image coordinates." 22 | self horizontalAlignment: 2. "left" 23 | self verticalAlignment: 1. "top" 24 | ! 25 | METHOD horizontalAlignment: alignment 26 | "void setHorizontalAlignment( int alignment ) 27 | alignment: 0 = center, 1 = top, 2 = left, 3 = bottom, 4 = right." 28 | < 38 nil self 'setHorizontalAlignment' alignment >. 29 | ! 30 | METHOD verticalAlignment: alignment 31 | "void setVerticalAlignment( int alignment ) 32 | alignment: 0 = center, 1 = top, 2 = left, 3 = bottom, 4 = right." 33 | < 38 nil self 'setVerticalAlignment' alignment >. 34 | ! 35 | -------------------------------------------------------------------------------- /Smalltalk/Component/ListComponent.st: -------------------------------------------------------------------------------- 1 | CLASS Component subclass: 'ListComponent' variables: '' classVariables: '' 2 | "Implements javax.swing.JList" 3 | META new 4 | | listComponent plainFont | 5 | "JList()" 6 | listComponent := < 37 self 'javax.swing.JList' >. 7 | "Set detault font style to plain." 8 | plainFont := listComponent font style: 0. "plain" 9 | ^ listComponent font: plainFont. 10 | ! 11 | METHOD listData: collection 12 | "void setListData( Object[] listData ). 13 | The argument is a Smalltalk collection that is converted to a JavaArray first." 14 | < 38 nil self 'setListData' ( JavaArray from: collection ) >. 15 | ! 16 | METHOD selectionMode: selectionMode 17 | "void setSelectionMode( int selectionMode ) 18 | selectionMode: 0 = int SINGLE_SELECTION, 1 = SINGLE_INTERVAL_SELECTION, 2 = MULTIPLE_INTERVAL_SELECTION" 19 | < 38 nil self 'setSelectionMode' selectionMode >. 20 | ! 21 | METHOD onSelect: block 22 | "On selection change in the list component, evaluate block 23 | with a new instance of ListSelectionEvent as a parameter, containing the event data. 24 | void addListSelectionListener( ListSelectionListener listener ) 25 | block is callded with selectedIndex, 1-based, nil for none." 26 | < 42 self 7 block ListSelectionEvent >. 27 | ! 28 | METHOD selectedIndex 29 | "int getSelectedIndex() 30 | The first index is 1. Returns 0 if there is no selection." 31 | ^ < 38 SmallInt self 'getSelectedIndex' > + 1. 32 | ! 33 | METHOD selectedIndex: index 34 | "void setSelectedIndex( int index ) 35 | The first index is 1. 0 clears selection." 36 | ^ < 38 nil self 'setSelectedIndex' ( index - 1 ) >. 37 | ! 38 | -------------------------------------------------------------------------------- /Smalltalk/Component/Menu.st: -------------------------------------------------------------------------------- 1 | CLASS Component subclass: 'Menu' variables: '' classVariables: '' 2 | "Implements javax.swing.JMenu and JMenuItem." 3 | META text: text 4 | "public JMenu( String text )" 5 | ^ < 37 Menu 'javax.swing.JMenu' text > 6 | setMnemonic: ( text at: 1 ). 7 | ! 8 | METHOD setMnemonic: char 9 | "setMnemonic( int mnemonic )" 10 | < 38 nil self 'setMnemonic' ( char value ) >. 11 | ! 12 | METHOD add: text action: block 13 | "Add item to menu excuting action block when selected." 14 | | menuItem | 15 | "JMenuItem add( String text )" 16 | menuItem := < 38 Menu self 'add' text >. 17 | menuItem setMnemonic: ( text at: 1 ). 18 | menuItem action: block. 19 | ^ menuItem. 20 | ! 21 | METHOD action: block 22 | < 42 self 2 block ActionEvent >. 23 | ! 24 | -------------------------------------------------------------------------------- /Smalltalk/Component/MenuBar.st: -------------------------------------------------------------------------------- 1 | CLASS Component subclass: 'MenuBar' variables: '' classVariables: '' 2 | "Implements javax.swing.JMenuBar." 3 | META new 4 | "public JMenuBar()" 5 | ^ < 37 MenuBar 'javax.swing.JMenuBar' >. 6 | ! 7 | METHOD add: menu 8 | "JMenu add( JMenu menu )" 9 | < 38 nil self 'add' menu >. 10 | ! 11 | -------------------------------------------------------------------------------- /Smalltalk/Component/Panel.st: -------------------------------------------------------------------------------- 1 | CLASS Component subclass: 'Panel' variables: '' classVariables: '' 2 | "Implements Java javax.swing.JPanel." 3 | META new 4 | "JPanel()" 5 | ^ < 37 self 'javax.swing.JPanel' >. 6 | ! 7 | METHOD layout: layout 8 | "void setLayout( LayoutManager layout )" 9 | < 38 nil self 'setLayout' layout >. 10 | ! 11 | -------------------------------------------------------------------------------- /Smalltalk/Component/Rectangle.st: -------------------------------------------------------------------------------- 1 | CLASS JavaObject subclass: 'Rectangle' variables: '' classVariables: '' 2 | "Implements java.awt.Rectangle." 3 | META x: x y: y width: width height: height 4 | ^ < 37 self 'java.awt.Rectangle' x y width height >. 5 | ! 6 | METHOD printString 7 | ^ 'Rectangle( loc: ' + self x printString + ' @ ' + self y printString + 8 | ', size: ' + self width printString + ' @ ' + self height printString + ' )'. 9 | ! 10 | METHOD location 11 | "Point getLocation()" 12 | ^ < 38 JPoint self 'getLocation' >. 13 | ! 14 | METHOD x 15 | ^ < 40 SmallInt self 'x' >. 16 | ! 17 | METHOD y 18 | ^ < 40 SmallInt self 'y' >. 19 | ! 20 | METHOD width 21 | ^ < 40 SmallInt self 'width' >. 22 | ! 23 | METHOD height 24 | ^ < 40 SmallInt self 'height' >. 25 | ! 26 | -------------------------------------------------------------------------------- /Smalltalk/Component/ScrollBar.st: -------------------------------------------------------------------------------- 1 | CLASS Component subclass: 'ScrollBar' variables: '' classVariables: '' 2 | "Implements javax.swing.JScrollBar" 3 | META orientation: orientation value: value extent: extent min: min max: max 4 | "JScrollBar( int orientation, int value, int extent, int min, int max ) 5 | Orientation: 0 = horizontal, 1 = vertical. 6 | Extent: Horizontal or vertical size of the viewable area (visible amount)." 7 | ^ < 37 ScrollBar 'javax.swing.JScrollBar' orientation value extent min max >. 8 | ! 9 | METHOD onAdjust: block 10 | < 42 self 3 block AdjustmentEvent >. 11 | ! 12 | METHOD maximum 13 | "public int getMaximum()" 14 | ^ < 38 SmallInt self 'getMaximum' >. 15 | ! 16 | METHOD value 17 | "public int getValue()" 18 | ^ < 38 SmallInt self 'getValue' >. 19 | ! 20 | METHOD value: value 21 | "public int setValue()" 22 | ^ < 38 nil self 'setValue' value >. 23 | ! 24 | -------------------------------------------------------------------------------- /Smalltalk/Component/ScrollPane.st: -------------------------------------------------------------------------------- 1 | CLASS Component subclass: 'ScrollPane' variables: '' classVariables: '' 2 | "Implements javax.swing.JScrollPane" 3 | META view: component 4 | "public JScrollPane​( Component view )" 5 | ^ < 37 ScrollPane 'javax.swing.JScrollPane' component >. 6 | ! 7 | METHOD verticalScrollBar 8 | "JScrollBar scrollPane.getVerticalScrollBar()" 9 | ^ < 38 ScrollBar self 'getVerticalScrollBar' >. 10 | ! 11 | METHOD viewport 12 | "JViewport getViewport()" 13 | ^ < 38 Viewport self 'getViewport' >. 14 | ! 15 | -------------------------------------------------------------------------------- /Smalltalk/Component/SplitPane.st: -------------------------------------------------------------------------------- 1 | CLASS Component subclass: 'SplitPane' variables: '' classVariables: '' 2 | "Implements javax.swing.JSplitPane." 3 | META new 4 | "JSplitPane()" 5 | ^ < 37 self 'javax.swing.JSplitPane' >. 6 | ! 7 | META vertical 8 | "JSplitPane.VERTICAL_SPLIT" 9 | ^ 0. 10 | ! 11 | META horizontal 12 | "JSplitPane.HORIZONTAL_SPLIT" 13 | ^ 1. 14 | ! 15 | METHOD orientation: orientation 16 | "void setOrientation​( int orientation )" 17 | < 38 nil self 'setOrientation' orientation >. 18 | ! 19 | METHOD leftComponent: component 20 | "void setLeftComponent( Component component )" 21 | < 38 nil self 'setLeftComponent' component >. 22 | ! 23 | METHOD rightComponent: component 24 | "void setRightComponent( Component component )" 25 | < 38 nil self 'setRightComponent' component >. 26 | ! 27 | -------------------------------------------------------------------------------- /Smalltalk/Component/TabbedPane.st: -------------------------------------------------------------------------------- 1 | CLASS Component subclass: 'TabbedPane' variables: '' classVariables: '' 2 | "Implements javax.swing.JTabbedPane 3 | Note: Indices of tabs are 1-based, with 0 indicating no selection." 4 | META new 5 | "JTabbedPane()" 6 | ^ < 37 self 'javax.swing.JTabbedPane' >. 7 | ! 8 | METHOD addTab: title component: component 9 | "void addTab( String title, Component component )" 10 | < 38 nil self 'addTab' title component >. 11 | ! 12 | METHOD removeTabAt: index 13 | "removeTabAt( int index )" 14 | ^ < 38 SmallInt self 'removeTabAt' ( index - 1 ) >. 15 | ! 16 | METHOD selectedIndex 17 | "Return index of selected tab, 1-based or 0 if none." 18 | "int getSelectedIndex()" 19 | ^ < 38 SmallInt self 'getSelectedIndex' > + 1. 20 | ! 21 | METHOD selectedIndex: index 22 | "Set selected tab by index, 1-based or 0 if none." 23 | "setSelectedIndex( int index )" 24 | ^ < 38 SmallInt self 'setSelectedIndex' ( index - 1 ) >. 25 | ! 26 | METHOD tabCount 27 | "int getTabCount()" 28 | ^ < 38 SmallInt self 'getTabCount' >. 29 | ! 30 | -------------------------------------------------------------------------------- /Smalltalk/Component/Table.st: -------------------------------------------------------------------------------- 1 | CLASS Component subclass: 'Table' variables: 'model' classVariables: '' 2 | "Implements javax.swing.JTable on model javax.swing.table.DefaultTableModel." 3 | META new 4 | | model | 5 | model := TableModel new. 6 | "JTable()" 7 | ^ < 37 self 'javax.swing.JTable' model > model: model. 8 | ! 9 | METHOD disableEditing 10 | | columnClass | 11 | "void setDefaultEditor( Class columnClass, TableCellEditor cellEditor ) 12 | Must call typed FFI primitive to match null argument type correctly. 13 | We want to call like this: setDefaultEditor( Object.class, null )." 14 | columnClass := < 46 JavaObject 'java.lang.Object' >. 15 | < 44 nil self 'setDefaultEditor' 'java.lang.Class' columnClass 'javax.swing.DefaultCellEditor' nil >. 16 | ! 17 | METHOD model 18 | ^ model. 19 | ! 20 | METHOD model: aModel 21 | model := aModel. 22 | ! 23 | METHOD selectedRow 24 | "Return selected row in table, 1-based, 0 if none." 25 | "public int getSelectedRow()" 26 | ^ < 38 SmallInt self 'getSelectedRow' > + 1. 27 | ! 28 | -------------------------------------------------------------------------------- /Smalltalk/Component/TableModel.st: -------------------------------------------------------------------------------- 1 | CLASS Component subclass: 'TableModel' variables: '' classVariables: '' 2 | "Implements javax.swing.table.DefaultTableModel." 3 | META new 4 | "TableModel()" 5 | ^ < 37 self 'javax.swing.table.DefaultTableModel' >. 6 | ! 7 | METHOD addColumns: columnNames 8 | "Add columns names in arguent to table." 9 | columnNames do: [ :columnName | 10 | self addColumn: columnName ]. 11 | ! 12 | METHOD addColumn: columnName 13 | "public void addColumn( Object columnName )" 14 | < 38 nil self 'addColumn' columnName >. 15 | ! 16 | METHOD addRow: rowData 17 | "public void addRow( Vector rowData )" 18 | < 38 nil self 'addRow' ( JavaArray from: rowData ) >. 19 | ! 20 | -------------------------------------------------------------------------------- /Smalltalk/Component/TextArea.st: -------------------------------------------------------------------------------- 1 | CLASS TextComponent subclass: 'TextArea' variables: '' classVariables: '' 2 | "Implements javax.swing.JTextArea" 3 | META new 4 | ^ < 37 self 'javax.swing.JTextArea' >. 5 | ! 6 | METHOD editable: bool 7 | "void setEditable( boolean bool )" 8 | < 38 nil self 'setEditable' bool >. 9 | ! 10 | METHOD lineCount 11 | "int getLineCount()" 12 | ^ < 38 SmallInt self 'getLineCount' >. 13 | ! 14 | METHOD lineStartOffset: lineNum 15 | "int getLineStartOffset( int line ) 16 | The first line number shall be 1." 17 | ^ < 38 SmallInt self 'getLineStartOffset' ( lineNum - 1 ) >. 18 | ! 19 | METHOD tabSize: size 20 | "void setTabSize( int size )" 21 | < 38 nil self 'setTabSize' size >. 22 | ! 23 | METHOD caretLinePosition: lineNum 24 | "Position caret at the start of lineNum in self." 25 | | offset | 26 | self caretPosition: ( 27 | self lineStartOffset: lineNum ). 28 | ! 29 | -------------------------------------------------------------------------------- /Smalltalk/Component/TextComponent.st: -------------------------------------------------------------------------------- 1 | CLASS Component subclass: 'TextComponent' variables: '' classVariables: '' 2 | "Implements javax.swing.JTextComponent" 3 | METHOD caretPosition: position 4 | "void setCaretPosition( int position )" 5 | < 38 nil self 'setCaretPosition' position >. 6 | ! 7 | METHOD editable: bool 8 | "void setEditable( boolean bool )" 9 | < 38 nil self 'setEditable' bool >. 10 | ! 11 | METHOD selectedText 12 | "public String getSelectedText()" 13 | ^ < 38 String self 'getSelectedText' >. 14 | ! 15 | METHOD text 16 | "public String getText()" 17 | ^ < 38 String self 'getText' >. 18 | ! 19 | METHOD text: string 20 | "public void setText( String text )" 21 | ^ < 38 nil self 'setText' string >. 22 | ! 23 | METHOD modelToView: position 24 | "Rectangle modelToView( int position )" 25 | ^ < 38 Rectangle self 'modelToView' position >. 26 | ! 27 | -------------------------------------------------------------------------------- /Smalltalk/Component/TextField.st: -------------------------------------------------------------------------------- 1 | CLASS TextComponent subclass: 'TextField' variables: '' classVariables: '' 2 | "Implements javax.swing.JTextField" 3 | META new 4 | ^ < 37 TextField 'javax.swing.JTextField' >. 5 | ! 6 | -------------------------------------------------------------------------------- /Smalltalk/Component/Viewport.st: -------------------------------------------------------------------------------- 1 | CLASS Component subclass: 'Viewport' variables: '' classVariables: '' 2 | "Implements javax.swing.JViewport" 3 | METHOD viewPosition: point 4 | "void setViewPosition( Point point )" 5 | ^ < 38 nil self 'setViewPosition' point >. 6 | ! 7 | -------------------------------------------------------------------------------- /Smalltalk/Event/ActionEvent.st: -------------------------------------------------------------------------------- 1 | CLASS JavaEvent subclass: 'ActionEvent' variables: '' classVariables: '' 2 | "Implements java.awt.event.ActionEvent. 3 | This event is send for button a click and a menu select. 4 | To receive this event add this code: < 42 aButtonOrMenu 2 aBlock ActionEvent >" 5 | META new 6 | "Note: Events are usually created with event handler primitive 42." 7 | ^ < 37 self 'java.awt.event.ActionEvent' >. 8 | ! 9 | -------------------------------------------------------------------------------- /Smalltalk/Event/AdjustmentEvent.st: -------------------------------------------------------------------------------- 1 | CLASS JavaEvent subclass: 'AdjustmentEvent' variables: '' classVariables: '' 2 | "Implements java.awt.event.AdjustmentEvent. 3 | To receive this event add this code: < 42 aScrollBar 3 aBlock AdjustmentEvent >" 4 | META new 5 | "Note: Events are usually created using event handler primitive 42." 6 | ^ < 37 self 'java.awt.event.AdjustmentEvent' >. 7 | ! 8 | METHOD value 9 | "int getValue()" 10 | ^ < 38 SmallInt self 'getValue' >. 11 | ! 12 | -------------------------------------------------------------------------------- /Smalltalk/Event/JavaEvent.st: -------------------------------------------------------------------------------- 1 | CLASS JavaObject subclass: 'JavaEvent' variables: '' classVariables: '' 2 | "Abstract base class for JavaEvent objects. 3 | These are generally created in response to primitive #42, the event handler, 4 | that passes the event object as the block argument. 5 | 6 | Primitive parameters: < 42 javaObject eventType block eventClass > 7 | Event types: 8 | 1 = windowClosing, 2 = buttonAction, 3 = adjustment (scrollbar), 9 | 4 = mousePressed, 4 = mouseReleased, 5 = mouseMotion (move & drag), 10 | 7 = listSelection, 8 = mouseClicked" 11 | -------------------------------------------------------------------------------- /Smalltalk/Event/ListSelectionEvent.st: -------------------------------------------------------------------------------- 1 | CLASS JavaEvent subclass: 'ListSelectionEvent' variables: '' classVariables: '' 2 | "Implements javax.swing.event.ListSelectionEvent 3 | To receive this event add this code: < 42 aListComponent 7 aBlock ListSelectionEvent >" 4 | ! 5 | META new 6 | ^ < 37 self 'javax.swing.event.ListSelectionEvent' >. 7 | ! 8 | METHOD valueIsAdjusting 9 | "public boolean getValueIsAdjusting()" 10 | ^ < 38 Boolean self 'getValueIsAdjusting' >. 11 | ! 12 | -------------------------------------------------------------------------------- /Smalltalk/Event/MouseEvent.st: -------------------------------------------------------------------------------- 1 | CLASS JavaEvent subclass: 'MouseEvent' variables: '' classVariables: '' 2 | "Implements java.awt.event.MouseEvent. 3 | To receive this event add this code: < 42 aComponent 8 aBlock MouseEvent >" 4 | META new 5 | "Note: Events are usually created using event handler primitive 42." 6 | ^ < 37 self 'java.awt.event.MouseEvent' >. 7 | ! 8 | METHOD x 9 | "int getX()" 10 | ^ < 38 SmallInt self 'getX' >. 11 | ! 12 | METHOD y 13 | "int getY()" 14 | ^ < 38 SmallInt self 'getY' >. 15 | ! 16 | METHOD clickCount 17 | "int getClickCount()" 18 | ^ < 38 SmallInt self 'getClickCount' >. 19 | ! 20 | -------------------------------------------------------------------------------- /Smalltalk/Event/WindowEvent.st: -------------------------------------------------------------------------------- 1 | CLASS JavaEvent subclass: 'WindowEvent' variables: '' classVariables: '' 2 | "Implements java.awt.event.WindowEvent. 3 | To receive this event, add this code: < 42 aWindowComponent 1 aBlock WindowEvent >" 4 | META new 5 | "Note: Events are usually created using event handler primitive 42." 6 | ^ < 37 self 'java.awt.event.WindowEvent' >. 7 | ! 8 | -------------------------------------------------------------------------------- /Smalltalk/Gui/ColorEditor.st: -------------------------------------------------------------------------------- 1 | CLASS Object subclass: 'ColorEditor' variables: 'color frame image imageLabel textField scrollBars semaphore' classVariables: '' 2 | META show: aColor 3 | ^ self new show: aColor 4 | ! 5 | METHOD show: aColor 6 | "Display color selection window on argument. Answer selected new color." 7 | color := aColor. 8 | 9 | semaphore := Semaphore new. 10 | self createFrame. 11 | self loadColor. 12 | frame show. 13 | 14 | ^ semaphore wait. 15 | ! 16 | METHOD createFrame 17 | | selectButton framePanel | 18 | 19 | textField := TextField new. 20 | selectButton := Button new text: 'Select' action: [ :actionEvent | self onSelect ]. 21 | 22 | framePanel := Panel new layout: BorderLayout new. 23 | framePanel border: ( BorderLayout emptyBorder: ( Insets top: 4 left: 4 bottom: 4 right: 4 ) ). 24 | framePanel add: textField constraints: BorderLayout north. 25 | framePanel add: self createScrollBarsPanel constraints: BorderLayout west. 26 | framePanel add: self createImageLabel constraints: BorderLayout center. 27 | framePanel add: selectButton constraints: BorderLayout south. 28 | 29 | frame := Frame new title: 'Color Editor'. 30 | frame setSize: 300 @ 250. 31 | frame add: framePanel. 32 | ! 33 | METHOD createScrollBarsPanel 34 | | scrollBarsPanel scrollBar | 35 | 36 | scrollBarsPanel := Panel new layout: ( GridLayout size: 3 @ 1 ). 37 | 38 | scrollBars := List new. 39 | 3 timesRepeat: [ 40 | "ScrollBar max must also have room for the extent: 255 + 10." 41 | scrollBar := ScrollBar orientation: 1 value: 0 extent: 10 min: 0 max: 265. 42 | scrollBar onAdjust: [ :adjustmentEvent | self onScrollBarChanged ]. 43 | scrollBars add: scrollBar. 44 | scrollBarsPanel add: scrollBar ]. 45 | 46 | ^ scrollBarsPanel. 47 | ! 48 | METHOD createImageLabel 49 | image := Image size: 200 @ 200. 50 | image setColor: color. 51 | image at: 0 @ 0 fillRect: 200 @ 200. 52 | 53 | ^ imageLabel := Label new image: image. 54 | ! 55 | METHOD loadColor 56 | "Load the current color into the GUI." 57 | textField text: color printString. 58 | 59 | ( scrollBars at: 1 ) value: color red. 60 | ( scrollBars at: 2 ) value: color green. 61 | ( scrollBars at: 3 ) value: color blue. 62 | 63 | image setColor: color. 64 | image at: 0 @ 0 fillRect: 200 @ 200. 65 | 66 | imageLabel repaint. 67 | ! 68 | METHOD onScrollBarChanged 69 | "Get new color from changed scrollbar values and update GUI." 70 | color := Color red: ( scrollBars at: 1 ) value green: ( scrollBars at: 2 ) value blue: ( scrollBars at: 3 ) value. 71 | self loadColor. 72 | ! 73 | METHOD onSelect 74 | "Close frame and return selected color via semaphore." 75 | frame close. 76 | semaphore set: color. 77 | ! 78 | -------------------------------------------------------------------------------- /Smalltalk/Gui/Debugger.st: -------------------------------------------------------------------------------- 1 | CLASS Object subclass: 'Debugger' variables: 'startContext frame frameTabbedPane errorTextField contextListComponent argumentListComponent contexts selectedContext arguments' classVariables: '' 2 | "The debugger GUI window inspects the call (context) stack and argument variables. 3 | It is created by the Object.error: method. 4 | It opens InspectorTab panes in new tabs when variables are double-clicked." 5 | METHOD show: message 6 | "Set start context for debugging, skipping the first 3 that are always present: Context.current, Debugger.show, String.error:" 7 | startContext := Context current previousContext previousContext previousContext. 8 | self createFrame. 9 | errorTextField text: message. 10 | self loadContexts. 11 | frame show. 12 | ! 13 | METHOD createFrame 14 | frameTabbedPane := TabbedPane new. 15 | frameTabbedPane addTab: 'Context' component: self createContextTab. 16 | 17 | frame := Frame new title: 'Debugger'. 18 | frame setSize: 800 @ 400. 19 | frame add: frameTabbedPane. 20 | ! 21 | METHOD createContextTab 22 | | contextTab | 23 | 24 | contextTab := Panel new. 25 | contextTab border: ( BorderLayout emptyBorder: ( Insets top: 4 left: 4 bottom: 4 right: 4 ) ). 26 | contextTab layout: ( BorderLayout gap: 4 @ 0 ). 27 | contextTab add: self createErrorPanel constraints: BorderLayout north. 28 | contextTab add: self createContextPane constraints: BorderLayout west. 29 | contextTab add: self createArgumentPane constraints: BorderLayout center. 30 | ^ contextTab. 31 | ! 32 | METHOD createErrorPanel 33 | | errorLabel errorPanel | 34 | 35 | errorLabel := Label new text: 'Error'. 36 | 37 | errorTextField := TextField new. 38 | errorTextField editable: false. 39 | errorTextField background: ( Color red: 250 green: 250 blue: 250 ). 40 | 41 | errorPanel := Panel new. 42 | errorPanel layout: ( BorderLayout gap: 4 @ 0 ). 43 | errorPanel add: errorLabel constraints: BorderLayout west. 44 | errorPanel add: errorTextField constraints: BorderLayout center. 45 | ^ errorPanel. 46 | ! 47 | METHOD createContextPane 48 | | contextScrollPane | 49 | 50 | contextListComponent := ListComponent new. 51 | contextListComponent onSelect: [ :listSelectionEvent | self onContextSelected ]. 52 | 53 | contextScrollPane := ScrollPane view: contextListComponent. 54 | contextScrollPane border: ( Border createTitledBorder: 'Call Stack' ). 55 | ^ contextScrollPane. 56 | ! 57 | METHOD createArgumentPane 58 | | argumentScrollPane | 59 | 60 | argumentListComponent := ListComponent new. 61 | argumentListComponent onMouseClicked: [ :mouseEvent | self onArgumentClicked: mouseEvent ]. 62 | 63 | argumentScrollPane := ScrollPane view: argumentListComponent. 64 | argumentScrollPane border: ( Border createTitledBorder: 'Self & Arguments' ). 65 | ^ argumentScrollPane. 66 | ! 67 | METHOD loadContexts 68 | "Load context methods names into contextListComponent component." 69 | | contextValues context | 70 | 71 | contexts := List new. 72 | contextValues := List new. 73 | context := startContext. 74 | [ context notNil ] whileTrue: [ 75 | contexts add: context. 76 | contextValues add: ( context arguments first class name + ' - ' + context method name ). 77 | context := context previousContext ]. 78 | 79 | contextListComponent listData: contextValues. 80 | contextListComponent selectedIndex: 1. 81 | self onContextSelected. 82 | ! 83 | METHOD onContextSelected 84 | "Load arguments for the selected context." 85 | | context argumentValues | 86 | 87 | context := contexts at: ( contextListComponent selectedIndex ). 88 | 89 | arguments := List new. 90 | argumentValues := List new. 91 | context arguments do: [ :argument | 92 | arguments add: argument. 93 | argumentValues add: argument printString ]. 94 | 95 | argumentListComponent listData: argumentValues. 96 | ! 97 | METHOD onArgumentClicked: mouseEvent 98 | "Open Inspector window on double clicked argument." 99 | | argument | 100 | "Check for double click." 101 | mouseEvent clickCount = 2 ifTrue: [ 102 | argument := arguments at: argumentListComponent selectedIndex. 103 | self addTab: argument ]. 104 | ! 105 | METHOD addTab: object 106 | "Add new inspector tab on argument." 107 | | tab | 108 | tab := InspectorTab new parent: self show: object. 109 | frameTabbedPane addTab: object class name component: tab panel. 110 | frameTabbedPane selectedIndex: frameTabbedPane tabCount. 111 | ! 112 | METHOD closeSelectedTab 113 | "Close the selected tab. 114 | The contex tab will always remain open becuase it does not have a close button." 115 | | index | 116 | index := frameTabbedPane selectedIndex. 117 | index > 1 ifTrue: [ 118 | frameTabbedPane removeTabAt: index. ]. 119 | ! 120 | -------------------------------------------------------------------------------- /Smalltalk/Gui/FileChooser.st: -------------------------------------------------------------------------------- 1 | CLASS Component subclass: 'FileChooser' variables: '' classVariables: '' 2 | "Implements Java javax.swing.JFileChooser" 3 | META new 4 | ^ < 37 self 'javax.swing.JFileChooser' > setToCurrentDirectory. 5 | ! 6 | METHOD extensionFilter: description extensions: extensions 7 | "Sets the extensions to be selected. 8 | Extensions shoud be a string collection of size >= 2, containing a description string and the extension names, like 'st'" 9 | | extensionFilter | 10 | "FileNameExtensionFilter( String description, String... extensions )" 11 | extensionFilter := < 37 JavaObject 'javax.swing.filechooser.FileNameExtensionFilter' description ( JavaArray from: extensions type: 'java.lang.String' ) >. 12 | "void setFileFilter( FileFilter filter )" 13 | < 38 nil self 'setFileFilter' extensionFilter >. 14 | ! 15 | METHOD showOpenDialog: parent 16 | "Shows open dialog and return filename selected of nil if none." 17 | | option file | 18 | "int showOpenDialog( Component parent ) 19 | Returns: 0 = APPROVE_OPTION, 1 = CANCEL_OPTION, -1 = ERROR_OPTION" 20 | option := < 38 SmallInt self 'showOpenDialog' parent >. 21 | option = 0 ifFalse: [ ^ nil ]. 22 | 23 | "File getSelectedFile()" 24 | file := < 38 File self 'getSelectedFile' >. 25 | ^ file relativePath. 26 | ! 27 | METHOD setToCurrentDirectory 28 | "Set file chooser to current working directory. 29 | This is the default behavior." 30 | self currentDirectory: System currentDirectoryName. 31 | ! 32 | METHOD currentDirectory: directoryName 33 | "void setCurrentDirectory( File directory )" 34 | < 38 nil self 'setCurrentDirectory' ( File name: directoryName ) > 35 | ! 36 | -------------------------------------------------------------------------------- /Smalltalk/Gui/ImageEditor.st: -------------------------------------------------------------------------------- 1 | CLASS Object subclass: 'ImageEditor' variables: 'image color semaphore frame colorTextField imageLabel prevPoint' classVariables: '' 2 | "Editor for Image objects." 3 | META show: aImage 4 | ^ self new show: aImage. 5 | ! 6 | METHOD show: aImage 7 | image := aImage. 8 | color := Color black. 9 | semaphore := Semaphore new. 10 | 11 | self createFrame. 12 | self loadImage. 13 | self loadColor. 14 | frame pack show. 15 | 16 | ^ semaphore wait. 17 | ! 18 | METHOD createFrame 19 | | closeButton framePanel | 20 | 21 | closeButton := Button new text: 'Close' action: [ :actionEvent | self onClose ]. 22 | 23 | framePanel := Panel new layout: ( BorderLayout gap: 0 @ 4 ). 24 | framePanel border: ( BorderLayout emptyBorder: ( Insets top: 4 left: 4 bottom: 4 right: 4 ) ). 25 | framePanel add: self createColorPanel constraints: BorderLayout north. 26 | framePanel add: self createImagePanel constraints: BorderLayout center. 27 | framePanel add: closeButton constraints: BorderLayout south. 28 | 29 | frame := Frame new. 30 | frame title: 'Image Editor'. 31 | frame add: framePanel. 32 | ! 33 | METHOD createColorPanel 34 | | colorButton colorPanel | 35 | 36 | colorButton := Button new text: 'Color' action: [ :actionEvent | self onColor ]. 37 | 38 | colorTextField := TextField new. 39 | colorTextField editable: false. 40 | colorTextField background: ( Color red: 250 green: 250 blue: 250 ). 41 | 42 | colorPanel := Panel new layout: ( BorderLayout gap: 4 @ 0 ). 43 | colorPanel add: colorButton constraints: BorderLayout west. 44 | colorPanel add: colorTextField constraints: BorderLayout center. 45 | ^ colorPanel. 46 | ! 47 | METHOD createImagePanel 48 | "In Java, an image in a frame is displayed as an image icon in a label component." 49 | imageLabel := Label new. 50 | imageLabel onMousePressed: [ :mouseEvent | self onMousePressed: mouseEvent ]. 51 | imageLabel onMouseReleased: [ :mouseEvent | self onMouseReleased: mouseEvent ]. 52 | imageLabel onMouseMoved: [ :mouseEvent | self onMouseMoved: mouseEvent ]. 53 | ^ ScrollPane view: imageLabel. 54 | ! 55 | METHOD loadColor 56 | colorTextField text: color printString. 57 | image setColor: color. 58 | ! 59 | METHOD loadImage 60 | imageLabel image: image. 61 | ! 62 | METHOD onColor 63 | color := ColorEditor show: color. 64 | self loadColor. 65 | ! 66 | METHOD onMousePressed: mouseEvent 67 | prevPoint := mouseEvent x @ mouseEvent y. 68 | ! 69 | METHOD onMouseReleased: mouseEvent 70 | prevPoint := nil. 71 | ! 72 | METHOD onMouseMoved: mouseEvent 73 | | newPoint | 74 | prevPoint ifNotNil: [ 75 | newPoint := mouseEvent x @ mouseEvent y. 76 | image at: prevPoint drawLine: newPoint. 77 | prevPoint := newPoint. 78 | frame repaint ]. 79 | ! 80 | METHOD onClose 81 | semaphore set: self. 82 | frame close. 83 | ! 84 | -------------------------------------------------------------------------------- /Smalltalk/Gui/Inspector.st: -------------------------------------------------------------------------------- 1 | CLASS Object subclass: 'Inspector' variables: 'frame frameTabbedPane' classVariables: '' 2 | "The Inspector GUI window for inspecting objects and classes. 3 | This window maintains a list of InspectorTab panes with objects displayed." 4 | META show: object 5 | ^ self new show: object. 6 | ! 7 | METHOD show: object 8 | self createFrame. 9 | self addTab: object. 10 | frame show. 11 | ! 12 | METHOD createFrame 13 | frame := Frame new title: 'Inspector'. 14 | frame setSize: 400 @ 400. 15 | frame add: self createObjectsTabbedPane. 16 | ! 17 | METHOD createObjectsTabbedPane 18 | ^ frameTabbedPane := TabbedPane new. 19 | ! 20 | METHOD addTab: object 21 | "Add object in a new tab." 22 | | tab | 23 | tab := InspectorTab new parent: self show: object. 24 | frameTabbedPane addTab: object class name component: tab panel. 25 | frameTabbedPane selectedIndex: frameTabbedPane tabCount. 26 | ! 27 | METHOD closeSelectedTab 28 | "Close the selected tab if it is not the last remaining one." 29 | | index | 30 | frameTabbedPane tabCount > 1 ifTrue: [ 31 | index := frameTabbedPane selectedIndex. 32 | index >= 1 ifTrue: [ 33 | frameTabbedPane removeTabAt: index ] ]. 34 | ! 35 | -------------------------------------------------------------------------------- /Smalltalk/Gui/InspectorTab.st: -------------------------------------------------------------------------------- 1 | CLASS Object subclass: 'InspectorTab' variables: 'parent object panel stringTextField variablesTable' classVariables: '' 2 | "Maintains a single tabbed pane in the Inspector window." 3 | METHOD parent: aParent show: aObject 4 | "Create new view on aObject" 5 | parent := aParent. 6 | object := aObject. 7 | self createPanel. 8 | self loadObject. 9 | ! 10 | METHOD createPanel 11 | panel := Panel new. 12 | panel border: ( BorderLayout emptyBorder: ( Insets top: 4 left: 4 bottom: 4 right: 4 ) ). 13 | panel layout: ( BorderLayout gap: 0 @ 4 ). 14 | panel add: self createStringPanel constraints: BorderLayout north. 15 | panel add: self createVariablesPanel constraints: BorderLayout center. 16 | ^ panel. 17 | ! 18 | METHOD panel 19 | ^ panel. 20 | ! 21 | METHOD createStringPanel 22 | | stringLabel stringPanel closeButton | 23 | 24 | stringLabel := Label new text: 'String'. 25 | 26 | stringTextField := TextField new. 27 | stringTextField editable: false. 28 | stringTextField background: ( Color red: 250 green: 250 blue: 250 ). 29 | 30 | closeButton := Button new text: 'x' action: [ :actionEvent | parent closeSelectedTab ]. 31 | 32 | stringPanel := Panel new. 33 | stringPanel layout: ( BorderLayout gap: 4 @ 0 ). 34 | stringPanel add: stringLabel constraints: BorderLayout west. 35 | stringPanel add: stringTextField constraints: BorderLayout center. 36 | stringPanel add: closeButton constraints: BorderLayout east. 37 | 38 | ^ stringPanel. 39 | ! 40 | METHOD createVariablesPanel 41 | variablesTable := Table new. 42 | variablesTable disableEditing. 43 | variablesTable model addColumns: #( 'Variable' 'Value' ). 44 | 45 | variablesTable onMouseClicked: [ :mouseEvent | self onTableClicked: mouseEvent ]. 46 | 47 | ^ ScrollPane view: variablesTable. 48 | ! 49 | METHOD loadObject 50 | | rowData | 51 | 52 | stringTextField text: object printString. 53 | 54 | ( object isKindOf: Indexed ) 55 | ifTrue: [ self loadIndexed ] 56 | ifFalse: [ self loadVariables ]. 57 | ! 58 | METHOD loadIndexed 59 | "Object to inspect is an indexed collection." 60 | | rowData | 61 | rowData := Array new: 2. 62 | 1 to: object size do: [ :index | 63 | rowData at: 1 put: index printString. 64 | rowData at: 2 put: ( object at: index ) printString. 65 | variablesTable model addRow: rowData ]. 66 | ! 67 | METHOD loadVariables 68 | | variables rowData | 69 | variables := object class instanceVariables. 70 | 71 | rowData := Array new: 2. 72 | 1 to: variables size do: [ :index | 73 | rowData at: 1 put: ( variables at: index ). 74 | rowData at: 2 put: ( Object in: object at: index ) printString. 75 | variablesTable model addRow: rowData ]. 76 | ! 77 | METHOD onTableClicked: mouseEvent 78 | "Open new inspector tab on double-clicked row." 79 | | row newObject | 80 | "Check for double-click." 81 | mouseEvent clickCount = 2 ifTrue: [ 82 | row := variablesTable selectedRow. 83 | row > 0 ifTrue: [ 84 | newObject := Object in: object at: row. 85 | parent addTab: newObject ] ]. 86 | ! 87 | -------------------------------------------------------------------------------- /Smalltalk/Gui/OptionPane.st: -------------------------------------------------------------------------------- 1 | CLASS Component subclass: 'OptionPane' variables: '' classVariables: '' 2 | "Implements Java javax.swing.JOptionPane" 3 | META showMessageDialog: message 4 | self showMessageDialogOn: nil message: message title: 'Message' messageType: 1 5 | ! 6 | META showMessageDialogOn: parentComponent message: message title: title type: type 7 | "Show modal dialog with message, title and type and OK button to close. 8 | messageType: -1 PLAIN_MESSAGE (no icon), 0 = ERROR_MESSAGE. 1 = INFORMATION_MESSAGE, 2 = WARNING_MESSAGE, 3 = QUESTION_MESSAGE" 9 | 10 | "void showMessageDialog( Component parentComponent, Object message, String title, int messageType ) 11 | Must call typed FFI primitive to match parentComponent argument type correctly if it is nil." 12 | ^ < 45 String 'javax.swing.JOptionPane' 'showMessageDialog' 'java.awt.Component' parentComponent 'java.lang.Object' message 'java.lang.String' title 'java.lang.Integer' type >. 13 | ! 14 | META showConfirmDialogOn: parentComponent message: message title: title option: option 15 | "Show conformation dialog with options yes, no and cancel. 16 | Return values: true for yes, false for no and nil for cancel or close." 17 | 18 | "public static int showConfirmDialog( Component parentComponent, Object message, String title, int optionType ). 19 | Option types: 0 = YES_NO_OPTION, 1 = YES_NO_CANCEL_OPTION, 2 = OK_CANCEL_OPTION, -1 = DEFAULT_OPTION. 20 | Return values: 0 = YES_OPTION, 1 NO_OPTION, 2 = CANCEL_OPTION, -1 = CLOSED_OPTION. 21 | Must call typed FFI primitive to match parentComponent argument type correctly if it is nil." 22 | | answer | 23 | answer := < 45 String 'javax.swing.JOptionPane' 'showConfirmDialog' 'java.awt.Component' parentComponent 'java.lang.Object' message 'java.lang.String' title 'java.lang.Integer' option >. 24 | answer = 0 ifTrue: [ ^ true ]. 25 | answer = 1 ifTrue: [ ^ false ]. 26 | ^ nil. "Cancel or close." 27 | ! 28 | META showInputDialogOn: parentComponent message: message title: title type: type 29 | "String showInputDialog( Component parentComponent, Object message, String title, int messageType ) 30 | Must call typed FFI primitive to match parentComponent argument type correctly if it is nil." 31 | ^ < 45 String 'javax.swing.JOptionPane' 'showInputDialog' 'java.awt.Component' parentComponent 'java.lang.Object' message 'java.lang.String' title 'java.lang.Integer' type >. 32 | ! 33 | -------------------------------------------------------------------------------- /Smalltalk/Io/File.st: -------------------------------------------------------------------------------- 1 | CLASS Object subclass: 'File' variables: '' classVariables: ''. 2 | "Implements: 3 | java.io.File for file constants. 4 | java.io.PrintStream for writing a file 5 | java.io.DataInputStream for reading it." 6 | META name: fileName 7 | ^ < 37 File 'java.io.File' fileName >. 8 | ! 9 | META forwardSlashes: fileName 10 | "Returns filename with Windows style backward slashes replaced with Unix style forward slashes." 11 | ^ ( fileName collect: [ :char | char = $\ ifTrue: [ $/ ] ifFalse: [ char ] ] ) asString. 12 | ! 13 | META openRead: fileName 14 | "Open fileName for reading using DataInputStream class in Java" 15 | | file fileInputStream | 16 | ( file := File name: fileName ) canRead ifFalse: [ 17 | self error: 'Cannot open file for reading: ' + fileName ]. 18 | 19 | fileInputStream := < 37 File 'java.io.FileInputStream' file >. 20 | ^ < 37 File 'java.io.DataInputStream' fileInputStream > 21 | ! 22 | META openWrite: fileName 23 | "Open fileName for writing using the PrintStream class in Java." 24 | | file fileOutputStream | 25 | ( file := File name: fileName ) canWrite ifFalse: [ 26 | self error: 'Cannot open file for writing: ' + fileName ]. 27 | fileOutputStream := < 37 File 'java.io.FileOutputStream' file >. 28 | ^ < 37 File 'java.io.PrintStream' fileOutputStream > 29 | ! 30 | META separatorChar 31 | "static final char separatorChar" 32 | ^ Char new: < 41 Char 'java.io.File' 'separatorChar' >. 33 | ! 34 | METHOD canRead 35 | "boolean canRead()" 36 | ^ < 38 Boolean self 'canRead' >. 37 | ! 38 | METHOD canWrite 39 | "boolean canWrite()" 40 | ^ < 38 Boolean self 'canWrite' >. 41 | ! 42 | METHOD exists 43 | "boolean exists()" 44 | ^ < 38 Boolean self 'exists' >. 45 | ! 46 | METHOD name 47 | "String getName()" 48 | ^ < 38 String self 'getName' >. 49 | ! 50 | METHOD path 51 | "String getPath()" 52 | ^ < 38 String self 'getPath' >. 53 | ! 54 | METHOD relativePath 55 | "Return relative path to file from current working folder, if possible. 56 | Otherwise return absolute path." 57 | | basePath path | 58 | basePath := System currentDirectoryName. 59 | path := self path. 60 | ( basePath from: 1 to: basePath size ) = ( path from: 1 to: basePath size ) ifFalse: [ ^ path ]. 61 | ^ path from: basePath size + 2 to: path size. 62 | ! 63 | METHOD readLine 64 | "Read next text line form file. 65 | Return nil on end-of-file." 66 | ^ < 38 String self 'readLine' >. 67 | ! 68 | METHOD asString 69 | "Read all the lines in file file and return them as a single string." 70 | | newline result line | 71 | newline := Char newline asString. 72 | result := ''. 73 | [ ( line := self readLine ) = nil ] whileFalse: [ 74 | result := result + line + newline ]. 75 | ^ result. 76 | ! 77 | METHOD write: aString 78 | < 38 nil self 'print' aString >. 79 | ! 80 | METHOD lastModified 81 | "long lastModified()" 82 | ^ < 38 SmallLong self 'lastModified' >. 83 | ! 84 | METHOD close 85 | "void close(). Self should be output stream." 86 | ^ < 38 nil self 'close' >. 87 | ! 88 | -------------------------------------------------------------------------------- /Smalltalk/Io/PrintStream.st: -------------------------------------------------------------------------------- 1 | CLASS JavaObject subclass: 'PrintStream' variables: '' classVariables: '' 2 | METHOD print: object 3 | "public void print( String s )" 4 | < 38 nil self 'print' ( object printString ) >. 5 | ! 6 | METHOD println: object 7 | "public void println( String s )" 8 | < 38 nil self 'println' ( object printString ) >. 9 | ! 10 | -------------------------------------------------------------------------------- /Smalltalk/Io/System.st: -------------------------------------------------------------------------------- 1 | CLASS JavaObject subclass: 'System' variables: '' classVariables: '' 2 | "Implements java.lang.System" 3 | META in 4 | "static InputStream in - The standard input stream." 5 | ^ < 41 JavaObject 'java.lang.System' 'in' >. 6 | ! 7 | META out 8 | "static PrintStream out - The standard output stream." 9 | ^ < 41 PrintStream 'java.lang.System' 'out' >. 10 | ! 11 | META err 12 | "static PrintStream err - The standard error output stream." 13 | ^ < 41 PrintStream 'java.lang.System' 'err' >. 14 | ! 15 | META log: text 16 | self out println: text. 17 | ! 18 | META exit: status 19 | "public static void exit( int status )" 20 | < 39 nil 'java.lang.System' 'exit' status >. 21 | ! 22 | META imageFileName 23 | ^ < 27 >. 24 | ! 25 | META saveImage 26 | "Save image under current file name." 27 | self saveImage: self imageFileName 28 | ! 29 | META saveImage: fileName 30 | < 29 fileName >. 31 | ! 32 | META sleep: time 33 | "Sleep for milliseconds time in argument. 34 | void java.lang.Thread.sleep( long time )." 35 | < 45 nil 'java.lang.Thread' 'sleep' 'java.lang.Long' time > 36 | ! 37 | META currentDirectoryName 38 | ^ < 39 String 'java.lang.System' 'getProperty' 'user.dir' >. 39 | ! 40 | -------------------------------------------------------------------------------- /Smalltalk/Java/JavaArray.st: -------------------------------------------------------------------------------- 1 | CLASS JavaObject subclass: 'JavaArray' variables: '' classVariables: '' 2 | "Implements java.lang.reflect.Array. 3 | Used for conversion of Smalltalk connections to this class, for use with FFI." 4 | META from: array 5 | "Return Java Object[] array with elements from argument." 6 | ^ self from: array type: 'java.lang.Object'. 7 | ! 8 | META from: array type: type 9 | "Return Java [] array with elements from array argument." 10 | | javaClass javaArray | 11 | javaClass := < 46 JavaObject type >. 12 | "static Object newInstance( Class elementType, int length )" 13 | javaArray := < 39 self 'java.lang.reflect.Array' 'newInstance' javaClass ( array size ) >. 14 | 1 to: array size do: [ :index | 15 | "static void set( Object array, int index, Object value )" 16 | self in: javaArray at: index - 1 put: ( array at: index ) ]. 17 | ^ javaArray. 18 | ! 19 | META in: array at: index put: object 20 | "static void set( Object array, int index, Object value )" 21 | < 39 nil 'java.lang.reflect.Array' 'set' array index object >. 22 | ! 23 | -------------------------------------------------------------------------------- /Smalltalk/Java/JavaObject.st: -------------------------------------------------------------------------------- 1 | CLASS Object subclass: 'JavaObject' variables: '' classVariables: '' 2 | "Abstract base helper class for Java objects, created with java primitives. 3 | This class can be used for created Java objects for which there is no Smalltalk class yet. 4 | Note: Any Smalltalk class can create paired Java objects. Inheritance from this class is not mandatory." 5 | META new 6 | ^ self error: 'JavaObject instances should be created with primitive 37 to pair them with Java objects.'. 7 | ! 8 | -------------------------------------------------------------------------------- /Smalltalk/Java/JavaVector.st: -------------------------------------------------------------------------------- 1 | CLASS JavaObject subclass: 'JavaVector' variables: '' classVariables: '' 2 | "Implements java.util.Vector. 3 | Used for conversion of Smalltalk connections to this class, for use with FFI." 4 | META from: array 5 | "Create a new instance of self with elements from argument array added to it." 6 | | javaVector | 7 | javaVector := < 37 self 'java.util.Vector' ( array size ) >. 8 | array do: [ :element | 9 | javaVector add: element ]. 10 | ^ javaVector. 11 | ! 12 | METHOD add: element 13 | "public boolean add( E element ) 14 | return value is always true." 15 | < 38 nil self 'add' element >. 16 | ! 17 | -------------------------------------------------------------------------------- /Smalltalk/Java/Semaphore.st: -------------------------------------------------------------------------------- 1 | CLASS JavaObject subclass: 'Semaphore' variables: 'value' classVariables: '' 2 | "implements java.util.concurrent.Semaphore. 3 | Additionally holds a value that can be communicated from sender to receiver (set: & wait)." 4 | META new 5 | "Semaphore​( int permits )" 6 | ^ < 37 self 'java.util.concurrent.Semaphore' 0 >. 7 | ! 8 | METHOD acquire 9 | "void acquire() 10 | throws InterruptedException" 11 | < 38 nil self 'acquire' >. 12 | ! 13 | METHOD release 14 | "void release()" 15 | < 38 nil self 'release' >. 16 | ! 17 | METHOD set: aValue 18 | "Set semaphore value and release it." 19 | value := aValue. 20 | self release. 21 | ! 22 | METHOD wait 23 | "Wait for semaphore release and return value that might have been set." 24 | self acquire. 25 | ^ value. 26 | ! 27 | -------------------------------------------------------------------------------- /Smalltalk/Magnitude/Char.st: -------------------------------------------------------------------------------- 1 | CLASS Magnitude subclass: 'Char' variables: 'value' classVariables: '' 2 | META new: v 3 | "Create and initialize a new char." 4 | ^ Object in: super new initialize: 'value' with: v 5 | ! 6 | META newline 7 | "Return newline character." 8 | ^ self new: 10 9 | ! 10 | META tab 11 | "Return tab character." 12 | ^ self new: 9. 13 | ! 14 | METHOD < aChar 15 | ^ value < aChar value 16 | ! 17 | METHOD = aChar 18 | ^ value = aChar value 19 | ! 20 | METHOD asString 21 | | r | 22 | "Return char as a string value." 23 | r := String new: 1. 24 | r at: 1 put: self. 25 | ^ r 26 | ! 27 | METHOD isAlphabetic 28 | ^ self isLowerCase or: [ self isUpperCase ] 29 | ! 30 | METHOD isAlphanumeric 31 | "Are we a letter or a digit?" 32 | ^ self isAlphabetic or: [ self isDigit ] 33 | ! 34 | METHOD isBlank 35 | "Spaces, tabs and newlines are considered blank." 36 | ^ value = 32 or: [ value = 9 or: [ value = 10 ] ] 37 | ! 38 | METHOD isDigit 39 | ^ self between: $0 and: $9 40 | ! 41 | METHOD isLowerCase 42 | ^ self between: $a and: $z 43 | ! 44 | METHOD isUpperCase 45 | ^ self between: $A and: $Z 46 | ! 47 | METHOD lowerCase 48 | self isUpperCase 49 | ifTrue: [ ^ Char new: (value - 65) + 97 ] 50 | ! 51 | METHOD printString 52 | | r | 53 | r := String new: 2. 54 | r at: 1 put: $$. 55 | r at: 2 put: self. 56 | ^ r 57 | ! 58 | METHOD upperCase 59 | self isLowerCase ifTrue: [ 60 | ^ Char new: (value - 97) + 65 ]. 61 | ! 62 | METHOD value 63 | "Return our ascii value as an integer." 64 | ^ value 65 | ! 66 | -------------------------------------------------------------------------------- /Smalltalk/Magnitude/Float.st: -------------------------------------------------------------------------------- 1 | CLASS Number subclass: 'Float' variables: '' classVariables: '' 2 | "Smalltalk floats are implemented as Java type double." 3 | META fromSmallInt: int 4 | ^ < 50 self int > 5 | ! 6 | META new 7 | ^ self error: 'Floats cannot be created with new.'. 8 | ! 9 | META random 10 | "static double random()" 11 | ^ < 39 Float 'java.lang.Math' 'random' >. 12 | ! 13 | METHOD * arg 14 | ^ arg multByFloat: self. 15 | ! 16 | METHOD + arg 17 | ^ arg addToFloat: self. 18 | ! 19 | METHOD - arg 20 | ^ arg subtractFromFloat: self. 21 | ! 22 | METHOD / arg 23 | ^ arg divideByFloat: self. 24 | ! 25 | METHOD < arg 26 | ^ arg asFloat lessThanFloat: self. 27 | ! 28 | METHOD = arg 29 | ^ arg asFloat equalToFloat: self. 30 | ! 31 | METHOD @ y 32 | "Return new point with self as x and arg as y" 33 | ^ Point x: self y: y 34 | ! 35 | METHOD addToFloat: arg 36 | ^ < 51 arg self >. 37 | ! 38 | METHOD asFloat 39 | ^ self. 40 | ! 41 | METHOD asInteger 42 | ^ < 57 self >. 43 | ! 44 | METHOD divideByFloat: arg 45 | ^ < 54 arg self >. 46 | ! 47 | METHOD equalToFloat: arg 48 | ^ < 56 arg self >. 49 | ! 50 | METHOD lessThanFloat: arg 51 | ^ < 55 arg self >. 52 | ! 53 | METHOD lessThanSmallInt: arg 54 | ^ arg asFloat < self. 55 | ! 56 | METHOD multByFloat: arg 57 | ^ < 53 arg self >. 58 | ! 59 | METHOD sqrt 60 | "double java.lang.Math.sqrt( double num )" 61 | ^ < 39 Float 'java.lang.Math' 'sqrt' self >. 62 | ! 63 | METHOD printString 64 | "String toString()" 65 | ^ < 39 String 'java.lang.Double' 'toString' self >. 66 | ! 67 | METHOD subtractFromFloat: arg 68 | ^ < 52 arg self >. 69 | ! 70 | -------------------------------------------------------------------------------- /Smalltalk/Magnitude/Fraction.st: -------------------------------------------------------------------------------- 1 | CLASS Number subclass: 'Fraction' variables: 'top bottom' classVariables: '' 2 | META top: t 3 | ^ self in: (self in: super new at: 1 put: t) at: 2 put: 1 4 | ! 5 | META top: t bottom: b | r | 6 | b = 0 ifTrue: [ ^ self error: ' division by zero in fraction']. 7 | r := t gcd: b. 8 | ^ self in: (self in: super new at: 1 put: (t quo: r)) at: 2 put: (b quo: r) 9 | ! 10 | METHOD * arg 11 | ^ arg multByFraction: self 12 | ! 13 | METHOD + arg 14 | ^ arg addToFraction: self 15 | ! 16 | METHOD - arg 17 | ^ arg subtractFromFraction: self 18 | ! 19 | METHOD / arg 20 | ^ arg divideByFraction: self 21 | ! 22 | METHOD addToFraction: arg 23 | ^ Fraction top: top * arg bottom + (bottom * arg top) bottom: bottom * arg bottom 24 | ! 25 | METHOD addToSmallInt: arg 26 | ^ (Fraction top: arg) + self 27 | ! 28 | METHOD asFloat 29 | ^ top asFloat / bottom asFloat 30 | ! 31 | METHOD bottom 32 | ^ bottom 33 | ! 34 | METHOD divideByFraction: arg 35 | ^ Fraction top: arg top * bottom bottom: arg bottom * top 36 | ! 37 | METHOD divideBySmallInt: arg 38 | ^ (Fraction top: arg) / self 39 | ! 40 | METHOD multByFraction: arg 41 | ^ Fraction top: top * arg top bottom: bottom * arg bottom 42 | ! 43 | METHOD multBySmallInt: arg 44 | ^ (Fraction top: arg) * self 45 | ! 46 | METHOD printString 47 | ^ '(' + top printString + '/' + bottom printString + ')' 48 | ! 49 | METHOD subtractFromFraction: arg 50 | ^ Fraction top: arg top * bottom - (top * arg bottom) bottom: bottom * arg bottom 51 | ! 52 | METHOD subtractFromSmallInt: arg 53 | ^ (Fraction top: arg) - self 54 | ! 55 | METHOD top 56 | ^ top 57 | ! 58 | -------------------------------------------------------------------------------- /Smalltalk/Magnitude/Integer.st: -------------------------------------------------------------------------------- 1 | CLASS Number subclass: 'Integer' variables: '' classVariables: '' 2 | METHOD / arg 3 | ^ arg divideByInteger: self 4 | ! 5 | METHOD @ y 6 | ^ Point x: self y: y 7 | ! 8 | METHOD addToFraction: arg 9 | ^ arg + (Fraction top: self) 10 | ! 11 | METHOD addToSmallInt: arg 12 | " private internal method " 13 | ^ arg asLargeInteger + self 14 | ! 15 | METHOD asHex 16 | "Return hexadecimal sting version of self. 17 | Negative numbers give zero." 18 | | hex | 19 | hex := '' 20 | ^ self 21 | ! 22 | METHOD asInteger 23 | ^ self 24 | ! 25 | METHOD divideByFraction: arg 26 | ^ arg / (Fraction top: self) 27 | ! 28 | METHOD divideByInteger: arg 29 | ^ Fraction top: arg bottom: self 30 | ! 31 | METHOD equalToSmallInt: arg 32 | ^ arg asLargeInteger = self 33 | ! 34 | METHOD gcd: x | n m | 35 | " euclids gcd algorithm " 36 | n := self. m := x. 37 | (n <= 0 or: [m <= 0]) ifTrue: [ ^ 1]. 38 | [ n = m ] whileFalse: [ n < m ifTrue: [ m := m - n ] ifFalse: [ n := n - m ]]. 39 | ^ n 40 | ! 41 | METHOD lessThanSmallInt: arg 42 | " private internal method " 43 | ^ arg asLargeInteger < self 44 | ! 45 | METHOD multByFraction: arg 46 | ^ arg * ( Fraction top: self ) 47 | ! 48 | METHOD random 49 | ^ ( Float random * self ) asInteger 50 | ! 51 | METHOD subtractFromFraction: arg 52 | ^ arg - (Fraction top: self) 53 | ! 54 | METHOD subtractFromSmallInt: arg 55 | " private method, used internally " 56 | ^ arg asLargeInteger - self 57 | ! 58 | -------------------------------------------------------------------------------- /Smalltalk/Magnitude/LargeNegative.st: -------------------------------------------------------------------------------- 1 | CLASS Integer subclass: 'LargeNegative' variables: 'values' classVariables: '' 2 | META new: value 3 | ^ self in: super new at: 1 put: value. 4 | ! 5 | METHOD * arg 6 | ^ ( self negated * arg ) negated. 7 | ! 8 | METHOD + arg 9 | ^ arg - self negated. 10 | ! 11 | METHOD - arg 12 | ^ ( self negated + arg ) negated. 13 | ! 14 | METHOD < arg 15 | ^ ( self negated < arg negated ) not. 16 | ! 17 | METHOD = arg 18 | ^ self negated = arg negated. 19 | ! 20 | METHOD addToLP: arg 21 | "Private internal method." 22 | ^ arg - self negated. 23 | ! 24 | METHOD asFloat 25 | ^ self negated asFloat negated. 26 | ! 27 | METHOD compareToLP: arg 28 | "We are always smaller than a positive number." 29 | ^ -1. 30 | ! 31 | METHOD multByLP: arg 32 | ^ ( self negated multByLP: arg ) negated. 33 | ! 34 | METHOD multBySmallInt: arg 35 | ^ ( self negated multBySmallInt: arg ) negated. 36 | ! 37 | METHOD negated 38 | ^ LargePositive new: values. 39 | ! 40 | METHOD printString 41 | ^ '-' + self negated printString. 42 | ! 43 | METHOD subtractFromLP: arg 44 | "Private internal method." 45 | ^ arg + self negated. 46 | ! 47 | -------------------------------------------------------------------------------- /Smalltalk/Magnitude/LargePositive.st: -------------------------------------------------------------------------------- 1 | CLASS Integer subclass: 'LargePositive' variables: 'values' classVariables: '' 2 | META new: v 3 | ^ self in: super new at: 1 put: v. 4 | ! 5 | METHOD * arg 6 | ^ arg multByLP: self. 7 | ! 8 | METHOD + arg 9 | ^ arg addToLP: self. 10 | ! 11 | METHOD - arg 12 | ^ self < arg 13 | ifTrue: [ ( arg - self ) negated ] 14 | ifFalse: [ arg subtractFromLP: self ]. 15 | ! 16 | METHOD < arg 17 | ^ 0 < (arg compareToLP: self) 18 | ! 19 | METHOD = arg 20 | ^ 0 = (arg compareToLP: self) 21 | ! 22 | METHOD addToLP: arg 23 | | carry nv newValue | 24 | carry := 0. 25 | newValue := List new. 26 | values with: arg values pad: 0 do: [ :lv :rv | 27 | nv := lv + rv + carry. 28 | carry := nv quo: 100. 29 | newValue add: (nv rem: 100) ]. 30 | ( carry = 0 ) ifFalse: [ newValue add: carry ]. 31 | ^ LargePositive new: newValue asByteArray. 32 | ! 33 | METHOD asFloat 34 | | r | 35 | r := 0 asFloat. 36 | values reverseDo: [ :e | r := r * 100 + e ]. 37 | ^ r. 38 | ! 39 | METHOD compareToLP: arg 40 | | r | 41 | r := 0. 42 | values with: arg values pad: 0 do: [ :lv :rv | 43 | ( lv = rv ) ifFalse: 44 | [ r := ( lv < rv ) ifTrue: [ -1 ] ifFalse: [ 1 ] ] ]. 45 | ^ r. 46 | ! 47 | METHOD multByLP: arg 48 | | r a b c| 49 | r := List new. 50 | values reverseDo: [ :e | 51 | r := ( ( LargePositive new: ( r addFirst: 0 ) ) + ( arg * e ) ) values asList ]. 52 | ^ LargePositive new: r asByteArray 53 | ! 54 | METHOD multBySmallInt: arg 55 | | carry newValue | 56 | " private internal method " 57 | arg < 0 ifTrue: [ ^ (self multBySmallInt: arg negated) negated ]. 58 | carry := 0. newValue := List new. 59 | values do: [:e | carry := e * arg + carry. 60 | newValue add: (carry rem: 100). carry := carry quo: 100 ]. 61 | [ carry > 0 ] whileTrue: [ newValue add: (carry rem: 100). carry := carry quo: 100 ]. 62 | ^ LargePositive new: newValue asByteArray 63 | ! 64 | METHOD negated 65 | ^ LargeNegative new: values 66 | ! 67 | METHOD printString 68 | ^ values inject: '' into: [ :r :e | 69 | ( '00' + e printString last: 2 ) + r ]. 70 | ! 71 | METHOD subtractFromLP: arg 72 | | borrow newValue | 73 | " private internal method, know we are smaller than arg " 74 | borrow := 0. newValue := List new. 75 | arg values with: values pad: 0 do: [ :lv :rv | 76 | lv := lv - borrow. 77 | ( lv < rv ) ifTrue: [ lv := lv + 100. borrow := 1 ] ifFalse: [ borrow := 0 ]. 78 | newValue add: (lv - rv) ]. 79 | ^ LargePositive new: newValue asByteArray 80 | 81 | ! 82 | METHOD values 83 | ^ values 84 | ! 85 | -------------------------------------------------------------------------------- /Smalltalk/Magnitude/Magnitude.st: -------------------------------------------------------------------------------- 1 | CLASS Object subclass: 'Magnitude' variables: '' classVariables: '' 2 | METHOD <= arg 3 | ^ self < arg or: [ self = arg ] 4 | ! 5 | METHOD > arg 6 | ^ arg < self 7 | ! 8 | METHOD >= arg 9 | ^ self > arg or: [ self = arg ] 10 | ! 11 | METHOD between: low and: high 12 | ^ low <= self and: [ self <= high ] 13 | ! 14 | METHOD max: arg 15 | ^ self < arg ifTrue: [ arg ] ifFalse: [ self ] 16 | ! 17 | METHOD min: arg 18 | ^ self < arg ifTrue: [ self ] ifFalse: [ arg ] 19 | ! 20 | -------------------------------------------------------------------------------- /Smalltalk/Magnitude/Number.st: -------------------------------------------------------------------------------- 1 | CLASS Magnitude subclass: 'Number' variables: '' classVariables: '' 2 | METHOD abs 3 | ^ self negative ifTrue: [ self negated ] ifFalse: [ self ] 4 | ! 5 | METHOD addToFloat: arg 6 | ^ arg + self asFloat 7 | ! 8 | METHOD addToFraction: arg 9 | ^ arg asFloat + self asFloat 10 | ! 11 | METHOD addToSmallInt: arg 12 | ^ arg asFloat + self 13 | ! 14 | METHOD divideByFloat: arg 15 | ^ arg / self asFloat 16 | ! 17 | METHOD divideBySmallInt: arg 18 | ^ arg asFloat / self 19 | ! 20 | METHOD equalToFloat: arg 21 | ^ arg = self asFloat 22 | ! 23 | METHOD lessThanFloat: arg 24 | ^ arg < self asFloat 25 | ! 26 | METHOD multByFloat: arg 27 | ^ arg * self asFloat 28 | ! 29 | METHOD multBySmallInt: arg 30 | ^ arg asFloat * self 31 | ! 32 | METHOD negated 33 | ^ 0 - self 34 | ! 35 | METHOD negative 36 | ^ self < 0 37 | ! 38 | METHOD subtractFromFloat: arg 39 | ^ arg - self asFloat 40 | ! 41 | METHOD subtractFromSmallInt: arg 42 | ^ arg asFloat - self 43 | ! 44 | -------------------------------------------------------------------------------- /Smalltalk/Magnitude/Point.st: -------------------------------------------------------------------------------- 1 | CLASS Magnitude subclass: 'Point' variables: 'x y' classVariables: '' 2 | META x: x y: y 3 | ^ self new x: x y: y. 4 | ! 5 | METHOD + aPoint 6 | ^ ( x + aPoint x ) @ ( y + aPoint y ). 7 | ! 8 | METHOD printString 9 | ^ x printString + ' @ ' + y printString. 10 | ! 11 | METHOD x 12 | ^ x. 13 | ! 14 | METHOD x: aX 15 | x := aX 16 | ! 17 | METHOD x: aX y: aY 18 | x := aX. 19 | y := aY. 20 | ! 21 | METHOD y 22 | ^ y. 23 | ! 24 | METHOD y: aY 25 | y := aY. 26 | ! 27 | -------------------------------------------------------------------------------- /Smalltalk/Magnitude/SmallInt.st: -------------------------------------------------------------------------------- 1 | CLASS Integer subclass: 'SmallInt' variables: '' classVariables: '' 2 | META new 3 | "Can't create this way, return zero." 4 | ^ 0. 5 | ! 6 | METHOD * arg 7 | ^ arg multBySmallInt: self. 8 | ! 9 | METHOD + arg 10 | ^ arg addToSmallInt: self. 11 | ! 12 | METHOD - arg 13 | ^ arg subtractFromSmallInt: self. 14 | ! 15 | METHOD < arg 16 | ^ arg lessThanSmallInt: self. 17 | ! 18 | METHOD = arg 19 | ^ arg equalToSmallInt: self. 20 | ! 21 | METHOD addToLP: arg 22 | ^ arg + self asLargeInteger. 23 | ! 24 | METHOD addToSmallInt: arg 25 | "This only gets invoked when overflow occurs." 26 | ^ arg asLargeInteger + self asLargeInteger. 27 | ! 28 | METHOD asFloat 29 | ^ Float fromSmallInt: self. 30 | ! 31 | METHOD asLargeInteger 32 | | newValue n | 33 | newValue := List new. 34 | n := self abs. 35 | [n > 0] whileTrue: [ newValue add: (n rem: 100). n := n quo: 100]. 36 | newValue size = 0 ifTrue: [ newValue add: 0]. 37 | ^ self < 0 ifTrue: [ LargeNegative new: newValue asByteArray] 38 | ifFalse: [ LargePositive new: newValue asByteArray ]. 39 | ! 40 | METHOD compareToLP: arg 41 | ^ self asLargeInteger compareToLP: arg. 42 | ! 43 | METHOD equalToSmallInt: arg 44 | ^ < 14 self arg >. 45 | ! 46 | METHOD lessThanSmallInt: arg 47 | ^ < 13 arg self >. 48 | ! 49 | METHOD multByLP: arg 50 | ^ self * arg. 51 | ! 52 | METHOD multBySmallInt: arg 53 | | result | 54 | "must check for overflow " 55 | result := < 15 arg self >. 56 | result isNil ifTrue: [ 57 | result := arg asLargeInteger * self asLargeInteger ]. 58 | ^ result. 59 | ! 60 | METHOD printString 61 | ( self < 0 ) ifTrue: [ ^ '-' + self negated printString ]. 62 | ( self < 10 ) ifTrue: [ ^ ( Char new: ( self + 48 ) ) asString ]. 63 | ^ ( self quo: 10 ) printString + ( self rem: 10 ) printString. 64 | ! 65 | METHOD quo: arg 66 | (0 = arg) ifTrue: [ ^ self error: 'division by zero' ]. 67 | ^ arg quoWithSmallInt: self 68 | 69 | ! 70 | METHOD quoWithSmallInt: arg 71 | ^ <11 arg self> 72 | ! 73 | METHOD rem: arg 74 | ( 0 = arg ) ifTrue: [ ^ self error: 'division by zero' ]. 75 | ^ arg remWithSmallInt: self 76 | ! 77 | METHOD remWithSmallInt: arg 78 | ^ <12 arg self> 79 | ! 80 | METHOD subtractFromLP: arg 81 | " private internal method " 82 | ^ arg - self asLargeInteger 83 | ! 84 | METHOD subtractFromSmallInt: arg 85 | | r | 86 | r := < 16 arg self >. 87 | "Check for overflow." 88 | r isNil ifTrue: [ 89 | r := arg asLargeInteger - self asLargeInteger ]. 90 | ^ r. 91 | ! 92 | METHOD timesRepeat: aBlock 93 | | times | 94 | times := self. 95 | [ times > 0 ] whileTrue: [ 96 | aBlock value. 97 | times := times - 1 ]. 98 | ! 99 | METHOD to: limit 100 | ^ Interval from: self to: limit by: 1 101 | ! 102 | METHOD to: limit by: step 103 | ^ Interval from: self to: limit by: step 104 | ! 105 | METHOD to: limit do: aBlock 106 | "Value aBlock repeatedly with integers in range from self upto limit. 107 | Is optimized case of Interval." 108 | | i | 109 | i := self. 110 | [ i <= limit ] whileTrue: [ 111 | aBlock value: i. 112 | i := i + 1 ]. 113 | ! 114 | -------------------------------------------------------------------------------- /Smalltalk/Magnitude/SmallLong.st: -------------------------------------------------------------------------------- 1 | CLASS Integer subclass: 'SmallLong' variables: '' classVariables: '' 2 | "Implements Java.lang.Long and long type. 3 | For now, does not automatically convert to other integer types (Small and Large). 4 | The main use of this class is to use it in the FFI." 5 | META new 6 | "Can't create this way, return zero." 7 | ^ self new: 0. 8 | ! 9 | META new: aSmallInt 10 | ^ < 65 self aSmallInt >. 11 | ! 12 | METHOD = arg 13 | ^ < 62 self arg >. 14 | ! 15 | METHOD < arg 16 | ^ < 61 self arg >. 17 | ! 18 | METHOD * arg 19 | ^ < 63 self arg >. 20 | ! 21 | METHOD + arg 22 | ^ < 58 self arg >. 23 | ! 24 | METHOD - arg 25 | ^ < 64 self arg >. 26 | ! 27 | METHOD quo: arg 28 | ^ < 59 self arg >. 29 | ! 30 | METHOD rem: arg 31 | ^ < 60 self arg >. 32 | ! 33 | METHOD printString 34 | "String toString()" 35 | ^ < 39 String 'java.lang.Long' 'toString' self >. 36 | ! 37 | -------------------------------------------------------------------------------- /Smalltalk/SmallJ.cmd: -------------------------------------------------------------------------------- 1 | start javaw --enable-preview -jar SmallJ.jar >SmallJ.log 2 | -------------------------------------------------------------------------------- /Smalltalk/SmallJ.code-workspace: -------------------------------------------------------------------------------- 1 | { 2 | "folders": [ 3 | { 4 | "path": "." 5 | }, 6 | { 7 | "path": "../VM" 8 | }, 9 | { 10 | "path": "../Documentation" 11 | } 12 | ], 13 | "settings": {} 14 | } 15 | -------------------------------------------------------------------------------- /Smalltalk/SmallJ.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smalljvm/SmallJ/430990e4dd143db15fd78063258000bfe38c9b9c/Smalltalk/SmallJ.jar -------------------------------------------------------------------------------- /Smalltalk/SmallJ.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smalljvm/SmallJ/430990e4dd143db15fd78063258000bfe38c9b9c/Smalltalk/SmallJ.png -------------------------------------------------------------------------------- /Smalltalk/image.sjim: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smalljvm/SmallJ/430990e4dd143db15fd78063258000bfe38c9b9c/Smalltalk/image.sjim -------------------------------------------------------------------------------- /VM/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "type": "java", 9 | "name": "Launch SmallJApp", 10 | "request": "launch", 11 | "mainClass": "SmallJApp", 12 | "cwd": "${workspaceFolder}/../Smalltalk" } 13 | ] 14 | } -------------------------------------------------------------------------------- /VM/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "cmake.configureOnOpen": false 3 | } -------------------------------------------------------------------------------- /VM/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "type": "java", 6 | "label": "java: exportjar:SmallJ", 7 | "mainClass": "SmallJApp", 8 | "targetPath": "${workspaceFolder}/../Smalltalk/SmallJ.jar", 9 | "elements": [ 10 | "${compileOutput}", 11 | "${dependencies}" 12 | ], 13 | "problemMatcher": [], 14 | "group": { 15 | "kind": "build", 16 | "isDefault": true 17 | } 18 | } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /VM/lib/commons-beanutils-1.9.4.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smalljvm/SmallJ/430990e4dd143db15fd78063258000bfe38c9b9c/VM/lib/commons-beanutils-1.9.4.jar -------------------------------------------------------------------------------- /VM/lib/commons-lang3-3.12.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smalljvm/SmallJ/430990e4dd143db15fd78063258000bfe38c9b9c/VM/lib/commons-lang3-3.12.0.jar -------------------------------------------------------------------------------- /VM/lib/commons-logging-1.2.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smalljvm/SmallJ/430990e4dd143db15fd78063258000bfe38c9b9c/VM/lib/commons-logging-1.2.jar -------------------------------------------------------------------------------- /VM/src/META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Main-Class: smallj.core.SmallJApp 3 | 4 | -------------------------------------------------------------------------------- /VM/src/smallj/core/JavaArgs.java: -------------------------------------------------------------------------------- 1 | // Small helper class for pairing java argument types and values used with typed method invocation. 2 | 3 | // @SuppressWarnings( "rawtypes" ) 4 | public class JavaArgs 5 | { 6 | public Class[] types; 7 | public Object[] values; 8 | 9 | JavaArgs( Class[] aTypes, Object[] aValues ) 10 | { 11 | types = aTypes; 12 | values = aValues; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /VM/src/smallj/core/MethodCache.java: -------------------------------------------------------------------------------- 1 | // Caches for message sends 2 | 3 | public class MethodCache 4 | { 5 | static final int cacheSize = 197; 6 | SmallObject[] selectors = new SmallObject[ cacheSize ]; 7 | SmallObject[] classes = new SmallObject[ cacheSize ]; 8 | SmallObject[] methods = new SmallObject[ cacheSize ];; 9 | 10 | public static long hits = 0; 11 | public static long misses = 0; 12 | 13 | // Lookup and return method in the cache 14 | // If not found, lookup method in Smalltalk and add it to the cache. 15 | // If still not found throw SmallException. 16 | 17 | SmallObject lookupOrSave( SmallContext context, SmallObject aSelector ) 18 | throws SmallException 19 | { 20 | SmallObject aClass = context.getSelf().objClass; 21 | 22 | // Hash lookup values to array index. 23 | int index = Math.abs( aClass.hashCode() + aSelector.hashCode() ) % cacheSize; 24 | SmallObject selector = selectors[ index ]; 25 | SmallObject _class = classes[ index ]; 26 | SmallObject method = methods[ index ]; 27 | 28 | // If not found, lookup method in context and add it to cache 29 | if( selector == null || selector != aSelector || _class != aClass ) { 30 | ++misses; 31 | method = context.lookupMethod( aClass, ( SmallByteArray ) aSelector ); 32 | selectors[ index ] = aSelector; 33 | classes[ index ] = aClass; 34 | methods[ index ] = method; 35 | } 36 | else 37 | ++hits; 38 | 39 | return method; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /VM/src/smallj/core/SmallBlock.java: -------------------------------------------------------------------------------- 1 | // Encapsulated access to smalltalk Bock instances. 2 | 3 | // Smalltalk definitions: 4 | // Context variables: 'method arguments temporaries stack bytePointer stackTop previousContext ' 5 | // Block variables, after Context: 'argumentLocation creatingContext oldBytePointer' 6 | 7 | public class SmallBlock extends SmallContext 8 | { 9 | 10 | public static final int objectSize = 10; 11 | 12 | // Block variable indices, after Context 13 | public final static int argumentLocationIndex = 7; 14 | public final static int creatingContextIndex = 8; 15 | public final static int oldCodesPointerIndex = 9; 16 | 17 | SmallBlock( SmallImage aImage ) 18 | { 19 | image = aImage; 20 | objClass = image.blockClass; 21 | data = new SmallObject[ objectSize ]; 22 | } 23 | 24 | SmallBlock( SmallContext context, int argumentLocation ) 25 | { 26 | image = context.image; 27 | objClass = image.blockClass; 28 | data = new SmallObject[ objectSize ]; 29 | 30 | data[ methodIndex ] = context.data[ methodIndex ]; 31 | data[ argumentVarsIndex ] = context.data[ argumentVarsIndex ]; 32 | data[ temporaryVarsIndex ] = context.data[ temporaryVarsIndex ]; 33 | data[ stackIndex ] = context.data[ stackIndex ]; // later replaced 34 | data[ codesPointerIndex ] = image.newInteger( context.codesPointer ); 35 | data[ stackTopIndex ] = image.smallInts[ 0 ]; 36 | data[ previousContextIndex ] = context.data[ previousContextIndex ]; 37 | data[ argumentLocationIndex ] = image.newInteger( argumentLocation ); 38 | data[ creatingContextIndex ] = context; 39 | data[ oldCodesPointerIndex ] = image.newInteger( context.codesPointer ); 40 | } 41 | 42 | // Prepare self as invokable context, with arguments from the stack. 43 | // Also saves argument context for later return. 44 | // Returns this. 45 | 46 | // Stack: < 8 self > or < 8 arg1 self > or < 8 arg1 arg2 self > 47 | // The stack order is non-standard here to be able to determine the variable number of arguments. 48 | 49 | SmallBlock invoke( int argCount, SmallContext context ) 50 | { 51 | // Save context. 52 | context.data[ stackTopIndex ] = image.newInteger( context.stackTop ); 53 | context.data[ codesPointerIndex ] = image.newInteger( context.codesPointer ); 54 | 55 | // Retrieve arguments. 56 | int argBase = ( ( SmallInt ) data[ argumentLocationIndex ] ).value; 57 | int blockArgCount = argCount - 2; 58 | if( blockArgCount >= 0 ) { 59 | SmallObject[] _temporaryVars = data[ temporaryVarsIndex ].data; 60 | while( blockArgCount >= 0 ) { 61 | _temporaryVars[ argBase + blockArgCount-- ] = context.stackPop(); 62 | } 63 | } 64 | 65 | data[ previousContextIndex ] = context.data[ previousContextIndex ]; 66 | data[ stackTopIndex ] = image.smallInts[ 0 ]; 67 | data[ codesPointerIndex ] = data[ oldCodesPointerIndex ]; // starting address 68 | int stackSize = data[ stackIndex ].data.length; 69 | data[ stackIndex ] = new SmallObject( image.arrayClass, stackSize ); 70 | 71 | return this; 72 | } 73 | 74 | // Set single argument for self. 75 | 76 | void setOneArg( SmallObject arg1 ) 77 | { 78 | int argLoc = ( ( SmallInt ) data[ argumentLocationIndex ] ).value; 79 | data[ temporaryVarsIndex ].data[ argLoc ] = arg1; 80 | } 81 | 82 | // Set two arguments for self. 83 | 84 | void setTwoArgs( SmallObject arg1, SmallObject arg2 ) 85 | { 86 | int argLoc = ( ( SmallInt ) data[ argumentLocationIndex ] ).value; 87 | data[ temporaryVarsIndex ].data[ argLoc ] = arg1; 88 | data[ temporaryVarsIndex ].data[ argLoc + 1 ] = arg2; 89 | } 90 | 91 | void prepareRun() 92 | { 93 | int stackSize = data[ SmallContext.stackIndex ].data.length; 94 | data[ stackIndex ] = new SmallObject( image.arrayClass, stackSize ); 95 | data[ stackTopIndex ] = image.newInteger( 0 ); 96 | data[ codesPointerIndex ] = data[ oldCodesPointerIndex ]; 97 | data[ previousContextIndex ] = image.nilObject; 98 | } 99 | 100 | void copyDataFrom( SmallObject sourceBlock ) 101 | { 102 | System.arraycopy( sourceBlock.data, 0, data, 0, objectSize ); 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /VM/src/smallj/core/SmallByteArray.java: -------------------------------------------------------------------------------- 1 | class SmallByteArray extends SmallObject 2 | { 3 | public byte[] values; 4 | 5 | public SmallByteArray( SmallObject aClass, int size ) 6 | { 7 | super( aClass, 0 ); 8 | values = new byte[ size ]; 9 | } 10 | 11 | public SmallByteArray( SmallObject aClass, String text ) 12 | { 13 | super( aClass, 0 ); 14 | int size = text.length(); 15 | values = new byte[ size ]; 16 | for( int i = 0; i < size; i++ ) 17 | values[ i ] = ( byte ) text.charAt( i ); 18 | } 19 | 20 | @Override 21 | public SmallObject copy( SmallObject aClass ) 22 | { 23 | SmallByteArray newObj = new SmallByteArray( aClass, values.length ); 24 | for( int i = 0; i < values.length; i++ ) { 25 | newObj.values[ i ] = values[ i ]; 26 | } 27 | return newObj; 28 | } 29 | 30 | @Override 31 | public String toString() 32 | { 33 | // we assume its a string, tho not always true... 34 | return new String( values ); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /VM/src/smallj/core/SmallClass.java: -------------------------------------------------------------------------------- 1 | // Some encapsulation for Smalltalk class: Class 2 | // Object subclass: 'Class' 3 | // variables: 'name parentClass methods size variables sourceFileName' 4 | // classVariables: 'classes Parser' 5 | 6 | public class SmallClass extends SmallObject 7 | { 8 | // Number of instance variables in de Smalltalk Class class. 9 | // It is important that this is set correctly. 10 | public final static int instVarCount = 6; 11 | 12 | // Instance variable indices 13 | public final static int nameIndex = 0; 14 | public final static int parentClassIndex = 1; 15 | public final static int methodsIndex = 2; 16 | public final static int sizeIndex = 3; 17 | public final static int variablesIndex = 4; 18 | 19 | // Class variable indices 20 | public final static int classesIndex = 0; 21 | } 22 | -------------------------------------------------------------------------------- /VM/src/smallj/core/SmallException.java: -------------------------------------------------------------------------------- 1 | class SmallException extends Exception 2 | { 3 | // Unique number for serializing. Unused but prevents VSCode warning. 4 | private static final long serialVersionUID = 750551701695347665L; 5 | 6 | public SmallObject context; 7 | 8 | SmallException( String errorMessage, SmallObject aContext ) 9 | { 10 | super( errorMessage ); 11 | context = aContext; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /VM/src/smallj/core/SmallFloat.java: -------------------------------------------------------------------------------- 1 | class SmallFloat extends SmallObject 2 | { 3 | // Smalltalk float is represented as a Java double precision floating point number. 4 | public double value; 5 | 6 | public SmallFloat( SmallObject floatClass, double aValue ) 7 | { 8 | super( floatClass, 0 ); 9 | value = aValue; 10 | } 11 | 12 | @Override 13 | public String toString() 14 | { 15 | return "SmallFloat: " + value; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /VM/src/smallj/core/SmallImage.java: -------------------------------------------------------------------------------- 1 | import java.io.*; 2 | 3 | /** 4 | Maintains Smalltalk image. 5 | 6 | Holds references to specific objects in the system: 7 | nil, true, false, Array, Block, Context, Integer and the numbers 0-9. 8 | 9 | From these references, you can get to Class, which holds 10 | references to all the classes in the system in Class#classes. 11 | 12 | Performs loading and saving from and to a file. 13 | Only the basic objects above, all classes and their instance variables are saved in the image. 14 | SmallJavaObjects are not saved. 15 | */ 16 | 17 | public class SmallImage 18 | { 19 | public static SmallImage current; 20 | 21 | static final int magic = 0x534A494D ; // "SJIM" 22 | static final int version = 0; 23 | 24 | // Object types in image 25 | static final int smallObjectType = 0; 26 | static final int smallIntType = 1; 27 | static final int smallByteArrayType = 2; 28 | static final int smallFloatType = 3; 29 | 30 | String fileName; 31 | 32 | public int smallIntsLength = 10; 33 | 34 | // Global constants, in order of location in image. 35 | public SmallObject nilObject; 36 | public SmallObject trueObject; 37 | public SmallObject falseObject; 38 | public SmallInt[] smallInts; 39 | public SmallObject arrayClass; 40 | public SmallObject blockClass; 41 | public SmallObject contextClass; 42 | public SmallObject integerClass; 43 | public SmallObject stringClass; 44 | public SmallObject floatClass; 45 | public SmallObject charClass; 46 | public SmallObject longClass; 47 | 48 | SmallImage() 49 | { 50 | current = this; 51 | } 52 | 53 | // Load image from file. 54 | 55 | public void load( String aFileName ) 56 | throws Exception 57 | { 58 | fileName = aFileName; 59 | 60 | new SmallImageReader( this ).load( fileName ); 61 | } 62 | 63 | public void saveAs( String aFileName ) 64 | throws IOException 65 | { 66 | fileName = aFileName; 67 | save(); 68 | } 69 | public void save() 70 | throws IOException 71 | { 72 | new SmallImageWriter( this ).save( fileName ); 73 | } 74 | 75 | SmallInt newInteger( int value ) 76 | { 77 | // Optimized case for integers [ 0 .. 9 ]. 78 | if( value >= 0 && value < smallIntsLength ) 79 | return smallInts[ value ]; 80 | 81 | return new SmallInt( integerClass, value ); 82 | } 83 | 84 | SmallLong newLong( long value ) 85 | { 86 | return new SmallLong( longClass, value ); 87 | } 88 | 89 | // Smalltalk Float class is implemented with Java double type. 90 | 91 | SmallFloat newFloat( double value ) 92 | { 93 | return new SmallFloat( floatClass, value ); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /VM/src/smallj/core/SmallImageReader.java: -------------------------------------------------------------------------------- 1 | import java.io.*; 2 | 3 | // Load image file indicated by argument. 4 | 5 | public class SmallImageReader 6 | { 7 | private SmallImage image; 8 | private DataInputStream stream; 9 | 10 | int objCount; 11 | private SmallObject[] objArray; 12 | 13 | public SmallImageReader( SmallImage aImage ) 14 | { 15 | image = aImage; 16 | } 17 | 18 | void load( String fileName ) 19 | throws IOException 20 | { 21 | stream = new DataInputStream( new FileInputStream( fileName ) ); 22 | 23 | readHeader(); 24 | readObjectTypes(); 25 | readObjectValues(); 26 | readRootObjects(); 27 | 28 | stream.close(); 29 | } 30 | 31 | private void readHeader() 32 | throws IOException 33 | { 34 | if( stream.readInt() != SmallImage.magic ) 35 | throw new RuntimeException( "Bad magic number." ); 36 | 37 | if( stream.readInt() != SmallImage.version ) 38 | throw new RuntimeException( "Bad version number." ); 39 | 40 | objCount = stream.readInt(); 41 | } 42 | 43 | // Construct placeholder objects in objArray. 44 | // Index is used for object references. 45 | 46 | private void readObjectTypes() 47 | throws IOException 48 | { 49 | objArray = new SmallObject[ objCount ]; 50 | 51 | for( int index = 0; index < objCount; index++ ) { 52 | int objType = stream.readByte(); 53 | switch( objType ) { 54 | case SmallImage.smallObjectType: 55 | objArray[ index ] = new SmallObject(); 56 | break; 57 | case SmallImage.smallIntType: 58 | objArray[ index ] = new SmallInt( null, 0 ); 59 | break; 60 | case SmallImage.smallByteArrayType: 61 | objArray[ index ] = new SmallByteArray( null, 0 ); 62 | break; 63 | case SmallImage.smallFloatType: 64 | objArray[ index ] = new SmallFloat( null, 0 ); 65 | break; 66 | default: 67 | throw new RuntimeException( "Unknown object type: " + objType ); 68 | } 69 | } 70 | } 71 | 72 | // Create data members in objects 73 | // and point them to the correct objects in objArray using the index as ids. 74 | 75 | private void readObjectValues() 76 | throws IOException 77 | { 78 | for( int index = 0; index < objCount; index++ ) { 79 | SmallObject obj = objArray[ index ]; 80 | obj.objClass = objArray[ stream.readInt() ]; 81 | int dataLength = stream.readInt(); 82 | if( dataLength == - 1 ) { 83 | obj.data = null; 84 | } else { 85 | obj.data = new SmallObject[ dataLength ]; 86 | for( int dataIndex = 0; dataIndex < dataLength; dataIndex++ ) { 87 | obj.data[ dataIndex ] = objArray[ stream.readInt() ]; 88 | } 89 | } 90 | 91 | // Set type specific data in value member of objects 92 | if( obj instanceof SmallInt ) { 93 | SmallInt smallInt = ( SmallInt ) obj; 94 | smallInt.value = stream.readInt(); 95 | } 96 | else if( obj instanceof SmallFloat ) { 97 | SmallFloat smallFloat = ( SmallFloat ) obj; 98 | smallFloat.value = stream.readDouble(); 99 | } 100 | else if( obj instanceof SmallByteArray ) { 101 | SmallByteArray smallByteArray = ( SmallByteArray ) obj; 102 | int arrayLength = stream.readInt(); 103 | smallByteArray.values = new byte[ arrayLength ]; 104 | stream.read( smallByteArray.values ); 105 | } 106 | } 107 | } 108 | 109 | private void readRootObjects() 110 | throws IOException 111 | { 112 | // Number of small integers with fixed allocation in image, normally 10. 113 | image.smallIntsLength = stream.readInt(); 114 | 115 | // Read root objects 116 | image.nilObject = readNextRoot(); 117 | image.trueObject = readNextRoot(); 118 | image.falseObject = readNextRoot(); 119 | image.smallInts = new SmallInt[ image.smallIntsLength ]; 120 | for( int index = 0; index < image.smallIntsLength; index++ ) 121 | image.smallInts[ index ] = ( SmallInt ) readNextRoot(); 122 | image.arrayClass = readNextRoot(); 123 | image.blockClass = readNextRoot(); 124 | image.contextClass = readNextRoot(); 125 | image.integerClass = readNextRoot(); 126 | image.stringClass = readNextRoot(); 127 | image.floatClass = readNextRoot(); 128 | image.longClass = readNextRoot(); 129 | } 130 | 131 | SmallObject readNextRoot() 132 | throws IOException 133 | { 134 | return objArray[ stream.readInt() ]; 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /VM/src/smallj/core/SmallImageWriter.java: -------------------------------------------------------------------------------- 1 | // Recursively writes basic objects, their classes and their member variables to the image. 2 | // All classes can be found this way because the Class object is the parent of all meta classes, 3 | // and it has a member variable than contains all classes. 4 | 5 | import java.io.DataOutputStream; 6 | import java.io.FileOutputStream; 7 | import java.io.IOException; 8 | import java.util.ArrayList; 9 | import java.util.HashMap; 10 | import java.util.Map; 11 | import java.util.TreeMap; 12 | 13 | class SmallImageWriter 14 | { 15 | SmallImage image; 16 | 17 | // Variables used while saving. 18 | DataOutputStream stream; 19 | private int objectCount; 20 | private TreeMap< Integer, SmallObject > indexToObjectMap; 21 | private HashMap< SmallObject, Integer > objectToIndexMap; 22 | private ArrayList< Integer > rootIds; 23 | 24 | public SmallImageWriter( SmallImage aImage ) 25 | { 26 | image = aImage; 27 | } 28 | 29 | // Main method: Save image to named file. 30 | 31 | public void save( String fileName ) 32 | throws IOException 33 | { 34 | // Fill Id maps. 35 | initialize(); 36 | mapRootObjects(); 37 | 38 | // Write out file 39 | stream = new DataOutputStream( new FileOutputStream( fileName ) ); 40 | 41 | writeHeader(); 42 | writeObjectTypes(); 43 | writeObjectValues(); 44 | writeRootObjects(); 45 | 46 | stream.close(); 47 | } 48 | 49 | // Initialize for a new image save. 50 | 51 | private void initialize() 52 | { 53 | objectToIndexMap = new HashMap<>(); 54 | indexToObjectMap = new TreeMap<>(); 55 | rootIds = new ArrayList<>(); 56 | objectCount = 0; 57 | } 58 | 59 | // Map image objects and classes to IDs. 60 | 61 | private void mapRootObjects() 62 | { 63 | mapRootObject( image.nilObject ); 64 | mapRootObject( image.trueObject ); 65 | mapRootObject( image.falseObject ); 66 | for( SmallInt smallInt : image.smallInts ) 67 | mapRootObject( smallInt ); 68 | mapRootObject( image.arrayClass ); 69 | mapRootObject( image.blockClass ); 70 | mapRootObject( image.contextClass ); 71 | mapRootObject( image.integerClass ); 72 | mapRootObject( image.stringClass ); 73 | mapRootObject( image.floatClass ); 74 | mapRootObject( image.longClass ); 75 | } 76 | 77 | private void mapRootObject( SmallObject obj ) 78 | { 79 | mapObjectAndChildren( obj ); 80 | rootIds.add( objectToIndexMap.get( obj ) ); 81 | } 82 | 83 | private void mapObjectAndChildren( SmallObject obj ) 84 | { 85 | if( ! objectToIndexMap.containsKey( obj ) ) { 86 | objectToIndexMap.put( obj, objectCount ); 87 | indexToObjectMap.put( objectCount, obj ); 88 | objectCount++; 89 | mapObjectAndChildren( obj.objClass ); 90 | if( obj.data != null ) { 91 | for( SmallObject child : obj.data ) { 92 | mapObjectAndChildren( child ); 93 | } 94 | } 95 | } 96 | } 97 | 98 | // Write out objects in internal tables to output stream. 99 | 100 | private void writeHeader() 101 | throws IOException 102 | { 103 | // Write header: magic number, version and object count 104 | stream.writeInt( SmallImage.magic ); 105 | stream.writeInt( SmallImage.version ); 106 | stream.writeInt( objectCount ); 107 | } 108 | 109 | private void writeObjectTypes() 110 | throws IOException 111 | { 112 | for( Map.Entry< Integer, SmallObject > entry : indexToObjectMap.entrySet() ) { 113 | SmallObject obj = entry.getValue(); 114 | if( obj instanceof SmallByteArray ) { 115 | stream.writeByte( SmallImage.smallByteArrayType ); 116 | } else if( obj instanceof SmallInt ) { 117 | stream.writeByte( SmallImage.smallIntType ); 118 | } else if( obj instanceof SmallFloat ) { 119 | stream.writeByte( SmallImage.smallFloatType ); 120 | } else if( obj instanceof SmallJavaObject ) { 121 | throw new RuntimeException( "JavaObject serialization not supported." ); 122 | } else { 123 | stream.writeByte( SmallImage.smallObjectType ); 124 | } 125 | } 126 | } 127 | 128 | private void writeObjectValues() 129 | throws IOException 130 | { 131 | for( Map.Entry< Integer, SmallObject > entry : indexToObjectMap.entrySet() ) { 132 | SmallObject obj = entry.getValue(); 133 | stream.writeInt( objectToIndexMap.get( obj.objClass ) ); 134 | // data (-1 if none) 135 | if( obj.data == null ) { 136 | stream.writeInt( - 1 ); 137 | } else { 138 | stream.writeInt( obj.data.length ); 139 | for( SmallObject child : obj.data ) { 140 | stream.writeInt( objectToIndexMap.get( child ) ); 141 | } 142 | } 143 | if( obj instanceof SmallInt ) { 144 | stream.writeInt( ( ( SmallInt ) obj ).value ); 145 | } 146 | if( obj instanceof SmallFloat ) { 147 | stream.writeDouble( ( ( SmallFloat ) obj ).value ); 148 | } 149 | if( obj instanceof SmallByteArray ) { 150 | SmallByteArray smallByteArray = ( SmallByteArray ) obj; 151 | stream.writeInt( smallByteArray.values.length ); 152 | stream.write( smallByteArray.values ); 153 | } 154 | } 155 | } 156 | 157 | private void writeRootObjects() 158 | throws IOException 159 | { 160 | // Write the count of small integers (special case) 161 | stream.writeInt( image.smallIntsLength ); 162 | 163 | for( Integer rootId : rootIds ) { 164 | stream.writeInt( rootId ); 165 | } 166 | } 167 | } 168 | -------------------------------------------------------------------------------- /VM/src/smallj/core/SmallInt.java: -------------------------------------------------------------------------------- 1 | class SmallInt extends SmallObject 2 | { 3 | public int value; 4 | 5 | public SmallInt( SmallObject integerClass, int aValue ) 6 | { 7 | super( integerClass, 0 ); 8 | value = aValue; 9 | } 10 | 11 | @Override 12 | public String toString() 13 | { 14 | return "SmallInt: " + value; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /VM/src/smallj/core/SmallJApp.java: -------------------------------------------------------------------------------- 1 | import javax.swing.*; 2 | import java.awt.*; 3 | 4 | public class SmallJApp 5 | { 6 | public SmallImage image; 7 | public SmallInterpreter interpreter; 8 | 9 | public static void main( String[] args ) 10 | { 11 | new SmallJApp().run( args ); 12 | } 13 | 14 | // First argument is image filename. 15 | // Second argument is Smalltalk startup expression. 16 | 17 | void run( String[] args ) 18 | { 19 | // setDefaultFont(); 20 | String defaultImageFileName = "image.sjim"; 21 | String defaultStartupExpression = "SystemBrowser show"; 22 | 23 | if( args.length >= 1 && ( args[ 0 ].equals( "-?" ) || args[ 0 ].equals( "/?" ) ) ) { 24 | System.out.println( "Usage: SmallJ [ image filename ] [ \"startup expression\" ]" ); 25 | System.out.println( " Default image filename: " + defaultImageFileName ); 26 | System.out.println( " Default startup expression: \"" + defaultStartupExpression + "\"" ); 27 | System.out.println( " Remember to quote the startup expression to make it a single string." ); 28 | System.exit( 0 ); 29 | } 30 | String imageFileName = args.length >= 1 ? args[ 0 ] : defaultImageFileName; 31 | if( ! loadImage( imageFileName ) ) 32 | System.exit( 1 ); 33 | 34 | String expression = args.length >= 2 ? args[ 1 ] : defaultStartupExpression; 35 | startInterpreter( expression ); 36 | } 37 | 38 | // Set default for for easier code reading. 39 | // Todo? Move to Smalltalk. 40 | 41 | public void setDefaultFont() 42 | { 43 | System.out.println(javax.swing.UIManager.getDefaults().getFont("Dialog.font")); 44 | 45 | Font defaultFont = new Font( "Consolas", Font.PLAIN, 14 ); 46 | Font defaultBoldFont = defaultFont.deriveFont( Font.BOLD ); 47 | 48 | UIManager.getLookAndFeelDefaults().put( "defaultFont", defaultFont ); 49 | 50 | java.util.Enumeration keys = UIManager.getDefaults().keys(); 51 | while( keys.hasMoreElements() ) { 52 | Object key = keys.nextElement(); 53 | Object object = UIManager.get( key ); 54 | if( object instanceof javax.swing.plaf.FontUIResource ) { 55 | Font currentFont = ( Font ) object; 56 | Font newFont = currentFont.isBold() ? defaultBoldFont : defaultFont; 57 | UIManager.put( key, newFont ); 58 | } 59 | } 60 | } 61 | 62 | // Load image in filename. Return true 63 | boolean loadImage( String imageFileName ) 64 | { 65 | image = new SmallImage(); 66 | try { 67 | image.load( imageFileName ); 68 | } catch( Exception e ) { 69 | System.err.println( "SmallJ: Error reading image: " + imageFileName ); 70 | return false; 71 | } 72 | return true; 73 | } 74 | 75 | void startInterpreter( String expression ) 76 | { 77 | interpreter = new SmallInterpreter( image ); 78 | try { 79 | interpreter.executeExpression( expression ); 80 | } catch( Exception e ) { 81 | System.err.println( "SmallJ: Error executing startup expression: " + expression + ": " + e ); 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /VM/src/smallj/core/SmallLong.java: -------------------------------------------------------------------------------- 1 | class SmallLong extends SmallObject 2 | { 3 | public long value; 4 | 5 | public SmallLong( SmallObject longClass, long aValue ) 6 | { 7 | super( longClass, 0 ); 8 | value = aValue; 9 | } 10 | 11 | @Override 12 | public String toString() 13 | { 14 | return "SmallLong: " + value; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /VM/src/smallj/core/SmallObject.java: -------------------------------------------------------------------------------- 1 | public class SmallObject 2 | { 3 | public SmallObject[] data; 4 | public SmallObject objClass; 5 | 6 | public SmallObject() 7 | { 8 | objClass = null; 9 | data = null; 10 | } 11 | 12 | public SmallObject( SmallObject smallObject ) 13 | { 14 | objClass = smallObject.objClass; 15 | data = smallObject.data; 16 | } 17 | 18 | public SmallObject( SmallObject aClass, int size ) 19 | { 20 | objClass = aClass; 21 | data = new SmallObject[ size ]; 22 | while( size > 0 ) 23 | data[ -- size ] = SmallImage.current.nilObject; 24 | } 25 | 26 | public SmallObject copy( SmallObject aClass ) 27 | { 28 | return this; 29 | } 30 | 31 | // Resize data array to new size. 32 | // Copy old data as much as possible. 33 | // New empty slots are set to nilObject. 34 | 35 | public void resize( int newSize ) 36 | { 37 | SmallObject[] newData = new SmallObject[ newSize ]; 38 | 39 | int copySize = Math.min( newSize, data.length ); 40 | System.arraycopy( data, 0, newData, 0, copySize ); 41 | 42 | // Fill remaining part with nil objects 43 | for( int index = copySize; index < newSize; ++ index ) 44 | newData[ index ] = SmallImage.current.nilObject; 45 | 46 | data = newData; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /VM/src/smallj/core/SmallThread.java: -------------------------------------------------------------------------------- 1 | import javax.swing.*; 2 | import java.util.EventObject; 3 | 4 | import static javax.swing.JOptionPane.ERROR_MESSAGE; 5 | 6 | public class SmallThread extends Thread 7 | { 8 | private final SmallBlock block; 9 | private final Thread myThread; 10 | 11 | public SmallThread( SmallObject aBlock, Thread aMyThread ) 12 | { 13 | myThread = aMyThread; 14 | block = new SmallBlock( SmallImage.current ); 15 | block.copyDataFrom( aBlock ); 16 | } 17 | 18 | public SmallThread( SmallObject aBlock, Thread aMyThread, SmallObject smallEventClass, EventObject event ) 19 | { 20 | this( aBlock, aMyThread ); 21 | SmallJavaObject smallEventObject = new SmallJavaObject( smallEventClass, event ); 22 | block.setOneArg( smallEventObject ); 23 | } 24 | 25 | @Override 26 | public void run() 27 | { 28 | block.prepareRun(); 29 | try { 30 | new SmallInterpreter( SmallImage.current ).execute( block, this, myThread ); 31 | } catch( Exception e ) { 32 | JOptionPane.showMessageDialog( null, e, "Exception", ERROR_MESSAGE ); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /VM/workspace.code-workspace: -------------------------------------------------------------------------------- 1 | { 2 | "folders": [ 3 | { 4 | "path": "." 5 | }, 6 | { 7 | "path": "..\\Smalltalk" 8 | }, 9 | { 10 | "path": "..\\Documentation" 11 | } 12 | ], 13 | "settings": {} 14 | } --------------------------------------------------------------------------------