1use std::error::Error;
2use std::fmt::Write;
3
4use crate::ir::ops::{LoopDecrement, Op, OpType};
5use crate::parser::Program;
6
7pub fn compile_to_rust(program: &Program) -> String {
9 let mut code = "".to_owned();
10
11 print_ops(&mut code, &program.ops).expect("No io error");
12
13 include_str!("rust.tpl").replace("{{CODE}}", &code)
14}
15
16fn print_ops(out: &mut String, ops: &[Op]) -> Result<(), Box<dyn Error>> {
17 for op in ops {
18 match &op.op_type {
19 OpType::Start => {
20 }
22 OpType::IncPtr(count) => writeln!(out, "rt.inc_ptr({});", count)?,
23 OpType::DecPtr(count) => writeln!(out, "rt.dec_ptr({});", count)?,
24 OpType::Inc(offset, count) => writeln!(out, "rt.inc({}, {});", offset, count)?,
25 OpType::Dec(offset, count) => writeln!(out, "rt.dec({}, {});", offset, count)?,
26 OpType::Set(offset, value) => writeln!(out, "rt.set({}, {});", offset, value)?,
27 OpType::Add(src_offset, dest_offset, multi) => {
28 writeln!(out, "rt.add({}, {}, {});", src_offset, dest_offset, multi)?
29 }
30 OpType::NzAdd(src_offset, dest_offset, multi) => writeln!(
31 out,
32 "rt.nz_add({}, {}, {});",
33 src_offset, dest_offset, multi
34 )?,
35 OpType::CAdd(src_offset, dest_offset, count) => {
36 writeln!(out, "rt.c_add({}, {}, {});", src_offset, dest_offset, count)?
37 }
38 OpType::NzCAdd(src_offset, dest_offset, count) => writeln!(
39 out,
40 "rt.nz_c_add({}, {}, {});",
41 src_offset, dest_offset, count
42 )?,
43 OpType::Sub(src_offset, dest_offset, multi) => {
44 writeln!(out, "rt.sub({}, {}, {});", src_offset, dest_offset, multi)?
45 }
46 OpType::NzSub(src_offset, dest_offset, multi) => writeln!(
47 out,
48 "rt.nz_sub({}, {}, {});",
49 src_offset, dest_offset, multi
50 )?,
51 OpType::CSub(src_offset, dest_offset, count) => {
52 writeln!(out, "rt.c_sub({}, {}, {});", src_offset, dest_offset, count)?
53 }
54 OpType::NzCSub(src_offset, dest_offset, count) => writeln!(
55 out,
56 "rt.nz_c_sub({}, {}, {});",
57 src_offset, dest_offset, count
58 )?,
59 OpType::Move(src_offset, dest_offset) => {
60 writeln!(out, "rt.move({}, {});", src_offset, dest_offset)?
61 }
62 OpType::Copy(src_offset, dest_offset) => {
63 writeln!(out, "rt.copy({}, {});", src_offset, dest_offset)?
64 }
65 OpType::Mul(src_offset, dest_offset, multi) => {
66 writeln!(out, "rt.mul({}, {}, {});", src_offset, dest_offset, multi)?
67 }
68 OpType::NzMul(src_offset, dest_offset, multi) => writeln!(
69 out,
70 "rt.nz_mul({}, {}, {});",
71 src_offset, dest_offset, multi
72 )?,
73 OpType::GetChar(offset) => writeln!(out, "rt.get_char({});", offset)?,
74 OpType::PutString(array) => writeln!(out, "rt.put_string({:?});", array)?,
75 OpType::PutChar(offset) => writeln!(out, "rt.put_char({});", offset)?,
76 OpType::DLoop(children, _) => {
77 writeln!(out, "{{")?;
78
79 writeln!(out, " while *rt.heap_value() > 0 {{")?;
80 print_ops(out, children)?;
81 writeln!(out, "}}")?;
82
83 writeln!(out, "}}")?;
84 }
85 OpType::LLoop(children, _) => {
86 writeln!(out, "{{")?;
87
88 writeln!(out, "let heap_pointer = rt.pointer;")?;
89 writeln!(out, "while *rt.heap_value() > 0 {{")?;
90 writeln!(out, "rt.pointer = heap_pointer;")?;
91 print_ops(out, children)?;
92 writeln!(out, "}}")?;
93 writeln!(out, "rt.pointer = heap_pointer;")?;
94
95 writeln!(out, "}}")?;
96 }
97 OpType::ILoop(children, step, decrement, _) => {
98 writeln!(out, "{{")?;
99
100 match decrement {
101 LoopDecrement::Pre => {
102 writeln!(out, "let heap_pointer = rt.pointer;")?;
103 writeln!(out, "let mut left = *rt.heap_value();")?;
104 writeln!(out, "while left > 0 {{")?;
105 writeln!(out, "rt.pointer = heap_pointer;")?;
106 writeln!(out, "left = left.wrapping_sub({});", step)?;
107 print_ops(out, children)?;
108 writeln!(out, "}}")?;
109 writeln!(out, "rt.pointer = heap_pointer;")?;
110 writeln!(out, "*rt.heap_value() = 0;")?;
111 }
112 LoopDecrement::Post | LoopDecrement::Auto => {
113 writeln!(out, "let heap_pointer = rt.pointer;")?;
114 writeln!(out, "let mut left = *rt.heap_value();")?;
115 writeln!(out, "while left > 0 {{")?;
116 writeln!(out, "rt.pointer = heap_pointer;")?;
117 print_ops(out, children)?;
118 writeln!(out, "left = left.wrapping_sub({});", step)?;
119 writeln!(out, "}}")?;
120 writeln!(out, "rt.pointer = heap_pointer;")?;
121 writeln!(out, "*rt.heap_value() = 0;")?;
122 }
123 }
124
125 writeln!(out, "}}")?;
126 }
127 OpType::CLoop(children, iterations, decrement, _) => {
128 writeln!(out, "{{")?;
129
130 match decrement {
131 LoopDecrement::Pre => {
132 writeln!(out, "let heap_pointer = rt.pointer;")?;
133 writeln!(out, "*rt.heap_value() = {}", iterations)?;
134 writeln!(out, "let mut left = *rt.heap_value();")?;
135 writeln!(out, "while left > 0 {{")?;
136 writeln!(out, "rt.pointer = heap_pointer;")?;
137 writeln!(out, "left = left.wrapping_sub(1);")?;
138 print_ops(out, children)?;
139 writeln!(out, "}}")?;
140 writeln!(out, "rt.pointer = heap_pointer;")?;
141 writeln!(out, "*rt.heap_value() = 0;")?;
142 }
143 LoopDecrement::Post => {
144 writeln!(out, "let heap_pointer = rt.pointer;")?;
145 writeln!(out, "*rt.heap_value() = {}", iterations)?;
146 writeln!(out, "let mut left = *rt.heap_value();")?;
147 writeln!(out, "while left > 0 {{")?;
148 writeln!(out, "rt.pointer = heap_pointer;")?;
149 print_ops(out, children)?;
150 writeln!(out, "left = left.wrapping_sub(1);")?;
151 writeln!(out, "}}")?;
152 writeln!(out, "rt.pointer = heap_pointer;")?;
153 writeln!(out, "*rt.heap_value() = 0;")?;
154 }
155 LoopDecrement::Auto => {
156 writeln!(out, "let heap_pointer = rt.pointer;")?;
157 writeln!(out, "for _ in 0..{} {{", iterations)?;
158 writeln!(out, "rt.pointer = heap_pointer;")?;
159 print_ops(out, children)?;
160 writeln!(out, "}}")?;
161 writeln!(out, "rt.pointer = heap_pointer;")?;
162 writeln!(out, "*rt.heap_value() = 0;")?;
163 }
164 }
165
166 writeln!(out, "}}")?;
167 }
168 OpType::TNz(children, _) => {
169 writeln!(out, "{{")?;
170
171 writeln!(out, "if *rt.heap_value() != 0 {{")?;
172 writeln!(out, "let heap_pointer = self.pointer;")?;
173 writeln!(out, "rt.pointer = heap_pointer;")?;
174 print_ops(out, children)?;
175 writeln!(out, "rt.pointer = heap_pointer;")?;
176 writeln!(out, "*rt.heap_value() = 0;")?;
177
178 writeln!(out, "}}")?;
179 }
180 OpType::DTNz(children, _, _) => {
181 writeln!(out, "{{")?;
182
183 writeln!(out, " if *rt.heap_value() > 0 {{")?;
184 print_ops(out, children)?;
185 writeln!(out, "}}")?;
186
187 writeln!(out, "}}")?;
188 }
189 OpType::SearchZero(step, _) => writeln!(out, "rt.search_zero({});", step)?,
190 }
191 }
192
193 Ok(())
194}