Add types to hovers in LSP, fix around and add metas
This commit is contained in:
parent
7d3aaa143a
commit
b71c253942
@ -3,7 +3,10 @@ use std::path::PathBuf;
|
||||
|
||||
use dashmap::DashMap;
|
||||
use reid::ast::lexer::{FullToken, Position};
|
||||
use reid::mir::{self, Context, StructType, TypeKind};
|
||||
use reid::mir::{
|
||||
self, Context, FunctionCall, FunctionDefinition, FunctionParam, IfExpression, SourceModuleId, StructType, TypeKind,
|
||||
WhileStatement,
|
||||
};
|
||||
use reid::{compile_module, parse_module, perform_all_passes};
|
||||
use tower_lsp::jsonrpc::Result;
|
||||
use tower_lsp::lsp_types::{
|
||||
@ -78,12 +81,6 @@ impl LanguageServer for Backend {
|
||||
let tokens = self.tokens.get(&file_name);
|
||||
let position = params.text_document_position_params.position;
|
||||
|
||||
self.client
|
||||
.log_message(
|
||||
MessageType::INFO,
|
||||
format!("line {}, col {}", position.line, position.character),
|
||||
)
|
||||
.await;
|
||||
let token = if let Some(tokens) = &tokens {
|
||||
tokens.iter().find(|tok| {
|
||||
tok.position.1 == position.line + 1
|
||||
@ -95,17 +92,21 @@ impl LanguageServer for Backend {
|
||||
};
|
||||
|
||||
let ty = if let Some(token) = token {
|
||||
if let Some(ty) = self.types.get(&file_name).unwrap().get(token) {
|
||||
ty.clone()
|
||||
if let Some(possible_ty) = self.types.get(&file_name).unwrap().get(token) {
|
||||
if let Some(ty) = possible_ty.clone() {
|
||||
format!("{}", ty)
|
||||
} else {
|
||||
String::from("no type")
|
||||
}
|
||||
} else {
|
||||
None
|
||||
String::from("no token")
|
||||
}
|
||||
} else {
|
||||
None
|
||||
String::from("no token")
|
||||
};
|
||||
|
||||
Ok(Some(Hover {
|
||||
contents: HoverContents::Scalar(MarkedString::String(format!("{:?}", ty))),
|
||||
contents: HoverContents::Scalar(MarkedString::String(format!("{}", ty))),
|
||||
range: None,
|
||||
}))
|
||||
}
|
||||
@ -139,7 +140,7 @@ impl Backend {
|
||||
|
||||
let mut reid_error = None;
|
||||
let mut tokens = None;
|
||||
let token_types = DashMap::new();
|
||||
let mut token_types_opt = None;
|
||||
|
||||
match parse_module(¶ms.text, file_name.clone(), &mut map) {
|
||||
Ok(module) => {
|
||||
@ -157,9 +158,11 @@ impl Backend {
|
||||
if module.module_id != module_id {
|
||||
continue;
|
||||
}
|
||||
let token_types = DashMap::new();
|
||||
for (idx, token) in module.tokens.iter().enumerate() {
|
||||
token_types.insert(token.clone(), find_type_in_context(&module, idx));
|
||||
}
|
||||
token_types_opt = Some(token_types);
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
@ -178,8 +181,9 @@ impl Backend {
|
||||
}
|
||||
|
||||
if let Some(tokens) = &tokens {
|
||||
if let Some(reid_error) = reid_error {
|
||||
if let Some(mut reid_error) = reid_error {
|
||||
let mut diagnostics = Vec::new();
|
||||
reid_error.errors.dedup();
|
||||
for error in reid_error.errors {
|
||||
let meta = error.get_meta();
|
||||
let positions = meta
|
||||
@ -226,7 +230,9 @@ impl Backend {
|
||||
if let Some(tokens) = tokens.take() {
|
||||
self.tokens.insert(file_name.clone(), tokens);
|
||||
}
|
||||
self.types.insert(file_name.clone(), token_types);
|
||||
if let Some(token_types) = token_types_opt {
|
||||
self.types.insert(file_name.clone(), token_types);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -278,7 +284,7 @@ pub fn find_type_in_context(module: &mir::Module, token_idx: usize) -> Option<Ty
|
||||
}
|
||||
|
||||
return match &function.kind {
|
||||
mir::FunctionDefinitionKind::Local(block, _) => find_type_in_block(&block, token_idx),
|
||||
mir::FunctionDefinitionKind::Local(block, _) => find_type_in_block(&block, module.module_id, token_idx),
|
||||
mir::FunctionDefinitionKind::Extern(_) => None,
|
||||
mir::FunctionDefinitionKind::Intrinsic(_) => None,
|
||||
};
|
||||
@ -286,8 +292,151 @@ pub fn find_type_in_context(module: &mir::Module, token_idx: usize) -> Option<Ty
|
||||
None
|
||||
}
|
||||
|
||||
pub fn find_type_in_block(block: &mir::Block, token_idx: usize) -> Option<TypeKind> {
|
||||
for statement in &block.statements {}
|
||||
pub fn find_type_in_block(block: &mir::Block, module_id: SourceModuleId, token_idx: usize) -> Option<TypeKind> {
|
||||
if !block.meta.contains(token_idx) {
|
||||
return None;
|
||||
}
|
||||
|
||||
for statement in &block.statements {
|
||||
if !statement.1.contains(token_idx) {
|
||||
continue;
|
||||
}
|
||||
match &statement.0 {
|
||||
mir::StmtKind::Let(named_variable_ref, _, expression) => {
|
||||
if named_variable_ref.2.contains(token_idx) {
|
||||
return expression
|
||||
.return_type(&Default::default(), module_id)
|
||||
.ok()
|
||||
.map(|(_, ty)| ty);
|
||||
} else {
|
||||
return find_type_in_expr(&expression, module_id, token_idx);
|
||||
}
|
||||
}
|
||||
mir::StmtKind::Set(lhs, rhs) => {
|
||||
return find_type_in_expr(lhs, module_id, token_idx).or(find_type_in_expr(rhs, module_id, token_idx));
|
||||
}
|
||||
mir::StmtKind::Import(_) => {}
|
||||
mir::StmtKind::Expression(expression) => return find_type_in_expr(expression, module_id, token_idx),
|
||||
mir::StmtKind::While(WhileStatement { condition, block, .. }) => {
|
||||
return find_type_in_expr(condition, module_id, token_idx)
|
||||
.or(find_type_in_block(block, module_id, token_idx));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some((_, Some(return_exp))) = &block.return_expression {
|
||||
if let Some(ty) = find_type_in_expr(return_exp, module_id, token_idx) {
|
||||
return Some(ty);
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
pub fn find_type_in_expr(expr: &mir::Expression, module_id: SourceModuleId, token_idx: usize) -> Option<TypeKind> {
|
||||
if !expr.1.contains(token_idx) {
|
||||
return None;
|
||||
}
|
||||
|
||||
match &expr.0 {
|
||||
mir::ExprKind::Variable(named_variable_ref) => Some(named_variable_ref.0.clone()),
|
||||
mir::ExprKind::Indexed(value, type_kind, index_expr) => Some(
|
||||
find_type_in_expr(&value, module_id, token_idx)
|
||||
.or(find_type_in_expr(&index_expr, module_id, token_idx))
|
||||
.unwrap_or(type_kind.clone()),
|
||||
),
|
||||
mir::ExprKind::Accessed(expression, type_kind, _, meta) => {
|
||||
if meta.contains(token_idx) {
|
||||
Some(type_kind.clone())
|
||||
} else {
|
||||
find_type_in_expr(&expression, module_id, token_idx)
|
||||
}
|
||||
}
|
||||
mir::ExprKind::Array(expressions) => {
|
||||
for expr in expressions {
|
||||
if let Some(ty) = find_type_in_expr(expr, module_id, token_idx) {
|
||||
return Some(ty);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
mir::ExprKind::Struct(name, items) => {
|
||||
for (_, expr, meta) in items {
|
||||
if meta.contains(token_idx) {
|
||||
return expr.return_type(&Default::default(), module_id).map(|(_, t)| t).ok();
|
||||
}
|
||||
if let Some(ty) = find_type_in_expr(expr, module_id, token_idx) {
|
||||
return Some(ty);
|
||||
}
|
||||
}
|
||||
Some(TypeKind::CustomType(mir::CustomTypeKey(name.clone(), module_id)))
|
||||
}
|
||||
mir::ExprKind::Literal(literal) => Some(literal.as_type()),
|
||||
mir::ExprKind::BinOp(binary_operator, lhs, rhs, type_kind) => {
|
||||
if let Some(ty) = find_type_in_expr(lhs, module_id, token_idx) {
|
||||
return Some(ty);
|
||||
}
|
||||
if let Some(ty) = find_type_in_expr(rhs, module_id, token_idx) {
|
||||
return Some(ty);
|
||||
}
|
||||
Some(type_kind.clone())
|
||||
}
|
||||
mir::ExprKind::FunctionCall(FunctionCall {
|
||||
return_type,
|
||||
parameters,
|
||||
..
|
||||
}) => {
|
||||
for expr in parameters {
|
||||
if let Some(ty) = find_type_in_expr(expr, module_id, token_idx) {
|
||||
return Some(ty);
|
||||
}
|
||||
}
|
||||
Some(return_type.clone())
|
||||
}
|
||||
mir::ExprKind::AssociatedFunctionCall(
|
||||
_,
|
||||
FunctionCall {
|
||||
return_type,
|
||||
parameters,
|
||||
..
|
||||
},
|
||||
) => {
|
||||
for expr in parameters {
|
||||
if let Some(ty) = find_type_in_expr(expr, module_id, token_idx) {
|
||||
return Some(ty);
|
||||
}
|
||||
}
|
||||
Some(return_type.clone())
|
||||
}
|
||||
mir::ExprKind::If(IfExpression(cond, then_e, else_e)) => find_type_in_expr(&cond, module_id, token_idx)
|
||||
.or(find_type_in_expr(&then_e, module_id, token_idx))
|
||||
.or(else_e.clone().and_then(|e| find_type_in_expr(&e, module_id, token_idx))),
|
||||
mir::ExprKind::Block(block) => find_type_in_block(block, module_id, token_idx),
|
||||
mir::ExprKind::Borrow(expression, mutable) => {
|
||||
if let Some(ty) = find_type_in_expr(&expression, module_id, token_idx) {
|
||||
return Some(ty);
|
||||
}
|
||||
if let Ok(inner) = expression.return_type(&Default::default(), module_id).map(|(_, ty)| ty) {
|
||||
Some(TypeKind::Borrow(Box::new(inner.clone()), *mutable))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
mir::ExprKind::Deref(expression) => {
|
||||
if let Some(ty) = find_type_in_expr(&expression, module_id, token_idx) {
|
||||
return Some(ty);
|
||||
}
|
||||
if let Ok(TypeKind::Borrow(inner, _)) =
|
||||
expression.return_type(&Default::default(), module_id).map(|(_, ty)| ty)
|
||||
{
|
||||
Some(*inner.clone())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
mir::ExprKind::CastTo(expression, type_kind) => {
|
||||
Some(find_type_in_expr(&expression, module_id, token_idx).unwrap_or(type_kind.clone()))
|
||||
}
|
||||
mir::ExprKind::GlobalRef(_, type_kind) => Some(type_kind.clone()),
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
//! This is the module that contains relevant code to parsing Reid, that is to
|
||||
//! say transforming a Vec of FullTokens into a loose parsed AST that can be
|
||||
//! used for unwrapping syntax sugar, and then be transformed into Reid MIR.
|
||||
use std::path::PathBuf;
|
||||
use std::{fs::Metadata, path::PathBuf};
|
||||
|
||||
use token_stream::TokenRange;
|
||||
|
||||
@ -88,7 +88,7 @@ pub enum ExpressionKind {
|
||||
/// Array-indexed, e.g. <expr>[<expr>]
|
||||
Indexed(Box<Expression>, Box<Expression>),
|
||||
/// Struct-accessed, e.g. <expr>.<expr>
|
||||
Accessed(Box<Expression>, String),
|
||||
Accessed(Box<Expression>, String, TokenRange),
|
||||
/// Associated function call, but with a shorthand
|
||||
AccessCall(Box<Expression>, Box<FunctionCallExpression>),
|
||||
Binop(BinaryOperator, Box<Expression>, Box<Expression>),
|
||||
@ -216,7 +216,7 @@ pub enum ReturnType {
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct StructExpression {
|
||||
name: String,
|
||||
fields: Vec<(String, Expression)>,
|
||||
fields: Vec<(String, Expression, TokenRange)>,
|
||||
range: TokenRange,
|
||||
}
|
||||
|
||||
|
@ -191,10 +191,11 @@ where
|
||||
),
|
||||
expr.0 .1,
|
||||
),
|
||||
ExpressionKind::Accessed(value_expr, index_name) => Expression(
|
||||
ExpressionKind::Accessed(value_expr, index_name, range) => Expression(
|
||||
ExpressionKind::Accessed(
|
||||
Box::new(apply_inner(PrimaryExpression(*value_expr.clone()), fun)),
|
||||
index_name.clone(),
|
||||
*range,
|
||||
),
|
||||
expr.0 .1,
|
||||
),
|
||||
@ -399,9 +400,9 @@ impl Parse for PrimaryExpression {
|
||||
);
|
||||
}
|
||||
ValueIndex::Dot(val) => match val {
|
||||
DotIndexKind::StructValueIndex(name) => {
|
||||
DotIndexKind::StructValueIndex(name, range) => {
|
||||
expr = Expression(
|
||||
ExpressionKind::Accessed(Box::new(expr), name),
|
||||
ExpressionKind::Accessed(Box::new(expr), name, range),
|
||||
stream.get_range().unwrap(),
|
||||
);
|
||||
}
|
||||
@ -818,9 +819,10 @@ impl Parse for StructExpression {
|
||||
let Some(Token::Identifier(name)) = stream.next() else {
|
||||
return Err(stream.expected_err("struct identifier")?);
|
||||
};
|
||||
|
||||
stream.expect(Token::BraceOpen)?;
|
||||
let named_list = stream.parse::<NamedFieldList<Expression>>()?;
|
||||
let fields = named_list.0.into_iter().map(|f| (f.0, f.1)).collect();
|
||||
let fields = named_list.0.into_iter().map(|f| (f.0, f.1, f.2)).collect();
|
||||
|
||||
stream.expect(Token::BraceClose)?;
|
||||
|
||||
@ -897,7 +899,7 @@ impl Parse for ArrayValueIndex {
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum DotIndexKind {
|
||||
StructValueIndex(String),
|
||||
StructValueIndex(String, TokenRange),
|
||||
FunctionCall(FunctionCallExpression),
|
||||
}
|
||||
|
||||
@ -913,7 +915,7 @@ impl Parse for DotIndexKind {
|
||||
is_macro: false,
|
||||
}))
|
||||
} else {
|
||||
Ok(Self::StructValueIndex(name))
|
||||
Ok(Self::StructValueIndex(name, stream.get_range().unwrap()))
|
||||
}
|
||||
} else {
|
||||
return Err(stream.expected_err("struct index (number)")?);
|
||||
|
@ -375,13 +375,14 @@ impl ast::Expression {
|
||||
struct_init
|
||||
.fields
|
||||
.iter()
|
||||
.map(|(n, e)| (n.clone(), e.process(module_id)))
|
||||
.map(|(n, e, r)| (n.clone(), e.process(module_id), r.as_meta(module_id)))
|
||||
.collect(),
|
||||
),
|
||||
ast::ExpressionKind::Accessed(expression, name) => mir::ExprKind::Accessed(
|
||||
ast::ExpressionKind::Accessed(expression, name, name_range) => mir::ExprKind::Accessed(
|
||||
Box::new(expression.process(module_id)),
|
||||
mir::TypeKind::Vague(mir::VagueType::Unknown),
|
||||
name.clone(),
|
||||
name_range.as_meta(module_id),
|
||||
),
|
||||
ast::ExpressionKind::Borrow(expr, mutable) => {
|
||||
mir::ExprKind::Borrow(Box::new(expr.process(module_id)), *mutable)
|
||||
|
@ -226,8 +226,8 @@ impl std::ops::Add for TokenRange {
|
||||
|
||||
fn add(self, rhs: Self) -> Self::Output {
|
||||
TokenRange {
|
||||
start: self.start.min(rhs.start),
|
||||
end: self.end.min(rhs.end),
|
||||
start: self.start.min(rhs.start).min(rhs.end),
|
||||
end: self.end.max(rhs.end).max(rhs.start),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -133,7 +133,7 @@ impl mir::Expression {
|
||||
allocated.extend(expr.allocate(scope));
|
||||
allocated.extend(idx.allocate(scope));
|
||||
}
|
||||
mir::ExprKind::Accessed(expression, _, _) => {
|
||||
mir::ExprKind::Accessed(expression, ..) => {
|
||||
allocated.extend(expression.allocate(scope));
|
||||
}
|
||||
mir::ExprKind::Array(expressions) => {
|
||||
@ -159,7 +159,7 @@ impl mir::Expression {
|
||||
.unwrap();
|
||||
allocated.push(Allocation(self.1, ty, allocation));
|
||||
|
||||
for (field_name, expression) in items {
|
||||
for (field_name, expression, _) in items {
|
||||
allocated.extend(expression.allocate(scope));
|
||||
|
||||
let (_, ty) = expression.return_type(&Default::default(), scope.mod_id).unwrap();
|
||||
|
@ -1160,7 +1160,7 @@ impl mir::Expression {
|
||||
TypeKind::Array(Box::new(elem_ty_kind), instr_list.len() as u64),
|
||||
))
|
||||
}
|
||||
mir::ExprKind::Accessed(expression, type_kind, field) => {
|
||||
mir::ExprKind::Accessed(expression, type_kind, field, _) => {
|
||||
let struct_val = expression.codegen(scope, &state.load(false))?.unwrap();
|
||||
|
||||
let TypeKind::CodegenPtr(inner) = &struct_val.1 else {
|
||||
@ -1222,7 +1222,7 @@ impl mir::Expression {
|
||||
.unwrap()
|
||||
.maybe_location(&mut scope.block, location.clone());
|
||||
|
||||
for (field_n, exp) in items {
|
||||
for (field_n, exp, _) in items {
|
||||
let gep_n = format!("{}.{}.gep", name, field_n);
|
||||
let store_n = format!("{}.{}.store", name, field_n);
|
||||
let i = indices.clone().find(|(_, f)| f.0 == *field_n).unwrap().0;
|
||||
|
@ -279,9 +279,9 @@ impl Display for ExprKind {
|
||||
let mut state = Default::default();
|
||||
let mut inner_f = PadAdapter::wrap(f, &mut state);
|
||||
let mut iter = items.iter();
|
||||
if let Some((name, expr)) = iter.next() {
|
||||
if let Some((name, expr, _)) = iter.next() {
|
||||
write!(inner_f, "\n{}: {}", name, expr)?;
|
||||
while let Some((name, expr)) = iter.next() {
|
||||
while let Some((name, expr, _)) = iter.next() {
|
||||
writeln!(inner_f, ",")?;
|
||||
write!(inner_f, "{}: {}", name, expr)?;
|
||||
}
|
||||
@ -289,7 +289,7 @@ impl Display for ExprKind {
|
||||
}
|
||||
f.write_char('}')
|
||||
}
|
||||
ExprKind::Accessed(expression, type_kind, name) => {
|
||||
ExprKind::Accessed(expression, type_kind, name, _) => {
|
||||
Display::fmt(&expression, f)?;
|
||||
write_access(f, name)?;
|
||||
write!(f, "<{}>", type_kind)
|
||||
|
@ -405,7 +405,7 @@ impl Expression {
|
||||
TypeKind::Array(Box::new(first.1), expressions.len() as u64),
|
||||
))
|
||||
}
|
||||
Accessed(_, type_kind, _) => Ok((ReturnKind::Soft, type_kind.clone())),
|
||||
Accessed(_, type_kind, ..) => Ok((ReturnKind::Soft, type_kind.clone())),
|
||||
Struct(name, _) => Ok((
|
||||
ReturnKind::Soft,
|
||||
TypeKind::CustomType(CustomTypeKey(name.clone(), mod_id)),
|
||||
@ -437,7 +437,7 @@ impl Expression {
|
||||
match &self.0 {
|
||||
ExprKind::Variable(var_ref) => Some(var_ref),
|
||||
ExprKind::Indexed(lhs, _, _) => lhs.backing_var(),
|
||||
ExprKind::Accessed(lhs, _, _) => lhs.backing_var(),
|
||||
ExprKind::Accessed(lhs, ..) => lhs.backing_var(),
|
||||
ExprKind::Borrow(expr, _) => expr.backing_var(),
|
||||
ExprKind::Deref(expr) => expr.backing_var(),
|
||||
ExprKind::Block(block) => block.backing_var(),
|
||||
|
@ -459,7 +459,7 @@ impl<'map> Pass for LinkerPass<'map> {
|
||||
super::ExprKind::Indexed(.., type_kind, _) => {
|
||||
*type_kind = type_kind.update_imported(extern_types, mod_id)
|
||||
}
|
||||
super::ExprKind::Accessed(.., type_kind, _) => {
|
||||
super::ExprKind::Accessed(.., type_kind, _, _) => {
|
||||
*type_kind = type_kind.update_imported(extern_types, mod_id)
|
||||
}
|
||||
super::ExprKind::BinOp(.., type_kind) => *type_kind = type_kind.update_imported(extern_types, mod_id),
|
||||
|
@ -262,9 +262,9 @@ pub struct Import(pub Vec<String>, pub Metadata);
|
||||
pub enum ExprKind {
|
||||
Variable(NamedVariableRef),
|
||||
Indexed(Box<Expression>, TypeKind, Box<Expression>),
|
||||
Accessed(Box<Expression>, TypeKind, String),
|
||||
Accessed(Box<Expression>, TypeKind, String, Metadata),
|
||||
Array(Vec<Expression>),
|
||||
Struct(String, Vec<(String, Expression)>),
|
||||
Struct(String, Vec<(String, Expression, Metadata)>),
|
||||
Literal(Literal),
|
||||
BinOp(BinaryOperator, Box<Expression>, Box<Expression>, TypeKind),
|
||||
FunctionCall(FunctionCall),
|
||||
|
@ -585,7 +585,7 @@ impl Expression {
|
||||
}
|
||||
}
|
||||
ExprKind::Struct(_, items) => {
|
||||
for (_, expr) in items {
|
||||
for (_, expr, _) in items {
|
||||
expr.pass(pass, state, scope, mod_id)?;
|
||||
}
|
||||
}
|
||||
|
@ -596,7 +596,7 @@ impl Expression {
|
||||
}
|
||||
}
|
||||
}
|
||||
ExprKind::Accessed(expression, type_kind, field_name) => {
|
||||
ExprKind::Accessed(expression, type_kind, field_name, _) => {
|
||||
// Resolve expected type
|
||||
let expected_ty = type_kind.resolve_ref(typerefs);
|
||||
|
||||
@ -640,7 +640,7 @@ impl Expression {
|
||||
HashSet::new()
|
||||
};
|
||||
|
||||
for (field_name, field_expr) in items {
|
||||
for (field_name, field_expr, _) in items {
|
||||
// Get expected type, or error if field does not exist
|
||||
let expected_ty = state.or_else(
|
||||
struct_def
|
||||
|
@ -526,7 +526,7 @@ impl Expression {
|
||||
}
|
||||
}
|
||||
}
|
||||
ExprKind::Accessed(expression, type_kind, field_name) => {
|
||||
ExprKind::Accessed(expression, type_kind, field_name, _) => {
|
||||
let expr_ty = expression.infer_types(state, type_refs)?;
|
||||
|
||||
// Check that the resolved type is at least a struct, no
|
||||
|
Loading…
Reference in New Issue
Block a user