ptype.pas 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675
  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;isforwarddef:boolean);
  34. procedure read_type(var tt:ttype;const name : stringid;parseprocvardir:boolean);
  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;isforwarddef:boolean);
  39. implementation
  40. uses
  41. { common }
  42. cutils,
  43. { global }
  44. globals,tokens,verbose,
  45. systems,
  46. { target }
  47. paramgr,
  48. { symtable }
  49. symconst,symbase,symdef,symsym,symtable,
  50. defutil,defcmp,
  51. { pass 1 }
  52. node,
  53. nmat,nadd,ncal,nset,ncnv,ninl,ncon,nld,nflw,
  54. { parser }
  55. scanner,
  56. pbase,pexpr,pdecsub,pdecvar,pdecobj;
  57. procedure id_type(var tt : ttype;isforwarddef:boolean);
  58. { reads a type definition }
  59. { to a appropriating tdef, s gets the name of }
  60. { the type to allow name mangling }
  61. var
  62. is_unit_specific : boolean;
  63. pos : tfileposinfo;
  64. srsym : tsym;
  65. srsymtable : tsymtable;
  66. s,sorg : stringid;
  67. begin
  68. s:=pattern;
  69. sorg:=orgpattern;
  70. pos:=akttokenpos;
  71. { classes can be used also in classes }
  72. if (curobjectname=pattern) and is_class_or_interface(aktobjectdef) then
  73. begin
  74. tt.setdef(aktobjectdef);
  75. consume(_ID);
  76. exit;
  77. end;
  78. { objects can be parameters }
  79. if (testcurobject=2) and (curobjectname=pattern) then
  80. begin
  81. tt.setdef(aktobjectdef);
  82. consume(_ID);
  83. exit;
  84. end;
  85. { try to load the symbol to see if it's a unitsym. Use the
  86. special searchsym_type that ignores records,objects and
  87. parameters }
  88. is_unit_specific:=false;
  89. searchsym_type(s,srsym,srsymtable);
  90. consume(_ID);
  91. if assigned(srsym) and
  92. (srsym.typ=unitsym) then
  93. begin
  94. is_unit_specific:=true;
  95. consume(_POINT);
  96. if not(srsym.owner.symtabletype in [staticsymtable,globalsymtable]) then
  97. internalerror(200501155);
  98. { only allow unit.symbol access if the name was
  99. found in the current module }
  100. if srsym.owner.iscurrentunit then
  101. begin
  102. srsym:=searchsymonlyin(tunitsym(srsym).unitsymtable,pattern);
  103. pos:=akttokenpos;
  104. s:=pattern;
  105. end
  106. else
  107. srsym:=nil;
  108. consume(_ID);
  109. end;
  110. { Types are first defined with an error def before assigning
  111. the real type so check if it's an errordef. if so then
  112. give an error. Only check for typesyms in the current symbol
  113. table as forwarddef are not resolved directly }
  114. if assigned(srsym) and
  115. (srsym.typ=typesym) and
  116. (srsym.owner=symtablestack) and
  117. (ttypesym(srsym).restype.def.deftype=errordef) then
  118. begin
  119. Message1(type_e_type_is_not_completly_defined,ttypesym(srsym).realname);
  120. tt:=generrortype;
  121. exit;
  122. end;
  123. { are we parsing a possible forward def ? }
  124. if isforwarddef and
  125. not(is_unit_specific) then
  126. begin
  127. tt.setdef(tforwarddef.create(s,pos));
  128. exit;
  129. end;
  130. { unknown sym ? }
  131. if not assigned(srsym) then
  132. begin
  133. Message1(sym_e_id_not_found,sorg);
  134. tt:=generrortype;
  135. exit;
  136. end;
  137. { type sym ? }
  138. if (srsym.typ<>typesym) then
  139. begin
  140. Message(type_e_type_id_expected);
  141. tt:=generrortype;
  142. exit;
  143. end;
  144. { Give an error when referring to an errordef }
  145. if (ttypesym(srsym).restype.def.deftype=errordef) then
  146. begin
  147. Message(sym_e_error_in_type_def);
  148. tt:=generrortype;
  149. exit;
  150. end;
  151. { Use the definitions for current unit, because
  152. they can be refered from the parameters and symbols are not
  153. loaded at that time. Only write the definition when the
  154. symbol is the real owner of the definition (not a redefine) }
  155. if (ttypesym(srsym).owner.symtabletype in [staticsymtable,globalsymtable]) and
  156. ttypesym(srsym).owner.iscurrentunit and
  157. (
  158. (ttypesym(srsym).restype.def.typesym=nil) or
  159. (srsym=ttypesym(srsym).restype.def.typesym)
  160. ) then
  161. tt.setdef(ttypesym(srsym).restype.def)
  162. else
  163. tt.setsym(srsym);
  164. end;
  165. procedure single_type(var tt:ttype;isforwarddef:boolean);
  166. var
  167. t2 : ttype;
  168. begin
  169. case token of
  170. _STRING:
  171. string_dec(tt);
  172. _FILE:
  173. begin
  174. consume(_FILE);
  175. if token=_OF then
  176. begin
  177. consume(_OF);
  178. single_type(t2,false);
  179. tt.setdef(tfiledef.createtyped(t2));
  180. end
  181. else
  182. tt:=cfiletype;
  183. end;
  184. _ID:
  185. id_type(tt,isforwarddef);
  186. else
  187. begin
  188. message(type_e_type_id_expected);
  189. tt:=generrortype;
  190. end;
  191. end;
  192. end;
  193. { reads a record declaration }
  194. function record_dec : tdef;
  195. var
  196. symtable : tsymtable;
  197. storetypecanbeforward : boolean;
  198. old_object_option : tsymoptions;
  199. begin
  200. { create recdef }
  201. symtable:=trecordsymtable.create(aktpackrecords);
  202. record_dec:=trecorddef.create(symtable);
  203. { update symtable stack }
  204. symtable.next:=symtablestack;
  205. symtablestack:=symtable;
  206. { parse record }
  207. consume(_RECORD);
  208. old_object_option:=current_object_option;
  209. current_object_option:=[sp_public];
  210. storetypecanbeforward:=typecanbeforward;
  211. { for tp7 don't allow forward types }
  212. if m_tp7 in aktmodeswitches then
  213. typecanbeforward:=false;
  214. read_var_decs(true,false,false);
  215. consume(_END);
  216. typecanbeforward:=storetypecanbeforward;
  217. current_object_option:=old_object_option;
  218. { make the record size aligned }
  219. trecordsymtable(symtablestack).addalignmentpadding;
  220. { restore symtable stack }
  221. symtablestack:=symtable.next;
  222. end;
  223. { reads a type definition and returns a pointer to it }
  224. procedure read_type(var tt : ttype;const name : stringid;parseprocvardir:boolean);
  225. var
  226. pt : tnode;
  227. tt2 : ttype;
  228. aktenumdef : tenumdef;
  229. ap : tarraydef;
  230. s : stringid;
  231. l,v : TConstExprInt;
  232. oldaktpackrecords : longint;
  233. defpos,storepos : tfileposinfo;
  234. procedure expr_type;
  235. var
  236. pt1,pt2 : tnode;
  237. lv,hv : TConstExprInt;
  238. begin
  239. { use of current parsed object ? }
  240. if (token=_ID) and (testcurobject=2) and (curobjectname=pattern) then
  241. begin
  242. consume(_ID);
  243. tt.setdef(aktobjectdef);
  244. exit;
  245. end;
  246. { classes can be used also in classes }
  247. if (curobjectname=pattern) and is_class_or_interface(aktobjectdef) then
  248. begin
  249. tt.setdef(aktobjectdef);
  250. consume(_ID);
  251. exit;
  252. end;
  253. { we can't accept a equal in type }
  254. pt1:=comp_expr(not(ignore_equal));
  255. if (token=_POINTPOINT) then
  256. begin
  257. consume(_POINTPOINT);
  258. { get high value of range }
  259. pt2:=comp_expr(not(ignore_equal));
  260. { make both the same type or give an error. This is not
  261. done when both are integer values, because typecasting
  262. between -3200..3200 will result in a signed-unsigned
  263. conflict and give a range check error (PFV) }
  264. if not(is_integer(pt1.resulttype.def) and is_integer(pt2.resulttype.def)) then
  265. inserttypeconv(pt1,pt2.resulttype);
  266. { both must be evaluated to constants now }
  267. if (pt1.nodetype=ordconstn) and
  268. (pt2.nodetype=ordconstn) then
  269. begin
  270. lv:=tordconstnode(pt1).value;
  271. hv:=tordconstnode(pt2).value;
  272. { Check bounds }
  273. if hv<lv then
  274. Message(parser_e_upper_lower_than_lower)
  275. else
  276. begin
  277. { All checks passed, create the new def }
  278. case pt1.resulttype.def.deftype of
  279. enumdef :
  280. tt.setdef(tenumdef.create_subrange(tenumdef(pt1.resulttype.def),lv,hv));
  281. orddef :
  282. begin
  283. if is_char(pt1.resulttype.def) then
  284. tt.setdef(torddef.create(uchar,lv,hv))
  285. else
  286. if is_boolean(pt1.resulttype.def) then
  287. tt.setdef(torddef.create(bool8bit,l,hv))
  288. else
  289. tt.setdef(torddef.create(range_to_basetype(lv,hv),lv,hv));
  290. end;
  291. end;
  292. end;
  293. end
  294. else
  295. Message(sym_e_error_in_type_def);
  296. pt2.free;
  297. end
  298. else
  299. begin
  300. { a simple type renaming }
  301. if (pt1.nodetype=typen) then
  302. tt:=ttypenode(pt1).resulttype
  303. else
  304. Message(sym_e_error_in_type_def);
  305. end;
  306. pt1.free;
  307. end;
  308. procedure array_dec;
  309. var
  310. lowval,
  311. highval : aint;
  312. arraytype : ttype;
  313. ht : ttype;
  314. procedure setdefdecl(const t:ttype);
  315. begin
  316. case t.def.deftype of
  317. enumdef :
  318. begin
  319. lowval:=tenumdef(t.def).min;
  320. highval:=tenumdef(t.def).max;
  321. if (m_fpc in aktmodeswitches) and
  322. (tenumdef(t.def).has_jumps) then
  323. Message(type_e_array_index_enums_with_assign_not_possible);
  324. arraytype:=t;
  325. end;
  326. orddef :
  327. begin
  328. if torddef(t.def).typ in [uchar,
  329. u8bit,u16bit,
  330. s8bit,s16bit,s32bit,
  331. {$ifdef cpu64bit}
  332. u32bit,s64bit,
  333. {$endif cpu64bit}
  334. bool8bit,bool16bit,bool32bit,
  335. uwidechar] then
  336. begin
  337. lowval:=torddef(t.def).low;
  338. highval:=torddef(t.def).high;
  339. arraytype:=t;
  340. end
  341. else
  342. Message1(parser_e_type_cant_be_used_in_array_index,t.def.gettypename);
  343. end;
  344. else
  345. Message(sym_e_error_in_type_def);
  346. end;
  347. end;
  348. begin
  349. consume(_ARRAY);
  350. { open array? }
  351. if token=_LECKKLAMMER then
  352. begin
  353. consume(_LECKKLAMMER);
  354. { defaults }
  355. arraytype:=generrortype;
  356. lowval:=low(aint);
  357. highval:=high(aint);
  358. tt.reset;
  359. repeat
  360. { read the expression and check it, check apart if the
  361. declaration is an enum declaration because that needs to
  362. be parsed by readtype (PFV) }
  363. if token=_LKLAMMER then
  364. begin
  365. read_type(ht,'',true);
  366. setdefdecl(ht);
  367. end
  368. else
  369. begin
  370. pt:=expr;
  371. if pt.nodetype=typen then
  372. setdefdecl(pt.resulttype)
  373. else
  374. begin
  375. if (pt.nodetype=rangen) then
  376. begin
  377. if (trangenode(pt).left.nodetype=ordconstn) and
  378. (trangenode(pt).right.nodetype=ordconstn) then
  379. begin
  380. { make both the same type or give an error. This is not
  381. done when both are integer values, because typecasting
  382. between -3200..3200 will result in a signed-unsigned
  383. conflict and give a range check error (PFV) }
  384. if not(is_integer(trangenode(pt).left.resulttype.def) and is_integer(trangenode(pt).left.resulttype.def)) then
  385. inserttypeconv(trangenode(pt).left,trangenode(pt).right.resulttype);
  386. lowval:=tordconstnode(trangenode(pt).left).value;
  387. highval:=tordconstnode(trangenode(pt).right).value;
  388. if highval<lowval then
  389. begin
  390. Message(parser_e_array_lower_less_than_upper_bound);
  391. highval:=lowval;
  392. end;
  393. if is_integer(trangenode(pt).left.resulttype.def) then
  394. range_to_type(lowval,highval,arraytype)
  395. else
  396. arraytype:=trangenode(pt).left.resulttype;
  397. end
  398. else
  399. Message(type_e_cant_eval_constant_expr);
  400. end
  401. else
  402. Message(sym_e_error_in_type_def)
  403. end;
  404. pt.free;
  405. end;
  406. { create arraydef }
  407. if not assigned(tt.def) then
  408. begin
  409. ap:=tarraydef.create(lowval,highval,arraytype);
  410. tt.setdef(ap);
  411. end
  412. else
  413. begin
  414. ap.elementtype.setdef(tarraydef.create(lowval,highval,arraytype));
  415. ap:=tarraydef(ap.elementtype.def);
  416. end;
  417. if token=_COMMA then
  418. consume(_COMMA)
  419. else
  420. break;
  421. until false;
  422. consume(_RECKKLAMMER);
  423. end
  424. else
  425. begin
  426. ap:=tarraydef.create(0,-1,s32inttype);
  427. ap.IsDynamicArray:=true;
  428. tt.setdef(ap);
  429. end;
  430. consume(_OF);
  431. read_type(tt2,'',true);
  432. { if no error, set element type }
  433. if assigned(ap) then
  434. ap.setelementtype(tt2);
  435. end;
  436. var
  437. p : tnode;
  438. pd : tabstractprocdef;
  439. is_func,
  440. enumdupmsg : boolean;
  441. newtype : ttypesym;
  442. oldlocalswitches : tlocalswitches;
  443. begin
  444. tt.reset;
  445. case token of
  446. _STRING,_FILE:
  447. begin
  448. single_type(tt,false);
  449. end;
  450. _LKLAMMER:
  451. begin
  452. consume(_LKLAMMER);
  453. { allow negativ value_str }
  454. l:=-1;
  455. enumdupmsg:=false;
  456. aktenumdef:=tenumdef.create;
  457. repeat
  458. s:=orgpattern;
  459. defpos:=akttokenpos;
  460. consume(_ID);
  461. { only allow assigning of specific numbers under fpc mode }
  462. if not(m_tp7 in aktmodeswitches) and
  463. (
  464. { in fpc mode also allow := to be compatible
  465. with previous 1.0.x versions }
  466. ((m_fpc in aktmodeswitches) and
  467. try_to_consume(_ASSIGNMENT)) or
  468. try_to_consume(_EQUAL)
  469. ) then
  470. begin
  471. oldlocalswitches:=aktlocalswitches;
  472. include(aktlocalswitches,cs_allow_enum_calc);
  473. p:=comp_expr(true);
  474. aktlocalswitches:=oldlocalswitches;
  475. if (p.nodetype=ordconstn) then
  476. begin
  477. { we expect an integer or an enum of the
  478. same type }
  479. if is_integer(p.resulttype.def) or
  480. is_char(p.resulttype.def) or
  481. equal_defs(p.resulttype.def,aktenumdef) then
  482. v:=tordconstnode(p).value
  483. else
  484. IncompatibleTypes(p.resulttype.def,s32inttype.def);
  485. end
  486. else
  487. Message(parser_e_illegal_expression);
  488. p.free;
  489. { please leave that a note, allows type save }
  490. { declarations in the win32 units ! }
  491. if (v<=l) and (not enumdupmsg) then
  492. begin
  493. Message(parser_n_duplicate_enum);
  494. enumdupmsg:=true;
  495. end;
  496. l:=v;
  497. end
  498. else
  499. inc(l);
  500. storepos:=akttokenpos;
  501. akttokenpos:=defpos;
  502. constsymtable.insert(tenumsym.create(s,aktenumdef,l));
  503. akttokenpos:=storepos;
  504. until not try_to_consume(_COMMA);
  505. tt.setdef(aktenumdef);
  506. consume(_RKLAMMER);
  507. end;
  508. _ARRAY:
  509. begin
  510. array_dec;
  511. end;
  512. _SET:
  513. begin
  514. consume(_SET);
  515. consume(_OF);
  516. read_type(tt2,'',true);
  517. if assigned(tt2.def) then
  518. begin
  519. case tt2.def.deftype of
  520. { don't forget that min can be negativ PM }
  521. enumdef :
  522. if tenumdef(tt2.def).min>=0 then
  523. tt.setdef(tsetdef.create(tt2,tenumdef(tt2.def).max))
  524. else
  525. Message(sym_e_ill_type_decl_set);
  526. orddef :
  527. begin
  528. case torddef(tt2.def).typ of
  529. uchar :
  530. tt.setdef(tsetdef.create(tt2,255));
  531. u8bit,u16bit,u32bit,
  532. s8bit,s16bit,s32bit :
  533. begin
  534. if (torddef(tt2.def).low>=0) then
  535. tt.setdef(tsetdef.create(tt2,torddef(tt2.def).high))
  536. else
  537. Message(sym_e_ill_type_decl_set);
  538. end;
  539. else
  540. Message(sym_e_ill_type_decl_set);
  541. end;
  542. end;
  543. else
  544. Message(sym_e_ill_type_decl_set);
  545. end;
  546. end
  547. else
  548. tt:=generrortype;
  549. end;
  550. _CARET:
  551. begin
  552. consume(_CARET);
  553. single_type(tt2,typecanbeforward);
  554. tt.setdef(tpointerdef.create(tt2));
  555. end;
  556. _RECORD:
  557. begin
  558. tt.setdef(record_dec);
  559. end;
  560. _PACKED:
  561. begin
  562. consume(_PACKED);
  563. if token=_ARRAY then
  564. array_dec
  565. else
  566. begin
  567. oldaktpackrecords:=aktpackrecords;
  568. aktpackrecords:=1;
  569. if token in [_CLASS,_OBJECT] then
  570. tt.setdef(object_dec(name,nil))
  571. else
  572. tt.setdef(record_dec);
  573. aktpackrecords:=oldaktpackrecords;
  574. end;
  575. end;
  576. _CLASS,
  577. _CPPCLASS,
  578. _INTERFACE,
  579. _OBJECT:
  580. begin
  581. tt.setdef(object_dec(name,nil));
  582. end;
  583. _PROCEDURE,
  584. _FUNCTION:
  585. begin
  586. is_func:=(token=_FUNCTION);
  587. consume(token);
  588. pd:=tprocvardef.create(normal_function_level);
  589. if token=_LKLAMMER then
  590. parse_parameter_dec(pd);
  591. if is_func then
  592. begin
  593. consume(_COLON);
  594. single_type(pd.rettype,false);
  595. end;
  596. if token=_OF then
  597. begin
  598. consume(_OF);
  599. consume(_OBJECT);
  600. include(pd.procoptions,po_methodpointer);
  601. end;
  602. tt.def:=pd;
  603. { possible proc directives }
  604. if parseprocvardir then
  605. begin
  606. if check_proc_directive(true) then
  607. begin
  608. newtype:=ttypesym.create('unnamed',tt);
  609. parse_var_proc_directives(tsym(newtype));
  610. newtype.restype.def:=nil;
  611. tt.def.typesym:=nil;
  612. newtype.free;
  613. end;
  614. { Add implicit hidden parameters and function result }
  615. handle_calling_convention(pd);
  616. end;
  617. end;
  618. else
  619. expr_type;
  620. end;
  621. if tt.def=nil then
  622. tt:=generrortype;
  623. end;
  624. end.
  625. {
  626. $Log$
  627. Revision 1.76 2005-02-17 17:52:39 peter
  628. * allow enum arithmetics inside an enum def, compatible with delphi
  629. Revision 1.75 2005/02/14 17:13:07 peter
  630. * truncate log
  631. Revision 1.74 2005/02/01 08:46:13 michael
  632. * Patch from peter: fix macpas anonymous function procvar
  633. Revision 1.73 2005/01/19 22:19:41 peter
  634. * unit mapping rewrite
  635. * new derefmap added
  636. Revision 1.72 2005/01/04 16:39:12 peter
  637. * allow enum with jumps as array index in delphi mode
  638. }