Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

990 lines
22 KiB

  1. //
  2. // Copyright (c) Microsoft Corporation 1995
  3. //
  4. // typechk.c
  5. //
  6. // This file contains the typechecking functions.
  7. //
  8. // The typechecking rules are:
  9. //
  10. // waitfor Takes a string expression
  11. // transmit Takes a string expression
  12. // delay Takes an integer expression
  13. // while Evaluates a boolean expression
  14. // set ipaddr Takes a string expression
  15. // getip Takes an integer expression
  16. //
  17. //
  18. //
  19. // History:
  20. // 06-15-95 ScottH Created
  21. //
  22. #include "proj.h"
  23. #include "rcids.h"
  24. RES PRIVATE Stmt_Typecheck(PSTMT this, PSYMTAB pst, HSA hsaStxerr);
  25. /*----------------------------------------------------------
  26. Purpose: Typechecks whether an identifier is a valid type.
  27. Returns: RES_OK
  28. RES_E_REQUIRELABEL
  29. RES_E_UNDEFINED
  30. Cond: --
  31. */
  32. RES PRIVATE Ident_Typecheck(
  33. LPCSTR pszIdent,
  34. DATATYPE dt,
  35. PDATATYPE pdt, // May be NULL
  36. DWORD iLine,
  37. PSYMTAB pst,
  38. HSA hsaStxerr)
  39. {
  40. RES res = RES_OK;
  41. PSTE pste;
  42. if (RES_OK == Symtab_FindEntry(pst, pszIdent, STFF_DEFAULT, &pste, NULL))
  43. {
  44. if (pdt)
  45. {
  46. *pdt = STE_GetDataType(pste);
  47. res = RES_OK;
  48. }
  49. else if (dt == STE_GetDataType(pste))
  50. {
  51. res = RES_OK;
  52. }
  53. else
  54. {
  55. switch (dt)
  56. {
  57. case DATA_LABEL:
  58. res = RES_E_REQUIRELABEL;
  59. break;
  60. case DATA_STRING:
  61. res = RES_E_REQUIRESTRING;
  62. break;
  63. case DATA_INT:
  64. res = RES_E_REQUIREINT;
  65. break;
  66. case DATA_BOOL:
  67. res = RES_E_REQUIREBOOL;
  68. break;
  69. default:
  70. ASSERT(0);
  71. break;
  72. }
  73. Stxerr_Add(hsaStxerr, pszIdent, iLine, res);
  74. }
  75. }
  76. else
  77. {
  78. res = Stxerr_Add(hsaStxerr, pszIdent, iLine, RES_E_UNDEFINED);
  79. }
  80. return res;
  81. }
  82. //
  83. // Exprs
  84. //
  85. RES PRIVATE Expr_Typecheck(PEXPR this, PSYMTAB pst, HSA hsaStxerr);
  86. /*----------------------------------------------------------
  87. Purpose: Return a string given a binoptype.
  88. Returns: Pointer to string
  89. Cond: --
  90. */
  91. LPCSTR PRIVATE SzFromBot(
  92. BINOPTYPE bot)
  93. {
  94. #pragma data_seg(DATASEG_READONLY)
  95. static const LPCSTR s_mpbotsz[] =
  96. { "'or' operand",
  97. "'and' operand",
  98. "'<=' operand",
  99. "'<' operand",
  100. "'>=' operand",
  101. "'>' operand",
  102. "'!=' operand",
  103. "'==' operand",
  104. "'+' operand",
  105. "'-' operand",
  106. "'*' operand",
  107. "'/' operand",
  108. };
  109. #pragma data_seg()
  110. if (ARRAY_ELEMENTS(s_mpbotsz) <= bot)
  111. {
  112. ASSERT(0);
  113. return "";
  114. }
  115. return s_mpbotsz[bot];
  116. }
  117. /*----------------------------------------------------------
  118. Purpose: Return a string given a unoptype.
  119. Returns: Pointer to string
  120. Cond: --
  121. */
  122. LPCSTR PRIVATE SzFromUot(
  123. UNOPTYPE uot)
  124. {
  125. #pragma data_seg(DATASEG_READONLY)
  126. static const LPCSTR s_mpuotsz[] =
  127. {
  128. "unary '-' operand",
  129. "'!' operand",
  130. "'getip' parameter",
  131. };
  132. #pragma data_seg()
  133. if (ARRAY_ELEMENTS(s_mpuotsz) <= uot)
  134. {
  135. ASSERT(0);
  136. return "";
  137. }
  138. return s_mpuotsz[uot];
  139. }
  140. /*----------------------------------------------------------
  141. Purpose: Typechecks a variable reference expression.
  142. Returns: RES_OK
  143. or some error result
  144. Cond: --
  145. */
  146. RES PRIVATE VarExpr_Typecheck(
  147. PEXPR this,
  148. PSYMTAB pst,
  149. HSA hsaStxerr)
  150. {
  151. RES res;
  152. LPSTR pszIdent;
  153. PSTE pste;
  154. ASSERT(this);
  155. ASSERT(hsaStxerr);
  156. pszIdent = VarExpr_GetIdent(this);
  157. if (RES_OK == Symtab_FindEntry(pst, pszIdent, STFF_DEFAULT, &pste, NULL))
  158. {
  159. DATATYPE dt = STE_GetDataType(pste);
  160. ASSERT(DATA_BOOL == dt || DATA_INT == dt || DATA_STRING == dt);
  161. Expr_SetDataType(this, dt);
  162. res = RES_OK;
  163. }
  164. else
  165. {
  166. res = Stxerr_Add(hsaStxerr, pszIdent, Ast_GetLine(this), RES_E_UNDEFINED);
  167. }
  168. return res;
  169. }
  170. /*----------------------------------------------------------
  171. Purpose: Typechecks a binary operator expression.
  172. Returns: RES_OK
  173. or some error result
  174. Cond: --
  175. */
  176. RES PRIVATE BinOpExpr_Typecheck(
  177. PEXPR this,
  178. PSYMTAB pst,
  179. HSA hsaStxerr)
  180. {
  181. RES res;
  182. PEXPR pexpr1;
  183. PEXPR pexpr2;
  184. ASSERT(this);
  185. ASSERT(hsaStxerr);
  186. pexpr1 = BinOpExpr_GetExpr1(this);
  187. res = Expr_Typecheck(pexpr1, pst, hsaStxerr);
  188. if (RSUCCEEDED(res))
  189. {
  190. pexpr2 = BinOpExpr_GetExpr2(this);
  191. res = Expr_Typecheck(pexpr2, pst, hsaStxerr);
  192. if (RSUCCEEDED(res))
  193. {
  194. BINOPTYPE bot = BinOpExpr_GetType(this);
  195. // Types must match
  196. if (Expr_GetDataType(pexpr1) != Expr_GetDataType(pexpr2))
  197. {
  198. res = RES_E_TYPEMISMATCH;
  199. }
  200. else
  201. {
  202. // Just choose one of the datatypes, since they
  203. // should be the same.
  204. DATATYPE dt = Expr_GetDataType(pexpr1);
  205. switch (bot)
  206. {
  207. case BOT_OR:
  208. case BOT_AND:
  209. Expr_SetDataType(this, DATA_BOOL);
  210. if (DATA_BOOL != dt)
  211. res = RES_E_REQUIREBOOL;
  212. break;
  213. case BOT_PLUS:
  214. Expr_SetDataType(this, dt);
  215. // String + string means concatenate.
  216. if (DATA_INT != dt && DATA_STRING != dt)
  217. res = RES_E_REQUIREINTSTRING;
  218. break;
  219. case BOT_NEQ:
  220. case BOT_EQ:
  221. Expr_SetDataType(this, DATA_BOOL);
  222. if (DATA_INT != dt && DATA_STRING != dt &&
  223. DATA_BOOL != dt)
  224. res = RES_E_REQUIREINTSTRBOOL;
  225. break;
  226. case BOT_LEQ:
  227. case BOT_LT:
  228. case BOT_GEQ:
  229. case BOT_GT:
  230. Expr_SetDataType(this, DATA_BOOL);
  231. if (DATA_INT != dt)
  232. res = RES_E_REQUIREINT;
  233. break;
  234. case BOT_MINUS:
  235. case BOT_MULT:
  236. case BOT_DIV:
  237. Expr_SetDataType(this, DATA_INT);
  238. if (DATA_INT != dt)
  239. res = RES_E_REQUIREINT;
  240. break;
  241. default:
  242. ASSERT(0);
  243. res = RES_E_INVALIDPARAM;
  244. break;
  245. }
  246. }
  247. if (RFAILED(res))
  248. Stxerr_Add(hsaStxerr, SzFromBot(bot), Ast_GetLine(this), res);
  249. }
  250. }
  251. return res;
  252. }
  253. /*----------------------------------------------------------
  254. Purpose: Typechecks a unary operator expression.
  255. Returns: RES_OK
  256. or some error result
  257. Cond: --
  258. */
  259. RES PRIVATE UnOpExpr_Typecheck(
  260. PEXPR this,
  261. PSYMTAB pst,
  262. HSA hsaStxerr)
  263. {
  264. RES res;
  265. PEXPR pexpr;
  266. ASSERT(this);
  267. ASSERT(hsaStxerr);
  268. pexpr = UnOpExpr_GetExpr(this);
  269. res = Expr_Typecheck(pexpr, pst, hsaStxerr);
  270. if (RSUCCEEDED(res))
  271. {
  272. UNOPTYPE uot = UnOpExpr_GetType(this);
  273. DATATYPE dt = Expr_GetDataType(pexpr);
  274. // Check the type of the expression
  275. switch (uot)
  276. {
  277. case UOT_NEG:
  278. Expr_SetDataType(this, DATA_INT);
  279. if (DATA_INT != dt)
  280. res = RES_E_REQUIREINT;
  281. break;
  282. case UOT_NOT:
  283. Expr_SetDataType(this, DATA_BOOL);
  284. if (DATA_BOOL != dt)
  285. res = RES_E_REQUIREBOOL;
  286. break;
  287. case UOT_GETIP:
  288. Expr_SetDataType(this, DATA_STRING);
  289. if (DATA_INT != dt)
  290. res = RES_E_REQUIREINT;
  291. break;
  292. default:
  293. ASSERT(0);
  294. res = RES_E_INVALIDPARAM;
  295. break;
  296. }
  297. if (RFAILED(res))
  298. Stxerr_Add(hsaStxerr, SzFromUot(uot), Ast_GetLine(this), res);
  299. }
  300. return res;
  301. }
  302. /*----------------------------------------------------------
  303. Purpose: Typechecks an expression.
  304. Returns: RES_OK
  305. or some error result
  306. Cond: --
  307. */
  308. RES PRIVATE Expr_Typecheck(
  309. PEXPR this,
  310. PSYMTAB pst,
  311. HSA hsaStxerr)
  312. {
  313. RES res;
  314. ASSERT(this);
  315. ASSERT(hsaStxerr);
  316. switch (Ast_GetType(this))
  317. {
  318. case AT_INT_EXPR:
  319. Expr_SetDataType(this, DATA_INT);
  320. res = RES_OK;
  321. break;
  322. case AT_STRING_EXPR:
  323. Expr_SetDataType(this, DATA_STRING);
  324. res = RES_OK;
  325. break;
  326. case AT_BOOL_EXPR:
  327. Expr_SetDataType(this, DATA_BOOL);
  328. res = RES_OK;
  329. break;
  330. case AT_VAR_EXPR:
  331. res = VarExpr_Typecheck(this, pst, hsaStxerr);
  332. break;
  333. case AT_UNOP_EXPR:
  334. res = UnOpExpr_Typecheck(this, pst, hsaStxerr);
  335. break;
  336. case AT_BINOP_EXPR:
  337. res = BinOpExpr_Typecheck(this, pst, hsaStxerr);
  338. break;
  339. default:
  340. ASSERT(0);
  341. res = RES_E_INVALIDPARAM;
  342. break;
  343. }
  344. return res;
  345. }
  346. /*----------------------------------------------------------
  347. Purpose: Typecheck the assignment statement
  348. Returns: RES_OK
  349. or some error result
  350. Cond: --
  351. */
  352. RES PRIVATE AssignStmt_Typecheck(
  353. PSTMT this,
  354. PSYMTAB pst,
  355. HSA hsaStxerr)
  356. {
  357. RES res;
  358. LPSTR pszIdent;
  359. DATATYPE dt;
  360. ASSERT(this);
  361. ASSERT(hsaStxerr);
  362. ASSERT(AT_ASSIGN_STMT == Ast_GetType(this));
  363. pszIdent = AssignStmt_GetIdent(this);
  364. res = Ident_Typecheck(pszIdent, 0, &dt, Ast_GetLine(this), pst, hsaStxerr);
  365. if (RSUCCEEDED(res))
  366. {
  367. PEXPR pexpr = AssignStmt_GetExpr(this);
  368. res = Expr_Typecheck(pexpr, pst, hsaStxerr);
  369. // Types must match
  370. if (dt != Expr_GetDataType(pexpr))
  371. {
  372. res = Stxerr_Add(hsaStxerr, "=", Ast_GetLine(pexpr), RES_E_TYPEMISMATCH);
  373. }
  374. }
  375. return res;
  376. }
  377. /*----------------------------------------------------------
  378. Purpose: Typecheck the 'while' statement
  379. Returns: RES_OK
  380. or some error result
  381. Cond: --
  382. */
  383. RES PRIVATE WhileStmt_Typecheck(
  384. PSTMT this,
  385. PSYMTAB pst,
  386. HSA hsaStxerr)
  387. {
  388. RES res;
  389. PEXPR pexpr;
  390. ASSERT(this);
  391. ASSERT(hsaStxerr);
  392. ASSERT(AT_WHILE_STMT == Ast_GetType(this));
  393. pexpr = WhileStmt_GetExpr(this);
  394. res = Expr_Typecheck(pexpr, pst, hsaStxerr);
  395. if (RSUCCEEDED(res))
  396. {
  397. if (DATA_BOOL != Expr_GetDataType(pexpr))
  398. {
  399. res = Stxerr_Add(hsaStxerr, "'while' expression", Ast_GetLine(pexpr), RES_E_REQUIREBOOL);
  400. }
  401. else
  402. {
  403. // Typecheck the statement block
  404. DWORD i;
  405. DWORD cstmts;
  406. HPA hpaStmts = WhileStmt_GetStmtBlock(this);
  407. res = RES_OK;
  408. cstmts = PAGetCount(hpaStmts);
  409. // Typecheck each statement
  410. for (i = 0; i < cstmts; i++)
  411. {
  412. PSTMT pstmt = PAFastGetPtr(hpaStmts, i);
  413. res = Stmt_Typecheck(pstmt, pst, hsaStxerr);
  414. if (RFAILED(res))
  415. break;
  416. }
  417. }
  418. }
  419. return res;
  420. }
  421. /*----------------------------------------------------------
  422. Purpose: Typecheck the 'if' statement
  423. Returns: RES_OK
  424. or some error result
  425. Cond: --
  426. */
  427. RES PRIVATE IfStmt_Typecheck(
  428. PSTMT this,
  429. PSYMTAB pst,
  430. HSA hsaStxerr)
  431. {
  432. RES res;
  433. PEXPR pexpr;
  434. ASSERT(this);
  435. ASSERT(hsaStxerr);
  436. ASSERT(AT_IF_STMT == Ast_GetType(this));
  437. pexpr = IfStmt_GetExpr(this);
  438. res = Expr_Typecheck(pexpr, pst, hsaStxerr);
  439. if (RSUCCEEDED(res))
  440. {
  441. if (DATA_BOOL != Expr_GetDataType(pexpr))
  442. {
  443. res = Stxerr_Add(hsaStxerr, "'if' expression", Ast_GetLine(pexpr), RES_E_REQUIREBOOL);
  444. }
  445. else
  446. {
  447. // Typecheck the statement block
  448. DWORD i;
  449. DWORD cstmts;
  450. HPA hpaStmts = IfStmt_GetStmtBlock(this);
  451. res = RES_OK;
  452. cstmts = PAGetCount(hpaStmts);
  453. // Typecheck each statement
  454. for (i = 0; i < cstmts; i++)
  455. {
  456. PSTMT pstmt = PAFastGetPtr(hpaStmts, i);
  457. res = Stmt_Typecheck(pstmt, pst, hsaStxerr);
  458. if (RFAILED(res))
  459. break;
  460. }
  461. }
  462. }
  463. return res;
  464. }
  465. /*----------------------------------------------------------
  466. Purpose: Typecheck the label statement
  467. Returns: RES_OK
  468. or some error result
  469. Cond: --
  470. */
  471. RES PRIVATE LabelStmt_Typecheck(
  472. PSTMT this,
  473. PSYMTAB pst,
  474. HSA hsaStxerr)
  475. {
  476. RES res;
  477. PSTE pste;
  478. LPSTR pszIdent;
  479. ASSERT(this);
  480. ASSERT(hsaStxerr);
  481. ASSERT(AT_LABEL_STMT == Ast_GetType(this));
  482. pszIdent = LabelStmt_GetIdent(this);
  483. if (RES_OK == Symtab_FindEntry(pst, pszIdent, STFF_DEFAULT, &pste, NULL))
  484. {
  485. if (DATA_LABEL == STE_GetDataType(pste))
  486. res = RES_OK;
  487. else
  488. res = Stxerr_Add(hsaStxerr, pszIdent, Ast_GetLine(this), RES_E_REQUIRELABEL);
  489. }
  490. else
  491. {
  492. // This should never get here
  493. ASSERT(0);
  494. res = RES_E_FAIL;
  495. }
  496. return res;
  497. }
  498. /*----------------------------------------------------------
  499. Purpose: Typecheck the 'goto' statement
  500. Returns: RES_OK
  501. or some error result
  502. Cond: --
  503. */
  504. RES PRIVATE GotoStmt_Typecheck(
  505. PSTMT this,
  506. PSYMTAB pst,
  507. HSA hsaStxerr)
  508. {
  509. LPSTR pszIdent;
  510. ASSERT(this);
  511. ASSERT(hsaStxerr);
  512. ASSERT(AT_GOTO_STMT == Ast_GetType(this));
  513. pszIdent = GotoStmt_GetIdent(this);
  514. return Ident_Typecheck(pszIdent, DATA_LABEL, NULL, Ast_GetLine(this), pst, hsaStxerr);
  515. }
  516. /*----------------------------------------------------------
  517. Purpose: Typecheck the transmit statement
  518. Returns: RES_OK
  519. or some error result
  520. Cond: --
  521. */
  522. RES PRIVATE TransmitStmt_Typecheck(
  523. PSTMT this,
  524. PSYMTAB pst,
  525. HSA hsaStxerr)
  526. {
  527. RES res;
  528. PEXPR pexpr;
  529. ASSERT(this);
  530. ASSERT(hsaStxerr);
  531. ASSERT(AT_TRANSMIT_STMT == Ast_GetType(this));
  532. pexpr = TransmitStmt_GetExpr(this);
  533. res = Expr_Typecheck(pexpr, pst, hsaStxerr);
  534. if (DATA_STRING != Expr_GetDataType(pexpr))
  535. {
  536. res = Stxerr_Add(hsaStxerr, "'transmit' parameter", Ast_GetLine(pexpr), RES_E_REQUIRESTRING);
  537. }
  538. return res;
  539. }
  540. /*----------------------------------------------------------
  541. Purpose: Typecheck the 'waitfor' statement
  542. waitfor <Expr>
  543. [ then IDENT { , <Expr> then IDENT } ]
  544. [ until <UntilExpr> ]
  545. where:
  546. <Expr> is a string
  547. IDENT is a label
  548. <UntilExpr> is an integer
  549. Returns: RES_OK
  550. or some error result
  551. Cond: --
  552. */
  553. RES PRIVATE WaitforStmt_Typecheck(
  554. PSTMT this,
  555. PSYMTAB pst,
  556. HSA hsaStxerr)
  557. {
  558. RES res = RES_E_FAIL;
  559. PEXPR pexpr;
  560. HSA hsa;
  561. DWORD i;
  562. DWORD ccase;
  563. PWAITCASE pwc;
  564. ASSERT(this);
  565. ASSERT(hsaStxerr);
  566. ASSERT(AT_WAITFOR_STMT == Ast_GetType(this));
  567. // Typecheck that <Expr> is of type string, and any
  568. // IDENTs are labels.
  569. hsa = WaitforStmt_GetCaseList(this);
  570. ccase = SAGetCount(hsa);
  571. for (i = 0; i < ccase; i++)
  572. {
  573. SAGetItemPtr(hsa, i, &pwc);
  574. ASSERT(pwc);
  575. // Typecheck <Expr>
  576. res = Expr_Typecheck(pwc->pexpr, pst, hsaStxerr);
  577. if (DATA_STRING != Expr_GetDataType(pwc->pexpr))
  578. {
  579. res = Stxerr_Add(hsaStxerr, "'waitfor' parameter", Ast_GetLine(pwc->pexpr), RES_E_REQUIRESTRING);
  580. break;
  581. }
  582. // Typecheck IDENT label. If there is only one <Expr>, there
  583. // may not be an IDENT label.
  584. if (pwc->pszIdent)
  585. {
  586. res = Ident_Typecheck(pwc->pszIdent, DATA_LABEL, NULL, Ast_GetLine(pwc->pexpr), pst, hsaStxerr);
  587. if (RFAILED(res))
  588. break;
  589. }
  590. else
  591. ASSERT(1 == ccase);
  592. }
  593. // 'until' expression is optional
  594. if (RSUCCEEDED(res) &&
  595. NULL != (pexpr = WaitforStmt_GetUntilExpr(this)))
  596. {
  597. res = Expr_Typecheck(pexpr, pst, hsaStxerr);
  598. if (DATA_INT != Expr_GetDataType(pexpr))
  599. {
  600. res = Stxerr_Add(hsaStxerr, "'until' parameter", Ast_GetLine(pexpr), RES_E_REQUIREINT);
  601. }
  602. }
  603. return res;
  604. }
  605. /*----------------------------------------------------------
  606. Purpose: Typecheck the 'delay' statement
  607. Returns: RES_OK
  608. or some error result
  609. Cond: --
  610. */
  611. RES PRIVATE DelayStmt_Typecheck(
  612. PSTMT this,
  613. PSYMTAB pst,
  614. HSA hsaStxerr)
  615. {
  616. RES res;
  617. PEXPR pexpr;
  618. ASSERT(this);
  619. ASSERT(hsaStxerr);
  620. ASSERT(AT_DELAY_STMT == Ast_GetType(this));
  621. pexpr = DelayStmt_GetExpr(this);
  622. res = Expr_Typecheck(pexpr, pst, hsaStxerr);
  623. if (DATA_INT != Expr_GetDataType(pexpr))
  624. {
  625. res = Stxerr_Add(hsaStxerr, "'delay' parameter", Ast_GetLine(pexpr), RES_E_REQUIREINT);
  626. }
  627. return res;
  628. }
  629. /*----------------------------------------------------------
  630. Purpose: Typecheck the 'set' statement
  631. Returns: RES_OK
  632. or some error result
  633. Cond: --
  634. */
  635. RES PRIVATE SetStmt_Typecheck(
  636. PSTMT this,
  637. PSYMTAB pst,
  638. HSA hsaStxerr)
  639. {
  640. RES res;
  641. PEXPR pexpr;
  642. ASSERT(this);
  643. ASSERT(hsaStxerr);
  644. ASSERT(AT_SET_STMT == Ast_GetType(this));
  645. switch (SetStmt_GetType(this))
  646. {
  647. case ST_IPADDR:
  648. pexpr = SetIPStmt_GetExpr(this);
  649. res = Expr_Typecheck(pexpr, pst, hsaStxerr);
  650. if (DATA_STRING != Expr_GetDataType(pexpr))
  651. {
  652. res = Stxerr_Add(hsaStxerr, "'ipaddr' parameter", Ast_GetLine(pexpr), RES_E_REQUIRESTRING);
  653. }
  654. break;
  655. case ST_PORT:
  656. case ST_SCREEN:
  657. res = RES_OK;
  658. break;
  659. default:
  660. ASSERT(0);
  661. res = RES_E_INVALIDPARAM;
  662. break;
  663. }
  664. return res;
  665. }
  666. /*----------------------------------------------------------
  667. Purpose: Typecheck a statement
  668. Returns: RES_OK
  669. or some error result
  670. Cond: --
  671. */
  672. RES PRIVATE Stmt_Typecheck(
  673. PSTMT this,
  674. PSYMTAB pst,
  675. HSA hsaStxerr)
  676. {
  677. RES res;
  678. ASSERT(this);
  679. ASSERT(hsaStxerr);
  680. switch (Ast_GetType(this))
  681. {
  682. case AT_ENTER_STMT:
  683. case AT_LEAVE_STMT:
  684. res = RES_OK;
  685. break;
  686. case AT_WHILE_STMT:
  687. res = WhileStmt_Typecheck(this, pst, hsaStxerr);
  688. break;
  689. case AT_IF_STMT:
  690. res = IfStmt_Typecheck(this, pst, hsaStxerr);
  691. break;
  692. case AT_ASSIGN_STMT:
  693. res = AssignStmt_Typecheck(this, pst, hsaStxerr);
  694. break;
  695. case AT_HALT_STMT:
  696. // Nothing to typecheck here
  697. res = RES_OK;
  698. break;
  699. case AT_TRANSMIT_STMT:
  700. res = TransmitStmt_Typecheck(this, pst, hsaStxerr);
  701. break;
  702. case AT_WAITFOR_STMT:
  703. res = WaitforStmt_Typecheck(this, pst, hsaStxerr);
  704. break;
  705. case AT_DELAY_STMT:
  706. res = DelayStmt_Typecheck(this, pst, hsaStxerr);
  707. break;
  708. case AT_LABEL_STMT:
  709. res = LabelStmt_Typecheck(this, pst, hsaStxerr);
  710. break;
  711. case AT_GOTO_STMT:
  712. res = GotoStmt_Typecheck(this, pst, hsaStxerr);
  713. break;
  714. case AT_SET_STMT:
  715. res = SetStmt_Typecheck(this, pst, hsaStxerr);
  716. break;
  717. default:
  718. ASSERT(0);
  719. res = RES_E_INVALIDPARAM;
  720. break;
  721. }
  722. return res;
  723. }
  724. /*----------------------------------------------------------
  725. Purpose: Typecheck a procedure declaration.
  726. Returns: RES_OK
  727. or some error result
  728. Cond: --
  729. */
  730. RES PRIVATE ProcDecl_Typecheck(
  731. PPROCDECL this,
  732. PSYMTAB pst,
  733. HSA hsaStxerr)
  734. {
  735. RES res = RES_OK;
  736. DWORD i;
  737. DWORD cstmts;
  738. ASSERT(this);
  739. ASSERT(hsaStxerr);
  740. cstmts = PAGetCount(this->hpaStmts);
  741. // Typecheck each statement
  742. for (i = 0; i < cstmts; i++)
  743. {
  744. PSTMT pstmt = PAFastGetPtr(this->hpaStmts, i);
  745. res = Stmt_Typecheck(pstmt, this->pst, hsaStxerr);
  746. if (RFAILED(res))
  747. break;
  748. }
  749. return res;
  750. }
  751. /*----------------------------------------------------------
  752. Purpose: Typecheck a module declaration.
  753. Returns: RES_OK
  754. or some error result
  755. Cond: --
  756. */
  757. RES PUBLIC ModuleDecl_Typecheck(
  758. PMODULEDECL this,
  759. HSA hsaStxerr)
  760. {
  761. RES res = RES_OK;
  762. DWORD i;
  763. DWORD cprocs;
  764. BOOL bFoundMain = FALSE;
  765. ASSERT(this);
  766. ASSERT(hsaStxerr);
  767. TRACE_MSG(TF_GENERAL, "Typechecking...");
  768. cprocs = PAGetCount(this->hpaProcs);
  769. // Typecheck each proc
  770. for (i = 0; i < cprocs; i++)
  771. {
  772. PPROCDECL pprocdecl = PAFastGetPtr(this->hpaProcs, i);
  773. if (IsSzEqualC(ProcDecl_GetIdent(pprocdecl), "main"))
  774. bFoundMain = TRUE;
  775. res = ProcDecl_Typecheck(pprocdecl, this->pst, hsaStxerr);
  776. if (RFAILED(res))
  777. break;
  778. }
  779. // There must be a main proc
  780. if (RSUCCEEDED(res) && !bFoundMain)
  781. res = Stxerr_AddTok(hsaStxerr, NULL, RES_E_MAINMISSING);
  782. return res;
  783. }