fork download
  1. #include <cstdlib>
  2. #include <iostream>
  3. #include <string>
  4. #include <vector>
  5. #include <deque>
  6. #include <boost/variant.hpp>
  7. #include <boost/foreach.hpp>
  8. #define foreach BOOST_FOREACH
  9.  
  10.  
  11. namespace Doubleplusungood {
  12. #define DOUBLEPLUSUNGOOD_DEBUG false
  13. #define DOUBLEPLUSUNGOOD_DBGPRINT(cont) if(DOUBLEPLUSUNGOOD_DEBUG){std::cout << cont << std::endl;}
  14.  
  15. template<typename T> void dieWithError(T const cont, int const wordNum) {
  16. std::cout << "Error: " << cont << " at "<< wordNum + 1 << std::endl;
  17. exit(1);
  18. }
  19. namespace Engine {
  20. namespace Opera {
  21. enum Type {
  22. pop,
  23. dup,
  24. swap,
  25. lrot,
  26. rrot,
  27. beg,
  28. end,
  29. call,
  30. if_else,
  31. add,
  32. neg,
  33. less_than,
  34. print,
  35. input
  36. };
  37. struct stringize : std::string {
  38. stringize(Type e) {
  39. switch(e) {
  40. #define ENUM_STRINGIZE(elem) break;case elem:assign(#elem)
  41. ENUM_STRINGIZE(Opera::pop);
  42. ENUM_STRINGIZE(Opera::dup);
  43. ENUM_STRINGIZE(Opera::swap);
  44. ENUM_STRINGIZE(Opera::lrot);
  45. ENUM_STRINGIZE(Opera::rrot);
  46. ENUM_STRINGIZE(Opera::beg);
  47. ENUM_STRINGIZE(Opera::end);
  48. ENUM_STRINGIZE(Opera::call);
  49. ENUM_STRINGIZE(Opera::if_else);
  50. ENUM_STRINGIZE(Opera::add);
  51. ENUM_STRINGIZE(Opera::neg);
  52. ENUM_STRINGIZE(Opera::less_than);
  53. ENUM_STRINGIZE(Opera::print);
  54. ENUM_STRINGIZE(Opera::input);
  55. #undef ENUM_STRINGIZE
  56. break;default:assign("Undef");
  57. } // switch(e)
  58. } // ctor stringize
  59. }; // struct stringize
  60. } // namespace Oper
  61. namespace ErrCode {
  62. enum Type {
  63. normalExit,
  64. stackShortage,
  65. expectedInt,
  66. expectedBlock,
  67. unclosedBlock,
  68. outOfRange,
  69. unknownCommand
  70. };
  71. struct stringize : std::string {
  72. stringize(Type e) {
  73. switch(e) {
  74. #define ENUM_STRINGIZE(elem) break;case elem:assign(#elem)
  75. ENUM_STRINGIZE(ErrCode::normalExit);
  76. ENUM_STRINGIZE(ErrCode::stackShortage);
  77. ENUM_STRINGIZE(ErrCode::expectedInt);
  78. ENUM_STRINGIZE(ErrCode::expectedBlock);
  79. ENUM_STRINGIZE(ErrCode::unclosedBlock);
  80. ENUM_STRINGIZE(ErrCode::outOfRange);
  81. ENUM_STRINGIZE(ErrCode::unknownCommand);
  82. #undef ENUM_STRINGIZE
  83. break;default:assign("Undef");
  84. } // switch(e)
  85. } // ctor stringize
  86. }; // struct stringize
  87. } // namespace ErrCode
  88.  
  89.  
  90. struct Address{
  91. int datum;
  92. Address& operator=(int const i){datum = i;return *this;}
  93. };
  94.  
  95. typedef boost::variant<int, Opera::Type> CodeWord;
  96. typedef std::vector<CodeWord> Source;
  97. typedef boost::variant<int, Address> MemDatum;
  98.  
  99. class Interpreter {
  100. private:
  101. std::deque<Address> callStack;
  102. public: std::deque<MemDatum> memStack; private:
  103. Address crntAddress;
  104.  
  105. ErrCode::Type applyOpera(Opera::Type op) {
  106. switch(op) {
  107. case Opera::pop: {
  108. if(memStack.empty()){return ErrCode::stackShortage;}
  109. memStack.pop_back();
  110. break;
  111. }
  112.  
  113. case Opera::dup: {
  114. if(memStack.empty()){return ErrCode::stackShortage;}
  115. memStack.push_back(memStack.back());
  116. break;
  117. }
  118.  
  119. case Opera::swap: {
  120. if(memStack.size() < 2){return ErrCode::stackShortage;}
  121. MemDatum const t1 = memStack.back();
  122. memStack.pop_back();
  123. MemDatum const t2 = memStack.back();
  124. memStack.pop_back();
  125. memStack.push_back(t1);
  126. memStack.push_back(t2);
  127. break;
  128. }
  129.  
  130. case Opera::lrot: {
  131. memStack.push_back(memStack.front());
  132. memStack.pop_front();
  133. break;
  134. }
  135.  
  136. case Opera::rrot: {
  137. memStack.push_front(memStack.back());
  138. memStack.pop_back();
  139. break;
  140. }
  141.  
  142. case Opera::add: {
  143. if(memStack.size() < 2){return ErrCode::stackShortage;}
  144. if(memStack.back().which() != 0) {return ErrCode::expectedInt;}
  145. int const i = boost::get<int>(memStack.back());
  146. memStack.pop_back();
  147.  
  148. if(memStack.back().which() != 0) {return ErrCode::expectedInt;}
  149. int const j = boost::get<int>(memStack.back());
  150. memStack.pop_back();
  151. DOUBLEPLUSUNGOOD_DBGPRINT(i + j);
  152. memStack.push_back(i + j);
  153. break;
  154. }
  155.  
  156. case Opera::neg: {
  157. if(memStack.empty()){return ErrCode::stackShortage;}
  158. if(memStack.back().which() != 0){return ErrCode::expectedInt;}
  159. int const i = boost::get<int>(memStack.back());
  160. memStack.pop_back();
  161. memStack.push_back(i * -1);
  162. break;
  163. }
  164. case Opera::less_than: {
  165. if(memStack.size() < 2){return ErrCode::stackShortage;}
  166. if(memStack.back().which() != 0) {return ErrCode::expectedInt;}
  167. int const i = boost::get<int>(memStack.back());
  168. memStack.pop_back();
  169.  
  170. if(memStack.back().which() != 0) {return ErrCode::expectedInt;}
  171. int const j = boost::get<int>(memStack.back());
  172. memStack.pop_back();
  173. memStack.push_back(((j < i)? 1: 0));
  174. break;
  175. }
  176. case Opera::print: {
  177. if(memStack.empty()){return ErrCode::stackShortage;}
  178. if(memStack.back().which() != 0) {return ErrCode::expectedInt;}
  179. int const cont = boost::get<int>(memStack.back());
  180.  
  181. if(-128 <= cont && cont <= 127) {
  182. std::cout << static_cast<char>(cont) << std::flush;
  183. } else {
  184. // std::cout << cont << std::flush;
  185. return(ErrCode::outOfRange); // Err
  186. }
  187. memStack.pop_back();
  188. break;
  189. }
  190. case Opera::input: {
  191. char c;
  192. std::cin >> c;
  193. memStack.push_back(static_cast<int>(c));
  194. break;
  195. }
  196. default:
  197. dieWithError(ErrCode::stringize(ErrCode::unknownCommand), crntAddress.datum);// Err
  198. break;
  199. } // switch(op)
  200. return ErrCode::normalExit;
  201. } // applyOpera
  202.  
  203. public:
  204.  
  205. void interpret(Source const& src) {
  206. DOUBLEPLUSUNGOOD_DBGPRINT("src.size: " << src.size());
  207. for(crntAddress.datum = 0; src.size() > crntAddress.datum; crntAddress.datum++){
  208. DOUBLEPLUSUNGOOD_DBGPRINT("----------");
  209. if(DOUBLEPLUSUNGOOD_DEBUG) {
  210. std::cout << "[ ";
  211. foreach(MemDatum const& e, memStack) {
  212. if(e.which() == 0){
  213. std::cout << boost::get<int>(e) << ' ';
  214. } else {
  215. std::cout << "<Addr> ";
  216. }
  217. }
  218. std::cout << "]" << std::endl;
  219. }
  220.  
  221. CodeWord const& word = src.at(crntAddress.datum);
  222. switch(word.which()) {
  223. case 0: {
  224. DOUBLEPLUSUNGOOD_DBGPRINT("<=" << boost::get<int>(word));
  225. memStack.push_back(boost::get<int>(word));
  226. break;
  227. }
  228.  
  229. case 1: {
  230. DOUBLEPLUSUNGOOD_DBGPRINT("<=" << Opera::stringize(boost::get<Opera::Type>(word)));
  231. Opera::Type const opera = boost::get<Opera::Type>(src.at(crntAddress.datum));
  232. switch(opera) {
  233. case Opera::end: {
  234. crntAddress = callStack.back();
  235. callStack.pop_back();
  236. break;
  237. }
  238.  
  239. case Opera::call: {
  240. if(memStack.empty()) {
  241. dieWithError(ErrCode::stringize(ErrCode::stackShortage), crntAddress.datum);// Err
  242. }
  243. if(memStack.back().which() != 1){
  244. dieWithError(ErrCode::stringize(ErrCode::expectedBlock), crntAddress.datum);// Err
  245. return;
  246. }
  247. callStack.push_back(crntAddress);
  248. crntAddress = boost::get<Address>(memStack.back());
  249. memStack.pop_back();
  250. break;
  251. }
  252. case Opera::if_else: {
  253. int cond;
  254. Address t;
  255. Address f;
  256. if(memStack.size() < 3) {
  257. dieWithError(ErrCode::stringize(ErrCode::stackShortage), crntAddress.datum);// Err
  258. return;
  259. }
  260. if(memStack.back().which() != 0){
  261. dieWithError(ErrCode::stringize(ErrCode::stackShortage), crntAddress.datum);// Err
  262. return;
  263. }
  264. cond = boost::get<int>(memStack.back());
  265. memStack.pop_back();
  266.  
  267. if(memStack.back().which() != 1){
  268. dieWithError(ErrCode::stringize(ErrCode::expectedBlock), crntAddress.datum); // Err
  269. return;
  270. }
  271. t = boost::get<Address>(memStack.back());
  272. memStack.pop_back();
  273.  
  274. if(memStack.back().which() != 1){
  275. dieWithError(ErrCode::stringize(ErrCode::expectedBlock), crntAddress.datum); // Err
  276. return;
  277. }
  278. f = boost::get<Address>(memStack.back());
  279. memStack.pop_back();
  280.  
  281. callStack.push_back(crntAddress);
  282. crntAddress = (cond)? t: f;
  283. break;
  284. }
  285.  
  286. case Opera::beg: {
  287. memStack.push_back(crntAddress);
  288.  
  289. int counter = 1;
  290. while(counter != 0) {
  291. if(crntAddress.datum >= src.size()) {
  292. dieWithError(ErrCode::stringize(ErrCode::unclosedBlock), crntAddress.datum);
  293. }
  294. crntAddress.datum++;
  295. CodeWord const& word = src.at(crntAddress.datum);
  296. if(word.which() == 1) {
  297. if(boost::get<Opera::Type>(word) == Opera::end) {
  298. counter--;
  299. }
  300. if(boost::get<Opera::Type>(word) == Opera::beg) {
  301. counter++;
  302. }
  303. }
  304. }
  305. break;
  306. }
  307. default: {
  308. ErrCode::Type const operaRes = applyOpera(opera);
  309. if(operaRes != ErrCode::normalExit) {
  310. dieWithError(ErrCode::stringize(operaRes), crntAddress.datum);
  311. }
  312. break;
  313. }
  314. } // switch(opera)
  315. break;
  316. }
  317.  
  318. default:
  319. dieWithError(ErrCode::stringize(ErrCode::unknownCommand), crntAddress.datum); // Err
  320. break;
  321. } // switch(word)
  322. } // for
  323. std::cout << std::endl;
  324. } // interpret
  325. }; // Interpreter
  326.  
  327. class Decoder {
  328. private:
  329. /*
  330. ldp : 後置++
  331. fdp : 前置++
  332. fsp : 前置1項+
  333. lsp : 2項+
  334. */
  335. /* state
  336. 0 : 初期状態
  337. 1 : ldp後
  338. 2 : fdp、fsp後
  339. 3 : lsp後
  340. */
  341. int state;
  342. int ldpCounter;
  343. int lspCounter;
  344. int fpCounter;
  345. int fpNum;
  346. Source & source;
  347.  
  348. void initState() {
  349. state = 0;
  350. ldpCounter = 0;
  351. lspCounter = 0;
  352. fpCounter = 0;
  353. fpNum = 0;
  354. }
  355.  
  356. Opera::Type convOpera() const{
  357. switch(fpCounter) {
  358. case 0: {
  359. break;
  360. }
  361. case 1: { // +(0) , ++(1)
  362. switch(fpNum) {
  363. case 0: {
  364. return Opera::beg; // +
  365. }
  366. case 1: {
  367. return Opera::end; // ++
  368. }
  369. }
  370. break;
  371. }
  372. case 2: { // + +(0) , ++ +(1) ,+ ++(2) , ++ ++(3)
  373. switch(fpNum) {
  374. case 0: {
  375. return Opera::dup; // + +
  376. }
  377. case 1: {
  378. return Opera::lrot; // ++ +
  379. }
  380. case 2: {
  381. return Opera::rrot; // + ++
  382. }
  383. case 3: {
  384. return Opera::swap; // ++ ++
  385. }
  386. }
  387. }
  388. case 3: { // + + +(0) , ++ + +(1) , + ++ + (2) , ++ ++ + (3) , + + ++(4) , ++ + ++(5) , + ++ ++(6) , ++ ++ ++(7)
  389. switch(fpNum) {
  390. case 0: {
  391. return Opera::call; // + + +
  392. }
  393. case 1: {
  394. return Opera::if_else; // ++ + +
  395. }
  396. case 2: {
  397. return Opera::add; // + ++ +
  398. }
  399. case 3: {
  400. return Opera::neg; // ++ ++ +
  401. }
  402. case 4: {
  403. return Opera::print; // + + ++
  404. }
  405. case 5: {
  406. return Opera::input; // ++ + ++
  407. }
  408. case 6: {
  409. return Opera::less_than; // + ++ ++
  410. }
  411. case 7: {
  412. return Opera::pop; // ++ ++ ++
  413. }
  414. }
  415. }
  416. }
  417. }
  418. void convMidCode() {
  419. DOUBLEPLUSUNGOOD_DBGPRINT("fpNum: " << fpNum << "fpCtr: " << fpCounter << "ldpCtr: " << ldpCounter << "lspCtr: " << lspCounter);
  420. switch(lspCounter) {
  421. case 0: {
  422. source.push_back(convOpera());
  423. break;
  424. }
  425. case 1: {
  426. source.push_back(fpNum << ((ldpCounter - 1) * 4));
  427. break;
  428. }
  429. default: {
  430. // Err
  431. break;
  432. }
  433. }
  434. initState();
  435. }
  436.  
  437.  
  438. public:
  439. void putLdp() {
  440. if(state > 1){convMidCode();}
  441. ldpCounter++;
  442. state = 1;
  443. }
  444. void putLsp() {
  445. if(state > 3){convMidCode();}
  446. lspCounter++;
  447. state = 3;
  448. }
  449. void putFdp() {
  450. if(state > 2){convMidCode();}
  451. fpNum <<= 1;
  452. fpNum += 1;
  453. fpCounter++;
  454. state = 2;
  455. }
  456. void putFsp() {
  457. if(state > 2){convMidCode();}
  458. fpNum <<= 1;
  459. fpCounter++;
  460. state = 2;
  461. }
  462. void finishDecode(){convMidCode();}
  463. Decoder(Source& src): source(src){initState();}
  464. }; // class Decoder
  465.  
  466. }
  467.  
  468.  
  469. class C_ {
  470. private:
  471. Engine::Decoder decoder;
  472. Engine::Source source;
  473. public:
  474. C_& operator++(int) {
  475. decoder.putLdp();
  476. return *this;
  477. }
  478. C_& operator++() {
  479. decoder.putFdp();
  480. return *this;
  481. }
  482. C_& operator+(C_&) {
  483. decoder.putLsp();
  484. return *this;
  485. }
  486. C_& operator+() {
  487. decoder.putFsp();
  488. return *this;
  489. }
  490. C_(): decoder(source){}
  491. ~C_(){
  492. decoder.finishDecode();
  493. Engine::Interpreter interpreter;
  494. interpreter.interpret(source);
  495. }
  496. };
  497. #undef DOUBLEPLUSUNGOOD_DEBUG
  498. #undef DOUBLEPLUSUNGOOD_DBGPRINT
  499. }
  500.  
  501.  
  502. int main() {
  503. Doubleplusungood::C_ C;
  504.  
  505. +C++; + + ++C++++ + C; + ++C++++ + C; + ++ + C++; + ++ + C++; + + ++ C++;
  506. ++C++; + ++C++; + + + ++ C++ + C; + + ++C++++ + C; + ++ + C++; + + ++ C++;
  507. ++ + ++C++ + C; ++ +C++; + +C++; + ++C++; + + +C++; + + ++ ++C++ + C; ++ +C
  508. ++; + +C++; + ++C++; + + +C++; + + ++ ++C++ + C; ++ +C++; + +C++; + ++C++;
  509. + + +C++; ++ ++ ++ ++C++ + C; ++ +C++; + +C++; + ++C++; + + +C++; + + ++ ++
  510. C++ + C; + ++ C++++ + C; + ++ + C++; + + ++ C++; + ++ C++++ + C; + + ++ C++;
  511. ++ ++ ++ C++ + C; ++ + ++ C++++ + C; + ++ + C++; + + ++ C++; ++ ++ ++ ++C++
  512. + C; ++ +C++; + +C++; + ++C++; + + +C++; ++C++++ + C; + ++C++ + C;+ ++ +C++;
  513. ++ +C++; + +C++; + ++C++; + + +C++; + + ++ ++C++ + C; ++ +C++; + +C++; + ++C
  514. ++; + + +C++; + + ++C++ + C; ++ +C++; + +C++; + ++C++; + + +C++; ++ C++ + C;
  515. + ++ C++++ + C; + ++ + C++; + + ++ C++;
  516.  
  517. return 0;
  518. }
  519.  
Success #stdin #stdout 0.01s 2936KB
stdin
Standard input is empty
stdout
Hello, World!