Skip to main content

celestial_hub_astrolabe/ast/
mod.rs

1pub type Location = std::ops::Range<usize>;
2
3use serde::Serialize;
4
5use crate::lexer::tokens::{Type, Value};
6
7pub mod to_string;
8
9#[derive(Serialize, Clone, Debug, PartialEq)]
10#[serde(rename_all = "camelCase")]
11pub struct Program {
12  pub data_section: DataSection,
13  pub text_section: TextSection,
14}
15
16#[derive(Serialize, Clone, Debug, PartialEq, Default)]
17#[serde(rename_all = "camelCase")]
18pub struct DataSection {
19  pub variables: Vec<Variable>,
20}
21
22#[derive(Serialize, Clone, Debug, PartialEq)]
23#[serde(rename_all = "camelCase")]
24pub struct TextSection {
25  pub statements: Vec<Statement>,
26  pub entrypoint: String,
27}
28
29impl Default for TextSection {
30  fn default() -> Self {
31    Self {
32      statements: Default::default(),
33      entrypoint: "main".into(),
34    }
35  }
36}
37
38#[derive(Serialize, Clone, Debug, PartialEq)]
39#[serde(rename_all = "camelCase")]
40pub struct Variable {
41  pub name: String,
42  pub type_: Type,
43  pub value: Value,
44}
45
46#[derive(Serialize, Clone, Debug, PartialEq)]
47#[serde(rename_all = "camelCase")]
48#[serde(tag = "kind", content = "value")]
49pub enum Statement {
50  Instruction(Instruction),
51  Label(String),
52}
53
54#[derive(Serialize, Clone, Debug, PartialEq)]
55#[serde(tag = "kind", content = "args")]
56#[serde(rename_all = "camelCase")]
57pub enum Instruction {
58  Li(Vec<InstructionArgument>),
59  La(Vec<InstructionArgument>),
60  Syscall,
61  Move(Vec<InstructionArgument>),
62  Jal(Vec<InstructionArgument>),
63  Sub(Vec<InstructionArgument>),
64  Add(Vec<InstructionArgument>),
65  Jr(Vec<InstructionArgument>),
66  Addi(Vec<InstructionArgument>),
67  Andi(Vec<InstructionArgument>),
68
69  /// Multiply. `mul $t0, $t1, $t2`
70  Mul(Vec<InstructionArgument>),
71
72  /// Integer division. `div $t0, $t1, $t2`
73  Div(Vec<InstructionArgument>),
74
75  /// Jump to label. `j label`
76  J(Vec<InstructionArgument>),
77
78  /// Store word. `sw $t0, 0($t1)`
79  Sw(Vec<InstructionArgument>),
80
81  /// Load word. `lw $t0, $t1`
82  Lw(Vec<InstructionArgument>),
83
84  /// Set if less than. `slt $t0, $t1, $t2`
85  Slt(Vec<InstructionArgument>),
86
87  /// Set if less or equal to. `sle $t0, $t1, $t2`
88  Sle(Vec<InstructionArgument>),
89
90  /// Set if greater than. `sgt $t0, $t1, $t2`
91  Sgt(Vec<InstructionArgument>),
92
93  /// Set if greater than or equal to. `sge $t0, $t1, $t2`
94  Sge(Vec<InstructionArgument>),
95
96  /// Set if equal. `seq $t0, $t1, $t2`
97  Seq(Vec<InstructionArgument>),
98
99  /// Set if not equal. `sne $t0, $t1, $t2`
100  Sne(Vec<InstructionArgument>),
101
102  /// Branch if equal zero. `beqz $t0, label`
103  Beqz(Vec<InstructionArgument>),
104
105  /// Branch if not equal zero. `bnez $t0, label`
106  Bnez(Vec<InstructionArgument>),
107
108  /// Branch less than zero. `bltz $t0, label`
109  Bltz(Vec<InstructionArgument>),
110
111  /// Branch greater than zero. `bgtz $t0, label`
112  Bgtz(Vec<InstructionArgument>),
113
114  /// Branch less than or equal to zero. `blez $t0, label`
115  Blez(Vec<InstructionArgument>),
116
117  /// Branch greater than or equal to zero. `bgez $t0, label`
118  Bgez(Vec<InstructionArgument>),
119
120  /// Branch less than. `blt $t0, $t1, label`
121  Blt(Vec<InstructionArgument>),
122
123  /// Branch greater than. `bgt $t0, $t1, label`
124  Bgt(Vec<InstructionArgument>),
125
126  /// Branch less than or equal to. `ble $t0, $t1, label`
127  Ble(Vec<InstructionArgument>),
128
129  /// Branch greater than or equal to. `bge $t0, $t1, label`
130  Bge(Vec<InstructionArgument>),
131
132  /// Branch on equal. `beq $t0, $t1, label`
133  Beq(Vec<InstructionArgument>),
134
135  /// Branch on not equal. `bne $t0, $t1, label`
136  Bne(Vec<InstructionArgument>),
137
138  /// Halt the program. `halt`
139  Halt,
140}
141
142impl Instruction {
143  pub fn new(name: String, args: Vec<InstructionArgument>) -> Self {
144    match name.as_str() {
145      "li" => Instruction::Li(args),
146      "la" => Instruction::La(args),
147      "syscall" => Instruction::Syscall,
148      "halt" => Instruction::Halt,
149      "move" => Instruction::Move(args),
150      "jal" => Instruction::Jal(args),
151      "sub" => Instruction::Sub(args),
152      "add" => Instruction::Add(args),
153      "mul" => Instruction::Mul(args),
154      "div" => Instruction::Div(args),
155      "jr" => Instruction::Jr(args),
156      "addi" => Instruction::Addi(args),
157      "andi" => Instruction::Andi(args),
158      "j" => Instruction::J(args),
159      "sw" => Instruction::Sw(args),
160      "lw" => Instruction::Lw(args),
161      "slt" => Instruction::Slt(args),
162      "sle" => Instruction::Sle(args),
163      "sgt" => Instruction::Sgt(args),
164      "sge" => Instruction::Sge(args),
165      "seq" => Instruction::Seq(args),
166      "sne" => Instruction::Sne(args),
167      "beqz" => Instruction::Beqz(args),
168      "bnez" => Instruction::Beqz(args),
169      "bltz" => Instruction::Bltz(args),
170      "bgtz" => Instruction::Bgtz(args),
171      "blez" => Instruction::Blez(args),
172      "bgez" => Instruction::Bgez(args),
173      "blt" => Instruction::Blt(args),
174      "bgt" => Instruction::Bgt(args),
175      "ble" => Instruction::Ble(args),
176      "bge" => Instruction::Bge(args),
177      "beq" => Instruction::Beq(args),
178      "bne" => Instruction::Bne(args),
179      _ => unreachable!(),
180    }
181  }
182}
183
184#[derive(Serialize, Clone, Debug, PartialEq)]
185#[serde(rename_all = "camelCase")]
186#[serde(tag = "kind", content = "value")]
187pub enum InstructionArgument {
188  Register(Register),
189  Immediate(i32),
190  Label(String),
191  Literal(String),
192}
193
194#[derive(Serialize, Clone, Debug, PartialEq)]
195#[serde(rename_all = "camelCase")]
196pub struct Register {
197  pub name: String,
198}
199
200#[derive(Serialize, Clone, Debug, PartialEq)]
201#[serde(rename_all = "camelCase")]
202#[serde(tag = "kind", content = "value")]
203pub enum Operand {
204  Immediate(i32),
205  Register(Register),
206  Label(String),
207}