function genCall($func, $indent) { global $current_server; $funcname = $func->name; $rettype = getRetType($funcname); $argstype = getArgsType($funcname); $args_set = parseArgs(@$func->args); if (count($args_set) == 0) { echo "{$indent}cerl::NoArgs _args;\n"; echo "{$indent}(void) _args;\n"; } else { if (@$argstype) { echo "{$indent}{$argstype} _args;\n"; } } if (@$rettype) { echo "{$indent}{$rettype} _result = cerl::code_unknown_error;\n"; } // decode args $arg_count = count($args_set); if ($arg_count) { echo "{$indent}const bool _fOk = cerl::getMailBody(_ar, _args);\n\n"; echo "{$indent}if (_fOk)\n"; echo "{$indent}{\n"; } else { echo "{$indent}NS_CERL_IO::check_vt_null(_ar);\n"; } $indent2 = $arg_count ? $indent . "\t" : $indent; echo "{$indent2}CERL_DUMP_RECV_REQUEST(caller->getSelf(), this, _fid, _args);\n"; echo "{$indent2}{$funcname}(caller, _result"; if (count($args_set) == 1) { echo ", _args"; } else { foreach ($args_set as $var => $tp) { echo ", _args.{$var}"; } } echo ");\n"; if ($arg_count) { echo "{$indent}}\n"; //echo "${indent}else\n"; //echo "${indent}\t_result = cerl::code_format_error;\n"; } echo "\n{$indent}caller->dbg_reply(this, _result);\n"; }
function genImplFunc($func, $indent) { if (!$func) { return; } $args = parseArgs(@$func->args); $name = $func->name; $async = @$func->async; $rettype = getRetType($name); if ($async) { echo "\n{$indent}/*[async]*/"; } echo "\n{$indent}void cerl_call {$name}("; if (count($args) || !$async) { echo "\n{$indent}\t"; } $fPrefixUnderline = false; foreach ($args as $var => $tp) { $varstr = strtolower($var); if ($varstr == "result" || $varstr == "mail") { $fPrefixUnderline = true; } } $var_from = $fPrefixUnderline ? "_mail" : "mail"; $var_result = $fPrefixUnderline ? "_result" : "result"; echo "Caller* caller"; if (!$async) { echo ",\n{$indent}\t{$rettype}& {$var_result}"; } $args = parseArgs(@$func->args); foreach ($args as $var => $tp) { $typename = mapType($tp, "&"); echo ",\n{$indent}\t"; echo "const {$typename} {$var}"; } echo ")\n"; echo "{$indent}{\n{$indent}}\n"; }
function serializeRetType($namespace, $func, $indent) { global $module; global $builtin_codes; global $current_server, $derived_types; global $cpp_keywords; $type = @$func->type; $async = @$func->async; if ($async) { if ($type) { die("\nERROR: You are expecting the 'async' function '{$func->name}' return a value!\n"); } return; } else { if (!$type) { die("\nERROR: Are you sure you have given 'sync' function '{$func->name}' a return value?\n"); } } $retTyName = getRetType($func->name); if (@$derived_types[$current_server][$retTyName]) { return; } $items = $type->coded_type->items; //put echo "{$indent}\nCERL_IO_BEGIN_PUTTER({$namespace}::{$retTyName})\n"; $indent2 = $indent . "\t"; $indent3 = $indent2 . "\t"; echo "{$indent2}NS_CERL_IO::put(os, val._code);\n"; $flagNeedSwitch = 0; foreach ($items as $item) { $code_name = mapCodeName($item->code); $vars = @$item->vars; if ($vars) { if (0 == $flagNeedSwitch++) { echo "{$indent2}switch(val._code)\n"; echo "{$indent2}{\n"; } echo "{$indent2}case {$code_name}:\n"; foreach ($vars as $var) { $var_member = ""; if ("ok" == $item->code) { $var_member = "val.{$var->name}"; } else { $ns_code_name = $item->code; if (@$cpp_keywords[$item->code]) { $ns_code_name = "_" . $ns_code_name; } $var_member = "val.{$ns_code_name}.{$var->name}"; } echo "{$indent3}NS_CERL_IO::put(os, {$var_member});\n"; } echo "{$indent3}break;\n"; } } if ($flagNeedSwitch) { echo "{$indent2}default:\n{$indent3}break;\n{$indent2}}\n"; } echo "{$indent}CERL_IO_END_PUTTER()\n\n"; //get echo "{$indent}CERL_IO_BEGIN_GETTER({$namespace}::{$retTyName})\n"; $only_code = true; foreach ($items as $item) { if (@$item->vars) { $only_code = false; break; } } if ($only_code) { echo "{$indent2}return NS_CERL_IO::get(is, val._code);\n"; echo "{$indent}CERL_IO_END_GETTER()\n"; } else { echo "{$indent2}if (!NS_CERL_IO::get(is, val._code))\n"; echo "{$indent3}return false;\n"; $flagNeedSwitch = 0; foreach ($items as $item) { $code_name = mapCodeName($item->code); $vars = @$item->vars; if ($vars) { if (0 == $flagNeedSwitch++) { echo "\n{$indent2}switch(val._code)\n"; echo "{$indent2}{\n"; } echo "{$indent2}case {$code_name}:\n"; echo "{$indent3}return "; $index = 0; foreach ($vars as $var) { $var_member = ""; if ("ok" == $item->code) { $var_member = "val.{$var->name}"; } else { $ns_code_name = $item->code; if (@$cpp_keywords[$item->code]) { $ns_code_name = "_" . $ns_code_name; } $var_member = "val.{$ns_code_name}.{$var->name}"; } if ($index++) { echo "\n{$indent3}\t&& "; } echo "NS_CERL_IO::get(is, {$var_member})"; } echo ";\n"; } } if ($flagNeedSwitch) { echo "{$indent2}default:\n"; echo "{$indent3}return true;\n"; echo "{$indent2}}\n"; } else { echo "{$indent2}return true;\n"; } echo "{$indent}CERL_IO_END_GETTER()\n"; } //copy //printPODTYPE($items); $podTrue = true; echo "\n{$indent}template <class AllocT>\n"; echo "{$indent}inline void copy(AllocT& alloc, {$namespace}::{$retTyName}& dest, const {$namespace}::{$retTyName}& src)\n"; echo "{$indent}{\n"; //echo "${indent2}NS_CERL_IO::copy(alloc, dest._code, src._code);\n"; echo "{$indent2}dest = src;\n"; $flagNeedSwitch = 0; foreach ($items as $item) { $code_name = mapCodeName($item->code); $vars = @$item->vars; if ($vars) { $flagNeedCase = 0; foreach ($vars as $var) { $var_des = ""; $var_src = ""; if ("ok" == $item->code) { $var_des = "dest.{$var->name}"; $var_src = "src.{$var->name}"; } else { $ns_code_name = $item->code; if (@$cpp_keywords[$item->code]) { $ns_code_name = "_" . $ns_code_name; } $var_des = "dest.{$ns_code_name}.{$var->name}"; $var_src = "src.{$ns_code_name}.{$var->name}"; } if (!isPOD($var->type)) { if (0 == $flagNeedSwitch++) { echo "{$indent2}switch(src._code)\n{$indent2}{\n"; } if (0 == $flagNeedCase++) { echo "{$indent2}case {$code_name}:\n"; } echo "{$indent3}NS_CERL_IO::copy(alloc, {$var_des}, {$var_src});\n"; $podTrue = false; } } if ($flagNeedCase) { echo "{$indent3}break;\n"; } } } if ($flagNeedSwitch) { echo "{$indent2}default:\n{$indent3}break;\n{$indent2}}\n"; } echo "{$indent}}\n"; if ($podTrue) { echo "{$indent}CERL_PODTYPE({$namespace}::{$retTyName}, true);\n"; } else { echo "{$indent}CERL_PODTYPE({$namespace}::{$retTyName}, false);\n"; } //dump echo "\ntemplate <class LogT>\n"; echo "inline void cerl_call dump(LogT& log, const {$namespace}::{$retTyName}& result)\n"; echo "{\n"; echo "\tNS_CERL_IO::dump(log, '{');\n"; echo "\tresult.dumpCode(log);\n"; $once = true; foreach ($items as $item) { $code_name = mapCodeName($item->code); $vars = @$item->vars; if ($vars) { if ($once == true) { $once = false; echo "\tswitch (result._code)\n\t{\n"; } echo "\tcase {$code_name}:\n"; foreach ($vars as $var) { $result_member = ""; if ("ok" == $item->code) { $result_member = "result.{$var->name}"; } else { $ns_code_name = $item->code; if (@$cpp_keywords[$item->code]) { $ns_code_name = "_" . $ns_code_name; } $result_member = "result.{$ns_code_name}.{$var->name}"; } echo "\t\tNS_CERL_IO::dump(log, \", \");\n"; echo "\t\tNS_CERL_IO::dump(log, {$result_member});\n"; } echo "\t\tbreak;\n"; } } if ($once == false) { echo "\tdefault:\n\t\tbreak;\n"; echo "\t}\n"; //end of switch } echo "\tNS_CERL_IO::dump(log, '}');\n"; echo "}\n"; }
function processRetType($func, $indent) { $async = @$func->async; $ret = @$func->type; $rettype = getRetType($func->name); $indent2 = $indent . "\t"; if ($async || !$ret) { return; } global $module, $current_server; global $typetraits, $derived_types; global $builtin_codes, $codeset; global $cpp_keywords; $coded_type = @$ret->coded_type; if (!$coded_type) { die("\n---Error: while define RetType of '{$func->name}', ret type must be coded!"); } checkCodedType($coded_type, $rettype); //ret type always coded. $exist_tp = typedefExistsType($ret, $rettype); if ($exist_tp) { echo "\n{$indent}typedef {$exist_tp} {$rettype};\n"; return; } echo "\n{$indent}typedef struct {$rettype}Tag {\n"; echo "{$indent2}cerl::Code _code;\n"; $items = $coded_type->items; $indent3 = $indent2; //将$items分为$constructArray和$nonConstructArray,分别表示包含构造函数和不包含构造函数的集合。 $constructArray = array(); $nonConstructArray = array(); foreach ($items as $item) { $vars = @$item->vars; $flag = false; //是否包含构造函数,true表示放在union外,false表示放在union内。 if ($vars) { foreach ($vars as $var) { $type = $var->type; $tp = @$type->named_type; if (!$tp) { die("\n---ERROR: Can not find the type definition of '{$var->name}' in '{$func->name}'!"); } $type_name = mapType($type, ""); if (!isPOD($type)) { $flag = true; break; } } if ($flag) { array_push($constructArray, $item); } else { array_push($nonConstructArray, $item); } } } if (count($nonConstructArray) > 0) { $count = getStructCount($nonConstructArray); if ($count > 1) { $indent3 = $indent2 . "\t"; echo "{$indent2}union {\n"; } foreach ($nonConstructArray as $item) { $vars = @$item->vars; if ($vars) { echo "{$indent3}struct {\n"; foreach ($vars as $var) { $type = $var->type; $tp = @$type->named_type; if (!$tp) { die("\n---ERROR: Can not find the type definition of '{$var->name}' in '{$func->name}'!"); } $type_name = mapType($type, ""); echo "{$indent3}\t{$type_name} {$var->name};\n"; } $item_name = $item->code == "ok" ? "" : $item->code; if ($item->code != "ok" && @$cpp_keywords[$item->code]) { $item_name = "_" . $item_name; } echo "{$indent3}}{$item_name};\n"; } } if ($count > 1) { echo "{$indent2}};\n"; } } if (count($constructArray) > 0) { foreach ($constructArray as $item) { $vars = @$item->vars; $indent3 = $indent2; if ($vars) { if ($item->code != "ok") { echo "{$indent2}struct {\n"; $indent3 = $indent2 . "\t"; } foreach ($vars as $var) { $type = $var->type; $tp = @$type->named_type; if (!$tp) { die("\n---ERROR: Can not find the type definition of '{$var->name}' in '{$func->name}'!"); } $type_name = mapType($type, ""); echo "{$indent3}{$type_name} {$var->name};\n"; } if ($item->code != "ok") { $item_name = $item->code; if (@$cpp_keywords[$item->code]) { $item_name = "_" . $item_name; } echo "{$indent2}}{$item_name};\n"; } } } } echo "\n{$indent2}{$rettype}Tag(cerl::Code code = cerl::code_error) {\n"; echo "{$indent2}\t_code = code;\n"; echo "{$indent2}}\n"; echo "\n{$indent2}operator cerl::Code() const {\n"; echo "{$indent2}\treturn _code;\n"; echo "{$indent2}}\n"; echo "\n{$indent2}void cerl_call operator=(cerl::Code code) {\n"; echo "{$indent2}\t_code = code;\n"; echo "{$indent2}}\n"; // generate dumpCode function echo "\n{$indent2}template <class LogT>\n"; echo "{$indent2}void cerl_call dumpCode(LogT& log) const {\n"; echo "{$indent2}\tNS_CERL_IO::dumpCode(log, _code);\n"; echo "{$indent2}}\n"; echo "{$indent}} {$rettype};\n"; /*end of struct*/ }
function genSyncFuncDef($func, $indent) { $name = $func->name; $async = @$func->async; $args_set = parseArgs(@$func->args); $retType = getRetType($name); if ($async) { echo "\n{$indent}/*[async]*/"; } echo "\n{$indent}bool cerl_call {$name}("; if (!$async) { echo "cerl::ScopedAlloc& alloc"; echo ",\n{$indent}\t{$retType}& _result"; } $flag = 0; foreach ($args_set as $var => $type) { $typename = mapType($type, "&"); if ($flag == 0 && $async) { echo "const {$typename} {$var}"; $flag = 1; } else { echo ",\n{$indent}\tconst {$typename} {$var}"; } } if (count($args_set) || !$async) { echo "\n{$indent}\t"; } echo ")\n"; echo "{$indent}{\n"; if (count($args_set) > 1) { $argsTyName = getArgsType($name); echo "{$indent}\t{$argsTyName} _args = {"; $j = 1; foreach ($args_set as $var => $type) { if ($j == 1) { echo "{$var}"; } else { echo ", {$var}"; } $j++; } echo "};\n"; } if ($async) { if (count($args_set) == 0) { echo "{$indent}\treturn m_conn.dbg_cast0(this, (cerl::FID)code_{$name});\n"; } else { if (count($args_set) == 1) { foreach ($args_set as $var => $type) { break; } echo "{$indent}\treturn m_conn.dbg_cast(this, (cerl::FID)code_{$name}, {$var});\n"; } else { echo "{$indent}\treturn m_conn.dbg_cast(this, (cerl::FID)code_{$name}, _args);\n"; } } } else { if (count($args_set) == 0) { echo "{$indent}\treturn m_conn.dbg_call0(this, alloc, _result, (cerl::FID)code_{$name});\n"; } else { if (count($args_set) == 1) { foreach ($args_set as $var => $type) { break; } echo "{$indent}\treturn m_conn.dbg_call(this, alloc, _result, (cerl::FID)code_{$name}, {$var});\n"; } else { echo "{$indent}\treturn m_conn.dbg_call(this, alloc, _result, (cerl::FID)code_{$name}, _args);\n"; } } } echo "{$indent}}\n"; }