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. 1~9までを出力するコード
  506. 9
  507. begin
  508.  begin
  509.   lrot
  510.   begin
  511.   lrot
  512.   pop
  513.   pop
  514.   end
  515.   swap
  516.   begin
  517.   dup
  518.   call
  519.   end
  520.   swap
  521.  
  522.   dup
  523.   neg
  524.   10
  525.   add
  526.   48
  527.   add
  528.   print
  529.   32
  530.   print
  531.   1
  532.   neg
  533.   add
  534.   dup
  535.   rrot
  536.   if-else
  537.  end
  538.  dup
  539.  rrot
  540.  call
  541. end
  542. call
  543.  */
  544.  
  545. ++ + + ++C++ + C;
  546. +C++;
  547. +C++;
  548. ++ +C++;
  549. +C++;
  550. ++ +C++;
  551. ++ ++ ++C++;
  552. ++ ++ ++C++;
  553. ++C++;
  554. ++ ++C++;
  555. +C++;
  556. + +C++;
  557. + + +C++;
  558. ++C++;
  559. ++ ++C++;
  560. // loop-body
  561. + +C++;
  562. ++ ++ +C++;
  563. + ++ + ++C++ + C;
  564. + ++ +C++;
  565. ++ ++C++ ++ + C;
  566. + ++ +C++;
  567. + + ++C++;
  568. + ++C++ ++ + C;
  569. + + ++C++;
  570. //end
  571. ++C++ + C;
  572. ++ ++ +C++;
  573. + ++ +C++;
  574. + +C++;
  575. + ++C++;
  576. ++ + +C++;
  577. ++C++;
  578. + +C++;
  579. + + +C++;
  580. ++C++;
  581. + + +C++;
  582.  
  583. return 0;
  584. }
  585.  
Success #stdin #stdout 0.01s 2980KB
stdin
Standard input is empty
stdout
1 2 3 4 5 6 7 8 9