home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume13 / little-st2 / part01 next >
Encoding:
Internet Message Format  |  1988-01-30  |  47.2 KB

  1. Subject:  v13i053:  New release of little smalltalk, Part01/05
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: Tim Budd <budd@MIST.CS.ORST.EDU>
  7. Posting-number: Volume 13, Issue 53
  8. Archive-name: little-st2/part01
  9.  
  10. This is a dialect of Smalltalk, described in the Addison-Wesley book
  11. "A Little Smalltalk" written by Tim.  It is not quite like ST-80 nor
  12. Smalltalk-V, especially in that lots of features are missing.
  13.  
  14. #!/bin/sh
  15. #
  16. # This is version 2.02 of Little Smalltalk, distributed in five parts.
  17. # This version is dated 12/25/87
  18. # Several bugs and many features and improvements have been made since the
  19. # first posting to comp.src.unix.  See the file ``todo'' for a partial list.
  20. # Comments, bug reports, and the like should be submitted to:
  21. #     Tim Budd
  22. #     Smalltalk Distribution
  23. #     Department of Computer Science
  24. #     Oregon State University
  25. #     Corvallis, Oregon
  26. #     97330
  27. #     budd@cs.orst.edu
  28. #     {hp-pcd, tektronix}!orstcs!budd
  29. #
  30. echo 'Start of small.v2, part 01 of 05:'
  31. echo 'x - basic.st'
  32. sed 's/^X//' > basic.st << '/'
  33. X*
  34. X* Little Smalltalk, version 2
  35. X* Written by Tim Budd, Oregon State University, July 1987
  36. X*
  37. X* basic classes common to all images
  38. X*
  39. XDeclare Object
  40. XDeclare Block Object context argumentCounter argumentLocation bytecodeCounter creatingInterpreter
  41. XDeclare Boolean Object
  42. XDeclare   True Boolean
  43. XDeclare   False Boolean
  44. XDeclare Class Object name instanceSize methods superClass variables icon
  45. XDeclare Context Object method methodClass arguments temporaries
  46. XDeclare Link Object key value nextLink
  47. XDeclare Magnitude Object
  48. XDeclare    Char Magnitude value
  49. XDeclare    Collection Magnitude
  50. XDeclare       IndexedCollection Collection
  51. XDeclare          Array IndexedCollection
  52. XDeclare             ByteArray Array
  53. XDeclare                String ByteArray
  54. XDeclare          Dictionary IndexedCollection hashTable
  55. XDeclare       Interval Collection lower upper step
  56. XDeclare       List Collection links
  57. XDeclare          Set List
  58. XDeclare    Number Magnitude
  59. XDeclare       Integer Number
  60. XDeclare       Float Number
  61. XDeclare Method Object text message bytecodes literals stackSize temporarySize
  62. XDeclare Random Object
  63. XDeclare Switch Object const notdone
  64. XDeclare Smalltalk Object
  65. XDeclare Symbol Object
  66. XDeclare UndefinedObject Object
  67. X*
  68. XInstance Smalltalk smalltalk
  69. XInstance True true
  70. XInstance False false
  71. X*
  72. XClass Object
  73. X    == aValue
  74. X        ^ <21 self aValue>
  75. X|
  76. X    = aValue
  77. X        ^ self == aValue
  78. X|
  79. X    basicAt: index
  80. X        ^ <25 self index>
  81. X|
  82. X    basicAt: index put: value
  83. X        ^ <31 self index value>
  84. X|
  85. X    basicSize
  86. X        ^ <12 self>
  87. X|
  88. X    class
  89. X        ^ <11 self>
  90. X|
  91. X    display
  92. X        ('(Class ', self class, ') ' , self printString ) print
  93. X|
  94. X    hash
  95. X        ^ <13 self>
  96. X|
  97. X    isMemberOf: aClass
  98. X        ^ self class == aClass
  99. X|
  100. X    isNil
  101. X        ^ false
  102. X|
  103. X    isKindOf: aClass
  104. X        self class upSuperclassChain:
  105. X            [:x | (x == aClass) ifTrue: [ ^ true ] ].
  106. X        ^ false
  107. X|
  108. X    new
  109. X            " default initialization protocol"
  110. X        ^ self
  111. X|
  112. X    notNil
  113. X        ^ true
  114. X|
  115. X    print
  116. X        ^ self printString print
  117. X|
  118. X    printString
  119. X        ^ self class printString
  120. X]
  121. XClass Array
  122. X    < coll
  123. X        (coll isKindOf: Array)
  124. X            ifTrue: [ self with: coll 
  125. X                   do: [:x :y | (x < y) ifTrue: [ ^ true ]].
  126. X                  ^ self size < coll size ]
  127. X            ifFalse: [ ^ super < coll ]
  128. X|
  129. X    = coll
  130. X        (coll isKindOf: Array)
  131. X            ifTrue: [ (self size = coll size)
  132. X                    ifFalse: [ ^ false ].
  133. X                  self with: coll
  134. X                    do: [:x :y | (x = y) 
  135. X                        ifFalse: [ ^ false ] ]. 
  136. X                 ^ true ]
  137. X            ifFalse: [ ^ super = coll ]
  138. X|
  139. X    at: index put: value
  140. X        (self includesKey: index)
  141. X            ifTrue: [ self basicAt: index put: value ]
  142. X            ifFalse: [ smalltalk error: 
  143. X                'illegal index to at:put: for array' ]
  144. X|
  145. X    binaryDo: aBlock
  146. X        (1 to: self size) do:
  147. X            [:i | aBlock value: i value: (self at: i) ]
  148. X|
  149. X    copyFrom: low to: high    | newArray newlow newhigh |
  150. X        newlow <- low max: 1.
  151. X        newhigh <- high min: self size.
  152. X        newArray <- self class new: (0 max: newhigh - newlow + 1).
  153. X        (newlow to: newhigh)
  154. X            do: [:i |  newArray at: ((i - newlow) + 1)
  155. X                    put: (self at: i) ].
  156. X        ^ newArray
  157. X|
  158. X    do: aBlock
  159. X        (1 to: self size) do:
  160. X            [:i | aBlock value: (self at: i) ]
  161. X|
  162. X    exchange: a and: b    | temp |
  163. X        temp <- self at: a.
  164. X        self at: a put: (self at: b).
  165. X        self at: b put: temp
  166. X|
  167. X    includesKey: index
  168. X        ^ index between: 1 and: self size
  169. X|
  170. X    size
  171. X        ^ self basicSize
  172. X|
  173. X    with: coll do: aBlock
  174. X        (1 to: (self size min: coll size))
  175. X            do: [:i | aBlock value: (self at: i) 
  176. X                    value: (coll at: i) ]
  177. X]
  178. XClass Block
  179. X    checkArgumentCount: count
  180. X        ^ (argumentCounter = count)
  181. X            ifTrue: [ true ]
  182. X            ifFalse: [ smalltalk error:
  183. X                'wrong number of arguments passed to block'.
  184. X                false ]
  185. X|
  186. X    value
  187. X        ^ (self checkArgumentCount: 0)
  188. X            ifTrue: [ context executeFrom: bytecodeCounter 
  189. X                    creator: creatingInterpreter ]
  190. X|
  191. X    value: x
  192. X        ^ (self checkArgumentCount:  1)
  193. X            ifTrue: [ context temporaries at: argumentLocation 
  194. X                    put: x.
  195. X                  context executeFrom: bytecodeCounter 
  196. X                    creator: creatingInterpreter ]
  197. X|
  198. X    value: x value: y    | temps |
  199. X        ^ (self checkArgumentCount: 2)
  200. X            ifTrue: [ temps <- context temporaries.
  201. X                  temps at: argumentLocation put: x.
  202. X                  temps at: argumentLocation + 1 put: y.
  203. X                  context executeFrom: bytecodeCounter 
  204. X                      creator: creatingInterpreter ]
  205. X|
  206. X    value: x value: y value: z    | temps |
  207. X        ^ (self checkArgumentCount:  3)
  208. X            ifTrue: [ temps <- context temporaries.
  209. X                  temps at: argumentLocation put: x.
  210. X                  temps at: argumentLocation + 1 put: y.
  211. X                  temps at: argumentLocation + 2 put: z.
  212. X                  context executeFrom: bytecodeCounter 
  213. X                    creator: creatingInterpreter ]
  214. X|
  215. X    whileTrue: aBlock
  216. X        ( self value ) ifTrue:
  217. X            [ aBlock value. 
  218. X                self whileTrue: aBlock ]
  219. X|
  220. X    whileTrue
  221. X        self whileTrue: []
  222. X]
  223. XClass Boolean
  224. X    ifTrue: trueBlock
  225. X        ^ self ifTrue: trueBlock ifFalse: []
  226. X|
  227. X    ifFalse: falseBlock
  228. X        ^ self ifTrue: [] ifFalse: falseBlock
  229. X|
  230. X    ifFalse: falseBlock ifTrue: trueBlock
  231. X        ^ self ifTrue: trueBlock
  232. X            ifFalse: falseBlock
  233. X|
  234. X    and: aBlock
  235. X        ^ self ifTrue: aBlock ifFalse: [ false ]
  236. X|
  237. X    or: aBlock
  238. X        ^ self ifTrue: [ true ] ifFalse: aBlock
  239. X]
  240. XClass ByteArray
  241. X    asString
  242. X        <22 self String>
  243. X|
  244. X    basicAt: index put: value
  245. X        ^ <32 self index value >
  246. X|
  247. X    basicAt: index
  248. X        ^ <26 self index>
  249. X|
  250. X    size: value
  251. X        ^ <22 <59 value> ByteArray>
  252. X|
  253. X    size
  254. X        ^ self basicSize * 2
  255. X]
  256. XClass Char
  257. X    < aValue
  258. X        ^ (aValue isMemberOf: Char)
  259. X            ifTrue: [ value < aValue asInteger ]
  260. X            ifFalse: [ smalltalk error: 'char compared to nonchar']
  261. X|
  262. X    == aValue
  263. X        ^ (aValue isMemberOf: Char)
  264. X            ifTrue: [ value = aValue asInteger ]
  265. X            ifFalse: [ false ]
  266. X|
  267. X    = aValue
  268. X        ^ self == aValue
  269. X|
  270. X    asInteger
  271. X        ^ value
  272. X|
  273. X    asString
  274. X        ^ ' ' copy; at: 1 put: self
  275. X|
  276. X    digitValue
  277. X        self isDigit ifTrue: [ ^ value - $0 asInteger ].
  278. X        self isUppercase ifTrue: [ ^ value - $A asInteger + 10 ].
  279. X        ^ smalltalk error: 'illegal conversion, char to digit'
  280. X|
  281. X    isAlphabetic
  282. X        ^ (self isLowercase) or: [ self isUppercase ]
  283. X|
  284. X    isAlphaNumeric
  285. X        ^ (self isAlphabetic) or: [ self isDigit ]
  286. X|
  287. X    isBlank
  288. X        ^ value = $   " blank char "
  289. X|
  290. X    isDigit
  291. X        ^ value between: $0 asInteger and: $9 asInteger
  292. X|
  293. X    isLowercase
  294. X        ^ value between: $a asInteger and: $z asInteger
  295. X|
  296. X    isUppercase
  297. X        ^ value between: $A asInteger and: $Z asInteger
  298. X|
  299. X    value: aValue        " private - used for initialization "
  300. X        value <- aValue
  301. X|
  302. X    printString
  303. X        ^ '$', self asString
  304. X]
  305. XClass Class
  306. X    new        | newObject |
  307. X        newObject <- self new: instanceSize.
  308. X        ^ (self == Class)
  309. X            ifTrue: [ newObject initialize ]
  310. X            ifFalse: [ newObject new ]
  311. X|
  312. X    new: size    " hack out block the right size and class "
  313. X        ^ < 22 < 58 size > self >
  314. X|
  315. X    initialize
  316. X        superClass <- Object.
  317. X        instanceSize <- 0.
  318. X        methods <- Dictionary new
  319. X|
  320. X    name
  321. X        ^ name
  322. X|
  323. X    name: aString
  324. X        name <- aString
  325. X|
  326. X    methods
  327. X        ^ methods
  328. X|
  329. X    instanceSize
  330. X        ^ instanceSize
  331. X|
  332. X    printString
  333. X        ^ name asString
  334. X|
  335. X    respondsTo    | theSet |
  336. X        theSet <- Set new.
  337. X        self upSuperclassChain: 
  338. X            [:x | theSet addAll: x methods keys ].
  339. X        ^ theSet
  340. X|
  341. X    respondsTo: message
  342. X        ^ methods includesKey: message
  343. X|
  344. X    subClasses
  345. X        ^ globalNames inject: List new
  346. X            into: [:x :y | ((y class = Class) and:
  347. X                    [ y superClass = self])
  348. X                        ifTrue: [ x add: y]. x ]
  349. X|
  350. X    superClass
  351. X        ^ superClass
  352. X|
  353. X    superClass: aClass
  354. X        superClass <- aClass
  355. X|
  356. X    upSuperclassChain: aBlock
  357. X        aBlock value: self.
  358. X        (superClass notNil)
  359. X            ifTrue: [ superClass upSuperclassChain: aBlock ]
  360. X|
  361. X    variables
  362. X        ^ variables
  363. X|
  364. X    variables: nameArray
  365. X        variables <- nameArray.
  366. X        instanceSize <- superClass instanceSize + nameArray size
  367. X]
  368. XClass Collection
  369. X    < coll
  370. X        self do: [:x | (coll includes: x) ifFalse: [ ^ false ]].
  371. X        ^ true
  372. X|
  373. X    = coll
  374. X        self do: [:x | (self occurrencesOf: x) = 
  375. X                (coll occurrencesOf: x) ifFalse: [ ^ false ] ].
  376. X        ^ true
  377. X|
  378. X    asArray        | newArray i |
  379. X        newArray <- Array new: self size.
  380. X        i <- 0.
  381. X        self do: [:x | i <- i + 1. newArray at: i put: x].
  382. X        ^ newArray
  383. X|
  384. X    asByteArray    | newArray i |
  385. X        newArray <- ByteArray new size: self size.
  386. X        i <- 0.
  387. X        self do: [:x | i <- i + 1. newArray at: i put: x].
  388. X        ^ newArray
  389. X|
  390. X    asSet
  391. X        ^ Set new addAll: self
  392. X|
  393. X    asString
  394. X        ^ self asByteArray asString
  395. X|
  396. X    display
  397. X        self do: [:x | x print ]
  398. X|
  399. X    includes: value
  400. X        self do: [:x | (x = value) ifTrue: [ ^ true ] ].
  401. X        ^ false
  402. X|
  403. X    inject: thisValue into: binaryBlock     | last |
  404. X        last <- thisValue.
  405. X        self do: [:x | last <- binaryBlock value: last value: x].
  406. X        ^ last
  407. X|
  408. X    isEmpty 
  409. X        ^ self size == 0
  410. X|
  411. X    occurrencesOf: anObject
  412. X        ^ self inject: 0
  413. X               into: [:x :y | (y = anObject) 
  414. X                     ifTrue: [x + 1]
  415. X                     ifFalse: [x] ]
  416. X|
  417. X    printString
  418. X        ^ ( self inject: self class printString , ' ('
  419. X             into: [:x :y | x , ' ' , y printString]), ' )'
  420. X|
  421. X    size
  422. X        ^ self inject: 0 into: [:x :y | x + 1]
  423. X|
  424. X    sort: aBlock
  425. X        ^ self inject: List new
  426. X            into: [:x :y | x add: y ordered: aBlock. x]
  427. X|
  428. X    sort
  429. X        ^ self sort: [:x :y | x < y ]
  430. X]
  431. XClass Context
  432. X    executeFrom: value creator: interp
  433. X        ^ <38 self value interp>
  434. X|
  435. X    method: value
  436. X        method <- value
  437. X|
  438. X    arguments: value
  439. X        arguments <- value
  440. X|
  441. X    temporaries
  442. X        ^ temporaries
  443. X|
  444. X    temporaries: value
  445. X        temporaries <- value
  446. X]
  447. XClass Dictionary
  448. X    new
  449. X        hashTable <- Array new: 39
  450. X|
  451. X    hash: aKey
  452. X        ^ 3 * ((aKey hash) rem: ((hashTable size) quo: 3))
  453. X|
  454. X    at: aKey ifAbsent: exceptionBlock    | hashPosition  link |
  455. X
  456. X        hashPosition <- self hash: aKey.
  457. X        ((hashTable at: hashPosition + 1) == aKey)
  458. X            ifTrue: [ ^ hashTable at: hashPosition + 2].
  459. X        link <- hashTable at: hashPosition + 3.
  460. X        ^ (link notNil)
  461. X            ifTrue: [ link at: aKey ifAbsent: exceptionBlock ]
  462. X            ifFalse: exceptionBlock
  463. X|
  464. X    at: aKey put: aValue            | hashPosition link |
  465. X
  466. X        hashPosition <- self hash: aKey.
  467. X        ((hashTable at: hashPosition + 1) isNil)
  468. X           ifTrue: [ hashTable at: hashPosition + 1 put: aKey ].
  469. X        ((hashTable at: hashPosition + 1) == aKey)
  470. X           ifTrue: [ hashTable at: hashPosition + 2 put: aValue ]
  471. X           ifFalse: [ link <- hashTable at: hashPosition + 3.
  472. X            (link notNil)
  473. X                ifTrue: [ link at: aKey put: aValue ]
  474. X                ifFalse: [ hashTable at: hashPosition + 3
  475. X                    put: (Link new; key: aKey; value: aValue)]]
  476. X|
  477. X    binaryDo: aBlock
  478. X        (1 to: hashTable size by: 3) do:
  479. X            [:i | (hashTable at: i) notNil
  480. X                ifTrue: [ aBlock value: (hashTable at: i)
  481. X                        value: (hashTable at: i+1) ].
  482. X                  (hashTable at: i+2) notNil
  483. X                ifTrue: [ (hashTable at: i+2) 
  484. X                        binaryDo: aBlock ] ]
  485. X|
  486. X    display
  487. X        self binaryDo: [:x :y | (x printString , ' -> ', 
  488. X                    y printString ) print ]
  489. X|
  490. X    includesKey: aKey
  491. X        " look up, but throw away result "
  492. X        self at: aKey ifAbsent: [ ^ false ].
  493. X        ^ true
  494. X|
  495. X    removeKey: aKey
  496. X        ^ self removeKey: aKey
  497. X            ifAbsent: [ smalltalk error: 'remove key not found']
  498. X|
  499. X    removeKey: aKey ifAbsent: exceptionBlock
  500. X        ^ (self includesKey: aKey)
  501. X            ifTrue: [ self basicRemoveKey: aKey ]
  502. X            ifFalse: exceptionBlock
  503. X|
  504. X    basicRemoveKey: aKey        | hashPosition link |
  505. X        hashPosition <- self hash: aKey.
  506. X        ((hashTable at: hashPosition + 1) == aKey)
  507. X            ifTrue: [ hashTable at: hashPosition + 1 put: nil.
  508. X                  hashTable at: hashPosition + 2 put: nil]
  509. X            ifFalse: [ link <- hashTable at: hashPosition + 3.
  510. X                (link notNil)
  511. X                    ifTrue: [ hashTable at: hashPosition + 3
  512. X                            put: (link removeKey: aKey) ]]
  513. X]
  514. XClass False
  515. X    ifTrue: trueBlock ifFalse: falseBlock
  516. X        ^ falseBlock value
  517. X|
  518. X    not
  519. X        ^ true
  520. X]
  521. XClass Float
  522. X    + value
  523. X        ^ (value isMemberOf: Float)
  524. X            ifTrue: [ <110 self value> ]
  525. X            ifFalse: [ super + value ]
  526. X|
  527. X    - value
  528. X        ^ (value isMemberOf: Float)
  529. X            ifTrue: [ <111 self value> ]
  530. X            ifFalse: [ super - value ]
  531. X|
  532. X    < value
  533. X        ^ (value isMemberOf: Float)
  534. X            ifTrue: [ <112 self value> ]
  535. X            ifFalse: [ super < value ]
  536. X|
  537. X    = value
  538. X        ^ (value isMemberOf: Float)
  539. X            ifTrue: [ <116 self value> ]
  540. X            ifFalse: [ super = value ]
  541. X|
  542. X    * value
  543. X        ^ (value isMemberOf: Float)
  544. X            ifTrue: [ <118 self value> ]
  545. X            ifFalse: [ super * value ]
  546. X|
  547. X    / value    
  548. X        ^ (value isMemberOf: Float)
  549. X            ifTrue: [ (value = 0.0)
  550. X                    ifTrue: [ smalltalk error:
  551. X                        'float division by zero' ]
  552. X                    ifFalse: [ <119 self value> ]]
  553. X            ifFalse: [ super / value ]
  554. X|
  555. X    ceiling        | i |
  556. X        i <- self integerPart.
  557. X        ^ ((self positive) and: [ self ~= i ])
  558. X            ifTrue: [ i + 1 ]
  559. X            ifFalse: [ i ]
  560. X|
  561. X    coerce: value
  562. X        ^ value asFloat
  563. X|
  564. X    exp
  565. X        ^ <103 self>
  566. X|
  567. X    floor        | i |
  568. X        i <- self integerPart.
  569. X        ^ ((self negative) and: [ self ~= i ])
  570. X            ifTrue: [ i - 1 ]
  571. X            ifFalse: [ i ]
  572. X|
  573. X    fractionalPart
  574. X        ^ self - self integerPart
  575. X|
  576. X    generality
  577. X        ^ 7
  578. X|
  579. X    integerPart
  580. X        ^ <106 self>
  581. X|
  582. X    ln
  583. X        ^ <102 self>
  584. X|
  585. X    printString
  586. X        ^ <101 self>
  587. X|
  588. X    rounded
  589. X        ^ (self + 0.5 ) floor
  590. X|
  591. X    sqrt
  592. X        ^ (self negative)
  593. X            ifTrue: [ smalltalk error: 'sqrt of negative']
  594. X            ifFalse: [ <104 self> ]
  595. X|
  596. X    truncated
  597. X        ^ (self negative) 
  598. X            ifTrue: [ self ceiling ]
  599. X            ifFalse: [ self floor ]
  600. X]
  601. XClass IndexedCollection
  602. X    addAll: aCollection
  603. X        aCollection binaryDo: [:i :x | self at: i put: x ]
  604. X|
  605. X    asArray    
  606. X        ^ Array new: self size ; addAll: self
  607. X|
  608. X    asDictionary
  609. X        ^ Dictionary new ; addAll: self
  610. X|
  611. X    at: aKey
  612. X        ^ self at: aKey 
  613. X            ifAbsent: [ smalltalk error: 'index to at: illegal' ]
  614. X|
  615. X    at: index ifAbsent: exceptionBlock
  616. X         ^ (self includesKey: index)
  617. X            ifTrue: [ self basicAt: index ]
  618. X            ifFalse: exceptionBlock
  619. X|
  620. X    binaryInject: thisValue into: aBlock     | last |
  621. X        last <- thisValue.
  622. X        self binaryDo: [:i :x | last <- aBlock value: last 
  623. X                        value: i value: x].
  624. X        ^ last
  625. X|
  626. X    collect: aBlock
  627. X        ^ self binaryInject: Dictionary new
  628. X            into: [:s :i :x | s at: i put: (aBlock value: x).  s]
  629. X|
  630. X    do: aBlock
  631. X        self binaryDo: [:i :x | aBlock value: x ]
  632. X|
  633. X    keys
  634. X        ^ self binaryInject: Set new 
  635. X            into: [:s :i :x | s add: i ]
  636. X|
  637. X    indexOf: aBlock
  638. X        ^ self indexOf: aBlock
  639. X            ifAbsent: [ smalltalk error: 'index not found']
  640. X|
  641. X    indexOf: aBlock ifAbsent: exceptionBlock
  642. X        self binaryDo: [:i :x | (aBlock value: x)
  643. X                ifTrue: [ ^ i ] ].
  644. X        ^ exceptionBlock value
  645. X|
  646. X    select: aBlock
  647. X        ^ self binaryInject: Dictionary new
  648. X            into: [:s :i :x | (aBlock value: x)
  649. X                    ifTrue: [ s at: i put: x ]. s ]
  650. X|
  651. X    values
  652. X        ^ self binaryInject: List new
  653. X            into: [:s :i :x | s add: x ]
  654. X]
  655. XClass Integer
  656. X    + value        | r |
  657. X        ^ (value isMemberOf: Integer)
  658. X            ifTrue: [ r <- <60 self value>.
  659. X                  r notNil ifTrue: [ r ]
  660. X                ifFalse: [ self asFloat + value asFloat ]]
  661. X            ifFalse: [ super + value ]
  662. X|
  663. X    - value        | r |
  664. X        ^ (value isMemberOf: Integer)
  665. X            ifTrue: [ r <- <61 self value>.
  666. X                r notNil ifTrue: [ r ]
  667. X                ifFalse: [ self asFloat - value asFloat ]]
  668. X            ifFalse: [ super - value ]
  669. X|
  670. X    < value
  671. X        ^ (value isMemberOf: Integer)
  672. X            ifTrue: [ <62 self value> ]
  673. X            ifFalse: [ super < value ]
  674. X|
  675. X    = value
  676. X        ^ (value isMemberOf: Integer)
  677. X            ifTrue: [ <66 self value> ]
  678. X            ifFalse: [ super = value ]
  679. X|
  680. X    * value        | r |
  681. X        ^ (value isMemberOf: Integer)
  682. X            ifTrue: [ r <- <68 self value>.
  683. X                  r notNil ifTrue: [ r ]
  684. X                  ifFalse: [ self asFloat * value asFloat ]]
  685. X            ifFalse: [ super * value ]
  686. X|
  687. X    / value        " do it as float "
  688. X        ^ self asFloat / value
  689. X|
  690. X    // value    | i |
  691. X        i <- self quo: value.
  692. X        ( (i < 0) and: [ (self rem: value) ~= 0] )
  693. X            ifTrue: [ i <- i - 1 ].
  694. X        ^ i
  695. X|
  696. X    \\ value
  697. X        ^ self * self sign rem: value
  698. X|
  699. X    allMask: value
  700. X        ^ value = (self bitAnd: value)
  701. X|
  702. X    anyMask: value
  703. X        ^ 0 ~= (self bitAnd: value)
  704. X|
  705. X    asCharacter
  706. X        ^ Char new; value: self
  707. X|
  708. X    asDigit
  709. X        (self >= 0)
  710. X            ifTrue: [ (self <= 9) ifTrue: 
  711. X                    [ ^ (self + $0 asInteger) asCharacter ].
  712. X                  (self <= 36) ifTrue:
  713. X                    [ ^ (self + $A asInteger - 10) asCharacter ] ].
  714. X        ^ smalltalk error: 'illegal conversion, integer to digit'
  715. X|
  716. X    asFloat
  717. X        ^ <51 self>
  718. X|
  719. X    asString
  720. X        ^ self radix: 10
  721. X|
  722. X    bitAnd: value
  723. X        ^ (value isMemberOf: Integer)
  724. X            ifTrue: [ <71 self value > ]
  725. X            ifFalse: [ smalltalk error: 
  726. X                'argument to bit operation must be integer']
  727. X|
  728. X    bitAt: value
  729. X        ^ (self bitShift: 1 - value) bitAnd: 1
  730. X|
  731. X    bitInvert
  732. X        ^ self bitXor: -1
  733. X|
  734. X    bitOr: value
  735. X        ^ (self bitXor: value) bitXor: (self bitAnd: value)
  736. X|
  737. X    bitXor: value
  738. X        ^ (value isMemberOf: Integer)
  739. X            ifTrue: [ <72 self value > ]
  740. X            ifFalse: [ smalltalk error: 
  741. X                'argument to bit operation must be integer']
  742. X|
  743. X    bitShift: value
  744. X        ^ (value isMemberOf: Integer)
  745. X            ifTrue: [ <79 self value > ]
  746. X            ifFalse: [ smalltalk error: 
  747. X                'argument to bit operation must be integer']
  748. X|
  749. X    even
  750. X        ^ (self rem: 2) = 0
  751. X|
  752. X    factorial
  753. X        ^ (2 to: self) inject: 1 into: [:x :y | x * y ]
  754. X|
  755. X    gcd: value
  756. X        (value = 0) ifTrue: [ ^ self ].
  757. X        (self negative) ifTrue: [ ^ self negated gcd: value ].
  758. X        (value negative) ifTrue: [ ^ self gcd: value negated ].
  759. X        (value > self) ifTrue: [ ^ value gcd: self ].
  760. X        ^ value gcd: (self rem: value)
  761. X|
  762. X    generality
  763. X        ^ 2
  764. X|
  765. X    lcm: value
  766. X        ^ (self quo: (self gcd: value)) * value
  767. X|
  768. X    odd
  769. X        ^ (self rem: 2) ~= 0
  770. X|
  771. X    quo: value    | r |
  772. X        ^ (value isMemberOf: Integer)
  773. X            ifTrue: [ r <- <69 self value>.
  774. X                (r isNil)
  775. X                    ifTrue: [ smalltalk error:
  776. X                        'quo: or rem: with argument 0']
  777. X                    ifFalse: [ r ]]
  778. X            ifFalse: [ smalltalk error: 
  779. X                'argument to quo: or rem: must be integer']
  780. X|
  781. X    radix: base     | text |
  782. X        text <- (self \\ base) asDigit asString.
  783. X        ^ (self abs < base)
  784. X            ifTrue: [ (self negative)
  785. X                    ifTrue: [ '-' , text ]
  786. X                    ifFalse: [ text ]]
  787. X            ifFalse: [ ((self quo: base) radix: base), text ]
  788. X|
  789. X    rem: value
  790. X        ^ self - ((self quo: value) * value)
  791. X|
  792. X    printString
  793. X        ^ self asString
  794. X|
  795. X    timesRepeat: aBlock    | i |
  796. X        " use while, which is optimized, not to:, which is not"
  797. X        i <- 0.
  798. X        [ i < self ] whileTrue:
  799. X            [ aBlock value. i <- i + 1]
  800. X]
  801. XClass Interval
  802. X    do: aBlock        | current |
  803. X        current <- lower.
  804. X        (step > 0) 
  805. X            ifTrue: [ [ current <= upper ] whileTrue:
  806. X                    [ aBlock value: current.
  807. X                      current <- current + step ] ]
  808. X            ifFalse: [ [ current >= upper ] whileTrue:
  809. X                    [ aBlock value: current.
  810. X                    current <- current + step ] ]
  811. X|
  812. X    lower: aValue
  813. X        lower <- aValue
  814. X|
  815. X    upper: aValue
  816. X        upper <- aValue
  817. X|
  818. X    step: aValue
  819. X        step <- aValue
  820. X]
  821. XClass Link
  822. X    add: newValue whenFalse: aBlock
  823. X        (aBlock value: value value: newValue)
  824. X            ifTrue: [ (nextLink notNil)
  825. X                ifTrue: [ nextLink <- nextLink add: newValue 
  826. X                    whenFalse: aBlock ]
  827. X            ifFalse: [ nextLink <- Link new; value: newValue] ]
  828. X            ifFalse: [ ^ Link new; value: newValue; link: self ]
  829. X|
  830. X    at: aKey ifAbsent: exceptionBlock
  831. X        (aKey == key)
  832. X            ifTrue: [ ^value ]
  833. X            ifFalse: [ ^ (nextLink notNil)
  834. X                    ifTrue: [ nextLink at: aKey
  835. X                            ifAbsent: exceptionBlock ]
  836. X                    ifFalse: exceptionBlock ]
  837. X|
  838. X    at: aKey put: aValue
  839. X        (aKey == key)
  840. X            ifTrue: [ value <- aValue ]
  841. X            ifFalse: [ (nextLink notNil)
  842. X                ifTrue: [ nextLink at: aKey put: aValue]
  843. X                ifFalse: [ nextLink <- Link new;
  844. X                        key: aKey; value: aValue] ]
  845. X|
  846. X    binaryDo: aBlock
  847. X        aBlock value: key value: value.
  848. X        (nextLink notNil)
  849. X            ifTrue: [ nextLink binaryDo: aBlock ]
  850. X|
  851. X    key: aKey
  852. X        key <- aKey
  853. X|
  854. X    includesKey: aKey
  855. X        (key == aKey)
  856. X            ifTrue: [ ^ true ].
  857. X        (nextLink notNil)
  858. X            ifTrue: [ ^ nextLink includesKey: aKey ]
  859. X            ifFalse: [ ^ false ]
  860. X|
  861. X    link: aLink
  862. X        nextLink <- aLink
  863. X|
  864. X    removeKey: aKey
  865. X        (aKey == key)
  866. X            ifTrue: [ ^ nextLink ]
  867. X            ifFalse: [ (nextLink notNil)
  868. X                ifTrue: [ nextLink <- nextLink removeKey: aKey]]
  869. X|
  870. X    removeValue: aValue
  871. X        (aValue == value)
  872. X            ifTrue: [ ^ nextLink ]
  873. X            ifFalse: [ (nextLink notNil)
  874. X                ifTrue: [ nextLink <- nextLink removeValue: aValue]]
  875. X|
  876. X    size
  877. X        (nextLink notNil)
  878. X            ifTrue: [ ^ 1 + nextLink size]
  879. X            ifFalse: [ ^ 1 ]
  880. X|
  881. X    value: aValue
  882. X        value <- aValue
  883. X|
  884. X    value
  885. X        ^ value
  886. X]
  887. XClass List
  888. X    add: aValue
  889. X        ^ self addFirst: aValue
  890. X|
  891. X    add: aValue ordered: aBlock
  892. X        (links isNil)
  893. X            ifTrue: [ self addFirst: aValue]
  894. X            ifFalse: [ links <- links add: aValue 
  895. X                    whenFalse: aBlock ]
  896. X|
  897. X    addAll: aValue
  898. X        aValue do: [:x | self add: x ]
  899. X|
  900. X    addFirst: aValue
  901. X        links <- Link new; value: aValue; link: links
  902. X|
  903. X    addLast: aValue
  904. X        (links isNil)
  905. X            ifTrue: [ self addFirst: aValue ]
  906. X            ifFalse: [ links add: aValue whenFalse: [ :x :y | true ] ]
  907. X|
  908. X    collect: aBlock
  909. X        ^ self inject: self class new
  910. X               into: [:x :y | x add: (aBlock value: y). x ]
  911. X|
  912. X    reject: aBlock          
  913. X        ^ self select: [:x | (aBlock value: x) not ]
  914. X|
  915. X    select: aBlock          
  916. X        ^ self inject: self class new
  917. X               into: [:x :y | (aBlock value: y) 
  918. X                    ifTrue: [x add: y]. x]
  919. X|
  920. X    do: aBlock
  921. X        (links notNil)
  922. X            ifTrue: [ links binaryDo: [:x :y | aBlock value: y]]
  923. X|
  924. X    first
  925. X        ^ (links notNil)
  926. X            ifTrue: links
  927. X            ifFalse: [ smalltalk error: 'first on empty list']
  928. X|
  929. X    removeFirst
  930. X        self remove: self first
  931. X|
  932. X    remove: value
  933. X        (links notNil)
  934. X            ifTrue: [ links <- links removeValue: value ]
  935. X|
  936. X    size
  937. X        (links isNil)
  938. X            ifTrue: [ ^ 0 ]
  939. X            ifFalse: [ ^ links size ]
  940. X]
  941. XClass Magnitude
  942. X    <= value
  943. X        ^ (self < value) or: [ self = value ]
  944. X|
  945. X    < value
  946. X        ^ (value > self)
  947. X|
  948. X    >= value
  949. X        ^ (self > value) or: [ self = value ]
  950. X|
  951. X    > value
  952. X        ^ (value < self)
  953. X|
  954. X    = value
  955. X        ^ (self == value)
  956. X|
  957. X    ~= value
  958. X        ^ (self = value) not
  959. X|
  960. X    between: low and: high
  961. X        ^ (low <= self) and: [ self <= high ]
  962. X|
  963. X    max: value
  964. X        ^ (self < value)
  965. X            ifTrue: [ value ]
  966. X            ifFalse: [ self ]
  967. X|
  968. X    min: value
  969. X        ^ (self < value)
  970. X            ifTrue: [ self ]
  971. X            ifFalse: [ value ]
  972. X]
  973. XClass Method
  974. X    compileWithClass: aClass
  975. X        ^ <39 aClass text self>
  976. X|
  977. X    name
  978. X        ^ message
  979. X|
  980. X    message: aSymbol
  981. X        message <- aSymbol
  982. X|
  983. X    printString
  984. X        ^ message asString
  985. X|
  986. X    text
  987. X        ^ text
  988. X|
  989. X    text: aString
  990. X        text <- aString
  991. X|
  992. X    display
  993. X        ('Method ', message) print.
  994. X        'text' print.
  995. X        text print.
  996. X        'literals' print.
  997. X        literals print.
  998. X        'bytecodes' print.
  999. X        bytecodes do: [:x |
  1000. X            (x printString, ' ', (x quo: 16), ' ', (x rem: 16))
  1001. X                print ]
  1002. X]
  1003. XClass Number
  1004. X    maxgen: value
  1005. X        ^ (self generality > value generality)
  1006. X            ifTrue: [ self ]
  1007. X            ifFalse: [ value coerce: self ]
  1008. X|
  1009. X    + value
  1010. X        ^ (self maxgen: value) + (value maxgen: self)
  1011. X|
  1012. X    - value
  1013. X        ^ (self maxgen: value) - (value maxgen: self)
  1014. X|
  1015. X    < value
  1016. X        ^ (self maxgen: value) < (value maxgen: self)
  1017. X|
  1018. X    = value
  1019. X        ^ (self maxgen: value) = (value maxgen: self)
  1020. X|
  1021. X    * value
  1022. X        ^ (self maxgen: value) * (value maxgen: self)
  1023. X|
  1024. X    / value
  1025. X        ^ (self maxgen: value) / (value maxgen: self)
  1026. X|
  1027. X    abs
  1028. X        ^ (self < 0)
  1029. X            ifTrue: [ 0 - self ]
  1030. X            ifFalse: [ self ]
  1031. X|
  1032. X    exp
  1033. X        ^ self asFloat exp
  1034. X|
  1035. X    ln
  1036. X        ^ self asFloat ln
  1037. X|
  1038. X    log: value
  1039. X        ^ self ln / value ln
  1040. X|
  1041. X    negated
  1042. X        ^ 0 - self
  1043. X|
  1044. X    negative
  1045. X        ^ self < 0
  1046. X|
  1047. X    positive
  1048. X        ^ self >= 0
  1049. X|
  1050. X    raisedTo: value
  1051. X        ^ ( value * self ln ) exp
  1052. X|
  1053. X    reciprocal
  1054. X        ^ 1.00 / self
  1055. X|
  1056. X    roundTo: value
  1057. X        ^ (self / value ) rounded * value
  1058. X|
  1059. X    sign
  1060. X        ^ self negative ifTrue: [ -1 ]
  1061. X            ifFalse: [ self strictlyPositive 
  1062. X                    ifTrue: [ 1 ] ifFalse: [ 0 ] ]
  1063. X|
  1064. X    sqrt
  1065. X        ^ self asFloat sqrt
  1066. X|
  1067. X    squared
  1068. X        ^ self * self
  1069. X|
  1070. X    strictlyPositive
  1071. X        ^ self > 0
  1072. X|
  1073. X    to: value
  1074. X        ^ Interval new; lower: self; upper: value; step: 1
  1075. X|
  1076. X    to: value by: step
  1077. X        ^ Interval new; lower: self; upper: value; step: step
  1078. X|
  1079. X    trucateTo: value
  1080. X        ^ (self / value) trucated * value
  1081. X]
  1082. XClass Random
  1083. X    between: low and: high
  1084. X        ^ (self next * (high - low)) + low
  1085. X|
  1086. X    next
  1087. X        ^ (<3> rem: 1000) / 1000
  1088. X|
  1089. X    next: value    | list |
  1090. X        list <- List new.
  1091. X        value timesRepeat: [ list add: self next ].
  1092. X        ^ list
  1093. X|
  1094. X    randInteger: value
  1095. X        ^ 1 + (<3> rem: value)
  1096. X|
  1097. X    set: value
  1098. X        <55 value>
  1099. X]
  1100. XClass Set
  1101. X    add: value
  1102. X        (self includes: value)
  1103. X            ifFalse: [ self addFirst: value ]
  1104. X]
  1105. XClass String
  1106. X    , value
  1107. X        ^ (value isMemberOf: String)
  1108. X            ifTrue: [ (self size + value size) > 512
  1109. X                    ifTrue: [ 'string too large' print.  self ]
  1110. X                    ifFalse: [ <24 self value> ] ]
  1111. X            ifFalse: [ self , value printString ]
  1112. X|
  1113. X    = value
  1114. X        (value isKindOf: String)
  1115. X            ifTrue: [ ^ super = value ]
  1116. X            ifFalse: [ ^ false ]
  1117. X|
  1118. X    < value
  1119. X        (value isKindOf: String)
  1120. X            ifTrue: [ ^ super < value ]
  1121. X            ifFalse: [ ^ false ]
  1122. X|
  1123. X    asInteger
  1124. X        ^ self inject: 0 into: [:x :y | x * 10 + y digitValue ]
  1125. X|
  1126. X    basicAt: index
  1127. X        ^  (super basicAt: index) asCharacter
  1128. X|
  1129. X    basicAt: index put: aValue
  1130. X        (aValue isMemberOf: Char)
  1131. X            ifTrue: [ super basicAt: index put: aValue asInteger ]
  1132. X            ifFalse: [ smalltalk error:
  1133. X                'cannot put non Char into string' ]
  1134. X|
  1135. X    asSymbol
  1136. X        ^ <83 self>
  1137. X|
  1138. X    copy
  1139. X        " catenation makes copy automatically "
  1140. X        ^ '',self
  1141. X|
  1142. X    copyFrom: position1 to: position2
  1143. X        ^ <33 self position1 position2>
  1144. X|
  1145. X    printString
  1146. X        ^ '''' , self, ''''
  1147. X|
  1148. X    size
  1149. X        ^ <81 self>
  1150. X|
  1151. X    words: aBlock    | text index list |
  1152. X        list <- List new.
  1153. X        text <- self.
  1154. X        [ text <- text copyFrom: 
  1155. X            (text indexOf: aBlock ifAbsent: [ text size + 1])
  1156. X                to: text size.
  1157. X          text size > 0 ] whileTrue:
  1158. X            [ index <- text 
  1159. X                indexOf: [:x | (aBlock value: x) not ]
  1160. X                ifAbsent: [ text size + 1].
  1161. X              list addLast: (text copyFrom: 1 to: index - 1).
  1162. X              text <- text copyFrom: index to: text size ].
  1163. X        ^ list asArray
  1164. X]
  1165. XClass Smalltalk
  1166. X    class: aClass doesNotRespond: aMessage
  1167. X        ^ self error: aClass printString ,
  1168. X            ' does not respond to ' , aMessage
  1169. X|
  1170. X    cantFindGlobal: name
  1171. X        ^ self error: 'cannot find global symbol ' , name
  1172. X|
  1173. X    flushMessageCache
  1174. X        <2>
  1175. X]
  1176. XClass Switch
  1177. X    key: value
  1178. X        const <- value.
  1179. X        notdone <- true.
  1180. X|
  1181. X    ifMatch: key do: block
  1182. X        (notdone and: [ const = key ])
  1183. X            ifTrue: [ notdone <- false. block value ]
  1184. X|
  1185. X    else: block
  1186. X        notdone ifTrue: [ notdone <- false. block value ]
  1187. X]
  1188. XClass Symbol
  1189. X    asString
  1190. X        " catenation makes copy automatically "
  1191. X        ^ <24 self ''>
  1192. X|
  1193. X    printString
  1194. X        ^ '#' , self asString
  1195. X|
  1196. X    respondsTo
  1197. X        ^ globalNames inject: Set new
  1198. X            into: [:x :y | ((y class = Class) and:
  1199. X                    [ y respondsTo: self])
  1200. X                        ifTrue: [ x add: y]. x]
  1201. X]
  1202. XClass True
  1203. X    ifTrue: trueBlock ifFalse: falseBlock
  1204. X        ^ trueBlock value
  1205. X|
  1206. X    not
  1207. X        ^ false
  1208. X]
  1209. XClass UndefinedObject
  1210. X    isNil
  1211. X        ^ true
  1212. X|
  1213. X    notNil
  1214. X        ^ false
  1215. X|
  1216. X    printString
  1217. X        ^ 'nil'
  1218. X]
  1219. /
  1220. echo 'x - memory.h'
  1221. sed 's/^X//' > memory.h << '/'
  1222. X/*
  1223. X    Little Smalltalk, version 2
  1224. X    Written by Tim Budd, Oregon State University, July 1987
  1225. X*/
  1226. X
  1227. X# define streq(a,b) (strcmp(a,b) == 0)
  1228. X
  1229. X/*
  1230. X    The first major decision to be made in the memory manager is what
  1231. Xan entity of type object really is.  Two obvious choices are a pointer (to 
  1232. Xthe actual object memory) or an index into an object table.  We decided to
  1233. Xuse the latter, although either would work.
  1234. X    Similarly, one can either define the token object using a typedef,
  1235. Xor using a define statement.  Either one will work (check this?)
  1236. X*/
  1237. X
  1238. Xtypedef short object;
  1239. X
  1240. X/*
  1241. X    The memory module itself is defined by over a dozen routines.
  1242. XAll of these could be defined by procedures, and indeed this was originally
  1243. Xdone.  However, for efficiency reasons, many of these procedures can be
  1244. Xreplaced by macros generating in-line code.  For the latter approach
  1245. Xto work, the structure of the object table must be known.  For this reason,
  1246. Xit is given here.  Note, however, that ONLY the macros described in this
  1247. Xfile make use of this structure: therefore modifications or even complete
  1248. Xreplacement is possible as long as the interface remains consistent
  1249. X
  1250. X*/
  1251. X
  1252. Xstruct objectStruct {
  1253. X    object class;
  1254. X    short referenceCount;
  1255. X    byte size;
  1256. X    byte type;
  1257. X    object *memory;
  1258. X    };
  1259. X
  1260. Xextern struct objectStruct objectTable[];
  1261. X
  1262. X/* types of object memory */
  1263. X# define objectMemory 0
  1264. X# define byteMemory 1
  1265. X# define charMemory 2
  1266. X# define floatMemory 3
  1267. X
  1268. X# define isString(x) ((objectTable[x>>1].type == charMemory) || (objectTable[x>>1].type == byteMemory))
  1269. X# define isFloat(x)  (objectTable[x>>1].type == floatMemory)
  1270. X
  1271. X/*
  1272. X    The most basic routines to the memory manager are incr and decr,
  1273. Xwhich increment and decrement reference counts in objects.  By separating
  1274. Xdecrement from memory freeing, we could replace these as procedure calls
  1275. Xby using the following macros:
  1276. Xextern object incrobj;
  1277. X# define incr(x) if ((incrobj=(x))&&!isInteger(incrobj)) \
  1278. XobjectTable[incrobj>>1].referenceCount++
  1279. X#  define decr(x) if (((incrobj=x)&&!isInteger(incrobj))&&\
  1280. X(--objectTable[incrobj>>1].referenceCount<=0)) sysDecr(incrobj);*/
  1281. X/*
  1282. Xnotice that the argument x is first assigned to a global variable; this is
  1283. Xin case evaluation of x results in side effects (such as assignment) which
  1284. Xshould not be repeated. */
  1285. X
  1286. Xextern noreturn sysDecr(OBJ);
  1287. X
  1288. X# ifndef incr
  1289. Xextern void incr(OBJ);
  1290. X# endif
  1291. X# ifndef decr
  1292. Xextern void decr(OBJ);
  1293. X# endif
  1294. X
  1295. X/*
  1296. X    The next most basic routines in the memory module are those that
  1297. Xallocate blocks of storage.  There are three routines:
  1298. X    allocObject(size) - allocate an array of objects
  1299. X    allocByte(size) - allocate an array of bytes
  1300. X    allocChar(size) - allocate an array of character values
  1301. X    allocSymbol(value) - allocate a string value
  1302. X    allocInt(value) - allocate an integer value
  1303. X    allocFloat(value) - allocate a floating point object
  1304. Xagain, these may be macros, or they may be actual procedure calls
  1305. X*/
  1306. X
  1307. Xextern object alcObject(INT X INT);    /* the actual routine */
  1308. X# define allocObject(size) alcObject(size, objectMemory)
  1309. X# define allocByte(size) alcObject(((size)+1)/2, byteMemory)
  1310. X# define allocChar(size) alcObject(((size)+1)/2, charMemory)
  1311. Xextern object allocSymbol(STR);
  1312. X# define allocInt(value) ((value<0)?value:(value<<1)+1)
  1313. Xextern object allocFloat(FLOAT);
  1314. X
  1315. X/*
  1316. X    integer objects are (but need not be) treated specially.
  1317. XIn this memory manager, negative integers are just left as is, but
  1318. Xpositive integers are changed to x*2+1.  Either a negative or an odd
  1319. Xnumber is therefore an integer, while a nonzero even number is an
  1320. Xobject pointer (multiplied by two).  Zero is reserved for the object ``nil''
  1321. XSince newInteger does not fill in the class field, it can be given here.
  1322. XIf it was required to use the class field, it would have to be deferred
  1323. Xuntil names.h
  1324. X*/
  1325. X
  1326. Xextern object intobj;
  1327. X# define isInteger(x) ((x) & 0x8001)
  1328. X# define newInteger(x) ( (intobj = x)<0 ? intobj : (intobj<<1)+1 )
  1329. X# define intValue(x) ( (intobj = x)<0 ? intobj : (intobj>>1) )
  1330. X
  1331. X/*
  1332. X    in addition to alloc floating point routine given above,
  1333. Xanother routine must be provided to go the other way.  Note that
  1334. Xthe routine newFloat, which fills in the class field as well, must
  1335. Xwait until the global name table is known, in names.h
  1336. X*/
  1337. Xextern double floatValue(OBJ);
  1338. X
  1339. X/*
  1340. X    there are four routines used to access fields within an object.
  1341. XAgain, some of these could be replaced by macros, for efficiency
  1342. X    basicAt(x, i) - ith field (start at 1) of object x
  1343. X    basicAtPut(x, i, v) - put value v in object x
  1344. X    byteAt(x, i) - ith field (start at 0) of object x
  1345. X    byteAtPut(x, i, v) - put value v in object x
  1346. X
  1347. X# define basicAt(x,i) (sysMemPtr(x)[i-1])
  1348. X*/
  1349. X# define byteAt(x, i) (charPtr(x)[i-1])
  1350. X
  1351. X# ifndef basicAt
  1352. Xextern object basicAt(OBJ X INT);
  1353. X# endif
  1354. X# ifndef basicAtPut
  1355. Xextern void basicAtPut(OBJ X INT X OBJ);
  1356. X# endif
  1357. X# ifndef byteAt
  1358. Xextern int byteAt(OBJ X INT);
  1359. X# endif
  1360. X# ifndef byteAtPut
  1361. Xextern void byteAtPut(OBJ X INT X INT);
  1362. X# endif
  1363. X
  1364. X/*
  1365. X    Finally, a few routines (or macros) are used to access or set
  1366. Xclass fields and size fields of objects
  1367. X*/
  1368. X
  1369. X# define classField(x) objectTable[x>>1].class
  1370. X# define setClass(x,y) incr(classField(x)=y)
  1371. X
  1372. X# define objectSize(x) byteToInt(objectTable[x>>1].size)
  1373. X
  1374. X# define sysMemPtr(x) objectTable[x>>1].memory
  1375. Xextern object sysobj;
  1376. X# define memoryPtr(x) (isInteger(sysobj = x)?(object *) 0:sysMemPtr(sysobj))
  1377. X# define bytePtr(x) ((byte *) memoryPtr(x))
  1378. X# define charPtr(x) ((char *) memoryPtr(x))
  1379. X
  1380. X# define nilobj (object) 0
  1381. X
  1382. X/*
  1383. X    these two objects are the source of all objects in the system
  1384. X*/
  1385. Xextern object symbols;
  1386. Xextern object globalNames;
  1387. X
  1388. Xextern noreturn sysError (STR X STR);
  1389. Xextern boolean debugging;
  1390. Xextern noreturn initMemoryManager(NOARGS);
  1391. Xextern noreturn imageRead(FILEP);
  1392. Xextern noreturn imageWrite(FILEP);
  1393. /
  1394. echo 'x - primitive.c'
  1395. sed 's/^X//' > primitive.c << '/'
  1396. X/*
  1397. X    Little Smalltalk, version 2
  1398. X    Written by Tim Budd, Oregon State University, July 1987
  1399. X
  1400. X    Primitive processor
  1401. X
  1402. X    primitives are how actions are ultimately executed in the Smalltalk 
  1403. X    system.
  1404. X    unlike ST-80, Little Smalltalk primitives cannot fail (although
  1405. X    they can return nil, and methods can take this as an indication
  1406. X    of failure).  In this respect primitives in Little Smalltalk are
  1407. X    much more like traditional system calls.
  1408. X
  1409. X    Primitives are combined into groups of 10 according to 
  1410. X    argument count and type, and in some cases type checking is performed.
  1411. X
  1412. X    IMPORTANT NOTE:
  1413. X        The technique used to tell if an arithmetic operation
  1414. X        has overflowed in intBinary() depends upon integers
  1415. X        being 16 bits.  If this is not true, other techniques
  1416. X        may be required.
  1417. X*/
  1418. X
  1419. X# include <stdio.h>
  1420. X# include <math.h>
  1421. X# include "env.h"
  1422. X# include "memory.h"
  1423. X# include "names.h"
  1424. X# include "process.h"
  1425. X# ifdef STRING
  1426. X# include <string.h>
  1427. X# endif
  1428. X# ifdef STRINGS
  1429. X# include <strings.h>
  1430. X# endif
  1431. X
  1432. X# define normalresult 1
  1433. X# define counterror 2
  1434. X# define typeerror  3
  1435. X# define quitinterp 4
  1436. X
  1437. Xextern object doInterp(OBJ);
  1438. Xextern noreturn flushMessageCache();
  1439. Xextern double modf();
  1440. Xextern char *getenv();
  1441. X
  1442. Xstatic int zeroaryPrims(number)
  1443. Xint number;
  1444. X{     short i;
  1445. X
  1446. X    returnedObject = nilobj;
  1447. X    switch(number) {
  1448. X        case 2:
  1449. X            flushMessageCache();
  1450. X            break;
  1451. X
  1452. X        case 3:            /* return a random number */
  1453. X            /* this is hacked because of the representation */
  1454. X            /* of integers as shorts */
  1455. X            i = rand() >> 8;    /* strip off lower bits */
  1456. X            if (i < 0) i = - i;
  1457. X            returnedObject = newInteger(i>>1);
  1458. X            break;
  1459. X
  1460. X        default:        /* unknown primitive */
  1461. X            sysError("unknown primitive","zeroargPrims");
  1462. X            break;
  1463. X    }
  1464. X    return(normalresult);
  1465. X}
  1466. X
  1467. Xstatic int unaryPrims(number, firstarg)
  1468. Xint number;
  1469. Xobject firstarg;
  1470. X{
  1471. X
  1472. X    returnedObject = firstarg;
  1473. X    switch(number) {
  1474. X        case 1:        /* class of object */
  1475. X            returnedObject = getClass(firstarg);
  1476. X            break;
  1477. X
  1478. X        case 2:        /* basic size of object */
  1479. X            if (isInteger(firstarg))
  1480. X                returnedObject = newInteger(0);
  1481. X            else
  1482. X                returnedObject = newInteger(objectSize(firstarg));
  1483. X            break;
  1484. X
  1485. X        case 3:        /* hash value of object */
  1486. X            if (isInteger(firstarg))
  1487. X                returnedObject = firstarg;
  1488. X            else
  1489. X                returnedObject = newInteger(firstarg);
  1490. X            break;
  1491. X
  1492. X        case 9:        /* interpreter bytecodes */
  1493. X            returnedObject = doInterp(firstarg);
  1494. X            break;
  1495. X
  1496. X        default:        /* unknown primitive */
  1497. X            sysError("unknown primitive","unaryPrims");
  1498. X            break;
  1499. X    }
  1500. X    return(normalresult);
  1501. X}
  1502. X
  1503. Xstatic int binaryPrims(number, firstarg, secondarg)
  1504. Xint number;
  1505. Xobject firstarg, secondarg;
  1506. X{    char buffer[512];
  1507. X    int i;
  1508. X
  1509. X    returnedObject = firstarg;
  1510. X    switch(number) {
  1511. X        case 1:        /* object identity test */
  1512. X            if (firstarg == secondarg)
  1513. X                returnedObject = trueobj;
  1514. X            else
  1515. X                returnedObject = falseobj;
  1516. X            break;
  1517. X
  1518. X        case 2:        /* set class of object */
  1519. X            decr(classField(firstarg));
  1520. X            setClass(firstarg, secondarg);
  1521. X            returnedObject = firstarg;
  1522. X            break;
  1523. X
  1524. X        case 4:        /* string cat */
  1525. X            ignore strcpy(buffer, charPtr(firstarg));
  1526. X            ignore strcat(buffer, charPtr(secondarg));
  1527. X            returnedObject = newStString(buffer);
  1528. X            break;
  1529. X        
  1530. X        case 5:        /* basicAt: */
  1531. X            if (! isInteger(secondarg))
  1532. X                sysError("non integer index","basicAt:");
  1533. X            returnedObject = basicAt(firstarg, intValue(secondarg));
  1534. X            break;
  1535. X
  1536. X        case 6:        /* byteAt: */
  1537. X            if (! isInteger(secondarg))
  1538. X                sysError("non integer index","bytAte:");
  1539. X            i = byteAt(firstarg, intValue(secondarg));
  1540. X            if (i < 0) i += 256;
  1541. X            returnedObject = newInteger(i);
  1542. X            break;
  1543. X
  1544. X        default:        /* unknown primitive */
  1545. X            sysError("unknown primitive","binaryPrims");
  1546. X            break;
  1547. X
  1548. X    }
  1549. X    return(normalresult);
  1550. X}
  1551. X
  1552. Xstatic int trinaryPrims(number, firstarg, secondarg, thirdarg)
  1553. Xint number;
  1554. Xobject firstarg, secondarg, thirdarg;
  1555. X{    char *bp, *tp, buffer[256];
  1556. X    int i, j;
  1557. X
  1558. X    returnedObject = firstarg;
  1559. X    switch(number) {
  1560. X        case 1:            /* basicAt:Put: */
  1561. X            if (! isInteger(secondarg))
  1562. X                sysError("non integer index","basicAtPut");
  1563. X            basicAtPut(firstarg, intValue(secondarg), thirdarg);
  1564. X            break;
  1565. X
  1566. X        case 2:            /* basicAt:Put: for bytes */
  1567. X            if (! isInteger(secondarg))
  1568. X                sysError("non integer index","byteAtPut");
  1569. X            if (! isInteger(thirdarg))
  1570. X                sysError("assigning non int","to byte");
  1571. X            byteAtPut(firstarg, intValue(secondarg),
  1572. X                    intValue(thirdarg));
  1573. X            break;
  1574. X
  1575. X        case 3:            /* string copyFrom:to: */
  1576. X            bp = charPtr(firstarg);
  1577. X            if ((! isInteger(secondarg)) || (! isInteger(thirdarg)))
  1578. X                sysError("non integer index","copyFromTo");
  1579. X            i = intValue(secondarg);
  1580. X            j = intValue(thirdarg);
  1581. X            tp = buffer;
  1582. X            if (i <= strlen(bp))
  1583. X                for ( ; (i <= j) && bp[i-1]; i++)
  1584. X                    *tp++ = bp[i-1];
  1585. X            *tp = '\0';
  1586. X            returnedObject = newStString(buffer);
  1587. X            break;
  1588. X
  1589. X        case 8:        /* execute a context */
  1590. X            messageToSend = firstarg;
  1591. X            if (! isInteger(secondarg))
  1592. X                sysError("non integer index","executeAt:");
  1593. X            argumentsOnStack = intValue(secondarg);
  1594. X            creator = thirdarg;
  1595. X            finalTask = ContextExecuteTask;
  1596. X            return(quitinterp);
  1597. X
  1598. X        case 9:            /* compile method */
  1599. X            setInstanceVariables(firstarg);
  1600. X            if (parse(thirdarg, charPtr(secondarg)))
  1601. X                returnedObject = trueobj;
  1602. X            else
  1603. X                returnedObject = falseobj;
  1604. X            break;
  1605. X        
  1606. X        default:        /* unknown primitive */
  1607. X            sysError("unknown primitive","trinaryPrims");
  1608. X            break;
  1609. X        }
  1610. X    return(normalresult);
  1611. X}
  1612. X
  1613. Xstatic int intUnary(number, firstarg)
  1614. Xint number, firstarg;
  1615. X{    char buffer[20];
  1616. X
  1617. X    switch(number) {
  1618. X        case 1:        /* float equiv of integer */
  1619. X            returnedObject = newFloat((double) firstarg);
  1620. X            break;
  1621. X
  1622. X        case 5:        /* set random number */
  1623. X            ignore srand((unsigned) firstarg);
  1624. X            returnedObject = nilobj;
  1625. X            break;
  1626. X
  1627. X        case 7:        /* string equiv of number */
  1628. X            ignore sprintf(buffer,"%d",firstarg);
  1629. X            returnedObject = newStString(buffer);
  1630. X            break;
  1631. X
  1632. X        case 8:
  1633. X            returnedObject = allocObject(firstarg);
  1634. X            break;
  1635. X
  1636. X        case 9:
  1637. X            returnedObject = allocByte(firstarg);
  1638. X            break;
  1639. X
  1640. X        default:
  1641. X            sysError("intUnary primitive","not implemented yet");
  1642. X        }
  1643. X    return(normalresult);
  1644. X}
  1645. X
  1646. Xint intBinary(number, firstarg, secondarg)
  1647. Xregister int firstarg, secondarg;
  1648. Xint number;
  1649. X{    boolean binresult;
  1650. X    long longresult;
  1651. X
  1652. X    switch(number) {
  1653. X        case 0:        /* addition */
  1654. X            longresult = firstarg;
  1655. X            longresult += secondarg;
  1656. X            if (longCanBeInt(longresult))
  1657. X                firstarg = longresult; 
  1658. X            else
  1659. X                goto overflow;
  1660. X            break;
  1661. X        case 1:        /* subtraction */
  1662. X            longresult = firstarg;
  1663. X            longresult -= secondarg;
  1664. X            if (longCanBeInt(longresult))
  1665. X                firstarg = longresult;
  1666. X            else
  1667. X                goto overflow;
  1668. X            break;
  1669. X
  1670. X        case 2:        /* relationals */
  1671. X            binresult = firstarg < secondarg; break;
  1672. X        case 3:
  1673. X            binresult = firstarg > secondarg; break;
  1674. X        case 4:
  1675. X            binresult = firstarg <= secondarg; break;
  1676. X        case 5:
  1677. X            binresult = firstarg >= secondarg; break;
  1678. X        case 6:
  1679. X            binresult = firstarg == secondarg; break;
  1680. X        case 7:
  1681. X            binresult = firstarg != secondarg; break;
  1682. X
  1683. X        case 8:        /* multiplication */
  1684. X            longresult = firstarg;
  1685. X            longresult *= secondarg;
  1686. X            if (longCanBeInt(longresult))
  1687. X                firstarg = longresult;
  1688. X            else
  1689. X                goto overflow;
  1690. X            break;
  1691. X
  1692. X        case 9:        /* quo: */
  1693. X            if (secondarg == 0) goto overflow;
  1694. X            firstarg /= secondarg; break;
  1695. X
  1696. X        case 10:    /* rem: */
  1697. X            if (secondarg == 0) goto overflow;
  1698. X            firstarg %= secondarg; break;
  1699. X
  1700. X        case 11:    /* bit operations */
  1701. X            firstarg &= secondarg; break;
  1702. X        case 12:
  1703. X            firstarg ^= secondarg; break;
  1704. X            
  1705. X        case 19:    /* shifts */
  1706. X            if (secondarg < 0)
  1707. X                firstarg >>= (- secondarg);
  1708. X            else
  1709. X                firstarg <<= secondarg;
  1710. X            break;
  1711. X    }
  1712. X    if ((number >= 2) && (number <= 7))
  1713. X        if (binresult)
  1714. X            returnedObject = trueobj;
  1715. X        else
  1716. X            returnedObject = falseobj;
  1717. X    else
  1718. X        returnedObject = newInteger(firstarg);
  1719. X    return(normalresult);
  1720. X
  1721. X        /* on overflow, return nil and let smalltalk code */
  1722. X        /* figure out what to do */
  1723. Xoverflow:
  1724. X    returnedObject = nilobj;
  1725. X    return(normalresult);
  1726. X}
  1727. X
  1728. Xstatic int strUnary(number, firstargument)
  1729. Xint number;
  1730. Xchar *firstargument;
  1731. X{
  1732. X    switch(number) {
  1733. X        case 1:        /* length of string */
  1734. X            returnedObject = newInteger(strlen(firstargument));
  1735. X            break;
  1736. X
  1737. X        case 3:        /* string as symbol */
  1738. X            returnedObject = newSymbol(firstargument);
  1739. X            break;
  1740. X
  1741. X        case 8:        /* do a system call */
  1742. X            returnedObject = newInteger(system(firstargument));
  1743. X            break;
  1744. X
  1745. X        default:
  1746. X            sysError("unknown primitive", "strUnary");
  1747. X            break;
  1748. X        }
  1749. X
  1750. X    return(normalresult);
  1751. X}
  1752. X
  1753. Xstatic int floatUnary(number, firstarg)
  1754. Xint number;
  1755. Xdouble firstarg;
  1756. X{    char buffer[20];
  1757. X    double temp;
  1758. X
  1759. X    switch(number) {
  1760. X        case 1:        /* asString */
  1761. X            ignore sprintf(buffer,"%g", firstarg);
  1762. X            returnedObject = newStString(buffer);
  1763. X            break;
  1764. X
  1765. X        case 2:        /* log */
  1766. X            returnedObject = newFloat(log(firstarg));
  1767. X            break;
  1768. X
  1769. X        case 3:        /* exp */
  1770. X            returnedObject = newFloat(exp(firstarg));
  1771. X            break;
  1772. X
  1773. X        case 4:        /* sqrt */
  1774. X            returnedObject = newFloat(sqrt(firstarg));
  1775. X            break;
  1776. X
  1777. X        case 6:        /* integer part */
  1778. X            ignore modf(firstarg, &temp);
  1779. X            returnedObject = newInteger((int) temp);
  1780. X            break;
  1781. X
  1782. X        default:
  1783. X            sysError("unknown primitive","floatUnary");
  1784. X            break;
  1785. X        }
  1786. X
  1787. X    return(normalresult);
  1788. X}
  1789. X
  1790. Xint floatBinary(number, first, second)
  1791. Xint number;
  1792. Xdouble first, second;
  1793. X{     boolean binResult;
  1794. X
  1795. X    switch(number) {
  1796. X        case 0: first += second; break;
  1797. X
  1798. X        case 1:    first -= second; break;
  1799. X        case 2: binResult = (first < second); break;
  1800. X        case 3: binResult = (first > second); break;
  1801. X        case 4: binResult = (first <= second); break;
  1802. X        case 5: binResult = (first >= second); break;
  1803. X        case 6: binResult = (first == second); break;
  1804. X        case 7: binResult = (first != second); break;
  1805. X        case 8: first *= second; break;
  1806. X        case 9: first /= second; break;
  1807. X        default:    
  1808. X            sysError("unknown primitive", "floatBinary");
  1809. X            break;
  1810. X        }
  1811. X
  1812. X    if ((number >= 2) && (number <= 7))
  1813. X        if (binResult)
  1814. X            returnedObject = trueobj;
  1815. X        else
  1816. X            returnedObject = falseobj;
  1817. X    else
  1818. X        returnedObject = newFloat(first);
  1819. X    return(normalresult);
  1820. X}
  1821. X
  1822. X/* file primitives - necessaryily rather UNIX dependent;
  1823. X    basically, files are all kept in a large array.
  1824. X    File operations then just give an index into this array 
  1825. X*/
  1826. X# define MAXFILES 20
  1827. X/* we assume this is initialized to NULL */
  1828. Xstatic FILE *filepointers[MAXFILES];
  1829. X
  1830. Xstatic int filePrimitive(number, arguments, size)
  1831. Xint number, size;
  1832. Xobject *arguments;
  1833. X{    int i;
  1834. X    char *p, buffer[512];
  1835. X
  1836. X    returnedObject = nilobj;
  1837. X
  1838. X    if (number) {        /* not an open, we can get file number*/
  1839. X        if (! isInteger(arguments[0]))
  1840. X            return(typeerror);
  1841. X        i = intValue(arguments[0]);
  1842. X        }
  1843. X
  1844. X    switch(number) {
  1845. X        case 0:        /* file open */
  1846. X                /* first find a free slot */
  1847. X            for (i = 0; i < MAXFILES; i++)
  1848. X                if (filepointers[i] == NULL)
  1849. X                    break;
  1850. X            if (i >= MAXFILES)
  1851. X                sysError("too many open files","primitive");
  1852. X
  1853. X            p = charPtr(arguments[0]);
  1854. X            if (streq(p, "stdin")) 
  1855. X                filepointers[i] = stdin;
  1856. X            else if (streq(p, "stdout"))
  1857. X                filepointers[i] = stdout;
  1858. X            else if (streq(p, "stderr"))
  1859. X                filepointers[i] = stderr;
  1860. X            else {
  1861. X                filepointers[i] = fopen(p, charPtr(arguments[1]));
  1862. X                }
  1863. X            if (filepointers[i] == NULL)
  1864. X                returnedObject = nilobj;
  1865. X            else
  1866. X                returnedObject = newInteger(i);
  1867. X            break;
  1868. X
  1869. X        case 1:        /* file close - recover slot */
  1870. X            ignore fclose(filepointers[i]);
  1871. X            filepointers[i] = NULL;
  1872. X            break;
  1873. X
  1874. X        case 2:        /* file size */
  1875. X        case 3:        /* file seek */
  1876. X        case 4:        /* get character */
  1877. X            sysError("file operation not implemented yet","");
  1878. X
  1879. X        case 5:        /* get string */
  1880. X            if (fgets(buffer, 512, filepointers[i]) != NULL) {
  1881. X                if (filepointers[i] == stdin) {
  1882. X                    /* delete the newline */
  1883. X                    i = strlen(buffer);
  1884. X                    if (buffer[i-1] == '\n')
  1885. X                        buffer[i-1] = '\0';
  1886. X                    }
  1887. X                returnedObject = newStString(buffer);
  1888. X                }
  1889. X            break;
  1890. X
  1891. X        case 7:        /* write an object image */
  1892. X            imageWrite(filepointers[i]);
  1893. X            returnedObject = trueobj;
  1894. X            break;
  1895. X
  1896. X        case 8:        /* print no return */
  1897. X        case 9:        /* print string */
  1898. X            ignore fputs(charPtr(arguments[1]), filepointers[i]);
  1899. X            if (number == 8)
  1900. X                ignore fflush(filepointers[i]);
  1901. X            else
  1902. X                ignore fputc('\n', filepointers[i]);
  1903. X            break;
  1904. X
  1905. X        default:
  1906. X            sysError("unknown primitive","filePrimitive");
  1907. X        }
  1908. X
  1909. X    return(normalresult);
  1910. X}
  1911. X
  1912. X/* primitive -
  1913. X    the main driver for the primitive handler
  1914. X*/
  1915. Xboolean primitive(primitiveNumber, arguments, size)
  1916. Xint primitiveNumber, size;
  1917. Xobject *arguments;
  1918. X{    int primitiveGroup;
  1919. X    boolean done = false;
  1920. X    int response;
  1921. X
  1922. X    primitiveGroup = primitiveNumber / 10;
  1923. X    response = normalresult;
  1924. X    switch(primitiveGroup) {
  1925. X        case 0: case 1: case 2: case 3:
  1926. X            if (size != primitiveGroup)
  1927. X                response = counterror;
  1928. X            else {
  1929. X                switch(primitiveGroup) {
  1930. X                    case 0:
  1931. X                        response = zeroaryPrims(primitiveNumber);
  1932. X                        break;
  1933. X                    case 1:
  1934. X                        response = unaryPrims(primitiveNumber - 10, arguments[0]);
  1935. X                        break;
  1936. X                    case 2:
  1937. X                        response = binaryPrims(primitiveNumber-20, arguments[0], arguments[1]);
  1938. X                        break;
  1939. X                    case 3:
  1940. X                        response = trinaryPrims(primitiveNumber-30, arguments[0], arguments[1], arguments[2]);
  1941. X                        break;
  1942. X                }
  1943. X            }
  1944. X            break;
  1945. X
  1946. X
  1947. X        case 5:            /* integer unary operations */
  1948. X            if (size != 1)
  1949. X                response = counterror;
  1950. X            else if (! isInteger(arguments[0]))
  1951. X                response = typeerror;
  1952. X            else
  1953. X                response = intUnary(primitiveNumber-50,
  1954. X                        intValue(arguments[0]));
  1955. X            break;
  1956. X
  1957. X        case 6: case 7:        /* integer binary operations */
  1958. X            if (size != 2)
  1959. X                response = counterror;
  1960. X            else if ((! isInteger(arguments[0])) || 
  1961. X                  ! isInteger(arguments[1]))
  1962. X                response = typeerror;
  1963. X            else
  1964. X                response = intBinary(primitiveNumber-60,
  1965. X                    intValue(arguments[0]), 
  1966. X                    intValue(arguments[1]));
  1967. X            break;
  1968. X
  1969. X        case 8:            /* string unary */
  1970. X            if (size != 1)
  1971. X                response = counterror;
  1972. X            else if (! isString(arguments[0]))
  1973. X                response = typeerror;
  1974. X            else
  1975. X                response = strUnary(primitiveNumber-80,
  1976. X                    charPtr(arguments[0]));
  1977. X            break;
  1978. X
  1979. X        case 10:        /* float unary */
  1980. X            if (size != 1)
  1981. X                response = counterror;
  1982. X            else if (! isFloat(arguments[0]))
  1983. X                response = typeerror;
  1984. X            else
  1985. X                response = floatUnary(primitiveNumber-100,
  1986. X                    floatValue(arguments[0]));
  1987. X            break;
  1988. X
  1989. X        case 11:        /* float binary */
  1990. X            if (size != 2)
  1991. X                response = counterror;
  1992. X            else if ((! isFloat(arguments[0])) ||
  1993. X                 (! isFloat(arguments[1])))
  1994. X                response = typeerror;
  1995. X            else
  1996. X                response = floatBinary(primitiveNumber-110,
  1997. X                    floatValue(arguments[0]),
  1998. X                    floatValue(arguments[1]));
  1999. X            break;
  2000. X
  2001. X        case 12:        /* file operations */
  2002. X            response = filePrimitive(primitiveNumber-120,
  2003. X                arguments, size);
  2004. X            break;
  2005. X    }
  2006. X
  2007. X    /* now check return code */
  2008. X    switch(response) {
  2009. X        case normalresult:
  2010. X            break;
  2011. X        case quitinterp:
  2012. X            done = true;
  2013. X            break;
  2014. X        case counterror:
  2015. X            sysError("count error","in primitive");
  2016. X            break;
  2017. X        case typeerror:
  2018. X            sysError("type error","in primitive");
  2019. X            returnedObject = nilobj;
  2020. X            break;
  2021. X
  2022. X        default:
  2023. X            sysError("unknown return code","in primitive");
  2024. X            returnedObject = nilobj;
  2025. X            break;
  2026. X    }
  2027. X    return (done);
  2028. X}
  2029. X
  2030. /
  2031. echo 'x - script.ini'
  2032. sed 's/^X//' > script.ini << '/'
  2033. X    globalNames at: #version put: '2.02'
  2034. X    globalNames at: #editor put: 'vi'
  2035. /
  2036. echo 'x - test.ini'
  2037. sed 's/^X//' > test.ini << '/'
  2038. X    test all
  2039. /
  2040. echo 'Part 01 of small.v2 complete.'
  2041. exit
  2042.