Created
February 25, 2012 02:35
-
-
Save mpapierski/1905412 to your computer and use it in GitHub Desktop.
Write GUI applications in a compile-time abstract language
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Write GUI applications in an compile-time abstract language | |
// | |
// Copyright 2011 Michał Papierski <[email protected]> | |
// | |
// This program is free software; you can redistribute it and/or modify | |
// it under the terms of the GNU General Public License as published by | |
// the Free Software Foundation; either version 2 of the License, or | |
// (at your option) any later version. | |
// | |
// This program is distributed in the hope that it will be useful, | |
// but WITHOUT ANY WARRANTY; without even the implied warranty of | |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
// GNU General Public License for more details. | |
// | |
// You should have received a copy of the GNU General Public License | |
// along with this program; if not, write to the Free Software | |
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, | |
// MA 02110-1301, USA. | |
#include <iostream> | |
#include <string> | |
#include <list> | |
#include <map> | |
#include <boost/lexical_cast.hpp> | |
using namespace std; | |
struct object | |
{ | |
virtual string description() const = 0; | |
operator string() const { return description(); } | |
}; | |
struct abstract_expr: object | |
{ | |
}; | |
template <typename T> | |
string toString(T t) { return (string)t; } | |
template <> | |
string toString(int t) { return boost::lexical_cast<string>(t); } | |
template <> | |
string toString(const char* t) { return string("\"") + t + '"'; } | |
template <typename T1, typename T2> | |
struct chain_op: abstract_expr | |
{ | |
T1 t1_; | |
T2 t2_; | |
chain_op(T1 t1, T2 t2): t1_(t1), t2_(t2) {} | |
virtual string description() const | |
{ | |
return t1_.description() + "\n" + t2_.description(); | |
} | |
template <typename F1> | |
chain_op<chain_op<T1, T2>, F1> operator,(F1 f1) | |
{ | |
return chain_op<chain_op<T1, T2>, F1>(*this, f1); | |
} | |
}; | |
namespace expr | |
{ | |
template <typename T1, typename T2> | |
struct add_impl: abstract_expr | |
{ | |
T1 t1_; | |
T2 t2_; | |
add_impl(T1 t1, T2 t2): t1_(t1), t2_(t2) {} | |
virtual string description() const | |
{ | |
return t1_.description() + " + " + t2_.description(); | |
} | |
}; | |
template <typename T1, typename T2> | |
struct setvar_impl: abstract_expr | |
{ | |
T1 t1_; | |
T2 t2_; | |
setvar_impl(T1 t1, T2 t2): t1_(t1), t2_(t2) {} | |
virtual string description() const | |
{ | |
return "var " + t1_.description() + " = " + t2_.description() + ';'; | |
} | |
template <typename F1> | |
chain_op<setvar_impl<T1, T2>, F1> operator,(F1 f1) | |
{ | |
return chain_op<setvar_impl<T1, T2>, F1>(*this, f1); | |
} | |
}; | |
template <typename T> | |
struct val_impl: abstract_expr | |
{ | |
T val_; | |
val_impl(T t): val_(t) {} | |
virtual string description() const | |
{ | |
return toString(val_); | |
} | |
template <typename F1> | |
add_impl<val_impl<T>, F1> operator+(F1 f1) | |
{ | |
return add_impl<val_impl<T>, F1>(*this, f1); | |
} | |
}; | |
template <typename T> | |
val_impl<T>* val(T t) { return new val_impl<T>(t); } | |
struct var_impl: abstract_expr | |
{ | |
string varname_; | |
var_impl(const string& varname): varname_(varname) {} | |
template <typename T1> | |
setvar_impl<var_impl, val_impl<T1> > operator=(T1 t1) | |
{ | |
return setvar_impl<var_impl, val_impl<T1> >(*this, val_impl<T1>(t1)); | |
} | |
virtual string description() const { return varname_; } | |
}; | |
var_impl var(const string& name) { return var_impl(name); } | |
} | |
template <typename T1> | |
expr::add_impl<expr::val_impl<T1>, expr::var_impl> operator+(T1 t1, expr::var_impl t2) | |
{ | |
return expr::add_impl<expr::val_impl<T1>, expr::var_impl>(t1, t2); | |
} | |
template <typename T> | |
struct alert_impl: abstract_expr | |
{ | |
T message_; | |
alert_impl(const T& message): message_(message) {} | |
virtual string description() const | |
{ | |
return "alert(" + message_.description() + ");"; | |
} | |
template <typename F1> | |
chain_op<alert_impl<T>, F1> operator,(F1 f1) | |
{ | |
return chain_op<alert_impl<T>, F1>(*this, f1); | |
} | |
}; | |
template <typename T> | |
alert_impl<expr::val_impl<T> > alert(T t) | |
{ | |
return alert_impl<expr::val_impl<T> >(t); | |
} | |
struct debug: abstract_expr | |
{ | |
string message_; | |
debug(const string& message): message_(message) {} | |
virtual string description() const | |
{ | |
return "debug(\"" + message_ + "\");"; | |
} | |
template <typename F1> | |
chain_op<debug, F1> operator,(F1 f1) | |
{ | |
return chain_op<debug, F1>(*this, f1); | |
} | |
}; | |
struct function: object | |
{ | |
string name_; | |
string code_; | |
function() {} | |
function(const string& name): name_(name) {} | |
template <typename T> | |
function& operator[](const T& t) | |
{ | |
cout << __PRETTY_FUNCTION__ << endl; | |
code_ = "var _" + name_ + " = function " + name_ + "()\n" + | |
"{\n" + t.description() + "\n}"; | |
return *this; | |
} | |
virtual string description() const | |
{ | |
return code_; | |
} | |
}; | |
struct widgethide_impl: abstract_expr | |
{ | |
string name_; | |
widgethide_impl(const string& name): name_(name) {} | |
virtual string description() const | |
{ | |
return "document.getElementByName(\"" + name_ + "\").visible = false;"; | |
} | |
}; | |
struct widget: object | |
{ | |
string widgetName_; | |
widget(const string& widgetName): widgetName_(widgetName) {} | |
map<string /* event */, function /* code */> events_; | |
virtual string description() const | |
{ | |
string out = '<' + widgetName_ + ' '; | |
for (map<string, function>::const_iterator it(events_.begin()), | |
end(events_.end()); it != end; ++it) | |
{ | |
out += it->first + "=\"javascript:_" + it->second.name_ + "()\" "; | |
} | |
return out + '>'; | |
} | |
widgethide_impl hide() | |
{ | |
return widgethide_impl(widgetName_); | |
} | |
}; | |
struct button: widget | |
{ | |
button(): widget("button") {} | |
}; | |
struct application: object | |
{ | |
application() {} | |
list<widget*> dom_; | |
virtual string description() const | |
{ | |
string script, temp; | |
for (list<widget*>::const_iterator it(dom_.begin()), | |
end(dom_.end()); it != end; ++it) | |
{ | |
for (map<string, function>::const_iterator it2((*it)->events_.begin()), | |
end2((*it)->events_.end()); it2 != end2; ++it2) | |
{ | |
script += it2->second.description() + '\n'; | |
} | |
temp += (*it)->description(); | |
} | |
return script + '\n' + temp; | |
} | |
}; | |
template <typename T> | |
struct if_impl: abstract_expr | |
{ | |
T cond_; | |
string truestmt_; | |
string falsestmt_; | |
if_impl(T cond): cond_(cond) {} | |
template <typename F1> | |
if_impl& operator[](F1 f1) | |
{ | |
truestmt_ = f1.description(); | |
return *this; | |
} | |
virtual string description() const | |
{ | |
return "if (" + cond_.description() + ")\n" + | |
"{\n" + | |
truestmt_ + '\n' + | |
"}"; | |
} | |
}; | |
template <typename T> | |
if_impl<T> if_(T t) | |
{ | |
return if_impl<T>(t); | |
} | |
/* | |
* | |
* "asdf" + var("var1") | |
* expression_impl<const char*, var_impl> | |
* "\"asdf\" + var("var1") + "\"" | |
* | |
*/ | |
int main(int argc, char **argv) | |
{ | |
using namespace expr; | |
application app; | |
button* btn1 = new button; | |
btn1->events_["onclick"] = function("jp2gmd")[ | |
var("asdf1") = 5, | |
var("asdf2") = "hello world", | |
alert("asdf1 = " + var("asdf1")), | |
alert("asdf2 = " + var("asdf2")) | |
]; | |
button* btn2 = new button; | |
btn2->events_["onclick"] = function("dupa")[ | |
alert("Test"), | |
widget("btn1").hide(), | |
widget("btn2").hide() | |
]; | |
app.dom_.push_back(btn1); | |
app.dom_.push_back(btn2); | |
cout << app.description() << endl; | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment