|
@@ -1293,14 +1293,17 @@ implementation
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
|
|
- function handle_factor_typenode(hdef:tdef;getaddr:boolean;var again:boolean;sym:tsym):tnode;
|
|
|
|
|
|
+ function handle_factor_typenode(hdef:tdef;getaddr:boolean;var again:boolean;sym:tsym;typeonly:boolean):tnode;
|
|
var
|
|
var
|
|
srsym : tsym;
|
|
srsym : tsym;
|
|
srsymtable : tsymtable;
|
|
srsymtable : tsymtable;
|
|
begin
|
|
begin
|
|
if sym=nil then
|
|
if sym=nil then
|
|
sym:=hdef.typesym;
|
|
sym:=hdef.typesym;
|
|
- if try_to_consume(_LKLAMMER) then
|
|
|
|
|
|
+ { allow Ordinal(Value) for type declarations since it
|
|
|
|
+ can be an enummeration declaration or a set lke:
|
|
|
|
+ (OrdinalType(const1)..OrdinalType(const2) }
|
|
|
|
+ if (not typeonly or is_ordinal(hdef))and try_to_consume(_LKLAMMER) then
|
|
begin
|
|
begin
|
|
result:=comp_expr(true,false);
|
|
result:=comp_expr(true,false);
|
|
consume(_RKLAMMER);
|
|
consume(_RKLAMMER);
|
|
@@ -1527,7 +1530,7 @@ implementation
|
|
newstatement,assstatement:tstatementnode;
|
|
newstatement,assstatement:tstatementnode;
|
|
arrnode:ttempcreatenode;
|
|
arrnode:ttempcreatenode;
|
|
temp2:ttempcreatenode;
|
|
temp2:ttempcreatenode;
|
|
- assnode,paranode:tnode;
|
|
|
|
|
|
+ assnode:tnode;
|
|
paracount:integer;
|
|
paracount:integer;
|
|
begin
|
|
begin
|
|
result:=internalstatements(newstatement);
|
|
result:=internalstatements(newstatement);
|
|
@@ -2251,110 +2254,7 @@ implementation
|
|
if (hdef=cvarianttype) and
|
|
if (hdef=cvarianttype) and
|
|
not(cs_compilesystem in current_settings.moduleswitches) then
|
|
not(cs_compilesystem in current_settings.moduleswitches) then
|
|
current_module.flags:=current_module.flags or uf_uses_variants;
|
|
current_module.flags:=current_module.flags or uf_uses_variants;
|
|
- p1:=handle_factor_typenode(hdef,getaddr,again,srsym);
|
|
|
|
- (*{ if we get a generic then check that it is not an inline specialization }
|
|
|
|
- if (df_generic in hdef.defoptions) and
|
|
|
|
- (token=_LT) and
|
|
|
|
- (m_delphi in current_settings.modeswitches) then
|
|
|
|
- generate_specialization(hdef,false,'');
|
|
|
|
- { allow Ordinal(Value) for type declarations since it
|
|
|
|
- can be an enummeration declaration or a set lke:
|
|
|
|
- (OrdinalType(const1)..OrdinalType(const2) }
|
|
|
|
- if (not typeonly or is_ordinal(hdef))and try_to_consume(_LKLAMMER) then
|
|
|
|
- begin
|
|
|
|
- p1:=comp_expr(true,false);
|
|
|
|
- consume(_RKLAMMER);
|
|
|
|
- { type casts to class helpers aren't allowed }
|
|
|
|
- if is_objectpascal_helper(hdef) then
|
|
|
|
- Message(parser_e_no_category_as_types)
|
|
|
|
- { recovery by not creating a conversion node }
|
|
|
|
- else
|
|
|
|
- p1:=ctypeconvnode.create_explicit(p1,hdef);
|
|
|
|
- end
|
|
|
|
- else { not LKLAMMER }
|
|
|
|
- if (token=_POINT) and
|
|
|
|
- (is_object(hdef) or is_record(hdef)) then
|
|
|
|
- begin
|
|
|
|
- consume(_POINT);
|
|
|
|
- { handles calling methods declared in parent objects
|
|
|
|
- using "parentobject.methodname()" }
|
|
|
|
- if assigned(current_structdef) and
|
|
|
|
- not(getaddr) and
|
|
|
|
- current_structdef.is_related(hdef) then
|
|
|
|
- begin
|
|
|
|
- p1:=ctypenode.create(hdef);
|
|
|
|
- { search also in inherited methods }
|
|
|
|
- searchsym_in_class(tobjectdef(hdef),tobjectdef(current_structdef),pattern,srsym,srsymtable,true);
|
|
|
|
- if assigned(srsym) then
|
|
|
|
- check_hints(srsym,srsym.symoptions,srsym.deprecatedmsg);
|
|
|
|
- consume(_ID);
|
|
|
|
- do_member_read(tabstractrecorddef(hdef),false,srsym,p1,again,[]);
|
|
|
|
- end
|
|
|
|
- else
|
|
|
|
- begin
|
|
|
|
- { handles:
|
|
|
|
- * @TObject.Load
|
|
|
|
- * static methods and variables }
|
|
|
|
- p1:=ctypenode.create(hdef);
|
|
|
|
- { TP allows also @TMenu.Load if Load is only }
|
|
|
|
- { defined in an anchestor class }
|
|
|
|
- srsym:=search_struct_member(tabstractrecorddef(hdef),pattern);
|
|
|
|
- if assigned(srsym) then
|
|
|
|
- begin
|
|
|
|
- check_hints(srsym,srsym.symoptions,srsym.deprecatedmsg);
|
|
|
|
- consume(_ID);
|
|
|
|
- do_member_read(tabstractrecorddef(hdef),getaddr,srsym,p1,again,[]);
|
|
|
|
- end
|
|
|
|
- else
|
|
|
|
- Message1(sym_e_id_no_member,orgpattern);
|
|
|
|
- end;
|
|
|
|
- end
|
|
|
|
- else
|
|
|
|
- begin
|
|
|
|
- { Normally here would be the check against the usage
|
|
|
|
- of "TClassHelper.Something", but as that might be
|
|
|
|
- used inside of system symbols like sizeof and
|
|
|
|
- typeinfo this check is put into ttypenode.pass_1
|
|
|
|
- (for "TClassHelper" alone) and tcallnode.pass_1
|
|
|
|
- (for "TClassHelper.Something") }
|
|
|
|
- { class reference ? }
|
|
|
|
- if is_class(hdef) or
|
|
|
|
- is_objcclass(hdef) then
|
|
|
|
- begin
|
|
|
|
- if getaddr and (token=_POINT) then
|
|
|
|
- begin
|
|
|
|
- consume(_POINT);
|
|
|
|
- { allows @Object.Method }
|
|
|
|
- { also allows static methods and variables }
|
|
|
|
- p1:=ctypenode.create(hdef);
|
|
|
|
- { TP allows also @TMenu.Load if Load is only }
|
|
|
|
- { defined in an anchestor class }
|
|
|
|
- srsym:=search_struct_member(tobjectdef(hdef),pattern);
|
|
|
|
- if assigned(srsym) then
|
|
|
|
- begin
|
|
|
|
- check_hints(srsym,srsym.symoptions,srsym.deprecatedmsg);
|
|
|
|
- consume(_ID);
|
|
|
|
- do_member_read(tabstractrecorddef(hdef),getaddr,srsym,p1,again,[]);
|
|
|
|
- end
|
|
|
|
- else
|
|
|
|
- begin
|
|
|
|
- Message1(sym_e_id_no_member,orgpattern);
|
|
|
|
- consume(_ID);
|
|
|
|
- end;
|
|
|
|
- end
|
|
|
|
- else
|
|
|
|
- begin
|
|
|
|
- p1:=ctypenode.create(hdef);
|
|
|
|
- { For a type block we simply return only
|
|
|
|
- the type. For all other blocks we return
|
|
|
|
- a loadvmt node }
|
|
|
|
- if not(block_type in [bt_type,bt_const_type,bt_var_type]) then
|
|
|
|
- p1:=cloadvmtaddrnode.create(p1);
|
|
|
|
- end;
|
|
|
|
- end
|
|
|
|
- else
|
|
|
|
- p1:=ctypenode.create(hdef);
|
|
|
|
- end;*)
|
|
|
|
|
|
+ p1:=handle_factor_typenode(hdef,getaddr,again,srsym,typeonly);
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
|
|
@@ -2522,637 +2422,6 @@ implementation
|
|
end;
|
|
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;
|
|
|
|
-
|
|
|
|
- function parse_array_constructor(arrdef:tarraydef): tnode;
|
|
|
|
- var
|
|
|
|
- newstatement,assstatement:tstatementnode;
|
|
|
|
- arrnode:ttempcreatenode;
|
|
|
|
- temp2:ttempcreatenode;
|
|
|
|
- assnode:tnode;
|
|
|
|
- paracount:integer;
|
|
|
|
- begin
|
|
|
|
- result:=internalstatements(newstatement);
|
|
|
|
- { create temp for result }
|
|
|
|
- arrnode:=ctempcreatenode.create(arrdef,arrdef.size,tt_persistent,true);
|
|
|
|
- addstatement(newstatement,arrnode);
|
|
|
|
-
|
|
|
|
- paracount:=0;
|
|
|
|
- { check arguments and create an assignment calls }
|
|
|
|
- if try_to_consume(_LKLAMMER) then
|
|
|
|
- begin
|
|
|
|
- assnode:=internalstatements(assstatement);
|
|
|
|
- repeat
|
|
|
|
- { arr[i] := param_i }
|
|
|
|
- addstatement(assstatement,
|
|
|
|
- cassignmentnode.create(
|
|
|
|
- cvecnode.create(
|
|
|
|
- ctemprefnode.create(arrnode),
|
|
|
|
- cordconstnode.create(paracount,arrdef.rangedef,false)),
|
|
|
|
- comp_expr(true,false)));
|
|
|
|
- inc(paracount);
|
|
|
|
- until not try_to_consume(_COMMA);
|
|
|
|
- consume(_RKLAMMER);
|
|
|
|
- end
|
|
|
|
- else
|
|
|
|
- assnode:=nil;
|
|
|
|
-
|
|
|
|
- { get temp for array of lengths }
|
|
|
|
- temp2:=ctempcreatenode.create(sinttype,sinttype.size,tt_persistent,false);
|
|
|
|
- addstatement(newstatement,temp2);
|
|
|
|
-
|
|
|
|
- { one dimensional }
|
|
|
|
- addstatement(newstatement,cassignmentnode.create(
|
|
|
|
- ctemprefnode.create_offset(temp2,0),
|
|
|
|
- cordconstnode.create
|
|
|
|
- (paracount,s32inttype,true)));
|
|
|
|
- { create call to fpc_dynarr_setlength }
|
|
|
|
- addstatement(newstatement,ccallnode.createintern('fpc_dynarray_setlength',
|
|
|
|
- ccallparanode.create(caddrnode.create_internal
|
|
|
|
- (ctemprefnode.create(temp2)),
|
|
|
|
- ccallparanode.create(cordconstnode.create
|
|
|
|
- (1,s32inttype,true),
|
|
|
|
- ccallparanode.create(caddrnode.create_internal
|
|
|
|
- (crttinode.create(tstoreddef(arrdef),initrtti,rdt_normal)),
|
|
|
|
- ccallparanode.create(
|
|
|
|
- ctypeconvnode.create_internal(
|
|
|
|
- ctemprefnode.create(arrnode),voidpointertype),
|
|
|
|
- nil))))
|
|
|
|
-
|
|
|
|
- ));
|
|
|
|
- { add assignment statememnts }
|
|
|
|
- addstatement(newstatement,ctempdeletenode.create(temp2));
|
|
|
|
- if assigned(assnode) then
|
|
|
|
- addstatement(newstatement,assnode);
|
|
|
|
- { 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(arrnode));
|
|
|
|
- addstatement(newstatement,ctemprefnode.create(arrnode));
|
|
|
|
- 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.<something> 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;
|
|
|
|
- arraydef:
|
|
|
|
- begin
|
|
|
|
- if is_dynamic_array(p1.resultdef) then
|
|
|
|
- begin
|
|
|
|
- if token=_ID then
|
|
|
|
- begin
|
|
|
|
- if pattern='CREATE' then
|
|
|
|
- begin
|
|
|
|
- consume(_ID);
|
|
|
|
- p2:=parse_array_constructor(tarraydef(p1.resultdef));
|
|
|
|
- p1.destroy;
|
|
|
|
- p1:=p2;
|
|
|
|
- end
|
|
|
|
- else
|
|
|
|
- begin
|
|
|
|
- Message2(scan_f_syn_expected,'CREATE',pattern);
|
|
|
|
- p1.destroy;
|
|
|
|
- p1:=cerrornode.create;
|
|
|
|
- consume(_ID);
|
|
|
|
- end;
|
|
|
|
- end;
|
|
|
|
- end
|
|
|
|
- else
|
|
|
|
- begin
|
|
|
|
- Message(parser_e_invalid_qualifier);
|
|
|
|
- p1.destroy;
|
|
|
|
- p1:=cerrornode.create;
|
|
|
|
- consume(_ID);
|
|
|
|
- end;
|
|
|
|
- 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)
|
|
Factor (Main)
|
|
---------------------------------------------}
|
|
---------------------------------------------}
|
|
@@ -3694,7 +2963,7 @@ implementation
|
|
internalerror(2011053001);
|
|
internalerror(2011053001);
|
|
again:=false;
|
|
again:=false;
|
|
{ handle potential typecasts, etc }
|
|
{ handle potential typecasts, etc }
|
|
- p1:=handle_factor_typenode(def,false,again,nil);
|
|
|
|
|
|
+ p1:=handle_factor_typenode(def,false,again,nil,false);
|
|
{ parse postfix operators }
|
|
{ parse postfix operators }
|
|
if postfixoperators(p1,again,false) then
|
|
if postfixoperators(p1,again,false) then
|
|
if assigned(p1) and (p1.nodetype=typen) then
|
|
if assigned(p1) and (p1.nodetype=typen) then
|
|
@@ -3847,7 +3116,7 @@ implementation
|
|
is always a classrefdef }
|
|
is always a classrefdef }
|
|
again:=false;
|
|
again:=false;
|
|
{ handle potential typecasts, etc }
|
|
{ handle potential typecasts, etc }
|
|
- p1:=handle_factor_typenode(gendef,false,again,nil);
|
|
|
|
|
|
+ p1:=handle_factor_typenode(gendef,false,again,nil,false);
|
|
{ parse postfix operators }
|
|
{ parse postfix operators }
|
|
if postfixoperators(p1,again,false) then
|
|
if postfixoperators(p1,again,false) then
|
|
if assigned(p1) then
|
|
if assigned(p1) then
|
|
@@ -3936,7 +3205,7 @@ implementation
|
|
|
|
|
|
again:=false;
|
|
again:=false;
|
|
{ handle potential typecasts, etc }
|
|
{ handle potential typecasts, etc }
|
|
- p2:=handle_factor_typenode(gendef,false,again,nil);
|
|
|
|
|
|
+ p2:=handle_factor_typenode(gendef,false,again,nil,false);
|
|
{ parse postfix operators }
|
|
{ parse postfix operators }
|
|
if postfixoperators(p2,again,false) then
|
|
if postfixoperators(p2,again,false) then
|
|
if assigned(p2) then
|
|
if assigned(p2) then
|