ptype.pas 62 KB

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