ptype.pas 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Florian Klaempfl
  4. Does parsing types for Free Pascal
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. unit ptype;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. globtype,symtype;
  23. const
  24. { forward types should only be possible inside a TYPE statement }
  25. typecanbeforward : boolean = false;
  26. var
  27. { hack, which allows to use the current parsed }
  28. { object type as function argument type }
  29. testcurobject : byte;
  30. curobjectname : stringid;
  31. { reads a string, file type or a type id and returns a name and }
  32. { tdef }
  33. procedure single_type(var tt:ttype;var s : string;isforwarddef:boolean);
  34. procedure read_type(var tt:ttype;const name : stringid);
  35. { reads a type definition }
  36. { to a appropriating tdef, s gets the name of }
  37. { the type to allow name mangling }
  38. procedure id_type(var tt : ttype;var s : string;isforwarddef:boolean);
  39. implementation
  40. uses
  41. { common }
  42. cutils,
  43. { global }
  44. globals,tokens,verbose,
  45. systems,
  46. { symtable }
  47. symconst,symbase,symdef,symsym,symtable,defbase,
  48. { pass 1 }
  49. node,
  50. nmat,nadd,ncal,nset,ncnv,ninl,ncon,nld,nflw,
  51. { parser }
  52. scanner,
  53. pbase,pexpr,pdecsub,pdecvar,pdecobj;
  54. procedure id_type(var tt : ttype;var s : string;isforwarddef:boolean);
  55. { reads a type definition }
  56. { to a appropriating tdef, s gets the name of }
  57. { the type to allow name mangling }
  58. var
  59. is_unit_specific : boolean;
  60. pos : tfileposinfo;
  61. srsym : tsym;
  62. srsymtable : tsymtable;
  63. sorg : stringid;
  64. begin
  65. s:=pattern;
  66. sorg:=orgpattern;
  67. pos:=akttokenpos;
  68. { classes can be used also in classes }
  69. if (curobjectname=pattern) and is_class_or_interface(aktobjectdef) then
  70. begin
  71. tt.setdef(aktobjectdef);
  72. consume(_ID);
  73. exit;
  74. end;
  75. { objects can be parameters }
  76. if (testcurobject=2) and (curobjectname=pattern) then
  77. begin
  78. tt.setdef(aktobjectdef);
  79. consume(_ID);
  80. exit;
  81. end;
  82. { try to load the symbol to see if it's a unitsym }
  83. is_unit_specific:=false;
  84. searchsym(s,srsym,srsymtable);
  85. consume(_ID);
  86. if assigned(srsym) and
  87. (srsym.typ=unitsym) then
  88. begin
  89. is_unit_specific:=true;
  90. consume(_POINT);
  91. if srsym.owner.unitid=0 then
  92. begin
  93. srsym:=searchsymonlyin(tunitsym(srsym).unitsymtable,pattern);
  94. pos:=akttokenpos;
  95. s:=pattern;
  96. end
  97. else
  98. srsym:=nil;
  99. consume(_ID);
  100. end;
  101. { are we parsing a possible forward def ? }
  102. if isforwarddef and
  103. not(is_unit_specific) then
  104. begin
  105. tt.setdef(tforwarddef.create(s,pos));
  106. exit;
  107. end;
  108. { unknown sym ? }
  109. if not assigned(srsym) then
  110. begin
  111. Message1(sym_e_id_not_found,sorg);
  112. tt:=generrortype;
  113. exit;
  114. end;
  115. { type sym ? }
  116. if (srsym.typ<>typesym) then
  117. begin
  118. Message(type_e_type_id_expected);
  119. tt:=generrortype;
  120. exit;
  121. end;
  122. { Types are first defined with an error def before assigning
  123. the real type so check if it's an errordef. if so then
  124. give an error }
  125. if (ttypesym(srsym).restype.def.deftype=errordef) then
  126. begin
  127. Message(sym_e_error_in_type_def);
  128. tt:=generrortype;
  129. exit;
  130. end;
  131. { Only use the definitions for system/current unit, becuase
  132. they can be refered from the parameters and symbols are not
  133. loaded at that time. A symbol reference to an other unit
  134. is still possible, because it's already loaded (PFV)
  135. can't use in [] here, becuase unitid can be > 255 }
  136. { if (ttypesym(srsym).owner.unitid=0) or
  137. (ttypesym(srsym).owner.unitid=1) then }
  138. if (ttypesym(srsym).owner.unitid=0) then
  139. tt.setdef(ttypesym(srsym).restype.def)
  140. else
  141. tt.setsym(srsym);
  142. end;
  143. procedure single_type(var tt:ttype;var s : string;isforwarddef:boolean);
  144. { reads a string, file type or a type id and returns a name and }
  145. { tdef }
  146. var
  147. hs : string;
  148. t2 : ttype;
  149. begin
  150. case token of
  151. _STRING:
  152. begin
  153. string_dec(tt);
  154. s:='STRING';
  155. end;
  156. _FILE:
  157. begin
  158. consume(_FILE);
  159. if token=_OF then
  160. begin
  161. consume(_OF);
  162. single_type(t2,hs,false);
  163. tt.setdef(tfiledef.createtyped(t2));
  164. s:='FILE$OF$'+hs;
  165. end
  166. else
  167. begin
  168. tt:=cfiletype;
  169. s:='FILE';
  170. end;
  171. end;
  172. _ID:
  173. begin
  174. id_type(tt,s,isforwarddef);
  175. end;
  176. else
  177. begin
  178. message(type_e_type_id_expected);
  179. s:='<unknown>';
  180. tt:=generrortype;
  181. end;
  182. end;
  183. end;
  184. { reads a record declaration }
  185. function record_dec : tdef;
  186. var
  187. symtable : tsymtable;
  188. storetypecanbeforward : boolean;
  189. old_object_option : tsymoptions;
  190. begin
  191. { create recdef }
  192. symtable:=trecordsymtable.create;
  193. record_dec:=trecorddef.create(symtable);
  194. { update symtable stack }
  195. symtable.next:=symtablestack;
  196. symtablestack:=symtable;
  197. { parse record }
  198. consume(_RECORD);
  199. old_object_option:=current_object_option;
  200. current_object_option:=[sp_public];
  201. storetypecanbeforward:=typecanbeforward;
  202. { for tp7 don't allow forward types }
  203. if m_tp7 in aktmodeswitches then
  204. typecanbeforward:=false;
  205. read_var_decs(true,false,false);
  206. consume(_END);
  207. typecanbeforward:=storetypecanbeforward;
  208. current_object_option:=old_object_option;
  209. { may be scale record size to a size of n*4 ? }
  210. symtablestack.datasize:=align(symtablestack.datasize,symtablestack.dataalignment);
  211. { restore symtable stack }
  212. symtablestack:=symtable.next;
  213. end;
  214. { reads a type definition and returns a pointer to it }
  215. procedure read_type(var tt : ttype;const name : stringid);
  216. var
  217. pt : tnode;
  218. tt2 : ttype;
  219. aktenumdef : tenumdef;
  220. ap : tarraydef;
  221. s : stringid;
  222. l,v : TConstExprInt;
  223. oldaktpackrecords : longint;
  224. hs : string;
  225. defpos,storepos : tfileposinfo;
  226. procedure expr_type;
  227. var
  228. pt1,pt2 : tnode;
  229. lv,hv : TConstExprInt;
  230. begin
  231. { use of current parsed object ? }
  232. if (token=_ID) and (testcurobject=2) and (curobjectname=pattern) then
  233. begin
  234. consume(_ID);
  235. tt.setdef(aktobjectdef);
  236. exit;
  237. end;
  238. { classes can be used also in classes }
  239. if (curobjectname=pattern) and is_class_or_interface(aktobjectdef) then
  240. begin
  241. tt.setdef(aktobjectdef);
  242. consume(_ID);
  243. exit;
  244. end;
  245. { we can't accept a equal in type }
  246. pt1:=comp_expr(not(ignore_equal));
  247. if (token=_POINTPOINT) then
  248. begin
  249. consume(_POINTPOINT);
  250. { get high value of range }
  251. pt2:=comp_expr(not(ignore_equal));
  252. { make both the same type }
  253. inserttypeconv(pt1,pt2.resulttype);
  254. { both must be evaluated to constants now }
  255. if (pt1.nodetype=ordconstn) and
  256. (pt2.nodetype=ordconstn) then
  257. begin
  258. lv:=tordconstnode(pt1).value;
  259. hv:=tordconstnode(pt2).value;
  260. { Check bounds }
  261. if hv<lv then
  262. Message(cg_e_upper_lower_than_lower)
  263. else
  264. begin
  265. { All checks passed, create the new def }
  266. case pt1.resulttype.def.deftype of
  267. enumdef :
  268. tt.setdef(tenumdef.create_subrange(tenumdef(pt1.resulttype.def),lv,hv));
  269. orddef :
  270. begin
  271. if is_char(pt1.resulttype.def) then
  272. tt.setdef(torddef.create(uchar,lv,hv))
  273. else
  274. if is_boolean(pt1.resulttype.def) then
  275. tt.setdef(torddef.create(bool8bit,l,hv))
  276. else
  277. tt.setdef(torddef.create(range_to_basetype(lv,hv),lv,hv));
  278. end;
  279. end;
  280. end;
  281. end
  282. else
  283. Message(sym_e_error_in_type_def);
  284. pt2.free;
  285. end
  286. else
  287. begin
  288. { a simple type renaming }
  289. if (pt1.nodetype=typen) then
  290. tt:=ttypenode(pt1).resulttype
  291. else
  292. Message(sym_e_error_in_type_def);
  293. end;
  294. pt1.free;
  295. end;
  296. procedure array_dec;
  297. var
  298. lowval,
  299. highval : longint;
  300. arraytype : ttype;
  301. ht : ttype;
  302. procedure setdefdecl(const t:ttype);
  303. begin
  304. case t.def.deftype of
  305. enumdef :
  306. begin
  307. lowval:=tenumdef(t.def).min;
  308. highval:=tenumdef(t.def).max;
  309. if tenumdef(t.def).has_jumps then
  310. Message(type_e_array_index_enums_with_assign_not_possible);
  311. arraytype:=t;
  312. end;
  313. orddef :
  314. begin
  315. if torddef(t.def).typ in [uchar,
  316. u8bit,u16bit,
  317. s8bit,s16bit,s32bit,
  318. bool8bit,bool16bit,bool32bit,
  319. uwidechar] then
  320. begin
  321. lowval:=torddef(t.def).low;
  322. highval:=torddef(t.def).high;
  323. arraytype:=t;
  324. end
  325. else
  326. Message1(parser_e_type_cant_be_used_in_array_index,t.def.gettypename);
  327. end;
  328. else
  329. Message(sym_e_error_in_type_def);
  330. end;
  331. end;
  332. begin
  333. consume(_ARRAY);
  334. { open array? }
  335. if token=_LECKKLAMMER then
  336. begin
  337. consume(_LECKKLAMMER);
  338. { defaults }
  339. arraytype:=generrortype;
  340. lowval:=longint($80000000);
  341. highval:=$7fffffff;
  342. tt.reset;
  343. repeat
  344. { read the expression and check it, check apart if the
  345. declaration is an enum declaration because that needs to
  346. be parsed by readtype (PFV) }
  347. if token=_LKLAMMER then
  348. begin
  349. read_type(ht,'');
  350. setdefdecl(ht);
  351. end
  352. else
  353. begin
  354. pt:=expr;
  355. if pt.nodetype=typen then
  356. setdefdecl(pt.resulttype)
  357. else
  358. begin
  359. if (pt.nodetype=rangen) then
  360. begin
  361. if (trangenode(pt).left.nodetype=ordconstn) and
  362. (trangenode(pt).right.nodetype=ordconstn) then
  363. begin
  364. lowval:=tordconstnode(trangenode(pt).left).value;
  365. highval:=tordconstnode(trangenode(pt).right).value;
  366. if highval<lowval then
  367. begin
  368. Message(parser_e_array_lower_less_than_upper_bound);
  369. highval:=lowval;
  370. end;
  371. arraytype:=trangenode(pt).right.resulttype;
  372. end
  373. else
  374. Message(type_e_cant_eval_constant_expr);
  375. end
  376. else
  377. Message(sym_e_error_in_type_def)
  378. end;
  379. pt.free;
  380. end;
  381. { create arraydef }
  382. if not assigned(tt.def) then
  383. begin
  384. ap:=tarraydef.create(lowval,highval,arraytype);
  385. tt.setdef(ap);
  386. end
  387. else
  388. begin
  389. ap.elementtype.setdef(tarraydef.create(lowval,highval,arraytype));
  390. ap:=tarraydef(ap.elementtype.def);
  391. end;
  392. if token=_COMMA then
  393. consume(_COMMA)
  394. else
  395. break;
  396. until false;
  397. consume(_RECKKLAMMER);
  398. end
  399. else
  400. begin
  401. ap:=tarraydef.create(0,-1,s32bittype);
  402. ap.IsDynamicArray:=true;
  403. tt.setdef(ap);
  404. end;
  405. consume(_OF);
  406. read_type(tt2,'');
  407. { if no error, set element type }
  408. if assigned(ap) then
  409. ap.elementtype:=tt2;
  410. end;
  411. var
  412. p : tnode;
  413. enumdupmsg : boolean;
  414. begin
  415. tt.reset;
  416. case token of
  417. _STRING,_FILE:
  418. begin
  419. single_type(tt,hs,false);
  420. end;
  421. _LKLAMMER:
  422. begin
  423. consume(_LKLAMMER);
  424. { allow negativ value_str }
  425. l:=-1;
  426. enumdupmsg:=false;
  427. aktenumdef:=tenumdef.create;
  428. repeat
  429. s:=orgpattern;
  430. defpos:=akttokenpos;
  431. consume(_ID);
  432. { only allow assigning of specific numbers under fpc mode }
  433. if (m_fpc in aktmodeswitches) and
  434. (token=_ASSIGNMENT) then
  435. begin
  436. consume(_ASSIGNMENT);
  437. p:=comp_expr(true);
  438. if (p.nodetype=ordconstn) then
  439. begin
  440. { we expect an integer or an enum of the
  441. same type }
  442. if is_integer(p.resulttype.def) or
  443. is_char(p.resulttype.def) or
  444. is_equal(p.resulttype.def,aktenumdef) then
  445. v:=tordconstnode(p).value
  446. else
  447. Message2(type_e_incompatible_types,p.resulttype.def.typename,s32bittype.def.typename);
  448. end
  449. else
  450. Message(cg_e_illegal_expression);
  451. p.free;
  452. { please leave that a note, allows type save }
  453. { declarations in the win32 units ! }
  454. if (v<=l) and (not enumdupmsg) then
  455. begin
  456. Message(parser_n_duplicate_enum);
  457. enumdupmsg:=true;
  458. end;
  459. l:=v;
  460. end
  461. else if (m_delphi in aktmodeswitches) and
  462. (token=_EQUAL) then
  463. begin
  464. consume(_EQUAL);
  465. p:=comp_expr(true);
  466. if (p.nodetype=ordconstn) then
  467. begin
  468. { we expect an integer or an enum of the
  469. same type }
  470. if is_integer(p.resulttype.def) or
  471. is_equal(p.resulttype.def,aktenumdef) then
  472. l:=tordconstnode(p).value
  473. else
  474. Message2(type_e_incompatible_types,p.resulttype.def.typename,s32bittype.def.typename);
  475. end
  476. else
  477. Message(cg_e_illegal_expression);
  478. p.free;
  479. end
  480. else
  481. inc(l);
  482. storepos:=akttokenpos;
  483. akttokenpos:=defpos;
  484. constsymtable.insert(tenumsym.create(s,aktenumdef,l));
  485. akttokenpos:=storepos;
  486. until not try_to_consume(_COMMA);
  487. tt.setdef(aktenumdef);
  488. consume(_RKLAMMER);
  489. end;
  490. _ARRAY:
  491. begin
  492. array_dec;
  493. end;
  494. _SET:
  495. begin
  496. consume(_SET);
  497. consume(_OF);
  498. read_type(tt2,'');
  499. if assigned(tt2.def) then
  500. begin
  501. case tt2.def.deftype of
  502. { don't forget that min can be negativ PM }
  503. enumdef :
  504. if tenumdef(tt2.def).min>=0 then
  505. tt.setdef(tsetdef.create(tt2,tenumdef(tt2.def).max))
  506. else
  507. Message(sym_e_ill_type_decl_set);
  508. orddef :
  509. begin
  510. case torddef(tt2.def).typ of
  511. uchar :
  512. tt.setdef(tsetdef.create(tt2,255));
  513. u8bit,u16bit,u32bit,
  514. s8bit,s16bit,s32bit :
  515. begin
  516. if (torddef(tt2.def).low>=0) then
  517. tt.setdef(tsetdef.create(tt2,torddef(tt2.def).high))
  518. else
  519. Message(sym_e_ill_type_decl_set);
  520. end;
  521. else
  522. Message(sym_e_ill_type_decl_set);
  523. end;
  524. end;
  525. else
  526. Message(sym_e_ill_type_decl_set);
  527. end;
  528. end
  529. else
  530. tt:=generrortype;
  531. end;
  532. _CARET:
  533. begin
  534. consume(_CARET);
  535. single_type(tt2,hs,typecanbeforward);
  536. tt.setdef(tpointerdef.create(tt2));
  537. end;
  538. _RECORD:
  539. begin
  540. tt.setdef(record_dec);
  541. end;
  542. _PACKED:
  543. begin
  544. consume(_PACKED);
  545. if token=_ARRAY then
  546. array_dec
  547. else
  548. begin
  549. oldaktpackrecords:=aktalignment.recordalignmax;
  550. aktalignment.recordalignmax:=1;
  551. if token in [_CLASS,_OBJECT] then
  552. tt.setdef(object_dec(name,nil))
  553. else
  554. tt.setdef(record_dec);
  555. aktalignment.recordalignmax:=oldaktpackrecords;
  556. end;
  557. end;
  558. _CLASS,
  559. _CPPCLASS,
  560. _INTERFACE,
  561. _OBJECT:
  562. begin
  563. tt.setdef(object_dec(name,nil));
  564. end;
  565. _PROCEDURE:
  566. begin
  567. consume(_PROCEDURE);
  568. tt.setdef(tprocvardef.create);
  569. if token=_LKLAMMER then
  570. parameter_dec(tprocvardef(tt.def));
  571. if token=_OF then
  572. begin
  573. consume(_OF);
  574. consume(_OBJECT);
  575. include(tprocvardef(tt.def).procoptions,po_methodpointer);
  576. end;
  577. end;
  578. _FUNCTION:
  579. begin
  580. consume(_FUNCTION);
  581. tt.def:=tprocvardef.create;
  582. if token=_LKLAMMER then
  583. parameter_dec(tprocvardef(tt.def));
  584. consume(_COLON);
  585. single_type(tprocvardef(tt.def).rettype,hs,false);
  586. if token=_OF then
  587. begin
  588. consume(_OF);
  589. consume(_OBJECT);
  590. include(tprocvardef(tt.def).procoptions,po_methodpointer);
  591. end;
  592. end;
  593. else
  594. expr_type;
  595. end;
  596. if tt.def=nil then
  597. tt:=generrortype;
  598. end;
  599. end.
  600. {
  601. $Log$
  602. Revision 1.42 2002-07-20 11:57:56 florian
  603. * types.pas renamed to defbase.pas because D6 contains a types
  604. unit so this would conflicts if D6 programms are compiled
  605. + Willamette/SSE2 instructions to assembler added
  606. Revision 1.41 2002/05/18 13:34:16 peter
  607. * readded missing revisions
  608. Revision 1.40 2002/05/16 19:46:44 carl
  609. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  610. + try to fix temp allocation (still in ifdef)
  611. + generic constructor calls
  612. + start of tassembler / tmodulebase class cleanup
  613. Revision 1.38 2002/05/12 16:53:10 peter
  614. * moved entry and exitcode to ncgutil and cgobj
  615. * foreach gets extra argument for passing local data to the
  616. iterator function
  617. * -CR checks also class typecasts at runtime by changing them
  618. into as
  619. * fixed compiler to cycle with the -CR option
  620. * fixed stabs with elf writer, finally the global variables can
  621. be watched
  622. * removed a lot of routines from cga unit and replaced them by
  623. calls to cgobj
  624. * u32bit-s32bit updates for and,or,xor nodes. When one element is
  625. u32bit then the other is typecasted also to u32bit without giving
  626. a rangecheck warning/error.
  627. * fixed pascal calling method with reversing also the high tree in
  628. the parast, detected by tcalcst3 test
  629. Revision 1.37 2002/04/19 15:46:03 peter
  630. * mangledname rewrite, tprocdef.mangledname is now created dynamicly
  631. in most cases and not written to the ppu
  632. * add mangeledname_prefix() routine to generate the prefix of
  633. manglednames depending on the current procedure, object and module
  634. * removed static procprefix since the mangledname is now build only
  635. on demand from tprocdef.mangledname
  636. Revision 1.36 2002/04/16 16:12:47 peter
  637. * give error when using enums with jumps as array index
  638. * allow char as enum value
  639. Revision 1.35 2002/04/04 19:06:04 peter
  640. * removed unused units
  641. * use tlocation.size in cg.a_*loc*() routines
  642. Revision 1.34 2002/01/24 18:25:49 peter
  643. * implicit result variable generation for assembler routines
  644. * removed m_tp modeswitch, use m_tp7 or not(m_fpc) instead
  645. Revision 1.33 2002/01/15 16:13:34 jonas
  646. * fixed web bugs 1758 and 1760
  647. Revision 1.32 2002/01/06 12:08:15 peter
  648. * removed uauto from orddef, use new range_to_basetype generating
  649. the correct ordinal type for a range
  650. }