Account for intrinsic associated functions with autocomplete

This commit is contained in:
Sofia 2025-08-03 01:00:02 +03:00
parent a6844b919b
commit 101ee2d8e5
7 changed files with 62 additions and 9 deletions

View File

@ -2,6 +2,7 @@ use std::{collections::HashMap, fmt::format, path::PathBuf};
use reid::{ use reid::{
ast::{self, FunctionDefinition, lexer::FullToken, token_stream::TokenRange}, ast::{self, FunctionDefinition, lexer::FullToken, token_stream::TokenRange},
codegen::intrinsics::get_intrinsic_assoc_functions,
compile_module, compile_module,
error_raporting::{ErrorModules, ReidError}, error_raporting::{ErrorModules, ReidError},
mir::{ mir::{
@ -306,7 +307,7 @@ pub fn analyze_expr(
_ => {} _ => {}
} }
set_autocomplete(map, meta.range.end - 1, autocompletes); set_autocomplete(map, meta.range.end, autocompletes);
} }
mir::ExprKind::Array(expressions) => { mir::ExprKind::Array(expressions) => {
for expr in expressions { for expr in expressions {
@ -337,7 +338,7 @@ pub fn analyze_expr(
for expr in parameters { for expr in parameters {
analyze_expr(context, source_module, expr, map); analyze_expr(context, source_module, expr, map);
} }
let function_autocomplete = source_module let mut function_autocomplete = source_module
.associated_functions .associated_functions
.iter() .iter()
.filter(|(t, fun)| t == ty && fun.name.starts_with(name)) .filter(|(t, fun)| t == ty && fun.name.starts_with(name))
@ -346,7 +347,20 @@ pub fn analyze_expr(
kind: AutocompleteKind::Function(fun.parameters.clone(), fun.return_type.clone()), kind: AutocompleteKind::Function(fun.parameters.clone(), fun.return_type.clone()),
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
set_autocomplete(map, meta.range.end, function_autocomplete); function_autocomplete.extend(
get_intrinsic_assoc_functions(ty)
.iter()
.filter_map(|(s, f)| f.as_ref().map(|f| (s, f)))
.filter(|(_, fun)| fun.name.starts_with(name))
.map(|(_, fun)| Autocomplete {
text: fun.name.clone(),
kind: AutocompleteKind::Function(fun.parameters.clone(), fun.return_type.clone()),
})
.collect::<Vec<_>>(),
);
dbg!(ty);
dbg!(&source_module.associated_functions);
set_autocomplete(map, meta.range.end, function_autocomplete.clone());
} }
mir::ExprKind::If(IfExpression(cond, then_e, else_e)) => { mir::ExprKind::If(IfExpression(cond, then_e, else_e)) => {
analyze_expr(context, source_module, &cond, map); analyze_expr(context, source_module, &cond, map);

View File

@ -937,7 +937,8 @@ pub enum DotIndexKind {
impl Parse for DotIndexKind { impl Parse for DotIndexKind {
fn parse(mut stream: TokenStream) -> Result<Self, Error> { fn parse(mut stream: TokenStream) -> Result<Self, Error> {
stream.expect(Token::Dot)?; stream.expect(Token::Dot)?;
if let Some(Token::Identifier(name)) = stream.next() { if let Some(Token::Identifier(name)) = stream.peek() {
stream.next(); // Consume identifer
if let Ok(args) = stream.parse::<FunctionArgs>() { if let Ok(args) = stream.parse::<FunctionArgs>() {
Ok(Self::FunctionCall(FunctionCallExpression { Ok(Self::FunctionCall(FunctionCallExpression {
name, name,
@ -946,10 +947,18 @@ impl Parse for DotIndexKind {
is_macro: false, is_macro: false,
})) }))
} else { } else {
Ok(Self::StructValueIndex(name, stream.get_range().unwrap())) Ok(Self::StructValueIndex(name, stream.get_range_prev().unwrap()))
} }
} else { } else {
return Err(stream.expected_err("struct index (number)")?); if stream.next_is_whitespace() {
stream.expecting_err_nonfatal("struct index");
Ok(Self::StructValueIndex(
String::new(),
stream.get_range_prev_single().unwrap(),
))
} else {
Err(stream.expecting_err("struct index")?)
}
} }
} }
} }

View File

@ -249,6 +249,18 @@ impl<'a, 'b> TokenStream<'a, 'b> {
pub fn errors(&self) -> Vec<Error> { pub fn errors(&self) -> Vec<Error> {
self.errors.borrow().clone().clone() self.errors.borrow().clone().clone()
} }
pub fn next_is_whitespace(&self) -> bool {
if let Some(token) = self.tokens.get(self.position) {
if let Token::Whitespace(_) = token.token {
true
} else {
false
}
} else {
true
}
}
} }
impl Drop for TokenStream<'_, '_> { impl Drop for TokenStream<'_, '_> {

View File

@ -1,3 +1,5 @@
use std::{collections::HashMap, hash::Hash};
use reid_lib::{builder::InstructionValue, CmpPredicate, ConstValueKind, Instr, Type}; use reid_lib::{builder::InstructionValue, CmpPredicate, ConstValueKind, Instr, Type};
use crate::{ use crate::{
@ -57,6 +59,15 @@ pub fn form_intrinsics() -> Vec<FunctionDefinition> {
intrinsics intrinsics
} }
pub fn get_intrinsic_assoc_functions(ty: &TypeKind) -> HashMap<String, Option<FunctionDefinition>> {
let mut map = HashMap::new();
map.insert("length".to_owned(), get_intrinsic_assoc_func(ty, "length"));
map.insert("sizeof".to_owned(), get_intrinsic_assoc_func(ty, "sizeof"));
map.insert("malloc".to_owned(), get_intrinsic_assoc_func(ty, "malloc"));
map.insert("null".to_owned(), get_intrinsic_assoc_func(ty, "null"));
map
}
pub fn get_intrinsic_assoc_func(ty: &TypeKind, name: &str) -> Option<FunctionDefinition> { pub fn get_intrinsic_assoc_func(ty: &TypeKind, name: &str) -> Option<FunctionDefinition> {
if let TypeKind::Array(_, len) = ty { if let TypeKind::Array(_, len) = ty {
match name { match name {

View File

@ -73,7 +73,7 @@ use crate::{
}; };
pub mod ast; pub mod ast;
mod codegen; pub mod codegen;
pub mod error_raporting; pub mod error_raporting;
pub mod ld; pub mod ld;
pub mod mir; pub mod mir;

View File

@ -727,7 +727,10 @@ impl Expression {
type_kind.clone(), type_kind.clone(),
function_call.name.clone(), function_call.name.clone(),
)) ))
.ok_or(ErrorKind::FunctionNotDefined(function_call.name.clone())); .ok_or(ErrorKind::AssocFunctionNotDefined(
function_call.name.clone(),
type_kind.clone(),
));
if let Some(f) = state.ok(true_function, self.1) { if let Some(f) = state.ok(true_function, self.1) {
let param_len_given = function_call.parameters.len(); let param_len_given = function_call.parameters.len();

View File

@ -655,9 +655,13 @@ impl Expression {
.ok_or(ErrorKind::AssocFunctionNotDefined( .ok_or(ErrorKind::AssocFunctionNotDefined(
function_call.name.clone(), function_call.name.clone(),
type_kind.clone(), type_kind.clone(),
))? ))
.clone(); .clone();
let Ok(fn_call) = fn_call else {
return Ok(type_refs.from_type(&Vague(Unknown)).unwrap());
};
// Infer param expression types and narrow them to the // Infer param expression types and narrow them to the
// expected function parameters (or Unknown types if too // expected function parameters (or Unknown types if too
// many were provided) // many were provided)