Skip to content

Commit

Permalink
Merge pull request #22 from lambdaclass/progress
Browse files Browse the repository at this point in the history
add tests and assign stmt
  • Loading branch information
edg-l authored Dec 10, 2024
2 parents 06d791d + 53b0d21 commit ffc9c94
Show file tree
Hide file tree
Showing 16 changed files with 128 additions and 14 deletions.
2 changes: 1 addition & 1 deletion docs/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
- [Workshop: Setup](./workshop_p1.md)
- [Workshop: Walk through the prepared codebase](./workshop_p2.md)
- [Workshop: Compiling Expressions](./workshop_p3.md)
- [Workshop: Compiling Let](./workshop_p4.md)
- [Workshop: Compiling Let and Assign](./workshop_p4.md)
- [Workshop: Compiling Return](./workshop_p5.md)
- [Workshop: Compiling If/Else](./workshop_p6.md)
- [Workshop: Compiling Function calls](./workshop_p7.md)
Expand Down
22 changes: 21 additions & 1 deletion docs/src/workshop_p4.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
# Workshop: Compiling Let
# Workshop: Compiling Let and Assign

## Let statement

On let statements, variables are declared, as explained before. In this case we need to allocate space for it and save the
pointer value on the `locals` hashmap.
Expand All @@ -7,6 +9,7 @@ You will need to use the `llvm` dialect.

```rust
// src/codegen/let_stmt.rs
// let x = 2;
pub fn compile_let<'ctx: 'parent, 'parent>(
ctx: &ModuleCtx<'ctx>,
locals: &mut HashMap<String, Value<'ctx, 'parent>>,
Expand All @@ -16,3 +19,20 @@ pub fn compile_let<'ctx: 'parent, 'parent>(
todo!()
}
```

## Assign statement

Assign is like let, but without creating the variable, only storing the updated value.

```rust
// src/codegen/let_stmt.rs
// x = 2;
pub fn compile_assign<'ctx: 'parent, 'parent>(
ctx: &ModuleCtx<'ctx>,
locals: &mut HashMap<String, Value<'ctx, 'parent>>,
block: &'parent Block<'ctx>,
stmt: &AssignStmt,
) {
todo!("implement assign")
}
```
8 changes: 8 additions & 0 deletions src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ pub enum Opcode {
#[derive(Debug, Clone)]
pub enum Statement {
Let(LetStmt),
Assign(AssignStmt),
If(IfStmt),
Return(ReturnStmt),
}
Expand All @@ -33,6 +34,13 @@ pub struct LetStmt {
pub expr: Expr,
}

/// The assign statement, it updates the value of the given variable.
#[derive(Debug, Clone)]
pub struct AssignStmt {
pub variable: String,
pub expr: Expr,
}

/// An if with an optional else statement, depending on whether the condition evaluates to true,
/// take one or another block.
#[derive(Debug, Clone)]
Expand Down
5 changes: 4 additions & 1 deletion src/codegen.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::{collections::HashMap, path::Path};

use ifelse_stmt::compile_if;
use let_stmt::compile_let;
use let_stmt::{compile_assign, compile_let};
use melior::{
dialect::{
func::{self, func},
Expand Down Expand Up @@ -145,5 +145,8 @@ fn compile_statement<'ctx: 'parent, 'parent>(
Statement::Return(return_stmt) => {
compile_return(ctx, locals, block, return_stmt);
}
Statement::Assign(assign_stmt) => {
compile_assign(ctx, locals, block, assign_stmt);
},
}
}
1 change: 1 addition & 0 deletions src/codegen/expressions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use crate::ast::{Expr, Opcode};

use super::ModuleCtx;

// A right hand side expression: `2 + x * 3`
pub fn compile_expr<'ctx: 'parent, 'parent>(
// Helper struct with the MLIR Context and Module
ctx: &ModuleCtx<'ctx>,
Expand Down
17 changes: 16 additions & 1 deletion src/codegen/let_stmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,13 @@ use melior::{
ir::{r#type::IntegerType, Block, Location, Value},
};

use crate::{ast::LetStmt, codegen::expressions::compile_expr};
use crate::{ast::{AssignStmt, LetStmt}, codegen::expressions::compile_expr};

use super::ModuleCtx;

/// A let statement
///
/// let x = 2;
pub fn compile_let<'ctx: 'parent, 'parent>(
ctx: &ModuleCtx<'ctx>,
locals: &mut HashMap<String, Value<'ctx, 'parent>>,
Expand All @@ -17,3 +20,15 @@ pub fn compile_let<'ctx: 'parent, 'parent>(
) {
todo!("implement let")
}

/// An assign statement
///
/// x = 2;
pub fn compile_assign<'ctx: 'parent, 'parent>(
ctx: &ModuleCtx<'ctx>,
locals: &mut HashMap<String, Value<'ctx, 'parent>>,
block: &'parent Block<'ctx>,
stmt: &AssignStmt,
) {
todo!("implement assign")
}
10 changes: 10 additions & 0 deletions src/grammar.lalrpop
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,15 @@ pub Let: LetStmt = {
}
}

pub Assign: AssignStmt = {
<variable:Name> "=" <expr:Expr> => {
AssignStmt {
variable,
expr
}
}
}

pub Return: ReturnStmt = {
"return" <expr:Expr> => {
ReturnStmt {
Expand All @@ -90,6 +99,7 @@ pub Else: Block = {

pub Stmt: Statement = {
<Let> => Statement::Let(<>),
<Assign> => Statement::Assign(<>),
<If> => Statement::If(<>),
<Return> => Statement::Return(<>),
}
Expand Down
30 changes: 22 additions & 8 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,15 +51,29 @@ mod tests {
}
}

#[test]
fn add() {
let program = grammar::ProgramParser::new()
.parse(include_str!("../test/add.prog"))
.unwrap();
macro_rules! program_test {
($name:ident, $filename:ident, $a:literal, $b:literal, $r:literal) => {
#[test]
fn $name() {
let program = grammar::ProgramParser::new()
.parse(include_str!(concat!("../test/", stringify!($filename), ".prog")))
.unwrap();

let engine = compile_program_jit(&program);
let engine = compile_program_jit(&program);

let res = call_program(&engine, 2, 3);
assert_eq!(res, 5);
let res = call_program(&engine, $a, $b);
assert_eq!(res, $r);
}
};
}

program_test!{add, add, 2, 2, 4}
program_test!{sub, sub, 2, 2, 0}
program_test!{subminus, sub, 2, 3, -1}
program_test!{mul, mul, 2, 4, 8}
program_test!{div, div, 4, 2, 2}
program_test!{ifelse, ifelse, 4, 2, 2}
program_test!{constant, constant, 2, 2, 6}
program_test!{call, call, 2, 2, 8}
program_test!{factorial, factorial, 5, 1, 120}
}
4 changes: 2 additions & 2 deletions test.prog
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
fn main(a, b, c) {
let x = a * b * c;
fn main() {
let x = 2 * 3 * 4;
return x;
}
7 changes: 7 additions & 0 deletions test/call.prog
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
fn test(a, b) {
return double(a) + double(b);
}

fn double(b) {
return b * 2;
}
4 changes: 4 additions & 0 deletions test/constant.prog
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
fn test(a, b) {
let x = a + b + 2;
return x;
}
4 changes: 4 additions & 0 deletions test/div.prog
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
fn test(a, b) {
let x = a / b;
return x;
}
9 changes: 9 additions & 0 deletions test/factorial.prog
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
fn test(n, acc) {
if n != 0 {
if n != 1 {
acc = test(n - 1, acc * n);
}
}

return acc;
}
11 changes: 11 additions & 0 deletions test/ifelse.prog
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
fn test(a, b) {
let x = b;

if a == 1 {
x = b * 2;
} else {
x = b;
}

return x;
}
4 changes: 4 additions & 0 deletions test/mul.prog
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
fn test(a, b) {
let x = a * b;
return x;
}
4 changes: 4 additions & 0 deletions test/sub.prog
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
fn test(a, b) {
let x = a - b;
return x;
}

0 comments on commit ffc9c94

Please sign in to comment.