final changes for -O C++ feature completeness, mainly "when" statement support

This commit is contained in:
Vern Paxson 2022-05-12 14:07:36 -07:00
parent 48f1e4df42
commit 56140046d3
9 changed files with 191 additions and 33 deletions

View file

@ -66,6 +66,10 @@ void CPPCompile::GenStmt(const Stmt* s)
GenSwitchStmt(static_cast<const SwitchStmt*>(s));
break;
case STMT_WHEN:
GenWhenStmt(static_cast<const WhenStmt*>(s));
break;
case STMT_FOR:
GenForStmt(s->AsForStmt());
break;
@ -91,10 +95,6 @@ void CPPCompile::GenStmt(const Stmt* s)
case STMT_FALLTHROUGH:
break;
case STMT_WHEN:
ASSERT(0);
break;
default:
reporter->InternalError("bad statement type in CPPCompile::GenStmt");
}
@ -163,23 +163,26 @@ void CPPCompile::GenReturnStmt(const ReturnStmt* r)
{
auto e = r->StmtExpr();
if ( ! ret_type || ! e || e->GetType()->Tag() == TYPE_VOID || in_hook )
if ( in_hook )
Emit("return true;");
else if ( ! e && ret_type && ret_type->Tag() != TYPE_VOID )
// This occurs for ExpressionlessReturnOkay() functions.
Emit("return nullptr;");
else if ( ! ret_type || ! e || e->GetType()->Tag() == TYPE_VOID )
Emit("return;");
else
{
if ( in_hook )
Emit("return true;");
else
Emit("return;");
auto gt = ret_type->Tag() == TYPE_ANY ? GEN_VAL_PTR : GEN_NATIVE;
auto ret = GenExpr(e, gt);
return;
if ( e->GetType()->Tag() == TYPE_ANY )
ret = GenericValPtrToGT(ret, ret_type, gt);
Emit("return %s;", ret);
}
auto gt = ret_type->Tag() == TYPE_ANY ? GEN_VAL_PTR : GEN_NATIVE;
auto ret = GenExpr(e, gt);
if ( e->GetType()->Tag() == TYPE_ANY )
ret = GenericValPtrToGT(ret, ret_type, gt);
Emit("return %s;", ret);
}
void CPPCompile::GenAddStmt(const ExprStmt* es)
@ -384,6 +387,68 @@ void CPPCompile::GenValueSwitchStmt(const Expr* e, const case_list* cases)
Emit("}");
}
void CPPCompile::GenWhenStmt(const WhenStmt* w)
{
auto wi = w->Info();
auto wl = wi->Lambda();
if ( ! wl )
reporter->FatalError("cannot compile deprecated \"when\" statement");
auto is_return = wi->IsReturn() ? "true" : "false";
auto timeout = wi->TimeoutExpr();
auto timeout_val = timeout ? GenExpr(timeout, GEN_NATIVE) : "-1.0";
auto loc = w->GetLocationInfo();
Emit("{ // begin a new scope for internal variables");
Emit("static WhenInfo* CPP__wi = nullptr;");
Emit("static IDSet CPP__w_globals;");
NL();
Emit("if ( ! CPP__wi )");
StartBlock();
Emit("CPP__wi = new WhenInfo(%s);", is_return);
for ( auto& wg : wi->WhenExprGlobals() )
Emit("CPP__w_globals.insert(find_global__CPP(\"%s\").get());", wg->Name());
EndBlock();
NL();
Emit("std::vector<ValPtr> CPP__local_aggrs;");
for ( auto l : wi->WhenExprLocals() )
if ( IsAggr(l->GetType()) )
Emit("CPP__local_aggrs.emplace_back(%s);", IDNameStr(l));
Emit("CPP__wi->Instantiate(%s);", GenExpr(wi->Lambda(), GEN_NATIVE));
// We need a new frame for the trigger to unambiguously associate
// with, in case we're called multiple times with our existing frame.
Emit("auto new_frame = make_intrusive<Frame>(0, nullptr, nullptr);");
Emit("auto curr_t = f__CPP->GetTrigger();");
Emit("auto curr_assoc = f__CPP->GetTriggerAssoc();");
Emit("new_frame->SetTrigger({NewRef{}, curr_t});");
Emit("new_frame->SetTriggerAssoc(curr_assoc);");
Emit("auto t = new trigger::Trigger(CPP__wi, %s, CPP__w_globals, CPP__local_aggrs, "
"new_frame.get(), "
"nullptr);",
timeout_val);
auto loc_str = util::fmt("%s:%d-%d", loc->filename, loc->first_line, loc->last_line);
Emit("t->SetName(\"%s\");", loc_str);
if ( ret_type && ret_type->Tag() != TYPE_VOID )
{
Emit("ValPtr retval = {NewRef{}, curr_t->Lookup(curr_assoc)};");
Emit("if ( ! retval )");
Emit("\tthrow DelayedCallException();");
Emit("return %s;", GenericValPtrToGT("retval", ret_type, GEN_NATIVE));
}
Emit("}");
}
void CPPCompile::GenForStmt(const ForStmt* f)
{
Emit("{ // begin a new scope for the internal loop vars");