VM Maker: VMMaker.oscog-AlistairGrant.2455.mcz

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

VM Maker: VMMaker.oscog-AlistairGrant.2455.mcz

commits-2
 
Alistair Grant uploaded a new version of VMMaker to project VM Maker:
http://source.squeak.org/VMMaker/VMMaker.oscog-AlistairGrant.2455.mcz

==================== Summary ====================

Name: VMMaker.oscog-AlistairGrant.2455
Author: AlistairGrant
Time: 14 October 2018, 8:59:01.383815 pm
UUID: 9e8e4134-b30b-4734-9477-95d556650155
Ancestors: VMMaker.oscog-eem.2454

VMClass strlen, strncpy and getenv

Pharo stores UTF8 encoded strings in ByteArrays (ByteString, strictly speaking, expects to only store characters that can be represented as a single byte in UTF8).  ByteArrays are also used within the simulator to represent buffers allocated by the simulator.  As such, the strings may either be the length of the ByteArray or less than the ByteArray size and null terminated.

These changes extend strlen: and strncpy:_:_: to handle ByteArrays and add some tests (tests for strings in the object memory are todo).

InterpreterPrimitives>>primitiveGetenv: returned nil rather than 0 in the simulator when a variable that isn't defined is requested.

=============== Diff against VMMaker.oscog-eem.2454 ===============

Item was changed:
  ----- Method: InterpreterPrimitives>>primitiveGetenv (in category 'other primitives') -----
  primitiveGetenv
  "Access to environment variables via getenv.  No putenv or setenv as yet."
  | key var result |
  <export: true>
  <var: #key type: #'char *'>
  <var: #var type: #'char *'>
  sHEAFn ~= 0 ifTrue: "secHasEnvironmentAccess"
  [self sHEAFn ifFalse: [^self primitiveFailFor: PrimErrInappropriate]].
  key := self cStringOrNullFor: self stackTop.
  key = 0 ifTrue:
  [self successful ifTrue:
  [^self primitiveFailFor: PrimErrBadArgument].
  ^self primitiveFailFor: primFailCode].
+ var := (self getenv: (self cCode: [key] inSmalltalk: [key allButLast])) ifNil: [0].
- var := self getenv: (self cCode: [key] inSmalltalk: [key allButLast]).
  self free: key.
  var ~= 0 ifTrue:
  [result := objectMemory stringForCString: var.
  result ifNil:
  [^self primitiveFailFor: PrimErrNoMemory]].
  self assert: primFailCode = 0.
  self pop: 2 thenPush: (var = 0 ifTrue: [objectMemory nilObject] ifFalse: [result])!

Item was changed:
  ----- Method: VMClass>>strlen: (in category 'C library simulation') -----
  strlen: aCString
  "Simulate strlen(3)"
  <doNotGenerate>
  | len |
  aCString isString ifTrue:
  [^aCString size].
+ aCString class == ByteArray ifTrue: [
+ "ByteArrays may be 0 terminated or the correct length (in the simulator)"
+ len := 0.
+ [(len = aCString size or: [(aCString at: len+1) = 0]) ifTrue: [^len].
+ len := len + 1] repeat].
+ "Must be an address"
  len := 0.
  [(self byteAt: aCString + len) = 0 ifTrue: [^len].
  len := len + 1] repeat!

Item was changed:
  ----- Method: VMClass>>strncpy:_:_: (in category 'C library simulation') -----
  strncpy: aString _: bString _: n
  <doNotGenerate>
  "implementation of strncpy(3)"
+
+ | getBlock setBlock count |
+
+ count := n.
+ aString isString ifTrue: [setBlock := [ :idx :ch | aString at: idx put: ch asCharacter]].
+ aString class == ByteArray ifTrue:
+ [setBlock := [ :idx :ch | aString at: idx put: ch]].
+ aString isInteger ifTrue: [setBlock := [ :idx :ch | self byteAt: aString + idx - 1 put: ch]].
+ bString isString ifTrue: [
+ getBlock := [ :idx | (bString at: idx) asInteger ].
+ count := count min: bString size].
+ bString class == ByteArray ifTrue: [
+ getBlock := [ :idx | bString at: idx].
+ count := count min: bString size].
+ bString isInteger ifTrue: [getBlock := [ :idx | self byteAt: bString + idx - 1]].
+ bString class == CArray ifTrue:
+ [getBlock := [ :idx | bString at: idx - 1]].
+ self assert: getBlock ~= nil.
+ self assert: setBlock ~= nil.
+ 1 to: count do: [ :i | | v |
+ v := getBlock value: i.
+ setBlock value: i value: v.
+ v = 0 ifTrue: [^aString] ].
- aString isString
- ifTrue:
- [1 to: n do:
- [:i| | v |
- v := bString isString
- ifTrue: [bString at: i]
- ifFalse: [Character value: (self byteAt: bString + i - 1)].
- aString at: i put: v.
- v asInteger = 0 ifTrue: [^aString]]]
- ifFalse:
- [1 to: n do:
- [:i| | v |
- v := bString isString
- ifTrue: [(bString at: i) asInteger]
- ifFalse: [self byteAt: bString + i - 1].
- self byteAt: aString + i - 1 put: v.
- v = 0 ifTrue: [^aString]]].
  ^aString!

Item was added:
+ TestCase subclass: #VMClassTests
+ instanceVariableNames: 'testString vmclass'
+ classVariableNames: ''
+ poolDictionaries: ''
+ category: 'VMMaker-Tests'!

Item was added:
+ ----- Method: VMClassTests>>initialize (in category 'initialize-release') -----
+ initialize
+
+ super initialize.
+ testString := 'hello world'.!

Item was added:
+ ----- Method: VMClassTests>>setUp (in category 'running') -----
+ setUp
+
+ super setUp.
+ vmclass := VMClass new.
+ !

Item was added:
+ ----- Method: VMClassTests>>testStrlen (in category 'tests') -----
+ testStrlen
+
+ | testByteArray |
+
+ "Instances of String must be the correct length"
+ self assert: (vmclass strlen: testString) equals: testString size.
+
+ "Instances of ByteArray can optionally have trailing nulls"
+ testByteArray := testString asByteArray.
+ self assert: (vmclass strlen: testByteArray) equals: testString size.
+ testByteArray := testByteArray, (ByteArray new: 3).
+ self assert: (vmclass strlen: testByteArray) equals: testString size.
+ !

Item was added:
+ ----- Method: VMClassTests>>testStrncpy (in category 'tests') -----
+ testStrncpy
+
+ | stringA byteArrayA |
+
+ stringA := String new: 5.
+ vmclass strncpy: stringA _: testString _: stringA size.
+ self assert: stringA equals: 'hello'.
+
+ stringA := String new: testString size + 3.
+ vmclass strncpy: stringA _: testString _: stringA size.
+ self assert: stringA equals: (testString, (String new: 3)).
+
+ byteArrayA := ByteArray new: 5.
+ vmclass strncpy: byteArrayA _: testString _: byteArrayA size.
+ self assert: byteArrayA equals: 'hello' asByteArray.
+
+ byteArrayA := ByteArray new: testString size + 3.
+ vmclass strncpy: byteArrayA _: testString _: byteArrayA size.
+ self assert: byteArrayA equals: (testString, (String new: 3)) asByteArray.
+
+ !

Reply | Threaded
Open this post in threaded view
|

Re: VM Maker: VMMaker.oscog-AlistairGrant.2455.mcz

Eliot Miranda-2
 
Hi Alistair,

    support code like this should be tuned for simulation speed.  Don't bother with the asserts: (asserts belong in code that will be translated to C, or tests), and try and use and ifTrue:ifFalse: style rather than foo isBar ifTrue: []. foo isBaz ifTrue: [], to reduce the number of types comparisons done.

On Mon, Oct 15, 2018 at 11:18 AM <[hidden email]> wrote:
 
Alistair Grant uploaded a new version of VMMaker to project VM Maker:
http://source.squeak.org/VMMaker/VMMaker.oscog-AlistairGrant.2455.mcz

==================== Summary ====================

Name: VMMaker.oscog-AlistairGrant.2455
Author: AlistairGrant
Time: 14 October 2018, 8:59:01.383815 pm
UUID: 9e8e4134-b30b-4734-9477-95d556650155
Ancestors: VMMaker.oscog-eem.2454

VMClass strlen, strncpy and getenv

Pharo stores UTF8 encoded strings in ByteArrays (ByteString, strictly speaking, expects to only store characters that can be represented as a single byte in UTF8).  ByteArrays are also used within the simulator to represent buffers allocated by the simulator.  As such, the strings may either be the length of the ByteArray or less than the ByteArray size and null terminated.

These changes extend strlen: and strncpy:_:_: to handle ByteArrays and add some tests (tests for strings in the object memory are todo).

InterpreterPrimitives>>primitiveGetenv: returned nil rather than 0 in the simulator when a variable that isn't defined is requested.

=============== Diff against VMMaker.oscog-eem.2454 ===============

Item was changed:
  ----- Method: InterpreterPrimitives>>primitiveGetenv (in category 'other primitives') -----
  primitiveGetenv
        "Access to environment variables via getenv.  No putenv or setenv as yet."
        | key var result |
        <export: true>
        <var: #key type: #'char *'>
        <var: #var type: #'char *'>
        sHEAFn ~= 0 ifTrue: "secHasEnvironmentAccess"
                [self sHEAFn ifFalse: [^self primitiveFailFor: PrimErrInappropriate]].
        key := self cStringOrNullFor: self stackTop.
        key = 0 ifTrue:
                [self successful ifTrue:
                        [^self primitiveFailFor: PrimErrBadArgument].
                 ^self primitiveFailFor: primFailCode].
+       var := (self getenv: (self cCode: [key] inSmalltalk: [key allButLast])) ifNil: [0].
-       var := self getenv: (self cCode: [key] inSmalltalk: [key allButLast]).
        self free: key.
        var ~= 0 ifTrue:
                [result := objectMemory stringForCString: var.
                 result ifNil:
                        [^self primitiveFailFor: PrimErrNoMemory]].
        self assert: primFailCode = 0.
        self pop: 2 thenPush: (var = 0 ifTrue: [objectMemory nilObject] ifFalse: [result])!

Item was changed:
  ----- Method: VMClass>>strlen: (in category 'C library simulation') -----
  strlen: aCString
        "Simulate strlen(3)"
        <doNotGenerate>
        | len |
        aCString isString ifTrue:
                [^aCString size].
+       aCString class == ByteArray ifTrue: [
+               "ByteArrays may be 0 terminated or the correct length (in the simulator)"
+               len := 0.
+               [(len = aCString size or: [(aCString at: len+1) = 0]) ifTrue: [^len].
+               len := len + 1] repeat].
+       "Must be an address"
        len := 0.
        [(self byteAt: aCString + len) = 0 ifTrue: [^len].
        len := len + 1] repeat!

Item was changed:
  ----- Method: VMClass>>strncpy:_:_: (in category 'C library simulation') -----
  strncpy: aString _: bString _: n
        <doNotGenerate>
        "implementation of strncpy(3)"
+
+       | getBlock setBlock count |
+
+       count := n.
+       aString isString ifTrue: [setBlock := [ :idx :ch | aString at: idx put: ch asCharacter]].
+       aString class == ByteArray ifTrue:
+                       [setBlock := [ :idx :ch | aString at: idx put: ch]].
+       aString isInteger ifTrue: [setBlock := [ :idx :ch | self byteAt: aString + idx - 1 put: ch]].
+       bString isString ifTrue: [
+               getBlock := [ :idx | (bString at: idx) asInteger ].
+               count := count min: bString size].
+       bString class == ByteArray ifTrue: [
+               getBlock := [ :idx | bString at: idx].
+               count := count min: bString size].
+       bString isInteger ifTrue: [getBlock := [ :idx | self byteAt: bString + idx - 1]].
+       bString class == CArray ifTrue:
+                       [getBlock := [ :idx | bString at: idx - 1]].
+       self assert: getBlock ~= nil.
+       self assert: setBlock ~= nil.
+       1 to: count do: [ :i | | v |
+               v := getBlock value: i.
+               setBlock value: i value: v.
+               v = 0 ifTrue: [^aString] ].
-       aString isString
-               ifTrue:
-                       [1 to: n do:
-                               [:i| | v |
-                               v := bString isString
-                                               ifTrue: [bString at: i]
-                                               ifFalse: [Character value: (self byteAt: bString + i - 1)].
-                               aString at: i put: v.
-                               v asInteger = 0 ifTrue: [^aString]]]
-               ifFalse:
-                       [1 to: n do:
-                               [:i| | v |
-                               v := bString isString
-                                               ifTrue: [(bString at: i) asInteger]
-                                               ifFalse: [self byteAt: bString + i - 1].
-                               self byteAt: aString + i - 1 put: v.
-                               v = 0 ifTrue: [^aString]]].
        ^aString!

Item was added:
+ TestCase subclass: #VMClassTests
+       instanceVariableNames: 'testString vmclass'
+       classVariableNames: ''
+       poolDictionaries: ''
+       category: 'VMMaker-Tests'!

Item was added:
+ ----- Method: VMClassTests>>initialize (in category 'initialize-release') -----
+ initialize
+
+       super initialize.
+       testString := 'hello world'.!

Item was added:
+ ----- Method: VMClassTests>>setUp (in category 'running') -----
+ setUp
+
+       super setUp.
+       vmclass := VMClass new.
+ !

Item was added:
+ ----- Method: VMClassTests>>testStrlen (in category 'tests') -----
+ testStrlen
+
+       | testByteArray |
+
+       "Instances of String must be the correct length"
+       self assert: (vmclass strlen: testString) equals: testString size.
+
+       "Instances of ByteArray can optionally have trailing nulls"
+       testByteArray := testString asByteArray.
+       self assert: (vmclass strlen: testByteArray) equals: testString size.
+       testByteArray := testByteArray, (ByteArray new: 3).
+       self assert: (vmclass strlen: testByteArray) equals: testString size.
+ !

Item was added:
+ ----- Method: VMClassTests>>testStrncpy (in category 'tests') -----
+ testStrncpy
+
+       | stringA byteArrayA |
+
+       stringA := String new: 5.
+       vmclass strncpy: stringA _: testString _: stringA size.
+       self assert: stringA equals: 'hello'.
+
+       stringA := String new: testString size + 3.
+       vmclass strncpy: stringA _: testString _: stringA size.
+       self assert: stringA equals: (testString, (String new: 3)).
+
+       byteArrayA := ByteArray new: 5.
+       vmclass strncpy: byteArrayA _: testString _: byteArrayA size.
+       self assert: byteArrayA equals: 'hello' asByteArray.
+
+       byteArrayA := ByteArray new: testString size + 3.
+       vmclass strncpy: byteArrayA _: testString _: byteArrayA size.
+       self assert: byteArrayA equals: (testString, (String new: 3)) asByteArray.
+
+ !



--
_,,,^..^,,,_
best, Eliot
Reply | Threaded
Open this post in threaded view
|

Re: VM Maker: VMMaker.oscog-AlistairGrant.2455.mcz

Eliot Miranda-2
In reply to this post by commits-2
 
Hi Alistair,

also
    var := (self getenv: (self cCode: [key] inSmalltalk: [key allButLast])) ifNil: [0].
doesn't make sense to me.  In C nil == 0.  So ifNil: [0] is a no-op in C.  Either the genenv: simulation should answer 0 or it should answer nil.  But we shouldn't fix the primitive two handle incorrect simulation; we should instead implement the simulated getenv: to match what the primitive expects.  Make sense?

On Mon, Oct 15, 2018 at 11:18 AM <[hidden email]> wrote:
 
Alistair Grant uploaded a new version of VMMaker to project VM Maker:
http://source.squeak.org/VMMaker/VMMaker.oscog-AlistairGrant.2455.mcz

==================== Summary ====================

Name: VMMaker.oscog-AlistairGrant.2455
Author: AlistairGrant
Time: 14 October 2018, 8:59:01.383815 pm
UUID: 9e8e4134-b30b-4734-9477-95d556650155
Ancestors: VMMaker.oscog-eem.2454

VMClass strlen, strncpy and getenv

Pharo stores UTF8 encoded strings in ByteArrays (ByteString, strictly speaking, expects to only store characters that can be represented as a single byte in UTF8).  ByteArrays are also used within the simulator to represent buffers allocated by the simulator.  As such, the strings may either be the length of the ByteArray or less than the ByteArray size and null terminated.

These changes extend strlen: and strncpy:_:_: to handle ByteArrays and add some tests (tests for strings in the object memory are todo).

InterpreterPrimitives>>primitiveGetenv: returned nil rather than 0 in the simulator when a variable that isn't defined is requested.

=============== Diff against VMMaker.oscog-eem.2454 ===============

Item was changed:
  ----- Method: InterpreterPrimitives>>primitiveGetenv (in category 'other primitives') -----
  primitiveGetenv
        "Access to environment variables via getenv.  No putenv or setenv as yet."
        | key var result |
        <export: true>
        <var: #key type: #'char *'>
        <var: #var type: #'char *'>
        sHEAFn ~= 0 ifTrue: "secHasEnvironmentAccess"
                [self sHEAFn ifFalse: [^self primitiveFailFor: PrimErrInappropriate]].
        key := self cStringOrNullFor: self stackTop.
        key = 0 ifTrue:
                [self successful ifTrue:
                        [^self primitiveFailFor: PrimErrBadArgument].
                 ^self primitiveFailFor: primFailCode].
+       var := (self getenv: (self cCode: [key] inSmalltalk: [key allButLast])) ifNil: [0].
-       var := self getenv: (self cCode: [key] inSmalltalk: [key allButLast]).
        self free: key.
        var ~= 0 ifTrue:
                [result := objectMemory stringForCString: var.
                 result ifNil:
                        [^self primitiveFailFor: PrimErrNoMemory]].
        self assert: primFailCode = 0.
        self pop: 2 thenPush: (var = 0 ifTrue: [objectMemory nilObject] ifFalse: [result])!

Item was changed:
  ----- Method: VMClass>>strlen: (in category 'C library simulation') -----
  strlen: aCString
        "Simulate strlen(3)"
        <doNotGenerate>
        | len |
        aCString isString ifTrue:
                [^aCString size].
+       aCString class == ByteArray ifTrue: [
+               "ByteArrays may be 0 terminated or the correct length (in the simulator)"
+               len := 0.
+               [(len = aCString size or: [(aCString at: len+1) = 0]) ifTrue: [^len].
+               len := len + 1] repeat].
+       "Must be an address"
        len := 0.
        [(self byteAt: aCString + len) = 0 ifTrue: [^len].
        len := len + 1] repeat!

Item was changed:
  ----- Method: VMClass>>strncpy:_:_: (in category 'C library simulation') -----
  strncpy: aString _: bString _: n
        <doNotGenerate>
        "implementation of strncpy(3)"
+
+       | getBlock setBlock count |
+
+       count := n.
+       aString isString ifTrue: [setBlock := [ :idx :ch | aString at: idx put: ch asCharacter]].
+       aString class == ByteArray ifTrue:
+                       [setBlock := [ :idx :ch | aString at: idx put: ch]].
+       aString isInteger ifTrue: [setBlock := [ :idx :ch | self byteAt: aString + idx - 1 put: ch]].
+       bString isString ifTrue: [
+               getBlock := [ :idx | (bString at: idx) asInteger ].
+               count := count min: bString size].
+       bString class == ByteArray ifTrue: [
+               getBlock := [ :idx | bString at: idx].
+               count := count min: bString size].
+       bString isInteger ifTrue: [getBlock := [ :idx | self byteAt: bString + idx - 1]].
+       bString class == CArray ifTrue:
+                       [getBlock := [ :idx | bString at: idx - 1]].
+       self assert: getBlock ~= nil.
+       self assert: setBlock ~= nil.
+       1 to: count do: [ :i | | v |
+               v := getBlock value: i.
+               setBlock value: i value: v.
+               v = 0 ifTrue: [^aString] ].
-       aString isString
-               ifTrue:
-                       [1 to: n do:
-                               [:i| | v |
-                               v := bString isString
-                                               ifTrue: [bString at: i]
-                                               ifFalse: [Character value: (self byteAt: bString + i - 1)].
-                               aString at: i put: v.
-                               v asInteger = 0 ifTrue: [^aString]]]
-               ifFalse:
-                       [1 to: n do:
-                               [:i| | v |
-                               v := bString isString
-                                               ifTrue: [(bString at: i) asInteger]
-                                               ifFalse: [self byteAt: bString + i - 1].
-                               self byteAt: aString + i - 1 put: v.
-                               v = 0 ifTrue: [^aString]]].
        ^aString!

Item was added:
+ TestCase subclass: #VMClassTests
+       instanceVariableNames: 'testString vmclass'
+       classVariableNames: ''
+       poolDictionaries: ''
+       category: 'VMMaker-Tests'!

Item was added:
+ ----- Method: VMClassTests>>initialize (in category 'initialize-release') -----
+ initialize
+
+       super initialize.
+       testString := 'hello world'.!

Item was added:
+ ----- Method: VMClassTests>>setUp (in category 'running') -----
+ setUp
+
+       super setUp.
+       vmclass := VMClass new.
+ !

Item was added:
+ ----- Method: VMClassTests>>testStrlen (in category 'tests') -----
+ testStrlen
+
+       | testByteArray |
+
+       "Instances of String must be the correct length"
+       self assert: (vmclass strlen: testString) equals: testString size.
+
+       "Instances of ByteArray can optionally have trailing nulls"
+       testByteArray := testString asByteArray.
+       self assert: (vmclass strlen: testByteArray) equals: testString size.
+       testByteArray := testByteArray, (ByteArray new: 3).
+       self assert: (vmclass strlen: testByteArray) equals: testString size.
+ !

Item was added:
+ ----- Method: VMClassTests>>testStrncpy (in category 'tests') -----
+ testStrncpy
+
+       | stringA byteArrayA |
+
+       stringA := String new: 5.
+       vmclass strncpy: stringA _: testString _: stringA size.
+       self assert: stringA equals: 'hello'.
+
+       stringA := String new: testString size + 3.
+       vmclass strncpy: stringA _: testString _: stringA size.
+       self assert: stringA equals: (testString, (String new: 3)).
+
+       byteArrayA := ByteArray new: 5.
+       vmclass strncpy: byteArrayA _: testString _: byteArrayA size.
+       self assert: byteArrayA equals: 'hello' asByteArray.
+
+       byteArrayA := ByteArray new: testString size + 3.
+       vmclass strncpy: byteArrayA _: testString _: byteArrayA size.
+       self assert: byteArrayA equals: (testString, (String new: 3)) asByteArray.
+
+ !



--
_,,,^..^,,,_
best, Eliot
Reply | Threaded
Open this post in threaded view
|

Re: VM Maker: VMMaker.oscog-AlistairGrant.2455.mcz

alistairgrant
 
Hi Eliot,

On Mon, 15 Oct 2018 at 21:58, Eliot Miranda <[hidden email]> wrote:
>
>
> Hi Alistair,
>
> also
>     var := (self getenv: (self cCode: [key] inSmalltalk: [key allButLast])) ifNil: [0].
> doesn't make sense to me.  In C nil == 0.  So ifNil: [0] is a no-op in C.  Either the genenv: simulation should answer 0 or it should answer nil.  But we shouldn't fix the primitive two handle incorrect simulation; we should instead implement the simulated getenv: to match what the primitive expects.  Make sense?

Sorry I didn't get to this last night.


On Mon, 15 Oct 2018 at 21:55, Eliot Miranda <[hidden email]> wrote:
>
>     support code like this should be tuned for simulation speed.  Don't bother with the asserts: (asserts belong in code that will be translated to C, or tests), and try and use and ifTrue:ifFalse: style rather than foo isBar ifTrue: []. foo isBaz ifTrue: [], to reduce the number of types comparisons done.

Done.

Thanks for your feedback,
Alistair
Reply | Threaded
Open this post in threaded view
|

Re: VM Maker: VMMaker.oscog-AlistairGrant.2455.mcz

Eliot Miranda-2
 



> On Oct 15, 2018, at 11:21 PM, Alistair Grant <[hidden email]> wrote:
>
>
> Hi Eliot,
>
>> On Mon, 15 Oct 2018 at 21:58, Eliot Miranda <[hidden email]> wrote:
>>
>>
>> Hi Alistair,
>>
>> also
>>    var := (self getenv: (self cCode: [key] inSmalltalk: [key allButLast])) ifNil: [0].
>> doesn't make sense to me.  In C nil == 0.  So ifNil: [0] is a no-op in C.  Either the genenv: simulation should answer 0 or it should answer nil.  But we shouldn't fix the primitive two handle incorrect simulation; we should instead implement the simulated getenv: to match what the primitive expects.  Make sense?
>
> Sorry I didn't get to this last night.

No probs.  It was < 5 mins work.

>> On Mon, 15 Oct 2018 at 21:55, Eliot Miranda <[hidden email]> wrote:
>>
>>    support code like this should be tuned for simulation speed.  Don't bother with the asserts: (asserts belong in code that will be translated to C, or tests), and try and use and ifTrue:ifFalse: style rather than foo isBar ifTrue: []. foo isBaz ifTrue: [], to reduce the number of types comparisons done.
>
> Done.

Thanks!

> Thanks for your feedback,

Please don’t hesitate to question and critique my work too!!

> Alistair