stmt.bmx 28 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058
  1. ' Copyright (c) 2013-2026 Bruce A Henderson
  2. '
  3. ' Based on the public domain Monkey "trans" by Mark Sibly
  4. '
  5. ' This software is provided 'as-is', without any express or implied
  6. ' warranty. In no event will the authors be held liable for any damages
  7. ' arising from the use of this software.
  8. '
  9. ' Permission is granted to anyone to use this software for any purpose,
  10. ' including commercial applications, and to alter it and redistribute it
  11. ' freely, subject to the following restrictions:
  12. '
  13. ' 1. The origin of this software must not be misrepresented; you must not
  14. ' claim that you wrote the original software. If you use this software
  15. ' in a product, an acknowledgment in the product documentation would be
  16. ' appreciated but is not required.
  17. '
  18. ' 2. Altered source versions must be plainly marked as such, and must not be
  19. ' misrepresented as being the original software.
  20. '
  21. ' 3. This notice may not be removed or altered from any source
  22. ' distribution.
  23. '
  24. Type TStmt Abstract
  25. Field errInfo$
  26. ' whether this statement was generated by the compiler or not
  27. Field generated:Int
  28. Field semanted:Int
  29. Method New()
  30. errInfo=_errInfo
  31. End Method
  32. Method OnCopy:TStmt( scope:TScopeDecl ) Abstract
  33. Method Semant()
  34. PushErr errInfo
  35. OnSemant
  36. PopErr
  37. End Method
  38. Method Copy:TStmt( scope:TScopeDecl )
  39. Local t:TStmt=OnCopy( scope )
  40. t.errInfo=errInfo
  41. Return t
  42. End Method
  43. Method OnSemant() Abstract
  44. Method Trans$() Abstract
  45. Method Clear()
  46. End Method
  47. End Type
  48. Type TDeclStmt Extends TStmt
  49. Field decl:TDecl
  50. Method Create:TDeclStmt( decl:TDecl, generated:Int = False )
  51. Self.decl=decl
  52. Self.generated = generated
  53. Return Self
  54. End Method
  55. Method CreateWithId:TDeclStmt( id$,ty:TType,init:TExpr )
  56. Self.decl=New TLocalDecl.Create( id,ty,init,0 )
  57. Return Self
  58. End Method
  59. Method OnCopy:TStmt( scope:TScopeDecl )
  60. Local d:TDecl = decl.Copy()
  61. 'If Not d.scope Then
  62. d.scope = Null
  63. 'End If
  64. Return New TDeclStmt.Create( d, generated )
  65. End Method
  66. Method OnSemant()
  67. If semanted Then Return
  68. semanted = True
  69. If TLocalDecl(decl) Then
  70. Local tryStmtDecl:TTryStmtDecl = _env.FindTry()
  71. If tryStmtDecl Then
  72. TLocalDecl(decl).declaredInTry = tryStmtDecl
  73. End If
  74. End If
  75. decl.Semant
  76. ' if scope is already set, don't try to add it to the current scope.
  77. If Not decl.scope Then
  78. _env.InsertDecl decl
  79. End If
  80. End Method
  81. Method Trans$()
  82. Return _trans.TransDeclStmt( Self )
  83. End Method
  84. Method Clear()
  85. decl.Clear()
  86. End Method
  87. End Type
  88. Type TAssignStmt Extends TStmt
  89. Field op$
  90. Field lhs:TExpr
  91. Field rhs:TExpr
  92. Method Create:TAssignStmt( op$,lhs:TExpr,rhs:TExpr, generated:Int = False )
  93. Self.op=op
  94. Self.lhs=lhs
  95. Self.rhs=rhs
  96. Self.generated = generated
  97. Return Self
  98. End Method
  99. Method OnCopy:TStmt( scope:TScopeDecl )
  100. Return New TAssignStmt.Create( op,lhs.Copy(),rhs.Copy(), generated )
  101. End Method
  102. Method OnSemant()
  103. If semanted Then Return
  104. semanted = True
  105. If TIdentExpr(rhs) Then
  106. TIdentExpr(rhs).isRhs = True
  107. End If
  108. rhs=rhs.Semant()
  109. lhs=lhs.SemantSet( op,rhs )
  110. If TInvokeExpr( lhs ) Or TInvokeMemberExpr( lhs )
  111. rhs=Null
  112. Else
  113. ' can't assign to readonly field outside of its class constructor, or anytime for readonly variable
  114. If TVarExpr(lhs) Or TMemberVarExpr(lhs) Then
  115. Local decl:TDecl
  116. If TVarExpr(lhs) Then
  117. decl = TVarExpr(lhs).decl
  118. Else
  119. Local mvExpr:TMemberVarExpr = TMemberVarExpr(lhs)
  120. decl = mvExpr.decl
  121. If TFieldDecl(decl) And (TInvokeExpr(mvExpr.expr) Or TInvokeMemberExpr(mvExpr.expr)) Then
  122. If TClassDecl(decl.scope) And TClassDecl(decl.scope).IsStruct() Then
  123. rhs = Null
  124. Warn "Discarding Field assignment of Struct returned via invocation"
  125. Return
  126. End If
  127. End If
  128. End If
  129. If decl And decl.IsReadOnly() Then
  130. If TFieldDecl(decl) Then
  131. ' check scope for ctor
  132. Local scope:TFuncDecl = _env.FuncScope()
  133. If Not scope Or Not scope.IsCtor() Or (Not scope.ClassScope().ExtendsClass(decl.ClassScope())) Then
  134. Err "Cannot modify ReadOnly field " + decl.ident
  135. End If
  136. Else
  137. Err "Cannot modify ReadOnly variable " + decl.ident
  138. End If
  139. End If
  140. If TValDecl(decl) And TArrayType(TValDecl(decl).ty) And TArrayType(TValDecl(decl).ty).isStatic Then
  141. Err "Static arrays cannot be assigned in this way."
  142. End If
  143. End If
  144. If IsPointerType(lhs.exprType, 0, TType.T_POINTER | TType.T_VARPTR) And TNumericType(rhs.exprType) Then
  145. ' with pointer assignment we don't cast the numeric to a pointer
  146. Else If IsPointerType(lhs.exprType, 0, TType.T_VAR) And TNumericType(rhs.exprType) Then
  147. ' for var, we cast to the non-var type
  148. Local ty:TType = lhs.exprType.Copy()
  149. ty._flags :~ TType.T_VAR
  150. rhs=rhs.Cast( ty )
  151. Else
  152. Local splitOp:Int = True
  153. Select op
  154. Case "="
  155. rhs=rhs.Cast( lhs.exprType )
  156. splitOp = False
  157. Case ":*",":/",":+",":-"
  158. If TNumericType( lhs.exprType ) And lhs.exprType.EqualsType( rhs.exprType ) Then
  159. splitOp = False
  160. End If
  161. If TObjectType(lhs.exprType) Then
  162. Local args:TExpr[] = [rhs]
  163. Try
  164. Local decl:TFuncDecl = TFuncDecl(TObjectType(lhs.exprType).classDecl.FindFuncDecl(op, args,,,,True,SCOPE_CLASS_HEIRARCHY))
  165. If decl Then
  166. lhs = New TInvokeMemberExpr.Create( lhs, decl, args ).Semant()
  167. rhs = Null
  168. Return
  169. End If
  170. Catch error:String
  171. Err "Operator " + op + " cannot be used with Objects."
  172. End Try
  173. End If
  174. Case ":&",":|",":^",":shl",":shr",":mod"
  175. If (TIntType( lhs.exprType ) And lhs.exprType.EqualsType( rhs.exprType )) Or TObjectType(lhs.exprType) Then
  176. splitOp = False
  177. End If
  178. If TObjectType(lhs.exprType) Then
  179. Local args:TExpr[] = [rhs]
  180. Try
  181. Local decl:TFuncDecl = TFuncDecl(TObjectType(lhs.exprType).classDecl.FindFuncDecl(op, args,,,,,SCOPE_CLASS_HEIRARCHY))
  182. If decl Then
  183. lhs = New TInvokeMemberExpr.Create( lhs, decl, args ).Semant()
  184. rhs = Null
  185. Return
  186. End If
  187. Catch error:String
  188. Err "Operator " + op + " cannot be used with Objects."
  189. End Try
  190. End If
  191. End Select
  192. If splitOp Then
  193. rhs = New TBinaryMathExpr.Create(op[1..], lhs, rhs).Semant().Cast(lhs.exprType)
  194. op = "="
  195. End If
  196. End If
  197. EndIf
  198. End Method
  199. Method Trans$()
  200. _errInfo=errInfo
  201. Return _trans.TransAssignStmt( Self )
  202. End Method
  203. End Type
  204. Type TExprStmt Extends TStmt
  205. Field expr:TExpr
  206. Method Create:TExprStmt( expr:TExpr )
  207. Self.expr=expr
  208. Return Self
  209. End Method
  210. Method OnCopy:TStmt( scope:TScopeDecl )
  211. Return New TExprStmt.Create( expr.Copy() )
  212. End Method
  213. Method OnSemant()
  214. If semanted Then Return
  215. semanted = True
  216. expr=expr.Semant()
  217. If Not expr InternalErr "TExprStmt.OnSemant"
  218. End Method
  219. Method Trans$()
  220. Return _trans.TransExprStmt( Self )
  221. End Method
  222. End Type
  223. Type TReturnStmt Extends TStmt
  224. Field expr:TExpr
  225. Field fRetType:TType
  226. Method Create:TReturnStmt( expr:TExpr )
  227. Self.expr=expr
  228. Return Self
  229. End Method
  230. Method OnCopy:TStmt( scope:TScopeDecl )
  231. Local r:TReturnStmt
  232. If expr Then
  233. r = New TReturnStmt.Create( expr.Copy() )
  234. Else
  235. r = New TReturnStmt.Create( Null )
  236. End If
  237. r.fRetType = fRetType
  238. Return r
  239. End Method
  240. Method OnSemant()
  241. If semanted Then Return
  242. semanted = True
  243. Local fdecl:TFuncDecl=_env.FuncScope()
  244. fRetType = fdecl.retType
  245. If expr
  246. If TIdentExpr(expr) Then
  247. TIdentExpr(expr).isRhs = True
  248. End If
  249. If fdecl.IsCtor() Err "Constructors may not return a value."
  250. If TVoidType( fRetType ) Then
  251. Local errorText:String = "Function can not return a value."
  252. If Not _env.ModuleScope().IsSuperStrict() Then
  253. errorText :+ " You may have Strict type overriding SuperStrict type."
  254. End If
  255. Err errorText
  256. End If
  257. expr=expr.SemantAndCast( fRetType )
  258. If TIdentTypeExpr(expr) Err "Function must return a value."
  259. Else If fdecl.IsCtor()
  260. ' ctors do not return anything
  261. Else If Not TVoidType( fRetType )
  262. If _env.ModuleScope().IsSuperStrict() Err "Function must return a value"
  263. expr=New TConstExpr.Create( fRetType ,"" ).Semant()
  264. EndIf
  265. End Method
  266. Method Trans$()
  267. Return _trans.TransReturnStmt( Self )
  268. End Method
  269. End Type
  270. Type TTryStmt Extends TStmt
  271. Field block:TBlockDecl
  272. Field catches:TCatchStmt[]
  273. Field finallyStmt:TFinallyStmt
  274. Field rethrowLabel:TLoopLabelDecl
  275. Field endTryLabel:TLoopLabelDecl
  276. Method Create:TTryStmt( block:TBlockDecl,catches:TCatchStmt[],finallyStmt:TFinallyStmt )
  277. Self.block=block
  278. Self.catches=catches
  279. Self.finallyStmt=finallyStmt
  280. Self.rethrowLabel = New TLoopLabelDecl.Create("rethrow")
  281. Self.endTryLabel = New TLoopLabelDecl.Create("endtry")
  282. Return Self
  283. End Method
  284. Method OnCopy:TStmt( scope:TScopeDecl )
  285. Local catchCopies:TCatchStmt[] = Self.catches[..]
  286. For Local i:Int = 0 Until catchCopies.Length
  287. catchCopies[i] = TCatchStmt(catchCopies[i].Copy(scope))
  288. Next
  289. Local finallyCopy:TFinallyStmt = Null
  290. If finallyStmt Then finallyCopy = TFinallyStmt(finallyStmt.Copy(scope))
  291. Return New TTryStmt.Create(block.CopyBlock(scope), catchCopies, finallyCopy)
  292. End Method
  293. Method OnSemant()
  294. If semanted Then Return
  295. semanted = True
  296. block.Semant
  297. Local hasObject:Int = False
  298. For Local i:Int = 0 Until catches.Length
  299. catches[i].Semant
  300. If hasObject Then
  301. PushErr catches[i].errInfo
  302. Err "Catch variable class extends earlier catch variable class"
  303. End If
  304. If TObjectType(catches[i].init.ty) And TObjectType(catches[i].init.ty).classdecl.ident = "Object" Then
  305. hasObject = True
  306. Continue
  307. End If
  308. For Local j:Int = 0 Until i
  309. If catches[i].init.ty.ExtendsType( catches[j].init.ty )
  310. PushErr catches[i].errInfo
  311. Err "Catch variable class extends earlier catch variable class"
  312. EndIf
  313. Next
  314. Next
  315. If finallyStmt Then finallyStmt.Semant
  316. End Method
  317. Method Trans$()
  318. Return _trans.TransTryStmt( Self )
  319. End Method
  320. End Type
  321. Type TCatchStmt Extends TStmt
  322. Field init:TLocalDecl
  323. Field block:TBlockDecl
  324. Method Create:TCatchStmt( init:TLocalDecl,block:TBlockDecl )
  325. Self.init=init
  326. Self.block=block
  327. Return Self
  328. End Method
  329. Method OnCopy:TStmt( scope:TScopeDecl )
  330. Return New TCatchStmt.Create( TLocalDecl( init.Copy() ),block.CopyBlock( scope ) )
  331. End Method
  332. Method OnSemant()
  333. If semanted Then Return
  334. semanted = True
  335. init.Semant
  336. If (Not TObjectType( init.ty ) Or (TObjectType( init.ty ) And TObjectType( init.ty ).classDecl.IsStruct())) And Not TStringType(init.ty) And Not TArrayType(init.ty) Err "'Catch' variables must be objects"
  337. block.InsertDecl init
  338. block.Semant
  339. End Method
  340. Method Trans$()
  341. End Method
  342. End Type
  343. Type TFinallyStmt Extends TStmt
  344. Field block:TBlockDecl
  345. Field finallyLabel:TLoopLabelDecl
  346. Field returnLabelPtrDecl:TLocalDecl
  347. Method Create:TFinallyStmt( block:TBlockDecl )
  348. Self.block=block
  349. Self.finallyLabel = New TLoopLabelDecl.Create("finally")
  350. Return Self
  351. End Method
  352. Method OnCopy:TStmt( scope:TScopeDecl )
  353. Return New TFinallyStmt.Create( block.CopyBlock( scope ) )
  354. End Method
  355. Method OnSemant()
  356. block.Semant
  357. End Method
  358. Method Trans$()
  359. End Method
  360. End Type
  361. Type TThrowStmt Extends TStmt
  362. Field expr:TExpr
  363. Method Create:TThrowStmt( expr:TExpr )
  364. Self.expr=expr
  365. Return Self
  366. End Method
  367. Method OnCopy:TStmt( scope:TScopeDecl )
  368. Return New TThrowStmt.Create( expr.Copy() )
  369. End Method
  370. Method OnSemant()
  371. expr=expr.Semant()
  372. If (Not TObjectType( expr.exprType ) Or (TObjectType( expr.exprType ) And TObjectType( expr.exprType ).classDecl.IsStruct())) And Not TStringType(expr.exprType) And Not TArrayType(expr.exprType) Err "'Throw' expression must be an object"
  373. End Method
  374. Method Trans$()
  375. ' TODO
  376. Return _trans.TransThrowStmt( Self )
  377. End Method
  378. End Type
  379. Type TLoopControlStmt Extends TStmt Abstract
  380. Field loop:TLoopStmt
  381. Field label:TExpr
  382. End Type
  383. Type TBreakStmt Extends TLoopControlStmt
  384. Method Create:TBreakStmt( label:TExpr )
  385. Self.label=label
  386. Return Self
  387. End Method
  388. Method OnSemant()
  389. If Not _loopnest Err "Exit statement must appear inside a loop."
  390. If label Then
  391. Local id:String
  392. If TIdentExpr(label) id = "'" + TIdentExpr(label).ident + "'"
  393. label = label.Semant(OPTION_WANT_LOOP_LABEL)
  394. If Not TLoopLabelExpr(label) Err "Continue/Exit label " + id + " not found"
  395. End If
  396. If opt_debug And Not loop Then
  397. loop = TLoopStmt(_env.FindLoop())
  398. If Not loop Err "Cannot find loop for Exit."
  399. End If
  400. End Method
  401. Method OnCopy:TStmt( scope:TScopeDecl )
  402. If label Then
  403. Return New TBreakStmt.Create(label.Copy())
  404. Else
  405. Return New TBreakStmt.Create(Null)
  406. End If
  407. End Method
  408. Method Trans$()
  409. Return _trans.TransBreakStmt( Self )
  410. End Method
  411. End Type
  412. Type TContinueStmt Extends TLoopControlStmt
  413. Method Create:TContinueStmt( label:TExpr, generated:Int = False )
  414. Self.label=label
  415. Self.generated = generated
  416. Return Self
  417. End Method
  418. Method OnSemant()
  419. If Not _loopnest Err "Continue statement must appear inside a loop."
  420. If label Then
  421. Local id:String
  422. If TIdentExpr(label) id = "'" + TIdentExpr(label).ident + "'"
  423. label = label.Semant(OPTION_WANT_LOOP_LABEL)
  424. If Not TLoopLabelExpr(label) Err "Continue/Exit label " + id + " not found"
  425. End If
  426. If opt_debug And Not loop Then
  427. loop = TLoopStmt(_env.FindLoop())
  428. If Not loop Err "Cannot find loop for Continue."
  429. End If
  430. End Method
  431. Method OnCopy:TStmt( scope:TScopeDecl )
  432. If label Then
  433. Return New TContinueStmt.Create(label.Copy(), generated)
  434. Else
  435. Return New TContinueStmt.Create(Null, generated)
  436. End If
  437. End Method
  438. Method Trans$()
  439. Return _trans.TransContinueStmt( Self )
  440. End Method
  441. End Type
  442. Type TIfStmt Extends TStmt
  443. Field expr:TExpr
  444. Field thenBlock:TBlockDecl
  445. Field elseBlock:TBlockDecl
  446. Method Create:TIfStmt( expr:TExpr,thenBlock:TBlockDecl,elseBlock:TBlockDecl, generated:Int = False )
  447. Self.expr=expr
  448. Self.thenBlock=thenBlock
  449. Self.elseBlock=elseBlock
  450. Self.generated = generated
  451. Return Self
  452. End Method
  453. Method OnCopy:TStmt( scope:TScopeDecl )
  454. Local eb:TBlockDecl
  455. If elseBlock Then
  456. eb = elseBlock.CopyBlock( scope )
  457. Else
  458. eb = Null
  459. End If
  460. Return New TIfStmt.Create( expr.Copy(),thenBlock.CopyBlock( scope ),eb, generated )
  461. End Method
  462. Method OnSemant()
  463. expr=expr.SemantAndCast( New TBoolType,CAST_EXPLICIT )
  464. thenBlock.Semant
  465. If elseBlock Then
  466. elseBlock.Semant
  467. End If
  468. End Method
  469. Method Trans$()
  470. Return _trans.TransIfStmt( Self )
  471. End Method
  472. End Type
  473. Type TLoopStmt Extends TStmt
  474. Field loopLabel:TLoopLabelDecl
  475. Field block:TBlockDecl
  476. Method Clear()
  477. block.Clear()
  478. End Method
  479. End Type
  480. Type TWhileStmt Extends TLoopStmt
  481. Field expr:TExpr
  482. Method Create:TWhileStmt( expr:TExpr,block:TBlockDecl,loopLabel:TLoopLabelDecl, generated:Int = False )
  483. Self.expr=expr
  484. Self.block=block
  485. Self.loopLabel = loopLabel
  486. ' If loopLabel Then
  487. block.extra = Self
  488. ' End If
  489. Self.generated = generated
  490. Return Self
  491. End Method
  492. Method OnCopy:TStmt( scope:TScopeDecl )
  493. If loopLabel Then
  494. Return New TWhileStmt.Create( expr.Copy(),block.CopyBlock( scope ),TLoopLabelDecl(loopLabel.Copy()), generated )
  495. Else
  496. Return New TWhileStmt.Create( expr.Copy(),block.CopyBlock( scope ),Null, generated )
  497. End If
  498. End Method
  499. Method OnSemant()
  500. expr=expr.SemantAndCast( New TBoolType,CAST_EXPLICIT )
  501. _loopnest:+1
  502. block.Semant
  503. _loopnest:-1
  504. End Method
  505. Method Trans$()
  506. Return _trans.TransWhileStmt( Self )
  507. End Method
  508. End Type
  509. Type TRepeatStmt Extends TLoopStmt
  510. Field expr:TExpr
  511. Method Create:TRepeatStmt( block:TBlockDecl,expr:TExpr,loopLabel:TLoopLabelDecl )
  512. Self.block=block
  513. Self.expr=expr
  514. Self.loopLabel=loopLabel
  515. ' If loopLabel Then
  516. block.extra = Self
  517. ' End If
  518. Return Self
  519. End Method
  520. Method OnCopy:TStmt( scope:TScopeDecl )
  521. If loopLabel Then
  522. Return New TRepeatStmt.Create( block.CopyBlock( scope ),expr.Copy(),TLoopLabelDecl(loopLabel.Copy()) )
  523. Else
  524. Return New TRepeatStmt.Create( block.CopyBlock( scope ),expr.Copy(),Null )
  525. End If
  526. End Method
  527. Method OnSemant()
  528. _loopnest:+1
  529. block.Semant
  530. _loopnest:-1
  531. expr=expr.SemantAndCast( New TBoolType,CAST_EXPLICIT )
  532. End Method
  533. Method Trans$()
  534. Return _trans.TransRepeatStmt( Self )
  535. End Method
  536. End Type
  537. Type TForStmt Extends TLoopStmt
  538. Field init:TStmt 'assignment or local decl...
  539. Field expr:TExpr
  540. Field incr:TStmt 'assignment...
  541. Method Create:TForStmt( init:TStmt,expr:TExpr,incr:TStmt,block:TBlockDecl,loopLabel:TLoopLabelDecl )
  542. Self.init=init
  543. Self.expr=expr
  544. Self.incr=incr
  545. Self.block=block
  546. Self.loopLabel=loopLabel
  547. ' If loopLabel Then
  548. block.extra = Self
  549. ' End If
  550. Return Self
  551. End Method
  552. Method OnCopy:TStmt( scope:TScopeDecl )
  553. Local b:TBlockDecl = block.CopyBlock( scope )
  554. If loopLabel Then
  555. Return New TForStmt.Create( init.Copy( Null ),expr.Copy(),incr.Copy( Null ),b,TLoopLabelDecl(loopLabel.Copy()) )
  556. Else
  557. Return New TForStmt.Create( init.Copy( Null ),expr.Copy(),incr.Copy(Null),b,Null )
  558. End If
  559. End Method
  560. Method OnSemant()
  561. PushEnv block
  562. Local updateCastTypes:Int
  563. If TAssignStmt(init) And TIdentExpr(TAssignStmt(init).lhs) Then
  564. updateCastTypes = True
  565. Else
  566. ' semant right-hand side first, in case the loop variable is shadowing one from rhs
  567. TBinaryCompareExpr(expr).rhs = TBinaryCompareExpr(expr).rhs.Semant()
  568. End If
  569. init.Semant
  570. If updateCastTypes Then
  571. ' ty in the casts are currently Null - we didn't know at the time of creating the statement, what the variable type was.
  572. ' Now we do, so we'll fill in the gaps.
  573. TCastExpr(TBinaryCompareExpr(expr).rhs).ty = TAssignStmt(init).lhs.exprType.Copy()
  574. TCastExpr(TBinaryMathExpr(TAssignStmt(incr).rhs).rhs).ty = TAssignStmt(init).lhs.exprType.Copy()
  575. End If
  576. ' scope for expression part should be block-scope
  577. expr=expr.Semant()
  578. PopEnv
  579. ' for anything other than a const value, use a new local variable
  580. If Not TConstExpr(TBinaryCompareExpr(expr).rhs) Then
  581. Local ty:TType = TBinaryCompareExpr(expr).rhs.exprType.Copy()
  582. If ty._flags & TType.T_VAR Then
  583. ty._flags :~ TType.T_VAR ' remove var for local variable
  584. End If
  585. Local tmp:TLocalDecl=New TLocalDecl.Create( "", ty,TBinaryCompareExpr(expr).rhs,, True )
  586. tmp.Semant()
  587. Local v:TVarExpr = New TVarExpr.Create( tmp )
  588. TBinaryCompareExpr(expr).rhs = New TStmtExpr.Create( New TDeclStmt.Create( tmp ), v ).Semant()
  589. End If
  590. _loopnest:+1
  591. block.Semant
  592. _loopnest:-1
  593. ' scope for increment part is also block-scope
  594. PushEnv block
  595. incr.Semant
  596. PopEnv
  597. 'dodgy as hell! Reverse comparison for backward loops!
  598. Local assop:TAssignStmt=TAssignStmt( incr )
  599. Local addop:TBinaryExpr=TBinaryExpr( assop.rhs )
  600. Local stpval$=addop.rhs.Eval()
  601. If stpval.StartsWith( "-" )
  602. Local bexpr:TBinaryExpr=TBinaryExpr( expr )
  603. Select bexpr.op
  604. Case "<" bexpr.op=">"
  605. Case "<=" bexpr.op=">="
  606. End Select
  607. EndIf
  608. End Method
  609. Method Trans$()
  610. Return _trans.TransForStmt( Self )
  611. End Method
  612. End Type
  613. Type TAssertStmt Extends TStmt
  614. Field expr:TExpr
  615. Field elseExpr:TExpr
  616. Method Create:TAssertStmt( expr:TExpr, elseExpr:TExpr )
  617. Self.expr=expr
  618. Self.elseExpr=elseExpr
  619. Return Self
  620. End Method
  621. Method OnCopy:TStmt( scope:TScopeDecl )
  622. If elseExpr Then
  623. Return New TAssertStmt.Create( expr.Copy(),elseExpr.Copy() )
  624. Else
  625. Return New TAssertStmt.Create( expr.Copy(), Null )
  626. End If
  627. End Method
  628. Method OnSemant()
  629. expr=expr.SemantAndCast( New TBoolType,CAST_EXPLICIT )
  630. If elseExpr Then
  631. elseExpr = elseExpr.SemantAndCast(New TStringType,CAST_EXPLICIT)
  632. Else
  633. elseExpr = New TConstExpr.Create(New TStringType, "Assert failed")
  634. End If
  635. End Method
  636. Method Trans$()
  637. Return _trans.TransAssertStmt( Self )
  638. End Method
  639. End Type
  640. Type TEndStmt Extends TStmt
  641. Method Create:TEndStmt( )
  642. Return Self
  643. End Method
  644. Method OnCopy:TStmt( scope:TScopeDecl )
  645. Return New TEndStmt.Create( )
  646. End Method
  647. Method OnSemant()
  648. End Method
  649. Method Trans$()
  650. Return _trans.TransEndStmt( Self )
  651. End Method
  652. End Type
  653. Type TReleaseStmt Extends TStmt
  654. Field expr:TExpr
  655. Method Create:TReleaseStmt( expr:TExpr )
  656. Self.expr=expr
  657. Return Self
  658. End Method
  659. Method OnCopy:TStmt( scope:TScopeDecl )
  660. Return New TReleaseStmt.Create( expr.Copy() )
  661. End Method
  662. Method OnSemant()
  663. expr=expr.Semant()
  664. If Not TVarExpr( expr ) And Not TMemberVarExpr( expr) And Not TIndexExpr( expr ) err "Expression must be a variable"
  665. If Not TNumericType(expr.exprType) Err "Subexpression for release must be an integer variable"
  666. End Method
  667. Method Trans$()
  668. Return _trans.TransReleaseStmt( Self )
  669. End Method
  670. End Type
  671. Type TReadDataStmt Extends TStmt
  672. Field args:TExpr[]
  673. Method Create:TReadDataStmt( args:TExpr[] )
  674. Self.args=args
  675. Return Self
  676. End Method
  677. Method OnCopy:TStmt( scope:TScopeDecl )
  678. Return New TReadDataStmt.Create( TExpr.CopyArgs(args) )
  679. End Method
  680. Method OnSemant()
  681. If args Then
  682. For Local i:Int = 0 Until args.length
  683. args[i]=args[i].Semant()
  684. Local arg:TExpr = args[i]
  685. If Not TVarExpr(arg) And Not TMemberVarExpr(arg) And Not TIndexExpr(arg) And Not (TStmtExpr(arg) And TIndexExpr(TStmtExpr(arg).expr)) Then
  686. Err "Expression must be a variable"
  687. End If
  688. Next
  689. End If
  690. End Method
  691. Method Trans$()
  692. Return _trans.TransReadDataStmt( Self )
  693. End Method
  694. End Type
  695. Type TRestoreDataStmt Extends TStmt
  696. Field label:TExpr
  697. Method Create:TRestoreDataStmt( label:TExpr )
  698. Self.label=label
  699. Return Self
  700. End Method
  701. Method OnCopy:TStmt( scope:TScopeDecl )
  702. Return New TRestoreDataStmt.Create( label.Copy() )
  703. End Method
  704. Method OnSemant()
  705. If label
  706. Local id:String
  707. If TIdentExpr(label) id = "'" + TIdentExpr(label).ident + "'"
  708. label = label.Semant(OPTION_WANT_DATA_LABEL)
  709. If Not TDataLabelExpr(label) Err "Data label " + id + " not found"
  710. Else
  711. Err "Expecting label"
  712. End If
  713. End Method
  714. Method Trans$()
  715. Return _trans.TransRestoreDataStmt( Self )
  716. End Method
  717. End Type
  718. Type TNativeStmt Extends TStmt
  719. Field raw:String
  720. Method Create:TNativeStmt( raw:String )
  721. Self.raw = raw
  722. Return Self
  723. End Method
  724. Method OnCopy:TStmt( scope:TScopeDecl )
  725. Return New TNativeStmt.Create( raw )
  726. End Method
  727. Method OnSemant()
  728. End Method
  729. Method Trans$()
  730. Return _trans.TransNativeStmt( Self )
  731. End Method
  732. End Type
  733. Type TUsingStmt Extends TStmt
  734. Field locals:TLocalDecl[]
  735. Field localInitExprs:TExpr[]
  736. Field wrapperBlock:TBlockDecl
  737. Field block:TBlockDecl
  738. Method Create:TUsingStmt( locals:TLocalDecl[], wrapperBlock:TBlockDecl, block:TBlockDecl )
  739. Self.locals=locals
  740. Self.wrapperBlock=wrapperBlock
  741. Self.block=block
  742. Return Self
  743. End Method
  744. Method OnCopy:TStmt( scope:TScopeDecl )
  745. Return New TUsingStmt.Create( locals[..], wrapperBlock.CopyBlock( scope ), block.CopyBlock( scope ) )
  746. End Method
  747. Method OnSemant()
  748. ' Using creates the following code from:
  749. ' Using
  750. ' Local v:TSomeCloseableType = New TSomeCloseableType()
  751. ' Local b:...
  752. ' Do
  753. ' ' do stuff
  754. ' End Using
  755. '
  756. ' Produces:
  757. ' <wrapperBlock>
  758. ' Local v:TSomeCloseableType
  759. ' Local b:...
  760. ' Try
  761. ' <block>
  762. ' v = New TSomeCloseableType()
  763. ' b = ...
  764. ' ' do stuff
  765. ' </block>
  766. ' Finally
  767. ' If b Then
  768. ' Try
  769. ' b.Close()
  770. ' Catch e:Object
  771. ' End Try
  772. ' End If
  773. ' If v Then
  774. ' Try
  775. ' v.Close()
  776. ' Catch e:Object
  777. ' End Try
  778. ' End If
  779. ' End Try
  780. ' </wrapperBlock>
  781. '
  782. PushEnv wrapperBlock
  783. localInitExprs = New TExpr[ locals.Length ]
  784. Local i:Int
  785. For Local decl:TDecl = Eachin locals
  786. If Not TLocalDecl(decl) Then
  787. PushErr decl.errInfo
  788. Err "Only local declarations are allowed in Using statements"
  789. End If
  790. Local ldecl:TLocalDecl = TLocalDecl(decl)
  791. localInitExprs[i] = ldecl.declInit
  792. ldecl.declInit = New TNullExpr.Create( TType.nullObjectType )
  793. ldecl.volatile = True
  794. ldecl.Semant()
  795. Local ty:TObjectType = TObjectType( ldecl.ty )
  796. If ty Then
  797. ty.classDecl.Semant()
  798. End If
  799. If Not ty Or Not ty.classDecl.IsCloseable() Then
  800. PushErr ldecl.errInfo
  801. If Not ty Then
  802. Err "Unexpected type " + ldecl.ty.ToString() + " in Using statement"
  803. Else
  804. Err "Type " + ldecl.ty.ToString() + " does not implement ICloseable interface"
  805. End If
  806. End If
  807. wrapperBlock.InsertDecl( ldecl )
  808. ldecl.Semant()
  809. Local sdecl:TDeclStmt = New TDeclStmt.Create( ldecl )
  810. wrapperBlock.AddStmt( sdecl )
  811. sdecl.Semant()
  812. i:+1
  813. Next
  814. Local tryStmtDecl:TTryStmtDecl = TTryStmtDecl(New TTryStmtDecl.Create( wrapperBlock ))
  815. block.scope = tryStmtDecl
  816. block.blockType = BLOCK_TRY
  817. ' Add local assignments to beginning of try block - must be inserted to the front in reverse order.
  818. For Local j:Int = locals.Length - 1 To 0 Step -1
  819. Local ldecl:TLocalDecl = locals[j]
  820. Local assignStmt:TAssignStmt = New TAssignStmt.Create( "=", New TVarExpr.Create( ldecl ), localInitExprs[j] )
  821. block.stmts.AddFirst( assignStmt )
  822. assignStmt.Semant()
  823. ldecl.attrs :| DECL_READ_ONLY
  824. Next
  825. ' build Finally, processing each local in reverse order
  826. Local finallyBlock:TBlockDecl = New TBlockDecl.Create(block, , BLOCK_FINALLY )
  827. Local finallyStmt:TFinallyStmt = New TFinallyStmt.Create(finallyBlock)
  828. For Local i:Int = locals.Length - 1 To 0 Step -1
  829. Local ldecl:TLocalDecl = locals[i]
  830. ' If <local> Then
  831. ' Try
  832. ' <local>.Close()
  833. ' Catch e:Object
  834. ' End Try
  835. ' End If
  836. Local ifStmt:TIfStmt = New TIfStmt.Create(New TVarExpr.Create( ldecl ), New TBlockDecl.Create(finallyBlock, , BLOCK_IF ), Null )
  837. Local tryStmt:TTryStmt = GenerateCloseTryCatch( ldecl, ifStmt.thenBlock )
  838. ifStmt.thenBlock.AddStmt( tryStmt )
  839. ifStmt.Semant()
  840. finallyBlock.AddStmt( ifStmt )
  841. Next
  842. ' generate TryStmt
  843. Local tryStmt:TTryStmt = New TTryStmt.Create( block, [], finallyStmt )
  844. tryStmtDecl.tryStmt = tryStmt
  845. wrapperBlock.AddStmt( tryStmt )
  846. wrapperBlock.Semant()
  847. PopEnv ' wrapperBlock
  848. End Method
  849. Method GenerateCloseTryCatch:TTryStmt( ldecl:TLocalDecl, block:TBlockDecl )
  850. Local tryStmtDecl:TTryStmtDecl = TTryStmtDecl(New TTryStmtDecl.Create( block ))
  851. Local tryBlock:TBlockDecl = New TBlockDecl.Create( tryStmtDecl, , BLOCK_TRY )
  852. Local ty:TObjectType = TObjectType( ldecl.ty )
  853. Local invokeClose:TInvokeMemberExpr = New TInvokeMemberExpr.Create(New TVarExpr.Create( ldecl ), ty.classDecl.FindFuncDecl( "close",,,,,,SCOPE_CLASS_HEIRARCHY),[])
  854. tryBlock.AddStmt( New TExprStmt.Create( invokeClose ) )
  855. Local catchBlock:TBlockDecl = New TBlockDecl.Create( tryBlock, , BLOCK_CATCH )
  856. Local catchDecl:TLocalDecl = New TLocalDecl.Create( "e", TType.objectType, Null )
  857. Local catchStmt:TCatchStmt = New TCatchStmt.Create( catchDecl, catchBlock )
  858. catchStmt.Semant()
  859. Local stmt:TTryStmt = New TTryStmt.Create( tryBlock, [catchStmt], Null )
  860. tryStmtDecl.tryStmt = stmt
  861. Return stmt
  862. End Method
  863. Method Trans$()
  864. Return _trans.TransUsingStmt( Self )
  865. End Method
  866. End Type