compiler: further improve preprocessor evaluator:

* support TRUE,FALSE for all modes
  * refactor texprvalue.evaluate to support arithmetic expressions and implement them here
  * simplify read_expr and read_factor code

git-svn-id: trunk@25463 -
This commit is contained in:
paul 2013-09-12 06:01:49 +00:00
parent cac09f9df1
commit 7ecaaf0ef8

View File

@ -814,6 +814,7 @@ type
def: tdef; def: tdef;
constructor create_const(c:tconstsym); constructor create_const(c:tconstsym);
constructor create_error; constructor create_error;
constructor create_ord(v: Tconstexprint);
constructor create_int(v: int64); constructor create_int(v: int64);
constructor create_uint(v: qword); constructor create_uint(v: qword);
constructor create_bool(b: boolean); constructor create_bool(b: boolean);
@ -822,7 +823,7 @@ type
constructor create_real(r: bestreal); constructor create_real(r: bestreal);
class function try_parse_number(s:string):texprvalue; static; class function try_parse_number(s:string):texprvalue; static;
class function try_parse_real(s:string):texprvalue; static; class function try_parse_real(s:string):texprvalue; static;
function evaluate(v:texprvalue;op:ttoken): boolean; function evaluate(v:texprvalue;op:ttoken):texprvalue;
procedure error(expecteddef, place: string); procedure error(expecteddef, place: string);
function asBool: Boolean; function asBool: Boolean;
function asInt: Integer; function asInt: Integer;
@ -894,6 +895,17 @@ type
def:=generrordef; def:=generrordef;
end; end;
constructor texprvalue.create_ord(v: Tconstexprint);
begin
fillchar(value,sizeof(value),#0);
consttyp:=constord;
value.valueord:=v;
if v.signed then
def:=sintdef
else
def:=uintdef;
end;
constructor texprvalue.create_int(v: int64); constructor texprvalue.create_int(v: int64);
begin begin
fillchar(value,sizeof(value),#0); fillchar(value,sizeof(value),#0);
@ -984,7 +996,7 @@ type
result:=nil; result:=nil;
end; end;
function texprvalue.evaluate(v:texprvalue;op:ttoken): boolean; function texprvalue.evaluate(v:texprvalue;op:ttoken):texprvalue;
function check_compatbile: boolean; function check_compatbile: boolean;
begin begin
@ -994,103 +1006,138 @@ type
) or ) or
(is_string(v.def) and is_string(def)); (is_string(v.def) and is_string(def));
if not result then if not result then
incompatibletypes(def,v.def); Message2(type_e_incompatible_types,def.typename,v.def.typename);
end; end;
var var
lv,rv: tconstexprint; lv,rv: tconstexprint;
lvd,rvd: bestreal; lvd,rvd: bestreal;
lvs,rvs: string; lvs,rvs: string;
begin begin
if op = _IN then case op of
_IN:
begin begin
if not is_set(v.def) then if not is_set(v.def) then
begin begin
v.error('set', 'IN'); v.error('Set', 'IN');
result:=false; result:=texprvalue.create_error;
end end
else else
if not is_ordinal(def) then if not is_ordinal(def) then
begin begin
error('ordinal', 'IN'); error('Ordinal', 'IN');
result:=false; result:=texprvalue.create_error;
end end
else else
if value.valueord.signed then if value.valueord.signed then
result:=value.valueord.svalue in pnormalset(v.value.valueptr)^ result:=texprvalue.create_bool(value.valueord.svalue in pnormalset(v.value.valueptr)^)
else else
result:=value.valueord.uvalue in pnormalset(v.value.valueptr)^; result:=texprvalue.create_bool(value.valueord.uvalue in pnormalset(v.value.valueptr)^);
end end;
else _OP_NOT:
if check_compatbile then
begin begin
if (is_ordinal(def) and is_ordinal(v.def)) then if is_boolean(def) then
begin result:=texprvalue.create_bool(not asBool)
lv:=value.valueord;
rv:=v.value.valueord;
case op of
_EQ:
result:=lv=rv;
_NE:
result:=lv<>rv;
_LT:
result:=lv<rv;
_GT:
result:=lv>rv;
_GTE:
result:=lv>=rv;
_LTE:
result:=lv<=rv;
end;
end
else else
if (is_fpu(def) or is_ordinal(def)) and
(is_fpu(v.def) or is_ordinal(v.def)) then
begin begin
if is_fpu(def) then error('Boolean', 'NOT');
lvd:=pbestreal(value.valueptr)^ result:=texprvalue.create_error;
else
lvd:=value.valueord;
if is_fpu(v.def) then
rvd:=pbestreal(v.value.valueptr)^
else
rvd:=v.value.valueord;
case op of
_EQ:
result:=lvd=rvd;
_NE:
result:=lvd<>rvd;
_LT:
result:=lvd<rvd;
_GT:
result:=lvd>rvd;
_GTE:
result:=lvd>=rvd;
_LTE:
result:=lvd<=rvd;
end;
end
else
begin
lvs:=asStr;
rvs:=v.asStr;
case op of
_EQ:
result:=lvs=rvs;
_NE:
result:=lvs<>rvs;
_LT:
result:=lvs<rvs;
_GT:
result:=lvs>rvs;
_GTE:
result:=lvs>=rvs;
_LTE:
result:=lvs<=rvs;
end; end;
end; end;
end _EQ,_NE,_LT,_GT,_GTE,_LTE,_PLUS,_MINUS,_STAR,_SLASH:
else if check_compatbile then
result:=false; begin
if (is_ordinal(def) and is_ordinal(v.def)) then
begin
lv:=value.valueord;
rv:=v.value.valueord;
case op of
_EQ:
result:=texprvalue.create_bool(lv=rv);
_NE:
result:=texprvalue.create_bool(lv<>rv);
_LT:
result:=texprvalue.create_bool(lv<rv);
_GT:
result:=texprvalue.create_bool(lv>rv);
_GTE:
result:=texprvalue.create_bool(lv>=rv);
_LTE:
result:=texprvalue.create_bool(lv<=rv);
_PLUS:
result:=texprvalue.create_ord(lv+rv);
_MINUS:
result:=texprvalue.create_ord(lv-rv);
_STAR:
result:=texprvalue.create_ord(lv*rv);
_SLASH:
result:=texprvalue.create_real(lv/rv);
end;
end
else
if (is_fpu(def) or is_ordinal(def)) and
(is_fpu(v.def) or is_ordinal(v.def)) then
begin
if is_fpu(def) then
lvd:=pbestreal(value.valueptr)^
else
lvd:=value.valueord;
if is_fpu(v.def) then
rvd:=pbestreal(v.value.valueptr)^
else
rvd:=v.value.valueord;
case op of
_EQ:
result:=texprvalue.create_bool(lvd=rvd);
_NE:
result:=texprvalue.create_bool(lvd<>rvd);
_LT:
result:=texprvalue.create_bool(lvd<rvd);
_GT:
result:=texprvalue.create_bool(lvd>rvd);
_GTE:
result:=texprvalue.create_bool(lvd>=rvd);
_LTE:
result:=texprvalue.create_bool(lvd<=rvd);
_PLUS:
result:=texprvalue.create_real(lvd+rvd);
_MINUS:
result:=texprvalue.create_real(lvd-rvd);
_STAR:
result:=texprvalue.create_real(lvd*rvd);
_SLASH:
result:=texprvalue.create_real(lvd/rvd);
end;
end
else
begin
lvs:=asStr;
rvs:=v.asStr;
case op of
_EQ:
result:=texprvalue.create_bool(lvs=rvs);
_NE:
result:=texprvalue.create_bool(lvs<>rvs);
_LT:
result:=texprvalue.create_bool(lvs<rvs);
_GT:
result:=texprvalue.create_bool(lvs>rvs);
_GTE:
result:=texprvalue.create_bool(lvs>=rvs);
_LTE:
result:=texprvalue.create_bool(lvs<=rvs);
_PLUS:
result:=texprvalue.create_str(lvs+rvs);
_MINUS, _STAR, _SLASH:
begin
Message(parser_e_illegal_expression);
result:=texprvalue.create_error;
end;
end;
end;
end
else
result:=texprvalue.create_error;
end;
end; end;
procedure texprvalue.error(expecteddef, place: string); procedure texprvalue.error(expecteddef, place: string);
@ -1375,9 +1422,9 @@ type
result:=texprvalue.try_parse_number(pp); result:=texprvalue.try_parse_number(pp);
if not assigned(result) then if not assigned(result) then
begin begin
if assigned(mac) and (m_mac in current_settings.modeswitches) and (pp='FALSE') then if assigned(mac) and (pp='FALSE') then
result:=texprvalue.create_bool(false) result:=texprvalue.create_bool(false)
else if assigned(mac) and (m_mac in current_settings.modeswitches) and (pp='TRUE') then else if assigned(mac) and (pp='TRUE') then
result:=texprvalue.create_bool(true) result:=texprvalue.create_bool(true)
else if (m_mac in current_settings.modeswitches) and else if (m_mac in current_settings.modeswitches) and
(not assigned(mac) or not mac.defined) and (not assigned(mac) or not mac.defined) and
@ -1691,24 +1738,19 @@ type
preproc_consume(_ID); preproc_consume(_ID);
exprvalue:=read_factor(eval); exprvalue:=read_factor(eval);
if eval then if eval then
begin result:=exprvalue.evaluate(nil,_OP_NOT)
if is_boolean(exprvalue.def) then
result:=texprvalue.create_bool(not exprvalue.asBool)
else
exprvalue.error('Boolean', 'NOT');
end
else else
result:=texprvalue.create_bool(false); {Just to have something} result:=texprvalue.create_bool(false); {Just to have something}
exprvalue.free; exprvalue.free;
end end
else else
if (m_mac in current_settings.modeswitches) and (current_scanner.preproc_pattern='TRUE') then if (current_scanner.preproc_pattern='TRUE') then
begin begin
result:=texprvalue.create_bool(true); result:=texprvalue.create_bool(true);
preproc_consume(_ID); preproc_consume(_ID);
end end
else else
if (m_mac in current_settings.modeswitches) and (current_scanner.preproc_pattern='FALSE') then if (current_scanner.preproc_pattern='FALSE') then
begin begin
result:=texprvalue.create_bool(false); result:=texprvalue.create_bool(false);
preproc_consume(_ID); preproc_consume(_ID);
@ -1871,8 +1913,7 @@ type
function read_expr(eval:Boolean): texprvalue; function read_expr(eval:Boolean): texprvalue;
var var
hs1,hs2: texprvalue; hs1,hs2: texprvalue;
b : boolean; op: ttoken;
op : ttoken;
begin begin
hs1:=read_simple_expr(eval); hs1:=read_simple_expr(eval);
op:=current_scanner.preproc_token; op:=current_scanner.preproc_token;
@ -1891,14 +1932,12 @@ type
hs2:=read_simple_expr(eval); hs2:=read_simple_expr(eval);
if eval then if eval then
b:=hs1.evaluate(hs2,op) result:=hs1.evaluate(hs2,op)
else else
b:= false; {Just to have something} result:=texprvalue.create_bool(false); {Just to have something}
hs1.free; hs1.free;
hs2.free; hs2.free;
result:=texprvalue.create_bool(b);
end; end;
begin begin