Skip to content

Commit

Permalink
builtin len func completed
Browse files Browse the repository at this point in the history
  • Loading branch information
tahadostifam committed Mar 2, 2025
1 parent 06b7b17 commit d2a1281
Show file tree
Hide file tree
Showing 8 changed files with 112 additions and 55 deletions.
56 changes: 36 additions & 20 deletions compiler/src/builtins/funcs.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use crate::Compiler;
use gccjit_sys::*;
use utils::compiler_error;
use utils::compile_time_errors::errors::*;
use std::{ffi::CString, ptr::null_mut};
use utils::compile_time_errors::errors::*;
use utils::compiler_error;

pub fn builtin_func__len(
pub fn builtin_func_len(
file_path: String,
context: *mut gcc_jit_context,
args: Vec<*mut gcc_jit_rvalue>,
Expand All @@ -17,7 +17,7 @@ pub fn builtin_func__len(

let size_t_type = Compiler::size_t_type(context);
let void_ptr_type = Compiler::void_ptr_type(context);
let wrapper_func_name = CString::new("__cyrus_builtin_wrapped_func__len").unwrap();
let wrapper_func_name = CString::new("__cyrus_builtin__len").unwrap();
// TODO Check param type to be array or string
let rvalue_param_name = CString::new("rvalue").unwrap();
let rvalue_param =
Expand All @@ -38,40 +38,56 @@ pub fn builtin_func__len(
let block_name = CString::new("entry").unwrap();
let block = unsafe { gcc_jit_function_new_block(wrapper_func, block_name.as_ptr()) };

let sizeof_array = unsafe { gcc_jit_context_new_sizeof(context, rvalue_type) };
let first_item_of_array = unsafe {
gcc_jit_context_new_array_access(
let sizeof_array = unsafe {
gcc_jit_context_new_cast(
context,
null_mut(),
gcc_jit_context_new_sizeof(context, rvalue_type),
size_t_type,
)
};

let sizeof_first_item = unsafe {
gcc_jit_context_new_cast(
context,
null_mut(),
rvalue,
gcc_jit_context_new_rvalue_from_int(context, Compiler::i32_type(context), 0),
gcc_jit_context_new_sizeof(
context,
gcc_jit_rvalue_get_type(gcc_jit_lvalue_as_rvalue(gcc_jit_context_new_array_access(
context,
null_mut(),
rvalue,
gcc_jit_context_new_rvalue_from_int(context, Compiler::i32_type(context), 0),
))),
),
size_t_type,
)
};

let len_result = unsafe {
let mut return_rvalue = unsafe {
gcc_jit_context_new_binary_op(
context,
null_mut(),
gcc_jit_binary_op::GCC_JIT_BINARY_OP_DIVIDE,
size_t_type,
Compiler::i32_type(context),
sizeof_array,
unsafe {
gcc_jit_lvalue_as_rvalue(first_item_of_array)
},
sizeof_first_item,
)
};
return_rvalue = unsafe { gcc_jit_context_new_cast(context, null_mut(), return_rvalue, size_t_type) };

unsafe { gcc_jit_block_end_with_return(block, null_mut(), len_result) };

return len_result;
unsafe { gcc_jit_block_end_with_return(block, null_mut(), return_rvalue) };
return return_rvalue;
}

pub fn builtin_func__sizeof(file_path: String,
pub fn builtin_func_sizeof(
_: String,
context: *mut gcc_jit_context,
args: Vec<*mut gcc_jit_rvalue>,) -> *mut gcc_jit_rvalue {
args: Vec<*mut gcc_jit_rvalue>,
) -> *mut gcc_jit_rvalue {
let rvalue = args.first().unwrap();
let rvalue_type = unsafe { gcc_jit_rvalue_get_type(*rvalue) };
let rvalue_size = unsafe { gcc_jit_context_new_sizeof(context, rvalue_type) };

return rvalue_size;
}
}
8 changes: 4 additions & 4 deletions compiler/src/builtins/loader.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use gccjit_sys::{gcc_jit_context, gcc_jit_rvalue};
use std::{collections::HashMap, sync::LazyLock};

use super::funcs::builtin_func__len;
use crate::builtins::funcs::builtin_func__sizeof;
use super::funcs::builtin_func_len;
use crate::builtins::funcs::builtin_func_sizeof;

pub type BuiltinFuncDef =
fn(file_path: String, context: *mut gcc_jit_context, args: Vec<*mut gcc_jit_rvalue>) -> *mut gcc_jit_rvalue;
Expand All @@ -22,7 +22,7 @@ macro_rules! build_builtin_funcs {

pub static BUILTIN_FUNCS: LazyLock<BuiltinFuncsTable> = LazyLock::new(|| {
build_builtin_funcs! {
"len" => builtin_func__len,
"sizeof" => builtin_func__sizeof
"len" => builtin_func_len,
"sizeof" => builtin_func_sizeof
}
});
57 changes: 44 additions & 13 deletions compiler/src/expressions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ use std::rc::Rc;
use ast::ast::*;
use ast::token::*;
use gccjit_sys::*;
use utils::compiler_error;
use utils::compile_time_errors::errors::*;
use utils::compiler_error;
use utils::purify_string::purify_string;

use crate::scope::ScopeRef;
use crate::Compiler;
use crate::scope::ScopeRef;

impl Compiler {
pub(crate) fn access_identifier_values(
Expand All @@ -32,7 +32,10 @@ impl Compiler {
}
}

compiler_error!(format!("'{}' is not defined in this scope.", from_package.to_string()), self.file_path.clone())
compiler_error!(
format!("'{}' is not defined in this scope.", from_package.to_string()),
self.file_path.clone()
)
}

fn compile_identifier(&mut self, scope: ScopeRef, identifier: Identifier) -> *mut gcc_jit_rvalue {
Expand Down Expand Up @@ -66,7 +69,9 @@ impl Compiler {

let last_chain = chains_copy.last().unwrap();
if let Some(method_call) = last_chain.method_call.clone() {
self.eval_func_call(result, method_call.loc);
if result != null_mut() {
self.eval_func_call(result, method_call.loc);
}
null_mut()
} else {
result
Expand All @@ -86,7 +91,9 @@ impl Compiler {
let item = struct_field_access.chains[struct_field_access.chains.len() - 1].clone();
if let Some(method_call) = item.method_call {
let rvalue = self.compile_struct_field_access(scope, *struct_field_access.clone());
self.eval_func_call(rvalue, method_call.loc.clone());
if rvalue != null_mut() {
self.eval_func_call(rvalue, method_call.loc.clone());
}
}
null_mut()
}
Expand Down Expand Up @@ -193,7 +200,10 @@ impl Compiler {
dimensions: Vec<Expression>,
) -> *mut gcc_jit_lvalue {
if dimensions.len() == 0 {
compiler_error!("You are trying to access an array item lvalue with empty dimension.", self.file_path.clone())
compiler_error!(
"You are trying to access an array item lvalue with empty dimension.",
self.file_path.clone()
)
}

let mut result: *mut gcc_jit_lvalue = variable;
Expand All @@ -217,13 +227,19 @@ impl Compiler {

result = lvalue;
} else {
compiler_error!("Unable to access array lvalue through a non-integer literal.", self.file_path.clone())
compiler_error!(
"Unable to access array lvalue through a non-integer literal.",
self.file_path.clone()
)
}
}
}

if result == variable {
compiler_error!("Unexpected behavior when trying to compile array_dimension_as_lvalue.", self.file_path.clone())
compiler_error!(
"Unexpected behavior when trying to compile array_dimension_as_lvalue.",
self.file_path.clone()
)
}

result
Expand Down Expand Up @@ -316,7 +332,10 @@ impl Compiler {

return casted_rvalue;
} else {
compiler_error!("Incorrect usage of the assignment. Assignments must be performed inside a valid block.", self.file_path.clone());
compiler_error!(
"Incorrect usage of the assignment. Assignments must be performed inside a valid block.",
self.file_path.clone()
);
}
}

Expand All @@ -334,7 +353,10 @@ impl Compiler {
let rvalue_type = unsafe { gcc_jit_rvalue_get_type(rvalue) };

if !self.is_int_data_type(rvalue_type) {
compiler_error!("Unary operations are only valid for integer types.", self.file_path.clone());
compiler_error!(
"Unary operations are only valid for integer types.",
self.file_path.clone()
);
}

let fixed_number = unsafe { gcc_jit_context_new_rvalue_from_int(self.context, rvalue_type, 1) };
Expand All @@ -360,7 +382,10 @@ impl Compiler {
unsafe { gcc_jit_block_add_assignment(block, loc, tmp_local, rvalue) };
}
} else {
compiler_error!("Unary operators (++, --, etc.) are only allowed inside functions.", self.file_path.clone());
compiler_error!(
"Unary operators (++, --, etc.) are only allowed inside functions.",
self.file_path.clone()
);
}

let tmp_rvalue = unsafe { gcc_jit_lvalue_as_rvalue(tmp_local) };
Expand Down Expand Up @@ -396,7 +421,10 @@ impl Compiler {
let op = match unary_expression.operator.kind {
TokenKind::Minus => gcc_jit_unary_op::GCC_JIT_UNARY_OP_MINUS,
TokenKind::Bang => gcc_jit_unary_op::GCC_JIT_UNARY_OP_LOGICAL_NEGATE,
_ => compiler_error!("Invalid operator given for the prefix expression.", self.file_path.clone()),
_ => compiler_error!(
"Invalid operator given for the prefix expression.",
self.file_path.clone()
),
};

let expr = self.compile_expression(scope, *unary_expression.operand);
Expand Down Expand Up @@ -454,7 +482,10 @@ impl Compiler {
| bin_op @ TokenKind::NotEqual => {
self.compile_comparison_operation(bin_op, casted_left, casted_right, binary_expression.loc)
}
_ => compiler_error!("Invalid operator given for the infix expression.", self.file_path.clone()),
_ => compiler_error!(
"Invalid operator given for the infix expression.",
self.file_path.clone()
),
}
}

Expand Down
11 changes: 6 additions & 5 deletions compiler/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
use ast::{
ast::*,
token::{Location, Span, TokenKind},
};
use ast::ast::*;
use control_flow::LoopBlockPair;
use funcs::{FuncMetadata, FuncParamsRecords};
use gccjit_sys::*;
use options::CompilerOptions;
use scope::{Scope, ScopeRef};
use std::{
cell::RefCell, collections::HashMap, ffi::CString, ops::Deref, rc::Rc, sync::{Arc, Mutex}
cell::RefCell,
collections::HashMap,
ffi::CString,
rc::Rc,
sync::{Arc, Mutex},
};
use structs::StructMetadata;

Expand Down
2 changes: 1 addition & 1 deletion compiler/src/output.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::{Compiler, scope::Scope};
use ast::token::{Location, TokenKind};
use ast::token::TokenKind;
use gccjit_sys::*;
use std::{
cell::RefCell,
Expand Down
14 changes: 10 additions & 4 deletions compiler/src/structs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,13 @@ impl Compiler {
let args =self.compile_func_arguments(Rc::clone(&scope), None, method_call.arguments);
let rvalue = func_def(self.file_path.clone(), self.context, args);
return rvalue;
}
}
// else {
// compiler_error!(format!(
// "Function '{}' not defined at this module.",
// func_name
// ), self.file_path.clone());
// }
}

let rvalue: *mut gcc_jit_rvalue = {
Expand Down Expand Up @@ -152,7 +158,7 @@ impl Compiler {
if let (Some(func), Some(block)) = (func, block) {
let mut result = rvalue.clone();

if result == null_mut() {
if result == null_mut() && chains.len() > 1 {
compiler_error!("Chained field_access_or_method_call on null value.", self.file_path.clone());
}

Expand Down Expand Up @@ -342,7 +348,7 @@ impl Compiler {
}
} else {
compiler_error!(
"Unexpected behaviour because compiler is trying to call struct method with empty chain.",
"Unexpected behavior because compiler is trying to call struct method with empty chain.",
self.file_path.clone()
);
}
Expand All @@ -354,7 +360,7 @@ impl Compiler {
}

if result == null_mut() {
compiler_error!("Unexpected behaviour in struct field access compilation.", self.file_path.clone());
compiler_error!("Unexpected behavior in struct field access compilation.", self.file_path.clone());
}

self.field_access_or_method_call(Rc::clone(&scope), result, method_call_chain)
Expand Down
9 changes: 7 additions & 2 deletions examples/main.cyr
Original file line number Diff line number Diff line change
@@ -1,2 +1,7 @@
#arr: i32[3] = [1, 2, 3];
#item = arr[2];
import std::io;

fn main() {
#arr: i32[4] = [1, 2, 3];
#size = len(arr);
std::io::printf("size: %d\n", size);
}
10 changes: 4 additions & 6 deletions parser/src/expressions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,11 @@ impl<'a> Parser<'a> {
})
} else if self.current_token_is(TokenKind::Assign) {
self.parse_assignment(from_package)?
} else if self.current_token_is(TokenKind::LeftBracket) {
} else if self.peek_token_is(TokenKind::LeftBracket) {
self.next_token(); // consume identifier
let array_index = self.parse_array_index(from_package)?;

if self.peek_token_is(TokenKind::Assign) {
if self.current_token_is(TokenKind::Assign) {
self.parse_array_index_assign(array_index)?
} else {
Expression::ArrayIndex(array_index)
Expand Down Expand Up @@ -620,8 +621,6 @@ impl<'a> Parser<'a> {
}

pub fn parse_array_index_assign(&mut self, array_index: ArrayIndex) -> Result<Expression, ParseError> {
self.next_token(); // consume right bracket

self.expect_current(TokenKind::Assign)?;

let expr = self.parse_expression(Precedence::Lowest)?.0;
Expand All @@ -641,13 +640,12 @@ impl<'a> Parser<'a> {
pub fn parse_array_index(&mut self, from_package: FromPackage) -> Result<ArrayIndex, ParseError> {
let start = self.current_token.span.start;

dbg!(self.current_token.kind.clone());

let mut dimensions: Vec<Expression> = Vec::new();

while self.current_token_is(TokenKind::LeftBracket) {
let expr = self.parse_array_items()?;
dimensions.push(expr);
self.next_token();
}

let end = self.current_token.span.end;
Expand Down

0 comments on commit d2a1281

Please sign in to comment.