123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218 |
- {
- Copyright (c) 2011 by Jonas Maebe
- This unit implements some JVM parser helper routines.
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- ****************************************************************************
- }
- {$i fpcdefs.inc}
- unit pjvm;
- interface
- uses
- symdef;
- { the JVM specs require that you add a default parameterless
- constructor in case the programmer hasn't specified any }
- procedure maybe_add_public_default_java_constructor(obj: tabstractrecorddef);
- { records are emulated via Java classes. They require a default constructor
- to initialise temps, a deep copy helper for assignments, and clone()
- to initialse dynamic arrays }
- procedure add_java_default_record_methods_intf(def: trecorddef);
- implementation
- uses
- globtype,
- cutils,cclasses,
- verbose,systems,
- fmodule,
- parabase,
- pdecsub,
- symbase,symtype,symtable,symconst,symsym,symcreat,defcmp,jvmdef,
- defutil,paramgr;
- { the JVM specs require that you add a default parameterless
- constructor in case the programmer hasn't specified any }
- procedure maybe_add_public_default_java_constructor(obj: tabstractrecorddef);
- var
- sym: tsym;
- ps: tprocsym;
- pd: tprocdef;
- topowner: tdefentry;
- i: longint;
- sstate: symcreat.tscannerstate;
- needclassconstructor: boolean;
- begin
- { if there is at least one constructor for a class, do nothing (for
- records, we'll always also need a parameterless constructor) }
- if not is_javaclass(obj) or
- not (oo_has_constructor in obj.objectoptions) then
- begin
- { check whether the parent has a parameterless constructor that we can
- call (in case of a class; all records will derive from
- java.lang.Object or a shim on top of that with a parameterless
- constructor) }
- if is_javaclass(obj) then
- begin
- pd:=nil;
- sym:=tsym(tobjectdef(obj).childof.symtable.find('CREATE'));
- if assigned(sym) and
- (sym.typ=procsym) then
- pd:=tprocsym(sym).find_bytype_parameterless(potype_constructor);
- if not assigned(pd) then
- begin
- Message(sym_e_no_matching_inherited_parameterless_constructor);
- exit
- end;
- end;
- { we call all constructors CREATE, because they don't have a name in
- Java and otherwise we can't determine whether multiple overloads
- are created with the same parameters }
- sym:=tsym(obj.symtable.find('CREATE'));
- if assigned(sym) then
- begin
- { does another, non-procsym, symbol already exist with that name? }
- if (sym.typ<>procsym) then
- begin
- Message1(sym_e_duplicate_id_create_java_constructor,sym.realname);
- exit;
- end;
- ps:=tprocsym(sym);
- { is there already a parameterless function/procedure create? }
- pd:=ps.find_bytype_parameterless(potype_function);
- if not assigned(pd) then
- pd:=ps.find_bytype_parameterless(potype_procedure);
- if assigned(pd) then
- begin
- Message1(sym_e_duplicate_id_create_java_constructor,pd.fullprocname(false));
- exit;
- end;
- end;
- if not assigned(sym) then
- begin
- ps:=tprocsym.create('Create');
- obj.symtable.insert(ps);
- end;
- { determine symtable level }
- topowner:=obj;
- while not(topowner.owner.symtabletype in [staticsymtable,globalsymtable,localsymtable]) do
- topowner:=topowner.owner.defowner;
- { create procdef }
- pd:=tprocdef.create(topowner.owner.symtablelevel+1);
- { method of this objectdef }
- pd.struct:=obj;
- { associated procsym }
- pd.procsym:=ps;
- { constructor }
- pd.proctypeoption:=potype_constructor;
- { needs to be exported }
- include(pd.procoptions,po_global);
- { for Delphi mode }
- include(pd.procoptions,po_overload);
- { generate anonymous inherited call in the implementation }
- pd.synthetickind:=tsk_anon_inherited;
- { public }
- pd.visibility:=vis_public;
- { result type }
- pd.returndef:=obj;
- { calling convention, self, ... }
- handle_calling_convention(pd);
- { register forward declaration with procsym }
- proc_add_definition(pd);
- end;
- { also add class constructor if class fields that need wrapping, and
- if none was defined }
- if obj.find_procdef_bytype(potype_class_constructor)=nil then
- begin
- needclassconstructor:=false;
- for i:=0 to obj.symtable.symlist.count-1 do
- begin
- if (tsym(obj.symtable.symlist[i]).typ=staticvarsym) and
- jvmimplicitpointertype(tstaticvarsym(obj.symtable.symlist[i]).vardef) then
- begin
- needclassconstructor:=true;
- break;
- end;
- end;
- if needclassconstructor then
- begin
- replace_scanner('custom_class_constructor',sstate);
- if str_parse_method_dec('constructor fpc_jvm_class_constructor;',potype_class_constructor,true,obj,pd) then
- pd.synthetickind:=tsk_empty
- else
- internalerror(2011040501);
- restore_scanner(sstate);
- end;
- end;
- end;
- procedure add_java_default_record_methods_intf(def: trecorddef);
- var
- sstate: tscannerstate;
- pd: tprocdef;
- begin
- maybe_add_public_default_java_constructor(def);
- replace_scanner('record_jvm_helpers',sstate);
- { no override, because not supported in records; the parser will still
- accept "inherited" though }
- if str_parse_method_dec('function clone: JLObject;',potype_function,false,def,pd) then
- pd.synthetickind:=tsk_jvm_clone
- else
- internalerror(2011032806);
- { can't use def.typesym, not yet set at this point }
- if def.symtable.realname^='' then
- internalerror(2011032803);
- if str_parse_method_dec('procedure fpcDeepCopy(out result:'+def.symtable.realname^+');',potype_procedure,false,def,pd) then
- pd.synthetickind:=tsk_record_deepcopy
- else
- internalerror(2011032807);
- restore_scanner(sstate);
- end;
- {******************************************************************
- jvm type validity checking
- *******************************************************************}
- function jvmencodetype(def: tdef): string;
- var
- errordef: tdef;
- begin
- if not jvmtryencodetype(def,result,errordef) then
- internalerror(2011012305);
- end;
- function jvmchecktype(def: tdef; out founderror: tdef): boolean;
- var
- encodedtype: string;
- begin
- { don't duplicate the code like in objcdef, since the resulting strings
- are much shorter here so it's not worth it }
- result:=jvmtryencodetype(def,encodedtype,founderror);
- end;
- end.
|