stmt.bmx 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870
  1. ' Copyright (c) 2013-2024 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. Method New()
  29. errInfo=_errInfo
  30. End Method
  31. Method OnCopy:TStmt( scope:TScopeDecl ) Abstract
  32. Method Semant()
  33. PushErr errInfo
  34. OnSemant
  35. PopErr
  36. End Method
  37. Method Copy:TStmt( scope:TScopeDecl )
  38. Local t:TStmt=OnCopy( scope )
  39. t.errInfo=errInfo
  40. Return t
  41. End Method
  42. Method OnSemant() Abstract
  43. Method Trans$() Abstract
  44. Method Clear()
  45. End Method
  46. End Type
  47. Type TDeclStmt Extends TStmt
  48. Field decl:TDecl
  49. Method Create:TDeclStmt( decl:TDecl, generated:Int = False )
  50. Self.decl=decl
  51. Self.generated = generated
  52. Return Self
  53. End Method
  54. Method CreateWithId:TDeclStmt( id$,ty:TType,init:TExpr )
  55. Self.decl=New TLocalDecl.Create( id,ty,init,0 )
  56. Return Self
  57. End Method
  58. Method OnCopy:TStmt( scope:TScopeDecl )
  59. Local d:TDecl = decl.Copy()
  60. 'If Not d.scope Then
  61. d.scope = Null
  62. 'End If
  63. Return New TDeclStmt.Create( d, generated )
  64. End Method
  65. Method OnSemant()
  66. If TLocalDecl(decl) Then
  67. Local tryStmtDecl:TTryStmtDecl = _env.FindTry()
  68. If tryStmtDecl Then
  69. TLocalDecl(decl).declaredInTry = tryStmtDecl
  70. End If
  71. End If
  72. decl.Semant
  73. ' if scope is already set, don't try to add it to the current scope.
  74. If Not decl.scope Then
  75. _env.InsertDecl decl
  76. End If
  77. End Method
  78. Method Trans$()
  79. Return _trans.TransDeclStmt( Self )
  80. End Method
  81. Method Clear()
  82. decl.Clear()
  83. End Method
  84. End Type
  85. Type TAssignStmt Extends TStmt
  86. Field op$
  87. Field lhs:TExpr
  88. Field rhs:TExpr
  89. Method Create:TAssignStmt( op$,lhs:TExpr,rhs:TExpr, generated:Int = False )
  90. Self.op=op
  91. Self.lhs=lhs
  92. Self.rhs=rhs
  93. Self.generated = generated
  94. Return Self
  95. End Method
  96. Method OnCopy:TStmt( scope:TScopeDecl )
  97. Return New TAssignStmt.Create( op,lhs.Copy(),rhs.Copy(), generated )
  98. End Method
  99. Method OnSemant()
  100. If TIdentExpr(rhs) Then
  101. TIdentExpr(rhs).isRhs = True
  102. End If
  103. rhs=rhs.Semant()
  104. lhs=lhs.SemantSet( op,rhs )
  105. If TInvokeExpr( lhs ) Or TInvokeMemberExpr( lhs )
  106. rhs=Null
  107. Else
  108. ' can't assign to readonly field outside of its class constructor, or anytime for readonly variable
  109. If TVarExpr(lhs) Or TMemberVarExpr(lhs) Then
  110. Local decl:TDecl
  111. If TVarExpr(lhs) Then
  112. decl = TVarExpr(lhs).decl
  113. Else
  114. Local mvExpr:TMemberVarExpr = TMemberVarExpr(lhs)
  115. decl = mvExpr.decl
  116. If TFieldDecl(decl) And (TInvokeExpr(mvExpr.expr) Or TInvokeMemberExpr(mvExpr.expr)) Then
  117. If TClassDecl(decl.scope) And TClassDecl(decl.scope).IsStruct() Then
  118. rhs = Null
  119. Warn "Discarding Field assignment of Struct returned via invocation"
  120. Return
  121. End If
  122. End If
  123. End If
  124. If decl And decl.IsReadOnly() Then
  125. If TFieldDecl(decl) Then
  126. ' check scope for ctor
  127. Local scope:TFuncDecl = _env.FuncScope()
  128. If Not scope Or Not scope.IsCtor() Or (Not scope.ClassScope().ExtendsClass(decl.ClassScope())) Then
  129. Err "Cannot modify ReadOnly field " + decl.ident
  130. End If
  131. Else
  132. Err "Cannot modify ReadOnly variable " + decl.ident
  133. End If
  134. End If
  135. If TValDecl(decl) And TArrayType(TValDecl(decl).ty) And TArrayType(TValDecl(decl).ty).isStatic Then
  136. Err "Static arrays cannot be assigned in this way."
  137. End If
  138. End If
  139. If IsPointerType(lhs.exprType, 0, TType.T_POINTER | TType.T_VARPTR) And TNumericType(rhs.exprType) Then
  140. ' with pointer assignment we don't cast the numeric to a pointer
  141. Else If IsPointerType(lhs.exprType, 0, TType.T_VAR) And TNumericType(rhs.exprType) Then
  142. ' for var, we cast to the non-var type
  143. Local ty:TType = lhs.exprType.Copy()
  144. ty._flags :~ TType.T_VAR
  145. rhs=rhs.Cast( ty )
  146. Else
  147. Local splitOp:Int = True
  148. Select op
  149. Case "="
  150. rhs=rhs.Cast( lhs.exprType )
  151. splitOp = False
  152. Case ":*",":/",":+",":-"
  153. If TNumericType( lhs.exprType ) And lhs.exprType.EqualsType( rhs.exprType ) Then
  154. splitOp = False
  155. End If
  156. If TObjectType(lhs.exprType) Then
  157. Local args:TExpr[] = [rhs]
  158. Try
  159. Local decl:TFuncDecl = TFuncDecl(TObjectType(lhs.exprType).classDecl.FindFuncDecl(op, args,,,,True,SCOPE_CLASS_HEIRARCHY))
  160. If decl Then
  161. lhs = New TInvokeMemberExpr.Create( lhs, decl, args ).Semant()
  162. rhs = Null
  163. Return
  164. End If
  165. Catch error:String
  166. Err "Operator " + op + " cannot be used with Objects."
  167. End Try
  168. End If
  169. Case ":&",":|",":^",":shl",":shr",":mod"
  170. If (TIntType( lhs.exprType ) And lhs.exprType.EqualsType( rhs.exprType )) Or TObjectType(lhs.exprType) Then
  171. splitOp = False
  172. End If
  173. If TObjectType(lhs.exprType) Then
  174. Local args:TExpr[] = [rhs]
  175. Try
  176. Local decl:TFuncDecl = TFuncDecl(TObjectType(lhs.exprType).classDecl.FindFuncDecl(op, args,,,,,SCOPE_CLASS_HEIRARCHY))
  177. If decl Then
  178. lhs = New TInvokeMemberExpr.Create( lhs, decl, args ).Semant()
  179. rhs = Null
  180. Return
  181. End If
  182. Catch error:String
  183. Err "Operator " + op + " cannot be used with Objects."
  184. End Try
  185. End If
  186. End Select
  187. If splitOp Then
  188. rhs = New TBinaryMathExpr.Create(op[1..], lhs, rhs).Semant().Cast(lhs.exprType)
  189. op = "="
  190. End If
  191. End If
  192. EndIf
  193. End Method
  194. Method Trans$()
  195. _errInfo=errInfo
  196. Return _trans.TransAssignStmt( Self )
  197. End Method
  198. End Type
  199. Type TExprStmt Extends TStmt
  200. Field expr:TExpr
  201. Method Create:TExprStmt( expr:TExpr )
  202. Self.expr=expr
  203. Return Self
  204. End Method
  205. Method OnCopy:TStmt( scope:TScopeDecl )
  206. Return New TExprStmt.Create( expr.Copy() )
  207. End Method
  208. Method OnSemant()
  209. expr=expr.Semant()
  210. If Not expr InternalErr "TExprStmt.OnSemant"
  211. End Method
  212. Method Trans$()
  213. Return _trans.TransExprStmt( Self )
  214. End Method
  215. End Type
  216. Type TReturnStmt Extends TStmt
  217. Field expr:TExpr
  218. Field fRetType:TType
  219. Method Create:TReturnStmt( expr:TExpr )
  220. Self.expr=expr
  221. Return Self
  222. End Method
  223. Method OnCopy:TStmt( scope:TScopeDecl )
  224. Local r:TReturnStmt
  225. If expr Then
  226. r = New TReturnStmt.Create( expr.Copy() )
  227. Else
  228. r = New TReturnStmt.Create( Null )
  229. End If
  230. r.fRetType = fRetType
  231. Return r
  232. End Method
  233. Method OnSemant()
  234. Local fdecl:TFuncDecl=_env.FuncScope()
  235. fRetType = fdecl.retType
  236. If expr
  237. If TIdentExpr(expr) Then
  238. TIdentExpr(expr).isRhs = True
  239. End If
  240. If fdecl.IsCtor() Err "Constructors may not return a value."
  241. If TVoidType( fRetType ) Then
  242. Local errorText:String = "Function can not return a value."
  243. If Not _env.ModuleScope().IsSuperStrict() Then
  244. errorText :+ " You may have Strict type overriding SuperStrict type."
  245. End If
  246. Err errorText
  247. End If
  248. expr=expr.SemantAndCast( fRetType )
  249. If TIdentTypeExpr(expr) Err "Function must return a value."
  250. Else If fdecl.IsCtor()
  251. ' ctors do not return anything
  252. Else If Not TVoidType( fRetType )
  253. If _env.ModuleScope().IsSuperStrict() Err "Function must return a value"
  254. expr=New TConstExpr.Create( fRetType ,"" ).Semant()
  255. EndIf
  256. End Method
  257. Method Trans$()
  258. Return _trans.TransReturnStmt( Self )
  259. End Method
  260. End Type
  261. Type TTryStmt Extends TStmt
  262. Field block:TBlockDecl
  263. Field catches:TCatchStmt[]
  264. Field finallyStmt:TFinallyStmt
  265. Field rethrowLabel:TLoopLabelDecl
  266. Field endTryLabel:TLoopLabelDecl
  267. Method Create:TTryStmt( block:TBlockDecl,catches:TCatchStmt[],finallyStmt:TFinallyStmt )
  268. Self.block=block
  269. Self.catches=catches
  270. Self.finallyStmt=finallyStmt
  271. Self.rethrowLabel = New TLoopLabelDecl.Create("rethrow")
  272. Self.endTryLabel = New TLoopLabelDecl.Create("endtry")
  273. Return Self
  274. End Method
  275. Method OnCopy:TStmt( scope:TScopeDecl )
  276. Local catchCopies:TCatchStmt[] = Self.catches[..]
  277. For Local i:Int = 0 Until catchCopies.Length
  278. catchCopies[i] = TCatchStmt(catchCopies[i].Copy(scope))
  279. Next
  280. Local finallyCopy:TFinallyStmt = Null
  281. If finallyStmt Then finallyCopy = TFinallyStmt(finallyStmt.Copy(scope))
  282. Return New TTryStmt.Create(block.CopyBlock(scope), catchCopies, finallyCopy)
  283. End Method
  284. Method OnSemant()
  285. block.Semant
  286. Local hasObject:Int = False
  287. For Local i:Int = 0 Until catches.Length
  288. catches[i].Semant
  289. If hasObject Then
  290. PushErr catches[i].errInfo
  291. Err "Catch variable class extends earlier catch variable class"
  292. End If
  293. If TObjectType(catches[i].init.ty) And TObjectType(catches[i].init.ty).classdecl.ident = "Object" Then
  294. hasObject = True
  295. Continue
  296. End If
  297. For Local j:Int = 0 Until i
  298. If catches[i].init.ty.ExtendsType( catches[j].init.ty )
  299. PushErr catches[i].errInfo
  300. Err "Catch variable class extends earlier catch variable class"
  301. EndIf
  302. Next
  303. Next
  304. If finallyStmt Then finallyStmt.Semant
  305. End Method
  306. Method Trans$()
  307. Return _trans.TransTryStmt( Self )
  308. End Method
  309. End Type
  310. Type TCatchStmt Extends TStmt
  311. Field init:TLocalDecl
  312. Field block:TBlockDecl
  313. Method Create:TCatchStmt( init:TLocalDecl,block:TBlockDecl )
  314. Self.init=init
  315. Self.block=block
  316. Return Self
  317. End Method
  318. Method OnCopy:TStmt( scope:TScopeDecl )
  319. Return New TCatchStmt.Create( TLocalDecl( init.Copy() ),block.CopyBlock( scope ) )
  320. End Method
  321. Method OnSemant()
  322. init.Semant
  323. 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"
  324. block.InsertDecl init
  325. block.Semant
  326. End Method
  327. Method Trans$()
  328. End Method
  329. End Type
  330. Type TFinallyStmt Extends TStmt
  331. Field block:TBlockDecl
  332. Field finallyLabel:TLoopLabelDecl
  333. Field returnLabelPtrDecl:TLocalDecl
  334. Method Create:TFinallyStmt( block:TBlockDecl )
  335. Self.block=block
  336. Self.finallyLabel = New TLoopLabelDecl.Create("finally")
  337. Return Self
  338. End Method
  339. Method OnCopy:TStmt( scope:TScopeDecl )
  340. Return New TFinallyStmt.Create( block.CopyBlock( scope ) )
  341. End Method
  342. Method OnSemant()
  343. block.Semant
  344. End Method
  345. Method Trans$()
  346. End Method
  347. End Type
  348. Type TThrowStmt Extends TStmt
  349. Field expr:TExpr
  350. Method Create:TThrowStmt( expr:TExpr )
  351. Self.expr=expr
  352. Return Self
  353. End Method
  354. Method OnCopy:TStmt( scope:TScopeDecl )
  355. Return New TThrowStmt.Create( expr.Copy() )
  356. End Method
  357. Method OnSemant()
  358. expr=expr.Semant()
  359. 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"
  360. End Method
  361. Method Trans$()
  362. ' TODO
  363. Return _trans.TransThrowStmt( Self )
  364. End Method
  365. End Type
  366. Type TLoopControlStmt Extends TStmt Abstract
  367. Field loop:TLoopStmt
  368. Field label:TExpr
  369. End Type
  370. Type TBreakStmt Extends TLoopControlStmt
  371. Method Create:TBreakStmt( label:TExpr )
  372. Self.label=label
  373. Return Self
  374. End Method
  375. Method OnSemant()
  376. If Not _loopnest Err "Exit statement must appear inside a loop."
  377. If label Then
  378. Local id:String
  379. If TIdentExpr(label) id = "'" + TIdentExpr(label).ident + "'"
  380. label = label.Semant(OPTION_WANT_LOOP_LABEL)
  381. If Not TLoopLabelExpr(label) Err "Continue/Exit label " + id + " not found"
  382. End If
  383. If opt_debug And Not loop Then
  384. loop = TLoopStmt(_env.FindLoop())
  385. If Not loop Err "Cannot find loop for Exit."
  386. End If
  387. End Method
  388. Method OnCopy:TStmt( scope:TScopeDecl )
  389. If label Then
  390. Return New TBreakStmt.Create(label.Copy())
  391. Else
  392. Return New TBreakStmt.Create(Null)
  393. End If
  394. End Method
  395. Method Trans$()
  396. Return _trans.TransBreakStmt( Self )
  397. End Method
  398. End Type
  399. Type TContinueStmt Extends TLoopControlStmt
  400. Method Create:TContinueStmt( label:TExpr, generated:Int = False )
  401. Self.label=label
  402. Self.generated = generated
  403. Return Self
  404. End Method
  405. Method OnSemant()
  406. If Not _loopnest Err "Continue statement must appear inside a loop."
  407. If label Then
  408. Local id:String
  409. If TIdentExpr(label) id = "'" + TIdentExpr(label).ident + "'"
  410. label = label.Semant(OPTION_WANT_LOOP_LABEL)
  411. If Not TLoopLabelExpr(label) Err "Continue/Exit label " + id + " not found"
  412. End If
  413. If opt_debug And Not loop Then
  414. loop = TLoopStmt(_env.FindLoop())
  415. If Not loop Err "Cannot find loop for Continue."
  416. End If
  417. End Method
  418. Method OnCopy:TStmt( scope:TScopeDecl )
  419. If label Then
  420. Return New TContinueStmt.Create(label.Copy(), generated)
  421. Else
  422. Return New TContinueStmt.Create(Null, generated)
  423. End If
  424. End Method
  425. Method Trans$()
  426. Return _trans.TransContinueStmt( Self )
  427. End Method
  428. End Type
  429. Type TIfStmt Extends TStmt
  430. Field expr:TExpr
  431. Field thenBlock:TBlockDecl
  432. Field elseBlock:TBlockDecl
  433. Method Create:TIfStmt( expr:TExpr,thenBlock:TBlockDecl,elseBlock:TBlockDecl, generated:Int = False )
  434. Self.expr=expr
  435. Self.thenBlock=thenBlock
  436. Self.elseBlock=elseBlock
  437. Self.generated = generated
  438. Return Self
  439. End Method
  440. Method OnCopy:TStmt( scope:TScopeDecl )
  441. Return New TIfStmt.Create( expr.Copy(),thenBlock.CopyBlock( scope ),elseBlock.CopyBlock( scope ), generated )
  442. End Method
  443. Method OnSemant()
  444. expr=expr.SemantAndCast( New TBoolType,CAST_EXPLICIT )
  445. thenBlock.Semant
  446. elseBlock.Semant
  447. End Method
  448. Method Trans$()
  449. Return _trans.TransIfStmt( Self )
  450. End Method
  451. End Type
  452. Type TLoopStmt Extends TStmt
  453. Field loopLabel:TLoopLabelDecl
  454. Field block:TBlockDecl
  455. Method Clear()
  456. block.Clear()
  457. End Method
  458. End Type
  459. Type TWhileStmt Extends TLoopStmt
  460. Field expr:TExpr
  461. Method Create:TWhileStmt( expr:TExpr,block:TBlockDecl,loopLabel:TLoopLabelDecl, generated:Int = False )
  462. Self.expr=expr
  463. Self.block=block
  464. Self.loopLabel = loopLabel
  465. ' If loopLabel Then
  466. block.extra = Self
  467. ' End If
  468. Self.generated = generated
  469. Return Self
  470. End Method
  471. Method OnCopy:TStmt( scope:TScopeDecl )
  472. If loopLabel Then
  473. Return New TWhileStmt.Create( expr.Copy(),block.CopyBlock( scope ),TLoopLabelDecl(loopLabel.Copy()), generated )
  474. Else
  475. Return New TWhileStmt.Create( expr.Copy(),block.CopyBlock( scope ),Null, generated )
  476. End If
  477. End Method
  478. Method OnSemant()
  479. expr=expr.SemantAndCast( New TBoolType,CAST_EXPLICIT )
  480. _loopnest:+1
  481. block.Semant
  482. _loopnest:-1
  483. End Method
  484. Method Trans$()
  485. Return _trans.TransWhileStmt( Self )
  486. End Method
  487. End Type
  488. Type TRepeatStmt Extends TLoopStmt
  489. Field expr:TExpr
  490. Method Create:TRepeatStmt( block:TBlockDecl,expr:TExpr,loopLabel:TLoopLabelDecl )
  491. Self.block=block
  492. Self.expr=expr
  493. Self.loopLabel=loopLabel
  494. ' If loopLabel Then
  495. block.extra = Self
  496. ' End If
  497. Return Self
  498. End Method
  499. Method OnCopy:TStmt( scope:TScopeDecl )
  500. If loopLabel Then
  501. Return New TRepeatStmt.Create( block.CopyBlock( scope ),expr.Copy(),TLoopLabelDecl(loopLabel.Copy()) )
  502. Else
  503. Return New TRepeatStmt.Create( block.CopyBlock( scope ),expr.Copy(),Null )
  504. End If
  505. End Method
  506. Method OnSemant()
  507. _loopnest:+1
  508. block.Semant
  509. _loopnest:-1
  510. expr=expr.SemantAndCast( New TBoolType,CAST_EXPLICIT )
  511. End Method
  512. Method Trans$()
  513. Return _trans.TransRepeatStmt( Self )
  514. End Method
  515. End Type
  516. Type TForStmt Extends TLoopStmt
  517. Field init:TStmt 'assignment or local decl...
  518. Field expr:TExpr
  519. Field incr:TStmt 'assignment...
  520. Method Create:TForStmt( init:TStmt,expr:TExpr,incr:TStmt,block:TBlockDecl,loopLabel:TLoopLabelDecl )
  521. Self.init=init
  522. Self.expr=expr
  523. Self.incr=incr
  524. Self.block=block
  525. Self.loopLabel=loopLabel
  526. ' If loopLabel Then
  527. block.extra = Self
  528. ' End If
  529. Return Self
  530. End Method
  531. Method OnCopy:TStmt( scope:TScopeDecl )
  532. Local b:TBlockDecl = block.CopyBlock( scope )
  533. If loopLabel Then
  534. Return New TForStmt.Create( init.Copy( Null ),expr.Copy(),incr.Copy( Null ),b,TLoopLabelDecl(loopLabel.Copy()) )
  535. Else
  536. Return New TForStmt.Create( init.Copy( Null ),expr.Copy(),incr.Copy(Null),b,Null )
  537. End If
  538. End Method
  539. Method OnSemant()
  540. PushEnv block
  541. Local updateCastTypes:Int
  542. If TAssignStmt(init) And TIdentExpr(TAssignStmt(init).lhs) Then
  543. updateCastTypes = True
  544. Else
  545. ' semant right-hand side first, in case the loop variable is shadowing one from rhs
  546. TBinaryCompareExpr(expr).rhs = TBinaryCompareExpr(expr).rhs.Semant()
  547. End If
  548. init.Semant
  549. If updateCastTypes Then
  550. ' ty in the casts are currently Null - we didn't know at the time of creating the statement, what the variable type was.
  551. ' Now we do, so we'll fill in the gaps.
  552. TCastExpr(TBinaryCompareExpr(expr).rhs).ty = TAssignStmt(init).lhs.exprType.Copy()
  553. TCastExpr(TBinaryMathExpr(TAssignStmt(incr).rhs).rhs).ty = TAssignStmt(init).lhs.exprType.Copy()
  554. End If
  555. ' scope for expression part should be block-scope
  556. expr=expr.Semant()
  557. PopEnv
  558. ' for anything other than a const value, use a new local variable
  559. If Not TConstExpr(TBinaryCompareExpr(expr).rhs) Then
  560. Local ty:TType = TBinaryCompareExpr(expr).rhs.exprType.Copy()
  561. If ty._flags & TType.T_VAR Then
  562. ty._flags :~ TType.T_VAR ' remove var for local variable
  563. End If
  564. Local tmp:TLocalDecl=New TLocalDecl.Create( "", ty,TBinaryCompareExpr(expr).rhs,, True )
  565. tmp.Semant()
  566. Local v:TVarExpr = New TVarExpr.Create( tmp )
  567. TBinaryCompareExpr(expr).rhs = New TStmtExpr.Create( New TDeclStmt.Create( tmp ), v ).Semant()
  568. End If
  569. _loopnest:+1
  570. block.Semant
  571. _loopnest:-1
  572. ' scope for increment part is also block-scope
  573. PushEnv block
  574. incr.Semant
  575. PopEnv
  576. 'dodgy as hell! Reverse comparison for backward loops!
  577. Local assop:TAssignStmt=TAssignStmt( incr )
  578. Local addop:TBinaryExpr=TBinaryExpr( assop.rhs )
  579. Local stpval$=addop.rhs.Eval()
  580. If stpval.StartsWith( "-" )
  581. Local bexpr:TBinaryExpr=TBinaryExpr( expr )
  582. Select bexpr.op
  583. Case "<" bexpr.op=">"
  584. Case "<=" bexpr.op=">="
  585. End Select
  586. EndIf
  587. End Method
  588. Method Trans$()
  589. Return _trans.TransForStmt( Self )
  590. End Method
  591. End Type
  592. Type TAssertStmt Extends TStmt
  593. Field expr:TExpr
  594. Field elseExpr:TExpr
  595. Method Create:TAssertStmt( expr:TExpr, elseExpr:TExpr )
  596. Self.expr=expr
  597. Self.elseExpr=elseExpr
  598. Return Self
  599. End Method
  600. Method OnCopy:TStmt( scope:TScopeDecl )
  601. If elseExpr Then
  602. Return New TAssertStmt.Create( expr.Copy(),elseExpr.Copy() )
  603. Else
  604. Return New TAssertStmt.Create( expr.Copy(), Null )
  605. End If
  606. End Method
  607. Method OnSemant()
  608. expr=expr.SemantAndCast( New TBoolType,CAST_EXPLICIT )
  609. If elseExpr Then
  610. elseExpr = elseExpr.SemantAndCast(New TStringType,CAST_EXPLICIT)
  611. Else
  612. elseExpr = New TConstExpr.Create(New TStringType, "Assert failed")
  613. End If
  614. End Method
  615. Method Trans$()
  616. Return _trans.TransAssertStmt( Self )
  617. End Method
  618. End Type
  619. Type TEndStmt Extends TStmt
  620. Method Create:TEndStmt( )
  621. Return Self
  622. End Method
  623. Method OnCopy:TStmt( scope:TScopeDecl )
  624. Return New TEndStmt.Create( )
  625. End Method
  626. Method OnSemant()
  627. End Method
  628. Method Trans$()
  629. Return _trans.TransEndStmt( Self )
  630. End Method
  631. End Type
  632. Type TReleaseStmt Extends TStmt
  633. Field expr:TExpr
  634. Method Create:TReleaseStmt( expr:TExpr )
  635. Self.expr=expr
  636. Return Self
  637. End Method
  638. Method OnCopy:TStmt( scope:TScopeDecl )
  639. Return New TReleaseStmt.Create( expr.Copy() )
  640. End Method
  641. Method OnSemant()
  642. expr=expr.Semant()
  643. If Not TVarExpr( expr ) And Not TMemberVarExpr( expr) And Not TIndexExpr( expr ) err "Expression must be a variable"
  644. If Not TNumericType(expr.exprType) Err "Subexpression for release must be an integer variable"
  645. End Method
  646. Method Trans$()
  647. Return _trans.TransReleaseStmt( Self )
  648. End Method
  649. End Type
  650. Type TReadDataStmt Extends TStmt
  651. Field args:TExpr[]
  652. Method Create:TReadDataStmt( args:TExpr[] )
  653. Self.args=args
  654. Return Self
  655. End Method
  656. Method OnCopy:TStmt( scope:TScopeDecl )
  657. Return New TReadDataStmt.Create( TExpr.CopyArgs(args) )
  658. End Method
  659. Method OnSemant()
  660. If args Then
  661. For Local i:Int = 0 Until args.length
  662. args[i]=args[i].Semant()
  663. Local arg:TExpr = args[i]
  664. If Not TVarExpr(arg) And Not TMemberVarExpr(arg) And Not TIndexExpr(arg) And Not (TStmtExpr(arg) And TIndexExpr(TStmtExpr(arg).expr)) Then
  665. Err "Expression must be a variable"
  666. End If
  667. Next
  668. End If
  669. End Method
  670. Method Trans$()
  671. Return _trans.TransReadDataStmt( Self )
  672. End Method
  673. End Type
  674. Type TRestoreDataStmt Extends TStmt
  675. Field label:TExpr
  676. Method Create:TRestoreDataStmt( label:TExpr )
  677. Self.label=label
  678. Return Self
  679. End Method
  680. Method OnCopy:TStmt( scope:TScopeDecl )
  681. Return New TRestoreDataStmt.Create( label.Copy() )
  682. End Method
  683. Method OnSemant()
  684. If label
  685. Local id:String
  686. If TIdentExpr(label) id = "'" + TIdentExpr(label).ident + "'"
  687. label = label.Semant(OPTION_WANT_DATA_LABEL)
  688. If Not TDataLabelExpr(label) Err "Data label " + id + " not found"
  689. Else
  690. Err "Expecting label"
  691. End If
  692. End Method
  693. Method Trans$()
  694. Return _trans.TransRestoreDataStmt( Self )
  695. End Method
  696. End Type
  697. Type TNativeStmt Extends TStmt
  698. Field raw:String
  699. Method Create:TNativeStmt( raw:String )
  700. Self.raw = raw
  701. Return Self
  702. End Method
  703. Method OnCopy:TStmt( scope:TScopeDecl )
  704. Return New TNativeStmt.Create( raw )
  705. End Method
  706. Method OnSemant()
  707. End Method
  708. Method Trans$()
  709. Return _trans.TransNativeStmt( Self )
  710. End Method
  711. End Type