Skip to content

Commit edd886e

Browse files
Chore: CI fixes and readme updates (#4)
* Update README to include array support and CI pipeline details * Refactor code for consistency and readability by adding missing commas and formatting adjustments across multiple files * Update Rust toolchain version to 1.87 in CI configuration
1 parent ed4fa4e commit edd886e

9 files changed

Lines changed: 295 additions & 242 deletions

File tree

.github/workflows/ci.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ jobs:
1414
- name: Set up Rust
1515
uses: dtolnay/rust-toolchain@master
1616
with:
17-
toolchain: "1.85"
17+
toolchain: "1.87"
1818
components: rustfmt, clippy
1919
- name: Build
2020
run: cargo build --verbose

README.md

Lines changed: 17 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -89,56 +89,25 @@ The WASM backend will:
8989
* 🔢 Increment / decrement (`i++`, `i--`)
9090
* 🔧 Functions with parameters, return values, and recursion
9191
* 🧩 Nested function calls (`add(add(1,2), 3)`)
92+
* 📦 Arrays (literals, index read/write, pass to functions)
9293
* 🖨️ Print statements (`print x;`)
9394
* 🔁 REPL (interactive shell)
9495
* 📂 File execution (`rusty run file.rts`)
96+
* ✅ CI pipeline (GitHub Actions)
9597

9698
---
9799

98-
## 🧪 Example
99-
100-
```ts
101-
let x = (2 + 3) * 4;
102-
print "x = " + x;
103-
104-
function max(a, b) {
105-
if (a > b) {
106-
return a;
107-
} else {
108-
return b;
109-
}
110-
}
111-
112-
print "max is " + max(x, 15);
113-
114-
function factorial(n) {
115-
if (n < 2) { return 1; }
116-
return n * factorial(n - 1);
117-
}
118-
print "5! = " + factorial(5);
119-
120-
for (let i = 0; i < 5; i++) {
121-
if (i == 2) { continue; }
122-
if (i == 4) { break; }
123-
print i;
124-
}
125-
126-
let name = "Rusty";
127-
if (name && x > 10) {
128-
print name + " works!";
129-
}
130-
```
100+
## 🧪 Examples
131101

132-
Output:
102+
Check out the [`example/`](example/) folder for sample RTS programs, including:
133103

134-
```
135-
x = 20
136-
max is 20
137-
5! = 120
138-
0
139-
1
140-
3
141-
Rusty works!
104+
- [`test.rts`](example/test.rts) — array basics (literals, indexing, mutation)
105+
- [`merge_sort.rts`](example/merge_sort.rts) — merge sort implementation using arrays, functions, and recursion
106+
107+
Run any example with:
108+
109+
```bash
110+
cargo run -- run example/merge_sort.rts
142111
```
143112

144113
---
@@ -210,15 +179,19 @@ cargo run -- repl
210179
* [x] Functions (declaration, params, return)
211180
* [x] Nested / recursive function calls
212181
* [x] Frame-based call stack
182+
* [x] Arrays (literals, indexing, mutation)
183+
* [x] Array pass/return from functions
213184
* [ ] Type annotations
214-
* [ ] Arrays and objects
185+
* [ ] Objects / maps
215186
* [ ] Closures
187+
* [ ] `<=`, `>=` operators
216188

217189
---
218190

219-
### Runtime Evolution
191+
### Runtime & Tooling
220192

221193
* [x] Bytecode VM
194+
* [x] CI pipeline (build, test, clippy, fmt)
222195
* [ ] WASM backend (in progress)
223196
* [ ] Bytecode optimizations
224197
* [ ] Register-based VM (optional)

src/ast/mod.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,13 @@ pub enum Statement {
1515
},
1616
While {
1717
condition: Expression,
18-
body: Vec<Statement>
18+
body: Vec<Statement>,
1919
},
2020
For {
2121
init: Box<Statement>,
2222
condition: Expression,
2323
update: Box<Statement>,
24-
body: Vec<Statement>
24+
body: Vec<Statement>,
2525
},
2626
Assignment {
2727
name: String,
@@ -32,16 +32,16 @@ pub enum Statement {
3232
Function {
3333
name: String,
3434
params: Vec<String>,
35-
body: Vec<Statement>
35+
body: Vec<Statement>,
3636
},
3737
Return {
38-
value: Expression
38+
value: Expression,
3939
},
4040
AssignmentIndex {
4141
array: String,
4242
index: Expression,
4343
value: Expression,
44-
}
44+
},
4545
}
4646

4747
#[derive(Debug, Clone, PartialEq)]
@@ -55,7 +55,7 @@ pub enum BinaryOperation {
5555
Equal,
5656
NotEqual,
5757
And,
58-
Or
58+
Or,
5959
}
6060

6161
#[derive(Debug, Clone)]
@@ -70,22 +70,22 @@ pub enum Expression {
7070
},
7171
Unary {
7272
op: BinaryOperation,
73-
expr: Box<Expression>
73+
expr: Box<Expression>,
7474
},
7575
Call {
7676
name: String,
77-
args: Vec<Expression>
77+
args: Vec<Expression>,
7878
},
7979
ArrayLiteral(Vec<Expression>),
8080
Index {
8181
array: Box<Expression>,
8282
index: Box<Expression>,
83-
}
83+
},
8484
}
8585

8686
#[derive(Debug, Clone, PartialEq, PartialOrd)]
8787
pub enum Value {
8888
Number(i32),
8989
String(String),
9090
Array(Vec<Value>),
91-
}
91+
}

src/compiler/mod.rs

Lines changed: 66 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use crate::ast::{BinaryOperation, Expression, Statement, Value};
55
#[derive(Debug)]
66
pub struct FunctionBytecode {
77
pub params: Vec<String>,
8-
pub instructions: Vec<Instruction>
8+
pub instructions: Vec<Instruction>,
99
}
1010

1111
pub struct LoopContext {
@@ -17,7 +17,7 @@ pub struct LoopContext {
1717
#[derive(Debug)]
1818
pub struct Program {
1919
pub main: Vec<Instruction>,
20-
pub functions: HashMap<String, FunctionBytecode>
20+
pub functions: HashMap<String, FunctionBytecode>,
2121
}
2222

2323
#[derive(Debug, Clone)]
@@ -45,13 +45,15 @@ pub enum Instruction {
4545
CallFunction(String, usize),
4646
CreateArray(usize),
4747
LoadIndex,
48-
StoreIndex
48+
StoreIndex,
4949
}
5050

5151
fn compile_expr(instructions: &mut Vec<Instruction>, expr: &Expression) {
5252
match expr {
5353
Expression::Number(x) => instructions.push(Instruction::LoadConst(Value::Number(*x))),
54-
Expression::String(s) => instructions.push(Instruction::LoadConst(Value::String(s.clone()))),
54+
Expression::String(s) => {
55+
instructions.push(Instruction::LoadConst(Value::String(s.clone())))
56+
}
5557
Expression::Identifier(val) => instructions.push(Instruction::LoadVar(val.to_string())),
5658
Expression::Binary { left, op, right } => {
5759
if *op != BinaryOperation::And && *op != BinaryOperation::Or {
@@ -75,37 +77,38 @@ fn compile_expr(instructions: &mut Vec<Instruction>, expr: &Expression) {
7577
let jump_instructions_index = instructions.len() - 1;
7678
instructions.push(Instruction::PopTop);
7779
compile_expr(instructions, right);
78-
instructions[jump_instructions_index] = Instruction::JumpIfFalse(instructions.len());
80+
instructions[jump_instructions_index] =
81+
Instruction::JumpIfFalse(instructions.len());
7982
}
8083
BinaryOperation::Or => {
8184
instructions.push(Instruction::DuplicateTop);
8285
instructions.push(Instruction::JumpIfTrue(0));
8386
let jump_instructions_index = instructions.len() - 1;
8487
instructions.push(Instruction::PopTop);
8588
compile_expr(instructions, right);
86-
instructions[jump_instructions_index] = Instruction::JumpIfTrue(instructions.len());
89+
instructions[jump_instructions_index] =
90+
Instruction::JumpIfTrue(instructions.len());
8791
}
8892
}
8993
}
9094
Expression::Unary { op, expr } => {
9195
compile_expr(instructions, expr);
92-
match op {
93-
BinaryOperation::Subtraction => instructions.push(Instruction::Negate),
94-
_ => {}
96+
if op == &BinaryOperation::Subtraction {
97+
instructions.push(Instruction::Negate);
9598
}
96-
},
99+
}
97100
Expression::Call { name, args } => {
98101
for arg in args {
99102
compile_expr(instructions, arg);
100103
}
101104
instructions.push(Instruction::CallFunction(name.clone(), args.len()));
102-
},
105+
}
103106
Expression::ArrayLiteral(elements) => {
104107
for element in elements {
105108
compile_expr(instructions, element);
106109
}
107110
instructions.push(Instruction::CreateArray(elements.len()));
108-
},
111+
}
109112
Expression::Index { array, index } => {
110113
compile_expr(instructions, array);
111114
compile_expr(instructions, index);
@@ -124,12 +127,16 @@ pub fn compile_statements(
124127
Statement::VarDecl { name, value } => {
125128
compile_expr(instructions, &value);
126129
instructions.push(Instruction::DeclareVar(name));
127-
},
130+
}
128131
Statement::Print { value } => {
129132
compile_expr(instructions, &value);
130133
instructions.push(Instruction::Print);
131134
}
132-
Statement::If { condition, body, else_body } => {
135+
Statement::If {
136+
condition,
137+
body,
138+
else_body,
139+
} => {
133140
compile_expr(instructions, &condition);
134141

135142
let jump_if_false_index = instructions.len();
@@ -140,11 +147,13 @@ pub fn compile_statements(
140147
if let Some(else_body) = else_body {
141148
let jump_to_end_index = instructions.len();
142149
instructions.push(Instruction::Jump(0));
143-
instructions[jump_if_false_index] = Instruction::JumpIfFalse(instructions.len());
150+
instructions[jump_if_false_index] =
151+
Instruction::JumpIfFalse(instructions.len());
144152
compile_statements(else_body, instructions, loop_ctx.as_deref_mut());
145153
instructions[jump_to_end_index] = Instruction::Jump(instructions.len());
146154
} else {
147-
instructions[jump_if_false_index] = Instruction::JumpIfFalse(instructions.len());
155+
instructions[jump_if_false_index] =
156+
Instruction::JumpIfFalse(instructions.len());
148157
}
149158
}
150159
Statement::While { condition, body } => {
@@ -171,8 +180,13 @@ pub fn compile_statements(
171180
for idx in ctx.break_placeholders {
172181
instructions[idx] = Instruction::Jump(instructions.len());
173182
}
174-
},
175-
Statement::For { init, condition, update, body } => {
183+
}
184+
Statement::For {
185+
init,
186+
condition,
187+
update,
188+
body,
189+
} => {
176190
compile_statements(vec![*init], instructions, loop_ctx.as_deref_mut());
177191

178192
let loop_start_index = instructions.len();
@@ -201,44 +215,50 @@ pub fn compile_statements(
201215
for idx in ctx.break_placeholders {
202216
instructions[idx] = Instruction::Jump(instructions.len());
203217
}
204-
},
218+
}
205219
Statement::Assignment { name, value } => {
206220
compile_expr(instructions, &value);
207221
instructions.push(Instruction::AssignVar(name));
208-
},
222+
}
209223
Statement::Break => {
210224
if let Some(ctx) = loop_ctx.as_deref_mut() {
211225
instructions.push(Instruction::Jump(0));
212226
ctx.break_placeholders.push(instructions.len() - 1);
213227
} else {
214228
panic!("'break' used outside of a loop");
215229
}
216-
},
230+
}
217231
Statement::Continue => {
218232
if let Some(ctx) = loop_ctx.as_deref_mut() {
219233
instructions.push(Instruction::Jump(0));
220234
ctx.continue_placeholders.push(instructions.len() - 1);
221235
} else {
222236
panic!("'continue' used outside of a loop");
223237
}
224-
},
225-
Statement::Function { name:_, params:_, body:_ } => {},
238+
}
239+
Statement::Function {
240+
name: _,
241+
params: _,
242+
body: _,
243+
} => {}
226244
Statement::Return { value } => {
227245
compile_expr(instructions, &value);
228246
instructions.push(Instruction::Return);
229-
},
230-
Statement::Expression(expr) => {
231-
match expr {
232-
Expression::Call { name, args } => {
233-
for arg in &args {
234-
compile_expr(instructions, arg);
235-
}
236-
instructions.push(Instruction::CallFunction(name.clone(), args.len()));
237-
},
238-
_ => compile_expr(instructions, &expr)
247+
}
248+
Statement::Expression(expr) => match expr {
249+
Expression::Call { name, args } => {
250+
for arg in &args {
251+
compile_expr(instructions, arg);
252+
}
253+
instructions.push(Instruction::CallFunction(name.clone(), args.len()));
239254
}
255+
_ => compile_expr(instructions, &expr),
240256
},
241-
Statement::AssignmentIndex { array, index, value } => {
257+
Statement::AssignmentIndex {
258+
array,
259+
index,
260+
value,
261+
} => {
242262
instructions.push(Instruction::LoadVar(array.clone()));
243263

244264
// index is expression
@@ -262,11 +282,20 @@ pub fn compile_program(statements: Vec<Statement>) -> Program {
262282
if let Statement::Function { name, params, body } = statement {
263283
let mut func_instructions = Vec::new();
264284
compile_statements(body, &mut func_instructions, None);
265-
functions.insert(name, FunctionBytecode { params, instructions: func_instructions });
285+
functions.insert(
286+
name,
287+
FunctionBytecode {
288+
params,
289+
instructions: func_instructions,
290+
},
291+
);
266292
} else {
267293
compile_statements(vec![statement], &mut main_instructions, None);
268294
}
269295
}
270296

271-
Program { main: main_instructions, functions }
272-
}
297+
Program {
298+
main: main_instructions,
299+
functions,
300+
}
301+
}

0 commit comments

Comments
 (0)