ptype.pas 61 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611
  1. {
  2. $Id$
  3. Copyright (c) 1999 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. interface
  20. uses
  21. globtype,symtable;
  22. const
  23. { forward types should only be possible inside a TYPE statement }
  24. typecanbeforward : boolean = false;
  25. var
  26. { ttypesym read by read_type, this is needed to be
  27. stored in the ppu for resolving purposes }
  28. readtypesym : ptypesym;
  29. { hack, which allows to use the current parsed }
  30. { object type as function argument type }
  31. testcurobject : byte;
  32. curobjectname : stringid;
  33. { parses a string declaration }
  34. function string_dec : pdef;
  35. { parses a object declaration }
  36. function object_dec(const n : stringid;fd : pobjectdef) : pdef;
  37. { reads a string, file type or a type id and returns a name and }
  38. { pdef }
  39. function single_type(var s : string;isforwarddef:boolean) : pdef;
  40. function read_type(const name : stringid) : pdef;
  41. implementation
  42. uses
  43. cobjects,globals,verbose,systems,tokens,
  44. aasm,symconst,types,
  45. {$ifdef GDB}
  46. gdb,
  47. {$endif}
  48. tree,hcodegen,hcgdata,
  49. scanner,pbase,pexpr,pdecl,psub,
  50. tccnv,pass_1;
  51. function string_dec : pdef;
  52. { reads a string type with optional length }
  53. { and returns a pointer to the string }
  54. { definition }
  55. var
  56. p : ptree;
  57. d : pdef;
  58. begin
  59. consume(_STRING);
  60. if token=_LECKKLAMMER then
  61. begin
  62. consume(_LECKKLAMMER);
  63. p:=comp_expr(true);
  64. do_firstpass(p);
  65. if not is_constintnode(p) then
  66. Message(cg_e_illegal_expression);
  67. if (p^.value<=0) then
  68. begin
  69. Message(parser_e_invalid_string_size);
  70. p^.value:=255;
  71. end;
  72. consume(_RECKKLAMMER);
  73. if p^.value>255 then
  74. d:=new(pstringdef,longinit(p^.value))
  75. else
  76. if p^.value<>255 then
  77. d:=new(pstringdef,shortinit(p^.value))
  78. else
  79. d:=cshortstringdef;
  80. disposetree(p);
  81. end
  82. else
  83. begin
  84. if cs_ansistrings in aktlocalswitches then
  85. d:=cansistringdef
  86. else
  87. d:=cshortstringdef;
  88. end;
  89. string_dec:=d;
  90. end;
  91. function id_type(var s : string;isforwarddef:boolean) : pdef;
  92. { reads a type definition and returns a pointer }
  93. { to a appropriating pdef, s gets the name of }
  94. { the type to allow name mangling }
  95. var
  96. is_unit_specific : boolean;
  97. begin
  98. s:=pattern;
  99. consume(_ID);
  100. { classes can be used also in classes }
  101. if (curobjectname=pattern) and aktobjectdef^.is_class then
  102. begin
  103. id_type:=aktobjectdef;
  104. exit;
  105. end;
  106. { objects can be parameters }
  107. if (testcurobject=2) and (curobjectname=pattern) then
  108. begin
  109. id_type:=aktobjectdef;
  110. exit;
  111. end;
  112. { try to load the symbol to see if it's a unitsym }
  113. is_unit_specific:=false;
  114. getsym(s,false);
  115. if assigned(srsym) and
  116. (srsym^.typ=unitsym) then
  117. begin
  118. consume(_POINT);
  119. getsymonlyin(punitsym(srsym)^.unitsymtable,pattern);
  120. s:=pattern;
  121. consume(_ID);
  122. is_unit_specific:=true;
  123. end;
  124. { are we parsing a possible forward def ? }
  125. if isforwarddef and
  126. not(is_unit_specific) then
  127. begin
  128. id_type:=new(pforwarddef,init(s));
  129. exit;
  130. end;
  131. { unknown sym ? }
  132. if not assigned(srsym) then
  133. begin
  134. Message1(sym_e_id_not_found,s);
  135. id_type:=generrordef;
  136. exit;
  137. end;
  138. if (srsym^.typ<>typesym) then
  139. begin
  140. Message(type_e_type_id_expected);
  141. id_type:=generrordef;
  142. exit;
  143. end;
  144. { can't use in [] here, becuase unitid can be > 255 }
  145. if (ptypesym(srsym)^.owner^.unitid=0) or
  146. (ptypesym(srsym)^.owner^.unitid=1) then
  147. readtypesym:=nil
  148. else
  149. readtypesym:=ptypesym(srsym);
  150. { return the definition of the type }
  151. id_type:=ptypesym(srsym)^.definition;
  152. end;
  153. function single_type(var s : string;isforwarddef:boolean) : pdef;
  154. { reads a string, file type or a type id and returns a name and }
  155. { pdef }
  156. var
  157. hs : string;
  158. begin
  159. readtypesym:=nil;
  160. case token of
  161. _STRING:
  162. begin
  163. single_type:=string_dec;
  164. s:='STRING';
  165. readtypesym:=nil;
  166. end;
  167. _FILE:
  168. begin
  169. consume(_FILE);
  170. if token=_OF then
  171. begin
  172. consume(_OF);
  173. single_type:=new(pfiledef,init(ft_typed,single_type(hs,false)));
  174. s:='FILE$OF$'+hs;
  175. end
  176. else
  177. begin
  178. single_type:=cfiledef;
  179. s:='FILE';
  180. end;
  181. readtypesym:=nil;
  182. end;
  183. else
  184. begin
  185. single_type:=id_type(s,isforwarddef);
  186. end;
  187. end;
  188. end;
  189. function object_dec(const n : stringid;fd : pobjectdef) : pdef;
  190. { this function parses an object or class declaration }
  191. var
  192. actmembertype : tsymoptions;
  193. there_is_a_destructor : boolean;
  194. is_a_class : boolean;
  195. childof : pobjectdef;
  196. aktclass : pobjectdef;
  197. procedure constructor_head;
  198. begin
  199. consume(_CONSTRUCTOR);
  200. { must be at same level as in implementation }
  201. inc(lexlevel);
  202. parse_proc_head(potype_constructor);
  203. dec(lexlevel);
  204. if (cs_constructor_name in aktglobalswitches) and (aktprocsym^.name<>'INIT') then
  205. Message(parser_e_constructorname_must_be_init);
  206. {$ifdef INCLUDEOK}
  207. include(aktclass^.objectoptions,oo_has_constructor);
  208. {$else}
  209. aktclass^.objectoptions:=aktclass^.objectoptions+[oo_has_constructor];
  210. {$endif}
  211. consume(_SEMICOLON);
  212. begin
  213. if (aktclass^.is_class) then
  214. begin
  215. { CLASS constructors return the created instance }
  216. aktprocsym^.definition^.retdef:=aktclass;
  217. end
  218. else
  219. begin
  220. { OBJECT constructors return a boolean }
  221. {$IfDef GDB}
  222. {GDB doesn't like unnamed types !}
  223. aktprocsym^.definition^.retdef:=
  224. globaldef('boolean');
  225. {$Else GDB}
  226. aktprocsym^.definition^.retdef:=
  227. new(porddef,init(bool8bit,0,1));
  228. {$Endif GDB}
  229. end;
  230. end;
  231. end;
  232. procedure property_dec;
  233. var
  234. sym : psym;
  235. propertyparas : plinkedlist;
  236. { returns the matching procedure to access a property }
  237. function get_procdef : pprocdef;
  238. var
  239. p : pprocdef;
  240. begin
  241. p:=pprocsym(sym)^.definition;
  242. get_procdef:=nil;
  243. while assigned(p) do
  244. begin
  245. if equal_paras(p^.para,propertyparas,true) then
  246. break;
  247. p:=p^.nextoverloaded;
  248. end;
  249. get_procdef:=p;
  250. end;
  251. procedure deletepropsymlist(p : ppropsymlist);
  252. var
  253. hp : ppropsymlist;
  254. begin
  255. while assigned(p) do
  256. begin
  257. hp:=p;
  258. p:=p^.next;
  259. dispose(hp);
  260. end;
  261. end;
  262. procedure addpropsymlist(var root:ppropsymlist;s:psym);
  263. var
  264. last,hp : ppropsymlist;
  265. begin
  266. if not assigned(s) then
  267. exit;
  268. last:=root;
  269. new(hp);
  270. hp^.sym:=s;
  271. hp^.next:=nil;
  272. if assigned(last) then
  273. begin
  274. while assigned(last^.next) do
  275. last:=last^.next;
  276. last^.next:=hp;
  277. end
  278. else
  279. root:=hp;
  280. end;
  281. function copypropsymlist(s:ppropsymlist):ppropsymlist;
  282. var
  283. root,last,hp : ppropsymlist;
  284. begin
  285. copypropsymlist:=nil;
  286. if not assigned(s) then
  287. exit;
  288. last:=nil;
  289. root:=nil;
  290. while assigned(s) do
  291. begin
  292. new(hp);
  293. hp^.sym:=s^.sym;
  294. hp^.next:=nil;
  295. if assigned(last) then
  296. last^.next:=hp;
  297. last:=hp;
  298. if not assigned(root) then
  299. root:=hp;
  300. s:=s^.next;
  301. end;
  302. copypropsymlist:=root;
  303. end;
  304. var
  305. hp2,datacoll : pparaitem;
  306. p,p2 : ppropertysym;
  307. overriden : psym;
  308. hs : string;
  309. varspez : tvarspez;
  310. sc : pstringcontainer;
  311. hp : pdef;
  312. s : string;
  313. declarepos : tfileposinfo;
  314. pp : pprocdef;
  315. pt : ptree;
  316. propname : stringid;
  317. begin
  318. { check for a class }
  319. if not(aktclass^.is_class) then
  320. Message(parser_e_syntax_error);
  321. consume(_PROPERTY);
  322. new(propertyparas,init);
  323. datacoll:=nil;
  324. if token=_ID then
  325. begin
  326. p:=new(ppropertysym,init(pattern));
  327. propname:=pattern;
  328. consume(_ID);
  329. { property parameters ? }
  330. if token=_LECKKLAMMER then
  331. begin
  332. if (sp_published in current_object_option) then
  333. Message(parser_e_cant_publish_that_property);
  334. { create a list of the parameters in propertyparas }
  335. consume(_LECKKLAMMER);
  336. inc(testcurobject);
  337. repeat
  338. if token=_VAR then
  339. begin
  340. consume(_VAR);
  341. varspez:=vs_var;
  342. end
  343. else if token=_CONST then
  344. begin
  345. consume(_CONST);
  346. varspez:=vs_const;
  347. end
  348. else varspez:=vs_value;
  349. sc:=idlist;
  350. if token=_COLON then
  351. begin
  352. consume(_COLON);
  353. if token=_ARRAY then
  354. begin
  355. {
  356. if (varspez<>vs_const) and
  357. (varspez<>vs_var) then
  358. begin
  359. varspez:=vs_const;
  360. Message(parser_e_illegal_open_parameter);
  361. end;
  362. }
  363. consume(_ARRAY);
  364. consume(_OF);
  365. { define range and type of range }
  366. hp:=new(parraydef,init(0,-1,s32bitdef));
  367. { define field type }
  368. parraydef(hp)^.definition:=single_type(s,false);
  369. end
  370. else
  371. hp:=single_type(s,false);
  372. end
  373. else
  374. hp:=cformaldef;
  375. repeat
  376. s:=sc^.get_with_tokeninfo(declarepos);
  377. if s='' then
  378. break;
  379. new(hp2,init);
  380. hp2^.paratyp:=varspez;
  381. hp2^.data:=hp;
  382. propertyparas^.insert(hp2);
  383. until false;
  384. dispose(sc,done);
  385. until not try_to_consume(_SEMICOLON);
  386. dec(testcurobject);
  387. consume(_RECKKLAMMER);
  388. end;
  389. { overriden property ? }
  390. { force property interface, if there is a property parameter }
  391. if (token=_COLON) or assigned(propertyparas) then
  392. begin
  393. consume(_COLON);
  394. p^.proptype:=single_type(hs,false);
  395. if (idtoken=_INDEX) then
  396. begin
  397. consume(_INDEX);
  398. pt:=comp_expr(true);
  399. do_firstpass(pt);
  400. if not(is_ordinal(pt^.resulttype)) or
  401. is_64bitint(pt^.resulttype) then
  402. Message(parser_e_invalid_property_index_value);
  403. p^.index:=pt^.value;
  404. {$ifdef INCLUDEOK}
  405. include(p^.propoptions,ppo_indexed);
  406. {$else}
  407. p^.propoptions:=p^.propoptions+[ppo_indexed];
  408. {$endif}
  409. { concat a longint to the para template }
  410. new(hp2,init);
  411. hp2^.paratyp:=vs_value;
  412. hp2^.data:=pt^.resulttype;
  413. propertyparas^.insert(hp2);
  414. disposetree(pt);
  415. end;
  416. end
  417. else
  418. begin
  419. { do an property override }
  420. overriden:=search_class_member(aktclass,propname);
  421. if assigned(overriden) and (overriden^.typ=propertysym) then
  422. begin
  423. { take the whole info: }
  424. p^.propoptions:=ppropertysym(overriden)^.propoptions;
  425. p^.index:=ppropertysym(overriden)^.index;
  426. p^.proptype:=ppropertysym(overriden)^.proptype;
  427. p^.writeaccesssym:=copypropsymlist(ppropertysym(overriden)^.writeaccesssym);
  428. p^.readaccesssym:=copypropsymlist(ppropertysym(overriden)^.readaccesssym);
  429. p^.storedsym:=copypropsymlist(ppropertysym(overriden)^.storedsym);
  430. p^.writeaccessdef:=ppropertysym(overriden)^.writeaccessdef;
  431. p^.readaccessdef:=ppropertysym(overriden)^.readaccessdef;
  432. p^.storeddef:=ppropertysym(overriden)^.storeddef;
  433. p^.default:=ppropertysym(overriden)^.default;
  434. end
  435. else
  436. begin
  437. p^.proptype:=generrordef;
  438. message(parser_e_no_property_found_to_override);
  439. end;
  440. end;
  441. if (sp_published in current_object_option) and
  442. not(p^.proptype^.is_publishable) then
  443. Message(parser_e_cant_publish_that_property);
  444. { create data defcoll to allow correct parameter checks }
  445. new(datacoll,init);
  446. datacoll^.paratyp:=vs_value;
  447. datacoll^.data:=p^.proptype;
  448. if (idtoken=_READ) then
  449. begin
  450. if assigned(p^.readaccesssym) then
  451. deletepropsymlist(p^.readaccesssym);
  452. p^.readaccesssym:=nil;
  453. consume(_READ);
  454. sym:=search_class_member(aktclass,pattern);
  455. if not(assigned(sym)) then
  456. begin
  457. Message1(sym_e_unknown_id,pattern);
  458. consume(_ID);
  459. end
  460. else
  461. begin
  462. consume(_ID);
  463. while (token=_POINT) and
  464. ((sym^.typ=varsym) and
  465. (pvarsym(sym)^.definition^.deftype=recorddef)) do
  466. begin
  467. addpropsymlist(p^.readaccesssym,sym);
  468. consume(_POINT);
  469. getsymonlyin(precorddef(pvarsym(sym)^.definition)^.symtable,pattern);
  470. if not assigned(srsym) then
  471. Message1(sym_e_illegal_field,pattern);
  472. sym:=srsym;
  473. consume(_ID);
  474. end;
  475. end;
  476. if assigned(sym) then
  477. begin
  478. { search the matching definition }
  479. case sym^.typ of
  480. procsym :
  481. begin
  482. pp:=get_procdef;
  483. if not(assigned(pp)) or
  484. not(is_equal(pp^.retdef,p^.proptype)) then
  485. Message(parser_e_ill_property_access_sym);
  486. p^.readaccessdef:=pp;
  487. end;
  488. varsym :
  489. begin
  490. if not(propertyparas^.empty) or
  491. not(is_equal(pvarsym(sym)^.definition,p^.proptype)) then
  492. Message(parser_e_ill_property_access_sym);
  493. end;
  494. else
  495. Message(parser_e_ill_property_access_sym);
  496. end;
  497. addpropsymlist(p^.readaccesssym,sym);
  498. end;
  499. end;
  500. if (idtoken=_WRITE) then
  501. begin
  502. if assigned(p^.writeaccesssym) then
  503. deletepropsymlist(p^.writeaccesssym);
  504. p^.writeaccesssym:=nil;
  505. consume(_WRITE);
  506. sym:=search_class_member(aktclass,pattern);
  507. if not(assigned(sym)) then
  508. begin
  509. Message1(sym_e_unknown_id,pattern);
  510. consume(_ID);
  511. end
  512. else
  513. begin
  514. consume(_ID);
  515. while (token=_POINT) and
  516. ((sym^.typ=varsym) and
  517. (pvarsym(sym)^.definition^.deftype=recorddef)) do
  518. begin
  519. addpropsymlist(p^.writeaccesssym,sym);
  520. consume(_POINT);
  521. getsymonlyin(precorddef(pvarsym(sym)^.definition)^.symtable,pattern);
  522. if not assigned(srsym) then
  523. Message1(sym_e_illegal_field,pattern);
  524. sym:=srsym;
  525. consume(_ID);
  526. end;
  527. end;
  528. if assigned(sym) then
  529. begin
  530. { search the matching definition }
  531. case sym^.typ of
  532. procsym :
  533. begin
  534. { insert data entry to check access method }
  535. propertyparas^.insert(datacoll);
  536. pp:=get_procdef;
  537. { ... and remove it }
  538. propertyparas^.remove(datacoll);
  539. if not(assigned(pp)) then
  540. Message(parser_e_ill_property_access_sym);
  541. p^.writeaccessdef:=pp;
  542. end;
  543. varsym :
  544. begin
  545. if not(propertyparas^.empty) or
  546. not(is_equal(pvarsym(sym)^.definition,p^.proptype)) then
  547. Message(parser_e_ill_property_access_sym);
  548. end
  549. else
  550. Message(parser_e_ill_property_access_sym);
  551. end;
  552. addpropsymlist(p^.writeaccesssym,sym);
  553. end;
  554. end;
  555. include(p^.propoptions,ppo_stored);
  556. if (idtoken=_STORED) then
  557. begin
  558. consume(_STORED);
  559. if assigned(p^.storedsym) then
  560. deletepropsymlist(p^.storedsym);
  561. p^.storedsym:=nil;
  562. p^.storeddef:=nil;
  563. case token of
  564. _ID:
  565. { in the case that idtoken=_DEFAULT }
  566. { we have to do nothing except }
  567. { setting ppo_stored, it's the same }
  568. { as stored true }
  569. if idtoken<>_DEFAULT then
  570. begin
  571. sym:=search_class_member(aktclass,pattern);
  572. if not(assigned(sym)) then
  573. begin
  574. Message1(sym_e_unknown_id,pattern);
  575. consume(_ID);
  576. end
  577. else
  578. begin
  579. consume(_ID);
  580. while (token=_POINT) and
  581. ((sym^.typ=varsym) and
  582. (pvarsym(sym)^.definition^.deftype=recorddef)) do
  583. begin
  584. addpropsymlist(p^.storedsym,sym);
  585. consume(_POINT);
  586. getsymonlyin(precorddef(pvarsym(sym)^.definition)^.symtable,pattern);
  587. if not assigned(srsym) then
  588. Message1(sym_e_illegal_field,pattern);
  589. sym:=srsym;
  590. consume(_ID);
  591. end;
  592. end;
  593. if assigned(sym) then
  594. begin
  595. { only non array properties can be stored }
  596. case sym^.typ of
  597. procsym :
  598. begin
  599. pp:=pprocsym(sym)^.definition;
  600. while assigned(pp) do
  601. begin
  602. { the stored function shouldn't have any parameters }
  603. if pp^.para^.empty then
  604. break;
  605. pp:=pp^.nextoverloaded;
  606. end;
  607. { found we a procedure and does it really return a bool? }
  608. if not(assigned(pp)) or
  609. not(is_equal(pp^.retdef,booldef)) then
  610. Message(parser_e_ill_property_storage_sym);
  611. p^.storeddef:=pp;
  612. end;
  613. varsym :
  614. begin
  615. if not(propertyparas^.empty) or
  616. not(is_equal(pvarsym(sym)^.definition,booldef)) then
  617. Message(parser_e_stored_property_must_be_boolean);
  618. end;
  619. else
  620. Message(parser_e_ill_property_storage_sym);
  621. end;
  622. addpropsymlist(p^.storedsym,sym);
  623. end;
  624. end;
  625. _FALSE:
  626. begin
  627. consume(_FALSE);
  628. exclude(p^.propoptions,ppo_stored);
  629. end;
  630. _TRUE:
  631. consume(_TRUE);
  632. end;
  633. end;
  634. if (idtoken=_DEFAULT) then
  635. begin
  636. consume(_DEFAULT);
  637. if not(is_ordinal(p^.proptype) or
  638. is_64bitint(p^.proptype) or
  639. ((p^.proptype^.deftype=setdef) and
  640. (psetdef(p^.proptype)^.settype=smallset)
  641. ) or
  642. assigned(propertyparas)
  643. ) then
  644. Message(parser_e_property_cant_have_a_default_value);
  645. { Get the result of the default, the firstpass is
  646. needed to support values like -1 }
  647. pt:=comp_expr(true);
  648. do_firstpass(pt);
  649. if p^.proptype^.deftype=setdef then
  650. begin
  651. {$ifndef newcg}
  652. {!!!!!!!!!!}
  653. arrayconstructor_to_set(pt);
  654. {$endif newcg}
  655. do_firstpass(pt);
  656. end;
  657. pt:=gentypeconvnode(pt,p^.proptype);
  658. do_firstpass(pt);
  659. if not(is_constnode(pt)) then
  660. Message(parser_e_property_default_value_must_const);
  661. if pt^.treetype=setconstn then
  662. p^.default:=plongint(pt^.value_set)^
  663. else
  664. p^.default:=pt^.value;
  665. disposetree(pt);
  666. end
  667. else if (idtoken=_NODEFAULT) then
  668. begin
  669. consume(_NODEFAULT);
  670. p^.default:=0;
  671. end;
  672. symtablestack^.insert(p);
  673. { default property ? }
  674. consume(_SEMICOLON);
  675. if (idtoken=_DEFAULT) then
  676. begin
  677. consume(_DEFAULT);
  678. p2:=search_default_property(aktclass);
  679. if assigned(p2) then
  680. message1(parser_e_only_one_default_property,
  681. pobjectdef(p2^.owner^.defowner)^.objname^)
  682. else
  683. begin
  684. {$ifdef INCLUDEOK}
  685. include(p^.propoptions,ppo_defaultproperty);
  686. {$else}
  687. p^.propoptions:=p^.propoptions+[ppo_defaultproperty];
  688. {$endif}
  689. if not(assigned(propertyparas)) then
  690. message(parser_e_property_need_paras);
  691. end;
  692. consume(_SEMICOLON);
  693. end;
  694. { clean up }
  695. if assigned(datacoll) then
  696. dispose(datacoll,done);
  697. end
  698. else
  699. begin
  700. consume(_ID);
  701. consume(_SEMICOLON);
  702. end;
  703. dispose(propertyparas,done);
  704. end;
  705. procedure destructor_head;
  706. begin
  707. consume(_DESTRUCTOR);
  708. inc(lexlevel);
  709. parse_proc_head(potype_destructor);
  710. dec(lexlevel);
  711. if (cs_constructor_name in aktglobalswitches) and (aktprocsym^.name<>'DONE') then
  712. Message(parser_e_destructorname_must_be_done);
  713. {$ifdef INCLUDEOK}
  714. include(aktclass^.objectoptions,oo_has_destructor);
  715. {$else}
  716. aktclass^.objectoptions:=aktclass^.objectoptions+[oo_has_destructor];
  717. {$endif}
  718. consume(_SEMICOLON);
  719. if not(aktprocsym^.definition^.para^.empty) then
  720. Message(parser_e_no_paras_for_destructor);
  721. { no return value }
  722. aktprocsym^.definition^.retdef:=voiddef;
  723. end;
  724. var
  725. hs : string;
  726. pcrd : pclassrefdef;
  727. hp1 : pdef;
  728. oldprocinfo : pprocinfo;
  729. oldprocsym : pprocsym;
  730. oldparse_only : boolean;
  731. methodnametable,intmessagetable,
  732. strmessagetable,classnamelabel : pasmlabel;
  733. storetypecanbeforward : boolean;
  734. vmtlist : taasmoutput;
  735. begin
  736. {Nowadays aktprocsym may already have a value, so we need to save
  737. it.}
  738. oldprocsym:=aktprocsym;
  739. { forward is resolved }
  740. if assigned(fd) then
  741. {$ifdef INCLUDEOK}
  742. exclude(fd^.objectoptions,oo_is_forward);
  743. {$else}
  744. fd^.objectoptions:=fd^.objectoptions-[oo_is_forward];
  745. {$endif}
  746. there_is_a_destructor:=false;
  747. actmembertype:=[sp_public];
  748. { objects and class types can't be declared local }
  749. if (symtablestack^.symtabletype<>globalsymtable) and
  750. (symtablestack^.symtabletype<>staticsymtable) then
  751. Message(parser_e_no_local_objects);
  752. storetypecanbeforward:=typecanbeforward;
  753. { for tp mode don't allow forward types }
  754. if m_tp in aktmodeswitches then
  755. typecanbeforward:=false;
  756. { distinguish classes and objects }
  757. if token=_OBJECT then
  758. begin
  759. is_a_class:=false;
  760. consume(_OBJECT)
  761. end
  762. else
  763. begin
  764. is_a_class:=true;
  765. consume(_CLASS);
  766. if not(assigned(fd)) and (token=_OF) then
  767. begin
  768. { a hack, but it's easy to handle }
  769. { class reference type }
  770. consume(_OF);
  771. hp1:=single_type(hs,typecanbeforward);
  772. { accept hp1, if is a forward def or a class }
  773. if (hp1^.deftype=forwarddef) or
  774. ((hp1^.deftype=objectdef) and pobjectdef(hp1)^.is_class) then
  775. begin
  776. pcrd:=new(pclassrefdef,init(hp1));
  777. object_dec:=pcrd;
  778. end
  779. else
  780. begin
  781. object_dec:=generrordef;
  782. Message1(type_e_class_type_expected,generrordef^.typename);
  783. end;
  784. typecanbeforward:=storetypecanbeforward;
  785. exit;
  786. end
  787. { forward class }
  788. else if not(assigned(fd)) and (token=_SEMICOLON) then
  789. begin
  790. { also anonym objects aren't allow (o : object a : longint; end;) }
  791. if n='' then
  792. begin
  793. Message(parser_f_no_anonym_objects)
  794. end;
  795. if n='TOBJECT' then
  796. begin
  797. aktclass:=new(pobjectdef,init(n,nil));
  798. class_tobject:=aktclass;
  799. end
  800. else
  801. aktclass:=new(pobjectdef,init(n,nil));
  802. aktclass^.objectoptions:=aktclass^.objectoptions+[oo_is_class,oo_is_forward];
  803. { all classes must have a vmt !! at offset zero }
  804. if not(oo_has_vmt in aktclass^.objectoptions) then
  805. aktclass^.insertvmt;
  806. object_dec:=aktclass;
  807. typecanbeforward:=storetypecanbeforward;
  808. exit;
  809. end;
  810. end;
  811. { also anonym objects aren't allow (o : object a : longint; end;) }
  812. if n='' then
  813. Message(parser_f_no_anonym_objects);
  814. { read the parent class }
  815. if token=_LKLAMMER then
  816. begin
  817. consume(_LKLAMMER);
  818. childof:=pobjectdef(id_type(pattern,false));
  819. if (childof^.deftype<>objectdef) then
  820. begin
  821. Message1(type_e_class_type_expected,childof^.typename);
  822. childof:=nil;
  823. aktclass:=new(pobjectdef,init(n,nil));
  824. end
  825. else
  826. begin
  827. { a mix of class and object isn't allowed }
  828. if (childof^.is_class and not is_a_class) or
  829. (not childof^.is_class and is_a_class) then
  830. Message(parser_e_mix_of_classes_and_objects);
  831. { the forward of the child must be resolved to get
  832. correct field addresses }
  833. if assigned(fd) then
  834. begin
  835. if (oo_is_forward in childof^.objectoptions) then
  836. Message1(parser_e_forward_declaration_must_be_resolved,childof^.objname^);
  837. aktclass:=fd;
  838. { we must inherit several options !!
  839. this was missing !!
  840. all is now done in set_parent
  841. including symtable datasize setting PM }
  842. fd^.set_parent(childof);
  843. end
  844. else
  845. aktclass:=new(pobjectdef,init(n,childof));
  846. end;
  847. consume(_RKLAMMER);
  848. end
  849. { if no parent class, then a class get tobject as parent }
  850. else if is_a_class then
  851. begin
  852. { is the current class tobject? }
  853. { so you could define your own tobject }
  854. if n='TOBJECT' then
  855. begin
  856. if assigned(fd) then
  857. aktclass:=fd
  858. else
  859. aktclass:=new(pobjectdef,init(n,nil));
  860. class_tobject:=aktclass;
  861. end
  862. else
  863. begin
  864. childof:=class_tobject;
  865. if assigned(fd) then
  866. begin
  867. { the forward of the child must be resolved to get
  868. correct field addresses
  869. }
  870. if (oo_is_forward in childof^.objectoptions) then
  871. Message1(parser_e_forward_declaration_must_be_resolved,childof^.objname^);
  872. aktclass:=fd;
  873. aktclass^.set_parent(childof);
  874. end
  875. else
  876. begin
  877. aktclass:=new(pobjectdef,init(n,childof));
  878. aktclass^.set_parent(childof);
  879. end;
  880. end;
  881. end
  882. else
  883. aktclass:=new(pobjectdef,init(n,nil));
  884. { default access is public }
  885. actmembertype:=[sp_public];
  886. { set the class attribute }
  887. if is_a_class then
  888. begin
  889. {$ifdef INCLUDEOK}
  890. include(aktclass^.objectoptions,oo_is_class);
  891. {$else}
  892. aktclass^.objectoptions:=aktclass^.objectoptions+[oo_is_class];
  893. {$endif}
  894. if (cs_generate_rtti in aktlocalswitches) or
  895. (assigned(aktclass^.childof) and
  896. (oo_can_have_published in aktclass^.childof^.objectoptions)) then
  897. begin
  898. include(aktclass^.objectoptions,oo_can_have_published);
  899. { in "publishable" classes the default access type is published }
  900. actmembertype:=[sp_published];
  901. { don't know if this is necessary (FK) }
  902. current_object_option:=[sp_published];
  903. end;
  904. end;
  905. aktobjectdef:=aktclass;
  906. aktclass^.symtable^.next:=symtablestack;
  907. symtablestack:=aktclass^.symtable;
  908. testcurobject:=1;
  909. curobjectname:=n;
  910. { new procinfo }
  911. oldprocinfo:=procinfo;
  912. new(procinfo);
  913. fillchar(procinfo^,sizeof(tprocinfo),0);
  914. procinfo^._class:=aktclass;
  915. { short class declaration ? }
  916. if (not is_a_class) or (token<>_SEMICOLON) then
  917. begin
  918. { Parse componenten }
  919. repeat
  920. if (sp_private in actmembertype) then
  921. {$ifdef INCLUDEOK}
  922. include(aktclass^.objectoptions,oo_has_private);
  923. {$else}
  924. aktclass^.objectoptions:=aktclass^.objectoptions+[oo_has_private];
  925. {$endif}
  926. if (sp_protected in actmembertype) then
  927. {$ifdef INCLUDEOK}
  928. include(aktclass^.objectoptions,oo_has_protected);
  929. {$else}
  930. aktclass^.objectoptions:=aktclass^.objectoptions+[oo_has_protected];
  931. {$endif}
  932. case token of
  933. _ID : begin
  934. case idtoken of
  935. _PRIVATE : begin
  936. consume(_PRIVATE);
  937. actmembertype:=[sp_private];
  938. current_object_option:=[sp_private];
  939. end;
  940. _PROTECTED : begin
  941. consume(_PROTECTED);
  942. current_object_option:=[sp_protected];
  943. actmembertype:=[sp_protected];
  944. end;
  945. _PUBLIC : begin
  946. consume(_PUBLIC);
  947. current_object_option:=[sp_public];
  948. actmembertype:=[sp_public];
  949. end;
  950. _PUBLISHED : begin
  951. if not(oo_can_have_published in aktclass^.objectoptions) then
  952. Message(parser_e_cant_have_published);
  953. consume(_PUBLISHED);
  954. current_object_option:=[sp_published];
  955. actmembertype:=[sp_published];
  956. end;
  957. else
  958. read_var_decs(false,true,false);
  959. end;
  960. end;
  961. _PROPERTY : property_dec;
  962. _PROCEDURE,
  963. _FUNCTION,
  964. _CLASS : begin
  965. oldparse_only:=parse_only;
  966. parse_only:=true;
  967. parse_proc_dec;
  968. {$ifndef newcg}
  969. parse_object_proc_directives(aktprocsym);
  970. {$endif newcg}
  971. if (po_msgint in aktprocsym^.definition^.procoptions) then
  972. {$ifdef INCLUDEOK}
  973. include(aktclass^.objectoptions,oo_has_msgint);
  974. {$else}
  975. aktclass^.objectoptions:=aktclass^.objectoptions+[oo_has_msgint];
  976. {$endif}
  977. if (po_msgstr in aktprocsym^.definition^.procoptions) then
  978. {$ifdef INCLUDEOK}
  979. include(aktclass^.objectoptions,oo_has_msgstr);
  980. {$else}
  981. aktclass^.objectoptions:=aktclass^.objectoptions+[oo_has_msgstr];
  982. {$endif}
  983. if (po_virtualmethod in aktprocsym^.definition^.procoptions) then
  984. {$ifdef INCLUDEOK}
  985. include(aktclass^.objectoptions,oo_has_virtual);
  986. {$else}
  987. aktclass^.objectoptions:=aktclass^.objectoptions+[oo_has_virtual];
  988. {$endif}
  989. parse_only:=oldparse_only;
  990. end;
  991. _CONSTRUCTOR : begin
  992. if not(sp_public in actmembertype) then
  993. Message(parser_w_constructor_should_be_public);
  994. oldparse_only:=parse_only;
  995. parse_only:=true;
  996. constructor_head;
  997. {$ifndef newcg}
  998. parse_object_proc_directives(aktprocsym);
  999. {$endif newcg}
  1000. if (po_virtualmethod in aktprocsym^.definition^.procoptions) then
  1001. {$ifdef INCLUDEOK}
  1002. include(aktclass^.objectoptions,oo_has_virtual);
  1003. {$else}
  1004. aktclass^.objectoptions:=aktclass^.objectoptions+[oo_has_virtual];
  1005. {$endif}
  1006. parse_only:=oldparse_only;
  1007. end;
  1008. _DESTRUCTOR : begin
  1009. if there_is_a_destructor then
  1010. Message(parser_n_only_one_destructor);
  1011. there_is_a_destructor:=true;
  1012. if not(sp_public in actmembertype) then
  1013. Message(parser_w_destructor_should_be_public);
  1014. oldparse_only:=parse_only;
  1015. parse_only:=true;
  1016. destructor_head;
  1017. {$ifndef newcg}
  1018. parse_object_proc_directives(aktprocsym);
  1019. {$endif newcg}
  1020. if (po_virtualmethod in aktprocsym^.definition^.procoptions) then
  1021. {$ifdef INCLUDEOK}
  1022. include(aktclass^.objectoptions,oo_has_virtual);
  1023. {$else}
  1024. aktclass^.objectoptions:=aktclass^.objectoptions+[oo_has_virtual];
  1025. {$endif}
  1026. parse_only:=oldparse_only;
  1027. end;
  1028. _END : begin
  1029. consume(_END);
  1030. break;
  1031. end;
  1032. else
  1033. consume(_ID); { Give a ident expected message, like tp7 }
  1034. end;
  1035. until false;
  1036. current_object_option:=[sp_public];
  1037. end;
  1038. testcurobject:=0;
  1039. curobjectname:='';
  1040. typecanbeforward:=storetypecanbeforward;
  1041. { generate vmt space if needed }
  1042. if not(oo_has_vmt in aktclass^.objectoptions) and
  1043. ([oo_has_virtual,oo_has_constructor,oo_has_destructor,oo_is_class]*aktclass^.objectoptions<>[]) then
  1044. aktclass^.insertvmt;
  1045. if (cs_create_smart in aktmoduleswitches) then
  1046. datasegment^.concat(new(pai_cut,init));
  1047. { Write the start of the VMT, wich is equal for classes and objects }
  1048. if (oo_has_vmt in aktclass^.objectoptions) then
  1049. begin
  1050. { this generates the entries }
  1051. vmtlist.init;
  1052. genvmt(@vmtlist,aktclass);
  1053. { write tables for classes, this must be done before the actual
  1054. class is written, because we need the labels defined }
  1055. if is_a_class then
  1056. begin
  1057. methodnametable:=genpublishedmethodstable(aktclass);
  1058. { rtti }
  1059. if (oo_can_have_published in aktclass^.objectoptions) then
  1060. aktclass^.generate_rtti;
  1061. { write class name }
  1062. getdatalabel(classnamelabel);
  1063. datasegment^.concat(new(pai_label,init(classnamelabel)));
  1064. datasegment^.concat(new(pai_const,init_8bit(length(aktclass^.objname^))));
  1065. datasegment^.concat(new(pai_string,init(aktclass^.objname^)));
  1066. { generate message and dynamic tables }
  1067. if (oo_has_msgstr in aktclass^.objectoptions) then
  1068. strmessagetable:=genstrmsgtab(aktclass);
  1069. if (oo_has_msgint in aktclass^.objectoptions) then
  1070. intmessagetable:=genintmsgtab(aktclass)
  1071. else
  1072. datasegment^.concat(new(pai_const,init_32bit(0)));
  1073. end;
  1074. { write debug info }
  1075. {$ifdef GDB}
  1076. if (cs_debuginfo in aktmoduleswitches) then
  1077. begin
  1078. do_count_dbx:=true;
  1079. if assigned(aktclass^.owner) and assigned(aktclass^.owner^.name) then
  1080. datasegment^.concat(new(pai_stabs,init(strpnew('"vmt_'+aktclass^.owner^.name^+n+':S'+
  1081. typeglobalnumber('__vtbl_ptr_type')+'",'+tostr(N_STSYM)+',0,0,'+aktclass^.vmt_mangledname))));
  1082. end;
  1083. {$endif GDB}
  1084. datasegment^.concat(new(pai_symbol,initname_global(aktclass^.vmt_mangledname,0)));
  1085. { determine the size with symtable^.datasize, because }
  1086. { size gives back 4 for classes }
  1087. datasegment^.concat(new(pai_const,init_32bit(aktclass^.symtable^.datasize)));
  1088. datasegment^.concat(new(pai_const,init_32bit(-aktclass^.symtable^.datasize)));
  1089. { write pointer to parent VMT, this isn't implemented in TP }
  1090. { but this is not used in FPC ? (PM) }
  1091. { it's not used yet, but the delphi-operators as and is need it (FK) }
  1092. { it is not written for parents that don't have any vmt !! }
  1093. if assigned(aktclass^.childof) and
  1094. (oo_has_vmt in aktclass^.childof^.objectoptions) then
  1095. datasegment^.concat(new(pai_const_symbol,initname(aktclass^.childof^.vmt_mangledname)))
  1096. else
  1097. datasegment^.concat(new(pai_const,init_32bit(0)));
  1098. { write extended info for classes, for the order see rtl/inc/objpash.inc }
  1099. if is_a_class then
  1100. begin
  1101. { pointer to class name string }
  1102. datasegment^.concat(new(pai_const_symbol,init(classnamelabel)));
  1103. { pointer to dynamic table }
  1104. if (oo_has_msgint in aktclass^.objectoptions) then
  1105. datasegment^.concat(new(pai_const_symbol,init(intmessagetable)))
  1106. else
  1107. datasegment^.concat(new(pai_const,init_32bit(0)));
  1108. { pointer to method table }
  1109. if assigned(methodnametable) then
  1110. datasegment^.concat(new(pai_const_symbol,init(methodnametable)))
  1111. else
  1112. datasegment^.concat(new(pai_const,init_32bit(0)));
  1113. { pointer to field table }
  1114. datasegment^.concat(new(pai_const,init_32bit(0)));
  1115. { pointer to type info of published section }
  1116. if (oo_can_have_published in aktclass^.objectoptions) then
  1117. datasegment^.concat(new(pai_const_symbol,initname(aktclass^.rtti_name)))
  1118. else
  1119. datasegment^.concat(new(pai_const,init_32bit(0)));
  1120. { inittable for con-/destruction }
  1121. if aktclass^.needs_inittable then
  1122. datasegment^.concat(new(pai_const_symbol,init(aktclass^.get_inittable_label)))
  1123. else
  1124. datasegment^.concat(new(pai_const,init_32bit(0)));
  1125. { auto table }
  1126. datasegment^.concat(new(pai_const,init_32bit(0)));
  1127. { interface table }
  1128. datasegment^.concat(new(pai_const,init_32bit(0)));
  1129. { table for string messages }
  1130. if (oo_has_msgstr in aktclass^.objectoptions) then
  1131. datasegment^.concat(new(pai_const_symbol,init(strmessagetable)))
  1132. else
  1133. datasegment^.concat(new(pai_const,init_32bit(0)));
  1134. end;
  1135. datasegment^.concatlist(@vmtlist);
  1136. vmtlist.done;
  1137. { write the size of the VMT }
  1138. datasegment^.concat(new(pai_symbol_end,initname(aktclass^.vmt_mangledname)));
  1139. end;
  1140. { restore old state }
  1141. symtablestack:=symtablestack^.next;
  1142. aktobjectdef:=nil;
  1143. {Restore procinfo}
  1144. dispose(procinfo);
  1145. procinfo:=oldprocinfo;
  1146. {Restore the aktprocsym.}
  1147. aktprocsym:=oldprocsym;
  1148. object_dec:=aktclass;
  1149. end;
  1150. { reads a record declaration }
  1151. function record_dec : pdef;
  1152. var
  1153. symtable : psymtable;
  1154. storetypecanbeforward : boolean;
  1155. begin
  1156. { create recdef }
  1157. symtable:=new(psymtable,init(recordsymtable));
  1158. record_dec:=new(precorddef,init(symtable));
  1159. { update symtable stack }
  1160. symtable^.next:=symtablestack;
  1161. symtablestack:=symtable;
  1162. { parse record }
  1163. consume(_RECORD);
  1164. storetypecanbeforward:=typecanbeforward;
  1165. { for tp mode don't allow forward types }
  1166. if m_tp in aktmodeswitches then
  1167. typecanbeforward:=false;
  1168. read_var_decs(true,false,false);
  1169. consume(_END);
  1170. typecanbeforward:=storetypecanbeforward;
  1171. { may be scale record size to a size of n*4 ? }
  1172. symtablestack^.datasize:=align(symtablestack^.datasize,symtablestack^.dataalignment);
  1173. { restore symtable stack }
  1174. symtablestack:=symtable^.next;
  1175. end;
  1176. { reads a type definition and returns a pointer to it }
  1177. function read_type(const name : stringid) : pdef;
  1178. var
  1179. pt : ptree;
  1180. hp1,p : pdef;
  1181. aufdef : penumdef;
  1182. aufsym : penumsym;
  1183. ap : parraydef;
  1184. s : stringid;
  1185. l,v : longint;
  1186. oldaktpackrecords : tpackrecords;
  1187. hs : string;
  1188. procedure expr_type;
  1189. var
  1190. pt1,pt2 : ptree;
  1191. begin
  1192. { use of current parsed object ? }
  1193. if (token=_ID) and (testcurobject=2) and (curobjectname=pattern) then
  1194. begin
  1195. consume(_ID);
  1196. p:=aktobjectdef;
  1197. exit;
  1198. end;
  1199. { we can't accept a equal in type }
  1200. pt1:=comp_expr(not(ignore_equal));
  1201. do_firstpass(pt1);
  1202. if (token=_POINTPOINT) then
  1203. begin
  1204. consume(_POINTPOINT);
  1205. { get high value of range }
  1206. pt2:=comp_expr(not(ignore_equal));
  1207. do_firstpass(pt2);
  1208. { both must be evaluated to constants now }
  1209. if (pt1^.treetype<>ordconstn) or (pt2^.treetype<>ordconstn) then
  1210. Message(sym_e_error_in_type_def)
  1211. else
  1212. begin
  1213. { check types }
  1214. if CheckTypes(pt1^.resulttype,pt2^.resulttype) then
  1215. begin
  1216. { Check bounds }
  1217. if pt2^.value<pt1^.value then
  1218. Message(cg_e_upper_lower_than_lower)
  1219. else
  1220. begin
  1221. { All checks passed, create the new def }
  1222. case pt1^.resulttype^.deftype of
  1223. enumdef : p:=new(penumdef,init_subrange(penumdef(pt1^.resulttype),pt1^.value,pt2^.value));
  1224. orddef : begin
  1225. if is_char(pt1^.resulttype) then
  1226. p:=new(porddef,init(uchar,pt1^.value,pt2^.value))
  1227. else
  1228. if is_boolean(pt1^.resulttype) then
  1229. p:=new(porddef,init(bool8bit,pt1^.value,pt2^.value))
  1230. else
  1231. p:=new(porddef,init(uauto,pt1^.value,pt2^.value));
  1232. end;
  1233. end;
  1234. end;
  1235. end;
  1236. end;
  1237. disposetree(pt2);
  1238. end
  1239. else
  1240. begin
  1241. { a simple type renaming }
  1242. if (pt1^.treetype=typen) then
  1243. begin
  1244. p:=pt1^.resulttype;
  1245. readtypesym:=pt1^.typenodesym;
  1246. end
  1247. else
  1248. Message(sym_e_error_in_type_def);
  1249. end;
  1250. disposetree(pt1);
  1251. end;
  1252. procedure array_dec;
  1253. var
  1254. lowval,
  1255. highval : longint;
  1256. arraytype : pdef;
  1257. begin
  1258. consume(_ARRAY);
  1259. consume(_LECKKLAMMER);
  1260. { defaults }
  1261. arraytype:=generrordef;
  1262. lowval:=$80000000;
  1263. highval:=$7fffffff;
  1264. p:=nil;
  1265. repeat
  1266. { read the expression and check it }
  1267. pt:=expr;
  1268. if pt^.treetype=typen then
  1269. begin
  1270. case pt^.resulttype^.deftype of
  1271. enumdef :
  1272. begin
  1273. lowval:=penumdef(pt^.resulttype)^.min;
  1274. highval:=penumdef(pt^.resulttype)^.max;
  1275. arraytype:=pt^.resulttype;
  1276. end;
  1277. orddef :
  1278. begin
  1279. lowval:=porddef(pt^.resulttype)^.low;
  1280. highval:=porddef(pt^.resulttype)^.high;
  1281. arraytype:=pt^.resulttype;
  1282. end;
  1283. else
  1284. Message(sym_e_error_in_type_def);
  1285. end;
  1286. end
  1287. else
  1288. begin
  1289. do_firstpass(pt);
  1290. if (pt^.treetype=rangen) then
  1291. begin
  1292. if (pt^.left^.treetype=ordconstn) and
  1293. (pt^.right^.treetype=ordconstn) then
  1294. begin
  1295. lowval:=pt^.left^.value;
  1296. highval:=pt^.right^.value;
  1297. if highval<lowval then
  1298. begin
  1299. Message(parser_e_array_lower_less_than_upper_bound);
  1300. highval:=lowval;
  1301. end;
  1302. arraytype:=pt^.right^.resulttype;
  1303. end
  1304. else
  1305. Message(type_e_cant_eval_constant_expr);
  1306. end
  1307. else
  1308. Message(sym_e_error_in_type_def)
  1309. end;
  1310. disposetree(pt);
  1311. { create arraydef }
  1312. if p=nil then
  1313. begin
  1314. ap:=new(parraydef,init(lowval,highval,arraytype));
  1315. p:=ap;
  1316. end
  1317. else
  1318. begin
  1319. ap^.definition:=new(parraydef,init(lowval,highval,arraytype));
  1320. ap:=parraydef(ap^.definition);
  1321. end;
  1322. if token=_COMMA then
  1323. consume(_COMMA)
  1324. else
  1325. break;
  1326. until false;
  1327. consume(_RECKKLAMMER);
  1328. consume(_OF);
  1329. hp1:=read_type('');
  1330. { if no error, set element type }
  1331. if assigned(ap) then
  1332. ap^.definition:=hp1;
  1333. end;
  1334. begin
  1335. readtypesym:=nil;
  1336. p:=nil;
  1337. case token of
  1338. _STRING,_FILE:
  1339. begin
  1340. p:=single_type(hs,false);
  1341. readtypesym:=nil;
  1342. end;
  1343. _LKLAMMER:
  1344. begin
  1345. consume(_LKLAMMER);
  1346. { allow negativ value_str }
  1347. l:=-1;
  1348. aufsym := Nil;
  1349. aufdef:=new(penumdef,init);
  1350. repeat
  1351. s:=pattern;
  1352. consume(_ID);
  1353. if token=_ASSIGNMENT then
  1354. begin
  1355. consume(_ASSIGNMENT);
  1356. v:=get_intconst;
  1357. { please leave that a note, allows type save }
  1358. { declarations in the win32 units ! }
  1359. if v<=l then
  1360. Message(parser_n_duplicate_enum);
  1361. l:=v;
  1362. end
  1363. else
  1364. inc(l);
  1365. constsymtable^.insert(new(penumsym,init(s,aufdef,l)));
  1366. if token=_COMMA then
  1367. consume(_COMMA)
  1368. else
  1369. break;
  1370. until false;
  1371. {aufdef^.max:=l;
  1372. if we allow unordered enums
  1373. this can be wrong
  1374. min and max are now set in tenumsym.init PM }
  1375. p:=aufdef;
  1376. consume(_RKLAMMER);
  1377. readtypesym:=nil;
  1378. end;
  1379. _ARRAY:
  1380. begin
  1381. array_dec;
  1382. readtypesym:=nil;
  1383. end;
  1384. _SET:
  1385. begin
  1386. consume(_SET);
  1387. consume(_OF);
  1388. hp1:=read_type('');
  1389. if assigned(hp1) then
  1390. begin
  1391. case hp1^.deftype of
  1392. { don't forget that min can be negativ PM }
  1393. enumdef :
  1394. if penumdef(hp1)^.min>=0 then
  1395. p:=new(psetdef,init(hp1,penumdef(hp1)^.max))
  1396. else
  1397. Message(sym_e_ill_type_decl_set);
  1398. orddef :
  1399. begin
  1400. case porddef(hp1)^.typ of
  1401. uchar :
  1402. p:=new(psetdef,init(hp1,255));
  1403. u8bit,u16bit,u32bit,
  1404. s8bit,s16bit,s32bit :
  1405. begin
  1406. if (porddef(hp1)^.low>=0) then
  1407. p:=new(psetdef,init(hp1,porddef(hp1)^.high))
  1408. else
  1409. Message(sym_e_ill_type_decl_set);
  1410. end;
  1411. else
  1412. Message(sym_e_ill_type_decl_set);
  1413. end;
  1414. end;
  1415. else
  1416. Message(sym_e_ill_type_decl_set);
  1417. end;
  1418. end
  1419. else
  1420. p:=generrordef;
  1421. readtypesym:=nil;
  1422. end;
  1423. _CARET:
  1424. begin
  1425. consume(_CARET);
  1426. hp1:=single_type(hs,typecanbeforward);
  1427. p:=new(ppointerdef,init(hp1));
  1428. readtypesym:=nil;
  1429. end;
  1430. _RECORD:
  1431. begin
  1432. p:=record_dec;
  1433. readtypesym:=nil;
  1434. end;
  1435. _PACKED:
  1436. begin
  1437. consume(_PACKED);
  1438. if token=_ARRAY then
  1439. array_dec
  1440. else
  1441. begin
  1442. oldaktpackrecords:=aktpackrecords;
  1443. aktpackrecords:=packrecord_1;
  1444. if token in [_CLASS,_OBJECT] then
  1445. p:=object_dec(name,nil)
  1446. else
  1447. p:=record_dec;
  1448. aktpackrecords:=oldaktpackrecords;
  1449. end;
  1450. readtypesym:=nil;
  1451. end;
  1452. _CLASS,
  1453. _OBJECT:
  1454. begin
  1455. p:=object_dec(name,nil);
  1456. readtypesym:=nil;
  1457. end;
  1458. _PROCEDURE:
  1459. begin
  1460. consume(_PROCEDURE);
  1461. p:=new(pprocvardef,init);
  1462. if token=_LKLAMMER then
  1463. parameter_dec(pprocvardef(p));
  1464. if token=_OF then
  1465. begin
  1466. consume(_OF);
  1467. consume(_OBJECT);
  1468. {$ifdef INCLUDEOK}
  1469. include(pprocvardef(p)^.procoptions,po_methodpointer);
  1470. {$else}
  1471. pprocvardef(p)^.procoptions:=pprocvardef(p)^.procoptions+[po_methodpointer];
  1472. {$endif}
  1473. end;
  1474. readtypesym:=nil;
  1475. end;
  1476. _FUNCTION:
  1477. begin
  1478. consume(_FUNCTION);
  1479. p:=new(pprocvardef,init);
  1480. if token=_LKLAMMER then
  1481. parameter_dec(pprocvardef(p));
  1482. consume(_COLON);
  1483. pprocvardef(p)^.retdef:=single_type(hs,false);
  1484. if token=_OF then
  1485. begin
  1486. consume(_OF);
  1487. consume(_OBJECT);
  1488. {$ifdef INCLUDEOK}
  1489. include(pprocvardef(p)^.procoptions,po_methodpointer);
  1490. {$else}
  1491. pprocvardef(p)^.procoptions:=pprocvardef(p)^.procoptions+[po_methodpointer];
  1492. {$endif}
  1493. end;
  1494. readtypesym:=nil;
  1495. end;
  1496. else
  1497. expr_type;
  1498. end;
  1499. if p=nil then
  1500. p:=generrordef;
  1501. read_type:=p;
  1502. end;
  1503. end.
  1504. {
  1505. $Log$
  1506. Revision 1.3 1999-10-26 12:30:45 peter
  1507. * const parameter is now checked
  1508. * better and generic check if a node can be used for assigning
  1509. * export fixes
  1510. * procvar equal works now (it never had worked at least from 0.99.8)
  1511. * defcoll changed to linkedlist with pparaitem so it can easily be
  1512. walked both directions
  1513. Revision 1.2 1999/10/22 14:37:30 peter
  1514. * error when properties are passed to var parameters
  1515. Revision 1.1 1999/10/22 10:39:35 peter
  1516. * split type reading from pdecl to ptype unit
  1517. * parameter_dec routine is now used for procedure and procvars
  1518. }