#include <functional>
#include <cassert>
namespace Wide {
namespace Codegen {
class Statement { public: virtual ~Statement() {} };
class Expression : public Statement {};
class IfStatement : public Statement {};
class Generator {
public:
virtual IfStatement* CreateIfStatement(Expression* expr, Statement* t, Statement* f) = 0;
virtual IfStatement* CreateIfStatement(std::function<Expression*()>, Statement*, Statement*) = 0;
};
}
namespace LLVMCodegen {
class Statement { public: virtual ~Statement() {} };
struct Expression : Statement {};
class IfStatement : public Statement, public Codegen::IfStatement {
public:
IfStatement(std::function<LLVMCodegen::Expression*()> cond, LLVMCodegen::Statement* tbr, LLVMCodegen::Statement* fbr) {}
};
Expression* AssertExpression(Wide::Codegen::Expression* e) {
return dynamic_cast<Wide::LLVMCodegen::Expression*>(e);
}
Statement* AssertStatement(Wide::Codegen::Statement* e) {
return dynamic_cast<Wide::LLVMCodegen::Statement*>(e);
}
class Generator : public Codegen::Generator {
public:
IfStatement* CreateIfStatement(Codegen::Expression* expr, Codegen::Statement* t, Codegen::Statement* f) {
return CreateIfStatement([=] { return expr; }, t, f);
}
IfStatement* CreateIfStatement(std::function<Codegen::Expression*()> cond, Codegen::Statement* tr, Codegen::Statement* fls) {
return new IfStatement([=] { return AssertExpression(cond()); }, AssertStatement(tr), fls ? AssertStatement(fls) : nullptr);
}
};
}
}
int main() {
Wide::LLVMCodegen::Generator g;
}
I2luY2x1ZGUgPGZ1bmN0aW9uYWw+CiNpbmNsdWRlIDxjYXNzZXJ0PgoKbmFtZXNwYWNlIFdpZGUgewogICAgbmFtZXNwYWNlIENvZGVnZW4gewogICAgICAgIGNsYXNzIFN0YXRlbWVudCB7IHB1YmxpYzogdmlydHVhbCB+U3RhdGVtZW50KCkge30gfTsKICAgICAgICBjbGFzcyBFeHByZXNzaW9uIDogcHVibGljIFN0YXRlbWVudCB7fTsKICAgICAgICBjbGFzcyBJZlN0YXRlbWVudCAgOiBwdWJsaWMgU3RhdGVtZW50IHt9OwogICAgICAgIGNsYXNzIEdlbmVyYXRvciB7CiAgICAgICAgcHVibGljOgogICAgICAgICAgICB2aXJ0dWFsIElmU3RhdGVtZW50KiBDcmVhdGVJZlN0YXRlbWVudChFeHByZXNzaW9uKiBleHByLCBTdGF0ZW1lbnQqIHQsIFN0YXRlbWVudCogZikgPSAwOwogICAgICAgICAgICB2aXJ0dWFsIElmU3RhdGVtZW50KiBDcmVhdGVJZlN0YXRlbWVudChzdGQ6OmZ1bmN0aW9uPEV4cHJlc3Npb24qKCk+LCBTdGF0ZW1lbnQqLCBTdGF0ZW1lbnQqKSA9IDA7CiAgICAgICAgfTsKICAgIH0KICAgIG5hbWVzcGFjZSBMTFZNQ29kZWdlbiB7CiAgICAgICAgY2xhc3MgU3RhdGVtZW50IHsgcHVibGljOiB2aXJ0dWFsIH5TdGF0ZW1lbnQoKSB7fSB9OwogICAgICAgIHN0cnVjdCBFeHByZXNzaW9uIDogU3RhdGVtZW50IHt9OwoKICAgICAgICBjbGFzcyBJZlN0YXRlbWVudCA6IHB1YmxpYyBTdGF0ZW1lbnQsIHB1YmxpYyBDb2RlZ2VuOjpJZlN0YXRlbWVudCB7CiAgICAgICAgcHVibGljOgogICAgICAgICAgICBJZlN0YXRlbWVudChzdGQ6OmZ1bmN0aW9uPExMVk1Db2RlZ2VuOjpFeHByZXNzaW9uKigpPiBjb25kLCBMTFZNQ29kZWdlbjo6U3RhdGVtZW50KiB0YnIsIExMVk1Db2RlZ2VuOjpTdGF0ZW1lbnQqIGZicikge30KICAgICAgICB9OwogICAgICAgIEV4cHJlc3Npb24qIEFzc2VydEV4cHJlc3Npb24oV2lkZTo6Q29kZWdlbjo6RXhwcmVzc2lvbiogZSkgewogICAgICAgICAgICByZXR1cm4gZHluYW1pY19jYXN0PFdpZGU6OkxMVk1Db2RlZ2VuOjpFeHByZXNzaW9uKj4oZSk7CiAgICAgICAgfQogICAgICAgIFN0YXRlbWVudCogQXNzZXJ0U3RhdGVtZW50KFdpZGU6OkNvZGVnZW46OlN0YXRlbWVudCogZSkgewogICAgICAgICAgICByZXR1cm4gZHluYW1pY19jYXN0PFdpZGU6OkxMVk1Db2RlZ2VuOjpTdGF0ZW1lbnQqPihlKTsKICAgICAgICB9CiAgICAgICAgY2xhc3MgR2VuZXJhdG9yIDogcHVibGljIENvZGVnZW46OkdlbmVyYXRvciB7CiAgICAgICAgcHVibGljOiAgICAgICAgICAgIAogICAgICAgICAgICBJZlN0YXRlbWVudCogQ3JlYXRlSWZTdGF0ZW1lbnQoQ29kZWdlbjo6RXhwcmVzc2lvbiogZXhwciwgQ29kZWdlbjo6U3RhdGVtZW50KiB0LCBDb2RlZ2VuOjpTdGF0ZW1lbnQqIGYpIHsKICAgICAgICAgICAgICAgIHJldHVybiBDcmVhdGVJZlN0YXRlbWVudChbPV0geyByZXR1cm4gZXhwcjsgfSwgdCwgZik7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgSWZTdGF0ZW1lbnQqIENyZWF0ZUlmU3RhdGVtZW50KHN0ZDo6ZnVuY3Rpb248Q29kZWdlbjo6RXhwcmVzc2lvbiooKT4gY29uZCwgQ29kZWdlbjo6U3RhdGVtZW50KiB0ciwgQ29kZWdlbjo6U3RhdGVtZW50KiBmbHMpIHsKICAgICAgICAgICAgICAgIHJldHVybiBuZXcgSWZTdGF0ZW1lbnQoWz1dIHsgcmV0dXJuIEFzc2VydEV4cHJlc3Npb24oY29uZCgpKTsgfSwgQXNzZXJ0U3RhdGVtZW50KHRyKSwgZmxzID8gQXNzZXJ0U3RhdGVtZW50KGZscykgOiBudWxscHRyKTsKICAgICAgICAgICAgfQogICAgICAgIH07CiAgICB9Cn0KCmludCBtYWluKCkgewogICAgV2lkZTo6TExWTUNvZGVnZW46OkdlbmVyYXRvciBnOwp9