aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--examples/hello.sloth15
-rw-r--r--sloth/src/codegen/mod.rs173
-rw-r--r--sloth/src/main.rs6
-rw-r--r--sloth/src/parser/ast.rs1
-rw-r--r--sloth/src/parser/mod.rs11
-rw-r--r--sloth/src/parser/stmt.rs4
-rw-r--r--sloth/src/symtable.rs6
-rw-r--r--test.c16
-rwxr-xr-xtest.sh3
9 files changed, 174 insertions, 61 deletions
diff --git a/examples/hello.sloth b/examples/hello.sloth
index 1bbdbd4..f4e6692 100644
--- a/examples/hello.sloth
+++ b/examples/hello.sloth
@@ -1,11 +1,22 @@
-fn test() [Int 3] {
- var list: [Int 3] = [500, 5, 7];
+fn test() [Int] {
+ var list: [Int] = [500, 5, 7];
vpushi(list, 3);
vpushi(list, 3);
vpushi(list, 3);
vpushi(list, 5);
+ var x: Int = vpopi(list);
+ vpushi(list, x);
+ vpushi(list, x * 2);
+ vpushi(list, x * 3);
+
return list;
}
+fn testtwo(list: [Int]) Int {
+ #vpopi(list);
+ var x: Int = vpopi(list);
+ return x;
+}
+
diff --git a/sloth/src/codegen/mod.rs b/sloth/src/codegen/mod.rs
index ad6b451..0035802 100644
--- a/sloth/src/codegen/mod.rs
+++ b/sloth/src/codegen/mod.rs
@@ -7,9 +7,9 @@ use inkwell::module::Module;
use inkwell::targets::{
CodeModel, FileType, InitializationConfig, RelocMode, Target, TargetMachine,
};
-use inkwell::types::{BasicMetadataTypeEnum, BasicType, BasicTypeEnum};
+use inkwell::types::{BasicMetadataTypeEnum, BasicType, BasicTypeEnum, FunctionType};
use inkwell::values::{
- BasicMetadataValueEnum, BasicValue, BasicValueEnum, FunctionValue, PointerValue,
+ BasicMetadataValueEnum, BasicValue, BasicValueEnum, FunctionValue, IntValue, PointerValue,
};
use inkwell::{AddressSpace, FloatPredicate, IntPredicate, OptimizationLevel};
use itertools::{Either, Itertools};
@@ -46,9 +46,14 @@ impl<'ctx> Codegen<'ctx> {
references: Default::default(),
};
- this.INTRINSIC_vpush("i", Type::Integer);
- this.INTRINSIC_vpush("f", Type::Float);
- this.INTRINSIC_vpush("b", Type::Boolean);
+ for (c, t) in [
+ ("i", Type::Integer),
+ ("f", Type::Float),
+ ("b", Type::Boolean),
+ ] {
+ this.INTRINSIC_vpush(c, t.clone());
+ this.INTRINSIC_vpop(c, t);
+ }
this
}
@@ -164,19 +169,45 @@ impl<'ctx> Codegen<'ctx> {
}
StmtKind::DefineFunction(function) => {
let table = code.symtable.clone();
- self.codegen_function(table, function.clone());
+ self.codegen_function(
+ table,
+ // if let FunctionKind::Normal { body } = &function.kind {
+ // Some(body.symtable.clone())
+ // } else {
+ // None
+ // },
+ function.clone(),
+ );
// If the function is written in sloth (as opposed to an extern one) we generate
// the block contents
if let FunctionKind::Normal { body } = &function.kind {
- if let StmtKind::Block(body) = &body.kind {
+ if let StmtKind::Block(code) = &body.kind {
// Make the block containing the code for the function
let func = self.current_func.unwrap();
let block = self.context.append_basic_block(func, "entrypoint");
// Position the builder to be at the block
self.builder.position_at_end(block);
- self.codegen_block(body);
+
+ // FIXME 🍝
+ // This code adds parameters to the body so they're accessible
+ let body_table = body.symtable.clone();
+ for (i, input) in function.inputs.iter().enumerate() {
+ let symbol = body_table.get_value(&input.identifier).unwrap();
+
+ let ptr = self.codegen_alloca(
+ self.type_as_basic_type(symbol.typ),
+ &input.identifier,
+ );
+ let init_value = func.get_nth_param(i as u32).unwrap();
+
+ self.builder.build_store(ptr, init_value);
+ self.references.insert(symbol.id, ptr);
+ }
+
+ // Codegen the function body
+ self.codegen_block(code);
if self.current_func_void {
self.builder.build_return(None);
@@ -222,15 +253,9 @@ impl<'ctx> Codegen<'ctx> {
.as_basic_type_enum();
let vector_type = self.context.struct_type(&[i32_type, i32_type, typ], false);
-
let ptr_to_that = vector_type.ptr_type(AddressSpace::default());
ptr_to_that.fn_type(&inputs_typ, false)
-
- // killll me
- // self.type_as_basic_type(*typ.clone())
- // .ptr_type(AddressSpace::default())
- // .fn_type(&inputs_typ, false)
}
_ => todo!(),
};
@@ -478,34 +503,28 @@ impl<'ctx> Codegen<'ctx> {
#[allow(non_snake_case)]
impl<'ctx> Codegen<'ctx> {
- fn INTRINSIC_vpush(&mut self, name: &str, typ: Type) {
+ fn _setup(&mut self, name: &str, func_type: FunctionType<'ctx>) {
// Preparing for function
self.references.clear();
- let bruh = self.type_as_basic_type(Type::Array {
- typ: Box::new(typ.clone()),
- len: 0,
- });
-
- let inputs = &[bruh.into(), self.type_as_metadata_type(typ.clone())];
-
// Making the function
- let func_type = self.context.void_type().fn_type(inputs, false);
- let func = self
- .module
- .add_function(&format!("vpush{name}"), func_type, None);
+ let func = self.module.add_function(name, func_type, None);
self.current_func = Some(func);
self.current_func_void = true;
let block = self.context.append_basic_block(func, "entrypoint");
self.builder.position_at_end(block);
+ }
- // Writing the logic
- let element_type = self.type_as_basic_type(typ);
- let element_ptr_type = element_type.ptr_type(AddressSpace::default());
-
+ fn _get_ptrs(
+ &mut self,
+ element_type: BasicTypeEnum<'ctx>,
+ vector_ptr: PointerValue<'ctx>,
+ ) -> (PointerValue<'ctx>, PointerValue<'ctx>, PointerValue<'ctx>) {
+ // Types
let i32_type = self.context.i32_type();
+ let element_ptr_type = element_type.ptr_type(AddressSpace::default());
let vector_type = self.context.struct_type(
&[
@@ -516,8 +535,7 @@ impl<'ctx> Codegen<'ctx> {
false,
);
- let vector_ptr = func.get_nth_param(0).unwrap().into_pointer_value();
-
+ // Getting pointers
let size_ptr = self
.builder
.build_struct_gep(vector_type, vector_ptr, 0, "sizegep")
@@ -531,11 +549,26 @@ impl<'ctx> Codegen<'ctx> {
.build_struct_gep(vector_type, vector_ptr, 2, "innergep")
.unwrap();
+ (size_ptr, cap_ptr, inner_ptr)
+ }
+
+ fn _get_values(
+ &mut self,
+ element_type: BasicTypeEnum<'ctx>,
+ size_ptr: PointerValue<'ctx>,
+ cap_ptr: PointerValue<'ctx>,
+ inner_ptr: PointerValue<'ctx>,
+ ) -> (IntValue<'ctx>, IntValue<'ctx>, PointerValue<'ctx>) {
+ // Types
+ let i32_type = self.context.i32_type();
+ let element_ptr_type = element_type.ptr_type(AddressSpace::default());
+
+ // Getting values
let size = self
.builder
.build_load(i32_type, size_ptr, "size")
.into_int_value();
- let _cap = self
+ let cap = self
.builder
.build_load(i32_type, cap_ptr, "cap")
.into_int_value();
@@ -544,21 +577,85 @@ impl<'ctx> Codegen<'ctx> {
.build_load(element_ptr_type, inner_ptr, "inner")
.into_pointer_value();
+ (size, cap, inner)
+ }
+
+ fn INTRINSIC_vpush(&mut self, name: &str, typ: Type) {
+ // Setup function
+ let array_input = self.type_as_basic_type(Type::Array {
+ typ: Box::new(typ.clone()),
+ });
+ let inputs = &[array_input.into(), self.type_as_metadata_type(typ.clone())];
+ let func_type = self.context.void_type().fn_type(inputs, false);
+ self._setup(&format!("vpush{name}"), func_type);
+ let func = self.current_func.unwrap();
+
+ // Types
+ let element_type = self.type_as_basic_type(typ);
+ let i32_type = self.context.i32_type();
+
+ // Getting the pointers and values needed
+ let vector_ptr = func.get_nth_param(0).unwrap().into_pointer_value();
+ let (size_ptr, cap_ptr, inner_ptr) = self._get_ptrs(element_type, vector_ptr);
+ let (size, _cap, inner) = self._get_values(element_type, size_ptr, cap_ptr, inner_ptr);
+
+ // FIXME: Array cant grow as of now
+
// Put the new element into backing array
let element = func.get_nth_param(1).unwrap();
let slot_ptr = unsafe { self.builder.build_gep(element_type, inner, &[size], "slot") };
-
self.builder.build_store(slot_ptr, element);
- // TODO: Handle going over capacity
-
// Increase size tracker
- let new_size = self
+ let updated_size = self
.builder
.build_int_add(size, i32_type.const_int(1, false), "");
- self.builder.build_store(size_ptr, new_size);
+ self.builder.build_store(size_ptr, updated_size);
// Function return
self.builder.build_return(None);
}
+
+ fn INTRINSIC_vpop(&mut self, name: &str, typ: Type) {
+ // Setup function
+ let array_input = self.type_as_basic_type(Type::Array {
+ typ: Box::new(typ.clone()),
+ });
+ let inputs = &[array_input.into(), self.type_as_metadata_type(typ.clone())];
+ let func_type = match typ {
+ Type::Integer => self.context.i32_type().fn_type(inputs, false),
+ Type::Float => self.context.f32_type().fn_type(inputs, false),
+ Type::Boolean => self.context.bool_type().fn_type(inputs, false),
+ _ => panic!(),
+ };
+ self._setup(&format!("vpop{name}"), func_type);
+ let func = self.current_func.unwrap();
+
+ // Types
+ let element_type = self.type_as_basic_type(typ);
+ let i32_type = self.context.i32_type();
+
+ // Getting the pointers and values needed
+ let vector_ptr = func.get_nth_param(0).unwrap().into_pointer_value();
+ let (size_ptr, cap_ptr, inner_ptr) = self._get_ptrs(element_type, vector_ptr);
+ let (size, _cap, inner) = self._get_values(element_type, size_ptr, cap_ptr, inner_ptr);
+
+ // Get the last element in the array
+ let element_idx = self
+ .builder
+ .build_int_sub(size, i32_type.const_int(1, false), "");
+ let element_ptr = unsafe {
+ self.builder
+ .build_gep(element_type, inner, &[element_idx], "elementptr")
+ };
+ let element = self
+ .builder
+ .build_load(element_type, element_ptr, "element");
+
+ // Decrease the size tracker
+ self.builder.build_store(size_ptr, element_idx);
+
+ // Return element
+ self.builder.build_return(Some(&element));
+ }
}
diff --git a/sloth/src/main.rs b/sloth/src/main.rs
index dec55de..5522082 100644
--- a/sloth/src/main.rs
+++ b/sloth/src/main.rs
@@ -59,7 +59,11 @@ fn main() {
global_symtable.insert("vpushi".into(), dummy.clone());
global_symtable.insert("vpushf".into(), dummy.clone());
- global_symtable.insert("vpushb".into(), dummy);
+ global_symtable.insert("vpushb".into(), dummy.clone());
+
+ global_symtable.insert("vpopi".into(), dummy.clone());
+ global_symtable.insert("vpopf".into(), dummy.clone());
+ global_symtable.insert("vpopb".into(), dummy);
// Parsing
let tokens = Lexer::new(&source).collect_vec();
diff --git a/sloth/src/parser/ast.rs b/sloth/src/parser/ast.rs
index 66bf851..00719e7 100644
--- a/sloth/src/parser/ast.rs
+++ b/sloth/src/parser/ast.rs
@@ -255,7 +255,6 @@ pub struct FunctionInput {
pub struct TypeIdentifier {
pub name: String,
pub is_list: bool,
- pub list_len: u32,
}
impl Display for TypeIdentifier {
diff --git a/sloth/src/parser/mod.rs b/sloth/src/parser/mod.rs
index 6dd534a..a1f251e 100644
--- a/sloth/src/parser/mod.rs
+++ b/sloth/src/parser/mod.rs
@@ -126,20 +126,11 @@ impl<'a> AstParser<'a> {
let name = self.consume_identifier()?;
- let mut list_len = 0;
if is_list {
- if let Literal::Integer(i) = self.consume_literal()? {
- list_len = i as u32;
- }
-
self.consume(TokenType::ClosingBracket, "Expected ']'")?;
}
- Ok(TypeIdentifier {
- name,
- is_list,
- list_len,
- })
+ Ok(TypeIdentifier { name, is_list })
}
pub fn reserve_id(&mut self) -> i32 {
diff --git a/sloth/src/parser/stmt.rs b/sloth/src/parser/stmt.rs
index d8c091d..d8a0509 100644
--- a/sloth/src/parser/stmt.rs
+++ b/sloth/src/parser/stmt.rs
@@ -311,7 +311,6 @@ mod tests {
typ: TypeIdentifier {
name: "Int".to_string(),
is_list: false,
- list_len: 0,
},
}));
@@ -346,13 +345,11 @@ mod tests {
typ: TypeIdentifier {
name: "Int".to_owned(),
is_list: false,
- list_len: 0,
},
}],
output: Some(TypeIdentifier {
name: "Int".to_owned(),
is_list: false,
- list_len: 0,
}),
kind: FunctionKind::Normal {
body: Box::new(Stmt::without_table(
@@ -374,7 +371,6 @@ mod tests {
typ: TypeIdentifier {
name: "Int".to_owned(),
is_list: false,
- list_len: 0,
},
}),
Stmt::without_table(7, StmtKind::AssignVariable {
diff --git a/sloth/src/symtable.rs b/sloth/src/symtable.rs
index 5a89c7a..8af1c60 100644
--- a/sloth/src/symtable.rs
+++ b/sloth/src/symtable.rs
@@ -59,10 +59,7 @@ impl SymbolTable {
if let Symbol::Type(ref typ) = *symbol {
let mut typ = typ.clone();
if identifier.is_list {
- typ = Type::Array {
- typ: Box::new(typ),
- len: identifier.list_len,
- };
+ typ = Type::Array { typ: Box::new(typ) };
}
return Some(typ);
}
@@ -160,6 +157,5 @@ pub enum Type {
},
Array {
typ: Box<Type>,
- len: u32,
},
}
diff --git a/test.c b/test.c
index c7e7f5c..988b352 100644
--- a/test.c
+++ b/test.c
@@ -7,6 +7,7 @@ typedef struct {
} IntVec;
IntVec* test();
+int testtwo(IntVec*);
int main() {
IntVec* v = test();
@@ -22,5 +23,20 @@ int main() {
int value = inner[i];
printf("%d ", value);
}
+ puts("\n\n");
+
+ testtwo(v);
+
+ size = (*v).size;
+ cap = (*v).cap;
+ inner = (*v).inner;
+
+ printf("%d\n", size);
+ printf("%d\n", cap);
+
+ for (int i = 0; i < size; ++i) {
+ int value = inner[i];
+ printf("%d ", value);
+ }
puts("\n");
}
diff --git a/test.sh b/test.sh
new file mode 100755
index 0000000..59dae87
--- /dev/null
+++ b/test.sh
@@ -0,0 +1,3 @@
+cargo run examples/hello.sloth
+clang output.o test.c -o output
+./output