aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--examples/hello.sloth18
-rw-r--r--sloth/src/analysis/setup.rs28
-rw-r--r--sloth/src/codegen/mod.rs85
-rw-r--r--sloth/src/lexer.rs6
-rw-r--r--sloth/src/parser/stmt.rs1
5 files changed, 97 insertions, 41 deletions
diff --git a/examples/hello.sloth b/examples/hello.sloth
index 8f42051..5aa54e9 100644
--- a/examples/hello.sloth
+++ b/examples/hello.sloth
@@ -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;
}
diff --git a/sloth/src/analysis/setup.rs b/sloth/src/analysis/setup.rs
index f124663..274ec4a 100644
--- a/sloth/src/analysis/setup.rs
+++ b/sloth/src/analysis/setup.rs
@@ -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);
+ }
_ => (),
}
}
@@ -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)?;
}
@@ -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, .. } => {
diff --git a/sloth/src/codegen/mod.rs b/sloth/src/codegen/mod.rs
index fbf3d5f..65277e7 100644
--- a/sloth/src/codegen/mod.rs
+++ b/sloth/src/codegen/mod.rs
@@ -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
@@ -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::*;
diff --git a/sloth/src/lexer.rs b/sloth/src/lexer.rs
index 01eeb46..0b2399f 100644
--- a/sloth/src/lexer.rs
+++ b/sloth/src/lexer.rs
@@ -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'
}
@@ -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() {
diff --git a/sloth/src/parser/stmt.rs b/sloth/src/parser/stmt.rs
index c326a0c..8bfbda5 100644
--- a/sloth/src/parser/stmt.rs
+++ b/sloth/src/parser/stmt.rs
@@ -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(),