pjvm.pas 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. {
  2. Copyright (c) 2011 by Jonas Maebe
  3. This unit implements some JVM parser helper routines.
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************
  16. }
  17. {$i fpcdefs.inc}
  18. unit pjvm;
  19. interface
  20. uses
  21. symdef;
  22. { the JVM specs require that you add a default parameterless
  23. constructor in case the programmer hasn't specified any }
  24. procedure maybe_add_public_default_java_constructor(obj: tabstractrecorddef);
  25. { records are emulated via Java classes. They require a default constructor
  26. to initialise temps, a deep copy helper for assignments, and clone()
  27. to initialse dynamic arrays }
  28. procedure add_java_default_record_methods_intf(def: trecorddef);
  29. implementation
  30. uses
  31. globtype,
  32. cutils,cclasses,
  33. verbose,systems,
  34. fmodule,
  35. parabase,
  36. pdecsub,
  37. symbase,symtype,symtable,symconst,symsym,symcreat,defcmp,jvmdef,
  38. defutil,paramgr;
  39. { the JVM specs require that you add a default parameterless
  40. constructor in case the programmer hasn't specified any }
  41. procedure maybe_add_public_default_java_constructor(obj: tabstractrecorddef);
  42. function find_parameterless_def(psym: tprocsym): tprocdef;
  43. var
  44. paras: tparalist;
  45. begin
  46. paras:=tparalist.create;
  47. result:=psym.find_procdef_bypara_no_rettype(paras,[cpo_ignorehidden,cpo_openequalisexact]);
  48. paras.free;
  49. end;
  50. var
  51. sym: tsym;
  52. ps: tprocsym;
  53. pd: tprocdef;
  54. topowner: tdefentry;
  55. begin
  56. { if there is at least one constructor for a class, do nothing (for
  57. records, we'll always also need a parameterless constructor) }
  58. if is_javaclass(obj) and
  59. (oo_has_constructor in obj.objectoptions) then
  60. exit;
  61. { check whether the parent has a parameterless constructor that we can
  62. call (in case of a class; all records will derive from
  63. java.lang.Object or a shim on top of that with a parameterless
  64. constructor) }
  65. if is_javaclass(obj) then
  66. begin
  67. pd:=nil;
  68. sym:=tsym(tobjectdef(obj).childof.symtable.find('CREATE'));
  69. if assigned(sym) and
  70. (sym.typ=procsym) then
  71. begin
  72. pd:=find_parameterless_def(tprocsym(sym));
  73. { make sure it's a constructor }
  74. if assigned(pd) and
  75. (pd.proctypeoption<>potype_constructor) then
  76. pd:=nil;
  77. end;
  78. if not assigned(pd) then
  79. begin
  80. Message(sym_e_no_matching_inherited_parameterless_constructor);
  81. exit
  82. end;
  83. end;
  84. { we call all constructors CREATE, because they don't have a name in
  85. Java and otherwise we can't determine whether multiple overloads
  86. are created with the same parameters }
  87. sym:=tsym(obj.symtable.find('CREATE'));
  88. if assigned(sym) then
  89. begin
  90. { does another, non-procsym, symbol already exist with that name? }
  91. if (sym.typ<>procsym) then
  92. begin
  93. Message1(sym_e_duplicate_id_create_java_constructor,sym.realname);
  94. exit;
  95. end;
  96. ps:=tprocsym(sym);
  97. { is there already a parameterless function/procedure create? }
  98. pd:=find_parameterless_def(ps);
  99. if assigned(pd) then
  100. begin
  101. Message1(sym_e_duplicate_id_create_java_constructor,pd.fullprocname(false));
  102. exit;
  103. end;
  104. end;
  105. if not assigned(sym) then
  106. begin
  107. ps:=tprocsym.create('Create');
  108. obj.symtable.insert(ps);
  109. end;
  110. { determine symtable level }
  111. topowner:=obj;
  112. while not(topowner.owner.symtabletype in [staticsymtable,globalsymtable,localsymtable]) do
  113. topowner:=topowner.owner.defowner;
  114. { create procdef }
  115. pd:=tprocdef.create(topowner.owner.symtablelevel+1);
  116. { method of this objectdef }
  117. pd.struct:=obj;
  118. { associated procsym }
  119. pd.procsym:=ps;
  120. { constructor }
  121. pd.proctypeoption:=potype_constructor;
  122. { needs to be exported }
  123. include(pd.procoptions,po_global);
  124. { for Delphi mode }
  125. include(pd.procoptions,po_overload);
  126. { generate anonymous inherited call in the implementation }
  127. pd.synthetickind:=tsk_anon_inherited;
  128. { public }
  129. pd.visibility:=vis_public;
  130. { result type }
  131. pd.returndef:=obj;
  132. { calling convention, self, ... }
  133. handle_calling_convention(pd);
  134. { register forward declaration with procsym }
  135. proc_add_definition(pd);
  136. end;
  137. procedure add_java_default_record_methods_intf(def: trecorddef);
  138. var
  139. sstate: tscannerstate;
  140. pd: tprocdef;
  141. begin
  142. maybe_add_public_default_java_constructor(def);
  143. replace_scanner('record_jvm_helpers',sstate);
  144. { no override, because not supported in records; the parser will still
  145. accept "inherited" though }
  146. if str_parse_method_dec('function clone: JLObject;',false,def,pd) then
  147. pd.synthetickind:=tsk_jvm_clone
  148. else
  149. internalerror(2011032806);
  150. { can't use def.typesym, not yet set at this point }
  151. if def.symtable.realname^='' then
  152. internalerror(2011032803);
  153. if str_parse_method_dec('procedure fpcDeepCopy(out result:'+def.symtable.realname^+');',false,def,pd) then
  154. pd.synthetickind:=tsk_record_deepcopy
  155. else
  156. internalerror(2011032807);
  157. restore_scanner(sstate);
  158. end;
  159. {******************************************************************
  160. jvm type validity checking
  161. *******************************************************************}
  162. function jvmencodetype(def: tdef): string;
  163. var
  164. errordef: tdef;
  165. begin
  166. if not jvmtryencodetype(def,result,errordef) then
  167. internalerror(2011012305);
  168. end;
  169. function jvmchecktype(def: tdef; out founderror: tdef): boolean;
  170. var
  171. encodedtype: string;
  172. begin
  173. { don't duplicate the code like in objcdef, since the resulting strings
  174. are much shorter here so it's not worth it }
  175. result:=jvmtryencodetype(def,encodedtype,founderror);
  176. end;
  177. end.