Compiler.st 78 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844
  1. Smalltalk current createPackage: 'Compiler'!
  2. Object subclass: #ChunkParser
  3. instanceVariableNames: 'stream'
  4. package:'Compiler'!
  5. !ChunkParser methodsFor: '*Compiler'!
  6. stream: aStream
  7. stream := aStream
  8. ! !
  9. !ChunkParser methodsFor: '*Compiler'!
  10. nextChunk
  11. "The chunk format (Smalltalk Interchange Format or Fileout format)
  12. is a trivial format but can be a bit tricky to understand:
  13. - Uses the exclamation mark as delimiter of chunks.
  14. - Inside a chunk a normal exclamation mark must be doubled.
  15. - A non empty chunk must be a valid Smalltalk expression.
  16. - A chunk on top level with a preceding empty chunk is an instruction chunk:
  17. - The object created by the expression then takes over reading chunks.
  18. This metod returns next chunk as a String (trimmed), empty String (all whitespace) or nil."
  19. | char result chunk |
  20. result := '' writeStream.
  21. [char := stream next.
  22. char notNil] whileTrue: [
  23. char = '!!' ifTrue: [
  24. stream peek = '!!'
  25. ifTrue: [stream next "skipping the escape double"]
  26. ifFalse: [^result contents trimBoth "chunk end marker found"]].
  27. result nextPut: char].
  28. ^nil "a chunk needs to end with !!"
  29. ! !
  30. !ChunkParser class methodsFor: '*Compiler'!
  31. on: aStream
  32. ^self new stream: aStream
  33. ! !
  34. Object subclass: #Exporter
  35. instanceVariableNames: ''
  36. package:'Compiler'!
  37. !Exporter methodsFor: '*Compiler'!
  38. exportAll
  39. "Export all packages in the system."
  40. ^String streamContents: [:stream |
  41. Smalltalk current packages do: [:pkg |
  42. stream nextPutAll: (self exportPackage: pkg name)]]
  43. !
  44. exportClass: aClass
  45. "Export a single class. Subclasses override these methods."
  46. ^String streamContents: [:stream |
  47. self exportDefinitionOf: aClass on: stream.
  48. self exportMethodsOf: aClass on: stream.
  49. self exportMetaDefinitionOf: aClass on: stream.
  50. self exportMethodsOf: aClass class on: stream]
  51. !
  52. exportPackage: packageName
  53. "Export a given package by name."
  54. | package |
  55. ^String streamContents: [:stream |
  56. package := Smalltalk current packageAt: packageName.
  57. self exportPackageDefinitionOf: package on: stream.
  58. "Export classes in dependency order.
  59. Update (issue #171): Remove duplicates for export"
  60. package sortedClasses asSet do: [:each |
  61. stream nextPutAll: (self exportClass: each)].
  62. self exportPackageExtensionsOf: package on: stream]
  63. ! !
  64. !Exporter methodsFor: '*Compiler'!
  65. classNameFor: aClass
  66. ^aClass isMetaclass
  67. ifTrue: [aClass instanceClass name, '.klass']
  68. ifFalse: [
  69. aClass isNil
  70. ifTrue: ['nil']
  71. ifFalse: [aClass name]]
  72. !
  73. exportDefinitionOf: aClass on: aStream
  74. aStream
  75. nextPutAll: 'smalltalk.addClass(';
  76. nextPutAll: '''', (self classNameFor: aClass), ''', ';
  77. nextPutAll: 'smalltalk.', (self classNameFor: aClass superclass);
  78. nextPutAll: ', ['.
  79. aClass instanceVariableNames
  80. do: [:each | aStream nextPutAll: '''', each, '''']
  81. separatedBy: [aStream nextPutAll: ', '].
  82. aStream
  83. nextPutAll: '], ''';
  84. nextPutAll: aClass category, '''';
  85. nextPutAll: ');'.
  86. aClass comment notEmpty ifTrue: [
  87. aStream
  88. lf;
  89. nextPutAll: 'smalltalk.';
  90. nextPutAll: (self classNameFor: aClass);
  91. nextPutAll: '.comment=';
  92. nextPutAll: aClass comment asJavascript].
  93. aStream lf
  94. !
  95. exportMetaDefinitionOf: aClass on: aStream
  96. aClass class instanceVariableNames isEmpty ifFalse: [
  97. aStream
  98. nextPutAll: 'smalltalk.', (self classNameFor: aClass class);
  99. nextPutAll: '.iVarNames = ['.
  100. aClass class instanceVariableNames
  101. do: [:each | aStream nextPutAll: '''', each, '''']
  102. separatedBy: [aStream nextPutAll: ','].
  103. aStream nextPutAll: '];', String lf]
  104. !
  105. exportMethod: aMethod of: aClass on: aStream
  106. aStream
  107. nextPutAll: 'smalltalk.addMethod(';lf;
  108. nextPutAll: aMethod selector asSelector asJavascript, ',';lf;
  109. nextPutAll: 'smalltalk.method({';lf;
  110. nextPutAll: 'selector: ', aMethod selector asJavascript, ',';lf;
  111. nextPutAll: 'category: ''', aMethod category, ''',';lf;
  112. nextPutAll: 'fn: ', aMethod fn compiledSource, ',';lf;
  113. nextPutAll: 'args: ', aMethod arguments asJavascript, ','; lf;
  114. nextPutAll: 'source: ', aMethod source asJavascript, ',';lf;
  115. nextPutAll: 'messageSends: ', aMethod messageSends asJavascript, ',';lf;
  116. nextPutAll: 'referencedClasses: ', aMethod referencedClasses asJavascript.
  117. aStream
  118. lf;
  119. nextPutAll: '}),';lf;
  120. nextPutAll: 'smalltalk.', (self classNameFor: aClass);
  121. nextPutAll: ');';lf;lf
  122. !
  123. exportMethodsOf: aClass on: aStream
  124. "Issue #143: sort methods alphabetically"
  125. ((aClass methodDictionary values) sorted: [:a :b | a selector <= b selector]) do: [:each |
  126. (each category match: '^\*') ifFalse: [
  127. self exportMethod: each of: aClass on: aStream]].
  128. aStream lf
  129. !
  130. exportPackageDefinitionOf: package on: aStream
  131. aStream
  132. nextPutAll: 'smalltalk.addPackage(';
  133. nextPutAll: '''', package name, ''', ', package propertiesAsJSON , ');'.
  134. aStream lf
  135. !
  136. exportPackageExtensionsOf: package on: aStream
  137. "Issue #143: sort classes and methods alphabetically"
  138. | name |
  139. name := package name.
  140. (Package sortedClasses: Smalltalk current classes) do: [:each |
  141. {each. each class} do: [:aClass |
  142. ((aClass methodDictionary values) sorted: [:a :b | a selector <= b selector]) do: [:method |
  143. (method category match: '^\*', name) ifTrue: [
  144. self exportMethod: method of: aClass on: aStream ]]]]
  145. ! !
  146. Exporter subclass: #ChunkExporter
  147. instanceVariableNames: ''
  148. package:'Compiler'!
  149. !ChunkExporter methodsFor: '*Compiler'!
  150. chunkEscape: aString
  151. "Replace all occurrences of !! with !!!! and trim at both ends."
  152. ^(aString replace: '!!' with: '!!!!') trimBoth
  153. !
  154. classNameFor: aClass
  155. ^aClass isMetaclass
  156. ifTrue: [aClass instanceClass name, ' class']
  157. ifFalse: [
  158. aClass isNil
  159. ifTrue: ['nil']
  160. ifFalse: [aClass name]]
  161. !
  162. exportDefinitionOf: aClass on: aStream
  163. "Chunk format."
  164. aStream
  165. nextPutAll: (self classNameFor: aClass superclass);
  166. nextPutAll: ' subclass: #', (self classNameFor: aClass); lf;
  167. nextPutAll: ' instanceVariableNames: '''.
  168. aClass instanceVariableNames
  169. do: [:each | aStream nextPutAll: each]
  170. separatedBy: [aStream nextPutAll: ' '].
  171. aStream
  172. nextPutAll: ''''; lf;
  173. nextPutAll: ' package: ''', aClass category, '''!!'; lf.
  174. aClass comment notEmpty ifTrue: [
  175. aStream
  176. nextPutAll: '!!', (self classNameFor: aClass), ' commentStamp!!';lf;
  177. nextPutAll: (self chunkEscape: aClass comment), '!!';lf].
  178. aStream lf
  179. !
  180. exportMetaDefinitionOf: aClass on: aStream
  181. aClass class instanceVariableNames isEmpty ifFalse: [
  182. aStream
  183. nextPutAll: (self classNameFor: aClass class);
  184. nextPutAll: ' instanceVariableNames: '''.
  185. aClass class instanceVariableNames
  186. do: [:each | aStream nextPutAll: each]
  187. separatedBy: [aStream nextPutAll: ' '].
  188. aStream
  189. nextPutAll: '''!!'; lf; lf]
  190. !
  191. exportMethod: aMethod of: aClass on: aStream
  192. aStream
  193. lf; lf; nextPutAll: (self chunkEscape: aMethod source); lf;
  194. nextPutAll: '!!'
  195. !
  196. exportMethods: methods category: category of: aClass on: aStream
  197. "Issue #143: sort methods alphabetically"
  198. aStream
  199. nextPutAll: '!!', (self classNameFor: aClass);
  200. nextPutAll: ' methodsFor: ''', category, '''!!'.
  201. (methods sorted: [:a :b | a selector <= b selector]) do: [:each |
  202. self exportMethod: each of: aClass on: aStream].
  203. aStream nextPutAll: ' !!'; lf; lf
  204. !
  205. exportMethodsOf: aClass on: aStream
  206. "Issue #143: sort protocol alphabetically"
  207. | map |
  208. map := Dictionary new.
  209. aClass protocolsDo: [:category :methods |
  210. (category match: '^\*') ifFalse: [ map at: category put: methods ]].
  211. (map keys sorted: [:a :b | a <= b ]) do: [:category | | methods |
  212. methods := map at: category.
  213. self
  214. exportMethods: methods
  215. category: category
  216. of: aClass
  217. on: aStream ]
  218. !
  219. exportPackageDefinitionOf: package on: aStream
  220. "Chunk format."
  221. aStream
  222. nextPutAll: 'Smalltalk current createPackage: ''', package name,
  223. ''' properties: ', package properties storeString, '!!'; lf.
  224. !
  225. exportPackageExtensionsOf: package on: aStream
  226. "We need to override this one too since we need to group
  227. all methods in a given protocol under a leading methodsFor: chunk
  228. for that class."
  229. "Issue #143: sort protocol alphabetically"
  230. | name map |
  231. name := package name.
  232. (Package sortedClasses: Smalltalk current classes) do: [:each |
  233. {each. each class} do: [:aClass |
  234. map := Dictionary new.
  235. aClass protocolsDo: [:category :methods |
  236. (category match: '^\*', name) ifTrue: [ map at: category put: methods ]].
  237. (map keys sorted: [:a :b | a <= b ]) do: [:category | | methods |
  238. methods := map at: category.
  239. self exportMethods: methods category: category of: aClass on: aStream ]]]
  240. ! !
  241. Exporter subclass: #StrippedExporter
  242. instanceVariableNames: ''
  243. package:'Compiler'!
  244. !StrippedExporter methodsFor: '*Compiler'!
  245. exportDefinitionOf: aClass on: aStream
  246. aStream
  247. nextPutAll: 'smalltalk.addClass(';
  248. nextPutAll: '''', (self classNameFor: aClass), ''', ';
  249. nextPutAll: 'smalltalk.', (self classNameFor: aClass superclass);
  250. nextPutAll: ', ['.
  251. aClass instanceVariableNames
  252. do: [:each | aStream nextPutAll: '''', each, '''']
  253. separatedBy: [aStream nextPutAll: ', '].
  254. aStream
  255. nextPutAll: '], ''';
  256. nextPutAll: aClass category, '''';
  257. nextPutAll: ');'.
  258. aStream lf
  259. !
  260. exportMethod: aMethod of: aClass on: aStream
  261. aStream
  262. nextPutAll: 'smalltalk.addMethod(';lf;
  263. nextPutAll: aMethod selector asSelector asJavascript, ',';lf;
  264. nextPutAll: 'smalltalk.method({';lf;
  265. nextPutAll: 'selector: ', aMethod selector asJavascript, ',';lf;
  266. nextPutAll: 'fn: ', aMethod fn compiledSource;lf;
  267. nextPutAll: '}),';lf;
  268. nextPutAll: 'smalltalk.', (self classNameFor: aClass);
  269. nextPutAll: ');';lf;lf
  270. ! !
  271. Object subclass: #Importer
  272. instanceVariableNames: ''
  273. package:'Compiler'!
  274. !Importer methodsFor: '*Compiler'!
  275. import: aStream
  276. | chunk result parser lastEmpty |
  277. parser := ChunkParser on: aStream.
  278. lastEmpty := false.
  279. [chunk := parser nextChunk.
  280. chunk isNil] whileFalse: [
  281. chunk isEmpty
  282. ifTrue: [lastEmpty := true]
  283. ifFalse: [
  284. result := Compiler new evaluateExpression: chunk.
  285. lastEmpty
  286. ifTrue: [
  287. lastEmpty := false.
  288. result scanFrom: parser]]]
  289. ! !
  290. Object subclass: #PackageLoader
  291. instanceVariableNames: ''
  292. package:'Compiler'!
  293. !PackageLoader methodsFor: '*Compiler'!
  294. initializePackageNamed: packageName prefix: aString
  295. (Package named: packageName)
  296. setupClasses;
  297. commitPathJs: '/', aString, '/js';
  298. commitPathSt: '/', aString, '/st'
  299. !
  300. loadPackage: packageName prefix: aString
  301. | url |
  302. url := '/', aString, '/js/', packageName, '.js'.
  303. jQuery
  304. ajax: url
  305. options: #{
  306. 'type' -> 'GET'.
  307. 'dataType' -> 'script'.
  308. 'complete' -> [ :jqXHR :textStatus |
  309. jqXHR readyState = 4
  310. ifTrue: [ self initializePackageNamed: packageName prefix: aString ] ].
  311. 'error' -> [ window alert: 'Could not load package at: ', url ]
  312. }
  313. !
  314. loadPackages: aCollection prefix: aString
  315. aCollection do: [ :each |
  316. self loadPackage: each prefix: aString ]
  317. ! !
  318. !PackageLoader class methodsFor: '*Compiler'!
  319. loadPackages: aCollection prefix: aString
  320. ^ self new loadPackages: aCollection prefix: aString
  321. ! !
  322. Error subclass: #CompilerError
  323. instanceVariableNames: ''
  324. package:'Compiler'!
  325. !CompilerError commentStamp!
  326. I am the common superclass of all compiling errors.!
  327. CompilerError subclass: #ParseError
  328. instanceVariableNames: ''
  329. package:'Compiler'!
  330. !ParseError commentStamp!
  331. Instance of ParseError are signaled on any parsing error.
  332. See `Smalltalk >> #parse:`!
  333. CompilerError subclass: #SemanticError
  334. instanceVariableNames: ''
  335. package:'Compiler'!
  336. !SemanticError commentStamp!
  337. I represent an abstract semantic error thrown by the SemanticAnalyzer.
  338. Semantic errors can be unknown variable errors, etc.
  339. See my subclasses for concrete errors.
  340. The IDE should catch instances of Semantic error to deal with them when compiling!
  341. SemanticError subclass: #InliningError
  342. instanceVariableNames: ''
  343. package:'Compiler'!
  344. !InliningError commentStamp!
  345. Instances of InliningError are signaled when using an `InliningCodeGenerator`in a `Compiler`.!
  346. SemanticError subclass: #InvalidAssignmentError
  347. instanceVariableNames: 'variableName'
  348. package:'Compiler'!
  349. !InvalidAssignmentError commentStamp!
  350. I get signaled when a pseudo variable gets assigned.!
  351. !InvalidAssignmentError methodsFor: '*Compiler'!
  352. messageText
  353. ^ ' Invalid assignment to variable: ', self variableName
  354. !
  355. variableName
  356. ^ variableName
  357. !
  358. variableName: aString
  359. variableName := aString
  360. ! !
  361. SemanticError subclass: #ShadowingVariableError
  362. instanceVariableNames: 'variableName'
  363. package:'Compiler'!
  364. !ShadowingVariableError commentStamp!
  365. I get signaled when a variable in a block or method scope shadows a variable of the same name in an outer scope.!
  366. !ShadowingVariableError methodsFor: '*Compiler'!
  367. messageText
  368. ^ 'Variable shadowing error: ', self variableName, ' is already defined'
  369. !
  370. variableName
  371. ^ variableName
  372. !
  373. variableName: aString
  374. variableName := aString
  375. ! !
  376. SemanticError subclass: #UnknownVariableError
  377. instanceVariableNames: 'variableName'
  378. package:'Compiler'!
  379. !UnknownVariableError commentStamp!
  380. I get signaled when a variable is not defined.
  381. The default behavior is to allow it, as this is how Amber currently is able to seamlessly send messages to JavaScript objects.!
  382. !UnknownVariableError methodsFor: '*Compiler'!
  383. variableName
  384. ^ variableName
  385. !
  386. variableName: aString
  387. variableName := aString
  388. ! !
  389. Object subclass: #Compiler
  390. instanceVariableNames: 'currentClass source unknownVariables codeGeneratorClass'
  391. package:'Compiler'!
  392. !Compiler commentStamp!
  393. I provide the public interface for compiling Amber source code into JavaScript.
  394. The code generator used to produce JavaScript can be plugged with `#codeGeneratorClass`.
  395. The default code generator is an instance of `InlinedCodeGenerator`!
  396. !Compiler methodsFor: '*Compiler'!
  397. codeGeneratorClass
  398. ^codeGeneratorClass ifNil: [InliningCodeGenerator]
  399. !
  400. codeGeneratorClass: aClass
  401. codeGeneratorClass := aClass
  402. !
  403. currentClass
  404. ^currentClass
  405. !
  406. currentClass: aClass
  407. currentClass := aClass
  408. !
  409. source
  410. ^source ifNil: ['']
  411. !
  412. source: aString
  413. source := aString
  414. !
  415. unknownVariables
  416. ^unknownVariables
  417. !
  418. unknownVariables: aCollection
  419. unknownVariables := aCollection
  420. ! !
  421. !Compiler methodsFor: '*Compiler'!
  422. compile: aString
  423. ^self compileNode: (self parse: aString)
  424. !
  425. compile: aString forClass: aClass
  426. self currentClass: aClass.
  427. self source: aString.
  428. ^self compile: aString
  429. !
  430. compileExpression: aString
  431. self currentClass: DoIt.
  432. self source: 'doIt ^[', aString, '] value'.
  433. ^self compileNode: (self parse: self source)
  434. !
  435. compileNode: aNode
  436. | generator result |
  437. generator := self codeGeneratorClass new.
  438. generator
  439. source: self source;
  440. currentClass: self currentClass.
  441. result := generator compileNode: aNode.
  442. self unknownVariables: #().
  443. ^result
  444. !
  445. eval: aString
  446. <return eval(aString)>
  447. !
  448. evaluateExpression: aString
  449. "Unlike #eval: evaluate a Smalltalk expression and answer the returned object"
  450. | result |
  451. DoIt addCompiledMethod: (self eval: (self compileExpression: aString)).
  452. result := DoIt new doIt.
  453. DoIt removeCompiledMethod: (DoIt methodDictionary at: 'doIt').
  454. ^result
  455. !
  456. install: aString forClass: aBehavior category: anotherString
  457. | compiled |
  458. compiled := self eval: (self compile: aString forClass: aBehavior).
  459. compiled category: anotherString.
  460. aBehavior addCompiledMethod: compiled.
  461. self setupClass: aBehavior.
  462. ^compiled
  463. !
  464. parse: aString
  465. ^Smalltalk current parse: aString
  466. !
  467. parseExpression: aString
  468. ^self parse: 'doIt ^[', aString, '] value'
  469. !
  470. recompile: aClass
  471. aClass methodDictionary do: [:each |
  472. console log: aClass name, ' >> ', each selector.
  473. self install: each source forClass: aClass category: each category].
  474. self setupClass: aClass.
  475. aClass isMetaclass ifFalse: [self recompile: aClass class]
  476. !
  477. recompileAll
  478. Smalltalk current classes do: [:each |
  479. Transcript show: each; cr.
  480. [self recompile: each] valueWithTimeout: 100]
  481. !
  482. setupClass: aClass
  483. <smalltalk.init(aClass)>
  484. ! !
  485. !Compiler class methodsFor: '*Compiler'!
  486. recompile: aClass
  487. self new recompile: aClass
  488. !
  489. recompileAll
  490. Smalltalk current classes do: [:each |
  491. self recompile: each]
  492. ! !
  493. Object subclass: #DoIt
  494. instanceVariableNames: ''
  495. package:'Compiler'!
  496. !DoIt commentStamp!
  497. `DoIt` is the class used to compile and evaluate expressions. See `Compiler >> evaluateExpression:`.!
  498. Object subclass: #NodeVisitor
  499. instanceVariableNames: ''
  500. package:'Compiler'!
  501. !NodeVisitor commentStamp!
  502. I am the abstract super class of all AST node visitors.!
  503. !NodeVisitor methodsFor: '*Compiler'!
  504. visit: aNode
  505. ^ aNode accept: self
  506. !
  507. visitAll: aCollection
  508. ^ aCollection do: [ :each | self visit: each ]
  509. !
  510. visitAssignmentNode: aNode
  511. ^ self visitNode: aNode
  512. !
  513. visitBlockNode: aNode
  514. ^ self visitNode: aNode
  515. !
  516. visitBlockSequenceNode: aNode
  517. ^ self visitSequenceNode: aNode
  518. !
  519. visitCascadeNode: aNode
  520. ^ self visitNode: aNode
  521. !
  522. visitClassReferenceNode: aNode
  523. ^ self visitVariableNode: aNode
  524. !
  525. visitDynamicArrayNode: aNode
  526. ^ self visitNode: aNode
  527. !
  528. visitDynamicDictionaryNode: aNode
  529. ^ self visitNode: aNode
  530. !
  531. visitJSStatementNode: aNode
  532. ^ self visitNode: aNode
  533. !
  534. visitMethodNode: aNode
  535. ^ self visitNode: aNode
  536. !
  537. visitNode: aNode
  538. ^ self visitAll: aNode nodes
  539. !
  540. visitReturnNode: aNode
  541. ^ self visitNode: aNode
  542. !
  543. visitSendNode: aNode
  544. ^ self visitNode: aNode
  545. !
  546. visitSequenceNode: aNode
  547. ^ self visitNode: aNode
  548. !
  549. visitValueNode: aNode
  550. ^ self visitNode: aNode
  551. !
  552. visitVariableNode: aNode
  553. ^ self visitNode: aNode
  554. ! !
  555. NodeVisitor subclass: #AbstractCodeGenerator
  556. instanceVariableNames: 'currentClass source'
  557. package:'Compiler'!
  558. !AbstractCodeGenerator commentStamp!
  559. I am the abstract super class of all code generators and provide their common API.!
  560. !AbstractCodeGenerator methodsFor: '*Compiler'!
  561. classNameFor: aClass
  562. ^aClass isMetaclass
  563. ifTrue: [aClass instanceClass name, '.klass']
  564. ifFalse: [
  565. aClass isNil
  566. ifTrue: ['nil']
  567. ifFalse: [aClass name]]
  568. !
  569. currentClass
  570. ^currentClass
  571. !
  572. currentClass: aClass
  573. currentClass := aClass
  574. !
  575. pseudoVariables
  576. ^#('self' 'super' 'true' 'false' 'nil' 'thisContext')
  577. !
  578. safeVariableNameFor: aString
  579. ^(Smalltalk current reservedWords includes: aString)
  580. ifTrue: [aString, '_']
  581. ifFalse: [aString]
  582. !
  583. source
  584. ^source ifNil: ['']
  585. !
  586. source: aString
  587. source := aString
  588. ! !
  589. !AbstractCodeGenerator methodsFor: '*Compiler'!
  590. compileNode: aNode
  591. self subclassResponsibility
  592. ! !
  593. AbstractCodeGenerator subclass: #CodeGenerator
  594. instanceVariableNames: ''
  595. package:'Compiler'!
  596. !CodeGenerator commentStamp!
  597. I am a basic code generator. I generate a valid JavaScript output, but no not perform any inlining.
  598. See `InliningCodeGenerator` for an optimized JavaScript code generation.!
  599. !CodeGenerator methodsFor: '*Compiler'!
  600. compileNode: aNode
  601. | ir stream |
  602. self semanticAnalyzer visit: aNode.
  603. ir := self translator visit: aNode.
  604. ^ self irTranslator
  605. visit: ir;
  606. contents
  607. !
  608. irTranslator
  609. ^ IRJSTranslator new
  610. !
  611. semanticAnalyzer
  612. ^ SemanticAnalyzer on: self currentClass
  613. !
  614. translator
  615. ^ IRASTTranslator new
  616. source: self source;
  617. theClass: self currentClass;
  618. yourself
  619. ! !
  620. Object subclass: #Node
  621. instanceVariableNames: 'position nodes shouldBeInlined shouldBeAliased'
  622. package:'Compiler'!
  623. !Node commentStamp!
  624. I am the abstract root class of the abstract syntax tree.
  625. position: holds a point containing lline- and column number of the symbol location in the original source file!
  626. !Node methodsFor: '*Compiler'!
  627. addNode: aNode
  628. self nodes add: aNode
  629. !
  630. nodes
  631. ^nodes ifNil: [nodes := Array new]
  632. !
  633. position
  634. ^position ifNil: [position := 0@0]
  635. !
  636. shouldBeAliased
  637. ^ shouldBeAliased ifNil: [ false ]
  638. !
  639. shouldBeAliased: aBoolean
  640. shouldBeAliased := aBoolean
  641. !
  642. shouldBeInlined
  643. ^ shouldBeInlined ifNil: [ false ]
  644. !
  645. shouldBeInlined: aBoolean
  646. shouldBeInlined := aBoolean
  647. ! !
  648. !Node methodsFor: '*Compiler'!
  649. nodes: aCollection
  650. nodes := aCollection
  651. !
  652. position: aPosition
  653. position := aPosition
  654. ! !
  655. !Node methodsFor: '*Compiler'!
  656. isAssignmentNode
  657. ^ false
  658. !
  659. isBlockNode
  660. ^false
  661. !
  662. isBlockSequenceNode
  663. ^false
  664. !
  665. isImmutable
  666. ^false
  667. !
  668. isReturnNode
  669. ^false
  670. !
  671. isSendNode
  672. ^false
  673. !
  674. isValueNode
  675. ^false
  676. !
  677. subtreeNeedsAliasing
  678. ^(self shouldBeAliased or: [ self shouldBeInlined ]) or: [
  679. (self nodes detect: [ :each | each subtreeNeedsAliasing ] ifNone: [ false ]) ~= false ]
  680. ! !
  681. !Node methodsFor: '*Compiler'!
  682. accept: aVisitor
  683. ^ aVisitor visitNode: self
  684. ! !
  685. Node subclass: #AssignmentNode
  686. instanceVariableNames: 'left right'
  687. package:'Compiler'!
  688. !AssignmentNode methodsFor: '*Compiler'!
  689. left
  690. ^left
  691. !
  692. left: aNode
  693. left := aNode
  694. !
  695. nodes
  696. ^ Array with: self left with: self right
  697. !
  698. right
  699. ^right
  700. !
  701. right: aNode
  702. right := aNode
  703. ! !
  704. !AssignmentNode methodsFor: '*Compiler'!
  705. isAssignmentNode
  706. ^ true
  707. ! !
  708. !AssignmentNode methodsFor: '*Compiler'!
  709. accept: aVisitor
  710. ^ aVisitor visitAssignmentNode: self
  711. ! !
  712. Node subclass: #BlockNode
  713. instanceVariableNames: 'parameters scope'
  714. package:'Compiler'!
  715. !BlockNode methodsFor: '*Compiler'!
  716. parameters
  717. ^parameters ifNil: [parameters := Array new]
  718. !
  719. parameters: aCollection
  720. parameters := aCollection
  721. !
  722. scope
  723. ^ scope
  724. !
  725. scope: aLexicalScope
  726. scope := aLexicalScope
  727. ! !
  728. !BlockNode methodsFor: '*Compiler'!
  729. isBlockNode
  730. ^true
  731. ! !
  732. !BlockNode methodsFor: '*Compiler'!
  733. accept: aVisitor
  734. ^ aVisitor visitBlockNode: self
  735. ! !
  736. Node subclass: #CascadeNode
  737. instanceVariableNames: 'receiver'
  738. package:'Compiler'!
  739. !CascadeNode methodsFor: '*Compiler'!
  740. receiver
  741. ^receiver
  742. !
  743. receiver: aNode
  744. receiver := aNode
  745. ! !
  746. !CascadeNode methodsFor: '*Compiler'!
  747. accept: aVisitor
  748. ^ aVisitor visitCascadeNode: self
  749. ! !
  750. Node subclass: #DynamicArrayNode
  751. instanceVariableNames: ''
  752. package:'Compiler'!
  753. !DynamicArrayNode methodsFor: '*Compiler'!
  754. accept: aVisitor
  755. ^ aVisitor visitDynamicArrayNode: self
  756. ! !
  757. Node subclass: #DynamicDictionaryNode
  758. instanceVariableNames: ''
  759. package:'Compiler'!
  760. !DynamicDictionaryNode methodsFor: '*Compiler'!
  761. accept: aVisitor
  762. ^ aVisitor visitDynamicDictionaryNode: self
  763. ! !
  764. Node subclass: #JSStatementNode
  765. instanceVariableNames: 'source'
  766. package:'Compiler'!
  767. !JSStatementNode methodsFor: '*Compiler'!
  768. source
  769. ^source ifNil: ['']
  770. !
  771. source: aString
  772. source := aString
  773. ! !
  774. !JSStatementNode methodsFor: '*Compiler'!
  775. accept: aVisitor
  776. ^ aVisitor visitJSStatementNode: self
  777. ! !
  778. Node subclass: #MethodNode
  779. instanceVariableNames: 'selector arguments source scope classReferences messageSends superSends'
  780. package:'Compiler'!
  781. !MethodNode methodsFor: '*Compiler'!
  782. arguments
  783. ^arguments ifNil: [#()]
  784. !
  785. arguments: aCollection
  786. arguments := aCollection
  787. !
  788. classReferences
  789. ^ classReferences
  790. !
  791. classReferences: aCollection
  792. classReferences := aCollection
  793. !
  794. messageSends
  795. ^ messageSends
  796. !
  797. messageSends: aCollection
  798. messageSends := aCollection
  799. !
  800. scope
  801. ^ scope
  802. !
  803. scope: aMethodScope
  804. scope := aMethodScope
  805. !
  806. selector
  807. ^selector
  808. !
  809. selector: aString
  810. selector := aString
  811. !
  812. source
  813. ^source
  814. !
  815. source: aString
  816. source := aString
  817. !
  818. superSends
  819. ^ superSends
  820. !
  821. superSends: aCollection
  822. superSends := aCollection
  823. ! !
  824. !MethodNode methodsFor: '*Compiler'!
  825. accept: aVisitor
  826. ^ aVisitor visitMethodNode: self
  827. ! !
  828. Node subclass: #ReturnNode
  829. instanceVariableNames: 'scope'
  830. package:'Compiler'!
  831. !ReturnNode methodsFor: '*Compiler'!
  832. scope
  833. ^ scope
  834. !
  835. scope: aLexicalScope
  836. scope := aLexicalScope
  837. ! !
  838. !ReturnNode methodsFor: '*Compiler'!
  839. isReturnNode
  840. ^ true
  841. !
  842. nonLocalReturn
  843. ^ self scope isMethodScope not
  844. ! !
  845. !ReturnNode methodsFor: '*Compiler'!
  846. accept: aVisitor
  847. ^ aVisitor visitReturnNode: self
  848. ! !
  849. Node subclass: #SendNode
  850. instanceVariableNames: 'selector arguments receiver superSend index'
  851. package:'Compiler'!
  852. !SendNode methodsFor: '*Compiler'!
  853. arguments
  854. ^arguments ifNil: [arguments := #()]
  855. !
  856. arguments: aCollection
  857. arguments := aCollection
  858. !
  859. cascadeNodeWithMessages: aCollection
  860. | first |
  861. first := SendNode new
  862. selector: self selector;
  863. arguments: self arguments;
  864. yourself.
  865. ^CascadeNode new
  866. receiver: self receiver;
  867. nodes: (Array with: first), aCollection;
  868. yourself
  869. !
  870. index
  871. ^ index
  872. !
  873. index: anInteger
  874. index := anInteger
  875. !
  876. nodes
  877. ^ (Array withAll: self arguments)
  878. add: self receiver;
  879. yourself
  880. !
  881. receiver
  882. ^receiver
  883. !
  884. receiver: aNode
  885. receiver := aNode
  886. !
  887. selector
  888. ^selector
  889. !
  890. selector: aString
  891. selector := aString
  892. !
  893. superSend
  894. ^ superSend ifNil: [ false ]
  895. !
  896. superSend: aBoolean
  897. superSend := aBoolean
  898. !
  899. valueForReceiver: anObject
  900. ^SendNode new
  901. receiver: (self receiver
  902. ifNil: [anObject]
  903. ifNotNil: [self receiver valueForReceiver: anObject]);
  904. selector: self selector;
  905. arguments: self arguments;
  906. yourself
  907. ! !
  908. !SendNode methodsFor: '*Compiler'!
  909. isSendNode
  910. ^ true
  911. ! !
  912. !SendNode methodsFor: '*Compiler'!
  913. accept: aVisitor
  914. ^ aVisitor visitSendNode: self
  915. ! !
  916. Node subclass: #SequenceNode
  917. instanceVariableNames: 'temps scope'
  918. package:'Compiler'!
  919. !SequenceNode methodsFor: '*Compiler'!
  920. scope
  921. ^ scope
  922. !
  923. scope: aLexicalScope
  924. scope := aLexicalScope
  925. !
  926. temps
  927. ^temps ifNil: [#()]
  928. !
  929. temps: aCollection
  930. temps := aCollection
  931. ! !
  932. !SequenceNode methodsFor: '*Compiler'!
  933. asBlockSequenceNode
  934. ^BlockSequenceNode new
  935. nodes: self nodes;
  936. temps: self temps;
  937. yourself
  938. ! !
  939. !SequenceNode methodsFor: '*Compiler'!
  940. accept: aVisitor
  941. ^ aVisitor visitSequenceNode: self
  942. ! !
  943. SequenceNode subclass: #BlockSequenceNode
  944. instanceVariableNames: ''
  945. package:'Compiler'!
  946. !BlockSequenceNode methodsFor: '*Compiler'!
  947. isBlockSequenceNode
  948. ^true
  949. ! !
  950. !BlockSequenceNode methodsFor: '*Compiler'!
  951. accept: aVisitor
  952. ^ aVisitor visitBlockSequenceNode: self
  953. ! !
  954. Node subclass: #ValueNode
  955. instanceVariableNames: 'value'
  956. package:'Compiler'!
  957. !ValueNode methodsFor: '*Compiler'!
  958. value
  959. ^value
  960. !
  961. value: anObject
  962. value := anObject
  963. ! !
  964. !ValueNode methodsFor: '*Compiler'!
  965. isImmutable
  966. ^true
  967. !
  968. isValueNode
  969. ^true
  970. ! !
  971. !ValueNode methodsFor: '*Compiler'!
  972. accept: aVisitor
  973. ^ aVisitor visitValueNode: self
  974. ! !
  975. ValueNode subclass: #VariableNode
  976. instanceVariableNames: 'assigned binding'
  977. package:'Compiler'!
  978. !VariableNode methodsFor: '*Compiler'!
  979. alias
  980. ^ self binding alias
  981. !
  982. assigned
  983. ^assigned ifNil: [false]
  984. !
  985. assigned: aBoolean
  986. assigned := aBoolean
  987. !
  988. beAssigned
  989. self binding validateAssignment.
  990. assigned := true
  991. !
  992. binding
  993. ^ binding
  994. !
  995. binding: aScopeVar
  996. binding := aScopeVar
  997. ! !
  998. !VariableNode methodsFor: '*Compiler'!
  999. isImmutable
  1000. ^false
  1001. ! !
  1002. !VariableNode methodsFor: '*Compiler'!
  1003. accept: aVisitor
  1004. ^ aVisitor visitVariableNode: self
  1005. ! !
  1006. VariableNode subclass: #ClassReferenceNode
  1007. instanceVariableNames: ''
  1008. package:'Compiler'!
  1009. !ClassReferenceNode methodsFor: '*Compiler'!
  1010. accept: aVisitor
  1011. ^ aVisitor visitClassReferenceNode: self
  1012. ! !
  1013. Object subclass: #LexicalScope
  1014. instanceVariableNames: 'node instruction temps args outerScope'
  1015. package:'Compiler'!
  1016. !LexicalScope commentStamp!
  1017. I represent a lexical scope where variable names are associated with ScopeVars
  1018. Instances are used for block scopes. Method scopes are instances of MethodLexicalScope.
  1019. I am attached to a ScopeVar and method/block nodes.
  1020. Each context (method/closure) get a fresh scope that inherits from its outer scope.!
  1021. !LexicalScope methodsFor: '*Compiler'!
  1022. alias
  1023. ^ '$ctx', self scopeLevel asString
  1024. !
  1025. allVariableNames
  1026. ^ self args keys, self temps keys
  1027. !
  1028. args
  1029. ^ args ifNil: [ args := Dictionary new ]
  1030. !
  1031. bindingFor: aStringOrNode
  1032. ^ self pseudoVars at: aStringOrNode value ifAbsent: [
  1033. self args at: aStringOrNode value ifAbsent: [
  1034. self temps at: aStringOrNode value ifAbsent: [ nil ]]]
  1035. !
  1036. instruction
  1037. ^ instruction
  1038. !
  1039. instruction: anIRInstruction
  1040. instruction := anIRInstruction
  1041. !
  1042. lookupVariable: aNode
  1043. | lookup |
  1044. lookup := (self bindingFor: aNode).
  1045. lookup ifNil: [
  1046. lookup := self outerScope ifNotNil: [
  1047. (self outerScope lookupVariable: aNode) ]].
  1048. ^ lookup
  1049. !
  1050. methodScope
  1051. ^ self outerScope ifNotNil: [
  1052. self outerScope methodScope ]
  1053. !
  1054. node
  1055. "Answer the node in which I am defined"
  1056. ^ node
  1057. !
  1058. node: aNode
  1059. node := aNode
  1060. !
  1061. outerScope
  1062. ^ outerScope
  1063. !
  1064. outerScope: aLexicalScope
  1065. outerScope := aLexicalScope
  1066. !
  1067. pseudoVars
  1068. ^ self methodScope pseudoVars
  1069. !
  1070. scopeLevel
  1071. self outerScope ifNil: [ ^ 1 ].
  1072. self isInlined ifTrue: [ ^ self outerScope scopeLevel ].
  1073. ^ self outerScope scopeLevel + 1
  1074. !
  1075. temps
  1076. ^ temps ifNil: [ temps := Dictionary new ]
  1077. ! !
  1078. !LexicalScope methodsFor: '*Compiler'!
  1079. addArg: aString
  1080. self args at: aString put: (ArgVar on: aString).
  1081. (self args at: aString) scope: self
  1082. !
  1083. addTemp: aString
  1084. self temps at: aString put: (TempVar on: aString).
  1085. (self temps at: aString) scope: self
  1086. ! !
  1087. !LexicalScope methodsFor: '*Compiler'!
  1088. canInlineNonLocalReturns
  1089. ^ self isInlined and: [ self outerScope canInlineNonLocalReturns ]
  1090. !
  1091. isBlockScope
  1092. ^ self isMethodScope not
  1093. !
  1094. isInlined
  1095. ^ self instruction notNil and: [
  1096. self instruction isInlined ]
  1097. !
  1098. isMethodScope
  1099. ^ false
  1100. ! !
  1101. LexicalScope subclass: #MethodLexicalScope
  1102. instanceVariableNames: 'iVars pseudoVars unknownVariables localReturn nonLocalReturns'
  1103. package:'Compiler'!
  1104. !MethodLexicalScope commentStamp!
  1105. I represent a method scope.!
  1106. !MethodLexicalScope methodsFor: '*Compiler'!
  1107. allVariableNames
  1108. ^ super allVariableNames, self iVars keys
  1109. !
  1110. bindingFor: aNode
  1111. ^ (super bindingFor: aNode) ifNil: [
  1112. self iVars at: aNode value ifAbsent: [ nil ]]
  1113. !
  1114. iVars
  1115. ^ iVars ifNil: [ iVars := Dictionary new ]
  1116. !
  1117. localReturn
  1118. ^ localReturn ifNil: [ false ]
  1119. !
  1120. localReturn: aBoolean
  1121. localReturn := aBoolean
  1122. !
  1123. methodScope
  1124. ^ self
  1125. !
  1126. nonLocalReturns
  1127. ^ nonLocalReturns ifNil: [ nonLocalReturns := OrderedCollection new ]
  1128. !
  1129. pseudoVars
  1130. pseudoVars ifNil: [
  1131. pseudoVars := Dictionary new.
  1132. Smalltalk current pseudoVariableNames do: [ :each |
  1133. pseudoVars at: each put: ((PseudoVar on: each)
  1134. scope: self methodScope;
  1135. yourself) ]].
  1136. ^ pseudoVars
  1137. !
  1138. unknownVariables
  1139. ^ unknownVariables ifNil: [ unknownVariables := OrderedCollection new ]
  1140. ! !
  1141. !MethodLexicalScope methodsFor: '*Compiler'!
  1142. addIVar: aString
  1143. self iVars at: aString put: (InstanceVar on: aString).
  1144. (self iVars at: aString) scope: self
  1145. !
  1146. addNonLocalReturn: aScope
  1147. self nonLocalReturns add: aScope
  1148. !
  1149. removeNonLocalReturn: aScope
  1150. self nonLocalReturns remove: aScope ifAbsent: []
  1151. ! !
  1152. !MethodLexicalScope methodsFor: '*Compiler'!
  1153. canInlineNonLocalReturns
  1154. ^ true
  1155. !
  1156. hasLocalReturn
  1157. ^ self localReturn
  1158. !
  1159. hasNonLocalReturn
  1160. ^ self nonLocalReturns notEmpty
  1161. !
  1162. isMethodScope
  1163. ^ true
  1164. ! !
  1165. Object subclass: #ScopeVar
  1166. instanceVariableNames: 'scope name'
  1167. package:'Compiler'!
  1168. !ScopeVar commentStamp!
  1169. I am an entry in a LexicalScope that gets associated with variable nodes of the same name.
  1170. There are 4 different subclasses of vars: temp vars, local vars, args, and unknown/global vars.!
  1171. !ScopeVar methodsFor: '*Compiler'!
  1172. alias
  1173. ^ self name asVariableName
  1174. !
  1175. name
  1176. ^ name
  1177. !
  1178. name: aString
  1179. name := aString
  1180. !
  1181. scope
  1182. ^ scope
  1183. !
  1184. scope: aScope
  1185. scope := aScope
  1186. ! !
  1187. !ScopeVar methodsFor: '*Compiler'!
  1188. isArgVar
  1189. ^ false
  1190. !
  1191. isClassRefVar
  1192. ^ false
  1193. !
  1194. isInstanceVar
  1195. ^ false
  1196. !
  1197. isPseudoVar
  1198. ^ false
  1199. !
  1200. isTempVar
  1201. ^ false
  1202. !
  1203. isUnknownVar
  1204. ^ false
  1205. !
  1206. validateAssignment
  1207. (self isArgVar or: [ self isPseudoVar ]) ifTrue: [
  1208. InvalidAssignmentError new
  1209. variableName: self name;
  1210. signal]
  1211. ! !
  1212. !ScopeVar class methodsFor: '*Compiler'!
  1213. on: aString
  1214. ^ self new
  1215. name: aString;
  1216. yourself
  1217. ! !
  1218. ScopeVar subclass: #AliasVar
  1219. instanceVariableNames: 'node'
  1220. package:'Compiler'!
  1221. !AliasVar commentStamp!
  1222. I am an internally defined variable by the compiler!
  1223. !AliasVar methodsFor: '*Compiler'!
  1224. node
  1225. ^ node
  1226. !
  1227. node: aNode
  1228. node := aNode
  1229. ! !
  1230. ScopeVar subclass: #ArgVar
  1231. instanceVariableNames: ''
  1232. package:'Compiler'!
  1233. !ArgVar commentStamp!
  1234. I am an argument of a method or block.!
  1235. !ArgVar methodsFor: '*Compiler'!
  1236. isArgVar
  1237. ^ true
  1238. ! !
  1239. ScopeVar subclass: #ClassRefVar
  1240. instanceVariableNames: ''
  1241. package:'Compiler'!
  1242. !ClassRefVar commentStamp!
  1243. I am an class reference variable!
  1244. !ClassRefVar methodsFor: '*Compiler'!
  1245. alias
  1246. ^ '(smalltalk.', self name, ' || ', self name, ')'
  1247. ! !
  1248. !ClassRefVar methodsFor: '*Compiler'!
  1249. isClassRefVar
  1250. ^ true
  1251. ! !
  1252. ScopeVar subclass: #InstanceVar
  1253. instanceVariableNames: ''
  1254. package:'Compiler'!
  1255. !InstanceVar commentStamp!
  1256. I am an instance variable of a method or block.!
  1257. !InstanceVar methodsFor: '*Compiler'!
  1258. alias
  1259. ^ 'self["@', self name, '"]'
  1260. !
  1261. isInstanceVar
  1262. ^ true
  1263. ! !
  1264. ScopeVar subclass: #PseudoVar
  1265. instanceVariableNames: ''
  1266. package:'Compiler'!
  1267. !PseudoVar commentStamp!
  1268. I am an pseudo variable.
  1269. The five Smalltalk pseudo variables are: 'self', 'super', 'nil', 'true' and 'false'!
  1270. !PseudoVar methodsFor: '*Compiler'!
  1271. alias
  1272. ^ self name
  1273. ! !
  1274. !PseudoVar methodsFor: '*Compiler'!
  1275. isPseudoVar
  1276. ^ true
  1277. ! !
  1278. ScopeVar subclass: #TempVar
  1279. instanceVariableNames: ''
  1280. package:'Compiler'!
  1281. !TempVar commentStamp!
  1282. I am an temporary variable of a method or block.!
  1283. !TempVar methodsFor: '*Compiler'!
  1284. alias
  1285. ^ self scope alias, '.locals.', super alias
  1286. ! !
  1287. !TempVar methodsFor: '*Compiler'!
  1288. isTempVar
  1289. ^ true
  1290. ! !
  1291. ScopeVar subclass: #UnknownVar
  1292. instanceVariableNames: ''
  1293. package:'Compiler'!
  1294. !UnknownVar commentStamp!
  1295. I am an unknown variable. Amber uses unknown variables as JavaScript globals!
  1296. !UnknownVar methodsFor: '*Compiler'!
  1297. isUnknownVar
  1298. ^ true
  1299. ! !
  1300. NodeVisitor subclass: #SemanticAnalyzer
  1301. instanceVariableNames: 'currentScope theClass classReferences messageSends superSends'
  1302. package:'Compiler'!
  1303. !SemanticAnalyzer commentStamp!
  1304. I semantically analyze the abstract syntax tree and annotate it with informations such as non local returns and variable scopes.!
  1305. !SemanticAnalyzer methodsFor: '*Compiler'!
  1306. classReferences
  1307. ^ classReferences ifNil: [ classReferences := Set new ]
  1308. !
  1309. messageSends
  1310. ^ messageSends ifNil: [ messageSends := Dictionary new ]
  1311. !
  1312. superSends
  1313. ^ superSends ifNil: [ superSends := Dictionary new ]
  1314. !
  1315. theClass
  1316. ^ theClass
  1317. !
  1318. theClass: aClass
  1319. theClass := aClass
  1320. ! !
  1321. !SemanticAnalyzer methodsFor: '*Compiler'!
  1322. errorShadowingVariable: aString
  1323. ShadowingVariableError new
  1324. variableName: aString;
  1325. signal
  1326. !
  1327. errorUnknownVariable: aNode
  1328. "Throw an error if the variable is undeclared in the global JS scope (i.e. window)"
  1329. | identifier |
  1330. identifier := aNode value.
  1331. ((#('jQuery' 'window' 'process' 'global') includes: identifier) not and: [ self isVariableGloballyUndefined: identifier ]) ifTrue: [
  1332. UnknownVariableError new
  1333. variableName: aNode value;
  1334. signal ]
  1335. ifFalse: [
  1336. currentScope methodScope unknownVariables add: aNode value. ]
  1337. ! !
  1338. !SemanticAnalyzer methodsFor: '*Compiler'!
  1339. newBlockScope
  1340. ^ self newScopeOfClass: LexicalScope
  1341. !
  1342. newMethodScope
  1343. ^ self newScopeOfClass: MethodLexicalScope
  1344. !
  1345. newScopeOfClass: aLexicalScopeClass
  1346. ^ aLexicalScopeClass new
  1347. outerScope: currentScope;
  1348. yourself
  1349. ! !
  1350. !SemanticAnalyzer methodsFor: '*Compiler'!
  1351. popScope
  1352. currentScope ifNotNil: [
  1353. currentScope := currentScope outerScope ]
  1354. !
  1355. pushScope: aScope
  1356. aScope outerScope: currentScope.
  1357. currentScope := aScope
  1358. !
  1359. validateVariableScope: aString
  1360. "Validate the variable scope in by doing a recursive lookup, up to the method scope"
  1361. (currentScope lookupVariable: aString) ifNotNil: [
  1362. self errorShadowingVariable: aString ]
  1363. ! !
  1364. !SemanticAnalyzer methodsFor: '*Compiler'!
  1365. isVariableGloballyUndefined: aString
  1366. <return eval('typeof ' + aString + ' == "undefined"')>
  1367. ! !
  1368. !SemanticAnalyzer methodsFor: '*Compiler'!
  1369. visitAssignmentNode: aNode
  1370. super visitAssignmentNode: aNode.
  1371. aNode left beAssigned
  1372. !
  1373. visitBlockNode: aNode
  1374. self pushScope: self newBlockScope.
  1375. aNode scope: currentScope.
  1376. currentScope node: aNode.
  1377. aNode parameters do: [ :each |
  1378. self validateVariableScope: each.
  1379. currentScope addArg: each ].
  1380. super visitBlockNode: aNode.
  1381. self popScope
  1382. !
  1383. visitCascadeNode: aNode
  1384. "Populate the receiver into all children"
  1385. aNode nodes do: [ :each |
  1386. each receiver: aNode receiver ].
  1387. super visitCascadeNode: aNode.
  1388. aNode nodes first superSend ifTrue: [
  1389. aNode nodes do: [ :each | each superSend: true ]]
  1390. !
  1391. visitClassReferenceNode: aNode
  1392. self classReferences add: aNode value.
  1393. aNode binding: (ClassRefVar new name: aNode value; yourself)
  1394. !
  1395. visitMethodNode: aNode
  1396. self pushScope: self newMethodScope.
  1397. aNode scope: currentScope.
  1398. currentScope node: aNode.
  1399. self theClass allInstanceVariableNames do: [:each |
  1400. currentScope addIVar: each ].
  1401. aNode arguments do: [ :each |
  1402. self validateVariableScope: each.
  1403. currentScope addArg: each ].
  1404. super visitMethodNode: aNode.
  1405. aNode
  1406. classReferences: self classReferences;
  1407. messageSends: self messageSends keys;
  1408. superSends: self superSends keys.
  1409. self popScope
  1410. !
  1411. visitReturnNode: aNode
  1412. aNode scope: currentScope.
  1413. currentScope isMethodScope
  1414. ifTrue: [ currentScope localReturn: true ]
  1415. ifFalse: [ currentScope methodScope addNonLocalReturn: currentScope ].
  1416. super visitReturnNode: aNode
  1417. !
  1418. visitSendNode: aNode
  1419. aNode receiver value = 'super'
  1420. ifTrue: [
  1421. aNode superSend: true.
  1422. aNode receiver value: 'self'.
  1423. self superSends at: aNode selector ifAbsentPut: [ Set new ].
  1424. (self superSends at: aNode selector) add: aNode ]
  1425. ifFalse: [ (IRSendInliner inlinedSelectors includes: aNode selector) ifTrue: [
  1426. aNode shouldBeInlined: true.
  1427. aNode receiver shouldBeAliased: true ] ].
  1428. self messageSends at: aNode selector ifAbsentPut: [ Set new ].
  1429. (self messageSends at: aNode selector) add: aNode.
  1430. aNode index: (self messageSends at: aNode selector) size.
  1431. super visitSendNode: aNode
  1432. !
  1433. visitSequenceNode: aNode
  1434. aNode temps do: [ :each |
  1435. self validateVariableScope: each.
  1436. currentScope addTemp: each ].
  1437. super visitSequenceNode: aNode
  1438. !
  1439. visitVariableNode: aNode
  1440. "Bind a ScopeVar to aNode by doing a lookup in the current scope.
  1441. If no ScopeVar is found, bind a UnknowVar and throw an error"
  1442. aNode binding: ((currentScope lookupVariable: aNode) ifNil: [
  1443. self errorUnknownVariable: aNode.
  1444. UnknownVar new name: aNode value; yourself ])
  1445. ! !
  1446. !SemanticAnalyzer class methodsFor: '*Compiler'!
  1447. on: aClass
  1448. ^ self new
  1449. theClass: aClass;
  1450. yourself
  1451. ! !
  1452. NodeVisitor subclass: #IRASTTranslator
  1453. instanceVariableNames: 'source theClass method sequence nextAlias'
  1454. package:'Compiler'!
  1455. !IRASTTranslator commentStamp!
  1456. I am the AST (abstract syntax tree) visitor responsible for building the intermediate representation graph.
  1457. I rely on a builder object, instance of IRBuilder.!
  1458. !IRASTTranslator methodsFor: '*Compiler'!
  1459. method
  1460. ^ method
  1461. !
  1462. method: anIRMethod
  1463. method := anIRMethod
  1464. !
  1465. nextAlias
  1466. nextAlias ifNil: [ nextAlias := 0 ].
  1467. nextAlias := nextAlias + 1.
  1468. ^ nextAlias asString
  1469. !
  1470. sequence
  1471. ^ sequence
  1472. !
  1473. sequence: anIRSequence
  1474. sequence := anIRSequence
  1475. !
  1476. source
  1477. ^ source
  1478. !
  1479. source: aString
  1480. source := aString
  1481. !
  1482. theClass
  1483. ^ theClass
  1484. !
  1485. theClass: aClass
  1486. theClass := aClass
  1487. !
  1488. withSequence: aSequence do: aBlock
  1489. | outerSequence |
  1490. outerSequence := self sequence.
  1491. self sequence: aSequence.
  1492. aBlock value.
  1493. self sequence: outerSequence.
  1494. ^ aSequence
  1495. ! !
  1496. !IRASTTranslator methodsFor: '*Compiler'!
  1497. alias: aNode
  1498. | variable |
  1499. aNode isImmutable ifTrue: [ ^ self visit: aNode ].
  1500. variable := IRVariable new
  1501. variable: (AliasVar new name: '$', self nextAlias);
  1502. yourself.
  1503. self sequence add: (IRAssignment new
  1504. add: variable;
  1505. add: (self visit: aNode);
  1506. yourself).
  1507. self method internalVariables add: variable.
  1508. ^ variable
  1509. !
  1510. aliasTemporally: aCollection
  1511. "https://github.com/NicolasPetton/amber/issues/296
  1512. If a node is aliased, all preceding ones are aliased as well.
  1513. The tree is iterated twice. First we get the aliasing dependency,
  1514. then the aliasing itself is done"
  1515. | threshold result |
  1516. threshold := 0.
  1517. aCollection withIndexDo: [ :each :i |
  1518. each subtreeNeedsAliasing
  1519. ifTrue: [ threshold := i ]].
  1520. result := OrderedCollection new.
  1521. aCollection withIndexDo: [ :each :i |
  1522. result add: (i <= threshold
  1523. ifTrue: [ self alias: each ]
  1524. ifFalse: [ self visit: each ])].
  1525. ^result
  1526. !
  1527. visitAssignmentNode: aNode
  1528. | left right assignment |
  1529. right := self visit: aNode right.
  1530. left := self visit: aNode left.
  1531. self sequence add: (IRAssignment new
  1532. add: left;
  1533. add: right;
  1534. yourself).
  1535. ^ left
  1536. !
  1537. visitBlockNode: aNode
  1538. | closure |
  1539. closure := IRClosure new
  1540. arguments: aNode parameters;
  1541. scope: aNode scope;
  1542. yourself.
  1543. aNode scope temps do: [ :each |
  1544. closure add: (IRTempDeclaration new
  1545. name: each name;
  1546. scope: aNode scope;
  1547. yourself) ].
  1548. aNode nodes do: [ :each | closure add: (self visit: each) ].
  1549. ^ closure
  1550. !
  1551. visitBlockSequenceNode: aNode
  1552. ^ self
  1553. withSequence: IRBlockSequence new
  1554. do: [
  1555. aNode nodes ifNotEmpty: [
  1556. aNode nodes allButLast do: [ :each |
  1557. self sequence add: (self visit: each) ].
  1558. aNode nodes last isReturnNode
  1559. ifFalse: [ self sequence add: (IRBlockReturn new add: (self visit: aNode nodes last); yourself) ]
  1560. ifTrue: [ self sequence add: (self visit: aNode nodes last) ]]]
  1561. !
  1562. visitCascadeNode: aNode
  1563. | alias |
  1564. aNode receiver isImmutable ifFalse: [
  1565. alias := self alias: aNode receiver.
  1566. aNode nodes do: [ :each |
  1567. each receiver: (VariableNode new binding: alias variable) ]].
  1568. aNode nodes allButLast do: [ :each |
  1569. self sequence add: (self visit: each) ].
  1570. ^ self alias: aNode nodes last
  1571. !
  1572. visitDynamicArrayNode: aNode
  1573. | array |
  1574. array := IRDynamicArray new.
  1575. (self aliasTemporally: aNode nodes) do: [:each | array add: each].
  1576. ^ array
  1577. !
  1578. visitDynamicDictionaryNode: aNode
  1579. | dictionary |
  1580. dictionary := IRDynamicDictionary new.
  1581. (self aliasTemporally: aNode nodes) do: [:each | dictionary add: each].
  1582. ^ dictionary
  1583. !
  1584. visitJSStatementNode: aNode
  1585. ^ IRVerbatim new
  1586. source: aNode source;
  1587. yourself
  1588. !
  1589. visitMethodNode: aNode
  1590. self method: (IRMethod new
  1591. source: self source;
  1592. theClass: self theClass;
  1593. arguments: aNode arguments;
  1594. selector: aNode selector;
  1595. messageSends: aNode messageSends;
  1596. superSends: aNode superSends;
  1597. classReferences: aNode classReferences;
  1598. scope: aNode scope;
  1599. yourself).
  1600. aNode scope temps do: [ :each |
  1601. self method add: (IRTempDeclaration new
  1602. name: each name;
  1603. scope: aNode scope;
  1604. yourself) ].
  1605. aNode nodes do: [ :each | self method add: (self visit: each) ].
  1606. aNode scope hasLocalReturn ifFalse: [
  1607. (self method add: IRReturn new) add: (IRVariable new
  1608. variable: (aNode scope pseudoVars at: 'self');
  1609. yourself) ].
  1610. ^ self method
  1611. !
  1612. visitReturnNode: aNode
  1613. | return |
  1614. return := aNode nonLocalReturn
  1615. ifTrue: [ IRNonLocalReturn new ]
  1616. ifFalse: [ IRReturn new ].
  1617. return scope: aNode scope.
  1618. aNode nodes do: [ :each |
  1619. return add: (self alias: each) ].
  1620. ^ return
  1621. !
  1622. visitSendNode: aNode
  1623. | send all receiver arguments |
  1624. send := IRSend new.
  1625. send
  1626. selector: aNode selector;
  1627. index: aNode index.
  1628. aNode superSend ifTrue: [ send classSend: self theClass superclass ].
  1629. all := self aliasTemporally: { aNode receiver }, aNode arguments.
  1630. receiver := all first.
  1631. arguments := all allButFirst.
  1632. send add: receiver.
  1633. arguments do: [ :each | send add: each ].
  1634. ^ send
  1635. !
  1636. visitSequenceNode: aNode
  1637. ^ self
  1638. withSequence: IRSequence new
  1639. do: [
  1640. aNode nodes do: [ :each | | instruction |
  1641. instruction := self visit: each.
  1642. instruction isVariable ifFalse: [
  1643. self sequence add: instruction ]]]
  1644. !
  1645. visitValueNode: aNode
  1646. ^ IRValue new
  1647. value: aNode value;
  1648. yourself
  1649. !
  1650. visitVariableNode: aNode
  1651. ^ IRVariable new
  1652. variable: aNode binding;
  1653. yourself
  1654. ! !
  1655. Object subclass: #IRInstruction
  1656. instanceVariableNames: 'parent instructions'
  1657. package:'Compiler'!
  1658. !IRInstruction commentStamp!
  1659. I am the abstract root class of the IR (intermediate representation) instructions class hierarchy.
  1660. The IR graph is used to emit JavaScript code using a JSStream.!
  1661. !IRInstruction methodsFor: '*Compiler'!
  1662. instructions
  1663. ^ instructions ifNil: [ instructions := OrderedCollection new ]
  1664. !
  1665. parent
  1666. ^ parent
  1667. !
  1668. parent: anIRInstruction
  1669. parent := anIRInstruction
  1670. ! !
  1671. !IRInstruction methodsFor: '*Compiler'!
  1672. add: anObject
  1673. anObject parent: self.
  1674. ^ self instructions add: anObject
  1675. !
  1676. remove
  1677. self parent remove: self
  1678. !
  1679. remove: anIRInstruction
  1680. self instructions remove: anIRInstruction
  1681. !
  1682. replace: anIRInstruction with: anotherIRInstruction
  1683. anotherIRInstruction parent: self.
  1684. self instructions
  1685. at: (self instructions indexOf: anIRInstruction)
  1686. put: anotherIRInstruction
  1687. !
  1688. replaceWith: anIRInstruction
  1689. self parent replace: self with: anIRInstruction
  1690. ! !
  1691. !IRInstruction methodsFor: '*Compiler'!
  1692. canBeAssigned
  1693. ^ true
  1694. !
  1695. isClosure
  1696. ^ false
  1697. !
  1698. isInlined
  1699. ^ false
  1700. !
  1701. isLocalReturn
  1702. ^ false
  1703. !
  1704. isReturn
  1705. ^ false
  1706. !
  1707. isSend
  1708. ^ false
  1709. !
  1710. isSequence
  1711. ^ false
  1712. !
  1713. isTempDeclaration
  1714. ^ false
  1715. !
  1716. isVariable
  1717. ^ false
  1718. ! !
  1719. !IRInstruction methodsFor: '*Compiler'!
  1720. accept: aVisitor
  1721. ^ aVisitor visitIRInstruction: self
  1722. ! !
  1723. !IRInstruction class methodsFor: '*Compiler'!
  1724. on: aBuilder
  1725. ^ self new
  1726. builder: aBuilder;
  1727. yourself
  1728. ! !
  1729. IRInstruction subclass: #IRAssignment
  1730. instanceVariableNames: ''
  1731. package:'Compiler'!
  1732. !IRAssignment methodsFor: '*Compiler'!
  1733. accept: aVisitor
  1734. ^ aVisitor visitIRAssignment: self
  1735. ! !
  1736. IRInstruction subclass: #IRDynamicArray
  1737. instanceVariableNames: ''
  1738. package:'Compiler'!
  1739. !IRDynamicArray methodsFor: '*Compiler'!
  1740. accept: aVisitor
  1741. ^ aVisitor visitIRDynamicArray: self
  1742. ! !
  1743. IRInstruction subclass: #IRDynamicDictionary
  1744. instanceVariableNames: ''
  1745. package:'Compiler'!
  1746. !IRDynamicDictionary methodsFor: '*Compiler'!
  1747. accept: aVisitor
  1748. ^ aVisitor visitIRDynamicDictionary: self
  1749. ! !
  1750. IRInstruction subclass: #IRScopedInstruction
  1751. instanceVariableNames: 'scope'
  1752. package:'Compiler'!
  1753. !IRScopedInstruction methodsFor: '*Compiler'!
  1754. scope
  1755. ^ scope
  1756. !
  1757. scope: aScope
  1758. scope := aScope
  1759. ! !
  1760. IRScopedInstruction subclass: #IRClosure
  1761. instanceVariableNames: 'arguments'
  1762. package:'Compiler'!
  1763. !IRClosure methodsFor: '*Compiler'!
  1764. arguments
  1765. ^ arguments ifNil: [ #() ]
  1766. !
  1767. arguments: aCollection
  1768. arguments := aCollection
  1769. !
  1770. scope: aScope
  1771. super scope: aScope.
  1772. aScope instruction: self
  1773. !
  1774. sequence
  1775. ^ self instructions last
  1776. ! !
  1777. !IRClosure methodsFor: '*Compiler'!
  1778. isClosure
  1779. ^ true
  1780. ! !
  1781. !IRClosure methodsFor: '*Compiler'!
  1782. accept: aVisitor
  1783. ^ aVisitor visitIRClosure: self
  1784. ! !
  1785. IRScopedInstruction subclass: #IRMethod
  1786. instanceVariableNames: 'theClass source selector classReferences messageSends superSends arguments internalVariables'
  1787. package:'Compiler'!
  1788. !IRMethod commentStamp!
  1789. I am a method instruction!
  1790. !IRMethod methodsFor: '*Compiler'!
  1791. arguments
  1792. ^ arguments
  1793. !
  1794. arguments: aCollection
  1795. arguments := aCollection
  1796. !
  1797. classReferences
  1798. ^ classReferences
  1799. !
  1800. classReferences: aCollection
  1801. classReferences := aCollection
  1802. !
  1803. internalVariables
  1804. ^ internalVariables ifNil: [ internalVariables := Set new ]
  1805. !
  1806. messageSends
  1807. ^ messageSends
  1808. !
  1809. messageSends: aCollection
  1810. messageSends := aCollection
  1811. !
  1812. scope: aScope
  1813. super scope: aScope.
  1814. aScope instruction: self
  1815. !
  1816. selector
  1817. ^ selector
  1818. !
  1819. selector: aString
  1820. selector := aString
  1821. !
  1822. source
  1823. ^ source
  1824. !
  1825. source: aString
  1826. source := aString
  1827. !
  1828. superSends
  1829. ^ superSends
  1830. !
  1831. superSends: aCollection
  1832. superSends := aCollection
  1833. !
  1834. theClass
  1835. ^ theClass
  1836. !
  1837. theClass: aClass
  1838. theClass := aClass
  1839. ! !
  1840. !IRMethod methodsFor: '*Compiler'!
  1841. accept: aVisitor
  1842. ^ aVisitor visitIRMethod: self
  1843. ! !
  1844. IRScopedInstruction subclass: #IRReturn
  1845. instanceVariableNames: ''
  1846. package:'Compiler'!
  1847. !IRReturn commentStamp!
  1848. I am a local return instruction.!
  1849. !IRReturn methodsFor: '*Compiler'!
  1850. canBeAssigned
  1851. ^ false
  1852. !
  1853. isBlockReturn
  1854. ^ false
  1855. !
  1856. isLocalReturn
  1857. ^ true
  1858. !
  1859. isNonLocalReturn
  1860. ^ self isLocalReturn not
  1861. !
  1862. isReturn
  1863. ^ true
  1864. ! !
  1865. !IRReturn methodsFor: '*Compiler'!
  1866. accept: aVisitor
  1867. ^ aVisitor visitIRReturn: self
  1868. ! !
  1869. IRReturn subclass: #IRBlockReturn
  1870. instanceVariableNames: ''
  1871. package:'Compiler'!
  1872. !IRBlockReturn commentStamp!
  1873. Smalltalk blocks return their last statement. I am a implicit block return instruction.!
  1874. !IRBlockReturn methodsFor: '*Compiler'!
  1875. isBlockReturn
  1876. ^ true
  1877. ! !
  1878. !IRBlockReturn methodsFor: '*Compiler'!
  1879. accept: aVisitor
  1880. ^ aVisitor visitIRBlockReturn: self
  1881. ! !
  1882. IRReturn subclass: #IRNonLocalReturn
  1883. instanceVariableNames: ''
  1884. package:'Compiler'!
  1885. !IRNonLocalReturn commentStamp!
  1886. I am a non local return instruction.
  1887. Non local returns are handled using a try/catch JS statement.
  1888. See IRNonLocalReturnHandling class!
  1889. !IRNonLocalReturn methodsFor: '*Compiler'!
  1890. isLocalReturn
  1891. ^ false
  1892. ! !
  1893. !IRNonLocalReturn methodsFor: '*Compiler'!
  1894. accept: aVisitor
  1895. ^ aVisitor visitIRNonLocalReturn: self
  1896. ! !
  1897. IRScopedInstruction subclass: #IRTempDeclaration
  1898. instanceVariableNames: 'name'
  1899. package:'Compiler'!
  1900. !IRTempDeclaration methodsFor: '*Compiler'!
  1901. name
  1902. ^ name
  1903. !
  1904. name: aString
  1905. name := aString
  1906. ! !
  1907. !IRTempDeclaration methodsFor: '*Compiler'!
  1908. accept: aVisitor
  1909. ^ aVisitor visitIRTempDeclaration: self
  1910. ! !
  1911. IRInstruction subclass: #IRSend
  1912. instanceVariableNames: 'selector classSend index'
  1913. package:'Compiler'!
  1914. !IRSend commentStamp!
  1915. I am a message send instruction.!
  1916. !IRSend methodsFor: '*Compiler'!
  1917. classSend
  1918. ^ classSend
  1919. !
  1920. classSend: aClass
  1921. classSend := aClass
  1922. !
  1923. index
  1924. ^ index
  1925. !
  1926. index: anInteger
  1927. index := anInteger
  1928. !
  1929. javascriptSelector
  1930. ^ self classSend
  1931. ifNil: [ self selector asSelector ]
  1932. ifNotNil: [ self selector asSuperSelector ]
  1933. !
  1934. selector
  1935. ^ selector
  1936. !
  1937. selector: aString
  1938. selector := aString
  1939. ! !
  1940. !IRSend methodsFor: '*Compiler'!
  1941. isSend
  1942. ^ true
  1943. ! !
  1944. !IRSend methodsFor: '*Compiler'!
  1945. accept: aVisitor
  1946. ^ aVisitor visitIRSend: self
  1947. ! !
  1948. IRInstruction subclass: #IRSequence
  1949. instanceVariableNames: ''
  1950. package:'Compiler'!
  1951. !IRSequence methodsFor: '*Compiler'!
  1952. isSequence
  1953. ^ true
  1954. ! !
  1955. !IRSequence methodsFor: '*Compiler'!
  1956. accept: aVisitor
  1957. ^ aVisitor visitIRSequence: self
  1958. ! !
  1959. IRSequence subclass: #IRBlockSequence
  1960. instanceVariableNames: ''
  1961. package:'Compiler'!
  1962. !IRBlockSequence methodsFor: '*Compiler'!
  1963. accept: aVisitor
  1964. ^ aVisitor visitIRBlockSequence: self
  1965. ! !
  1966. IRInstruction subclass: #IRValue
  1967. instanceVariableNames: 'value'
  1968. package:'Compiler'!
  1969. !IRValue commentStamp!
  1970. I am the simplest possible instruction. I represent a value.!
  1971. !IRValue methodsFor: '*Compiler'!
  1972. value
  1973. ^value
  1974. !
  1975. value: aString
  1976. value := aString
  1977. ! !
  1978. !IRValue methodsFor: '*Compiler'!
  1979. accept: aVisitor
  1980. ^ aVisitor visitIRValue: self
  1981. ! !
  1982. IRInstruction subclass: #IRVariable
  1983. instanceVariableNames: 'variable'
  1984. package:'Compiler'!
  1985. !IRVariable commentStamp!
  1986. I am a variable instruction.!
  1987. !IRVariable methodsFor: '*Compiler'!
  1988. variable
  1989. ^ variable
  1990. !
  1991. variable: aScopeVariable
  1992. variable := aScopeVariable
  1993. ! !
  1994. !IRVariable methodsFor: '*Compiler'!
  1995. isVariable
  1996. ^ true
  1997. ! !
  1998. !IRVariable methodsFor: '*Compiler'!
  1999. accept: aVisitor
  2000. ^ aVisitor visitIRVariable: self
  2001. ! !
  2002. IRInstruction subclass: #IRVerbatim
  2003. instanceVariableNames: 'source'
  2004. package:'Compiler'!
  2005. !IRVerbatim methodsFor: '*Compiler'!
  2006. source
  2007. ^ source
  2008. !
  2009. source: aString
  2010. source := aString
  2011. ! !
  2012. !IRVerbatim methodsFor: '*Compiler'!
  2013. accept: aVisitor
  2014. ^ aVisitor visitIRVerbatim: self
  2015. ! !
  2016. Object subclass: #IRVisitor
  2017. instanceVariableNames: ''
  2018. package:'Compiler'!
  2019. !IRVisitor methodsFor: '*Compiler'!
  2020. visit: anIRInstruction
  2021. ^ anIRInstruction accept: self
  2022. !
  2023. visitIRAssignment: anIRAssignment
  2024. ^ self visitIRInstruction: anIRAssignment
  2025. !
  2026. visitIRBlockReturn: anIRBlockReturn
  2027. ^ self visitIRReturn: anIRBlockReturn
  2028. !
  2029. visitIRBlockSequence: anIRBlockSequence
  2030. ^ self visitIRSequence: anIRBlockSequence
  2031. !
  2032. visitIRClosure: anIRClosure
  2033. ^ self visitIRInstruction: anIRClosure
  2034. !
  2035. visitIRDynamicArray: anIRDynamicArray
  2036. ^ self visitIRInstruction: anIRDynamicArray
  2037. !
  2038. visitIRDynamicDictionary: anIRDynamicDictionary
  2039. ^ self visitIRInstruction: anIRDynamicDictionary
  2040. !
  2041. visitIRInlinedClosure: anIRInlinedClosure
  2042. ^ self visitIRClosure: anIRInlinedClosure
  2043. !
  2044. visitIRInlinedSequence: anIRInlinedSequence
  2045. ^ self visitIRSequence: anIRInlinedSequence
  2046. !
  2047. visitIRInstruction: anIRInstruction
  2048. anIRInstruction instructions do: [ :each | self visit: each ].
  2049. ^ anIRInstruction
  2050. !
  2051. visitIRMethod: anIRMethod
  2052. ^ self visitIRInstruction: anIRMethod
  2053. !
  2054. visitIRNonLocalReturn: anIRNonLocalReturn
  2055. ^ self visitIRInstruction: anIRNonLocalReturn
  2056. !
  2057. visitIRNonLocalReturnHandling: anIRNonLocalReturnHandling
  2058. ^ self visitIRInstruction: anIRNonLocalReturnHandling
  2059. !
  2060. visitIRReturn: anIRReturn
  2061. ^ self visitIRInstruction: anIRReturn
  2062. !
  2063. visitIRSend: anIRSend
  2064. ^ self visitIRInstruction: anIRSend
  2065. !
  2066. visitIRSequence: anIRSequence
  2067. ^ self visitIRInstruction: anIRSequence
  2068. !
  2069. visitIRTempDeclaration: anIRTempDeclaration
  2070. ^ self visitIRInstruction: anIRTempDeclaration
  2071. !
  2072. visitIRValue: anIRValue
  2073. ^ self visitIRInstruction: anIRValue
  2074. !
  2075. visitIRVariable: anIRVariable
  2076. ^ self visitIRInstruction: anIRVariable
  2077. !
  2078. visitIRVerbatim: anIRVerbatim
  2079. ^ self visitIRInstruction: anIRVerbatim
  2080. ! !
  2081. IRVisitor subclass: #IRJSTranslator
  2082. instanceVariableNames: 'stream'
  2083. package:'Compiler'!
  2084. !IRJSTranslator methodsFor: '*Compiler'!
  2085. contents
  2086. ^ self stream contents
  2087. !
  2088. stream
  2089. ^ stream
  2090. !
  2091. stream: aStream
  2092. stream := aStream
  2093. ! !
  2094. !IRJSTranslator methodsFor: '*Compiler'!
  2095. initialize
  2096. super initialize.
  2097. stream := JSStream new.
  2098. ! !
  2099. !IRJSTranslator methodsFor: '*Compiler'!
  2100. visitIRAssignment: anIRAssignment
  2101. self visit: anIRAssignment instructions first.
  2102. self stream nextPutAssignment.
  2103. self visit: anIRAssignment instructions last.
  2104. !
  2105. visitIRClosure: anIRClosure
  2106. self stream
  2107. nextPutClosureWith: [
  2108. self stream
  2109. nextPutBlockContextFor: anIRClosure
  2110. during: [ super visitIRClosure: anIRClosure ] ]
  2111. arguments: anIRClosure arguments
  2112. !
  2113. visitIRDynamicArray: anIRDynamicArray
  2114. self stream nextPutAll: '['.
  2115. anIRDynamicArray instructions
  2116. do: [ :each | self visit: each ]
  2117. separatedBy: [ self stream nextPutAll: ',' ].
  2118. stream nextPutAll: ']'
  2119. !
  2120. visitIRDynamicDictionary: anIRDynamicDictionary
  2121. self stream nextPutAll: 'smalltalk.HashedCollection._fromPairs_(['.
  2122. anIRDynamicDictionary instructions
  2123. do: [ :each | self visit: each ]
  2124. separatedBy: [self stream nextPutAll: ',' ].
  2125. self stream nextPutAll: '])'
  2126. !
  2127. visitIRMethod: anIRMethod
  2128. self stream
  2129. nextPutMethodDeclaration: anIRMethod
  2130. with: [ self stream
  2131. nextPutFunctionWith: [
  2132. self stream nextPutContextFor: anIRMethod during: [
  2133. anIRMethod internalVariables notEmpty ifTrue: [
  2134. self stream nextPutVars: (anIRMethod internalVariables asArray collect: [ :each |
  2135. each variable alias ]) ].
  2136. anIRMethod scope hasNonLocalReturn
  2137. ifTrue: [
  2138. self stream nextPutNonLocalReturnHandlingWith: [
  2139. super visitIRMethod: anIRMethod ]]
  2140. ifFalse: [ super visitIRMethod: anIRMethod ]]]
  2141. arguments: anIRMethod arguments ]
  2142. !
  2143. visitIRNonLocalReturn: anIRNonLocalReturn
  2144. self stream nextPutNonLocalReturnWith: [
  2145. super visitIRNonLocalReturn: anIRNonLocalReturn ]
  2146. !
  2147. visitIRReturn: anIRReturn
  2148. self stream nextPutReturnWith: [
  2149. super visitIRReturn: anIRReturn ]
  2150. !
  2151. visitIRSend: anIRSend
  2152. anIRSend classSend
  2153. ifNil: [
  2154. self stream nextPutAll: '_st('.
  2155. self visit: anIRSend instructions first.
  2156. self stream nextPutAll: ').', anIRSend selector asSelector, '('.
  2157. anIRSend instructions allButFirst
  2158. do: [ :each | self visit: each ]
  2159. separatedBy: [ self stream nextPutAll: ',' ].
  2160. self stream nextPutAll: ')' ]
  2161. ifNotNil: [
  2162. self stream
  2163. nextPutAll: anIRSend classSend asJavascript, '.fn.prototype.';
  2164. nextPutAll: anIRSend selector asSelector, '.apply(';
  2165. nextPutAll: '_st('.
  2166. self visit: anIRSend instructions first.
  2167. self stream nextPutAll: '), ['.
  2168. anIRSend instructions allButFirst
  2169. do: [ :each | self visit: each ]
  2170. separatedBy: [ self stream nextPutAll: ',' ].
  2171. self stream nextPutAll: '])' ]
  2172. !
  2173. visitIRSequence: anIRSequence
  2174. self stream nextPutSequenceWith: [
  2175. anIRSequence instructions do: [ :each |
  2176. self stream nextPutStatementWith: (self visit: each) ]]
  2177. !
  2178. visitIRTempDeclaration: anIRTempDeclaration
  2179. self stream
  2180. nextPutAll: anIRTempDeclaration scope alias, '.locals.', anIRTempDeclaration name, '=nil;';
  2181. lf
  2182. !
  2183. visitIRValue: anIRValue
  2184. self stream nextPutAll: anIRValue value asJavascript
  2185. !
  2186. visitIRVariable: anIRVariable
  2187. anIRVariable variable name = 'thisContext'
  2188. ifTrue: [ self stream nextPutAll: 'smalltalk.getThisContext()' ]
  2189. ifFalse: [ self stream nextPutAll: anIRVariable variable alias ]
  2190. !
  2191. visitIRVerbatim: anIRVerbatim
  2192. self stream nextPutStatementWith: [
  2193. self stream nextPutAll: anIRVerbatim source ]
  2194. ! !
  2195. Object subclass: #JSStream
  2196. instanceVariableNames: 'stream'
  2197. package:'Compiler'!
  2198. !JSStream methodsFor: '*Compiler'!
  2199. contents
  2200. ^ stream contents
  2201. ! !
  2202. !JSStream methodsFor: '*Compiler'!
  2203. initialize
  2204. super initialize.
  2205. stream := '' writeStream.
  2206. ! !
  2207. !JSStream methodsFor: '*Compiler'!
  2208. lf
  2209. stream lf
  2210. !
  2211. nextPut: aString
  2212. stream nextPut: aString
  2213. !
  2214. nextPutAll: aString
  2215. stream nextPutAll: aString
  2216. !
  2217. nextPutAssignment
  2218. stream nextPutAll: '='
  2219. !
  2220. nextPutBlockContextFor: anIRClosure during: aBlock
  2221. self
  2222. nextPutAll: 'return smalltalk.withContext(function(', anIRClosure scope alias, ') { ';
  2223. nextPutAll: String cr.
  2224. aBlock value.
  2225. self nextPutAll: '})'
  2226. !
  2227. nextPutClosureWith: aBlock arguments: anArray
  2228. stream nextPutAll: '(function('.
  2229. anArray
  2230. do: [ :each | stream nextPutAll: each asVariableName ]
  2231. separatedBy: [ stream nextPut: ',' ].
  2232. stream nextPutAll: '){'; lf.
  2233. aBlock value.
  2234. stream nextPutAll: '})'
  2235. !
  2236. nextPutContextFor: aMethod during: aBlock
  2237. self
  2238. nextPutAll: 'return smalltalk.withContext(function(', aMethod scope alias, ') { ';
  2239. nextPutAll: String cr.
  2240. aBlock value.
  2241. self
  2242. nextPutAll: '}, self, ';
  2243. nextPutAll: aMethod selector asJavascript, ', ['.
  2244. aMethod arguments
  2245. do: [ :each | self nextPutAll: each asVariableName ]
  2246. separatedBy: [ self nextPutAll: ',' ].
  2247. self nextPutAll: '], ';
  2248. nextPutAll: aMethod theClass asJavascript;
  2249. nextPutAll: ')'
  2250. !
  2251. nextPutFunctionWith: aBlock arguments: anArray
  2252. stream nextPutAll: 'fn: function('.
  2253. anArray
  2254. do: [ :each | stream nextPutAll: each asVariableName ]
  2255. separatedBy: [ stream nextPut: ',' ].
  2256. stream nextPutAll: '){'; lf.
  2257. stream nextPutAll: 'var self=this;'; lf.
  2258. aBlock value.
  2259. stream nextPutAll: '}'
  2260. !
  2261. nextPutIf: aBlock with: anotherBlock
  2262. stream nextPutAll: 'if('.
  2263. aBlock value.
  2264. stream nextPutAll: '){'; lf.
  2265. anotherBlock value.
  2266. stream nextPutAll: '}'
  2267. !
  2268. nextPutIfElse: aBlock with: ifBlock with: elseBlock
  2269. stream nextPutAll: 'if('.
  2270. aBlock value.
  2271. stream nextPutAll: '){'; lf.
  2272. ifBlock value.
  2273. stream nextPutAll: '} else {'; lf.
  2274. elseBlock value.
  2275. stream nextPutAll: '}'
  2276. !
  2277. nextPutMethodDeclaration: aMethod with: aBlock
  2278. stream
  2279. nextPutAll: 'smalltalk.method({'; lf;
  2280. nextPutAll: 'selector: "', aMethod selector, '",'; lf;
  2281. nextPutAll: 'source: ', aMethod source asJavascript, ',';lf.
  2282. aBlock value.
  2283. stream
  2284. nextPutAll: ',', String lf, 'messageSends: ';
  2285. nextPutAll: aMethod messageSends asArray asJavascript, ','; lf;
  2286. nextPutAll: 'args: ', (aMethod arguments collect: [ :each | each value ]) asArray asJavascript, ','; lf;
  2287. nextPutAll: 'referencedClasses: ['.
  2288. aMethod classReferences
  2289. do: [:each | stream nextPutAll: each asJavascript]
  2290. separatedBy: [stream nextPutAll: ','].
  2291. stream
  2292. nextPutAll: ']';
  2293. nextPutAll: '})'
  2294. !
  2295. nextPutNonLocalReturnHandlingWith: aBlock
  2296. stream
  2297. nextPutAll: 'var $early={};'; lf;
  2298. nextPutAll: 'try {'; lf.
  2299. aBlock value.
  2300. stream
  2301. nextPutAll: '}'; lf;
  2302. nextPutAll: 'catch(e) {if(e===$early)return e[0]; throw e}'; lf
  2303. !
  2304. nextPutNonLocalReturnWith: aBlock
  2305. stream nextPutAll: 'throw $early=['.
  2306. aBlock value.
  2307. stream nextPutAll: ']'
  2308. !
  2309. nextPutReturn
  2310. stream nextPutAll: 'return '
  2311. !
  2312. nextPutReturnWith: aBlock
  2313. self nextPutReturn.
  2314. aBlock value
  2315. !
  2316. nextPutSequenceWith: aBlock
  2317. "stream
  2318. nextPutAll: 'switch(smalltalk.thisContext.pc){'; lf."
  2319. aBlock value.
  2320. "stream
  2321. nextPutAll: '};'; lf"
  2322. !
  2323. nextPutStatement: anInteger with: aBlock
  2324. stream nextPutAll: 'case ', anInteger asString, ':'; lf.
  2325. self nextPutStatementWith: aBlock.
  2326. stream nextPutAll: 'smalltalk.thisContext.pc=', (anInteger + 1) asString, ';'; lf
  2327. !
  2328. nextPutStatementWith: aBlock
  2329. aBlock value.
  2330. stream nextPutAll: ';'; lf
  2331. !
  2332. nextPutVar: aString
  2333. stream nextPutAll: 'var ', aString, ';'; lf
  2334. !
  2335. nextPutVars: aCollection
  2336. stream nextPutAll: 'var '.
  2337. aCollection
  2338. do: [ :each | stream nextPutAll: each ]
  2339. separatedBy: [ stream nextPutAll: ',' ].
  2340. stream nextPutAll: ';'; lf
  2341. ! !
  2342. !BlockClosure methodsFor: '*Compiler'!
  2343. appendToInstruction: anIRInstruction
  2344. anIRInstruction appendBlock: self
  2345. ! !
  2346. !String methodsFor: '*Compiler'!
  2347. asVariableName
  2348. ^ (Smalltalk current reservedWords includes: self)
  2349. ifTrue: [ self, '_' ]
  2350. ifFalse: [ self ]
  2351. ! !
  2352. IRAssignment subclass: #IRInlinedAssignment
  2353. instanceVariableNames: ''
  2354. package:'Compiler'!
  2355. !IRInlinedAssignment commentStamp!
  2356. I represent an inlined assignment instruction.!
  2357. !IRInlinedAssignment methodsFor: '*Compiler'!
  2358. isInlined
  2359. ^ true
  2360. ! !
  2361. !IRInlinedAssignment methodsFor: '*Compiler'!
  2362. accept: aVisitor
  2363. ^ aVisitor visitIRInlinedAssignment: self
  2364. ! !
  2365. IRClosure subclass: #IRInlinedClosure
  2366. instanceVariableNames: ''
  2367. package:'Compiler'!
  2368. !IRInlinedClosure commentStamp!
  2369. I represent an inlined closure instruction.!
  2370. !IRInlinedClosure methodsFor: '*Compiler'!
  2371. isInlined
  2372. ^ true
  2373. ! !
  2374. !IRInlinedClosure methodsFor: '*Compiler'!
  2375. accept: aVisitor
  2376. aVisitor visitIRInlinedClosure: self
  2377. ! !
  2378. IRReturn subclass: #IRInlinedReturn
  2379. instanceVariableNames: ''
  2380. package:'Compiler'!
  2381. !IRInlinedReturn commentStamp!
  2382. I represent an inlined local return instruction.!
  2383. !IRInlinedReturn methodsFor: '*Compiler'!
  2384. isInlined
  2385. ^ true
  2386. ! !
  2387. !IRInlinedReturn methodsFor: '*Compiler'!
  2388. accept: aVisitor
  2389. ^ aVisitor visitIRInlinedReturn: self
  2390. ! !
  2391. IRInlinedReturn subclass: #IRInlinedNonLocalReturn
  2392. instanceVariableNames: ''
  2393. package:'Compiler'!
  2394. !IRInlinedNonLocalReturn commentStamp!
  2395. I represent an inlined non local return instruction.!
  2396. !IRInlinedNonLocalReturn methodsFor: '*Compiler'!
  2397. isInlined
  2398. ^ true
  2399. ! !
  2400. !IRInlinedNonLocalReturn methodsFor: '*Compiler'!
  2401. accept: aVisitor
  2402. ^ aVisitor visitIRInlinedNonLocalReturn: self
  2403. ! !
  2404. IRSend subclass: #IRInlinedSend
  2405. instanceVariableNames: ''
  2406. package:'Compiler'!
  2407. !IRInlinedSend commentStamp!
  2408. I am the abstract super class of inlined message send instructions.!
  2409. !IRInlinedSend methodsFor: '*Compiler'!
  2410. isInlined
  2411. ^ true
  2412. ! !
  2413. !IRInlinedSend methodsFor: '*Compiler'!
  2414. accept: aVisitor
  2415. aVisitor visitInlinedSend: self
  2416. ! !
  2417. IRInlinedSend subclass: #IRInlinedIfFalse
  2418. instanceVariableNames: ''
  2419. package:'Compiler'!
  2420. !IRInlinedIfFalse methodsFor: '*Compiler'!
  2421. accept: aVisitor
  2422. aVisitor visitIRInlinedIfFalse: self
  2423. ! !
  2424. IRInlinedSend subclass: #IRInlinedIfNilIfNotNil
  2425. instanceVariableNames: ''
  2426. package:'Compiler'!
  2427. !IRInlinedIfNilIfNotNil methodsFor: '*Compiler'!
  2428. accept: aVisitor
  2429. aVisitor visitIRInlinedIfNilIfNotNil: self
  2430. ! !
  2431. IRInlinedSend subclass: #IRInlinedIfTrue
  2432. instanceVariableNames: ''
  2433. package:'Compiler'!
  2434. !IRInlinedIfTrue methodsFor: '*Compiler'!
  2435. accept: aVisitor
  2436. aVisitor visitIRInlinedIfTrue: self
  2437. ! !
  2438. IRInlinedSend subclass: #IRInlinedIfTrueIfFalse
  2439. instanceVariableNames: ''
  2440. package:'Compiler'!
  2441. !IRInlinedIfTrueIfFalse methodsFor: '*Compiler'!
  2442. accept: aVisitor
  2443. aVisitor visitIRInlinedIfTrueIfFalse: self
  2444. ! !
  2445. IRBlockSequence subclass: #IRInlinedSequence
  2446. instanceVariableNames: ''
  2447. package:'Compiler'!
  2448. !IRInlinedSequence commentStamp!
  2449. I represent a (block) sequence inside an inlined closure instruction (instance of `IRInlinedClosure`).!
  2450. !IRInlinedSequence methodsFor: '*Compiler'!
  2451. isInlined
  2452. ^ true
  2453. ! !
  2454. !IRInlinedSequence methodsFor: '*Compiler'!
  2455. accept: aVisitor
  2456. aVisitor visitIRInlinedSequence: self
  2457. ! !
  2458. IRVisitor subclass: #IRInliner
  2459. instanceVariableNames: ''
  2460. package:'Compiler'!
  2461. !IRInliner commentStamp!
  2462. I visit an IR tree, inlining message sends and block closures.
  2463. Message selectors that can be inlined are answered by `IRSendInliner >> #inlinedSelectors`!
  2464. !IRInliner methodsFor: '*Compiler'!
  2465. assignmentInliner
  2466. ^ IRAssignmentInliner new
  2467. translator: self;
  2468. yourself
  2469. !
  2470. nonLocalReturnInliner
  2471. ^ IRNonLocalReturnInliner new
  2472. translator: self;
  2473. yourself
  2474. !
  2475. returnInliner
  2476. ^ IRReturnInliner new
  2477. translator: self;
  2478. yourself
  2479. !
  2480. sendInliner
  2481. ^ IRSendInliner new
  2482. translator: self;
  2483. yourself
  2484. ! !
  2485. !IRInliner methodsFor: '*Compiler'!
  2486. shouldInlineAssignment: anIRAssignment
  2487. ^ anIRAssignment isInlined not and: [
  2488. anIRAssignment instructions last isSend and: [
  2489. self shouldInlineSend: (anIRAssignment instructions last) ]]
  2490. !
  2491. shouldInlineReturn: anIRReturn
  2492. ^ anIRReturn isInlined not and: [
  2493. anIRReturn instructions first isSend and: [
  2494. self shouldInlineSend: (anIRReturn instructions first) ]]
  2495. !
  2496. shouldInlineSend: anIRSend
  2497. ^ anIRSend isInlined not and: [
  2498. IRSendInliner shouldInline: anIRSend ]
  2499. ! !
  2500. !IRInliner methodsFor: '*Compiler'!
  2501. transformNonLocalReturn: anIRNonLocalReturn
  2502. "Replace a non local return into a local return"
  2503. | localReturn |
  2504. anIRNonLocalReturn scope canInlineNonLocalReturns ifTrue: [
  2505. anIRNonLocalReturn scope methodScope removeNonLocalReturn: anIRNonLocalReturn scope.
  2506. localReturn := IRReturn new
  2507. scope: anIRNonLocalReturn scope;
  2508. yourself.
  2509. anIRNonLocalReturn instructions do: [ :each |
  2510. localReturn add: each ].
  2511. anIRNonLocalReturn replaceWith: localReturn.
  2512. ^ localReturn ].
  2513. ^ super visitIRNonLocalReturn: anIRNonLocalReturn
  2514. !
  2515. visitIRAssignment: anIRAssignment
  2516. ^ (self shouldInlineAssignment: anIRAssignment)
  2517. ifTrue: [ self assignmentInliner inlineAssignment: anIRAssignment ]
  2518. ifFalse: [ super visitIRAssignment: anIRAssignment ]
  2519. !
  2520. visitIRNonLocalReturn: anIRNonLocalReturn
  2521. ^ (self shouldInlineReturn: anIRNonLocalReturn)
  2522. ifTrue: [ self nonLocalReturnInliner inlineReturn: anIRNonLocalReturn ]
  2523. ifFalse: [ self transformNonLocalReturn: anIRNonLocalReturn ]
  2524. !
  2525. visitIRReturn: anIRReturn
  2526. ^ (self shouldInlineReturn: anIRReturn)
  2527. ifTrue: [ self returnInliner inlineReturn: anIRReturn ]
  2528. ifFalse: [ super visitIRReturn: anIRReturn ]
  2529. !
  2530. visitIRSend: anIRSend
  2531. ^ (self shouldInlineSend: anIRSend)
  2532. ifTrue: [ self sendInliner inlineSend: anIRSend ]
  2533. ifFalse: [ super visitIRSend: anIRSend ]
  2534. ! !
  2535. IRJSTranslator subclass: #IRInliningJSTranslator
  2536. instanceVariableNames: ''
  2537. package:'Compiler'!
  2538. !IRInliningJSTranslator commentStamp!
  2539. I am a specialized JavaScript translator able to write inlined IR instructions to JavaScript stream (`JSStream` instance).!
  2540. !IRInliningJSTranslator methodsFor: '*Compiler'!
  2541. visitIRInlinedAssignment: anIRInlinedAssignment
  2542. self visit: anIRInlinedAssignment instructions last
  2543. !
  2544. visitIRInlinedClosure: anIRInlinedClosure
  2545. anIRInlinedClosure instructions do: [ :each |
  2546. self visit: each ]
  2547. !
  2548. visitIRInlinedIfFalse: anIRInlinedIfFalse
  2549. self stream nextPutIf: [
  2550. self stream nextPutAll: '!! smalltalk.assert('.
  2551. self visit: anIRInlinedIfFalse instructions first.
  2552. self stream nextPutAll: ')' ]
  2553. with: [ self visit: anIRInlinedIfFalse instructions last ]
  2554. !
  2555. visitIRInlinedIfNil: anIRInlinedIfNil
  2556. self stream nextPutIf: [
  2557. self stream nextPutAll: '($receiver = '.
  2558. self visit: anIRInlinedIfNil instructions first.
  2559. self stream nextPutAll: ') == nil || $receiver == undefined' ]
  2560. with: [ self visit: anIRInlinedIfNil instructions last ]
  2561. !
  2562. visitIRInlinedIfNilIfNotNil: anIRInlinedIfNilIfNotNil
  2563. self stream
  2564. nextPutIfElse: [
  2565. self stream nextPutAll: '($receiver = '.
  2566. self visit: anIRInlinedIfNilIfNotNil instructions first.
  2567. self stream nextPutAll: ') == nil || $receiver == undefined' ]
  2568. with: [ self visit: anIRInlinedIfNilIfNotNil instructions second ]
  2569. with: [ self visit: anIRInlinedIfNilIfNotNil instructions third ]
  2570. !
  2571. visitIRInlinedIfTrue: anIRInlinedIfTrue
  2572. self stream nextPutIf: [
  2573. self stream nextPutAll: 'smalltalk.assert('.
  2574. self visit: anIRInlinedIfTrue instructions first.
  2575. self stream nextPutAll: ')' ]
  2576. with: [ self visit: anIRInlinedIfTrue instructions last ]
  2577. !
  2578. visitIRInlinedIfTrueIfFalse: anIRInlinedIfTrueIfFalse
  2579. self stream
  2580. nextPutIfElse: [
  2581. self stream nextPutAll: 'smalltalk.assert('.
  2582. self visit: anIRInlinedIfTrueIfFalse instructions first.
  2583. self stream nextPutAll: ')' ]
  2584. with: [ self visit: anIRInlinedIfTrueIfFalse instructions second ]
  2585. with: [ self visit: anIRInlinedIfTrueIfFalse instructions third ]
  2586. !
  2587. visitIRInlinedNonLocalReturn: anIRInlinedReturn
  2588. self stream nextPutStatementWith: [
  2589. self visit: anIRInlinedReturn instructions last ].
  2590. self stream nextPutNonLocalReturnWith: [ ]
  2591. !
  2592. visitIRInlinedReturn: anIRInlinedReturn
  2593. self visit: anIRInlinedReturn instructions last
  2594. !
  2595. visitIRInlinedSequence: anIRInlinedSequence
  2596. anIRInlinedSequence instructions do: [ :each |
  2597. self stream nextPutStatementWith: [ self visit: each ]]
  2598. ! !
  2599. Object subclass: #IRSendInliner
  2600. instanceVariableNames: 'send translator'
  2601. package:'Compiler'!
  2602. !IRSendInliner commentStamp!
  2603. I inline some message sends and block closure arguments. I heavily rely on #perform: to dispatch inlining methods.!
  2604. !IRSendInliner methodsFor: '*Compiler'!
  2605. send
  2606. ^ send
  2607. !
  2608. send: anIRSend
  2609. send := anIRSend
  2610. !
  2611. translator
  2612. ^ translator
  2613. !
  2614. translator: anASTTranslator
  2615. translator := anASTTranslator
  2616. ! !
  2617. !IRSendInliner methodsFor: '*Compiler'!
  2618. inliningError: aString
  2619. InliningError signal: aString
  2620. ! !
  2621. !IRSendInliner methodsFor: '*Compiler'!
  2622. inlinedClosure
  2623. ^ IRInlinedClosure new
  2624. !
  2625. inlinedSequence
  2626. ^ IRInlinedSequence new
  2627. ! !
  2628. !IRSendInliner methodsFor: '*Compiler'!
  2629. ifFalse: anIRInstruction
  2630. ^ self inlinedSend: IRInlinedIfFalse new with: anIRInstruction
  2631. !
  2632. ifFalse: anIRInstruction ifTrue: anotherIRInstruction
  2633. ^ self perform: #ifTrue:ifFalse: withArguments: { anotherIRInstruction. anIRInstruction }
  2634. !
  2635. ifNil: anIRInstruction
  2636. ^ self
  2637. inlinedSend: IRInlinedIfNilIfNotNil new
  2638. with: anIRInstruction
  2639. with: (IRClosure new
  2640. scope: anIRInstruction scope copy;
  2641. add: (IRBlockSequence new
  2642. add: self send instructions first;
  2643. yourself);
  2644. yourself)
  2645. !
  2646. ifNil: anIRInstruction ifNotNil: anotherIRInstruction
  2647. ^ self inlinedSend: IRInlinedIfNilIfNotNil new with: anIRInstruction with: anotherIRInstruction
  2648. !
  2649. ifNotNil: anIRInstruction
  2650. ^ self
  2651. inlinedSend: IRInlinedIfNilIfNotNil new
  2652. with: (IRClosure new
  2653. scope: anIRInstruction scope copy;
  2654. add: (IRBlockSequence new
  2655. add: self send instructions first;
  2656. yourself);
  2657. yourself)
  2658. with: anIRInstruction
  2659. !
  2660. ifNotNil: anIRInstruction ifNil: anotherIRInstruction
  2661. ^ self inlinedSend: IRInlinedIfNilIfNotNil new with: anotherIRInstruction with: anIRInstruction
  2662. !
  2663. ifTrue: anIRInstruction
  2664. ^ self inlinedSend: IRInlinedIfTrue new with: anIRInstruction
  2665. !
  2666. ifTrue: anIRInstruction ifFalse: anotherIRInstruction
  2667. ^ self inlinedSend: IRInlinedIfTrueIfFalse new with: anIRInstruction with: anotherIRInstruction
  2668. !
  2669. inlineClosure: anIRClosure
  2670. | inlinedClosure sequence statements |
  2671. inlinedClosure := self inlinedClosure.
  2672. inlinedClosure scope: anIRClosure scope.
  2673. "Add the possible temp declarations"
  2674. anIRClosure instructions do: [ :each |
  2675. each isSequence ifFalse: [
  2676. inlinedClosure add: each ]].
  2677. "Add a block sequence"
  2678. sequence := self inlinedSequence.
  2679. inlinedClosure add: sequence.
  2680. "Get all the statements"
  2681. statements := anIRClosure instructions last instructions.
  2682. statements ifNotEmpty: [
  2683. statements allButLast do: [ :each | sequence add: each ].
  2684. "Inlined closures don't have implicit local returns"
  2685. (statements last isReturn and: [ statements last isBlockReturn ])
  2686. ifTrue: [ sequence add: statements last instructions first ]
  2687. ifFalse: [ sequence add: statements last ] ].
  2688. ^ inlinedClosure
  2689. !
  2690. inlineSend: anIRSend
  2691. self send: anIRSend.
  2692. ^ self
  2693. perform: self send selector
  2694. withArguments: self send instructions allButFirst
  2695. !
  2696. inlinedSend: inlinedSend with: anIRInstruction
  2697. | inlinedClosure |
  2698. anIRInstruction isClosure ifFalse: [ self inliningError: 'Message argument should be a block' ].
  2699. anIRInstruction arguments size = 0 ifFalse: [ self inliningError: 'Inlined block should have zero argument' ].
  2700. inlinedClosure := self translator visit: (self inlineClosure: anIRInstruction).
  2701. inlinedSend
  2702. add: self send instructions first;
  2703. add: inlinedClosure.
  2704. self send replaceWith: inlinedSend.
  2705. ^ inlinedSend
  2706. !
  2707. inlinedSend: inlinedSend with: anIRInstruction with: anotherIRInstruction
  2708. | inlinedClosure1 inlinedClosure2 |
  2709. anIRInstruction isClosure ifFalse: [ self inliningError: 'Message argument should be a block' ].
  2710. anIRInstruction arguments size = 0 ifFalse: [ self inliningError: 'Inlined block should have zero argument' ].
  2711. anotherIRInstruction isClosure ifFalse: [ self inliningError: 'Message argument should be a block' ].
  2712. anotherIRInstruction arguments size = 0 ifFalse: [ self inliningError: 'Inlined block should have zero argument' ].
  2713. inlinedClosure1 := self translator visit: (self inlineClosure: anIRInstruction).
  2714. inlinedClosure2 := self translator visit: (self inlineClosure: anotherIRInstruction).
  2715. inlinedSend
  2716. add: self send instructions first;
  2717. add: inlinedClosure1;
  2718. add: inlinedClosure2.
  2719. self send replaceWith: inlinedSend.
  2720. ^ inlinedSend
  2721. ! !
  2722. !IRSendInliner class methodsFor: '*Compiler'!
  2723. inlinedSelectors
  2724. ^ #('ifTrue:' 'ifFalse:' 'ifTrue:ifFalse:' 'ifFalse:ifTrue:' 'ifNil:' 'ifNotNil:' 'ifNil:ifNotNil:' 'ifNotNil:ifNil')
  2725. !
  2726. shouldInline: anIRInstruction
  2727. (self inlinedSelectors includes: anIRInstruction selector) ifFalse: [ ^ false ].
  2728. anIRInstruction instructions allButFirst do: [ :each |
  2729. each isClosure ifFalse: [ ^ false ]].
  2730. ^ true
  2731. ! !
  2732. IRSendInliner subclass: #IRAssignmentInliner
  2733. instanceVariableNames: 'assignment'
  2734. package:'Compiler'!
  2735. !IRAssignmentInliner commentStamp!
  2736. I inline message sends together with assignments by moving them around into the inline closure instructions.
  2737. ##Example
  2738. foo
  2739. | a |
  2740. a := true ifTrue: [ 1 ]
  2741. Will produce:
  2742. if(smalltalk.assert(true) {
  2743. a = 1;
  2744. };!
  2745. !IRAssignmentInliner methodsFor: '*Compiler'!
  2746. assignment
  2747. ^ assignment
  2748. !
  2749. assignment: aNode
  2750. assignment := aNode
  2751. ! !
  2752. !IRAssignmentInliner methodsFor: '*Compiler'!
  2753. inlineAssignment: anIRAssignment
  2754. | inlinedAssignment |
  2755. self assignment: anIRAssignment.
  2756. inlinedAssignment := IRInlinedAssignment new.
  2757. anIRAssignment instructions do: [ :each |
  2758. inlinedAssignment add: each ].
  2759. anIRAssignment replaceWith: inlinedAssignment.
  2760. self inlineSend: inlinedAssignment instructions last.
  2761. ^ inlinedAssignment
  2762. !
  2763. inlineClosure: anIRClosure
  2764. | inlinedClosure statements |
  2765. inlinedClosure := super inlineClosure: anIRClosure.
  2766. statements := inlinedClosure instructions last instructions.
  2767. statements ifNotEmpty: [
  2768. statements last canBeAssigned ifTrue: [
  2769. statements last replaceWith: (IRAssignment new
  2770. add: self assignment instructions first;
  2771. add: statements last copy;
  2772. yourself) ] ].
  2773. ^ inlinedClosure
  2774. ! !
  2775. IRSendInliner subclass: #IRNonLocalReturnInliner
  2776. instanceVariableNames: ''
  2777. package:'Compiler'!
  2778. !IRNonLocalReturnInliner methodsFor: '*Compiler'!
  2779. inlinedReturn
  2780. ^ IRInlinedNonLocalReturn new
  2781. ! !
  2782. !IRNonLocalReturnInliner methodsFor: '*Compiler'!
  2783. inlineClosure: anIRClosure
  2784. "| inlinedClosure statements |
  2785. inlinedClosure := super inlineClosure: anIRClosure.
  2786. statements := inlinedClosure instructions last instructions.
  2787. statements ifNotEmpty: [
  2788. statements last replaceWith: (IRNonLocalReturn new
  2789. add: statements last copy;
  2790. yourself) ].
  2791. ^ inlinedClosure"
  2792. ^ super inlineCLosure: anIRClosure
  2793. ! !
  2794. IRSendInliner subclass: #IRReturnInliner
  2795. instanceVariableNames: ''
  2796. package:'Compiler'!
  2797. !IRReturnInliner commentStamp!
  2798. I inline message sends with inlined closure together with a return instruction.!
  2799. !IRReturnInliner methodsFor: '*Compiler'!
  2800. inlinedReturn
  2801. ^ IRInlinedReturn new
  2802. ! !
  2803. !IRReturnInliner methodsFor: '*Compiler'!
  2804. inlineClosure: anIRClosure
  2805. | closure statements |
  2806. closure := super inlineClosure: anIRClosure.
  2807. statements := closure instructions last instructions.
  2808. statements ifNotEmpty: [
  2809. statements last isReturn
  2810. ifFalse: [ statements last replaceWith: (IRReturn new
  2811. add: statements last copy;
  2812. yourself)] ].
  2813. ^ closure
  2814. !
  2815. inlineReturn: anIRReturn
  2816. | return |
  2817. return := self inlinedReturn.
  2818. anIRReturn instructions do: [ :each |
  2819. return add: each ].
  2820. anIRReturn replaceWith: return.
  2821. self inlineSend: return instructions last.
  2822. ^ return
  2823. ! !
  2824. CodeGenerator subclass: #InliningCodeGenerator
  2825. instanceVariableNames: ''
  2826. package:'Compiler'!
  2827. !InliningCodeGenerator commentStamp!
  2828. I am a specialized code generator that uses inlining to produce more optimized JavaScript output!
  2829. !InliningCodeGenerator methodsFor: '*Compiler'!
  2830. compileNode: aNode
  2831. | ir stream |
  2832. self semanticAnalyzer visit: aNode.
  2833. ir := self translator visit: aNode.
  2834. self inliner visit: ir.
  2835. ^ self irTranslator
  2836. visit: ir;
  2837. contents
  2838. !
  2839. inliner
  2840. ^ IRInliner new
  2841. !
  2842. irTranslator
  2843. ^ IRInliningJSTranslator new
  2844. ! !
  2845. NodeVisitor subclass: #AIContext
  2846. instanceVariableNames: 'outerContext pc locals receiver selector'
  2847. package:'Compiler'!
  2848. !AIContext methodsFor: '*Compiler'!
  2849. initializeFromMethodContext: aMethodContext
  2850. self pc: aMethodContext pc.
  2851. self receiver: aMethodContext receiver.
  2852. self selector: aMethodContext selector.
  2853. aMethodContext outerContext ifNotNil: [
  2854. self outerContext: (self class fromMethodContext: aMethodContext outerContext) ].
  2855. aMethodContext locals keysAndValuesDo: [ :key :value |
  2856. self locals at: key put: value ]
  2857. !
  2858. locals
  2859. ^ locals ifNil: [ locals := Dictionary new ]
  2860. !
  2861. outerContext
  2862. ^ outerContext
  2863. !
  2864. outerContext: anAIContext
  2865. outerContext := anAIContext
  2866. !
  2867. pc
  2868. ^ pc ifNil: [ pc := 0 ]
  2869. !
  2870. pc: anInteger
  2871. pc := anInteger
  2872. !
  2873. receiver
  2874. ^ receiver
  2875. !
  2876. receiver: anObject
  2877. receiver := anObject
  2878. !
  2879. selector
  2880. ^ selector
  2881. !
  2882. selector: aString
  2883. selector := aString
  2884. ! !
  2885. !AIContext class methodsFor: '*Compiler'!
  2886. fromMethodContext: aMethodContext
  2887. ^ self new
  2888. initializeFromMethodContext: aMethodContext;
  2889. yourself
  2890. ! !
  2891. NodeVisitor subclass: #ASTInterpreter
  2892. instanceVariableNames: 'currentNode context shouldReturn'
  2893. package:'Compiler'!
  2894. !ASTInterpreter methodsFor: '*Compiler'!
  2895. context
  2896. ^ context
  2897. !
  2898. context: anAIContext
  2899. context := anAIContext
  2900. ! !
  2901. !ASTInterpreter methodsFor: '*Compiler'!
  2902. initialize
  2903. super initialize.
  2904. shouldReturn := false
  2905. ! !
  2906. !ASTInterpreter methodsFor: '*Compiler'!
  2907. interpret: aNode
  2908. shouldReturn := false.
  2909. ^ self interpretNode: aNode
  2910. !
  2911. interpretNode: aNode
  2912. currentNode := aNode.
  2913. ^ self visit: aNode
  2914. !
  2915. messageFromSendNode: aSendNode
  2916. ^ Message new
  2917. selector: aSendNode selector;
  2918. arguments: (aSendNode arguments collect: [ :each |
  2919. self interpretNode: each ]);
  2920. yourself
  2921. ! !
  2922. !ASTInterpreter methodsFor: '*Compiler'!
  2923. visitBlockNode: aNode
  2924. ^ [ self interpretNode: aNode nodes first ]
  2925. !
  2926. visitCascadeNode: aNode
  2927. "TODO: Handle super sends"
  2928. | receiver |
  2929. receiver := self interpretNode: aNode receiver.
  2930. aNode nodes allButLast
  2931. do: [ :each |
  2932. (self messageFromSendNode: each)
  2933. sendTo: receiver ].
  2934. ^ (self messageFromSendNode: aNode nodes last)
  2935. sendTo: receiver
  2936. !
  2937. visitClassReferenceNode: aNode
  2938. ^ Smalltalk current at: aNode value
  2939. !
  2940. visitJSStatementNode: aNode
  2941. self halt
  2942. !
  2943. visitReturnNode: aNode
  2944. shouldReturn := true.
  2945. ^ self interpretNode: aNode nodes first
  2946. !
  2947. visitSendNode: aNode
  2948. "TODO: Handle super sends"
  2949. ^ (self messageFromSendNode: aNode)
  2950. sendTo: (self interpretNode: aNode receiver)
  2951. !
  2952. visitSequenceNode: aNode
  2953. aNode nodes allButLast do: [ :each | | value |
  2954. value := self interpretNode: each.
  2955. shouldReturn ifTrue: [ ^ value ] ].
  2956. ^ self interpretNode: aNode nodes last
  2957. !
  2958. visitValueNode: aNode
  2959. ^ aNode value
  2960. ! !