fork(20) download
  1. class String
  2. def is_digit?
  3. !!Float(self) rescue false
  4. end
  5. end
  6.  
  7. class BFCompiler
  8. # 0 | stack | 0 | 10 tmp cells| 0 | 3 cmp cell | 0 | ax | bx | cx | dx | 0 | 0 | 0 | 0 | 254 buffer | arrays... | strings... |
  9. # start pos ^ index of array ^ ^
  10.  
  11. attr_accessor :registers
  12.  
  13. def addRegister(name)
  14. @registers[name]=@regnow
  15. @regnow+=1
  16. end
  17.  
  18. def initialize
  19. @program = ["<<<->>>"] #init stack
  20. @pos=0
  21. # registers offset
  22. @ro=16
  23. @eqR=@ro-4 # equal flag
  24. @ltR=@ro-3 # little flag
  25. @gtR=@ro-2 # great flag
  26. @regnow=@ro
  27. @registers={}
  28. addRegister "ax"
  29. addRegister "bx"
  30. addRegister "cx"
  31. addRegister "dx"
  32. #addRegister "sp"
  33. @indEl = @regnow+2 # index of array
  34. @arrays = []
  35. @total=256
  36. end
  37.  
  38. def compileBf
  39. i=0
  40. @total = @total ==256? 0: @total
  41. "Min cells used:#{@total+@indEl}\n" + @program.join("").split(//).collect { |ch|
  42. i+=1
  43. if i>=80
  44. i=0
  45. ch+"\n"
  46. else
  47. ch
  48. end
  49. }.join("")
  50. end
  51.  
  52. def gotoR(reg)
  53. @program << (reg-@pos>0? ">" : "<")*(reg-@pos).abs
  54. @pos=reg
  55. end
  56.  
  57. def addNumToR(reg,num)
  58. gotoR(reg)
  59. @program << "+"*num
  60. end
  61.  
  62. def subNumFromR(reg,num)
  63. gotoR(reg)
  64. @program << "-"*num
  65. end
  66.  
  67. def moveRToR(reg1,reg2)
  68. startCycle(reg1)
  69. subNumFromR(reg1,1)
  70. addNumToR(reg2,1)
  71. endCycle(reg1)
  72. end
  73.  
  74. def outR(reg)
  75. gotoR(reg)
  76. @program << "."
  77. end
  78.  
  79. def inputR(reg)
  80. gotoR(reg)
  81. @program << ","
  82. end
  83.  
  84. def startCycle(reg)
  85. gotoR(reg)
  86. @program << "["
  87. end
  88.  
  89. def endCycle(reg)
  90. gotoR(reg)
  91. @program << "]"
  92. end
  93.  
  94. def inc(reg)
  95. addNumToR(reg,1)
  96. end
  97.  
  98. def dec(reg)
  99. subNumFromR(reg,1)
  100. end
  101.  
  102. def zeroR(reg)
  103. startCycle(reg)
  104. dec reg
  105. endCycle(reg)
  106. end
  107.  
  108. def setR(reg,num)
  109. zeroR(reg)
  110. addNumToR(reg,num)
  111. end
  112.  
  113. def copyR(reg2,reg1)
  114. #copy reg1 to reg2
  115. zeroR(reg2)
  116. zeroR(0)
  117. startCycle(reg1)
  118. dec reg1
  119. inc reg2
  120. inc 0
  121. endCycle(reg1)
  122. moveRToR(0,reg1)
  123. end
  124.  
  125. def addRToR(reg1,reg2)
  126. # reg1=reg1+reg2
  127. zeroR(0)
  128. startCycle(reg2)
  129. dec reg2
  130. inc reg1
  131. inc 0
  132. endCycle(reg2)
  133. moveRToR(0,reg2)
  134. end
  135.  
  136. def subRFromR(reg1,reg2)
  137. # reg1= reg1-reg2
  138. zeroR(0)
  139. startCycle(reg2)
  140. dec reg2
  141. dec reg1
  142. inc 0
  143. endCycle(reg2)
  144. moveRToR(0,reg2)
  145. end
  146.  
  147. def pushNumToStack(num)
  148. setR(0,num)
  149. @program << "-<<[<]<[->+<]<<[-]>+>>[>]>[-<<[<]<+>>[>]>]"
  150. end
  151.  
  152. def pushRToStack(reg)
  153. copyR(1,reg)
  154. moveRToR(1,0)
  155. gotoR(0)
  156. @program << "-<<[<]<[->+<]<<[-]>+>>[>]>[-<<[<]<+>>[>]>]"
  157. end
  158.  
  159. def popNumToR(reg)
  160. zeroR(0)
  161. @program << "+<<[<]<-[->>[>]>+<<[<]<]>>[-<+>]>[>]>"
  162. zeroR(reg)
  163. moveRToR(0,reg)
  164. end
  165.  
  166. def mulRonR(reg1,reg2)
  167. zeroR(0)
  168. zeroR(1)
  169. startCycle(reg1)
  170. inc 1
  171. dec reg1
  172. endCycle(reg1)
  173. startCycle(1)
  174. startCycle(reg2)
  175. inc reg1
  176. inc 0
  177. dec reg2
  178. endCycle(reg2)
  179. startCycle(0)
  180. inc reg2
  181. dec 0
  182. endCycle(0)
  183. dec 1
  184. endCycle(1)
  185. end
  186.  
  187. def divRonR(reg1,reg2)
  188. zeroR(0)
  189. zeroR(1)
  190. zeroR(2)
  191. zeroR(3)
  192. zeroR(4)
  193. copyR(1,reg1)
  194. copyR(2,reg2)
  195. # divmod algorithm
  196. gotoR(1)
  197. @program << "[->-[>+>>]>[+[-<+>]>+>>]<<<<<]"
  198. copyR(reg2,3)
  199. copyR(reg1,4)
  200. end
  201.  
  202. def cmpRR(reg1,reg2)
  203. copyR(1,reg1)
  204. copyR(2,reg2)
  205. zeroR(0)
  206. setR(@eqR,1)
  207. setR(@ltR,1)
  208. setR(@gtR,2)
  209. startCycle(2)
  210. subNumFromR(2,1)
  211. startCycle(1)
  212. inc @ltR
  213. moveRToR(1,0)
  214. endCycle(1)
  215. moveRToR(0,1)
  216. dec @ltR
  217. dec 1
  218. endCycle(2)
  219. startCycle(1)
  220. inc @eqR
  221. zeroR(1)
  222. endCycle(1)
  223. dec @eqR
  224. startCycle(@ltR)
  225. dec @gtR
  226. moveRToR(@ltR,0)
  227. endCycle(@ltR)
  228. moveRToR(0,@ltR)
  229. startCycle(@eqR)
  230. dec @gtR
  231. moveRToR(@eqR,0)
  232. endCycle(@eqR)
  233. moveRToR(0,@eqR)
  234. end
  235.  
  236. def declareArray(name,size)
  237. @arrays << {:name => name , :size => size+1 }
  238. @total+=size+1
  239. end
  240.  
  241. def getKnownArrElem(name,index,reg)
  242. # set reg to name[index]
  243. toArr=256
  244. i=0
  245. while @arrays[i][:name]!=name
  246. toArr+=@arrays[i][:size]
  247. i+=1
  248. end
  249. toArr+=index
  250. copyR(reg,@indEl+toArr)
  251. end
  252.  
  253. def getUnknownArrElem(name,regindex,reg)
  254. # set reg to name[regindex]
  255. toArr=256
  256. i=0
  257. while @arrays[i][:name]!=name
  258. toArr+=@arrays[i][:size]
  259. i+=1
  260. end
  261. copyR(@indEl,regindex)
  262. copyR(@indEl+1,regindex)
  263. gotoR(@indEl)
  264. # copy indEl and indEl+1 on regindex register forward
  265. @program << "[>[->+<]<[->+<]>-]"
  266. # go to arr element
  267. @program << ">"*toArr
  268. # copy arr element
  269. @program << "[-" << "<"*toArr <<"+<+>" << ">"*toArr << "]"
  270. # restore arr element
  271. @program << "<"*toArr << "<[->" << ">"*toArr << "+" << "<"*toArr << "<]"
  272. # copy indEl and indEl+1 back
  273. @program << ">>[<[-<+>]>[-<+>]<-]<"
  274. # fast move
  275. @pos = @indEl
  276. startCycle(@indEl)
  277. dec @indEl
  278. inc reg
  279. endCycle(@indEl)
  280. end
  281.  
  282. def setKnownArrElemWithR(name,index,reg)
  283. # set name[index] to reg
  284. toArr=256
  285. i=0
  286. while @arrays[i][:name]!=name
  287. toArr+=@arrays[i][:size]
  288. i+=1
  289. end
  290. toArr+=index
  291. copyR(@indEl+toArr,reg)
  292. end
  293.  
  294. def setKnownArrElemWithNum(name,index,num)
  295. # set name[index] to num
  296. toArr=256
  297. i=0
  298. while @arrays[i][:name]!=name
  299. toArr+=@arrays[i][:size]
  300. i+=1
  301. end
  302. toArr+=index
  303. setR(@indEl+toArr,num)
  304. end
  305.  
  306. def setUnknownArrElemWithNum(name,regindex,num)
  307. # set name[regindex] to num
  308. toArr=256
  309. i=0
  310. while @arrays[i][:name]!=name
  311. toArr+=@arrays[i][:size]
  312. i+=1
  313. end
  314. setR(@indEl-1,num)
  315. copyR(@indEl,regindex)
  316. copyR(@indEl+1,regindex)
  317. gotoR(@indEl)
  318. @program << "[>[->+<]<[->+<]<[->+<]>>-]"
  319. @program << ">"*toArr
  320. @program << "[-]"
  321. @program << "<"*toArr
  322. @program << "<[->"
  323. @program << ">"*toArr
  324. @program << "+"
  325. @program << "<"*toArr
  326. @program << "<]>>[[-<+>]<-]<"
  327. @pos=@indEl
  328. end
  329.  
  330. def setUnknownArrElemWithR(name,regindex,reg)
  331. # set name[regindex] to reg
  332. toArr=256
  333. i=0
  334. while @arrays[i][:name]!=name
  335. toArr+=@arrays[i][:size]
  336. i+=1
  337. end
  338. copyR(@indEl-1,reg)
  339. copyR(@indEl,regindex)
  340. copyR(@indEl+1,regindex)
  341. gotoR(@indEl)
  342. @program << "[>[->+<]<[->+<]<[->+<]>>-]"
  343. @program << ">"*toArr
  344. @program << "[-]"
  345. @program << "<"*toArr
  346. @program << "<[->"
  347. @program << ">"*toArr
  348. @program << "+"
  349. @program << "<"*toArr
  350. @program << "<]>>[[-<+>]<-]<"
  351. @pos=@indEl
  352. end
  353.  
  354. def makeInitCode(numArr)
  355. res=[]
  356. numArr.each { |num|
  357. res << "+"*num << ">"
  358. }
  359. res.join("")
  360. end
  361.  
  362. def addString(name, data)
  363. declareArray(name,data.length)
  364. forInit=data.split("").collect { |ch| ch.ord }
  365. toArr=256
  366. i=0
  367. while @arrays[i][:name]!=name
  368. toArr+=@arrays[i][:size]
  369. i+=1
  370. end
  371. @program.unshift(">"*(toArr+@indEl)+makeInitCode(forInit)+"<"*(toArr+@indEl+data.length))
  372. end
  373.  
  374. def putStr(name)
  375. toArr=256
  376. i=0
  377. while @arrays[i][:name]!=name
  378. toArr+=@arrays[i][:size]
  379. i+=1
  380. end
  381. gotoR(@indEl)
  382. @program << ">"*toArr << "[.>]<[<]>" << "<"*toArr
  383. end
  384.  
  385. def ifFalse(op)
  386. case op
  387. when :eq
  388. reg=@eqR
  389. when :lt
  390. reg=@ltR
  391. when :gt
  392. reg=@gtR
  393. else
  394. raise "logic error"
  395. end
  396. zeroR(5)
  397. zeroR(6)
  398. startCycle(reg)
  399. inc 5
  400. moveRToR(reg,6)
  401. endCycle(reg)
  402. moveRToR(6,reg)
  403. startCycle(5)
  404. end
  405.  
  406. def ifTrue(op)
  407. case op
  408. when :eq
  409. reg=@eqR
  410. when :lt
  411. reg=@ltR
  412. when :gt
  413. reg=@gtR
  414. else
  415. raise "logic error"
  416. end
  417. zeroR(5)
  418. zeroR(6)
  419. startCycle(reg)
  420. dec 5
  421. moveRToR(reg,6)
  422. endCycle(reg)
  423. moveRToR(6,reg)
  424. inc 5
  425. startCycle(5)
  426. end
  427.  
  428. def endif
  429. zeroR(5)
  430. endCycle(5)
  431. end
  432.  
  433. end
  434. i=0
  435. tmp=[]
  436.  
  437. word=[]
  438. instring=false
  439.  
  440. STDIN.read.split("").each { |a|
  441. if !instring
  442. if a==" " or a=="\n"
  443. tmp << word.join("").chomp if word.size >0
  444. word=[]
  445. else
  446. word << a
  447.   end
  448.   if a=="\""
  449.   instring=true
  450.   word=[]
  451.   end
  452.   else
  453.   if a=="\""
  454.   tmp << word.join("").chomp
  455.   word=[]
  456.   instring=false
  457.   else
  458.   word << a
  459.   end
  460.   end
  461. }
  462. tmp << word.join("").chomp
  463. #puts tmp.inspect
  464. cycles = []
  465. a=BFCompiler.new
  466. registers=a.registers
  467. while i<tmp.length
  468. case tmp[i].upcase
  469. when "MOV"
  470. if registers.has_key?(tmp[i+2])
  471. a.copyR(registers[tmp[i+1]],registers[tmp[i+2]])
  472. else
  473. a.setR(registers[tmp[i+1]], tmp[i+2].is_digit? ? tmp[i+2].to_i: tmp[i+2].ord)
  474. end
  475. i+=3
  476. when "SUB"
  477. if registers.has_key?(tmp[i+2])
  478. a.subRFromR(registers[tmp[i+1]],registers[tmp[i+2]])
  479. else
  480. a.subNumFromR(registers[tmp[i+1]],tmp[i+2].to_i)
  481. end
  482. i+=3
  483. when "ADD"
  484. if registers.has_key?(tmp[i+2])
  485. a.addRToR(registers[tmp[i+1]],registers[tmp[i+2]])
  486. else
  487. a.addNumToR(registers[tmp[i+1]],tmp[i+2].to_i)
  488. end
  489. i+=3
  490. when "MUL"
  491. a.mulRonR(registers[tmp[i+1]],registers[tmp[i+2]])
  492. i+=3
  493. when "DIV"
  494. a.divRonR(registers[tmp[i+1]],registers[tmp[i+2]])
  495. i+=3
  496. when "ARRAY"
  497. a.declareArray(tmp[i+1],tmp[i+2].to_i)
  498. i+=3
  499. when "CMP"
  500. a.cmpRR(registers[tmp[i+1]],registers[tmp[i+2]])
  501. i+=3
  502. when "GET"
  503. if registers.has_key?(tmp[i+2])
  504. a.getUnknownArrElem(tmp[i+1],registers[tmp[i+2]],registers[tmp[i+3]])
  505. else
  506. a.getKnownArrElem(tmp[i+1],tmp[i+2].to_i,registers[tmp[i+3]])
  507. end
  508. i+=4
  509. when "SET"
  510. if registers.has_key?(tmp[i+2])
  511. if registers.has_key?(tmp[i+3])
  512. a.setUnknownArrElemWithR(tmp[i+1],registers[tmp[i+2]],registers[tmp[i+3]])
  513. else
  514. a.setUnknownArrElemWithNum(tmp[i+1],registers[tmp[i+2]],tmp[i+3].to_i)
  515. end
  516. else
  517. if registers.has_key?(tmp[i+3])
  518. a.setKnownArrElemWithR(tmp[i+1],tmp[i+2].to_i,registers[tmp[i+3]])
  519. else
  520. a.setKnownArrElemWithNum(tmp[i+1],tmp[i+2].to_i,tmp[i+3].to_i)
  521. end
  522. end
  523. i+=4
  524. when "PUSH"
  525. if registers.has_key?(tmp[i+1])
  526. a.pushRToStack(registers[tmp[i+1]])
  527. else
  528. a.pushNumToStack(tmp[i+1].to_i)
  529. end
  530. i+=2
  531.  
  532. when "NE"
  533. a.ifFalse(:eq)
  534. i+=1
  535. when "NL"
  536. a.ifFalse(:lt)
  537. i+=1
  538. when "NG"
  539. a.ifFalse(:gt)
  540. i+=1
  541. when "EQ"
  542. a.ifTrue(:eq)
  543. i+=1
  544. when "LT"
  545. a.ifTrue(:lt)
  546. i+=1
  547. when "GT"
  548. a.ifTrue(:gt)
  549. i+=1
  550. when "PUT"
  551. a.outR(registers[tmp[i+1]])
  552. i+=2
  553. when "POP"
  554. a.popNumToR(registers[tmp[i+1]])
  555. i+=2
  556. when "TAKE"
  557. a.inputR(registers[tmp[i+1]])
  558. i+=2
  559. when "PUTS"
  560. a.putStr(tmp[i+1])
  561. i+=2
  562. when "INC"
  563. a.inc(registers[tmp[i+1]])
  564. i+=2
  565. when "DEC"
  566. a.dec(registers[tmp[i+1]])
  567. i+=2
  568. when "WHILE"
  569. a.startCycle(registers[tmp[i+1]])
  570. cycles << registers[tmp[i+1]]
  571. i+=2
  572. when "ENDWHILE"
  573. a.endCycle(cycles.pop)
  574. i+=1
  575. when "END"
  576. a.endif
  577. i+=1
  578. when "STRING"
  579. a.addString(tmp[i+1],tmp[i+2])
  580. i+=3
  581. else
  582. i+=1
  583. end
  584. end
  585. puts a.compileBf
Success #stdin #stdout 0.02s 7564KB
stdin
числа фиббоначи
для просмотра ставить брейкпоинт на точку в конце
mov ax 1
mov bx 1
mov dx 11

while dx

mov cx bx
add cx ax
mov bx ax
mov ax cx
put ax

dec dx
endwhile
stdout
Min cells used:22
<<<->>>>>>>>>>>>>>>>>>>[-]+>[-]+>>[-]+++++++++++[<[-]<<<<<<<<<<<<<<<<<<[-]>>>>>>
>>>>>>>>>>>[->+<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>]<<<<<<<<<<<<<<<<<[->>>>>>>>>
>>>>>>>>+<<<<<<<<<<<<<<<<<][-]>>>>>>>>>>>>>>>>[->>+<<<<<<<<<<<<<<<<<<+>>>>>>>>>>
>>>>>>]<<<<<<<<<<<<<<<<[->>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>>[-]<
<<<<<<<<<<<<<<<<[-]>>>>>>>>>>>>>>>>[->+<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>]<<<<<<
<<<<<<<<<<[->>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>[-]<<<<<<<<<<<<<<<
<[-]>>>>>>>>>>>>>>>>>>[-<<+<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>]<<<<<<<<<<<<<<<<<
<[->>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>>.>>>-]