Track various symbols in the parse stage of Slang
This commit is contained in:
@@ -21,6 +21,7 @@ impl<'a> SymbolInfo<'a> {
|
||||
lsp_types::SymbolInformation {
|
||||
name: self.name.to_string(),
|
||||
kind: self.kind.to_lsp_symbol_kind(),
|
||||
#[allow(deprecated)]
|
||||
deprecated: None,
|
||||
location: lsp_types::Location {
|
||||
uri,
|
||||
|
||||
@@ -704,6 +704,10 @@ impl<'a> Compiler<'a> {
|
||||
let name_str = var_name.node;
|
||||
let name_span = var_name.span;
|
||||
|
||||
// Track the variable in metadata
|
||||
self.metadata
|
||||
.add_variable(name_str.clone(), Some(name_span));
|
||||
|
||||
// optimization. Check for a negated numeric literal (including nested negations)
|
||||
// e.g., -5, -(-5), -(-(5)), etc.
|
||||
if let Some(num) = self.try_fold_negation(&expr.node) {
|
||||
@@ -1063,6 +1067,10 @@ impl<'a> Compiler<'a> {
|
||||
value: const_value,
|
||||
} = expr;
|
||||
|
||||
// Track the const variable in metadata
|
||||
self.metadata
|
||||
.add_variable(const_name.node.clone(), Some(const_name.span));
|
||||
|
||||
// check for a hash expression or a literal
|
||||
let value = match const_value {
|
||||
LiteralOr::Or(Spanned {
|
||||
@@ -1486,6 +1494,14 @@ impl<'a> Compiler<'a> {
|
||||
) -> Result<(), Error<'a>> {
|
||||
let TupleDeclarationExpression { names, value } = tuple_decl;
|
||||
|
||||
// Track each variable in the tuple declaration
|
||||
for name_spanned in &names {
|
||||
if name_spanned.node.as_ref() != "_" {
|
||||
self.metadata
|
||||
.add_variable(name_spanned.node.clone(), Some(name_spanned.span));
|
||||
}
|
||||
}
|
||||
|
||||
match value.node {
|
||||
Expression::Invocation(invoke_expr) => {
|
||||
// Execute the function call - tuple values will be on the stack
|
||||
@@ -1924,6 +1940,10 @@ impl<'a> Compiler<'a> {
|
||||
&mut self,
|
||||
expr: DeviceDeclarationExpression<'a>,
|
||||
) -> Result<(), Error<'a>> {
|
||||
// Track the device declaration in metadata
|
||||
self.metadata
|
||||
.add_variable(expr.name.node.clone(), Some(expr.name.span));
|
||||
|
||||
if self.devices.contains_key(&expr.name.node) {
|
||||
self.errors.push(Error::DuplicateIdentifier(
|
||||
expr.name.node.clone(),
|
||||
@@ -2928,6 +2948,15 @@ impl<'a> Compiler<'a> {
|
||||
span: Span,
|
||||
scope: &mut VariableScope<'a, '_>,
|
||||
) -> Result<Option<CompileLocation<'a>>, Error<'a>> {
|
||||
// Track the syscall in metadata
|
||||
let syscall_name = expr.name();
|
||||
self.metadata.add_syscall(
|
||||
Cow::Borrowed(syscall_name),
|
||||
crate::SyscallType::System,
|
||||
expr.arg_count(),
|
||||
Some(span),
|
||||
);
|
||||
|
||||
macro_rules! cleanup {
|
||||
($($to_clean:expr),*) => {
|
||||
$(
|
||||
@@ -3325,6 +3354,15 @@ impl<'a> Compiler<'a> {
|
||||
span: Span,
|
||||
scope: &mut VariableScope<'a, '_>,
|
||||
) -> Result<Option<CompileLocation<'a>>, Error<'a>> {
|
||||
// Track the syscall in metadata
|
||||
let syscall_name = expr.name();
|
||||
self.metadata.add_syscall(
|
||||
Cow::Borrowed(syscall_name),
|
||||
crate::SyscallType::Math,
|
||||
expr.arg_count(),
|
||||
Some(span),
|
||||
);
|
||||
|
||||
macro_rules! cleanup {
|
||||
($($to_clean:expr),*) => {
|
||||
$(
|
||||
@@ -3585,6 +3623,11 @@ impl<'a> Compiler<'a> {
|
||||
|
||||
let span = expr.span;
|
||||
|
||||
// Track the function definition in metadata
|
||||
let param_names: Vec<Cow<'a, str>> = arguments.iter().map(|a| a.node.clone()).collect();
|
||||
self.metadata
|
||||
.add_function(name.node.clone(), param_names, Some(name.span));
|
||||
|
||||
if self.function_meta.locations.contains_key(&name.node) {
|
||||
self.errors
|
||||
.push(Error::DuplicateIdentifier(name.node.clone(), name.span));
|
||||
|
||||
@@ -127,6 +127,52 @@ impl<'a> std::fmt::Display for Math<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Math<'a> {
|
||||
/// Returns the name of this math function (e.g., "acos", "sin", "sqrt", etc.)
|
||||
pub fn name(&self) -> &'static str {
|
||||
match self {
|
||||
Math::Acos(_) => "acos",
|
||||
Math::Asin(_) => "asin",
|
||||
Math::Atan(_) => "atan",
|
||||
Math::Atan2(_, _) => "atan2",
|
||||
Math::Abs(_) => "abs",
|
||||
Math::Ceil(_) => "ceil",
|
||||
Math::Cos(_) => "cos",
|
||||
Math::Floor(_) => "floor",
|
||||
Math::Log(_) => "log",
|
||||
Math::Max(_, _) => "max",
|
||||
Math::Min(_, _) => "min",
|
||||
Math::Rand => "rand",
|
||||
Math::Sin(_) => "sin",
|
||||
Math::Sqrt(_) => "sqrt",
|
||||
Math::Tan(_) => "tan",
|
||||
Math::Trunc(_) => "trunc",
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the number of arguments this math function expects
|
||||
pub fn arg_count(&self) -> usize {
|
||||
match self {
|
||||
Math::Acos(_) => 1,
|
||||
Math::Asin(_) => 1,
|
||||
Math::Atan(_) => 1,
|
||||
Math::Atan2(_, _) => 2,
|
||||
Math::Abs(_) => 1,
|
||||
Math::Ceil(_) => 1,
|
||||
Math::Cos(_) => 1,
|
||||
Math::Floor(_) => 1,
|
||||
Math::Log(_) => 1,
|
||||
Math::Max(_, _) => 2,
|
||||
Math::Min(_, _) => 2,
|
||||
Math::Rand => 0,
|
||||
Math::Sin(_) => 1,
|
||||
Math::Sqrt(_) => 1,
|
||||
Math::Tan(_) => 1,
|
||||
Math::Trunc(_) => 1,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
documented! {
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum System<'a> {
|
||||
@@ -297,6 +343,48 @@ impl<'a> std::fmt::Display for System<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> System<'a> {
|
||||
/// Returns the name of this syscall (e.g., "yield", "sleep", "hash", etc.)
|
||||
pub fn name(&self) -> &'static str {
|
||||
match self {
|
||||
System::Yield => "yield",
|
||||
System::Sleep(_) => "sleep",
|
||||
System::Clr(_) => "clr",
|
||||
System::Hash(_) => "hash",
|
||||
System::LoadFromDevice(_, _) => "loadFromDevice",
|
||||
System::LoadBatch(_, _, _) => "loadBatch",
|
||||
System::LoadBatchNamed(_, _, _, _) => "loadBatchNamed",
|
||||
System::SetOnDevice(_, _, _) => "setOnDevice",
|
||||
System::SetOnDeviceBatched(_, _, _) => "setOnDeviceBatched",
|
||||
System::SetOnDeviceBatchedNamed(_, _, _, _) => "setOnDeviceBatchedNamed",
|
||||
System::LoadSlot(_, _, _) => "loadSlot",
|
||||
System::SetSlot(_, _, _, _) => "setSlot",
|
||||
System::LoadReagent(_, _, _) => "loadReagent",
|
||||
System::Rmap(_, _) => "rmap",
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the number of arguments this syscall expects
|
||||
pub fn arg_count(&self) -> usize {
|
||||
match self {
|
||||
System::Yield => 0,
|
||||
System::Sleep(_) => 1,
|
||||
System::Clr(_) => 1,
|
||||
System::Hash(_) => 1,
|
||||
System::LoadFromDevice(_, _) => 2,
|
||||
System::LoadBatch(_, _, _) => 3,
|
||||
System::LoadBatchNamed(_, _, _, _) => 4,
|
||||
System::SetOnDevice(_, _, _) => 3,
|
||||
System::SetOnDeviceBatched(_, _, _) => 3,
|
||||
System::SetOnDeviceBatchedNamed(_, _, _, _) => 4,
|
||||
System::LoadSlot(_, _, _) => 3,
|
||||
System::SetSlot(_, _, _, _) => 4,
|
||||
System::LoadReagent(_, _, _) => 3,
|
||||
System::Rmap(_, _) => 2,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
/// This represents built in functions that cannot be overwritten, but can be invoked by the user as functions.
|
||||
|
||||
Reference in New Issue
Block a user