Marcel Taeumel uploaded a new version of FFI-Kernel to project FFI:
http://source.squeak.org/FFI/FFI-Kernel-mt.124.mcz
==================== Summary ====================
Name: FFI-Kernel-mt.124
Author: mt
Time: 1 May 2021, 6:29:01.295408 pm
UUID: 7c619637-8c9f-5648-b752-5043a9a455c9
Ancestors: FFI-Kernel-mt.123
Removes deprecated collection interface from ExternalData.
Nukes unused instVar 'fieldTypes' in structure types. I could not remember what I planned to do with it. Could not find it on squeak-dev either.
Extends print-string for external types with byteSize and byteAlignment. It does not look too noisy. I hope it will help remind programmers about the bytes they are working with. Well, if it becomes too noisy, we could make it a preference.
=============== Diff against FFI-Kernel-mt.123 ===============
Item was removed:
- ----- Method: ExternalData>>collectWithIndex: (in category 'enumerating') -----
- collectWithIndex: elementAndIndexBlock
- "See SequenceableCollection >> #collectWithIndex:."
-
- ^ self collectWithIndex: elementAndIndexBlock!
Item was removed:
- ----- Method: ExternalData>>doWithIndex: (in category 'enumerating') -----
- doWithIndex: elementAndIndexBlock
- "See SequenceableCollection >> #doWithIndex:."
-
- self withIndexDo: elementAndIndexBlock.!
Item was changed:
ExternalType subclass: #ExternalStructureType
+ instanceVariableNames: ''
- instanceVariableNames: 'fieldTypes'
classVariableNames: ''
poolDictionaries: ''
category: 'FFI-Kernel'!
!ExternalStructureType commentStamp: 'mt 6/18/2020 08:54' prior: 0!
I am specializing types for external structures. While compiledSpec and referentClass are still paramount when the FFI plugin is processing FFI calls, this specialization can help untangle in-image processing of external structures and their data.
In terms of plugin compatibility, you could still use instances of ExternalType as, for example, argument types in ExternalFunction -- given that compiledSpec and referentClass are correct. Argument coercing in FFI calls would still work. However, you could no longer use in-image facilities such as #readFieldAt: / #writeFieldAt:width, which is used for generating struct-field accessors. And the dynamic access through #handle:at: / #handle:at:put: would fail. Also, #printOn: would not be very helpful anymore.
So, having this specialization of ExternalType for ExternalStructure helps packaging code. :-) Of course, this type can also be used for ExternalUnion, ExternalPackagedStructure, and ExternalTypeAlias.!
Item was changed:
----- Method: ExternalStructureType>>printOn: (in category 'printing') -----
printOn: aStream
self isTypeAlias ifTrue: [
aStream nextPutAll: referentClass name.
aStream
nextPutAll: '~>';
print: self originalType.
self isEmpty
ifTrue: [aStream nextPutAll: ' ???'].
^ self].
referentClass == nil
ifTrue:[aStream nextPutAll: '<unknown struct type>']
ifFalse:[
+ super printOn: aStream.
- aStream nextPutAll: referentClass name.
self isEmpty
ifTrue: [aStream nextPutAll: ' { void }']].!
Item was changed:
----- Method: ExternalType>>printOn: (in category 'printing') -----
printOn: aStream
aStream nextPutAll: (referentClass ifNil: [self atomicTypeName] ifNotNil: [referentClass name]).
+ self isPointerType ifTrue: [aStream nextPut: $*].
+
+ aStream
+ space;
+ nextPut: $(;
+ nextPutAll: self byteSize asString;
+ space;
+ nextPutAll: self byteAlignment asString;
+ nextPut: $).!
- self isPointerType ifTrue: [aStream nextPut: $*].!
Marcel Taeumel uploaded a new version of Monticello to project The Trunk:
http://source.squeak.org/trunk/Monticello-ct.746.mcz
==================== Summary ====================
Name: Monticello-ct.746
Author: ct
Time: 1 May 2021, 2:41:51.667049 pm
UUID: 6079f513-f9db-2245-9e92-878ae823e5ee
Ancestors: Monticello-nice.745
Fixes and cleans up snapshot creation in MCVersionHistoryBrowser.
Instead of scanning the global repository group for a version, ask the current package for its specific repository group. Make sure to always pass the package. Nuke unused instvar repositoryGroup.
=============== Diff against Monticello-nice.745 ===============
Item was changed:
MCTool subclass: #MCVersionHistoryBrowser
+ instanceVariableNames: 'ancestry index package infos'
- instanceVariableNames: 'ancestry index repositoryGroup package infos'
classVariableNames: ''
poolDictionaries: ''
category: 'Monticello-UI'!
Item was changed:
----- Method: MCVersionHistoryBrowser>>repositoryGroup (in category 'accessing') -----
repositoryGroup
+
+ ^ self package workingCopy repositoryGroup!
- ^ MCRepositoryGroup default!
Item was changed:
----- Method: MCVersionInspector>>history (in category 'accessing') -----
history
+ (MCVersionHistoryBrowser new
+ package: self version package;
+ ancestry: self versionInfo) show!
- (MCVersionHistoryBrowser new ancestry: self versionInfo) show!
Marcel Taeumel uploaded a new version of Tools to project The Trunk:
http://source.squeak.org/trunk/Tools-mt.1054.mcz
==================== Summary ====================
Name: Tools-mt.1054
Author: mt
Time: 1 May 2021, 12:06:08.609299 pm
UUID: 9da21c77-f717-ab4c-b024-42dfbe629f2e
Ancestors: Tools-mt.1053
Adds preference and means to embed a transcript in workspaces. Thanks to Jaromir (jar) for the idea!
The preference is disabled by default.
=============== Diff against Tools-mt.1053 ===============
Item was changed:
StringHolder subclass: #Workspace
instanceVariableNames: 'bindings acceptDroppedMorphs acceptAction mustDeclareVariables shouldStyle environment'
+ classVariableNames: 'DeclareVariablesAutomatically EmbedTranscript LookupPools ShouldStyle'
- classVariableNames: 'DeclareVariablesAutomatically LookupPools ShouldStyle'
poolDictionaries: ''
category: 'Tools-Base'!
!Workspace commentStamp: 'fbs 6/2/2012 20:46' prior: 0!
A Workspace is a text area plus a lot of support for executable code. It is a great place to execute top-level commands to compute something useful, and it is a great place to develop bits of a program before those bits get put into class methods.
To open a new workspace, execute:
Workspace open
A workspace can have its own variables, called "workspace variables", to hold intermediate results. For example, if you type into a workspace "x := 5" and do-it, then later you could type in "y := x * 2" and y would become 10.
Additionally, in Morphic, a workspace can gain access to morphs that are on the screen. If acceptDroppedMorphs is turned on, then whenever a morph is dropped on the workspace, a variable will be created which references that morph. This functionality is toggled with the window-wide menu of a workspace.
The instance variables of this class are:
bindings - holds the workspace variables for this workspace
acceptDroppedMorphs - whether dropped morphs should create new variables!
Item was added:
+ ----- Method: Workspace class>>embedTranscript (in category 'preferences') -----
+ embedTranscript
+ <preference: 'Embed a Transcript in Workspace'
+ category: 'browsing'
+ description: 'If true, new workspaces will open with an embedded Transcript.'
+ type: #Boolean>
+ ^ EmbedTranscript ifNil: [ false ]!
Item was added:
+ ----- Method: Workspace class>>embedTranscript: (in category 'preferences') -----
+ embedTranscript: aBoolean
+
+ EmbedTranscript := aBoolean.!
Item was added:
+ ----- Method: Workspace>>buildTranscriptWith: (in category 'toolbuilder') -----
+ buildTranscriptWith: builder
+
+ | textSpec |
+ textSpec := builder pluggableTextSpec new.
+ textSpec
+ model: Transcript;
+ menu: #codePaneMenu:shifted:.
+ ^ textSpec!
Item was added:
+ ----- Method: Workspace>>buildWith: (in category 'toolbuilder') -----
+ buildWith: builder
+
+ ^ self class embedTranscript
+ ifTrue: [self buildWorkspaceTranscriptWith: builder]
+ ifFalse: [super buildWith: builder]!
Item was added:
+ ----- Method: Workspace>>buildWorkspaceTranscriptWith: (in category 'toolbuilder') -----
+ buildWorkspaceTranscriptWith: builder
+
+ | windowSpec |
+ windowSpec := self buildWindowWith: builder specs: {
+ (0.0 @ 0.0 corner: 1.0 @ 0.6) -> [self buildCodePaneWith: builder].
+ (0.0 @ 0.6 corner: 1.0 @ 1.0) -> [self buildTranscriptWith: builder].
+ }.
+ ^builder build: windowSpec!
Marcel Taeumel uploaded a new version of FFI-Kernel to project FFI:
http://source.squeak.org/FFI/FFI-Kernel-mt.123.mcz
==================== Summary ====================
Name: FFI-Kernel-mt.123
Author: mt
Time: 1 May 2021, 10:22:08.119394 am
UUID: 8a1725e7-90a1-2348-9e01-3ce391c4036f
Ancestors: FFI-Kernel-mt.122
Given that we usually talk to external types or external structures (and unions ...) where #allocate: is the current pattern to prepare a list of such things, use #allocateExternal: to allocate external memory, not internal object memory.
While this conflicts with ExternalAddress class #allocate:, clients might not notice because they should usually not deal with the difference between handles being either ByteArray or ExternalAddress (or atomics). I suppose.
Let #free for handles being ExternAdress also null that address. Maybe we could establish a common prototype for a null-address?
(Removes duplicate #isExternalAddress.)
=============== Diff against FFI-Kernel-mt.122 ===============
Item was removed:
- ----- Method: ByteArray>>isExternalAddress (in category '*FFI-Kernel-testing') -----
- isExternalAddress
- "Return true if the receiver describes the address of an object in the outside world"
- ^false!
Item was added:
+ ----- Method: ExternalStructure class>>allocateExternal: (in category 'instance creation') -----
+ allocateExternal: anInteger
+ "Create an ExternalData with enough room for storing an array of size anInteger of such structure. Don't forget to free the allocated memory!!!!!!"
+ ^self externalType allocateExternal: anInteger!
Item was changed:
----- Method: ExternalStructure>>free (in category 'initialize-release') -----
free
"Free the handle pointed to by the receiver"
+
+ handle isExternalAddress
+ ifTrue: [handle free; beNull]
+ ifFalse: [handle := nil].!
- (handle ~~ nil and:[handle isExternalAddress]) ifTrue:[handle free].
- handle := nil.!
Item was added:
+ ----- Method: ExternalType>>allocateExternal: (in category 'external data') -----
+ allocateExternal: anInteger
+ "Allocate space for containing an array of size anInteger of this dataType"
+
+ | handle |
+ handle := ExternalAddress allocate: self byteSize * anInteger.
+ ^(ExternalData fromHandle: handle type: self) size: anInteger!
Marcel Taeumel uploaded a new version of FFI-Callbacks to project FFI:
http://source.squeak.org/FFI/FFI-Callbacks-mt.7.mcz
==================== Summary ====================
Name: FFI-Callbacks-mt.7
Author: mt
Time: 1 May 2021, 9:06:54.87419 am
UUID: 1094c754-1e24-d342-8822-31dce676cd6a
Ancestors: FFI-Callbacks-mt.6
Fixes regression. I forgot to resolve materialize pointers from integers when reading intRegArgs.
(For debugging, adds #mostRecent shortcut to FFICallbackContext class.)
=============== Diff against FFI-Callbacks-mt.6 ===============
Item was changed:
----- Method: FFICallback>>evaluateDynamic: (in category 'callback - evaluators') -----
evaluateDynamic: callbackContext
"Read all arguments and make the call(back). Assume that 'handle' and 'type' are set correctly. Only watch out for the sign. See field definition in FFICallbackContext to explore alternative ways to read the arguments."
| byteOffset args intArgs intPos floatArgs floatPos |
handle := callbackContext stackPtr getHandle.
type := callbackContext stackPtr contentType.
byteOffset := 1.
intArgs := callbackContext integerArguments.
intPos := 0.
floatArgs := callbackContext floatArguments.
floatPos := 0.
args := Array new: argumentTypes size.
1 to: args size do: [:argIndex |
+ | argType data isPointer |
- | argType data |
argType := argumentTypes at: argIndex.
"1) Try to read arguments from registers."
+ data := (intPos < intArgs size and: [(isPointer := argType isPointerType) or: [argType isIntegerType]])
- data := (intPos < intArgs size and: [argType isPointerType or: [argType isIntegerType]])
ifTrue: [intPos := intPos + 1. intArgs at: intPos]
ifFalse: [(floatPos < floatArgs size and: [argType isFloatType])
ifTrue: [floatPos := floatPos + 1. floatArgs at: floatPos]].
+ data
+ ifNotNil: [ "1b) Materialize pointers from integers."
+ isPointer ifTrue: [
+ self flag: #designSmell. "mt: If we had a way to set, for example, double** as container type and double* as content type for intArgs, we would not have to construct the correct external object here but already had it."
+ self flag: #discuss. "mt: Should we resolve atomic types? That is, double* to an actual float object etc? Well, for pointers to external structures (unions, ...) it would make sense to provide an actual instance of that structure to the callback... If so, we just need to send #value below."
+ data := (ExternalData
+ fromHandle: (ExternalAddress fromInteger: data)
+ type: argType) size: 1; "value; " yourself]]
+ ifNil: [ "2) If nothing was read, read the argument from the stack."
+ data := argType handle: handle at: byteOffset.
+ byteOffset := byteOffset
+ + ((type byteSize max: argType byteSize) roundUpTo: type byteAlignment)].
- "2) If nothing was read, read the argument from the stack."
- data ifNil: [
- data := argType handle: handle at: byteOffset.
- byteOffset := byteOffset
- + ((type byteSize max: argType byteSize) roundUpTo: type byteAlignment)].
args at: argIndex put: data].
^ self
setResult: (evaluableObject valueWithArguments: args)
inContext: callbackContext!
Item was added:
+ ----- Method: FFICallbackContext class>>mostRecent (in category 'instance lookup') -----
+ mostRecent
+
+ ^ FFICallbackMemory mostRecentCallbackContext!
Marcel Taeumel uploaded a new version of FFI-Kernel to project FFI:
http://source.squeak.org/FFI/FFI-Kernel-mt.122.mcz
==================== Summary ====================
Name: FFI-Kernel-mt.122
Author: mt
Time: 1 May 2021, 8:25:28.22519 am
UUID: 6c3424fd-34f9-f44e-b109-3e27c0690885
Ancestors: FFI-Kernel-mt.121
Adds check to separate integer types from float types. There already is #isIntegerType. For example, callback handles can use this to choose between integer-registers and float-registers easily based on argument types.
=============== Diff against FFI-Kernel-mt.121 ===============
Item was added:
+ ----- Method: ExternalStructureType>>isFloatType (in category 'testing') -----
+ isFloatType
+ "Overwritten to not raise an error for struct types."
+
+ ^ false!
Item was added:
+ ----- Method: ExternalType>>isFloatType (in category 'testing') -----
+ isFloatType
+ "Return true if the receiver is a built-in float type"
+ | type |
+ type := self atomicType.
+ ^type = FFITypeSingleFloat or: [type = FFITypeDoubleFloat]!