#include <string>
#include <stack>
#include <map>
#include <iostream>
typedef long val_t;
typedef std::map<std::string, val_t> frame_t;
typedef std::stack<frame_t> stack_t;
stack_t stack;
frame_t globals;
val_t NOWHERE, arg1_tmp, arg2_tmp, arg3_tmp, result_tmp;
#define BEGIN_FUNCTION(name) \
goto end##name; \
name: ;
#define END_FUNCTION(name) \
RETURN(0); \
end##name: ;
#define FRAME (stack.top())
#define LOCAL(name) (FRAME[#name])
#define GLOBAL(name) (globals[#name])
#define SPEC(name) (FRAME[":" #name])
#define ARG1 SPEC(ARG1)
#define ARG2 SPEC(ARG2)
#define ARG3 SPEC(ARG3)
#define _RET SPEC(RET)
#define _RES SPEC(RES)
#define RETURN(val) \
do { \
_RES = val; \
goto *(void*)_RET; \
} while(0);
#define CALL_START stack.push(frame_t())
#define CONCAT(x,y) x##y
#define CALL_END(name, uniqueid) \
_RET = (val_t) &&CONCAT(here, uniqueid); \
goto name; \
CONCAT(here, uniqueid): ;
#define PUT_RESULT(where) \
result_tmp = _RES; \
stack.pop(); \
where = result_tmp;
#define CALL0(func, out) \
CALL_START; \
CALL_END(func, __LINE__); \
PUT_RESULT(out);
#define CALL1(func, arg, out) \
arg1_tmp = arg; \
CALL_START; \
ARG1 = arg1_tmp; \
CALL_END(func, __LINE__); \
PUT_RESULT(out);
#define CALL2(func, arg1, arg2, out) \
arg1_tmp = arg1; \
arg2_tmp = arg2; \
CALL_START; \
ARG1 = arg1_tmp; \
ARG2 = arg2_tmp; \
CALL_END(func, __LINE__); \
PUT_RESULT(out);
#define CALL3(func, arg1, arg2, arg3, out) \
arg1_tmp = arg1; \
arg2_tmp = arg2; \
arg3_tmp = arg3; \
CALL_START; \
ARG1 = arg1_tmp; \
ARG2 = arg2_tmp; \
ARG3 = arg3_tmp; \
CALL_END(func, __LINE__); \
PUT_RESULT(out);
int main() {
BEGIN_FUNCTION(fac);
LOCAL(f) = 1;
while(ARG1 > 0) {
LOCAL(f) *= ARG1--;
}
RETURN(LOCAL(f));
END_FUNCTION(fac);
BEGIN_FUNCTION(fibs);
if(ARG1 <= 0) RETURN(0);
if(ARG1 == 1) RETURN(1);
CALL1(fibs, ARG1 - 1, LOCAL(n1));
CALL1(fibs, ARG1 - 2, LOCAL(n2));
RETURN(LOCAL(n1) + LOCAL(n2));
END_FUNCTION(fibs);
CALL1(fac, 5, GLOBAL(fac5));
CALL1(fibs, 10, GLOBAL(fibs10));
BEGIN_FUNCTION(print);
std::cout << "VALUE: " << ARG1 << std::endl;
END_FUNCTION(print);
BEGIN_FUNCTION(print_a);
std::cout << "A: " << GLOBAL(a) << std::endl;
END_FUNCTION(print_a);
CALL1(print, GLOBAL(fac5), NOWHERE); // 120
GLOBAL(a) = GLOBAL(fibs10); // 55
CALL0(print_a, NOWHERE);
}
I2luY2x1ZGUgPHN0cmluZz4KI2luY2x1ZGUgPHN0YWNrPgojaW5jbHVkZSA8bWFwPgojaW5jbHVkZSA8aW9zdHJlYW0+Cgp0eXBlZGVmIGxvbmcgdmFsX3Q7CnR5cGVkZWYgc3RkOjptYXA8c3RkOjpzdHJpbmcsIHZhbF90PiBmcmFtZV90Owp0eXBlZGVmIHN0ZDo6c3RhY2s8ZnJhbWVfdD4gc3RhY2tfdDsKCnN0YWNrX3Qgc3RhY2s7CmZyYW1lX3QgZ2xvYmFsczsKCnZhbF90IE5PV0hFUkUsIGFyZzFfdG1wLCBhcmcyX3RtcCwgYXJnM190bXAsIHJlc3VsdF90bXA7CgojZGVmaW5lIEJFR0lOX0ZVTkNUSU9OKG5hbWUpIFwKICBnb3RvIGVuZCMjbmFtZTsgXAogIG5hbWU6IDsKCiNkZWZpbmUgRU5EX0ZVTkNUSU9OKG5hbWUpIFwKICBSRVRVUk4oMCk7IFwKICBlbmQjI25hbWU6IDsKCiNkZWZpbmUgRlJBTUUgKHN0YWNrLnRvcCgpKQojZGVmaW5lIExPQ0FMKG5hbWUpIChGUkFNRVsjbmFtZV0pCiNkZWZpbmUgR0xPQkFMKG5hbWUpIChnbG9iYWxzWyNuYW1lXSkKI2RlZmluZSBTUEVDKG5hbWUpIChGUkFNRVsiOiIgI25hbWVdKQojZGVmaW5lIEFSRzEgU1BFQyhBUkcxKQojZGVmaW5lIEFSRzIgU1BFQyhBUkcyKQojZGVmaW5lIEFSRzMgU1BFQyhBUkczKQojZGVmaW5lIF9SRVQgU1BFQyhSRVQpCiNkZWZpbmUgX1JFUyBTUEVDKFJFUykKCiNkZWZpbmUgUkVUVVJOKHZhbCkgXAogIGRvIHsgXAogICAgX1JFUyA9IHZhbDsgXAogICAgZ290byAqKHZvaWQqKV9SRVQ7IFwKICB9IHdoaWxlKDApOwoKI2RlZmluZSBDQUxMX1NUQVJUIHN0YWNrLnB1c2goZnJhbWVfdCgpKQoKI2RlZmluZSBDT05DQVQoeCx5KSB4IyN5CgojZGVmaW5lIENBTExfRU5EKG5hbWUsIHVuaXF1ZWlkKSBcCiAgX1JFVCA9ICh2YWxfdCkgJiZDT05DQVQoaGVyZSwgdW5pcXVlaWQpOyBcCiAgZ290byBuYW1lOyBcCiAgQ09OQ0FUKGhlcmUsIHVuaXF1ZWlkKTogOwoKI2RlZmluZSBQVVRfUkVTVUxUKHdoZXJlKSBcCiAgcmVzdWx0X3RtcCA9IF9SRVM7IFwKICBzdGFjay5wb3AoKTsgXAogIHdoZXJlID0gcmVzdWx0X3RtcDsKCiNkZWZpbmUgQ0FMTDAoZnVuYywgb3V0KSBcCiAgQ0FMTF9TVEFSVDsgXAogIENBTExfRU5EKGZ1bmMsIF9fTElORV9fKTsgXAogIFBVVF9SRVNVTFQob3V0KTsKCiNkZWZpbmUgQ0FMTDEoZnVuYywgYXJnLCBvdXQpIFwKICBhcmcxX3RtcCA9IGFyZzsgXAogIENBTExfU1RBUlQ7IFwKICBBUkcxID0gYXJnMV90bXA7IFwKICBDQUxMX0VORChmdW5jLCBfX0xJTkVfXyk7IFwKICBQVVRfUkVTVUxUKG91dCk7CgojZGVmaW5lIENBTEwyKGZ1bmMsIGFyZzEsIGFyZzIsIG91dCkgXAogIGFyZzFfdG1wID0gYXJnMTsgXAogIGFyZzJfdG1wID0gYXJnMjsgXAogIENBTExfU1RBUlQ7IFwKICBBUkcxID0gYXJnMV90bXA7IFwKICBBUkcyID0gYXJnMl90bXA7IFwKICBDQUxMX0VORChmdW5jLCBfX0xJTkVfXyk7IFwKICBQVVRfUkVTVUxUKG91dCk7CgojZGVmaW5lIENBTEwzKGZ1bmMsIGFyZzEsIGFyZzIsIGFyZzMsIG91dCkgXAogIGFyZzFfdG1wID0gYXJnMTsgXAogIGFyZzJfdG1wID0gYXJnMjsgXAogIGFyZzNfdG1wID0gYXJnMzsgXAogIENBTExfU1RBUlQ7IFwKICBBUkcxID0gYXJnMV90bXA7IFwKICBBUkcyID0gYXJnMl90bXA7IFwKICBBUkczID0gYXJnM190bXA7IFwKICBDQUxMX0VORChmdW5jLCBfX0xJTkVfXyk7IFwKICBQVVRfUkVTVUxUKG91dCk7CgppbnQgbWFpbigpIHsKCiAgQkVHSU5fRlVOQ1RJT04oZmFjKTsKICAgIExPQ0FMKGYpID0gMTsKICAgIHdoaWxlKEFSRzEgPiAwKSB7CiAgICAgIExPQ0FMKGYpICo9IEFSRzEtLTsKICAgIH0KICAgIFJFVFVSTihMT0NBTChmKSk7CiAgRU5EX0ZVTkNUSU9OKGZhYyk7CiAgCiAgQkVHSU5fRlVOQ1RJT04oZmlicyk7CiAgICBpZihBUkcxIDw9IDApIFJFVFVSTigwKTsKICAgIGlmKEFSRzEgPT0gMSkgUkVUVVJOKDEpOwogICAgCiAgICBDQUxMMShmaWJzLCBBUkcxIC0gMSwgTE9DQUwobjEpKTsKICAgIENBTEwxKGZpYnMsIEFSRzEgLSAyLCBMT0NBTChuMikpOwogICAgUkVUVVJOKExPQ0FMKG4xKSArIExPQ0FMKG4yKSk7CiAgRU5EX0ZVTkNUSU9OKGZpYnMpOwogIAogIENBTEwxKGZhYywgNSwgR0xPQkFMKGZhYzUpKTsKICBDQUxMMShmaWJzLCAxMCwgR0xPQkFMKGZpYnMxMCkpOwogIAogIEJFR0lOX0ZVTkNUSU9OKHByaW50KTsKICAgIHN0ZDo6Y291dCA8PCAiVkFMVUU6ICIgPDwgQVJHMSA8PCBzdGQ6OmVuZGw7CiAgRU5EX0ZVTkNUSU9OKHByaW50KTsKCiAgQkVHSU5fRlVOQ1RJT04ocHJpbnRfYSk7CiAgICBzdGQ6OmNvdXQgPDwgIkE6ICIgPDwgR0xPQkFMKGEpIDw8IHN0ZDo6ZW5kbDsKICBFTkRfRlVOQ1RJT04ocHJpbnRfYSk7CiAgCiAgQ0FMTDEocHJpbnQsIEdMT0JBTChmYWM1KSwgTk9XSEVSRSk7IC8vIDEyMAogIEdMT0JBTChhKSA9IEdMT0JBTChmaWJzMTApOyAvLyA1NQogIENBTEwwKHByaW50X2EsIE5PV0hFUkUpOwogIAp9Cg==