mirror of
https://github.com/SpaceManiac/SpacemanDMM.git
synced 2025-12-23 05:36:47 +00:00
Implements base functionality for __TYPE__ and __PROC__ (#366)
We basically just capture them early, and then treat them as unique symbols. We don't replace inline or anything because the required context isn't quite there.
This commit is contained in:
parent
47ef0c58ab
commit
d3dbed0fb2
5 changed files with 58 additions and 0 deletions
|
|
@ -544,6 +544,20 @@ impl<'o> WalkProc<'o> {
|
|||
StaticType::None
|
||||
}
|
||||
},
|
||||
|
||||
Term::__TYPE__ => {
|
||||
self.tab.use_symbol(self.ty.id, location);
|
||||
StaticType::None
|
||||
},
|
||||
Term::__PROC__ => {
|
||||
let Some(proc) = self.proc else {
|
||||
return StaticType::None
|
||||
};
|
||||
if let Some(decl) = self.ty.get_proc_declaration(proc.name()) {
|
||||
self.tab.use_symbol(decl.id, location);
|
||||
}
|
||||
StaticType::None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1738,6 +1738,8 @@ impl<'o, 's> AnalyzeProc<'o, 's> {
|
|||
let src = self.ty;
|
||||
if let Some(proc) = self.ty.get_proc(unscoped_name) {
|
||||
self.visit_call(location, src, proc, args, false, local_vars)
|
||||
} else if unscoped_name == "__PROC__" {
|
||||
self.visit_call(location, src, self.proc_ref, args, false, local_vars)
|
||||
} else if unscoped_name == "SpacemanDMM_unlint" {
|
||||
// Escape hatch for cases like `src` in macros used in
|
||||
// global procs.
|
||||
|
|
@ -1882,6 +1884,20 @@ impl<'o, 's> AnalyzeProc<'o, 's> {
|
|||
self.visit_arguments(location, args, local_vars);
|
||||
Analysis::empty() // TODO
|
||||
},
|
||||
Term::__TYPE__ => {
|
||||
let pop = dm::constants::Pop::from(self.ty.path.split('/').skip(1).map(ToOwned::to_owned).collect::<Vec<_>>().into_boxed_slice());
|
||||
Analysis {
|
||||
static_ty: StaticType::None,
|
||||
aset: assumption_set![Assumption::IsPath(true, self.ty)],
|
||||
value: Some(Constant::Prefab(Box::new(pop))),
|
||||
fix_hint: None,
|
||||
is_impure: None,
|
||||
}
|
||||
},
|
||||
Term::__PROC__ => {
|
||||
// Can't fuckin do it bros
|
||||
Analysis::empty()
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -643,6 +643,10 @@ impl<'a, T: fmt::Display> fmt::Display for FormatTreePath<'a, T> {
|
|||
/// A series of identifiers separated by path operators.
|
||||
pub type TypePath = Vec<(PathOp, Ident)>;
|
||||
|
||||
pub fn make_typepath(segments: Vec<String>) -> TypePath {
|
||||
segments.into_iter().fold(vec![], |mut acc, segment| { acc.push((PathOp::Slash, segment)); acc })
|
||||
}
|
||||
|
||||
pub struct FormatTypePath<'a>(pub &'a [(PathOp, Ident)]);
|
||||
|
||||
impl<'a> fmt::Display for FormatTypePath<'a> {
|
||||
|
|
@ -867,6 +871,10 @@ pub enum Term {
|
|||
Resource(String),
|
||||
/// An `as()` call, with an input type. Undocumented.
|
||||
As(InputType),
|
||||
/// A reference to our current proc's name
|
||||
__PROC__,
|
||||
/// A reference to the current proc/scope's type
|
||||
__TYPE__,
|
||||
|
||||
// Non-function calls with recursive contents -----------------------------
|
||||
/// An expression contained in a term.
|
||||
|
|
|
|||
|
|
@ -783,6 +783,15 @@ impl<'a> ConstantFolder<'a> {
|
|||
Term::Int(v) => Constant::Float(v as f32),
|
||||
Term::Float(v) => Constant::from(v),
|
||||
Term::Expr(expr) => self.expr(*expr, type_hint)?,
|
||||
Term::__TYPE__ => {
|
||||
if let Some(obj_tree) = &self.tree {
|
||||
let typeval = TypeRef::new(obj_tree, self.ty).get();
|
||||
let path = make_typepath(typeval.path.split("/").filter(|elem| *elem != "").map(|segment| segment.to_string()).collect());
|
||||
Constant::Prefab(Box::new(self.prefab(Prefab::from(path))?))
|
||||
} else {
|
||||
return Err(self.error("No type context".to_owned()))
|
||||
}
|
||||
},
|
||||
_ => return Err(self.error("non-constant expression".to_owned())),
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2073,6 +2073,17 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> {
|
|||
require!(self.exact(Token::Punct(Punctuation::RParen)));
|
||||
Term::As(input_type)
|
||||
},
|
||||
// term :: __PROC__
|
||||
Token::Ident(ref i, _) if i == "__PROC__" => {
|
||||
// We cannot replace with the proc path yet, you don't need one it's fine
|
||||
Term::__PROC__
|
||||
},
|
||||
|
||||
// term :: __TYPE__
|
||||
Token::Ident(ref i, _) if i == "__TYPE__" => {
|
||||
// We cannot replace with the typepath yet, so we'll hand back a term we can parse later
|
||||
Term::__TYPE__
|
||||
},
|
||||
|
||||
// term :: ident arglist | ident
|
||||
Token::Ident(i, _) => {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue