const type: inlineParamData is new struct
var reference: paramValue is NIL;
var integer: paramNum is 0;
var reference: actualParam is NIL;
end struct;
const type: inlineParamHash is hash [reference] array inlineParamData;
var inlineParamHash: inlineParam is inlineParamHash.EMPTY_HASH;
const func boolean: isPointerParam (in reference: a_param) is forward;
const func boolean: isCopyParam (in reference: a_param) is forward;
const func boolean: canTakeAddress (in reference: an_expression) is forward;
const func boolean: getConstant (in reference: currExpr,
inout reference: evaluatedExpr) is forward;
const proc: process_local_var_declaration (in reference: current_object,
inout expr_type: c_expr) is forward;
const proc: pushInlineParam (in reference: obj, in inlineParamData: paramData) is func
begin
if obj in inlineParam then
inlineParam @:= [obj] [] (paramData) & inlineParam[obj];
else
inlineParam @:= [obj] [] (paramData);
end if;
end func;
const proc: popInlineParam (in reference: obj) is func
begin
if length(inlineParam[obj]) = 1 then
excl(inlineParam, obj);
else
inlineParam @:= [obj] inlineParam[obj][2 ..];
end if;
end func;
const proc: assign_inline_param (in reference: formal_param,
in reference: actual_param, inout expr_type: c_expr) is func
local
var integer: temp_num is 0;
begin
if isPointerParam(formal_param) then
if category(actual_param) = REFPARAMOBJECT then
if actual_param in inlineParam and
inlineParam[actual_param][1].paramNum <> 0 then
c_expr.expr &:= "par_";
c_expr.expr &:= str(inlineParam[actual_param][1].paramNum);
c_expr.expr &:= "_";
end if;
c_expr.expr &:= "o_";
create_name(actual_param, c_expr.expr);
elsif canTakeAddress(actual_param) then
c_expr.expr &:= "&(";
process_expr(actual_param, c_expr);
c_expr.expr &:= ")";
else
incr(c_expr.temp_num);
temp_num := c_expr.temp_num;
c_expr.temp_decls &:= type_name(getExprResultType(actual_param));
c_expr.temp_decls &:= " tmp_";
c_expr.temp_decls &:= str(temp_num);
c_expr.temp_decls &:= ";\n";
c_expr.expr &:= "(tmp_";
c_expr.expr &:= str(temp_num);
c_expr.expr &:= "=(";
c_expr.expr &:= type_name(getExprResultType(actual_param));
c_expr.expr &:= ")(";
getAnyParamToExpr(actual_param, c_expr);
c_expr.expr &:= "), &tmp_";
c_expr.expr &:= str(temp_num);
c_expr.expr &:= ")";
end if;
else
getAnyParamToExpr(actual_param, c_expr);
end if;
end func;
const proc: push_inline_func_param (in reference: formal_param,
in reference: actual_param, inout expr_type: c_expr) is func
local
var category: paramCategory is category.value;
var reference: evaluatedParam is NIL;
var type: param_type is void;
var string: param_name is "";
var expr_type: actual_param_expr is expr_type.value;
var integer: temp_num is 0;
var inlineParamData: paramData is inlineParamData.value;
begin
paramCategory := category(formal_param);
if paramCategory = TYPEOBJECT then
c_expr.expr &:= "/* attr t_";
c_expr.expr &:= str(typeNumber(getValue(formal_param, type)));
c_expr.expr &:= " ";
c_expr.expr &:= str(getValue(formal_param, type));
c_expr.expr &:= "*/\n";
elsif paramCategory <> SYMBOLOBJECT then
param_type := getType(formal_param);
c_expr.expr &:= diagnosticLine(formal_param);
if isFunc(param_type) then
c_expr.expr &:= "/* push proc param o_";
create_name2(formal_param, c_expr.expr);
c_expr.expr &:= " */\n";
paramData.paramValue := actual_param;
paramData.actualParam := actual_param;
pushInlineParam(formal_param, paramData);
elsif not isVar(formal_param) and getConstant(actual_param, evaluatedParam) then
c_expr.expr &:= "/* push const param o_";
create_name2(formal_param, c_expr.expr);
c_expr.expr &:= " */\n";
setVar(evaluatedParam, FALSE);
paramData.paramValue := evaluatedParam;
paramData.actualParam := actual_param;
pushInlineParam(formal_param, paramData);
else
c_expr.expr &:= "/* push param o_";
create_name2(formal_param, c_expr.expr);
c_expr.expr &:= " */ ";
if not isVar(formal_param) then
if isPointerParam(formal_param) then
c_expr.temp_decls &:= "const ";
elsif useConstPrefix(param_type) then
c_expr.temp_decls &:= "const_";
end if;
end if;
c_expr.temp_decls &:= type_name(param_type);
c_expr.temp_decls &:= " ";
if isPointerParam(formal_param) then
c_expr.temp_decls &:= "*";
end if;
incr(c_expr.temp_num);
temp_num := c_expr.temp_num;
paramData.paramNum := temp_num;
paramData.actualParam := actual_param;
pushInlineParam(formal_param, paramData);
param_name := "par_";
param_name &:= str(temp_num);
param_name &:= "_o_";
create_name(formal_param, param_name);
c_expr.temp_decls &:= param_name;
c_expr.temp_decls &:= " = (";
c_expr.temp_decls &:= type_name(param_type);
if isPointerParam(formal_param) then
c_expr.temp_decls &:= " *";
end if;
c_expr.temp_decls &:= ")(0);\n";
c_expr.expr &:= param_name;
c_expr.expr &:= "=";
if isCopyParam(formal_param) then
prepareAnyParamTemporarys(actual_param, actual_param_expr, c_expr);
if actual_param_expr.result_expr <> "" then
c_expr.expr &:= actual_param_expr.result_expr;
else
process_create_declaration(getType(formal_param), global_c_expr);
process_create_call(getType(formal_param),
actual_param_expr.expr, c_expr.expr);
end if;
process_destr_declaration(getType(formal_param), global_c_expr);
process_destr_call(getType(formal_param),
param_name, c_expr.temp_frees);
else
assign_inline_param(formal_param, actual_param, c_expr);
end if;
c_expr.expr &:= ",\n";
end if;
end if;
end func;
const proc: push_inline_func_params (in ref_list: formal_params,
in ref_list: actual_params, inout expr_type: c_expr) is func
local
var integer: number is 0;
begin
for number range 1 to length(formal_params) do
push_inline_func_param(formal_params[number], actual_params[number], c_expr);
end for;
end func;
const proc: pop_inline_func_param (in reference: formal_param,
inout string: expr) is func
local
var category: paramCategory is category.value;
var type: param_type is void;
begin
paramCategory := category(formal_param);
if paramCategory <> SYMBOLOBJECT and paramCategory <> TYPEOBJECT then
param_type := getType(formal_param);
if isFunc(param_type) then
expr &:= diagnosticLine(formal_param);
expr &:= "/* pop proc param o_";
create_name2(formal_param, expr);
expr &:= " */\n";
elsif not isVar(formal_param) and formal_param in inlineParam and
inlineParam[formal_param][1].paramValue <> NIL then
expr &:= diagnosticLine(formal_param);
expr &:= "/* pop const param o_";
create_name2(formal_param, expr);
expr &:= " */\n";
end if;
popInlineParam(formal_param);
end if;
end func;
const proc: pop_inline_func_params (in ref_list: formal_params,
inout string: expr) is func
local
var integer: number is 0;
begin
for number range 1 to length(formal_params) do
pop_inline_func_param(formal_params[number], expr);
end for;
end func;
const proc: process_inline_func (in reference: function,
in ref_list: actual_params, inout expr_type: c_expr) is func
local
var string: diagnosticLine is "";
var type: function_type is void;
var type: result_type is void;
var ref_list: formal_params is ref_list.EMPTY;
var expr_type: inline_body is expr_type.value;
var expr_type: inline_decls is expr_type.value;
var reference: result_object is NIL;
begin
diagnosticLine := diagnosticLine(function);
function_type := getType(function);
result_type := resultType(function_type);
formal_params := formalParams(function);
inline_decls.temp_num := c_expr.temp_num;
push_inline_func_params(formal_params, actual_params, inline_decls);
process_local_var_declaration(function, inline_decls);
result_object := resultVar(function);
if result_object <> NIL then
inline_decls.temp_decls &:= type_name(getType(result_object));
inline_decls.temp_decls &:= " o_";
create_name(result_object, inline_decls.temp_decls);
inline_decls.temp_decls &:= ";\n";
end if;
c_expr.temp_num := inline_decls.temp_num;
c_expr.temp_decls &:= inline_decls.temp_decls;
c_expr.temp_assigns &:= inline_decls.temp_assigns;
c_expr.temp_frees &:= inline_decls.temp_frees;
c_expr.temp_to_null &:= inline_decls.temp_to_null;
prepareAnyParamTemporarys(body(function), inline_body, c_expr);
if inline_body.result_expr <> "" then
c_expr.result_expr &:= "\n";
c_expr.result_expr &:= diagnosticLine;
c_expr.result_expr &:= "/* ";
c_expr.result_expr &:= "inline func o_";
create_name2(function, c_expr.result_expr);
c_expr.result_expr &:= " */ ";
c_expr.result_expr &:= "((";
c_expr.result_expr &:= type_name(result_type);
c_expr.result_expr &:= ")(\n";
c_expr.result_expr &:= inline_decls.expr;
c_expr.result_name := inline_body.result_name;
c_expr.result_decl := inline_body.result_decl;
c_expr.result_free := inline_body.result_free;
c_expr.result_to_null := inline_body.result_to_null;
c_expr.result_intro := inline_body.result_intro;
c_expr.result_finish := inline_body.result_finish;
c_expr.result_expr &:= diagnosticLine;
c_expr.result_expr &:= inline_body.result_expr;
c_expr.result_expr &:= "\n";
pop_inline_func_params(formal_params, c_expr.result_expr);
c_expr.result_expr &:= diagnosticLine;
c_expr.result_expr &:= ")) /* ";
c_expr.result_expr &:= "inline func o_";
create_name2(function, c_expr.result_expr);
c_expr.result_expr &:= " */\n";
else
c_expr.expr &:= "\n";
c_expr.expr &:= diagnosticLine;
c_expr.expr &:= "/* ";
if isVarfunc(function_type) then
c_expr.expr &:= "var";
end if;
c_expr.expr &:= "inline func o_";
create_name2(function, c_expr.expr);
c_expr.expr &:= " */ ";
if isVarfunc(function_type) then
c_expr.expr &:= "*";
end if;
c_expr.expr &:= "((";
c_expr.expr &:= type_name(result_type);
if isVarfunc(function_type) then
c_expr.expr &:= " *";
end if;
c_expr.expr &:= ")(\n";
c_expr.expr &:= inline_decls.expr;
c_expr.expr &:= diagnosticLine;
if isVarfunc(function_type) then
c_expr.expr &:= "&(";
c_expr.expr &:= inline_body.expr;
c_expr.expr &:= ")";
else
c_expr.expr &:= inline_body.expr;
end if;
c_expr.expr &:= "\n";
pop_inline_func_params(formal_params, c_expr.expr);
c_expr.expr &:= diagnosticLine;
c_expr.expr &:= ")) /* ";
if isVarfunc(function_type) then
c_expr.expr &:= "var";
end if;
c_expr.expr &:= "inline func o_";
create_name2(function, c_expr.expr);
c_expr.expr &:= " */\n";
end if;
end func;
const proc: push_inline_proc_param (in reference: formal_param,
in reference: actual_param, inout expr_type: c_expr) is func
local
var category: paramCategory is category.value;
var reference: evaluatedParam is NIL;
var type: param_type is void;
var string: param_name is "";
var expr_type: actual_param_expr is expr_type.value;
var expr_type: assign_decls is expr_type.value;
var inlineParamData: paramData is inlineParamData.value;
begin
paramCategory := category(formal_param);
if paramCategory = TYPEOBJECT then
c_expr.expr &:= "/* attr t_";
c_expr.expr &:= str(typeNumber(getValue(formal_param, type)));
c_expr.expr &:= " ";
c_expr.expr &:= str(getValue(formal_param, type));
c_expr.expr &:= "*/\n";
elsif paramCategory <> SYMBOLOBJECT then
param_type := getType(formal_param);
if isFunc(param_type) then
c_expr.temp_decls &:= diagnosticLine(formal_param);
c_expr.temp_decls &:= "/* push proc param o_";
create_name2(formal_param, c_expr.temp_decls);
c_expr.temp_decls &:= " */\n";
paramData.paramValue := actual_param;
elsif not isVar(formal_param) and getConstant(actual_param, evaluatedParam) then
c_expr.temp_decls &:= diagnosticLine(formal_param);
c_expr.temp_decls &:= "/* push const param o_";
create_name2(formal_param, c_expr.temp_decls);
c_expr.temp_decls &:= " */\n";
setVar(evaluatedParam, FALSE);
paramData.paramValue := evaluatedParam;
elsif isCopyParam(formal_param) then
c_expr.expr &:= diagnosticLine(formal_param);
c_expr.expr &:= "/* push param o_";
create_name2(formal_param, c_expr.expr);
c_expr.expr &:= " */ ";
create_name(formal_param, param_name);
if not isVar(formal_param) and useConstPrefix(param_type) then
c_expr.temp_decls &:= "const_";
end if;
c_expr.temp_decls &:= type_name(param_type);
c_expr.temp_decls &:= " o_";
c_expr.temp_decls &:= param_name;
c_expr.temp_decls &:= ";\n";
c_expr.temp_assigns &:= "o_";
c_expr.temp_assigns &:= param_name;
c_expr.temp_assigns &:= "=";
prepareAnyParamTemporarys(actual_param, actual_param_expr, c_expr);
if actual_param_expr.result_expr <> "" then
c_expr.temp_assigns &:= actual_param_expr.result_expr;
else
process_create_declaration(getType(formal_param), global_c_expr);
process_create_call(getType(formal_param),
actual_param_expr.expr, c_expr.temp_assigns);
end if;
c_expr.temp_assigns &:= ";\n";
process_destr_declaration(getType(formal_param), global_c_expr);
process_destr_call(getType(formal_param),
"o_" & param_name, c_expr.temp_frees);
else
c_expr.expr &:= diagnosticLine(formal_param);
c_expr.expr &:= "/* push o_";
create_name2(formal_param, c_expr.expr);
c_expr.expr &:= " */\n";
assign_decls.temp_num := c_expr.temp_num;
assign_inline_param(formal_param, actual_param, assign_decls);
c_expr.temp_num := assign_decls.temp_num;
c_expr.temp_decls &:= assign_decls.temp_decls;
c_expr.temp_assigns &:= assign_decls.temp_assigns;
c_expr.temp_frees &:= assign_decls.temp_frees;
if not isVar(formal_param) then
if assign_decls.expr = "" or assign_decls.temp_assigns = "" then
c_expr.temp_decls &:= "const ";
end if;
if not isPointerParam(formal_param) and useConstPrefix(param_type) then
c_expr.temp_decls &:= "const_";
end if;
end if;
c_expr.temp_decls &:= type_name(param_type);
c_expr.temp_decls &:= " ";
if isPointerParam(formal_param) then
c_expr.temp_decls &:= "*const ";
end if;
c_expr.temp_decls &:= "o_";
create_name(formal_param, c_expr.temp_decls);
if assign_decls.expr <> "" then
if assign_decls.temp_assigns = "" then
c_expr.temp_decls &:= "=";
c_expr.temp_decls &:= assign_decls.expr;
c_expr.temp_decls &:= ";\n";
else
c_expr.temp_decls &:= ";\n";
c_expr.temp_assigns &:= "o_";
create_name(formal_param, c_expr.temp_assigns);
c_expr.temp_assigns &:= "=";
c_expr.temp_assigns &:= assign_decls.expr;
c_expr.temp_assigns &:= ";\n";
end if;
else
c_expr.temp_decls &:= ";\n";
end if;
end if;
paramData.actualParam := actual_param;
pushInlineParam(formal_param, paramData);
end if;
end func;
const proc: push_inline_proc_params (in ref_list: formal_params,
in ref_list: actual_params, inout expr_type: c_expr) is func
local
var integer: number is 0;
begin
for number range 1 to length(formal_params) do
push_inline_proc_param(formal_params[number], actual_params[number], c_expr);
end for;
end func;
const proc: pop_inline_proc_param (in reference: formal_param,
inout expr_type: c_expr) is func
local
var category: paramCategory is category.value;
var type: param_type is void;
begin
paramCategory := category(formal_param);
if paramCategory <> SYMBOLOBJECT and paramCategory <> TYPEOBJECT then
param_type := getType(formal_param);
if isFunc(param_type) then
c_expr.expr &:= diagnosticLine(formal_param);
c_expr.expr &:= "/* pop proc param o_";
create_name2(formal_param, c_expr.expr);
c_expr.expr &:= " */\n";
elsif not isVar(formal_param) and formal_param in inlineParam and
inlineParam[formal_param][1].paramValue <> NIL then
c_expr.expr &:= diagnosticLine(formal_param);
c_expr.expr &:= "/* pop const param o_";
create_name2(formal_param, c_expr.expr);
c_expr.expr &:= " */\n";
end if;
popInlineParam(formal_param);
end if;
end func;
const proc: pop_inline_proc_params (in ref_list: formal_params,
inout expr_type: c_expr) is func
local
var integer: number is 0;
begin
for number range 1 to length(formal_params) do
pop_inline_proc_param(formal_params[number], c_expr);
end for;
end func;
const proc: process_inline_proc (in reference: function,
in ref_list: actual_params, inout expr_type: c_expr) is func
local
var string: diagnosticLine is "";
var ref_list: formal_params is ref_list.EMPTY;
var expr_type: inline_decls is expr_type.value;
begin
diagnosticLine := diagnosticLine(function);
formal_params := formalParams(function);
c_expr.expr &:= diagnosticLine;
c_expr.expr &:= "/* inline proc o_";
create_name2(function, c_expr.expr);
c_expr.expr &:= " */ {\n";
c_expr.expr &:= diagnosticLine;
c_expr.expr &:= "/* inline params */\n";
inline_decls.temp_num := c_expr.temp_num;
push_inline_proc_params(formal_params, actual_params, inline_decls);
inline_decls.temp_decls &:= "/* inline local_vars */\n";
process_local_var_declaration(function, inline_decls);
c_expr.temp_num := inline_decls.temp_num;
appendWithDiagnostic(inline_decls.temp_decls, c_expr);
appendWithDiagnostic(inline_decls.temp_assigns, c_expr);
c_expr.expr &:= diagnosticLine;
c_expr.expr &:= "/* inline body */\n";
process_expr(body(function), c_expr);
appendWithDiagnostic(inline_decls.temp_frees, c_expr);
pop_inline_proc_params(formal_params, c_expr);
c_expr.expr &:= "\n";
c_expr.expr &:= diagnosticLine;
c_expr.expr &:= "} /* inline proc o_";
create_name2(function, c_expr.expr);
c_expr.expr &:= " */\n";
end func;
const proc: process_inline (in reference: function,
in ref_list: actual_params, inout expr_type: c_expr) is func
begin
if resultType(getType(function)) <> voidtype then
process_inline_func(function, actual_params, c_expr);
else
process_inline_proc(function, actual_params, c_expr);
end if;
end func;
const proc: process_inline_param (in reference: formal_param,
inout expr_type: c_expr) is func
local
var expr_type: c_body is expr_type.value;
begin
if getType(formal_param) = proctype then
c_expr.expr &:= "/* closure o_";
create_name2(formal_param, c_expr.expr);
c_expr.expr &:= "*/ {\n";
process_call_by_name_expr(inlineParam[formal_param][1].paramValue, c_body);
appendWithDiagnostic(c_body.temp_decls, c_expr);
appendWithDiagnostic(c_body.temp_assigns, c_expr);
c_expr.expr &:= c_body.expr;
appendWithDiagnostic(c_body.temp_frees, c_expr);
c_expr.expr &:= "\n} /* closure o_";
create_name2(formal_param, c_expr.expr);
c_expr.expr &:= "*/\n";
else
c_body.temp_num := c_expr.temp_num;
process_call_by_name_expr(inlineParam[formal_param][1].paramValue, c_body);
c_expr.temp_num := c_body.temp_num;
if c_body.result_expr <> "" then
c_expr.result_expr &:= "/* closure o_";
create_name2(formal_param, c_expr.result_expr);
c_expr.result_expr &:= "*/ (";
c_expr.result_expr &:= c_body.result_expr;
c_expr.result_expr &:= ")";
c_expr.temp_decls &:= c_body.temp_decls;
c_expr.temp_assigns &:= c_body.temp_assigns;
c_expr.temp_frees &:= c_body.temp_frees;
c_expr.result_name := c_body.result_name;
c_expr.result_decl := c_body.result_decl;
c_expr.result_free := c_body.result_free;
c_expr.result_to_null := c_body.result_to_null;
c_expr.result_intro := c_body.result_intro;
c_expr.result_finish := c_body.result_finish;
else
c_expr.expr &:= "/* closure o_";
create_name2(formal_param, c_expr.expr);
c_expr.expr &:= "*/ (";
c_expr.expr &:= c_body.expr;
c_expr.expr &:= ")";
c_expr.temp_decls &:= c_body.temp_decls;
c_expr.temp_assigns &:= c_body.temp_assigns;
c_expr.temp_frees &:= c_body.temp_frees;
end if;
end if;
end func;