Skip to content

Commit

Permalink
For loops
Browse files Browse the repository at this point in the history
  • Loading branch information
cody-quinn committed Jun 29, 2023
1 parent c8a987d commit ee2133a
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 41 deletions.
18 changes: 3 additions & 15 deletions examples/hello.sloth
Original file line number Diff line number Diff line change
@@ -1,19 +1,7 @@
fn main() Int {
var x: [Int] = [5];
vpopi(x);
var i: Int = 0;
while i < 100 {
vpushi(x, randGen(0, 100));
i = i + 1;
var i: Int = 10;
for j in 0..i {
print(istr(j));
}

var y: Int = vgeti(x, 42);
var y: Int = vgeti(x, 45);
var y: Int = vgeti(x, 41);
var y: Int = vgeti(x, 49);
println(istr(y));


print("Hello World\n");
return 0;
}
28 changes: 22 additions & 6 deletions sloth/src/analysis/setup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,19 @@ impl Populator {
}
}
}
StmtKind::ForStmt {
identifier, body, ..
} => {
// When a for statement exists we must bind the identifier
// to the value of the iterator.
let mut body_table = body.symtable.clone();
let symbol = Symbol::Value(ValueSymbol {
typ: Type::Integer,
id: self.reserve_id(),
});

body_table.insert(identifier.to_owned(), symbol);
}
_ => (),
}
}
Expand Down Expand Up @@ -134,11 +147,7 @@ pub(super) fn propagate_types_stmt(node: &mut Stmt) -> Result<(), AnalysisError>
propagate_types(condition)?;
propagate_types_stmt(body)?;
}
StmtKind::ForStmt {
iterator,
identifier,
body,
} => {
StmtKind::ForStmt { iterator, body, .. } => {
propagate_types(iterator)?;
propagate_types_stmt(body)?;
}
Expand Down Expand Up @@ -223,10 +232,17 @@ pub(super) fn propagate_types(node: &mut Expr) -> Result<(), AnalysisError> {
| BinaryOp::GtEq
| BinaryOp::EqEq
| BinaryOp::NotEq => Type::Boolean,
BinaryOp::LogicalAnd | BinaryOp::LogicalOr | BinaryOp::Range => lhs
BinaryOp::LogicalAnd | BinaryOp::LogicalOr => lhs
.typ
.clone()
.ok_or(AnalysisError::Unknown(node.line, "owo?? choco???"))?,
BinaryOp::Range => Type::Iterator {
typ: Box::new(
lhs.typ
.clone()
.ok_or(AnalysisError::Unknown(node.line, "skill issue"))?,
),
},
}
}
ExprKind::UnaryOp { value, .. } => {
Expand Down
85 changes: 66 additions & 19 deletions sloth/src/codegen/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,17 +164,58 @@ impl<'ctx> Codegen<'ctx> {
let body_bb = self.context.append_basic_block(func, "loop body");
let after_bb = self.context.append_basic_block(func, "after loop");

// Before the loop
let i32_type = self.context.i32_type();
let range_type = self
.context
.struct_type(&[i32_type.into(), i32_type.into()], false);

let range = self.codegen_expr(iterator).unwrap().into_struct_value();
let range_ptr = self.codegen_alloca(range_type.as_basic_type_enum(), "range");
self.builder.build_store(range_ptr, range);

let current_ptr = self
.builder
.build_struct_gep(range_type, range_ptr, 0, "current")
.expect("Butter corn salt!");

let table = body.symtable.clone();
let symbol = table.get_value(identifier).unwrap();
self.references.insert(symbol.id, current_ptr);

let end_ptr = self
.builder
.build_struct_gep(range_type, range_ptr, 1, "end")
.expect("❌🧢");

self.builder.build_unconditional_branch(loop_bb);

// Building the blocks for the head of the loop
self.builder.position_at_end(loop_bb);
let iterator = self.codegen_expr(iterator).unwrap().into_int_value();
let current = self.builder.build_load(i32_type, current_ptr, "");
let end = self.builder.build_load(i32_type, end_ptr, "");
let condition = self.builder.build_int_compare(
IntPredicate::SLT,
current.into_int_value(),
end.into_int_value(),
"",
);

self.builder
.build_conditional_branch(iterator, body_bb, after_bb);
.build_conditional_branch(condition, body_bb, after_bb);

// Building the blocks for the body of the loop
self.builder.position_at_end(body_bb);
self.codegen_stmt(body);

let current = self.builder.build_load(i32_type, current_ptr, "");
let updated_current = self.builder.build_int_add(
current.into_int_value(),
i32_type.const_int(1, true),
"",
);
self.builder.build_store(current_ptr, updated_current);

self.builder.build_unconditional_branch(loop_bb);

// Position the builder at the end of the loop
Expand Down Expand Up @@ -330,26 +371,32 @@ impl<'ctx> Codegen<'ctx> {
let r = self.codegen_expr(rhs).unwrap().into_int_value();

match op {
BinaryOp::Add => self.builder.build_int_add(l, r, "add"),
BinaryOp::Sub => self.builder.build_int_sub(l, r, "sub"),
BinaryOp::Mul => self.builder.build_int_mul(l, r, "mul"),
BinaryOp::Div => self.builder.build_int_signed_div(l, r, "div"),
BinaryOp::Mod => self.builder.build_int_signed_rem(l, r, "mod"),

BinaryOp::Gt => self.builder.build_int_compare(SGT, l, r, "gt"),
BinaryOp::GtEq => self.builder.build_int_compare(SGE, l, r, ""),
BinaryOp::Lt => self.builder.build_int_compare(SLT, l, r, "lt"),
BinaryOp::LtEq => self.builder.build_int_compare(SLE, l, r, ""),

BinaryOp::EqEq => self.builder.build_int_compare(EQ, l, r, ""),
BinaryOp::NotEq => self.builder.build_int_compare(NE, l, r, ""),

BinaryOp::LogicalAnd => self.builder.build_and(l, r, "logand"),
BinaryOp::LogicalOr => self.builder.build_or(l, r, "logor"),
BinaryOp::Add => self.builder.build_int_add(l, r, "add").into(),
BinaryOp::Sub => self.builder.build_int_sub(l, r, "sub").into(),
BinaryOp::Mul => self.builder.build_int_mul(l, r, "mul").into(),
BinaryOp::Div => self.builder.build_int_signed_div(l, r, "div").into(),
BinaryOp::Mod => self.builder.build_int_signed_rem(l, r, "mod").into(),

BinaryOp::Gt => self.builder.build_int_compare(SGT, l, r, "gt").into(),
BinaryOp::GtEq => self.builder.build_int_compare(SGE, l, r, "").into(),
BinaryOp::Lt => self.builder.build_int_compare(SLT, l, r, "lt").into(),
BinaryOp::LtEq => self.builder.build_int_compare(SLE, l, r, "").into(),

BinaryOp::EqEq => self.builder.build_int_compare(EQ, l, r, "").into(),
BinaryOp::NotEq => self.builder.build_int_compare(NE, l, r, "").into(),

BinaryOp::LogicalAnd => self.builder.build_and(l, r, "logand").into(),
BinaryOp::LogicalOr => self.builder.build_or(l, r, "logor").into(),

BinaryOp::Range => {
// FIXME: Change Range type to Iterator type
self.context
.const_struct(&[l.into(), r.into()], false)
.into()
}

_ => panic!("{op:?}"),
}
.into()
}
Some(Type::Float) => {
use FloatPredicate::*;
Expand Down
6 changes: 5 additions & 1 deletion sloth/src/lexer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,10 @@ impl<'a> Lexer<'a> {
self.window[0]
}

fn peek2(&self) -> char {
self.window[1]
}

fn eof(&self) -> bool {
self.peek() == '\0'
}
Expand Down Expand Up @@ -323,7 +327,7 @@ impl<'a> Lexer<'a> {
value.push(self.advance());
}

if self.peek() == '.' {
if self.peek() == '.' && self.peek2() != '.' {
value.push(self.advance());

while self.peek().is_ascii_digit() {
Expand Down
1 change: 1 addition & 0 deletions sloth/src/parser/stmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ impl<'a> AstParser<'a> {

TokenType::If => self.if_stmt(),
TokenType::While => self.while_stmt(),
TokenType::For => self.for_stmt(),
TokenType::Var => self.define_variable(),
TokenType::Fn => self.define_function(false),
TokenType::Return => self.return_stmt(),
Expand Down

0 comments on commit ee2133a

Please sign in to comment.