use crate::span::Span;
use crate::{
ast::{
builder::Builder,
diagnostics::{
Diagnostic::{self},
MaybeSpanDiag,
},
resolve::literals::ExpectedType,
Value,
},
cst::Kind,
parse::Token,
Node, RitoType,
};
impl<'a> Builder<'a> {
pub(crate) fn resolve_literal(
&mut self,
text: &str,
token: &Token,
expected_type: Option<ExpectedType>,
expected_type_span: Option<Span>,
) -> Value {
match Value::eval(text, token, expected_type, expected_type_span) {
Ok(value) => value,
Err(e) => {
self.push(Diagnostic::from(e).default_span(token.span));
match expected_type {
Some(ExpectedType::Exact(kind)) => Value::Unresolved {
span: token.span,
kind,
},
_ => Value::Unknown(token.span),
}
}
}
}
pub(crate) fn resolve_value(
&mut self,
wrapper: &Node,
numeric_hint: Option<impl Into<ExpectedType>>,
numeric_hint_span: Option<Span>,
) -> Result<Value, Diagnostic> {
self.resolve_value_inner(wrapper, numeric_hint.map(Into::into), numeric_hint_span)
}
fn resolve_value_inner(
&mut self,
wrapper: &Node,
numeric_hint: Option<ExpectedType>,
numeric_hint_span: Option<Span>,
) -> Result<Value, Diagnostic> {
let Some(child) = wrapper.children.get(self.cst).first() else {
return Err(Diagnostic::CustomSpan(
"[resolve_value] node has no children",
wrapper.span,
));
};
let Some(node) = child.tree(self.cst) else {
return Err(Diagnostic::CustomSpan(
"[resolve_value] first child is not a node",
wrapper.span,
));
};
match node.kind {
Kind::Class => {
let Some(ExpectedType::Exact(kind)) = numeric_hint else {
return Err(Diagnostic::CustomSpan(
"Cannot resolve class block with no type hint",
node.span,
));
};
self.resolve_class(node, kind)
}
Kind::Block => {
let Some(ExpectedType::Exact(kind)) = numeric_hint else {
return Err(Diagnostic::CustomSpan(
"Cannot resolve block with no type hint",
node.span,
));
};
self.resolve_block_value(node, kind, numeric_hint_span)
.map_err(|e| e.fallback(node.span).diagnostic)
}
Kind::Literal => {
let Some(token_child) = node.children.get(self.cst).first() else {
return Err(Diagnostic::CustomSpan(
"[resolve_value] literal node has no children",
wrapper.span,
));
};
let Some(token) = token_child.token(self.cst) else {
return Err(Diagnostic::CustomSpan(
"[resolve_value] literal node's first child is not a token",
wrapper.span,
));
};
Ok(self.resolve_literal(self.text, token, numeric_hint, numeric_hint_span))
}
Kind::ErrorTree => Ok(Value::Unknown(node.span)),
_ => Err(Diagnostic::CustomSpan(
"[resolve_value] cannot resolve this node kind",
node.span,
)),
}
}
pub(crate) fn resolve_list_item_block(
&mut self,
node: &Node,
hint: impl Into<RitoType>,
hint_span: Option<Span>,
) -> Result<Value, MaybeSpanDiag> {
self.resolve_block_value(node, hint, hint_span)
}
}