From 101ee2d8e5865756c7f442990f3635781ce405ba Mon Sep 17 00:00:00 2001 From: sofia Date: Sun, 3 Aug 2025 01:00:02 +0300 Subject: [PATCH] Account for intrinsic associated functions with autocomplete --- reid-lsp/src/analysis.rs | 20 +++++++++++++++++--- reid/src/ast/parse.rs | 15 ++++++++++++--- reid/src/ast/token_stream.rs | 12 ++++++++++++ reid/src/codegen/intrinsics.rs | 11 +++++++++++ reid/src/lib.rs | 2 +- reid/src/mir/typecheck/typecheck.rs | 5 ++++- reid/src/mir/typecheck/typeinference.rs | 6 +++++- 7 files changed, 62 insertions(+), 9 deletions(-) diff --git a/reid-lsp/src/analysis.rs b/reid-lsp/src/analysis.rs index a7facbc..aa6882f 100644 --- a/reid-lsp/src/analysis.rs +++ b/reid-lsp/src/analysis.rs @@ -2,6 +2,7 @@ use std::{collections::HashMap, fmt::format, path::PathBuf}; use reid::{ ast::{self, FunctionDefinition, lexer::FullToken, token_stream::TokenRange}, + codegen::intrinsics::get_intrinsic_assoc_functions, compile_module, error_raporting::{ErrorModules, ReidError}, 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) => { for expr in expressions { @@ -337,7 +338,7 @@ pub fn analyze_expr( for expr in parameters { analyze_expr(context, source_module, expr, map); } - let function_autocomplete = source_module + let mut function_autocomplete = source_module .associated_functions .iter() .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()), }) .collect::>(); - 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::>(), + ); + 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)) => { analyze_expr(context, source_module, &cond, map); diff --git a/reid/src/ast/parse.rs b/reid/src/ast/parse.rs index c53c996..a0e5073 100644 --- a/reid/src/ast/parse.rs +++ b/reid/src/ast/parse.rs @@ -937,7 +937,8 @@ pub enum DotIndexKind { impl Parse for DotIndexKind { fn parse(mut stream: TokenStream) -> Result { 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::() { Ok(Self::FunctionCall(FunctionCallExpression { name, @@ -946,10 +947,18 @@ impl Parse for DotIndexKind { is_macro: false, })) } else { - Ok(Self::StructValueIndex(name, stream.get_range().unwrap())) + Ok(Self::StructValueIndex(name, stream.get_range_prev().unwrap())) } } 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")?) + } } } } diff --git a/reid/src/ast/token_stream.rs b/reid/src/ast/token_stream.rs index a6e5539..f043459 100644 --- a/reid/src/ast/token_stream.rs +++ b/reid/src/ast/token_stream.rs @@ -249,6 +249,18 @@ impl<'a, 'b> TokenStream<'a, 'b> { pub fn errors(&self) -> Vec { 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<'_, '_> { diff --git a/reid/src/codegen/intrinsics.rs b/reid/src/codegen/intrinsics.rs index 5ff88c0..5886e45 100644 --- a/reid/src/codegen/intrinsics.rs +++ b/reid/src/codegen/intrinsics.rs @@ -1,3 +1,5 @@ +use std::{collections::HashMap, hash::Hash}; + use reid_lib::{builder::InstructionValue, CmpPredicate, ConstValueKind, Instr, Type}; use crate::{ @@ -57,6 +59,15 @@ pub fn form_intrinsics() -> Vec { intrinsics } +pub fn get_intrinsic_assoc_functions(ty: &TypeKind) -> HashMap> { + 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 { if let TypeKind::Array(_, len) = ty { match name { diff --git a/reid/src/lib.rs b/reid/src/lib.rs index 66e566b..b954363 100644 --- a/reid/src/lib.rs +++ b/reid/src/lib.rs @@ -73,7 +73,7 @@ use crate::{ }; pub mod ast; -mod codegen; +pub mod codegen; pub mod error_raporting; pub mod ld; pub mod mir; diff --git a/reid/src/mir/typecheck/typecheck.rs b/reid/src/mir/typecheck/typecheck.rs index c67f22b..45a4748 100644 --- a/reid/src/mir/typecheck/typecheck.rs +++ b/reid/src/mir/typecheck/typecheck.rs @@ -727,7 +727,10 @@ impl Expression { type_kind.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) { let param_len_given = function_call.parameters.len(); diff --git a/reid/src/mir/typecheck/typeinference.rs b/reid/src/mir/typecheck/typeinference.rs index 2068131..4f2d10b 100644 --- a/reid/src/mir/typecheck/typeinference.rs +++ b/reid/src/mir/typecheck/typeinference.rs @@ -655,9 +655,13 @@ impl Expression { .ok_or(ErrorKind::AssocFunctionNotDefined( function_call.name.clone(), type_kind.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 // expected function parameters (or Unknown types if too // many were provided)