Compiler.st 90 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378
  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, ''');';
  134. 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. 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: 'messageSends: ', aMethod messageSends asJavascript;
  268. nextPutAll: '}),';lf;
  269. nextPutAll: 'smalltalk.', (self classNameFor: aClass);
  270. nextPutAll: ');';lf;lf
  271. ! !
  272. Object subclass: #Importer
  273. instanceVariableNames: ''
  274. package:'Compiler'!
  275. !Importer methodsFor: '*Compiler'!
  276. import: aStream
  277. | chunk result parser lastEmpty |
  278. parser := ChunkParser on: aStream.
  279. lastEmpty := false.
  280. [chunk := parser nextChunk.
  281. chunk isNil] whileFalse: [
  282. chunk isEmpty
  283. ifTrue: [lastEmpty := true]
  284. ifFalse: [
  285. result := Compiler new evaluateExpression: chunk.
  286. lastEmpty
  287. ifTrue: [
  288. lastEmpty := false.
  289. result scanFrom: parser]]]
  290. ! !
  291. Object subclass: #PackageLoader
  292. instanceVariableNames: ''
  293. package:'Compiler'!
  294. !PackageLoader methodsFor: '*Compiler'!
  295. initializePackageNamed: packageName prefix: aString
  296. (Package named: packageName)
  297. setupClasses;
  298. commitPathJs: '/', aString, '/js';
  299. commitPathSt: '/', aString, '/st'
  300. !
  301. loadPackage: packageName prefix: aString
  302. | url |
  303. url := '/', aString, '/js/', packageName, '.js'.
  304. jQuery
  305. ajax: url
  306. options: #{
  307. 'type' -> 'GET'.
  308. 'dataType' -> 'script'.
  309. 'complete' -> [ :jqXHR :textStatus |
  310. jqXHR readyState = 4
  311. ifTrue: [ self initializePackageNamed: packageName prefix: aString ] ].
  312. 'error' -> [ window alert: 'Could not load package at: ', url ]
  313. }
  314. !
  315. loadPackages: aCollection prefix: aString
  316. aCollection do: [ :each |
  317. self loadPackage: each prefix: aString ]
  318. ! !
  319. !PackageLoader class methodsFor: '*Compiler'!
  320. loadPackages: aCollection prefix: aString
  321. ^ self new loadPackages: aCollection prefix: aString
  322. ! !
  323. Error subclass: #CompilerError
  324. instanceVariableNames: ''
  325. package:'Compiler'!
  326. !CompilerError commentStamp!
  327. I am the common superclass of all compiling errors.!
  328. CompilerError subclass: #ParseError
  329. instanceVariableNames: ''
  330. package:'Compiler'!
  331. !ParseError commentStamp!
  332. Instance of ParseError are signaled on any parsing error.
  333. See `Smalltalk >> #parse:`!
  334. CompilerError subclass: #SemanticError
  335. instanceVariableNames: ''
  336. package:'Compiler'!
  337. !SemanticError commentStamp!
  338. I represent an abstract semantic error thrown by the SemanticAnalyzer.
  339. Semantic errors can be unknown variable errors, etc.
  340. See my subclasses for concrete errors.
  341. The IDE should catch instances of Semantic error to deal with them when compiling!
  342. SemanticError subclass: #InliningError
  343. instanceVariableNames: ''
  344. package:'Compiler'!
  345. !InliningError commentStamp!
  346. Instances of InliningError are signaled when using an `InliningCodeGenerator`in a `Compiler`.!
  347. SemanticError subclass: #InvalidAssignmentError
  348. instanceVariableNames: 'variableName'
  349. package:'Compiler'!
  350. !InvalidAssignmentError commentStamp!
  351. I get signaled when a pseudo variable gets assigned.!
  352. !InvalidAssignmentError methodsFor: '*Compiler'!
  353. messageText
  354. ^ ' Invalid assignment to variable: ', self variableName
  355. !
  356. variableName
  357. ^ variableName
  358. !
  359. variableName: aString
  360. variableName := aString
  361. ! !
  362. SemanticError subclass: #ShadowingVariableError
  363. instanceVariableNames: 'variableName'
  364. package:'Compiler'!
  365. !ShadowingVariableError commentStamp!
  366. I get signaled when a variable in a block or method scope shadows a variable of the same name in an outer scope.!
  367. !ShadowingVariableError methodsFor: '*Compiler'!
  368. messageText
  369. ^ 'Variable shadowing error: ', self variableName, ' is already defined'
  370. !
  371. variableName
  372. ^ variableName
  373. !
  374. variableName: aString
  375. variableName := aString
  376. ! !
  377. SemanticError subclass: #UnknownVariableError
  378. instanceVariableNames: 'variableName'
  379. package:'Compiler'!
  380. !UnknownVariableError commentStamp!
  381. I get signaled when a variable is not defined.
  382. The default behavior is to allow it, as this is how Amber currently is able to seamlessly send messages to JavaScript objects.!
  383. !UnknownVariableError methodsFor: '*Compiler'!
  384. messageText
  385. ^ 'Unknown Variable error: ', self variableName, ' is not defined'
  386. !
  387. variableName
  388. ^ variableName
  389. !
  390. variableName: aString
  391. variableName := aString
  392. ! !
  393. ErrorHandler subclass: #RethrowErrorHandler
  394. instanceVariableNames: ''
  395. package:'Compiler'!
  396. !RethrowErrorHandler commentStamp!
  397. This class is used in the commandline version of the compiler.
  398. It uses the handleError: message of ErrorHandler for printing the stacktrace and throws the error again as JS exception.
  399. As a result Smalltalk errors are not swallowd by the Amber runtime and compilation can be aborted.!
  400. !RethrowErrorHandler methodsFor: '*Compiler'!
  401. basicSignal: anError
  402. <throw anError>
  403. !
  404. handleError: anError
  405. super handleError: anError.
  406. self basicSignal: anError
  407. ! !
  408. Object subclass: #Compiler
  409. instanceVariableNames: 'currentClass source unknownVariables codeGeneratorClass'
  410. package:'Compiler'!
  411. !Compiler commentStamp!
  412. I provide the public interface for compiling Amber source code into JavaScript.
  413. The code generator used to produce JavaScript can be plugged with `#codeGeneratorClass`.
  414. The default code generator is an instance of `InlinedCodeGenerator`!
  415. !Compiler methodsFor: '*Compiler'!
  416. codeGeneratorClass
  417. ^codeGeneratorClass ifNil: [InliningCodeGenerator]
  418. !
  419. codeGeneratorClass: aClass
  420. codeGeneratorClass := aClass
  421. !
  422. currentClass
  423. ^currentClass
  424. !
  425. currentClass: aClass
  426. currentClass := aClass
  427. !
  428. source
  429. ^source ifNil: ['']
  430. !
  431. source: aString
  432. source := aString
  433. !
  434. unknownVariables
  435. ^unknownVariables
  436. !
  437. unknownVariables: aCollection
  438. unknownVariables := aCollection
  439. ! !
  440. !Compiler methodsFor: '*Compiler'!
  441. compile: aString
  442. ^self compileNode: (self parse: aString)
  443. !
  444. compile: aString forClass: aClass
  445. self currentClass: aClass.
  446. self source: aString.
  447. ^self compile: aString
  448. !
  449. compileExpression: aString
  450. self currentClass: DoIt.
  451. self source: 'doIt ^[', aString, '] value'.
  452. ^self compileNode: (self parse: self source)
  453. !
  454. compileNode: aNode
  455. | generator result |
  456. generator := self codeGeneratorClass new.
  457. generator
  458. source: self source;
  459. currentClass: self currentClass.
  460. result := generator compileNode: aNode.
  461. self unknownVariables: #().
  462. ^result
  463. !
  464. eval: aString
  465. <return eval(aString)>
  466. !
  467. evaluateExpression: aString
  468. "Unlike #eval: evaluate a Smalltalk expression and answer the returned object"
  469. | result |
  470. DoIt addCompiledMethod: (self eval: (self compileExpression: aString)).
  471. result := DoIt new doIt.
  472. DoIt removeCompiledMethod: (DoIt methodDictionary at: 'doIt').
  473. ^result
  474. !
  475. install: aString forClass: aBehavior category: anotherString
  476. ^ ClassBuilder new
  477. installMethod: (self eval: (self compile: aString forClass: aBehavior))
  478. forClass: aBehavior
  479. category: anotherString
  480. !
  481. parse: aString
  482. ^Smalltalk current parse: aString
  483. !
  484. parseExpression: aString
  485. ^self parse: 'doIt ^[', aString, '] value'
  486. !
  487. recompile: aClass
  488. aClass methodDictionary do: [:each |
  489. console log: aClass name, ' >> ', each selector.
  490. self install: each source forClass: aClass category: each category].
  491. "self setupClass: aClass."
  492. aClass isMetaclass ifFalse: [self recompile: aClass class]
  493. !
  494. recompileAll
  495. Smalltalk current classes do: [:each |
  496. Transcript show: each; cr.
  497. [self recompile: each] valueWithTimeout: 100]
  498. ! !
  499. !Compiler class methodsFor: '*Compiler'!
  500. recompile: aClass
  501. self new recompile: aClass
  502. !
  503. recompileAll
  504. Smalltalk current classes do: [:each |
  505. self recompile: each]
  506. ! !
  507. Object subclass: #DoIt
  508. instanceVariableNames: ''
  509. package:'Compiler'!
  510. !DoIt commentStamp!
  511. `DoIt` is the class used to compile and evaluate expressions. See `Compiler >> evaluateExpression:`.!
  512. Object subclass: #NodeVisitor
  513. instanceVariableNames: ''
  514. package:'Compiler'!
  515. !NodeVisitor commentStamp!
  516. I am the abstract super class of all AST node visitors.!
  517. !NodeVisitor methodsFor: '*Compiler'!
  518. visit: aNode
  519. ^ aNode accept: self
  520. !
  521. visitAll: aCollection
  522. ^ aCollection collect: [ :each | self visit: each ]
  523. !
  524. visitAssignmentNode: aNode
  525. ^ self visitNode: aNode
  526. !
  527. visitBlockNode: aNode
  528. ^ self visitNode: aNode
  529. !
  530. visitBlockSequenceNode: aNode
  531. ^ self visitSequenceNode: aNode
  532. !
  533. visitCascadeNode: aNode
  534. ^ self visitNode: aNode
  535. !
  536. visitClassReferenceNode: aNode
  537. ^ self visitVariableNode: aNode
  538. !
  539. visitDynamicArrayNode: aNode
  540. ^ self visitNode: aNode
  541. !
  542. visitDynamicDictionaryNode: aNode
  543. ^ self visitNode: aNode
  544. !
  545. visitJSStatementNode: aNode
  546. ^ self visitNode: aNode
  547. !
  548. visitMethodNode: aNode
  549. ^ self visitNode: aNode
  550. !
  551. visitNode: aNode
  552. ^ self visitAll: aNode nodes
  553. !
  554. visitReturnNode: aNode
  555. ^ self visitNode: aNode
  556. !
  557. visitSendNode: aNode
  558. ^ self visitNode: aNode
  559. !
  560. visitSequenceNode: aNode
  561. ^ self visitNode: aNode
  562. !
  563. visitValueNode: aNode
  564. ^ self visitNode: aNode
  565. !
  566. visitVariableNode: aNode
  567. ^ self visitNode: aNode
  568. ! !
  569. NodeVisitor subclass: #AbstractCodeGenerator
  570. instanceVariableNames: 'currentClass source'
  571. package:'Compiler'!
  572. !AbstractCodeGenerator commentStamp!
  573. I am the abstract super class of all code generators and provide their common API.!
  574. !AbstractCodeGenerator methodsFor: '*Compiler'!
  575. classNameFor: aClass
  576. ^aClass isMetaclass
  577. ifTrue: [aClass instanceClass name, '.klass']
  578. ifFalse: [
  579. aClass isNil
  580. ifTrue: ['nil']
  581. ifFalse: [aClass name]]
  582. !
  583. currentClass
  584. ^currentClass
  585. !
  586. currentClass: aClass
  587. currentClass := aClass
  588. !
  589. pseudoVariables
  590. ^#('self' 'super' 'true' 'false' 'nil' 'thisContext')
  591. !
  592. safeVariableNameFor: aString
  593. ^(Smalltalk current reservedWords includes: aString)
  594. ifTrue: [aString, '_']
  595. ifFalse: [aString]
  596. !
  597. source
  598. ^source ifNil: ['']
  599. !
  600. source: aString
  601. source := aString
  602. ! !
  603. !AbstractCodeGenerator methodsFor: '*Compiler'!
  604. compileNode: aNode
  605. self subclassResponsibility
  606. ! !
  607. AbstractCodeGenerator subclass: #CodeGenerator
  608. instanceVariableNames: ''
  609. package:'Compiler'!
  610. !CodeGenerator commentStamp!
  611. I am a basic code generator. I generate a valid JavaScript output, but no not perform any inlining.
  612. See `InliningCodeGenerator` for an optimized JavaScript code generation.!
  613. !CodeGenerator methodsFor: '*Compiler'!
  614. compileNode: aNode
  615. | ir stream |
  616. self semanticAnalyzer visit: aNode.
  617. ir := self translator visit: aNode.
  618. ^ self irTranslator
  619. visit: ir;
  620. contents
  621. !
  622. irTranslator
  623. ^ IRJSTranslator new
  624. !
  625. semanticAnalyzer
  626. ^ SemanticAnalyzer on: self currentClass
  627. !
  628. translator
  629. ^ IRASTTranslator new
  630. source: self source;
  631. theClass: self currentClass;
  632. yourself
  633. ! !
  634. Object subclass: #Node
  635. instanceVariableNames: 'position nodes shouldBeInlined shouldBeAliased'
  636. package:'Compiler'!
  637. !Node commentStamp!
  638. I am the abstract root class of the abstract syntax tree.
  639. position: holds a point containing lline- and column number of the symbol location in the original source file!
  640. !Node methodsFor: '*Compiler'!
  641. addNode: aNode
  642. self nodes add: aNode
  643. !
  644. nodes
  645. ^nodes ifNil: [nodes := Array new]
  646. !
  647. position
  648. ^position ifNil: [position := 0@0]
  649. !
  650. shouldBeAliased
  651. ^ shouldBeAliased ifNil: [ false ]
  652. !
  653. shouldBeAliased: aBoolean
  654. shouldBeAliased := aBoolean
  655. !
  656. shouldBeInlined
  657. ^ shouldBeInlined ifNil: [ false ]
  658. !
  659. shouldBeInlined: aBoolean
  660. shouldBeInlined := aBoolean
  661. ! !
  662. !Node methodsFor: '*Compiler'!
  663. nodes: aCollection
  664. nodes := aCollection
  665. !
  666. position: aPosition
  667. position := aPosition
  668. ! !
  669. !Node methodsFor: '*Compiler'!
  670. isAssignmentNode
  671. ^ false
  672. !
  673. isBlockNode
  674. ^false
  675. !
  676. isBlockSequenceNode
  677. ^false
  678. !
  679. isImmutable
  680. ^false
  681. !
  682. isNode
  683. ^ true
  684. !
  685. isReturnNode
  686. ^false
  687. !
  688. isSendNode
  689. ^false
  690. !
  691. isValueNode
  692. ^false
  693. !
  694. subtreeNeedsAliasing
  695. ^(self shouldBeAliased or: [ self shouldBeInlined ]) or: [
  696. (self nodes detect: [ :each | each subtreeNeedsAliasing ] ifNone: [ false ]) ~= false ]
  697. ! !
  698. !Node methodsFor: '*Compiler'!
  699. accept: aVisitor
  700. ^ aVisitor visitNode: self
  701. ! !
  702. Node subclass: #AssignmentNode
  703. instanceVariableNames: 'left right'
  704. package:'Compiler'!
  705. !AssignmentNode methodsFor: '*Compiler'!
  706. left
  707. ^left
  708. !
  709. left: aNode
  710. left := aNode
  711. !
  712. nodes
  713. ^ Array with: self left with: self right
  714. !
  715. right
  716. ^right
  717. !
  718. right: aNode
  719. right := aNode
  720. ! !
  721. !AssignmentNode methodsFor: '*Compiler'!
  722. isAssignmentNode
  723. ^ true
  724. ! !
  725. !AssignmentNode methodsFor: '*Compiler'!
  726. accept: aVisitor
  727. ^ aVisitor visitAssignmentNode: self
  728. ! !
  729. Node subclass: #BlockNode
  730. instanceVariableNames: 'parameters scope'
  731. package:'Compiler'!
  732. !BlockNode methodsFor: '*Compiler'!
  733. parameters
  734. ^parameters ifNil: [parameters := Array new]
  735. !
  736. parameters: aCollection
  737. parameters := aCollection
  738. !
  739. scope
  740. ^ scope
  741. !
  742. scope: aLexicalScope
  743. scope := aLexicalScope
  744. ! !
  745. !BlockNode methodsFor: '*Compiler'!
  746. isBlockNode
  747. ^true
  748. !
  749. subtreeNeedsAliasing
  750. ^ self shouldBeAliased or: [ self shouldBeInlined ]
  751. ! !
  752. !BlockNode methodsFor: '*Compiler'!
  753. accept: aVisitor
  754. ^ aVisitor visitBlockNode: self
  755. ! !
  756. Node subclass: #CascadeNode
  757. instanceVariableNames: 'receiver'
  758. package:'Compiler'!
  759. !CascadeNode methodsFor: '*Compiler'!
  760. receiver
  761. ^receiver
  762. !
  763. receiver: aNode
  764. receiver := aNode
  765. ! !
  766. !CascadeNode methodsFor: '*Compiler'!
  767. accept: aVisitor
  768. ^ aVisitor visitCascadeNode: self
  769. ! !
  770. Node subclass: #DynamicArrayNode
  771. instanceVariableNames: ''
  772. package:'Compiler'!
  773. !DynamicArrayNode methodsFor: '*Compiler'!
  774. accept: aVisitor
  775. ^ aVisitor visitDynamicArrayNode: self
  776. ! !
  777. Node subclass: #DynamicDictionaryNode
  778. instanceVariableNames: ''
  779. package:'Compiler'!
  780. !DynamicDictionaryNode methodsFor: '*Compiler'!
  781. accept: aVisitor
  782. ^ aVisitor visitDynamicDictionaryNode: self
  783. ! !
  784. Node subclass: #JSStatementNode
  785. instanceVariableNames: 'source'
  786. package:'Compiler'!
  787. !JSStatementNode methodsFor: '*Compiler'!
  788. source
  789. ^source ifNil: ['']
  790. !
  791. source: aString
  792. source := aString
  793. ! !
  794. !JSStatementNode methodsFor: '*Compiler'!
  795. accept: aVisitor
  796. ^ aVisitor visitJSStatementNode: self
  797. ! !
  798. Node subclass: #MethodNode
  799. instanceVariableNames: 'selector arguments source scope classReferences messageSends superSends'
  800. package:'Compiler'!
  801. !MethodNode methodsFor: '*Compiler'!
  802. arguments
  803. ^arguments ifNil: [#()]
  804. !
  805. arguments: aCollection
  806. arguments := aCollection
  807. !
  808. classReferences
  809. ^ classReferences
  810. !
  811. classReferences: aCollection
  812. classReferences := aCollection
  813. !
  814. messageSends
  815. ^ messageSends
  816. !
  817. messageSends: aCollection
  818. messageSends := aCollection
  819. !
  820. scope
  821. ^ scope
  822. !
  823. scope: aMethodScope
  824. scope := aMethodScope
  825. !
  826. selector
  827. ^selector
  828. !
  829. selector: aString
  830. selector := aString
  831. !
  832. source
  833. ^source
  834. !
  835. source: aString
  836. source := aString
  837. !
  838. superSends
  839. ^ superSends
  840. !
  841. superSends: aCollection
  842. superSends := aCollection
  843. ! !
  844. !MethodNode methodsFor: '*Compiler'!
  845. accept: aVisitor
  846. ^ aVisitor visitMethodNode: self
  847. ! !
  848. Node subclass: #ReturnNode
  849. instanceVariableNames: 'scope'
  850. package:'Compiler'!
  851. !ReturnNode methodsFor: '*Compiler'!
  852. scope
  853. ^ scope
  854. !
  855. scope: aLexicalScope
  856. scope := aLexicalScope
  857. ! !
  858. !ReturnNode methodsFor: '*Compiler'!
  859. isReturnNode
  860. ^ true
  861. !
  862. nonLocalReturn
  863. ^ self scope isMethodScope not
  864. ! !
  865. !ReturnNode methodsFor: '*Compiler'!
  866. accept: aVisitor
  867. ^ aVisitor visitReturnNode: self
  868. ! !
  869. Node subclass: #SendNode
  870. instanceVariableNames: 'selector arguments receiver superSend index'
  871. package:'Compiler'!
  872. !SendNode methodsFor: '*Compiler'!
  873. arguments
  874. ^arguments ifNil: [arguments := #()]
  875. !
  876. arguments: aCollection
  877. arguments := aCollection
  878. !
  879. cascadeNodeWithMessages: aCollection
  880. | first |
  881. first := SendNode new
  882. selector: self selector;
  883. arguments: self arguments;
  884. yourself.
  885. ^CascadeNode new
  886. receiver: self receiver;
  887. nodes: (Array with: first), aCollection;
  888. yourself
  889. !
  890. index
  891. ^ index
  892. !
  893. index: anInteger
  894. index := anInteger
  895. !
  896. nodes
  897. ^ (Array withAll: self arguments)
  898. add: self receiver;
  899. yourself
  900. !
  901. receiver
  902. ^receiver
  903. !
  904. receiver: aNode
  905. receiver := aNode
  906. !
  907. selector
  908. ^selector
  909. !
  910. selector: aString
  911. selector := aString
  912. !
  913. superSend
  914. ^ superSend ifNil: [ false ]
  915. !
  916. superSend: aBoolean
  917. superSend := aBoolean
  918. !
  919. valueForReceiver: anObject
  920. ^SendNode new
  921. receiver: (self receiver
  922. ifNil: [anObject]
  923. ifNotNil: [self receiver valueForReceiver: anObject]);
  924. selector: self selector;
  925. arguments: self arguments;
  926. yourself
  927. ! !
  928. !SendNode methodsFor: '*Compiler'!
  929. isSendNode
  930. ^ true
  931. ! !
  932. !SendNode methodsFor: '*Compiler'!
  933. accept: aVisitor
  934. ^ aVisitor visitSendNode: self
  935. ! !
  936. Node subclass: #SequenceNode
  937. instanceVariableNames: 'temps scope'
  938. package:'Compiler'!
  939. !SequenceNode methodsFor: '*Compiler'!
  940. scope
  941. ^ scope
  942. !
  943. scope: aLexicalScope
  944. scope := aLexicalScope
  945. !
  946. temps
  947. ^temps ifNil: [#()]
  948. !
  949. temps: aCollection
  950. temps := aCollection
  951. ! !
  952. !SequenceNode methodsFor: '*Compiler'!
  953. asBlockSequenceNode
  954. ^BlockSequenceNode new
  955. nodes: self nodes;
  956. temps: self temps;
  957. yourself
  958. ! !
  959. !SequenceNode methodsFor: '*Compiler'!
  960. accept: aVisitor
  961. ^ aVisitor visitSequenceNode: self
  962. ! !
  963. SequenceNode subclass: #BlockSequenceNode
  964. instanceVariableNames: ''
  965. package:'Compiler'!
  966. !BlockSequenceNode methodsFor: '*Compiler'!
  967. isBlockSequenceNode
  968. ^true
  969. ! !
  970. !BlockSequenceNode methodsFor: '*Compiler'!
  971. accept: aVisitor
  972. ^ aVisitor visitBlockSequenceNode: self
  973. ! !
  974. Node subclass: #ValueNode
  975. instanceVariableNames: 'value'
  976. package:'Compiler'!
  977. !ValueNode methodsFor: '*Compiler'!
  978. value
  979. ^value
  980. !
  981. value: anObject
  982. value := anObject
  983. ! !
  984. !ValueNode methodsFor: '*Compiler'!
  985. isImmutable
  986. ^true
  987. !
  988. isValueNode
  989. ^true
  990. ! !
  991. !ValueNode methodsFor: '*Compiler'!
  992. accept: aVisitor
  993. ^ aVisitor visitValueNode: self
  994. ! !
  995. ValueNode subclass: #VariableNode
  996. instanceVariableNames: 'assigned binding'
  997. package:'Compiler'!
  998. !VariableNode methodsFor: '*Compiler'!
  999. alias
  1000. ^ self binding alias
  1001. !
  1002. assigned
  1003. ^assigned ifNil: [false]
  1004. !
  1005. assigned: aBoolean
  1006. assigned := aBoolean
  1007. !
  1008. beAssigned
  1009. self binding validateAssignment.
  1010. assigned := true
  1011. !
  1012. binding
  1013. ^ binding
  1014. !
  1015. binding: aScopeVar
  1016. binding := aScopeVar
  1017. ! !
  1018. !VariableNode methodsFor: '*Compiler'!
  1019. isImmutable
  1020. ^false
  1021. ! !
  1022. !VariableNode methodsFor: '*Compiler'!
  1023. accept: aVisitor
  1024. ^ aVisitor visitVariableNode: self
  1025. ! !
  1026. VariableNode subclass: #ClassReferenceNode
  1027. instanceVariableNames: ''
  1028. package:'Compiler'!
  1029. !ClassReferenceNode methodsFor: '*Compiler'!
  1030. accept: aVisitor
  1031. ^ aVisitor visitClassReferenceNode: self
  1032. ! !
  1033. !Object methodsFor: '*Compiler'!
  1034. isNode
  1035. ^ false
  1036. ! !
  1037. Object subclass: #LexicalScope
  1038. instanceVariableNames: 'node instruction temps args outerScope'
  1039. package:'Compiler'!
  1040. !LexicalScope commentStamp!
  1041. I represent a lexical scope where variable names are associated with ScopeVars
  1042. Instances are used for block scopes. Method scopes are instances of MethodLexicalScope.
  1043. I am attached to a ScopeVar and method/block nodes.
  1044. Each context (method/closure) get a fresh scope that inherits from its outer scope.!
  1045. !LexicalScope methodsFor: '*Compiler'!
  1046. alias
  1047. ^ '$ctx', self scopeLevel asString
  1048. !
  1049. allVariableNames
  1050. ^ self args keys, self temps keys
  1051. !
  1052. args
  1053. ^ args ifNil: [ args := Dictionary new ]
  1054. !
  1055. bindingFor: aStringOrNode
  1056. ^ self pseudoVars at: aStringOrNode value ifAbsent: [
  1057. self args at: aStringOrNode value ifAbsent: [
  1058. self temps at: aStringOrNode value ifAbsent: [ nil ]]]
  1059. !
  1060. instruction
  1061. ^ instruction
  1062. !
  1063. instruction: anIRInstruction
  1064. instruction := anIRInstruction
  1065. !
  1066. lookupVariable: aNode
  1067. | lookup |
  1068. lookup := (self bindingFor: aNode).
  1069. lookup ifNil: [
  1070. lookup := self outerScope ifNotNil: [
  1071. (self outerScope lookupVariable: aNode) ]].
  1072. ^ lookup
  1073. !
  1074. methodScope
  1075. ^ self outerScope ifNotNil: [
  1076. self outerScope methodScope ]
  1077. !
  1078. node
  1079. "Answer the node in which I am defined"
  1080. ^ node
  1081. !
  1082. node: aNode
  1083. node := aNode
  1084. !
  1085. outerScope
  1086. ^ outerScope
  1087. !
  1088. outerScope: aLexicalScope
  1089. outerScope := aLexicalScope
  1090. !
  1091. pseudoVars
  1092. ^ self methodScope pseudoVars
  1093. !
  1094. scopeLevel
  1095. self outerScope ifNil: [ ^ 1 ].
  1096. self isInlined ifTrue: [ ^ self outerScope scopeLevel ].
  1097. ^ self outerScope scopeLevel + 1
  1098. !
  1099. temps
  1100. ^ temps ifNil: [ temps := Dictionary new ]
  1101. ! !
  1102. !LexicalScope methodsFor: '*Compiler'!
  1103. addArg: aString
  1104. self args at: aString put: (ArgVar on: aString).
  1105. (self args at: aString) scope: self
  1106. !
  1107. addTemp: aString
  1108. self temps at: aString put: (TempVar on: aString).
  1109. (self temps at: aString) scope: self
  1110. ! !
  1111. !LexicalScope methodsFor: '*Compiler'!
  1112. canInlineNonLocalReturns
  1113. ^ self isInlined and: [ self outerScope canInlineNonLocalReturns ]
  1114. !
  1115. isBlockScope
  1116. ^ self isMethodScope not
  1117. !
  1118. isInlined
  1119. ^ self instruction notNil and: [
  1120. self instruction isInlined ]
  1121. !
  1122. isMethodScope
  1123. ^ false
  1124. ! !
  1125. LexicalScope subclass: #MethodLexicalScope
  1126. instanceVariableNames: 'iVars pseudoVars unknownVariables localReturn nonLocalReturns'
  1127. package:'Compiler'!
  1128. !MethodLexicalScope commentStamp!
  1129. I represent a method scope.!
  1130. !MethodLexicalScope methodsFor: '*Compiler'!
  1131. allVariableNames
  1132. ^ super allVariableNames, self iVars keys
  1133. !
  1134. bindingFor: aNode
  1135. ^ (super bindingFor: aNode) ifNil: [
  1136. self iVars at: aNode value ifAbsent: [ nil ]]
  1137. !
  1138. iVars
  1139. ^ iVars ifNil: [ iVars := Dictionary new ]
  1140. !
  1141. localReturn
  1142. ^ localReturn ifNil: [ false ]
  1143. !
  1144. localReturn: aBoolean
  1145. localReturn := aBoolean
  1146. !
  1147. methodScope
  1148. ^ self
  1149. !
  1150. nonLocalReturns
  1151. ^ nonLocalReturns ifNil: [ nonLocalReturns := OrderedCollection new ]
  1152. !
  1153. pseudoVars
  1154. pseudoVars ifNil: [
  1155. pseudoVars := Dictionary new.
  1156. Smalltalk current pseudoVariableNames do: [ :each |
  1157. pseudoVars at: each put: ((PseudoVar on: each)
  1158. scope: self methodScope;
  1159. yourself) ]].
  1160. ^ pseudoVars
  1161. !
  1162. unknownVariables
  1163. ^ unknownVariables ifNil: [ unknownVariables := OrderedCollection new ]
  1164. ! !
  1165. !MethodLexicalScope methodsFor: '*Compiler'!
  1166. addIVar: aString
  1167. self iVars at: aString put: (InstanceVar on: aString).
  1168. (self iVars at: aString) scope: self
  1169. !
  1170. addNonLocalReturn: aScope
  1171. self nonLocalReturns add: aScope
  1172. !
  1173. removeNonLocalReturn: aScope
  1174. self nonLocalReturns remove: aScope ifAbsent: []
  1175. ! !
  1176. !MethodLexicalScope methodsFor: '*Compiler'!
  1177. canInlineNonLocalReturns
  1178. ^ true
  1179. !
  1180. hasLocalReturn
  1181. ^ self localReturn
  1182. !
  1183. hasNonLocalReturn
  1184. ^ self nonLocalReturns notEmpty
  1185. !
  1186. isMethodScope
  1187. ^ true
  1188. ! !
  1189. Object subclass: #ScopeVar
  1190. instanceVariableNames: 'scope name'
  1191. package:'Compiler'!
  1192. !ScopeVar commentStamp!
  1193. I am an entry in a LexicalScope that gets associated with variable nodes of the same name.
  1194. There are 4 different subclasses of vars: temp vars, local vars, args, and unknown/global vars.!
  1195. !ScopeVar methodsFor: '*Compiler'!
  1196. alias
  1197. ^ self name asVariableName
  1198. !
  1199. name
  1200. ^ name
  1201. !
  1202. name: aString
  1203. name := aString
  1204. !
  1205. scope
  1206. ^ scope
  1207. !
  1208. scope: aScope
  1209. scope := aScope
  1210. ! !
  1211. !ScopeVar methodsFor: '*Compiler'!
  1212. isArgVar
  1213. ^ false
  1214. !
  1215. isClassRefVar
  1216. ^ false
  1217. !
  1218. isInstanceVar
  1219. ^ false
  1220. !
  1221. isPseudoVar
  1222. ^ false
  1223. !
  1224. isTempVar
  1225. ^ false
  1226. !
  1227. isUnknownVar
  1228. ^ false
  1229. !
  1230. validateAssignment
  1231. (self isArgVar or: [ self isPseudoVar ]) ifTrue: [
  1232. InvalidAssignmentError new
  1233. variableName: self name;
  1234. signal]
  1235. ! !
  1236. !ScopeVar class methodsFor: '*Compiler'!
  1237. on: aString
  1238. ^ self new
  1239. name: aString;
  1240. yourself
  1241. ! !
  1242. ScopeVar subclass: #AliasVar
  1243. instanceVariableNames: 'node'
  1244. package:'Compiler'!
  1245. !AliasVar commentStamp!
  1246. I am an internally defined variable by the compiler!
  1247. !AliasVar methodsFor: '*Compiler'!
  1248. node
  1249. ^ node
  1250. !
  1251. node: aNode
  1252. node := aNode
  1253. ! !
  1254. ScopeVar subclass: #ArgVar
  1255. instanceVariableNames: ''
  1256. package:'Compiler'!
  1257. !ArgVar commentStamp!
  1258. I am an argument of a method or block.!
  1259. !ArgVar methodsFor: '*Compiler'!
  1260. isArgVar
  1261. ^ true
  1262. ! !
  1263. ScopeVar subclass: #ClassRefVar
  1264. instanceVariableNames: ''
  1265. package:'Compiler'!
  1266. !ClassRefVar commentStamp!
  1267. I am an class reference variable!
  1268. !ClassRefVar methodsFor: '*Compiler'!
  1269. alias
  1270. ^ '(smalltalk.', self name, ' || ', self name, ')'
  1271. ! !
  1272. !ClassRefVar methodsFor: '*Compiler'!
  1273. isClassRefVar
  1274. ^ true
  1275. ! !
  1276. ScopeVar subclass: #InstanceVar
  1277. instanceVariableNames: ''
  1278. package:'Compiler'!
  1279. !InstanceVar commentStamp!
  1280. I am an instance variable of a method or block.!
  1281. !InstanceVar methodsFor: '*Compiler'!
  1282. alias
  1283. ^ 'self["@', self name, '"]'
  1284. !
  1285. isInstanceVar
  1286. ^ true
  1287. ! !
  1288. ScopeVar subclass: #PseudoVar
  1289. instanceVariableNames: ''
  1290. package:'Compiler'!
  1291. !PseudoVar commentStamp!
  1292. I am an pseudo variable.
  1293. The five Smalltalk pseudo variables are: 'self', 'super', 'nil', 'true' and 'false'!
  1294. !PseudoVar methodsFor: '*Compiler'!
  1295. alias
  1296. ^ self name
  1297. ! !
  1298. !PseudoVar methodsFor: '*Compiler'!
  1299. isPseudoVar
  1300. ^ true
  1301. ! !
  1302. ScopeVar subclass: #TempVar
  1303. instanceVariableNames: ''
  1304. package:'Compiler'!
  1305. !TempVar commentStamp!
  1306. I am an temporary variable of a method or block.!
  1307. !TempVar methodsFor: '*Compiler'!
  1308. isTempVar
  1309. ^ true
  1310. ! !
  1311. ScopeVar subclass: #UnknownVar
  1312. instanceVariableNames: ''
  1313. package:'Compiler'!
  1314. !UnknownVar commentStamp!
  1315. I am an unknown variable. Amber uses unknown variables as JavaScript globals!
  1316. !UnknownVar methodsFor: '*Compiler'!
  1317. isUnknownVar
  1318. ^ true
  1319. ! !
  1320. NodeVisitor subclass: #SemanticAnalyzer
  1321. instanceVariableNames: 'currentScope theClass classReferences messageSends superSends'
  1322. package:'Compiler'!
  1323. !SemanticAnalyzer commentStamp!
  1324. I semantically analyze the abstract syntax tree and annotate it with informations such as non local returns and variable scopes.!
  1325. !SemanticAnalyzer methodsFor: '*Compiler'!
  1326. classReferences
  1327. ^ classReferences ifNil: [ classReferences := Set new ]
  1328. !
  1329. messageSends
  1330. ^ messageSends ifNil: [ messageSends := Dictionary new ]
  1331. !
  1332. superSends
  1333. ^ superSends ifNil: [ superSends := Dictionary new ]
  1334. !
  1335. theClass
  1336. ^ theClass
  1337. !
  1338. theClass: aClass
  1339. theClass := aClass
  1340. ! !
  1341. !SemanticAnalyzer methodsFor: '*Compiler'!
  1342. errorShadowingVariable: aString
  1343. ShadowingVariableError new
  1344. variableName: aString;
  1345. signal
  1346. !
  1347. errorUnknownVariable: aNode
  1348. "Throw an error if the variable is undeclared in the global JS scope (i.e. window).
  1349. We allow four variable names in addition: `jQuery`, `window`, `process` and `global`
  1350. for nodejs and browser environments.
  1351. This is only to make sure compilation works on both browser-based and nodejs environments.
  1352. The ideal solution would be to use a pragma instead"
  1353. | identifier |
  1354. identifier := aNode value.
  1355. ((#('jQuery' 'window' 'document' 'process' 'global') includes: identifier) not
  1356. and: [ self isVariableGloballyUndefined: identifier ])
  1357. ifTrue: [
  1358. UnknownVariableError new
  1359. variableName: aNode value;
  1360. signal ]
  1361. ifFalse: [
  1362. currentScope methodScope unknownVariables add: aNode value ]
  1363. ! !
  1364. !SemanticAnalyzer methodsFor: '*Compiler'!
  1365. newBlockScope
  1366. ^ self newScopeOfClass: LexicalScope
  1367. !
  1368. newMethodScope
  1369. ^ self newScopeOfClass: MethodLexicalScope
  1370. !
  1371. newScopeOfClass: aLexicalScopeClass
  1372. ^ aLexicalScopeClass new
  1373. outerScope: currentScope;
  1374. yourself
  1375. ! !
  1376. !SemanticAnalyzer methodsFor: '*Compiler'!
  1377. popScope
  1378. currentScope ifNotNil: [
  1379. currentScope := currentScope outerScope ]
  1380. !
  1381. pushScope: aScope
  1382. aScope outerScope: currentScope.
  1383. currentScope := aScope
  1384. !
  1385. validateVariableScope: aString
  1386. "Validate the variable scope in by doing a recursive lookup, up to the method scope"
  1387. (currentScope lookupVariable: aString) ifNotNil: [
  1388. self errorShadowingVariable: aString ]
  1389. ! !
  1390. !SemanticAnalyzer methodsFor: '*Compiler'!
  1391. isVariableGloballyUndefined: aString
  1392. <return eval('typeof ' + aString + ' == "undefined"')>
  1393. ! !
  1394. !SemanticAnalyzer methodsFor: '*Compiler'!
  1395. visitAssignmentNode: aNode
  1396. super visitAssignmentNode: aNode.
  1397. aNode left beAssigned
  1398. !
  1399. visitBlockNode: aNode
  1400. self pushScope: self newBlockScope.
  1401. aNode scope: currentScope.
  1402. currentScope node: aNode.
  1403. aNode parameters do: [ :each |
  1404. self validateVariableScope: each.
  1405. currentScope addArg: each ].
  1406. super visitBlockNode: aNode.
  1407. self popScope
  1408. !
  1409. visitCascadeNode: aNode
  1410. "Populate the receiver into all children"
  1411. aNode nodes do: [ :each |
  1412. each receiver: aNode receiver ].
  1413. super visitCascadeNode: aNode.
  1414. aNode nodes first superSend ifTrue: [
  1415. aNode nodes do: [ :each | each superSend: true ]]
  1416. !
  1417. visitClassReferenceNode: aNode
  1418. self classReferences add: aNode value.
  1419. aNode binding: (ClassRefVar new name: aNode value; yourself)
  1420. !
  1421. visitMethodNode: aNode
  1422. self pushScope: self newMethodScope.
  1423. aNode scope: currentScope.
  1424. currentScope node: aNode.
  1425. self theClass allInstanceVariableNames do: [:each |
  1426. currentScope addIVar: each ].
  1427. aNode arguments do: [ :each |
  1428. self validateVariableScope: each.
  1429. currentScope addArg: each ].
  1430. super visitMethodNode: aNode.
  1431. aNode
  1432. classReferences: self classReferences;
  1433. messageSends: self messageSends keys;
  1434. superSends: self superSends keys.
  1435. self popScope
  1436. !
  1437. visitReturnNode: aNode
  1438. aNode scope: currentScope.
  1439. currentScope isMethodScope
  1440. ifTrue: [ currentScope localReturn: true ]
  1441. ifFalse: [ currentScope methodScope addNonLocalReturn: currentScope ].
  1442. super visitReturnNode: aNode
  1443. !
  1444. visitSendNode: aNode
  1445. aNode receiver value = 'super'
  1446. ifTrue: [
  1447. aNode superSend: true.
  1448. aNode receiver value: 'self'.
  1449. self superSends at: aNode selector ifAbsentPut: [ Set new ].
  1450. (self superSends at: aNode selector) add: aNode ]
  1451. ifFalse: [ (IRSendInliner inlinedSelectors includes: aNode selector) ifTrue: [
  1452. aNode shouldBeInlined: true.
  1453. aNode receiver shouldBeAliased: true ] ].
  1454. self messageSends at: aNode selector ifAbsentPut: [ Set new ].
  1455. (self messageSends at: aNode selector) add: aNode.
  1456. aNode index: (self messageSends at: aNode selector) size.
  1457. super visitSendNode: aNode
  1458. !
  1459. visitSequenceNode: aNode
  1460. aNode temps do: [ :each |
  1461. self validateVariableScope: each.
  1462. currentScope addTemp: each ].
  1463. super visitSequenceNode: aNode
  1464. !
  1465. visitVariableNode: aNode
  1466. "Bind a ScopeVar to aNode by doing a lookup in the current scope.
  1467. If no ScopeVar is found, bind a UnknowVar and throw an error"
  1468. aNode binding: ((currentScope lookupVariable: aNode) ifNil: [
  1469. self errorUnknownVariable: aNode.
  1470. UnknownVar new name: aNode value; yourself ])
  1471. ! !
  1472. !SemanticAnalyzer class methodsFor: '*Compiler'!
  1473. on: aClass
  1474. ^ self new
  1475. theClass: aClass;
  1476. yourself
  1477. ! !
  1478. NodeVisitor subclass: #IRASTTranslator
  1479. instanceVariableNames: 'source theClass method sequence nextAlias'
  1480. package:'Compiler'!
  1481. !IRASTTranslator commentStamp!
  1482. I am the AST (abstract syntax tree) visitor responsible for building the intermediate representation graph.
  1483. I rely on a builder object, instance of IRBuilder.!
  1484. !IRASTTranslator methodsFor: '*Compiler'!
  1485. method
  1486. ^ method
  1487. !
  1488. method: anIRMethod
  1489. method := anIRMethod
  1490. !
  1491. nextAlias
  1492. nextAlias ifNil: [ nextAlias := 0 ].
  1493. nextAlias := nextAlias + 1.
  1494. ^ nextAlias asString
  1495. !
  1496. sequence
  1497. ^ sequence
  1498. !
  1499. sequence: anIRSequence
  1500. sequence := anIRSequence
  1501. !
  1502. source
  1503. ^ source
  1504. !
  1505. source: aString
  1506. source := aString
  1507. !
  1508. theClass
  1509. ^ theClass
  1510. !
  1511. theClass: aClass
  1512. theClass := aClass
  1513. !
  1514. withSequence: aSequence do: aBlock
  1515. | outerSequence |
  1516. outerSequence := self sequence.
  1517. self sequence: aSequence.
  1518. aBlock value.
  1519. self sequence: outerSequence.
  1520. ^ aSequence
  1521. ! !
  1522. !IRASTTranslator methodsFor: '*Compiler'!
  1523. alias: aNode
  1524. | variable |
  1525. aNode isImmutable ifTrue: [ ^ self visit: aNode ].
  1526. variable := IRVariable new
  1527. variable: (AliasVar new name: '$', self nextAlias);
  1528. yourself.
  1529. self sequence add: (IRAssignment new
  1530. add: variable;
  1531. add: (self visit: aNode);
  1532. yourself).
  1533. self method internalVariables add: variable.
  1534. ^ variable
  1535. !
  1536. aliasTemporally: aCollection
  1537. "https://github.com/NicolasPetton/amber/issues/296
  1538. If a node is aliased, all preceding ones are aliased as well.
  1539. The tree is iterated twice. First we get the aliasing dependency,
  1540. then the aliasing itself is done"
  1541. | threshold result |
  1542. threshold := 0.
  1543. aCollection withIndexDo: [ :each :i |
  1544. each subtreeNeedsAliasing
  1545. ifTrue: [ threshold := i ]].
  1546. result := OrderedCollection new.
  1547. aCollection withIndexDo: [ :each :i |
  1548. result add: (i <= threshold
  1549. ifTrue: [ self alias: each ]
  1550. ifFalse: [ self visit: each ])].
  1551. ^result
  1552. !
  1553. visitAssignmentNode: aNode
  1554. | left right assignment |
  1555. right := self visit: aNode right.
  1556. left := self visit: aNode left.
  1557. self sequence add: (IRAssignment new
  1558. add: left;
  1559. add: right;
  1560. yourself).
  1561. ^ left
  1562. !
  1563. visitBlockNode: aNode
  1564. | closure |
  1565. closure := IRClosure new
  1566. arguments: aNode parameters;
  1567. scope: aNode scope;
  1568. yourself.
  1569. aNode scope temps do: [ :each |
  1570. closure add: (IRTempDeclaration new
  1571. name: each name;
  1572. scope: aNode scope;
  1573. yourself) ].
  1574. aNode nodes do: [ :each | closure add: (self visit: each) ].
  1575. ^ closure
  1576. !
  1577. visitBlockSequenceNode: aNode
  1578. ^ self
  1579. withSequence: IRBlockSequence new
  1580. do: [
  1581. aNode nodes ifNotEmpty: [
  1582. aNode nodes allButLast do: [ :each |
  1583. self sequence add: (self visit: each) ].
  1584. aNode nodes last isReturnNode
  1585. ifFalse: [ self sequence add: (IRBlockReturn new add: (self visit: aNode nodes last); yourself) ]
  1586. ifTrue: [ self sequence add: (self visit: aNode nodes last) ]]]
  1587. !
  1588. visitCascadeNode: aNode
  1589. | alias |
  1590. aNode receiver isImmutable ifFalse: [
  1591. alias := self alias: aNode receiver.
  1592. aNode nodes do: [ :each |
  1593. each receiver: (VariableNode new binding: alias variable) ]].
  1594. aNode nodes allButLast do: [ :each |
  1595. self sequence add: (self visit: each) ].
  1596. ^ self alias: aNode nodes last
  1597. !
  1598. visitDynamicArrayNode: aNode
  1599. | array |
  1600. array := IRDynamicArray new.
  1601. (self aliasTemporally: aNode nodes) do: [:each | array add: each].
  1602. ^ array
  1603. !
  1604. visitDynamicDictionaryNode: aNode
  1605. | dictionary |
  1606. dictionary := IRDynamicDictionary new.
  1607. (self aliasTemporally: aNode nodes) do: [:each | dictionary add: each].
  1608. ^ dictionary
  1609. !
  1610. visitJSStatementNode: aNode
  1611. ^ IRVerbatim new
  1612. source: aNode source;
  1613. yourself
  1614. !
  1615. visitMethodNode: aNode
  1616. self method: (IRMethod new
  1617. source: self source;
  1618. theClass: self theClass;
  1619. arguments: aNode arguments;
  1620. selector: aNode selector;
  1621. messageSends: aNode messageSends;
  1622. superSends: aNode superSends;
  1623. classReferences: aNode classReferences;
  1624. scope: aNode scope;
  1625. yourself).
  1626. aNode scope temps do: [ :each |
  1627. self method add: (IRTempDeclaration new
  1628. name: each name;
  1629. scope: aNode scope;
  1630. yourself) ].
  1631. aNode nodes do: [ :each | self method add: (self visit: each) ].
  1632. aNode scope hasLocalReturn ifFalse: [
  1633. (self method add: IRReturn new) add: (IRVariable new
  1634. variable: (aNode scope pseudoVars at: 'self');
  1635. yourself) ].
  1636. ^ self method
  1637. !
  1638. visitReturnNode: aNode
  1639. | return |
  1640. return := aNode nonLocalReturn
  1641. ifTrue: [ IRNonLocalReturn new ]
  1642. ifFalse: [ IRReturn new ].
  1643. return scope: aNode scope.
  1644. aNode nodes do: [ :each |
  1645. return add: (self alias: each) ].
  1646. ^ return
  1647. !
  1648. visitSendNode: aNode
  1649. | send all receiver arguments |
  1650. send := IRSend new.
  1651. send
  1652. selector: aNode selector;
  1653. index: aNode index.
  1654. aNode superSend ifTrue: [ send classSend: self theClass superclass ].
  1655. all := self aliasTemporally: { aNode receiver }, aNode arguments.
  1656. receiver := all first.
  1657. arguments := all allButFirst.
  1658. send add: receiver.
  1659. arguments do: [ :each | send add: each ].
  1660. ^ send
  1661. !
  1662. visitSequenceNode: aNode
  1663. ^ self
  1664. withSequence: IRSequence new
  1665. do: [
  1666. aNode nodes do: [ :each | | instruction |
  1667. instruction := self visit: each.
  1668. instruction isVariable ifFalse: [
  1669. self sequence add: instruction ]]]
  1670. !
  1671. visitValueNode: aNode
  1672. ^ IRValue new
  1673. value: aNode value;
  1674. yourself
  1675. !
  1676. visitVariableNode: aNode
  1677. ^ IRVariable new
  1678. variable: aNode binding;
  1679. yourself
  1680. ! !
  1681. Object subclass: #IRInstruction
  1682. instanceVariableNames: 'parent instructions'
  1683. package:'Compiler'!
  1684. !IRInstruction commentStamp!
  1685. I am the abstract root class of the IR (intermediate representation) instructions class hierarchy.
  1686. The IR graph is used to emit JavaScript code using a JSStream.!
  1687. !IRInstruction methodsFor: '*Compiler'!
  1688. instructions
  1689. ^ instructions ifNil: [ instructions := OrderedCollection new ]
  1690. !
  1691. method
  1692. ^ self parent method
  1693. !
  1694. parent
  1695. ^ parent
  1696. !
  1697. parent: anIRInstruction
  1698. parent := anIRInstruction
  1699. ! !
  1700. !IRInstruction methodsFor: '*Compiler'!
  1701. add: anObject
  1702. anObject parent: self.
  1703. ^ self instructions add: anObject
  1704. !
  1705. remove
  1706. self parent remove: self
  1707. !
  1708. remove: anIRInstruction
  1709. self instructions remove: anIRInstruction
  1710. !
  1711. replace: anIRInstruction with: anotherIRInstruction
  1712. anotherIRInstruction parent: self.
  1713. self instructions
  1714. at: (self instructions indexOf: anIRInstruction)
  1715. put: anotherIRInstruction
  1716. !
  1717. replaceWith: anIRInstruction
  1718. self parent replace: self with: anIRInstruction
  1719. ! !
  1720. !IRInstruction methodsFor: '*Compiler'!
  1721. canBeAssigned
  1722. ^ true
  1723. !
  1724. isClosure
  1725. ^ false
  1726. !
  1727. isInlined
  1728. ^ false
  1729. !
  1730. isLocalReturn
  1731. ^ false
  1732. !
  1733. isMethod
  1734. ^ false
  1735. !
  1736. isReturn
  1737. ^ false
  1738. !
  1739. isSend
  1740. ^ false
  1741. !
  1742. isSequence
  1743. ^ false
  1744. !
  1745. isTempDeclaration
  1746. ^ false
  1747. !
  1748. isVariable
  1749. ^ false
  1750. ! !
  1751. !IRInstruction methodsFor: '*Compiler'!
  1752. accept: aVisitor
  1753. ^ aVisitor visitIRInstruction: self
  1754. ! !
  1755. !IRInstruction class methodsFor: '*Compiler'!
  1756. on: aBuilder
  1757. ^ self new
  1758. builder: aBuilder;
  1759. yourself
  1760. ! !
  1761. IRInstruction subclass: #IRAssignment
  1762. instanceVariableNames: ''
  1763. package:'Compiler'!
  1764. !IRAssignment methodsFor: '*Compiler'!
  1765. accept: aVisitor
  1766. ^ aVisitor visitIRAssignment: self
  1767. ! !
  1768. IRInstruction subclass: #IRDynamicArray
  1769. instanceVariableNames: ''
  1770. package:'Compiler'!
  1771. !IRDynamicArray methodsFor: '*Compiler'!
  1772. accept: aVisitor
  1773. ^ aVisitor visitIRDynamicArray: self
  1774. ! !
  1775. IRInstruction subclass: #IRDynamicDictionary
  1776. instanceVariableNames: ''
  1777. package:'Compiler'!
  1778. !IRDynamicDictionary methodsFor: '*Compiler'!
  1779. accept: aVisitor
  1780. ^ aVisitor visitIRDynamicDictionary: self
  1781. ! !
  1782. IRInstruction subclass: #IRScopedInstruction
  1783. instanceVariableNames: 'scope'
  1784. package:'Compiler'!
  1785. !IRScopedInstruction methodsFor: '*Compiler'!
  1786. scope
  1787. ^ scope
  1788. !
  1789. scope: aScope
  1790. scope := aScope
  1791. ! !
  1792. IRScopedInstruction subclass: #IRClosureInstruction
  1793. instanceVariableNames: 'arguments'
  1794. package:'Compiler'!
  1795. !IRClosureInstruction methodsFor: '*Compiler'!
  1796. arguments
  1797. ^ arguments ifNil: [ #() ]
  1798. !
  1799. arguments: aCollection
  1800. arguments := aCollection
  1801. !
  1802. locals
  1803. ^ self arguments copy
  1804. addAll: (self tempDeclarations collect: [ :each | each name ]);
  1805. yourself
  1806. !
  1807. scope: aScope
  1808. super scope: aScope.
  1809. aScope instruction: self
  1810. !
  1811. tempDeclarations
  1812. ^ self instructions select: [ :each |
  1813. each isTempDeclaration ]
  1814. ! !
  1815. IRClosureInstruction subclass: #IRClosure
  1816. instanceVariableNames: ''
  1817. package:'Compiler'!
  1818. !IRClosure methodsFor: '*Compiler'!
  1819. sequence
  1820. ^ self instructions last
  1821. ! !
  1822. !IRClosure methodsFor: '*Compiler'!
  1823. isClosure
  1824. ^ true
  1825. ! !
  1826. !IRClosure methodsFor: '*Compiler'!
  1827. accept: aVisitor
  1828. ^ aVisitor visitIRClosure: self
  1829. ! !
  1830. IRClosureInstruction subclass: #IRMethod
  1831. instanceVariableNames: 'theClass source selector classReferences messageSends superSends internalVariables'
  1832. package:'Compiler'!
  1833. !IRMethod commentStamp!
  1834. I am a method instruction!
  1835. !IRMethod methodsFor: '*Compiler'!
  1836. classReferences
  1837. ^ classReferences
  1838. !
  1839. classReferences: aCollection
  1840. classReferences := aCollection
  1841. !
  1842. internalVariables
  1843. ^ internalVariables ifNil: [ internalVariables := Set new ]
  1844. !
  1845. isMethod
  1846. ^ true
  1847. !
  1848. messageSends
  1849. ^ messageSends
  1850. !
  1851. messageSends: aCollection
  1852. messageSends := aCollection
  1853. !
  1854. method
  1855. ^ self
  1856. !
  1857. selector
  1858. ^ selector
  1859. !
  1860. selector: aString
  1861. selector := aString
  1862. !
  1863. source
  1864. ^ source
  1865. !
  1866. source: aString
  1867. source := aString
  1868. !
  1869. superSends
  1870. ^ superSends
  1871. !
  1872. superSends: aCollection
  1873. superSends := aCollection
  1874. !
  1875. theClass
  1876. ^ theClass
  1877. !
  1878. theClass: aClass
  1879. theClass := aClass
  1880. ! !
  1881. !IRMethod methodsFor: '*Compiler'!
  1882. accept: aVisitor
  1883. ^ aVisitor visitIRMethod: self
  1884. ! !
  1885. IRScopedInstruction subclass: #IRReturn
  1886. instanceVariableNames: ''
  1887. package:'Compiler'!
  1888. !IRReturn commentStamp!
  1889. I am a local return instruction.!
  1890. !IRReturn methodsFor: '*Compiler'!
  1891. canBeAssigned
  1892. ^ false
  1893. !
  1894. isBlockReturn
  1895. ^ false
  1896. !
  1897. isLocalReturn
  1898. ^ true
  1899. !
  1900. isNonLocalReturn
  1901. ^ self isLocalReturn not
  1902. !
  1903. isReturn
  1904. ^ true
  1905. ! !
  1906. !IRReturn methodsFor: '*Compiler'!
  1907. accept: aVisitor
  1908. ^ aVisitor visitIRReturn: self
  1909. ! !
  1910. IRReturn subclass: #IRBlockReturn
  1911. instanceVariableNames: ''
  1912. package:'Compiler'!
  1913. !IRBlockReturn commentStamp!
  1914. Smalltalk blocks return their last statement. I am a implicit block return instruction.!
  1915. !IRBlockReturn methodsFor: '*Compiler'!
  1916. isBlockReturn
  1917. ^ true
  1918. ! !
  1919. !IRBlockReturn methodsFor: '*Compiler'!
  1920. accept: aVisitor
  1921. ^ aVisitor visitIRBlockReturn: self
  1922. ! !
  1923. IRReturn subclass: #IRNonLocalReturn
  1924. instanceVariableNames: ''
  1925. package:'Compiler'!
  1926. !IRNonLocalReturn commentStamp!
  1927. I am a non local return instruction.
  1928. Non local returns are handled using a try/catch JS statement.
  1929. See IRNonLocalReturnHandling class!
  1930. !IRNonLocalReturn methodsFor: '*Compiler'!
  1931. isLocalReturn
  1932. ^ false
  1933. ! !
  1934. !IRNonLocalReturn methodsFor: '*Compiler'!
  1935. accept: aVisitor
  1936. ^ aVisitor visitIRNonLocalReturn: self
  1937. ! !
  1938. IRScopedInstruction subclass: #IRTempDeclaration
  1939. instanceVariableNames: 'name'
  1940. package:'Compiler'!
  1941. !IRTempDeclaration methodsFor: '*Compiler'!
  1942. name
  1943. ^ name
  1944. !
  1945. name: aString
  1946. name := aString
  1947. ! !
  1948. !IRTempDeclaration methodsFor: '*Compiler'!
  1949. isTempDeclaration
  1950. ^ true
  1951. ! !
  1952. !IRTempDeclaration methodsFor: '*Compiler'!
  1953. accept: aVisitor
  1954. ^ aVisitor visitIRTempDeclaration: self
  1955. ! !
  1956. IRInstruction subclass: #IRSend
  1957. instanceVariableNames: 'selector classSend index'
  1958. package:'Compiler'!
  1959. !IRSend commentStamp!
  1960. I am a message send instruction.!
  1961. !IRSend methodsFor: '*Compiler'!
  1962. classSend
  1963. ^ classSend
  1964. !
  1965. classSend: aClass
  1966. classSend := aClass
  1967. !
  1968. index
  1969. ^ index
  1970. !
  1971. index: anInteger
  1972. index := anInteger
  1973. !
  1974. javascriptSelector
  1975. ^ self classSend
  1976. ifNil: [ self selector asSelector ]
  1977. ifNotNil: [ self selector asSuperSelector ]
  1978. !
  1979. selector
  1980. ^ selector
  1981. !
  1982. selector: aString
  1983. selector := aString
  1984. ! !
  1985. !IRSend methodsFor: '*Compiler'!
  1986. isSend
  1987. ^ true
  1988. ! !
  1989. !IRSend methodsFor: '*Compiler'!
  1990. accept: aVisitor
  1991. ^ aVisitor visitIRSend: self
  1992. ! !
  1993. IRInstruction subclass: #IRSequence
  1994. instanceVariableNames: ''
  1995. package:'Compiler'!
  1996. !IRSequence methodsFor: '*Compiler'!
  1997. isSequence
  1998. ^ true
  1999. ! !
  2000. !IRSequence methodsFor: '*Compiler'!
  2001. accept: aVisitor
  2002. ^ aVisitor visitIRSequence: self
  2003. ! !
  2004. IRSequence subclass: #IRBlockSequence
  2005. instanceVariableNames: ''
  2006. package:'Compiler'!
  2007. !IRBlockSequence methodsFor: '*Compiler'!
  2008. accept: aVisitor
  2009. ^ aVisitor visitIRBlockSequence: self
  2010. ! !
  2011. IRInstruction subclass: #IRValue
  2012. instanceVariableNames: 'value'
  2013. package:'Compiler'!
  2014. !IRValue commentStamp!
  2015. I am the simplest possible instruction. I represent a value.!
  2016. !IRValue methodsFor: '*Compiler'!
  2017. value
  2018. ^value
  2019. !
  2020. value: aString
  2021. value := aString
  2022. ! !
  2023. !IRValue methodsFor: '*Compiler'!
  2024. accept: aVisitor
  2025. ^ aVisitor visitIRValue: self
  2026. ! !
  2027. IRInstruction subclass: #IRVariable
  2028. instanceVariableNames: 'variable'
  2029. package:'Compiler'!
  2030. !IRVariable commentStamp!
  2031. I am a variable instruction.!
  2032. !IRVariable methodsFor: '*Compiler'!
  2033. variable
  2034. ^ variable
  2035. !
  2036. variable: aScopeVariable
  2037. variable := aScopeVariable
  2038. ! !
  2039. !IRVariable methodsFor: '*Compiler'!
  2040. isVariable
  2041. ^ true
  2042. ! !
  2043. !IRVariable methodsFor: '*Compiler'!
  2044. accept: aVisitor
  2045. ^ aVisitor visitIRVariable: self
  2046. ! !
  2047. IRInstruction subclass: #IRVerbatim
  2048. instanceVariableNames: 'source'
  2049. package:'Compiler'!
  2050. !IRVerbatim methodsFor: '*Compiler'!
  2051. source
  2052. ^ source
  2053. !
  2054. source: aString
  2055. source := aString
  2056. ! !
  2057. !IRVerbatim methodsFor: '*Compiler'!
  2058. accept: aVisitor
  2059. ^ aVisitor visitIRVerbatim: self
  2060. ! !
  2061. Object subclass: #IRVisitor
  2062. instanceVariableNames: ''
  2063. package:'Compiler'!
  2064. !IRVisitor methodsFor: '*Compiler'!
  2065. visit: anIRInstruction
  2066. ^ anIRInstruction accept: self
  2067. !
  2068. visitIRAssignment: anIRAssignment
  2069. ^ self visitIRInstruction: anIRAssignment
  2070. !
  2071. visitIRBlockReturn: anIRBlockReturn
  2072. ^ self visitIRReturn: anIRBlockReturn
  2073. !
  2074. visitIRBlockSequence: anIRBlockSequence
  2075. ^ self visitIRSequence: anIRBlockSequence
  2076. !
  2077. visitIRClosure: anIRClosure
  2078. ^ self visitIRInstruction: anIRClosure
  2079. !
  2080. visitIRDynamicArray: anIRDynamicArray
  2081. ^ self visitIRInstruction: anIRDynamicArray
  2082. !
  2083. visitIRDynamicDictionary: anIRDynamicDictionary
  2084. ^ self visitIRInstruction: anIRDynamicDictionary
  2085. !
  2086. visitIRInlinedClosure: anIRInlinedClosure
  2087. ^ self visitIRClosure: anIRInlinedClosure
  2088. !
  2089. visitIRInlinedSequence: anIRInlinedSequence
  2090. ^ self visitIRSequence: anIRInlinedSequence
  2091. !
  2092. visitIRInstruction: anIRInstruction
  2093. anIRInstruction instructions do: [ :each | self visit: each ].
  2094. ^ anIRInstruction
  2095. !
  2096. visitIRMethod: anIRMethod
  2097. ^ self visitIRInstruction: anIRMethod
  2098. !
  2099. visitIRNonLocalReturn: anIRNonLocalReturn
  2100. ^ self visitIRInstruction: anIRNonLocalReturn
  2101. !
  2102. visitIRNonLocalReturnHandling: anIRNonLocalReturnHandling
  2103. ^ self visitIRInstruction: anIRNonLocalReturnHandling
  2104. !
  2105. visitIRReturn: anIRReturn
  2106. ^ self visitIRInstruction: anIRReturn
  2107. !
  2108. visitIRSend: anIRSend
  2109. ^ self visitIRInstruction: anIRSend
  2110. !
  2111. visitIRSequence: anIRSequence
  2112. ^ self visitIRInstruction: anIRSequence
  2113. !
  2114. visitIRTempDeclaration: anIRTempDeclaration
  2115. ^ self visitIRInstruction: anIRTempDeclaration
  2116. !
  2117. visitIRValue: anIRValue
  2118. ^ self visitIRInstruction: anIRValue
  2119. !
  2120. visitIRVariable: anIRVariable
  2121. ^ self visitIRInstruction: anIRVariable
  2122. !
  2123. visitIRVerbatim: anIRVerbatim
  2124. ^ self visitIRInstruction: anIRVerbatim
  2125. ! !
  2126. IRVisitor subclass: #IRJSTranslator
  2127. instanceVariableNames: 'stream'
  2128. package:'Compiler'!
  2129. !IRJSTranslator methodsFor: '*Compiler'!
  2130. contents
  2131. ^ self stream contents
  2132. !
  2133. stream
  2134. ^ stream
  2135. !
  2136. stream: aStream
  2137. stream := aStream
  2138. ! !
  2139. !IRJSTranslator methodsFor: '*Compiler'!
  2140. initialize
  2141. super initialize.
  2142. stream := JSStream new.
  2143. ! !
  2144. !IRJSTranslator methodsFor: '*Compiler'!
  2145. visitIRAssignment: anIRAssignment
  2146. self visit: anIRAssignment instructions first.
  2147. self stream nextPutAssignment.
  2148. self visit: anIRAssignment instructions last.
  2149. !
  2150. visitIRClosure: anIRClosure
  2151. self stream
  2152. nextPutClosureWith: [
  2153. self stream nextPutVars: (anIRClosure tempDeclarations collect: [ :each |
  2154. each name asVariableName ]).
  2155. self stream
  2156. nextPutBlockContextFor: anIRClosure
  2157. during: [ super visitIRClosure: anIRClosure ] ]
  2158. arguments: anIRClosure arguments
  2159. !
  2160. visitIRDynamicArray: anIRDynamicArray
  2161. self stream nextPutAll: '['.
  2162. anIRDynamicArray instructions
  2163. do: [ :each | self visit: each ]
  2164. separatedBy: [ self stream nextPutAll: ',' ].
  2165. stream nextPutAll: ']'
  2166. !
  2167. visitIRDynamicDictionary: anIRDynamicDictionary
  2168. self stream nextPutAll: 'smalltalk.HashedCollection._fromPairs_(['.
  2169. anIRDynamicDictionary instructions
  2170. do: [ :each | self visit: each ]
  2171. separatedBy: [self stream nextPutAll: ',' ].
  2172. self stream nextPutAll: '])'
  2173. !
  2174. visitIRMethod: anIRMethod
  2175. self stream
  2176. nextPutMethodDeclaration: anIRMethod
  2177. with: [ self stream
  2178. nextPutFunctionWith: [
  2179. self stream nextPutVars: (anIRMethod tempDeclarations collect: [ :each |
  2180. each name asVariableName ]).
  2181. self stream nextPutContextFor: anIRMethod during: [
  2182. anIRMethod internalVariables notEmpty ifTrue: [
  2183. self stream nextPutVars: (anIRMethod internalVariables asArray collect: [ :each |
  2184. each variable alias ]) ].
  2185. anIRMethod scope hasNonLocalReturn
  2186. ifTrue: [
  2187. self stream nextPutNonLocalReturnHandlingWith: [
  2188. super visitIRMethod: anIRMethod ]]
  2189. ifFalse: [ super visitIRMethod: anIRMethod ]]]
  2190. arguments: anIRMethod arguments ]
  2191. !
  2192. visitIRNonLocalReturn: anIRNonLocalReturn
  2193. self stream nextPutNonLocalReturnWith: [
  2194. super visitIRNonLocalReturn: anIRNonLocalReturn ]
  2195. !
  2196. visitIRReturn: anIRReturn
  2197. self stream nextPutReturnWith: [
  2198. super visitIRReturn: anIRReturn ]
  2199. !
  2200. visitIRSend: anIRSend
  2201. anIRSend classSend
  2202. ifNil: [
  2203. self stream nextPutAll: '_st('.
  2204. self visit: anIRSend instructions first.
  2205. self stream nextPutAll: ').', anIRSend selector asSelector, '('.
  2206. anIRSend instructions allButFirst
  2207. do: [ :each | self visit: each ]
  2208. separatedBy: [ self stream nextPutAll: ',' ].
  2209. self stream nextPutAll: ')' ]
  2210. ifNotNil: [
  2211. self stream
  2212. nextPutAll: anIRSend classSend asJavascript, '.fn.prototype.';
  2213. nextPutAll: anIRSend selector asSelector, '.apply(';
  2214. nextPutAll: '_st('.
  2215. self visit: anIRSend instructions first.
  2216. self stream nextPutAll: '), ['.
  2217. anIRSend instructions allButFirst
  2218. do: [ :each | self visit: each ]
  2219. separatedBy: [ self stream nextPutAll: ',' ].
  2220. self stream nextPutAll: '])' ]
  2221. !
  2222. visitIRSequence: anIRSequence
  2223. self stream nextPutSequenceWith: [
  2224. anIRSequence instructions do: [ :each |
  2225. self stream nextPutStatementWith: (self visit: each) ]]
  2226. !
  2227. visitIRTempDeclaration: anIRTempDeclaration
  2228. "self stream
  2229. nextPutAll: 'var ', anIRTempDeclaration name asVariableName, ';';
  2230. lf"
  2231. !
  2232. visitIRValue: anIRValue
  2233. self stream nextPutAll: anIRValue value asJavascript
  2234. !
  2235. visitIRVariable: anIRVariable
  2236. anIRVariable variable name = 'thisContext'
  2237. ifTrue: [ self stream nextPutAll: 'smalltalk.getThisContext()' ]
  2238. ifFalse: [ self stream nextPutAll: anIRVariable variable alias ]
  2239. !
  2240. visitIRVerbatim: anIRVerbatim
  2241. self stream nextPutStatementWith: [
  2242. self stream nextPutAll: anIRVerbatim source ]
  2243. ! !
  2244. Object subclass: #JSStream
  2245. instanceVariableNames: 'stream'
  2246. package:'Compiler'!
  2247. !JSStream methodsFor: '*Compiler'!
  2248. contents
  2249. ^ stream contents
  2250. ! !
  2251. !JSStream methodsFor: '*Compiler'!
  2252. initialize
  2253. super initialize.
  2254. stream := '' writeStream.
  2255. ! !
  2256. !JSStream methodsFor: '*Compiler'!
  2257. lf
  2258. stream lf
  2259. !
  2260. nextPut: aString
  2261. stream nextPut: aString
  2262. !
  2263. nextPutAll: aString
  2264. stream nextPutAll: aString
  2265. !
  2266. nextPutAssignment
  2267. stream nextPutAll: '='
  2268. !
  2269. nextPutBlockContextFor: anIRClosure during: aBlock
  2270. self
  2271. nextPutAll: 'return smalltalk.withContext(function(', anIRClosure scope alias, ') {';
  2272. nextPutAll: String cr.
  2273. aBlock value.
  2274. self
  2275. nextPutAll: '}, function(', anIRClosure scope alias, ') {';
  2276. nextPutAll: anIRClosure scope alias, '.fillBlock({'.
  2277. anIRClosure locals
  2278. do: [ :each |
  2279. self
  2280. nextPutAll: each asVariableName;
  2281. nextPutAll: ':';
  2282. nextPutAll: each asVariableName]
  2283. separatedBy: [ self nextPutAll: ',' ].
  2284. self
  2285. nextPutAll: '},';
  2286. nextPutAll: anIRClosure method scope alias, ')})'
  2287. !
  2288. nextPutClosureWith: aBlock arguments: anArray
  2289. stream nextPutAll: '(function('.
  2290. anArray
  2291. do: [ :each | stream nextPutAll: each asVariableName ]
  2292. separatedBy: [ stream nextPut: ',' ].
  2293. stream nextPutAll: '){'; lf.
  2294. aBlock value.
  2295. stream nextPutAll: '})'
  2296. !
  2297. nextPutContextFor: aMethod during: aBlock
  2298. self
  2299. nextPutAll: 'return smalltalk.withContext(function(', aMethod scope alias, ') { ';
  2300. nextPutAll: String cr.
  2301. aBlock value.
  2302. self
  2303. nextPutAll: '}, function(', aMethod scope alias, ') {', aMethod scope alias;
  2304. nextPutAll: '.fill(self,', aMethod selector asJavascript, ',{'.
  2305. aMethod locals
  2306. do: [ :each |
  2307. self
  2308. nextPutAll: each asVariableName;
  2309. nextPutAll: ':';
  2310. nextPutAll: each asVariableName]
  2311. separatedBy: [ self nextPutAll: ',' ].
  2312. self
  2313. nextPutAll: '}, ';
  2314. nextPutAll: aMethod theClass asJavascript;
  2315. nextPutAll: ')})'
  2316. !
  2317. nextPutFunctionWith: aBlock arguments: anArray
  2318. stream nextPutAll: 'fn: function('.
  2319. anArray
  2320. do: [ :each | stream nextPutAll: each asVariableName ]
  2321. separatedBy: [ stream nextPut: ',' ].
  2322. stream nextPutAll: '){'; lf.
  2323. stream nextPutAll: 'var self=this;'; lf.
  2324. aBlock value.
  2325. stream nextPutAll: '}'
  2326. !
  2327. nextPutIf: aBlock with: anotherBlock
  2328. stream nextPutAll: 'if('.
  2329. aBlock value.
  2330. stream nextPutAll: '){'; lf.
  2331. anotherBlock value.
  2332. stream nextPutAll: '}'
  2333. !
  2334. nextPutIfElse: aBlock with: ifBlock with: elseBlock
  2335. stream nextPutAll: 'if('.
  2336. aBlock value.
  2337. stream nextPutAll: '){'; lf.
  2338. ifBlock value.
  2339. stream nextPutAll: '} else {'; lf.
  2340. elseBlock value.
  2341. stream nextPutAll: '}'
  2342. !
  2343. nextPutMethodDeclaration: aMethod with: aBlock
  2344. stream
  2345. nextPutAll: 'smalltalk.method({'; lf;
  2346. nextPutAll: 'selector: "', aMethod selector, '",'; lf;
  2347. nextPutAll: 'source: ', aMethod source asJavascript, ',';lf.
  2348. aBlock value.
  2349. stream
  2350. nextPutAll: ',', String lf, 'messageSends: ';
  2351. nextPutAll: aMethod messageSends asArray asJavascript, ','; lf;
  2352. nextPutAll: 'args: ', (aMethod arguments collect: [ :each | each value ]) asArray asJavascript, ','; lf;
  2353. nextPutAll: 'referencedClasses: ['.
  2354. aMethod classReferences
  2355. do: [:each | stream nextPutAll: each asJavascript]
  2356. separatedBy: [stream nextPutAll: ','].
  2357. stream
  2358. nextPutAll: ']';
  2359. nextPutAll: '})'
  2360. !
  2361. nextPutNonLocalReturnHandlingWith: aBlock
  2362. stream
  2363. nextPutAll: 'var $early={};'; lf;
  2364. nextPutAll: 'try {'; lf.
  2365. aBlock value.
  2366. stream
  2367. nextPutAll: '}'; lf;
  2368. nextPutAll: 'catch(e) {if(e===$early)return e[0]; throw e}'; lf
  2369. !
  2370. nextPutNonLocalReturnWith: aBlock
  2371. stream nextPutAll: 'throw $early=['.
  2372. aBlock value.
  2373. stream nextPutAll: ']'
  2374. !
  2375. nextPutReturn
  2376. stream nextPutAll: 'return '
  2377. !
  2378. nextPutReturnWith: aBlock
  2379. self nextPutReturn.
  2380. aBlock value
  2381. !
  2382. nextPutSequenceWith: aBlock
  2383. "stream
  2384. nextPutAll: 'switch(smalltalk.thisContext.pc){'; lf."
  2385. aBlock value.
  2386. "stream
  2387. nextPutAll: '};'; lf"
  2388. !
  2389. nextPutStatement: anInteger with: aBlock
  2390. stream nextPutAll: 'case ', anInteger asString, ':'; lf.
  2391. self nextPutStatementWith: aBlock.
  2392. stream nextPutAll: 'smalltalk.thisContext.pc=', (anInteger + 1) asString, ';'; lf
  2393. !
  2394. nextPutStatementWith: aBlock
  2395. aBlock value.
  2396. stream nextPutAll: ';'; lf
  2397. !
  2398. nextPutVar: aString
  2399. stream nextPutAll: 'var ', aString, ';'; lf
  2400. !
  2401. nextPutVars: aCollection
  2402. aCollection ifEmpty: [ ^self ].
  2403. stream nextPutAll: 'var '.
  2404. aCollection
  2405. do: [ :each | stream nextPutAll: each ]
  2406. separatedBy: [ stream nextPutAll: ',' ].
  2407. stream nextPutAll: ';'; lf
  2408. ! !
  2409. !BlockClosure methodsFor: '*Compiler'!
  2410. appendToInstruction: anIRInstruction
  2411. anIRInstruction appendBlock: self
  2412. ! !
  2413. !String methodsFor: '*Compiler'!
  2414. asVariableName
  2415. ^ (Smalltalk current reservedWords includes: self)
  2416. ifTrue: [ self, '_' ]
  2417. ifFalse: [ self ]
  2418. ! !
  2419. IRAssignment subclass: #IRInlinedAssignment
  2420. instanceVariableNames: ''
  2421. package:'Compiler'!
  2422. !IRInlinedAssignment commentStamp!
  2423. I represent an inlined assignment instruction.!
  2424. !IRInlinedAssignment methodsFor: '*Compiler'!
  2425. isInlined
  2426. ^ true
  2427. ! !
  2428. !IRInlinedAssignment methodsFor: '*Compiler'!
  2429. accept: aVisitor
  2430. ^ aVisitor visitIRInlinedAssignment: self
  2431. ! !
  2432. IRClosure subclass: #IRInlinedClosure
  2433. instanceVariableNames: ''
  2434. package:'Compiler'!
  2435. !IRInlinedClosure commentStamp!
  2436. I represent an inlined closure instruction.!
  2437. !IRInlinedClosure methodsFor: '*Compiler'!
  2438. isInlined
  2439. ^ true
  2440. ! !
  2441. !IRInlinedClosure methodsFor: '*Compiler'!
  2442. accept: aVisitor
  2443. aVisitor visitIRInlinedClosure: self
  2444. ! !
  2445. IRReturn subclass: #IRInlinedReturn
  2446. instanceVariableNames: ''
  2447. package:'Compiler'!
  2448. !IRInlinedReturn commentStamp!
  2449. I represent an inlined local return instruction.!
  2450. !IRInlinedReturn methodsFor: '*Compiler'!
  2451. isInlined
  2452. ^ true
  2453. ! !
  2454. !IRInlinedReturn methodsFor: '*Compiler'!
  2455. accept: aVisitor
  2456. ^ aVisitor visitIRInlinedReturn: self
  2457. ! !
  2458. IRInlinedReturn subclass: #IRInlinedNonLocalReturn
  2459. instanceVariableNames: ''
  2460. package:'Compiler'!
  2461. !IRInlinedNonLocalReturn commentStamp!
  2462. I represent an inlined non local return instruction.!
  2463. !IRInlinedNonLocalReturn methodsFor: '*Compiler'!
  2464. isInlined
  2465. ^ true
  2466. ! !
  2467. !IRInlinedNonLocalReturn methodsFor: '*Compiler'!
  2468. accept: aVisitor
  2469. ^ aVisitor visitIRInlinedNonLocalReturn: self
  2470. ! !
  2471. IRSend subclass: #IRInlinedSend
  2472. instanceVariableNames: ''
  2473. package:'Compiler'!
  2474. !IRInlinedSend commentStamp!
  2475. I am the abstract super class of inlined message send instructions.!
  2476. !IRInlinedSend methodsFor: '*Compiler'!
  2477. isInlined
  2478. ^ true
  2479. ! !
  2480. !IRInlinedSend methodsFor: '*Compiler'!
  2481. accept: aVisitor
  2482. aVisitor visitInlinedSend: self
  2483. ! !
  2484. IRInlinedSend subclass: #IRInlinedIfFalse
  2485. instanceVariableNames: ''
  2486. package:'Compiler'!
  2487. !IRInlinedIfFalse methodsFor: '*Compiler'!
  2488. accept: aVisitor
  2489. aVisitor visitIRInlinedIfFalse: self
  2490. ! !
  2491. IRInlinedSend subclass: #IRInlinedIfNilIfNotNil
  2492. instanceVariableNames: ''
  2493. package:'Compiler'!
  2494. !IRInlinedIfNilIfNotNil methodsFor: '*Compiler'!
  2495. accept: aVisitor
  2496. aVisitor visitIRInlinedIfNilIfNotNil: self
  2497. ! !
  2498. IRInlinedSend subclass: #IRInlinedIfTrue
  2499. instanceVariableNames: ''
  2500. package:'Compiler'!
  2501. !IRInlinedIfTrue methodsFor: '*Compiler'!
  2502. accept: aVisitor
  2503. aVisitor visitIRInlinedIfTrue: self
  2504. ! !
  2505. IRInlinedSend subclass: #IRInlinedIfTrueIfFalse
  2506. instanceVariableNames: ''
  2507. package:'Compiler'!
  2508. !IRInlinedIfTrueIfFalse methodsFor: '*Compiler'!
  2509. accept: aVisitor
  2510. aVisitor visitIRInlinedIfTrueIfFalse: self
  2511. ! !
  2512. IRBlockSequence subclass: #IRInlinedSequence
  2513. instanceVariableNames: ''
  2514. package:'Compiler'!
  2515. !IRInlinedSequence commentStamp!
  2516. I represent a (block) sequence inside an inlined closure instruction (instance of `IRInlinedClosure`).!
  2517. !IRInlinedSequence methodsFor: '*Compiler'!
  2518. isInlined
  2519. ^ true
  2520. ! !
  2521. !IRInlinedSequence methodsFor: '*Compiler'!
  2522. accept: aVisitor
  2523. aVisitor visitIRInlinedSequence: self
  2524. ! !
  2525. IRVisitor subclass: #IRInliner
  2526. instanceVariableNames: ''
  2527. package:'Compiler'!
  2528. !IRInliner commentStamp!
  2529. I visit an IR tree, inlining message sends and block closures.
  2530. Message selectors that can be inlined are answered by `IRSendInliner >> #inlinedSelectors`!
  2531. !IRInliner methodsFor: '*Compiler'!
  2532. assignmentInliner
  2533. ^ IRAssignmentInliner new
  2534. translator: self;
  2535. yourself
  2536. !
  2537. nonLocalReturnInliner
  2538. ^ IRNonLocalReturnInliner new
  2539. translator: self;
  2540. yourself
  2541. !
  2542. returnInliner
  2543. ^ IRReturnInliner new
  2544. translator: self;
  2545. yourself
  2546. !
  2547. sendInliner
  2548. ^ IRSendInliner new
  2549. translator: self;
  2550. yourself
  2551. ! !
  2552. !IRInliner methodsFor: '*Compiler'!
  2553. shouldInlineAssignment: anIRAssignment
  2554. ^ anIRAssignment isInlined not and: [
  2555. anIRAssignment instructions last isSend and: [
  2556. self shouldInlineSend: (anIRAssignment instructions last) ]]
  2557. !
  2558. shouldInlineReturn: anIRReturn
  2559. ^ anIRReturn isInlined not and: [
  2560. anIRReturn instructions first isSend and: [
  2561. self shouldInlineSend: (anIRReturn instructions first) ]]
  2562. !
  2563. shouldInlineSend: anIRSend
  2564. ^ anIRSend isInlined not and: [
  2565. IRSendInliner shouldInline: anIRSend ]
  2566. ! !
  2567. !IRInliner methodsFor: '*Compiler'!
  2568. transformNonLocalReturn: anIRNonLocalReturn
  2569. "Replace a non local return into a local return"
  2570. | localReturn |
  2571. anIRNonLocalReturn scope canInlineNonLocalReturns ifTrue: [
  2572. anIRNonLocalReturn scope methodScope removeNonLocalReturn: anIRNonLocalReturn scope.
  2573. localReturn := IRReturn new
  2574. scope: anIRNonLocalReturn scope;
  2575. yourself.
  2576. anIRNonLocalReturn instructions do: [ :each |
  2577. localReturn add: each ].
  2578. anIRNonLocalReturn replaceWith: localReturn.
  2579. ^ localReturn ].
  2580. ^ super visitIRNonLocalReturn: anIRNonLocalReturn
  2581. !
  2582. visitIRAssignment: anIRAssignment
  2583. ^ (self shouldInlineAssignment: anIRAssignment)
  2584. ifTrue: [ self assignmentInliner inlineAssignment: anIRAssignment ]
  2585. ifFalse: [ super visitIRAssignment: anIRAssignment ]
  2586. !
  2587. visitIRNonLocalReturn: anIRNonLocalReturn
  2588. ^ (self shouldInlineReturn: anIRNonLocalReturn)
  2589. ifTrue: [ self nonLocalReturnInliner inlineReturn: anIRNonLocalReturn ]
  2590. ifFalse: [ self transformNonLocalReturn: anIRNonLocalReturn ]
  2591. !
  2592. visitIRReturn: anIRReturn
  2593. ^ (self shouldInlineReturn: anIRReturn)
  2594. ifTrue: [ self returnInliner inlineReturn: anIRReturn ]
  2595. ifFalse: [ super visitIRReturn: anIRReturn ]
  2596. !
  2597. visitIRSend: anIRSend
  2598. ^ (self shouldInlineSend: anIRSend)
  2599. ifTrue: [ self sendInliner inlineSend: anIRSend ]
  2600. ifFalse: [ super visitIRSend: anIRSend ]
  2601. ! !
  2602. IRJSTranslator subclass: #IRInliningJSTranslator
  2603. instanceVariableNames: ''
  2604. package:'Compiler'!
  2605. !IRInliningJSTranslator commentStamp!
  2606. I am a specialized JavaScript translator able to write inlined IR instructions to JavaScript stream (`JSStream` instance).!
  2607. !IRInliningJSTranslator methodsFor: '*Compiler'!
  2608. visitIRInlinedAssignment: anIRInlinedAssignment
  2609. self visit: anIRInlinedAssignment instructions last
  2610. !
  2611. visitIRInlinedClosure: anIRInlinedClosure
  2612. anIRInlinedClosure instructions do: [ :each |
  2613. self visit: each ]
  2614. !
  2615. visitIRInlinedIfFalse: anIRInlinedIfFalse
  2616. self stream nextPutIf: [
  2617. self stream nextPutAll: '!! smalltalk.assert('.
  2618. self visit: anIRInlinedIfFalse instructions first.
  2619. self stream nextPutAll: ')' ]
  2620. with: [ self visit: anIRInlinedIfFalse instructions last ]
  2621. !
  2622. visitIRInlinedIfNil: anIRInlinedIfNil
  2623. self stream nextPutIf: [
  2624. self stream nextPutAll: '($receiver = '.
  2625. self visit: anIRInlinedIfNil instructions first.
  2626. self stream nextPutAll: ') == nil || $receiver == undefined' ]
  2627. with: [ self visit: anIRInlinedIfNil instructions last ]
  2628. !
  2629. visitIRInlinedIfNilIfNotNil: anIRInlinedIfNilIfNotNil
  2630. self stream
  2631. nextPutIfElse: [
  2632. self stream nextPutAll: '($receiver = '.
  2633. self visit: anIRInlinedIfNilIfNotNil instructions first.
  2634. self stream nextPutAll: ') == nil || $receiver == undefined' ]
  2635. with: [ self visit: anIRInlinedIfNilIfNotNil instructions second ]
  2636. with: [ self visit: anIRInlinedIfNilIfNotNil instructions third ]
  2637. !
  2638. visitIRInlinedIfTrue: anIRInlinedIfTrue
  2639. self stream nextPutIf: [
  2640. self stream nextPutAll: 'smalltalk.assert('.
  2641. self visit: anIRInlinedIfTrue instructions first.
  2642. self stream nextPutAll: ')' ]
  2643. with: [ self visit: anIRInlinedIfTrue instructions last ]
  2644. !
  2645. visitIRInlinedIfTrueIfFalse: anIRInlinedIfTrueIfFalse
  2646. self stream
  2647. nextPutIfElse: [
  2648. self stream nextPutAll: 'smalltalk.assert('.
  2649. self visit: anIRInlinedIfTrueIfFalse instructions first.
  2650. self stream nextPutAll: ')' ]
  2651. with: [ self visit: anIRInlinedIfTrueIfFalse instructions second ]
  2652. with: [ self visit: anIRInlinedIfTrueIfFalse instructions third ]
  2653. !
  2654. visitIRInlinedNonLocalReturn: anIRInlinedReturn
  2655. self stream nextPutStatementWith: [
  2656. self visit: anIRInlinedReturn instructions last ].
  2657. self stream nextPutNonLocalReturnWith: [ ]
  2658. !
  2659. visitIRInlinedReturn: anIRInlinedReturn
  2660. self visit: anIRInlinedReturn instructions last
  2661. !
  2662. visitIRInlinedSequence: anIRInlinedSequence
  2663. anIRInlinedSequence instructions do: [ :each |
  2664. self stream nextPutStatementWith: [ self visit: each ]]
  2665. ! !
  2666. Object subclass: #IRSendInliner
  2667. instanceVariableNames: 'send translator'
  2668. package:'Compiler'!
  2669. !IRSendInliner commentStamp!
  2670. I inline some message sends and block closure arguments. I heavily rely on #perform: to dispatch inlining methods.!
  2671. !IRSendInliner methodsFor: '*Compiler'!
  2672. send
  2673. ^ send
  2674. !
  2675. send: anIRSend
  2676. send := anIRSend
  2677. !
  2678. translator
  2679. ^ translator
  2680. !
  2681. translator: anASTTranslator
  2682. translator := anASTTranslator
  2683. ! !
  2684. !IRSendInliner methodsFor: '*Compiler'!
  2685. inliningError: aString
  2686. InliningError signal: aString
  2687. ! !
  2688. !IRSendInliner methodsFor: '*Compiler'!
  2689. inlinedClosure
  2690. ^ IRInlinedClosure new
  2691. !
  2692. inlinedSequence
  2693. ^ IRInlinedSequence new
  2694. ! !
  2695. !IRSendInliner methodsFor: '*Compiler'!
  2696. ifFalse: anIRInstruction
  2697. ^ self inlinedSend: IRInlinedIfFalse new with: anIRInstruction
  2698. !
  2699. ifFalse: anIRInstruction ifTrue: anotherIRInstruction
  2700. ^ self perform: #ifTrue:ifFalse: withArguments: { anotherIRInstruction. anIRInstruction }
  2701. !
  2702. ifNil: anIRInstruction
  2703. ^ self
  2704. inlinedSend: IRInlinedIfNilIfNotNil new
  2705. with: anIRInstruction
  2706. with: (IRClosure new
  2707. scope: anIRInstruction scope copy;
  2708. add: (IRBlockSequence new
  2709. add: self send instructions first;
  2710. yourself);
  2711. yourself)
  2712. !
  2713. ifNil: anIRInstruction ifNotNil: anotherIRInstruction
  2714. ^ self inlinedSend: IRInlinedIfNilIfNotNil new with: anIRInstruction with: anotherIRInstruction
  2715. !
  2716. ifNotNil: anIRInstruction
  2717. ^ self
  2718. inlinedSend: IRInlinedIfNilIfNotNil new
  2719. with: (IRClosure new
  2720. scope: anIRInstruction scope copy;
  2721. add: (IRBlockSequence new
  2722. add: self send instructions first;
  2723. yourself);
  2724. yourself)
  2725. with: anIRInstruction
  2726. !
  2727. ifNotNil: anIRInstruction ifNil: anotherIRInstruction
  2728. ^ self inlinedSend: IRInlinedIfNilIfNotNil new with: anotherIRInstruction with: anIRInstruction
  2729. !
  2730. ifTrue: anIRInstruction
  2731. ^ self inlinedSend: IRInlinedIfTrue new with: anIRInstruction
  2732. !
  2733. ifTrue: anIRInstruction ifFalse: anotherIRInstruction
  2734. ^ self inlinedSend: IRInlinedIfTrueIfFalse new with: anIRInstruction with: anotherIRInstruction
  2735. !
  2736. inlineClosure: anIRClosure
  2737. | inlinedClosure sequence statements |
  2738. inlinedClosure := self inlinedClosure.
  2739. inlinedClosure scope: anIRClosure scope.
  2740. "Add the possible temp declarations"
  2741. anIRClosure instructions do: [ :each |
  2742. each isSequence ifFalse: [
  2743. inlinedClosure add: each ]].
  2744. "Add a block sequence"
  2745. sequence := self inlinedSequence.
  2746. inlinedClosure add: sequence.
  2747. "Get all the statements"
  2748. statements := anIRClosure instructions last instructions.
  2749. statements ifNotEmpty: [
  2750. statements allButLast do: [ :each | sequence add: each ].
  2751. "Inlined closures don't have implicit local returns"
  2752. (statements last isReturn and: [ statements last isBlockReturn ])
  2753. ifTrue: [ sequence add: statements last instructions first ]
  2754. ifFalse: [ sequence add: statements last ] ].
  2755. ^ inlinedClosure
  2756. !
  2757. inlineSend: anIRSend
  2758. self send: anIRSend.
  2759. ^ self
  2760. perform: self send selector
  2761. withArguments: self send instructions allButFirst
  2762. !
  2763. inlinedSend: inlinedSend with: anIRInstruction
  2764. | inlinedClosure |
  2765. anIRInstruction isClosure ifFalse: [ self inliningError: 'Message argument should be a block' ].
  2766. anIRInstruction arguments size = 0 ifFalse: [ self inliningError: 'Inlined block should have zero argument' ].
  2767. inlinedClosure := self translator visit: (self inlineClosure: anIRInstruction).
  2768. inlinedSend
  2769. add: self send instructions first;
  2770. add: inlinedClosure.
  2771. self send replaceWith: inlinedSend.
  2772. ^ inlinedSend
  2773. !
  2774. inlinedSend: inlinedSend with: anIRInstruction with: anotherIRInstruction
  2775. | inlinedClosure1 inlinedClosure2 |
  2776. anIRInstruction isClosure ifFalse: [ self inliningError: 'Message argument should be a block' ].
  2777. anIRInstruction arguments size = 0 ifFalse: [ self inliningError: 'Inlined block should have zero argument' ].
  2778. anotherIRInstruction isClosure ifFalse: [ self inliningError: 'Message argument should be a block' ].
  2779. anotherIRInstruction arguments size = 0 ifFalse: [ self inliningError: 'Inlined block should have zero argument' ].
  2780. inlinedClosure1 := self translator visit: (self inlineClosure: anIRInstruction).
  2781. inlinedClosure2 := self translator visit: (self inlineClosure: anotherIRInstruction).
  2782. inlinedSend
  2783. add: self send instructions first;
  2784. add: inlinedClosure1;
  2785. add: inlinedClosure2.
  2786. self send replaceWith: inlinedSend.
  2787. ^ inlinedSend
  2788. ! !
  2789. !IRSendInliner class methodsFor: '*Compiler'!
  2790. inlinedSelectors
  2791. ^ #('ifTrue:' 'ifFalse:' 'ifTrue:ifFalse:' 'ifFalse:ifTrue:' 'ifNil:' 'ifNotNil:' 'ifNil:ifNotNil:' 'ifNotNil:ifNil')
  2792. !
  2793. shouldInline: anIRInstruction
  2794. (self inlinedSelectors includes: anIRInstruction selector) ifFalse: [ ^ false ].
  2795. anIRInstruction instructions allButFirst do: [ :each |
  2796. each isClosure ifFalse: [ ^ false ]].
  2797. ^ true
  2798. ! !
  2799. IRSendInliner subclass: #IRAssignmentInliner
  2800. instanceVariableNames: 'assignment'
  2801. package:'Compiler'!
  2802. !IRAssignmentInliner commentStamp!
  2803. I inline message sends together with assignments by moving them around into the inline closure instructions.
  2804. ##Example
  2805. foo
  2806. | a |
  2807. a := true ifTrue: [ 1 ]
  2808. Will produce:
  2809. if(smalltalk.assert(true) {
  2810. a = 1;
  2811. };!
  2812. !IRAssignmentInliner methodsFor: '*Compiler'!
  2813. assignment
  2814. ^ assignment
  2815. !
  2816. assignment: aNode
  2817. assignment := aNode
  2818. ! !
  2819. !IRAssignmentInliner methodsFor: '*Compiler'!
  2820. inlineAssignment: anIRAssignment
  2821. | inlinedAssignment |
  2822. self assignment: anIRAssignment.
  2823. inlinedAssignment := IRInlinedAssignment new.
  2824. anIRAssignment instructions do: [ :each |
  2825. inlinedAssignment add: each ].
  2826. anIRAssignment replaceWith: inlinedAssignment.
  2827. self inlineSend: inlinedAssignment instructions last.
  2828. ^ inlinedAssignment
  2829. !
  2830. inlineClosure: anIRClosure
  2831. | inlinedClosure statements |
  2832. inlinedClosure := super inlineClosure: anIRClosure.
  2833. statements := inlinedClosure instructions last instructions.
  2834. statements ifNotEmpty: [
  2835. statements last canBeAssigned ifTrue: [
  2836. statements last replaceWith: (IRAssignment new
  2837. add: self assignment instructions first;
  2838. add: statements last copy;
  2839. yourself) ] ].
  2840. ^ inlinedClosure
  2841. ! !
  2842. IRSendInliner subclass: #IRNonLocalReturnInliner
  2843. instanceVariableNames: ''
  2844. package:'Compiler'!
  2845. !IRNonLocalReturnInliner methodsFor: '*Compiler'!
  2846. inlinedReturn
  2847. ^ IRInlinedNonLocalReturn new
  2848. ! !
  2849. !IRNonLocalReturnInliner methodsFor: '*Compiler'!
  2850. inlineClosure: anIRClosure
  2851. "| inlinedClosure statements |
  2852. inlinedClosure := super inlineClosure: anIRClosure.
  2853. statements := inlinedClosure instructions last instructions.
  2854. statements ifNotEmpty: [
  2855. statements last replaceWith: (IRNonLocalReturn new
  2856. add: statements last copy;
  2857. yourself) ].
  2858. ^ inlinedClosure"
  2859. ^ super inlineCLosure: anIRClosure
  2860. ! !
  2861. IRSendInliner subclass: #IRReturnInliner
  2862. instanceVariableNames: ''
  2863. package:'Compiler'!
  2864. !IRReturnInliner commentStamp!
  2865. I inline message sends with inlined closure together with a return instruction.!
  2866. !IRReturnInliner methodsFor: '*Compiler'!
  2867. inlinedReturn
  2868. ^ IRInlinedReturn new
  2869. ! !
  2870. !IRReturnInliner methodsFor: '*Compiler'!
  2871. inlineClosure: anIRClosure
  2872. | closure statements |
  2873. closure := super inlineClosure: anIRClosure.
  2874. statements := closure instructions last instructions.
  2875. statements ifNotEmpty: [
  2876. statements last isReturn
  2877. ifFalse: [ statements last replaceWith: (IRReturn new
  2878. add: statements last copy;
  2879. yourself)] ].
  2880. ^ closure
  2881. !
  2882. inlineReturn: anIRReturn
  2883. | return |
  2884. return := self inlinedReturn.
  2885. anIRReturn instructions do: [ :each |
  2886. return add: each ].
  2887. anIRReturn replaceWith: return.
  2888. self inlineSend: return instructions last.
  2889. ^ return
  2890. ! !
  2891. CodeGenerator subclass: #InliningCodeGenerator
  2892. instanceVariableNames: ''
  2893. package:'Compiler'!
  2894. !InliningCodeGenerator commentStamp!
  2895. I am a specialized code generator that uses inlining to produce more optimized JavaScript output!
  2896. !InliningCodeGenerator methodsFor: '*Compiler'!
  2897. compileNode: aNode
  2898. | ir stream |
  2899. self semanticAnalyzer visit: aNode.
  2900. ir := self translator visit: aNode.
  2901. self inliner visit: ir.
  2902. ^ self irTranslator
  2903. visit: ir;
  2904. contents
  2905. !
  2906. inliner
  2907. ^ IRInliner new
  2908. !
  2909. irTranslator
  2910. ^ IRInliningJSTranslator new
  2911. ! !
  2912. NodeVisitor subclass: #AIContext
  2913. instanceVariableNames: 'outerContext pc locals method'
  2914. package:'Compiler'!
  2915. !AIContext commentStamp!
  2916. AIContext is like a `MethodContext`, used by the `ASTInterpreter`.
  2917. Unlike a `MethodContext`, it is not read-only.
  2918. When debugging, `AIContext` instances are created by copying the current `MethodContext` (thisContext)!
  2919. !AIContext methodsFor: '*Compiler'!
  2920. localAt: aString
  2921. ^ self locals at: aString ifAbsent: [ nil ]
  2922. !
  2923. localAt: aString put: anObject
  2924. self locals at: aString put: anObject
  2925. !
  2926. locals
  2927. ^ locals ifNil: [ locals := Dictionary new ]
  2928. !
  2929. method
  2930. ^ method
  2931. !
  2932. method: aCompiledMethod
  2933. method := aCompiledMethod
  2934. !
  2935. outerContext
  2936. ^ outerContext
  2937. !
  2938. outerContext: anAIContext
  2939. outerContext := anAIContext
  2940. !
  2941. pc
  2942. ^ pc ifNil: [ pc := 0 ]
  2943. !
  2944. pc: anInteger
  2945. pc := anInteger
  2946. !
  2947. receiver
  2948. ^ self localAt: 'self'
  2949. !
  2950. receiver: anObject
  2951. self localAt: 'self' put: anObject
  2952. !
  2953. selector
  2954. ^ self metod
  2955. ifNotNil: [ self method selector ]
  2956. ! !
  2957. !AIContext methodsFor: '*Compiler'!
  2958. initializeFromMethodContext: aMethodContext
  2959. self pc: aMethodContext pc.
  2960. self receiver: aMethodContext receiver.
  2961. self method: aMethodContext method.
  2962. aMethodContext outerContext ifNotNil: [
  2963. self outerContext: (self class fromMethodContext: aMethodContext outerContext) ].
  2964. aMethodContext locals keysAndValuesDo: [ :key :value |
  2965. self locals at: key put: value ]
  2966. ! !
  2967. !AIContext class methodsFor: '*Compiler'!
  2968. fromMethodContext: aMethodContext
  2969. ^ self new
  2970. initializeFromMethodContext: aMethodContext;
  2971. yourself
  2972. ! !
  2973. Object subclass: #ASTDebugger
  2974. instanceVariableNames: 'interpreter context'
  2975. package:'Compiler'!
  2976. !ASTDebugger commentStamp!
  2977. ASTDebugger is a debugger to Amber.
  2978. It uses an AST interpreter to step through the code.
  2979. ASTDebugger instances are created from a `MethodContext` with `ASTDebugger class >> context:`.
  2980. They hold an `AIContext` instance internally, recursive copy of the `MethodContext`.
  2981. Use the methods of the 'stepping' protocol to do stepping.!
  2982. !ASTDebugger methodsFor: '*Compiler'!
  2983. context
  2984. ^ context
  2985. !
  2986. context: aContext
  2987. context := AIContext new.
  2988. !
  2989. interpreter
  2990. ^ interpreter ifNil: [ interpreter := self defaultInterpreterClass new ]
  2991. !
  2992. interpreter: anInterpreter
  2993. interpreter := anInterpreter
  2994. !
  2995. method
  2996. ^ self context method
  2997. ! !
  2998. !ASTDebugger methodsFor: '*Compiler'!
  2999. defaultInterpreterClass
  3000. ^ ASTSteppingInterpreter
  3001. ! !
  3002. !ASTDebugger methodsFor: '*Compiler'!
  3003. buildAST
  3004. "Build the AST tree from the method source code.
  3005. The AST is annotated with a SemanticAnalyzer,
  3006. to know the semantics and bindings of each node needed for later debugging"
  3007. | ast |
  3008. ast := Smalltalk current parse: self method source.
  3009. (SemanticAnalyzer on: self context receiver class)
  3010. visit: ast.
  3011. ^ ast
  3012. !
  3013. initializeInterpreter
  3014. self interpreter interpret: self buildAST nodes first
  3015. !
  3016. initializeWithContext: aMethodContext
  3017. "TODO: do we need to handle block contexts?"
  3018. self context: (AIContext fromMethodContext: aMethodContext).
  3019. self initializeInterpreter
  3020. ! !
  3021. !ASTDebugger methodsFor: '*Compiler'!
  3022. restart
  3023. self shouldBeImplemented
  3024. !
  3025. resume
  3026. self shouldBeImplemented
  3027. !
  3028. step
  3029. "The ASTSteppingInterpreter stops at each node interpretation.
  3030. One step will interpret nodes until:
  3031. - we get at the end
  3032. - the next node is a stepping node (send, assignment, etc.)"
  3033. [ (self interpreter nextNode notNil and: [ self interpreter nextNode stopOnStepping ])
  3034. or: [ self interpreter atEnd not ] ]
  3035. whileFalse: [
  3036. self interpreter step.
  3037. self step ]
  3038. !
  3039. stepInto
  3040. self shouldBeImplemented
  3041. !
  3042. stepOver
  3043. self step
  3044. ! !
  3045. !ASTDebugger class methodsFor: '*Compiler'!
  3046. context: aMethodContext
  3047. ^ self new
  3048. initializeWithContext: aMethodContext;
  3049. yourself
  3050. ! !
  3051. Object subclass: #ASTInterpreter
  3052. instanceVariableNames: 'currentNode context shouldReturn result'
  3053. package:'Compiler'!
  3054. !ASTInterpreter commentStamp!
  3055. ASTIntepreter is like a `NodeVisitor`, interpreting nodes one after each other.
  3056. It is built using Continuation Passing Style for stepping purposes.
  3057. Usage example:
  3058. | ast interpreter |
  3059. ast := Smalltalk current parse: 'foo 1+2+4'.
  3060. (SemanticAnalyzer on: Object) visit: ast.
  3061. ASTInterpreter new
  3062. interpret: ast nodes first;
  3063. result "Answers 7"!
  3064. !ASTInterpreter methodsFor: '*Compiler'!
  3065. context
  3066. ^ context ifNil: [ context := AIContext new ]
  3067. !
  3068. context: anAIContext
  3069. context := anAIContext
  3070. !
  3071. currentNode
  3072. ^ currentNode
  3073. !
  3074. result
  3075. ^ result
  3076. ! !
  3077. !ASTInterpreter methodsFor: '*Compiler'!
  3078. initialize
  3079. super initialize.
  3080. shouldReturn := false
  3081. ! !
  3082. !ASTInterpreter methodsFor: '*Compiler'!
  3083. interpret: aNode
  3084. shouldReturn := false.
  3085. self interpret: aNode continue: [ :value |
  3086. result := value ]
  3087. !
  3088. interpret: aNode continue: aBlock
  3089. shouldReturn ifTrue: [ ^ self ].
  3090. aNode isNode
  3091. ifTrue: [
  3092. currentNode := aNode.
  3093. self interpretNode: aNode continue: [ :value |
  3094. self continue: aBlock value: value ] ]
  3095. ifFalse: [ self continue: aBlock value: aNode ]
  3096. !
  3097. interpretAssignmentNode: aNode continue: aBlock
  3098. self interpret: aNode right continue: [ :value |
  3099. self
  3100. continue: aBlock
  3101. value: (self assign: aNode left to: value) ]
  3102. !
  3103. interpretBlockNode: aNode continue: aBlock
  3104. "TODO: Context should be set"
  3105. self
  3106. continue: aBlock
  3107. value: [ self interpret: aNode nodes first; result ]
  3108. !
  3109. interpretBlockSequenceNode: aNode continue: aBlock
  3110. self interpretSequenceNode: aNode continue: aBlock
  3111. !
  3112. interpretCascadeNode: aNode continue: aBlock
  3113. "TODO: Handle super sends"
  3114. self interpret: aNode receiver continue: [ :receiver |
  3115. "Only interpret the receiver once"
  3116. aNode nodes do: [ :each | each receiver: receiver ].
  3117. self
  3118. interpretAll: aNode nodes allButLast
  3119. continue: [
  3120. self
  3121. interpret: aNode nodes last
  3122. continue: [ :val | self continue: aBlock value: val ] ] ]
  3123. !
  3124. interpretClassReferenceNode: aNode continue: aBlock
  3125. self continue: aBlock value: (Smalltalk current at: aNode value)
  3126. !
  3127. interpretDynamicArrayNode: aNode continue: aBlock
  3128. self interpretAll: aNode nodes continue: [ :array |
  3129. self
  3130. continue: aBlock
  3131. value: array ]
  3132. !
  3133. interpretDynamicDictionaryNode: aNode continue: aBlock
  3134. self interpretAll: aNode nodes continue: [ :array | | hashedCollection |
  3135. hashedCollection := HashedCollection new.
  3136. array do: [ :each | hashedCollection add: each ].
  3137. self
  3138. continue: aBlock
  3139. value: hashedCollection ]
  3140. !
  3141. interpretJSStatementNode: aNode continue: aBlock
  3142. shouldReturn := true.
  3143. self continue: aBlock value: (self eval: aNode source)
  3144. !
  3145. interpretMethodNode: aNode continue: aBlock
  3146. self interpretAll: aNode nodes continue: [ :array |
  3147. self continue: aBlock value: array first ]
  3148. !
  3149. interpretNode: aNode continue: aBlock
  3150. aNode interpreter: self continue: aBlock
  3151. !
  3152. interpretReturnNode: aNode continue: aBlock
  3153. self interpret: aNode nodes first continue: [ :value |
  3154. shouldReturn := true.
  3155. self continue: aBlock value: value ]
  3156. !
  3157. interpretSendNode: aNode continue: aBlock
  3158. "TODO: Handle super sends"
  3159. self interpret: aNode receiver continue: [ :receiver |
  3160. self interpretAll: aNode arguments continue: [ :args |
  3161. self
  3162. messageFromSendNode: aNode
  3163. arguments: args
  3164. do: [ :message |
  3165. self context pc: self context pc + 1.
  3166. self
  3167. continue: aBlock
  3168. value: (message sendTo: receiver) ] ] ]
  3169. !
  3170. interpretSequenceNode: aNode continue: aBlock
  3171. self interpretAll: aNode nodes continue: [ :array |
  3172. self continue: aBlock value: array last ]
  3173. !
  3174. interpretValueNode: aNode continue: aBlock
  3175. self continue: aBlock value: aNode value
  3176. !
  3177. interpretVariableNode: aNode continue: aBlock
  3178. self
  3179. continue: aBlock
  3180. value: (aNode binding isInstanceVar
  3181. ifTrue: [ self context receiver instVarAt: aNode value ]
  3182. ifFalse: [ self context localAt: aNode value ])
  3183. ! !
  3184. !ASTInterpreter methodsFor: '*Compiler'!
  3185. assign: aNode to: anObject
  3186. ^ aNode binding isInstanceVar
  3187. ifTrue: [ self context receiver instVarAt: aNode value put: anObject ]
  3188. ifFalse: [ self context localAt: aNode value put: anObject ]
  3189. !
  3190. continue: aBlock value: anObject
  3191. result := anObject.
  3192. aBlock value: anObject
  3193. !
  3194. eval: aString
  3195. "Evaluate aString as JS source inside an JS function.
  3196. aString is not sandboxed."
  3197. | source function |
  3198. source := String streamContents: [ :str |
  3199. str nextPutAll: '(function('.
  3200. self context locals keys
  3201. do: [ :each | str nextPutAll: each ]
  3202. separatedBy: [ str nextPutAll: ',' ].
  3203. str
  3204. nextPutAll: '){ return (function() {';
  3205. nextPutAll: aString;
  3206. nextPutAll: '})() })' ].
  3207. function := Compiler new eval: source.
  3208. ^ function valueWithPossibleArguments: self context locals values
  3209. !
  3210. interpretAll: aCollection continue: aBlock
  3211. self
  3212. interpretAll: aCollection
  3213. continue: aBlock
  3214. result: OrderedCollection new
  3215. !
  3216. interpretAll: nodes continue: aBlock result: aCollection
  3217. nodes isEmpty
  3218. ifTrue: [ self continue: aBlock value: aCollection ]
  3219. ifFalse: [
  3220. self interpret: nodes first continue: [:value |
  3221. self
  3222. interpretAll: nodes allButFirst
  3223. continue: aBlock
  3224. result: aCollection, { value } ] ]
  3225. !
  3226. messageFromSendNode: aSendNode arguments: aCollection do: aBlock
  3227. self
  3228. continue: aBlock
  3229. value: (Message new
  3230. selector: aSendNode selector;
  3231. arguments: aCollection;
  3232. yourself)
  3233. ! !
  3234. !ASTInterpreter methodsFor: '*Compiler'!
  3235. shouldReturn
  3236. ^ shouldReturn ifNil: [ false ]
  3237. ! !
  3238. ASTInterpreter subclass: #ASTSteppingInterpreter
  3239. instanceVariableNames: 'continuation nextNode'
  3240. package:'Compiler'!
  3241. !ASTSteppingInterpreter commentStamp!
  3242. ASTSteppingInterpreter is an interpreter with stepping capabilities.
  3243. Use `#step` to actually interpret the next node.
  3244. Usage example:
  3245. | ast interpreter |
  3246. ast := Smalltalk current parse: 'foo 1+2+4'.
  3247. (SemanticAnalyzer on: Object) visit: ast.
  3248. interpreter := ASTSteppingInterpreter new
  3249. interpret: ast nodes first;
  3250. yourself.
  3251. debugger step; step.
  3252. debugger step; step.
  3253. debugger result."Answers 1"
  3254. debugger step.
  3255. debugger result. "Answers 3"
  3256. debugger step.
  3257. debugger result. "Answers 7"!
  3258. !ASTSteppingInterpreter methodsFor: '*Compiler'!
  3259. nextNode
  3260. ^ nextNode
  3261. ! !
  3262. !ASTSteppingInterpreter methodsFor: '*Compiler'!
  3263. initialize
  3264. super initialize.
  3265. continuation := [ ]
  3266. ! !
  3267. !ASTSteppingInterpreter methodsFor: '*Compiler'!
  3268. interpret: aNode continue: aBlock
  3269. nextNode := aNode.
  3270. continuation := [
  3271. super interpret: aNode continue: aBlock ]
  3272. ! !
  3273. !ASTSteppingInterpreter methodsFor: '*Compiler'!
  3274. step
  3275. continuation value
  3276. ! !
  3277. !ASTSteppingInterpreter methodsFor: '*Compiler'!
  3278. atEnd
  3279. ^ self shouldReturn or: [ self nextNode == self currentNode ]
  3280. ! !
  3281. !Node methodsFor: '*Compiler'!
  3282. interpreter: anInterpreter continue: aBlock
  3283. ^ anInterpreter interpretNode: self continue: aBlock
  3284. !
  3285. isSteppingNode
  3286. ^ false
  3287. ! !
  3288. !AssignmentNode methodsFor: '*Compiler'!
  3289. interpreter: anInterpreter continue: aBlock
  3290. ^ anInterpreter interpretAssignmentNode: self continue: aBlock
  3291. !
  3292. isSteppingNode
  3293. ^ true
  3294. ! !
  3295. !BlockNode methodsFor: '*Compiler'!
  3296. interpreter: anInterpreter continue: aBlock
  3297. ^ anInterpreter interpretBlockNode: self continue: aBlock
  3298. !
  3299. isSteppingNode
  3300. ^ true
  3301. ! !
  3302. !CascadeNode methodsFor: '*Compiler'!
  3303. interpreter: anInterpreter continue: aBlock
  3304. ^ anInterpreter interpretCascadeNode: self continue: aBlock
  3305. ! !
  3306. !DynamicArrayNode methodsFor: '*Compiler'!
  3307. interpreter: anInterpreter continue: aBlock
  3308. ^ anInterpreter interpretDynamicArrayNode: self continue: aBlock
  3309. !
  3310. isSteppingNode
  3311. ^ true
  3312. ! !
  3313. !DynamicDictionaryNode methodsFor: '*Compiler'!
  3314. interpreter: anInterpreter continue: aBlock
  3315. ^ anInterpreter interpretDynamicDictionaryNode: self continue: aBlock
  3316. !
  3317. isSteppingNode
  3318. ^ true
  3319. ! !
  3320. !JSStatementNode methodsFor: '*Compiler'!
  3321. interpreter: anInterpreter continue: aBlock
  3322. ^ anInterpreter interpretJSStatementNode: self continue: aBlock
  3323. !
  3324. isSteppingNode
  3325. ^ true
  3326. ! !
  3327. !MethodNode methodsFor: '*Compiler'!
  3328. interpreter: anInterpreter continue: aBlock
  3329. ^ anInterpreter interpretMethodNode: self continue: aBlock
  3330. ! !
  3331. !ReturnNode methodsFor: '*Compiler'!
  3332. interpreter: anInterpreter continue: aBlock
  3333. ^ anInterpreter interpretReturnNode: self continue: aBlock
  3334. ! !
  3335. !SendNode methodsFor: '*Compiler'!
  3336. interpreter: anInterpreter continue: aBlock
  3337. ^ anInterpreter interpretSendNode: self continue: aBlock
  3338. !
  3339. isSteppingNode
  3340. ^ true
  3341. ! !
  3342. !SequenceNode methodsFor: '*Compiler'!
  3343. interpreter: anInterpreter continue: aBlock
  3344. ^ anInterpreter interpretSequenceNode: self continue: aBlock
  3345. ! !
  3346. !BlockSequenceNode methodsFor: '*Compiler'!
  3347. interpreter: anInterpreter continue: aBlock
  3348. ^ anInterpreter interpretBlockSequenceNode: self continue: aBlock
  3349. ! !
  3350. !ValueNode methodsFor: '*Compiler'!
  3351. interpreter: anInterpreter continue: aBlock
  3352. ^ anInterpreter interpretValueNode: self continue: aBlock
  3353. ! !
  3354. !VariableNode methodsFor: '*Compiler'!
  3355. interpreter: anInterpreter continue: aBlock
  3356. ^ anInterpreter interpretVariableNode: self continue: aBlock
  3357. ! !
  3358. !ClassReferenceNode methodsFor: '*Compiler'!
  3359. interpreter: anInterpreter continue: aBlock
  3360. ^ anInterpreter interpretClassReferenceNode: self continue: aBlock
  3361. ! !