From 6a60f9d42aeee09f553765d03428809df408644a Mon Sep 17 00:00:00 2001 From: svenbarth Date: Sat, 16 Jul 2011 14:08:49 +0000 Subject: [PATCH] Integrated the changes from trunks's postfixoperators into my own and removed the local version again. git-svn-id: branches/svenbarth/generics@17997 - --- compiler/pexpr.pas | 535 +-------------------------------------------- 1 file changed, 1 insertion(+), 534 deletions(-) diff --git a/compiler/pexpr.pas b/compiler/pexpr.pas index 3479df6242..e642925fbe 100644 --- a/compiler/pexpr.pas +++ b/compiler/pexpr.pas @@ -1568,7 +1568,7 @@ implementation is_dispinterface(p1.resultdef) or is_record(p1.resultdef) then begin { default property } - protsym:=search_default_property(tobjectdef(p1.resultdef)); + protsym:=search_default_property(tabstractrecorddef(p1.resultdef)); if not(assigned(protsym)) then begin p1.destroy; @@ -2298,539 +2298,6 @@ implementation end; - {--------------------------------------------- - PostFixOperators - ---------------------------------------------} - - { returns whether or not p1 has been changed } - function postfixoperators(var p1:tnode;var again:boolean): boolean; - - { tries to avoid syntax errors after invalid qualifiers } - procedure recoverconsume_postfixops; - begin - repeat - if not try_to_consume(_CARET) then - if try_to_consume(_POINT) then - try_to_consume(_ID) - else if try_to_consume(_LECKKLAMMER) then - begin - repeat - comp_expr(true,false); - until not try_to_consume(_COMMA); - consume(_RECKKLAMMER); - end - else if try_to_consume(_LKLAMMER) then - begin - repeat - comp_expr(true,false); - until not try_to_consume(_COMMA); - consume(_RKLAMMER); - end - else - break; - until false; - end; - - - procedure handle_variantarray; - var - p4 : tnode; - newstatement : tstatementnode; - tempresultvariant, - temp : ttempcreatenode; - paras : tcallparanode; - newblock : tnode; - countindices : aint; - begin - { create statements with call initialize the arguments and - call fpc_dynarr_setlength } - newblock:=internalstatements(newstatement); - - { get temp for array of indicies, - we set the real size later } - temp:=ctempcreatenode.create(s32inttype,4,tt_persistent,false); - addstatement(newstatement,temp); - - countindices:=0; - repeat - p4:=comp_expr(true,false); - - addstatement(newstatement,cassignmentnode.create( - ctemprefnode.create_offset(temp,countindices*s32inttype.size),p4)); - inc(countindices); - until not try_to_consume(_COMMA); - - { set real size } - temp.size:=countindices*s32inttype.size; - - consume(_RECKKLAMMER); - - { we need only a write access if a := follows } - if token=_ASSIGNMENT then - begin - consume(_ASSIGNMENT); - p4:=comp_expr(true,false); - - { create call to fpc_vararray_put } - paras:=ccallparanode.create(cordconstnode.create - (countindices,s32inttype,true), - ccallparanode.create(caddrnode.create_internal - (ctemprefnode.create(temp)), - ccallparanode.create(ctypeconvnode.create_internal(p4,cvarianttype), - ccallparanode.create(ctypeconvnode.create_internal(p1,cvarianttype) - ,nil)))); - - addstatement(newstatement,ccallnode.createintern('fpc_vararray_put',paras)); - addstatement(newstatement,ctempdeletenode.create(temp)); - end - else - begin - { create temp for result } - tempresultvariant:=ctempcreatenode.create(cvarianttype,cvarianttype.size,tt_persistent,true); - addstatement(newstatement,tempresultvariant); - - { create call to fpc_vararray_get } - paras:=ccallparanode.create(cordconstnode.create - (countindices,s32inttype,true), - ccallparanode.create(caddrnode.create_internal - (ctemprefnode.create(temp)), - ccallparanode.create(p1, - ccallparanode.create( - ctemprefnode.create(tempresultvariant) - ,nil)))); - - addstatement(newstatement,ccallnode.createintern('fpc_vararray_get',paras)); - addstatement(newstatement,ctempdeletenode.create(temp)); - { the last statement should return the value as - location and type, this is done be referencing the - temp and converting it first from a persistent temp to - normal temp } - addstatement(newstatement,ctempdeletenode.create_normal_temp(tempresultvariant)); - addstatement(newstatement,ctemprefnode.create(tempresultvariant)); - end; - p1:=newblock; - end; - - var - protsym : tpropertysym; - p2,p3 : tnode; - srsym : tsym; - srsymtable : TSymtable; - structh : tabstractrecorddef; - { shouldn't be used that often, so the extra overhead is ok to save - stack space } - dispatchstring : ansistring; - nodechanged : boolean; - calltype: tdispcalltype; - label - skipreckklammercheck; - begin - result:=false; - again:=true; - while again do - begin - { we need the resultdef } - do_typecheckpass_changed(p1,nodechanged); - result:=result or nodechanged; - - if codegenerror then - begin - recoverconsume_postfixops; - exit; - end; - { handle token } - case token of - _CARET: - begin - consume(_CARET); - - { support tp/mac procvar^ if the procvar returns a - pointer type } - if ((m_tp_procvar in current_settings.modeswitches) or - (m_mac_procvar in current_settings.modeswitches)) and - (p1.resultdef.typ=procvardef) and - (tprocvardef(p1.resultdef).returndef.typ=pointerdef) then - begin - p1:=ccallnode.create_procvar(nil,p1); - typecheckpass(p1); - end; - - if (p1.resultdef.typ<>pointerdef) then - begin - { ^ as binary operator is a problem!!!! (FK) } - again:=false; - Message(parser_e_invalid_qualifier); - recoverconsume_postfixops; - p1.destroy; - p1:=cerrornode.create; - end - else - p1:=cderefnode.create(p1); - end; - - _LECKKLAMMER: - begin - if is_class_or_interface_or_object(p1.resultdef) or - is_dispinterface(p1.resultdef) or is_record(p1.resultdef) then - begin - { default property } - protsym:=search_default_property(tabstractrecorddef(p1.resultdef)); - if not(assigned(protsym)) then - begin - p1.destroy; - p1:=cerrornode.create; - again:=false; - message(parser_e_no_default_property_available); - end - else - begin - { The property symbol is referenced indirect } - protsym.IncRefCount; - handle_propertysym(protsym,protsym.owner,p1); - end; - end - else - begin - consume(_LECKKLAMMER); - repeat - { in all of the cases below, p1 is changed } - case p1.resultdef.typ of - pointerdef: - begin - { support delphi autoderef } - if (tpointerdef(p1.resultdef).pointeddef.typ=arraydef) and - (m_autoderef in current_settings.modeswitches) then - p1:=cderefnode.create(p1); - p2:=comp_expr(true,false); - { Support Pbytevar[0..9] which returns array [0..9].} - if try_to_consume(_POINTPOINT) then - p2:=crangenode.create(p2,comp_expr(true,false)); - p1:=cvecnode.create(p1,p2); - end; - variantdef: - begin - handle_variantarray; - { the RECKKLAMMER is already read } - goto skipreckklammercheck; - end; - stringdef : - begin - p2:=comp_expr(true,false); - { Support string[0..9] which returns array [0..9] of char.} - if try_to_consume(_POINTPOINT) then - p2:=crangenode.create(p2,comp_expr(true,false)); - p1:=cvecnode.create(p1,p2); - end; - arraydef: - begin - p2:=comp_expr(true,false); - { support SEG:OFS for go32v2 Mem[] } - if (target_info.system in [system_i386_go32v2,system_i386_watcom]) and - (p1.nodetype=loadn) and - assigned(tloadnode(p1).symtableentry) and - assigned(tloadnode(p1).symtableentry.owner.name) and - (tloadnode(p1).symtableentry.owner.name^='SYSTEM') and - ((tloadnode(p1).symtableentry.name='MEM') or - (tloadnode(p1).symtableentry.name='MEMW') or - (tloadnode(p1).symtableentry.name='MEML')) then - begin - if try_to_consume(_COLON) then - begin - p3:=caddnode.create(muln,cordconstnode.create($10,s32inttype,false),p2); - p2:=comp_expr(true,false); - p2:=caddnode.create(addn,p2,p3); - if try_to_consume(_POINTPOINT) then - { Support mem[$a000:$0000..$07ff] which returns array [0..$7ff] of memtype.} - p2:=crangenode.create(p2,caddnode.create(addn,comp_expr(true,false),p3.getcopy)); - p1:=cvecnode.create(p1,p2); - include(tvecnode(p1).flags,nf_memseg); - include(tvecnode(p1).flags,nf_memindex); - end - else - begin - if try_to_consume(_POINTPOINT) then - { Support mem[$80000000..$80000002] which returns array [0..2] of memtype.} - p2:=crangenode.create(p2,comp_expr(true,false)); - p1:=cvecnode.create(p1,p2); - include(tvecnode(p1).flags,nf_memindex); - end; - end - else - begin - if try_to_consume(_POINTPOINT) then - { Support arrayvar[0..9] which returns array [0..9] of arraytype.} - p2:=crangenode.create(p2,comp_expr(true,false)); - p1:=cvecnode.create(p1,p2); - end; - end; - else - begin - if p1.resultdef.typ<>undefineddef then - Message(parser_e_invalid_qualifier); - p1.destroy; - p1:=cerrornode.create; - comp_expr(true,false); - again:=false; - end; - end; - do_typecheckpass(p1); - until not try_to_consume(_COMMA); - consume(_RECKKLAMMER); - { handle_variantarray eats the RECKKLAMMER and jumps here } - skipreckklammercheck: - end; - end; - - _POINT : - begin - consume(_POINT); - if (p1.resultdef.typ=pointerdef) and - (m_autoderef in current_settings.modeswitches) and - { don't auto-deref objc.id, because then the code - below for supporting id.anyobjcmethod isn't triggered } - (p1.resultdef<>objc_idtype) then - begin - p1:=cderefnode.create(p1); - do_typecheckpass(p1); - end; - { procvar. can never mean anything so always - try to call it in case it returns a record/object/... } - maybe_call_procvar(p1,false); - - case p1.resultdef.typ of - recorddef: - begin - if token=_ID then - begin - structh:=tabstractrecorddef(p1.resultdef); - searchsym_in_record(structh,pattern,srsym,srsymtable); - if assigned(srsym) then - begin - check_hints(srsym,srsym.symoptions,srsym.deprecatedmsg); - consume(_ID); - do_member_read(structh,getaddr,srsym,p1,again,[]); - end - else - begin - Message1(sym_e_id_no_member,orgpattern); - p1.destroy; - p1:=cerrornode.create; - { try to clean up } - consume(_ID); - end; - end - else - consume(_ID); - end; - enumdef: - begin - if token=_ID then - begin - srsym:=tsym(tenumdef(p1.resultdef).symtable.Find(pattern)); - p1.destroy; - if assigned(srsym) and (srsym.typ=enumsym) then - begin - check_hints(srsym,srsym.symoptions,srsym.deprecatedmsg); - p1:=genenumnode(tenumsym(srsym)); - end - else - begin - Message1(sym_e_id_no_member,orgpattern); - p1:=cerrornode.create; - end; - end; - consume(_ID); - end; - variantdef: - begin - { dispatch call? } - { lhs := v.ident[parameters] -> property get - lhs := v.ident(parameters) -> method call - v.ident[parameters] := rhs -> property put - v.ident(parameters) := rhs -> also property put } - if token=_ID then - begin - dispatchstring:=orgpattern; - consume(_ID); - calltype:=dct_method; - if try_to_consume(_LKLAMMER) then - begin - p2:=parse_paras(false,true,_RKLAMMER); - consume(_RKLAMMER); - end - else if try_to_consume(_LECKKLAMMER) then - begin - p2:=parse_paras(false,true,_RECKKLAMMER); - consume(_RECKKLAMMER); - calltype:=dct_propget; - end - else - p2:=nil; - { property setter? } - if (token=_ASSIGNMENT) and not(afterassignment) then - begin - consume(_ASSIGNMENT); - { read the expression } - p3:=comp_expr(true,false); - { concat value parameter too } - p2:=ccallparanode.create(p3,p2); - p1:=translate_disp_call(p1,p2,dct_propput,dispatchstring,0,voidtype); - end - else - { this is only an approximation - setting useresult if not necessary is only a waste of time, no more, no less (FK) } - if afterassignment or in_args or (token<>_SEMICOLON) then - p1:=translate_disp_call(p1,p2,calltype,dispatchstring,0,cvarianttype) - else - p1:=translate_disp_call(p1,p2,calltype,dispatchstring,0,voidtype); - end - else { Error } - Consume(_ID); - end; - classrefdef: - begin - if token=_ID then - begin - structh:=tobjectdef(tclassrefdef(p1.resultdef).pointeddef); - searchsym_in_class(tobjectdef(structh),tobjectdef(structh),pattern,srsym,srsymtable,true); - if assigned(srsym) then - begin - check_hints(srsym,srsym.symoptions,srsym.deprecatedmsg); - consume(_ID); - do_member_read(structh,getaddr,srsym,p1,again,[]); - end - else - begin - Message1(sym_e_id_no_member,orgpattern); - p1.destroy; - p1:=cerrornode.create; - { try to clean up } - consume(_ID); - end; - end - else { Error } - Consume(_ID); - end; - objectdef: - begin - if token=_ID then - begin - structh:=tobjectdef(p1.resultdef); - searchsym_in_class(tobjectdef(structh),tobjectdef(structh),pattern,srsym,srsymtable,true); - if assigned(srsym) then - begin - check_hints(srsym,srsym.symoptions,srsym.deprecatedmsg); - consume(_ID); - do_member_read(structh,getaddr,srsym,p1,again,[]); - end - else - begin - Message1(sym_e_id_no_member,orgpattern); - p1.destroy; - p1:=cerrornode.create; - { try to clean up } - consume(_ID); - end; - end - else { Error } - Consume(_ID); - end; - pointerdef: - begin - if (p1.resultdef=objc_idtype) then - begin - { objc's id type can be used to call any - Objective-C method of any Objective-C class - type that's currently in scope } - if search_objc_method(pattern,srsym,srsymtable) then - begin - consume(_ID); - do_proc_call(srsym,srsymtable,nil, - (getaddr and not(token in [_CARET,_POINT])), - again,p1,[cnf_objc_id_call]); - { we need to know which procedure is called } - do_typecheckpass(p1); - end - else - begin - consume(_ID); - Message(parser_e_methode_id_expected); - end; - end - else - begin - Message(parser_e_invalid_qualifier); - if tpointerdef(p1.resultdef).pointeddef.typ in [recorddef,objectdef,classrefdef] then - Message(parser_h_maybe_deref_caret_missing); - end - end; - else - begin - if p1.resultdef.typ<>undefineddef then - Message(parser_e_invalid_qualifier); - p1.destroy; - p1:=cerrornode.create; - { Error } - consume(_ID); - end; - end; - end; - - else - begin - { is this a procedure variable ? } - if assigned(p1.resultdef) and - (p1.resultdef.typ=procvardef) then - begin - { Typenode for typecasting or expecting a procvar } - if (p1.nodetype=typen) or - ( - assigned(getprocvardef) and - equal_defs(p1.resultdef,getprocvardef) - ) then - begin - if try_to_consume(_LKLAMMER) then - begin - p1:=comp_expr(true,false); - consume(_RKLAMMER); - p1:=ctypeconvnode.create_explicit(p1,p1.resultdef); - end - else - again:=false - end - else - begin - if try_to_consume(_LKLAMMER) then - begin - p2:=parse_paras(false,false,_RKLAMMER); - consume(_RKLAMMER); - p1:=ccallnode.create_procvar(p2,p1); - { proc():= is never possible } - if token=_ASSIGNMENT then - begin - Message(parser_e_illegal_expression); - p1.free; - p1:=cerrornode.create; - again:=false; - end; - end - else - again:=false; - end; - end - else - again:=false; - end; - end; - - { we only try again if p1 was changed } - if again or - (p1.nodetype=errorn) then - result:=true; - end; { while again } - end; - - {--------------------------------------------- Factor (Main) ---------------------------------------------}