Compiler-Tests.st 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  1. Smalltalk current createPackage: 'Compiler-Tests' properties: #{}!
  2. TestCase subclass: #CodeGeneratorTest
  3. instanceVariableNames: 'receiver'
  4. package: 'Compiler-Tests'!
  5. !CodeGeneratorTest methodsFor: 'accessing'!
  6. codeGeneratorClass
  7. ^ CodeGenerator
  8. !
  9. targetClass
  10. ^ DoIt
  11. ! !
  12. !CodeGeneratorTest methodsFor: 'factory'!
  13. compiler
  14. ^ Compiler new
  15. codeGeneratorClass: self codeGeneratorClass;
  16. yourself
  17. ! !
  18. !CodeGeneratorTest methodsFor: 'initialization'!
  19. setUp
  20. receiver := self targetClass new
  21. !
  22. tearDown
  23. "receiver := nil"
  24. ! !
  25. !CodeGeneratorTest methodsFor: 'testing'!
  26. should: aString return: anObject
  27. | method result |
  28. method := self compiler install: aString forClass: self targetClass category: 'tests'.
  29. result := receiver perform: method selector.
  30. self targetClass removeCompiledMethod: method.
  31. self assert: anObject equals: result
  32. ! !
  33. !CodeGeneratorTest methodsFor: 'tests'!
  34. testAssignment
  35. self should: 'foo | a | a := true ifTrue: [ 1 ]. ^ a' return: 1.
  36. self should: 'foo | a | a := false ifTrue: [ 1 ]. ^ a' return: nil.
  37. self should: 'foo | a | ^ a := true ifTrue: [ 1 ]' return: 1
  38. !
  39. testBlockReturn
  40. self should: 'foo ^ #(1 2 3) collect: [ :each | true ifTrue: [ each + 1 ] ]' return: #(2 3 4).
  41. self should: 'foo ^ #(1 2 3) collect: [ :each | false ifFalse: [ each + 1 ] ]' return: #(2 3 4).
  42. self should: 'foo ^ #(1 2 3) collect: [ :each | each odd ifTrue: [ each + 1 ] ifFalse: [ each - 1 ] ]' return: #(2 1 4).
  43. !
  44. testCascades
  45. self should: 'foo ^ Array new add: 3; add: 4; yourself' return: #(3 4)
  46. !
  47. testLiterals
  48. self should: 'foo ^ 1' return: 1.
  49. self should: 'foo ^ ''hello''' return: 'hello'.
  50. self should: 'foo ^ #(1 2 3 4)' return: #(1 2 3 4).
  51. self should: 'foo ^ {1. [:x | x ] value: 2. 3. [4] value}' return: #(1 2 3 4).
  52. self should: 'foo ^ true' return: true.
  53. self should: 'foo ^ false' return: false.
  54. self should: 'foo ^ #{1->2. 3->4}' return: #{1->2. 3->4}.
  55. self should: 'foo ^ #hello' return: #hello.
  56. self should: 'foo ^ -123.456' return: -123.456
  57. !
  58. testLocalReturn
  59. self should: 'foo ^ 1' return: 1.
  60. self should: 'foo ^ 1 + 1' return: 2.
  61. self should: 'foo ' return: receiver.
  62. self should: 'foo self asString' return: receiver.
  63. self should: 'foo | a b | a := 1. b := 2. ^ a + b' return: 3
  64. !
  65. testMessageSends
  66. self should: 'foo ^ 1 asString' return: '1'.
  67. self should: 'foo ^ 1 + 1' return: 2.
  68. self should: 'foo ^ 1 + 2 * 3' return: 9.
  69. self should: 'foo ^ 1 to: 3' return: #(1 2 3).
  70. self should: 'foo ^ 1 to: 5 by: 2' return: #(1 3 5)
  71. !
  72. testNestedIfTrue
  73. self should: 'foo ^ true ifTrue: [ false ifFalse: [ 1 ] ]' return: 1.
  74. self should: 'foo ^ true ifTrue: [ false ifTrue: [ 1 ] ]' return: nil.
  75. self should: 'foo true ifTrue: [ false ifFalse: [ ^ 1 ] ]' return: 1.
  76. self should: 'foo true ifTrue: [ false ifTrue: [ ^ 1 ] ]' return: receiver.
  77. !
  78. testNonLocalReturn
  79. self should: 'foo [ ^ 1 ] value' return: 1.
  80. self should: 'foo [ ^ 1 + 1 ] value' return: 2.
  81. self should: 'foo | a b | a := 1. b := 2. [ ^ a + b ] value. self halt' return: 3.
  82. self should: 'foo [ :x | ^ x + x ] value: 4. ^ 2' return: 8
  83. !
  84. testSendReceiverAndArgumentsOrdered
  85. self should: 'foo
  86. | x |
  87. x := 1.
  88. ^ Array with: x with: (true ifTrue: [ x := 2 ])
  89. ' return: #(1 2).
  90. self should: 'foo
  91. | x |
  92. x := Array.
  93. ^ x with: x with: (true ifTrue: [ x := 2 ])
  94. ' return: {Array. 2}.
  95. !
  96. testifFalse
  97. self should: 'foo true ifFalse: [ ^ 1 ]' return: receiver.
  98. self should: 'foo false ifFalse: [ ^ 2 ]' return: 2.
  99. self should: 'foo ^ true ifFalse: [ 1 ]' return: nil.
  100. self should: 'foo ^ false ifFalse: [ 2 ]' return: 2.
  101. !
  102. testifFalseIfTrue
  103. self should: 'foo true ifFalse: [ ^ 1 ] ifTrue: [ ^ 2 ]' return: 2.
  104. self should: 'foo false ifFalse: [ ^ 2 ] ifTrue: [ ^1 ]' return: 2.
  105. self should: 'foo ^ true ifFalse: [ 1 ] ifTrue: [ 2 ]' return: 2.
  106. self should: 'foo ^ false ifFalse: [ 2 ] ifTrue: [ 1 ]' return: 2.
  107. !
  108. testifNil
  109. self should: 'foo ^ 1 ifNil: [ 2 ]' return: 1.
  110. self should: 'foo ^ nil ifNil: [ 2 ]' return: 2.
  111. self should: 'foo 1 ifNil: [ ^ 2 ]' return: receiver.
  112. self should: 'foo nil ifNil: [ ^ 2 ]' return: 2.
  113. !
  114. testifNilIfNotNil
  115. self should: 'foo ^ 1 ifNil: [ 2 ] ifNotNil: [ 3 ]' return: 3.
  116. self should: 'foo ^ nil ifNil: [ 2 ] ifNotNil: [ 3 ]' return: 2.
  117. self should: 'foo 1 ifNil: [ ^ 2 ] ifNotNil: [ ^3 ]' return: 3.
  118. self should: 'foo nil ifNil: [ ^ 2 ] ifNotNil: [ ^3 ]' return: 2.
  119. !
  120. testifNotNil
  121. self should: 'foo ^ 1 ifNotNil: [ 2 ]' return: 2.
  122. self should: 'foo ^ nil ifNotNil: [ 2 ]' return: nil.
  123. self should: 'foo 1 ifNotNil: [ ^ 2 ]' return: 2.
  124. self should: 'foo nil ifNotNil: [ ^ 2 ]' return: receiver.
  125. !
  126. testifTrue
  127. self should: 'foo false ifTrue: [ ^ 1 ]' return: receiver.
  128. self should: 'foo true ifTrue: [ ^ 2 ]' return: 2.
  129. self should: 'foo ^ false ifTrue: [ 1 ]' return: nil.
  130. self should: 'foo ^ true ifTrue: [ 2 ]' return: 2.
  131. !
  132. testifTrueIfFalse
  133. self should: 'foo false ifTrue: [ ^ 1 ] ifFalse: [ ^2 ]' return: 2.
  134. self should: 'foo true ifTrue: [ ^ 1 ] ifFalse: [ ^ 2 ]' return: 1.
  135. self should: 'foo ^ false ifTrue: [ 2 ] ifFalse: [ 1 ]' return: 1.
  136. self should: 'foo ^ true ifTrue: [ 2 ] ifFalse: [ 1 ]' return: 2.
  137. ! !
  138. CodeGeneratorTest subclass: #InliningCodeGeneratorTest
  139. instanceVariableNames: ''
  140. package: 'Compiler-Tests'!
  141. !InliningCodeGeneratorTest methodsFor: 'accessing'!
  142. codeGeneratorClass
  143. ^ InliningCodeGenerator
  144. ! !
  145. TestCase subclass: #ScopeVarTest
  146. instanceVariableNames: ''
  147. package: 'Compiler-Tests'!
  148. !ScopeVarTest methodsFor: 'tests'!
  149. testClassRefVar
  150. | node |
  151. node := ClassReferenceNode new
  152. value: 'Object';
  153. yourself.
  154. SemanticAnalyzer new visit: node.
  155. self assert: node binding isClassRefVar
  156. !
  157. testInstanceVar
  158. | node scope |
  159. node := VariableNode new
  160. value: 'bzzz';
  161. yourself.
  162. scope := MethodLexicalScope new.
  163. scope addIVar: 'bzzz'.
  164. self assert: (scope bindingFor: node) isInstanceVar
  165. !
  166. testPseudoVar
  167. | node pseudoVars |
  168. pseudoVars := #('self' 'super' 'true' 'false' 'nil').
  169. pseudoVars do: [:each |
  170. node := VariableNode new
  171. value: each;
  172. yourself.
  173. self assert: (MethodLexicalScope new bindingFor: node) isPseudoVar ]
  174. !
  175. testTempVar
  176. | node scope |
  177. node := VariableNode new
  178. value: 'bzzz';
  179. yourself.
  180. scope := MethodLexicalScope new.
  181. scope addTemp: 'bzzz'.
  182. self assert: (scope bindingFor: node) isTempVar
  183. !
  184. testUnknownVar
  185. | node |
  186. node := VariableNode new
  187. value: 'bzzz';
  188. yourself.
  189. self assert: (MethodLexicalScope new bindingFor: node) isNil
  190. ! !
  191. TestCase subclass: #SemanticAnalyzerTest
  192. instanceVariableNames: 'analyzer'
  193. package: 'Compiler-Tests'!
  194. !SemanticAnalyzerTest methodsFor: 'running'!
  195. setUp
  196. analyzer := SemanticAnalyzer on: Object
  197. ! !
  198. !SemanticAnalyzerTest methodsFor: 'tests'!
  199. testAssignment
  200. | src ast |
  201. src := 'foo self := 1'.
  202. ast := smalltalk parse: src.
  203. self should: [analyzer visit: ast] raise: InvalidAssignmentError
  204. !
  205. testNonLocalReturn
  206. | src ast |
  207. src := 'foo | a | a + 1. ^ a'.
  208. ast := smalltalk parse: src.
  209. analyzer visit: ast.
  210. self deny: ast scope hasNonLocalReturn
  211. !
  212. testNonLocalReturn2
  213. | src ast |
  214. src := 'foo | a | a + 1. [ [ ^ a] ]'.
  215. ast := smalltalk parse: src.
  216. analyzer visit: ast.
  217. self assert: ast scope hasNonLocalReturn
  218. !
  219. testScope
  220. | src ast |
  221. src := 'foo | a | a + 1. [ | b | b := a ]'.
  222. ast := smalltalk parse: src.
  223. analyzer visit: ast.
  224. self deny: ast nodes first nodes last scope == ast scope.
  225. !
  226. testScope2
  227. | src ast |
  228. src := 'foo | a | a + 1. [ [ | b | b := a ] ]'.
  229. ast := smalltalk parse: src.
  230. analyzer visit: ast.
  231. self deny: ast nodes first nodes last nodes first nodes first scope == ast scope.
  232. !
  233. testScopeLevel
  234. | src ast |
  235. src := 'foo | a | a + 1. [ [ | b | b := a ] ]'.
  236. ast := smalltalk parse: src.
  237. analyzer visit: ast.
  238. self assert: ast scope scopeLevel = 1.
  239. self assert: ast nodes first nodes last nodes first nodes first scope scopeLevel = 3
  240. !
  241. testUnknownVariables
  242. | src ast |
  243. src := 'foo | a | b + a'.
  244. ast := smalltalk parse: src.
  245. self should: [ analyzer visit: ast ] raise: UnknownVariableError
  246. !
  247. testUnknownVariablesDefinedInJS
  248. < var someVariable = 1 >.
  249. self shouldnt: [ smalltalk parse: 'foo someVariable' ] raise: UnknownVariableError
  250. !
  251. testUnknownVariablesWithScope
  252. | src ast |
  253. src := 'foo | a b | [ c + 1. [ a + 1. d + 1 ]]'.
  254. ast := smalltalk parse: src.
  255. self should: [ analyzer visit: ast ] raise: UnknownVariableError
  256. !
  257. testVariableShadowing
  258. | src ast |
  259. src := 'foo | a | a + 1'.
  260. ast := smalltalk parse: src.
  261. analyzer visit: ast
  262. !
  263. testVariableShadowing2
  264. | src ast |
  265. src := 'foo | a | a + 1. [ | a | a := 2 ]'.
  266. ast := smalltalk parse: src.
  267. self should: [analyzer visit: ast] raise: ShadowingVariableError
  268. !
  269. testVariableShadowing3
  270. | src ast |
  271. src := 'foo | a | a + 1. [ | b | b := 2 ]'.
  272. ast := smalltalk parse: src.
  273. analyzer visit: ast
  274. !
  275. testVariableShadowing4
  276. | src ast |
  277. src := 'foo | a | a + 1. [ [ [ | b | b := 2 ] ] ]'.
  278. ast := smalltalk parse: src.
  279. analyzer visit: ast
  280. !
  281. testVariableShadowing5
  282. | src ast |
  283. src := 'foo | a | a + 1. [ [ [ | a | a := 2 ] ] ]'.
  284. ast := smalltalk parse: src.
  285. self should: [analyzer visit: ast] raise: ShadowingVariableError
  286. !
  287. testVariablesLookup
  288. | src ast |
  289. src := 'foo | a | a + 1. [ | b | b := a ]'.
  290. ast := smalltalk parse: src.
  291. analyzer visit: ast.
  292. "Binding for `a` in the message send"
  293. self assert: ast nodes first nodes first receiver binding isTempVar.
  294. self assert: ast nodes first nodes first receiver binding scope == ast scope.
  295. "Binding for `b`"
  296. self assert: ast nodes first nodes last nodes first nodes first left binding isTempVar.
  297. self assert: ast nodes first nodes last nodes first nodes first left binding scope == ast nodes first nodes last scope.
  298. ! !