WIP: str_starts_with loop

This commit is contained in:
Dimitar Apostolov 2020-10-18 22:04:35 +02:00
parent 0ae045c1f3
commit 9beeafb6cd
2 changed files with 67 additions and 10 deletions

View file

@ -1393,7 +1393,7 @@ where
// This helper simulates a basic for loop, where // This helper simulates a basic for loop, where
// and index increments up from 0 to some end value // and index increments up from 0 to some end value
fn incrementing_index_loop<'ctx, LoopFn>( pub fn incrementing_index_loop<'ctx, LoopFn>(
builder: &Builder<'ctx>, builder: &Builder<'ctx>,
ctx: &'ctx Context, ctx: &'ctx Context,
parent: FunctionValue<'ctx>, parent: FunctionValue<'ctx>,

View file

@ -1,6 +1,7 @@
use crate::llvm::build::{ptr_from_symbol, Env, InPlace, Scope}; use crate::llvm::build::{ptr_from_symbol, Env, InPlace, Scope};
use crate::llvm::build_list::{ use crate::llvm::build_list::{
allocate_list, build_basic_phi2, empty_list, incrementing_elem_loop, load_list_ptr, store_list, allocate_list, build_basic_phi2, empty_list, incrementing_elem_loop, incrementing_index_loop,
load_list_ptr, store_list,
}; };
use crate::llvm::convert::{collection, ptr_int}; use crate::llvm::convert::{collection, ptr_int};
use inkwell::builder::Builder; use inkwell::builder::Builder;
@ -601,7 +602,7 @@ pub fn str_starts_with<'a, 'ctx, 'env>(
first_str_symbol: Symbol, first_str_symbol: Symbol,
second_str_symbol: Symbol, second_str_symbol: Symbol,
) -> BasicValueEnum<'ctx> { ) -> BasicValueEnum<'ctx> {
let _builder = env.builder; let builder = env.builder;
let ctx = env.context; let ctx = env.context;
let prefix_str_ptr = ptr_from_symbol(scope, first_str_symbol); let prefix_str_ptr = ptr_from_symbol(scope, first_str_symbol);
let str_ptr = ptr_from_symbol(scope, second_str_symbol); let str_ptr = ptr_from_symbol(scope, second_str_symbol);
@ -612,31 +613,87 @@ pub fn str_starts_with<'a, 'ctx, 'env>(
parent, parent,
*prefix_str_ptr, *prefix_str_ptr,
bool_wrapper_type, bool_wrapper_type,
|_prefix_str_ptr, prefix_str_len, _prefix_str_smallness| { |prefix_str_ptr, prefix_str_len, _prefix_str_smallness| {
load_str( load_str(
env, env,
parent, parent,
*str_ptr, *str_ptr,
bool_wrapper_type, bool_wrapper_type,
|_second_str_ptr, second_str_len, _second_str_smallness| { |input_str_ptr, input_str_len, _second_str_smallness| {
let return_false = || ctx.bool_type().const_int(0, false).into(); let return_false = || ctx.bool_type().const_zero().into();
let if_second_str_is_longer_or_equal_to_prefix = env.builder.build_int_compare( let if_input_str_is_longer_or_equal_to_prefix = builder.build_int_compare(
IntPredicate::UGE, IntPredicate::UGE,
second_str_len, input_str_len,
prefix_str_len, prefix_str_len,
"str_longer_than_prefix", "str_longer_than_prefix",
); );
let check_if_str_starts_with_prefix = || { let check_if_str_starts_with_prefix = || {
ctx.bool_type().const_int(1, false).into()
// Loop over prefix and compare each character to the one from the input // Loop over prefix and compare each character to the one from the input
// string at the same index // string at the same index
// If they are different - return false // If they are different - return false
incrementing_index_loop(
builder,
ctx,
parent,
prefix_str_len,
"starts_with_loop",
|index| {
// The pointer to the element in the list
let prefix_ptr = unsafe {
builder.build_in_bounds_gep(
prefix_str_ptr,
&[index],
"prefix_index",
)
};
let input_ptr = unsafe {
builder.build_in_bounds_gep(
input_str_ptr,
&[index],
"input_str_index",
)
};
let prefix_char = builder
.build_load(prefix_ptr, "get_prefix_char")
.into_int_value();
let input_char = builder
.build_load(input_ptr, "get_input_char")
.into_int_value();
let comparison = builder.build_int_compare(
IntPredicate::EQ,
prefix_char,
input_char,
"prefix_char_equals_to_input_char",
);
let condition_block =
ctx.append_basic_block(parent, "condition_block");
// Empty block to continue the loop if the comparison is true
let then_block = ctx.append_basic_block(parent, "then_block");
//
let else_block = ctx.append_basic_block(parent, "else_block");
// Build the condition_block
builder.position_at_end(condition_block);
builder
.build_conditional_branch(comparison, then_block, else_block);
// Build the else_block
builder.position_at_end(else_block);
// Do an early return
builder.build_return(Some(&ctx.bool_type().const_zero()));
// Return true by default
// builder.build_return(Some(&ctx.bool_type().const_int(1, false)));
},
);
}; };
build_basic_phi2( build_basic_phi2(
env, env,
parent, parent,
if_second_str_is_longer_or_equal_to_prefix, if_input_str_is_longer_or_equal_to_prefix,
check_if_str_starts_with_prefix, check_if_str_starts_with_prefix,
return_false, return_false,
bool_wrapper_type, bool_wrapper_type,