Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions crates/oak_db/src/tests/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,8 +145,8 @@ fn test_semantic_index_recognizes_bare_base_nse() {
// Base NSE resolves through the real `SalsaImportsResolver` (base-only
// `resolve_effects`): a bare `local()` still pushes a nested NSE scope, so
// `x` lands there rather than at file scope.
use oak_semantic::semantic_index::NseScope;
use oak_semantic::semantic_index::NseTiming;
use oak_semantic::semantic_index::EvalEnv;
use oak_semantic::semantic_index::EvalTiming;
use oak_semantic::semantic_index::ScopeId;
use oak_semantic::semantic_index::ScopeKind;

Expand All @@ -159,7 +159,7 @@ fn test_semantic_index_recognizes_bare_base_nse() {

assert_eq!(
index.scope(local_scope).kind(),
ScopeKind::Nse(NseScope::Nested, NseTiming::Eager)
ScopeKind::Nse(EvalEnv::Nested, EvalTiming::Eager)
);
assert!(index.symbols(file_scope).get("x").is_none());
assert!(index.symbols(local_scope).get("x").is_some());
Expand Down
24 changes: 12 additions & 12 deletions crates/oak_db/src/tests/resolver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ use std::collections::HashSet;
use oak_package_metadata::namespace::Import;
use oak_package_metadata::namespace::Namespace;
use oak_semantic::semantic_index::DefinitionKind;
use oak_semantic::semantic_index::NseScope;
use oak_semantic::semantic_index::NseTiming;
use oak_semantic::semantic_index::EvalEnv;
use oak_semantic::semantic_index::EvalTiming;
use oak_semantic::semantic_index::ScopeId;
use oak_semantic::semantic_index::ScopeKind;
use oak_semantic::semantic_index::SemanticCallKind;
Expand Down Expand Up @@ -154,7 +154,7 @@ fn test_testthat_test_that_is_nse_without_library() {
assert_eq!(index.scope_ids().count(), 2);
assert_eq!(
index.scope(test_scope).kind(),
ScopeKind::Nse(NseScope::Nested, NseTiming::Eager)
ScopeKind::Nse(EvalEnv::Nested, EvalTiming::Eager)
);
}

Expand All @@ -178,7 +178,7 @@ fn test_testthat_helper_attach_enables_nse() {
assert_eq!(index.scope_ids().count(), 2);
assert_eq!(
index.scope(reactive_scope).kind(),
ScopeKind::Nse(NseScope::Nested, NseTiming::Lazy)
ScopeKind::Nse(EvalEnv::Nested, EvalTiming::Lazy)
);
}

Expand Down Expand Up @@ -223,7 +223,7 @@ fn test_namespace_import_from_enables_nse() {
assert_eq!(index.scope_ids().count(), 2);
assert_eq!(
index.scope(reactive_scope).kind(),
ScopeKind::Nse(NseScope::Nested, NseTiming::Lazy)
ScopeKind::Nse(EvalEnv::Nested, EvalTiming::Lazy)
);
}

Expand Down Expand Up @@ -257,7 +257,7 @@ fn test_namespace_bulk_import_enables_nse() {
assert_eq!(index.scope_ids().count(), 2);
assert_eq!(
index.scope(reactive_scope).kind(),
ScopeKind::Nse(NseScope::Nested, NseTiming::Lazy)
ScopeKind::Nse(EvalEnv::Nested, EvalTiming::Lazy)
);
}

Expand Down Expand Up @@ -299,7 +299,7 @@ fn test_namespace_reexport_chases_to_source_package() {
assert_eq!(index.scope_ids().count(), 2);
assert_eq!(
index.scope(reactive_scope).kind(),
ScopeKind::Nse(NseScope::Nested, NseTiming::Lazy)
ScopeKind::Nse(EvalEnv::Nested, EvalTiming::Lazy)
);
}

Expand Down Expand Up @@ -384,7 +384,7 @@ fn test_testthat_namespace_import_enables_nse() {
assert_eq!(index.scope_ids().count(), 2);
assert_eq!(
index.scope(reactive_scope).kind(),
ScopeKind::Nse(NseScope::Nested, NseTiming::Lazy)
ScopeKind::Nse(EvalEnv::Nested, EvalTiming::Lazy)
);
}

Expand Down Expand Up @@ -488,7 +488,7 @@ fn test_later_sibling_does_not_shadow() {
assert_eq!(index.scope_ids().count(), 2);
assert_eq!(
index.scope(reactive_scope).kind(),
ScopeKind::Nse(NseScope::Nested, NseTiming::Lazy)
ScopeKind::Nse(EvalEnv::Nested, EvalTiming::Lazy)
);
}

Expand All @@ -510,7 +510,7 @@ fn test_predecessor_sibling_attach_enables_nse() {
assert_eq!(index.scope_ids().count(), 2);
assert_eq!(
index.scope(reactive_scope).kind(),
ScopeKind::Nse(NseScope::Nested, NseTiming::Lazy)
ScopeKind::Nse(EvalEnv::Nested, EvalTiming::Lazy)
);
}

Expand Down Expand Up @@ -724,7 +724,7 @@ fn test_attached_package_enables_nse_scope() {
assert_eq!(index.scope_ids().count(), 2);
assert_eq!(
index.scope(reactive_scope).kind(),
ScopeKind::Nse(NseScope::Nested, NseTiming::Lazy)
ScopeKind::Nse(EvalEnv::Nested, EvalTiming::Lazy)
);
}

Expand All @@ -742,7 +742,7 @@ fn test_base_nse_resolves_with_no_attaches() {
assert_eq!(index.scope_ids().count(), 2);
assert_eq!(
index.scope(local_scope).kind(),
ScopeKind::Nse(NseScope::Nested, NseTiming::Eager)
ScopeKind::Nse(EvalEnv::Nested, EvalTiming::Eager)
);
}

Expand Down
10 changes: 5 additions & 5 deletions crates/oak_semantic/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,10 @@ use crate::semantic_index::DefinitionId;
use crate::semantic_index::DefinitionKind;
use crate::semantic_index::EnclosingSnapshotId;
use crate::semantic_index::EnclosingSnapshotKey;
use crate::semantic_index::EvalEnv;
use crate::semantic_index::EvalTiming;
use crate::semantic_index::NamespaceAccess;
use crate::semantic_index::NamespaceAccessKind;
use crate::semantic_index::NseScope;
use crate::semantic_index::NseTiming;
use crate::semantic_index::Scope;
use crate::semantic_index::ScopeId;
use crate::semantic_index::ScopeKind;
Expand Down Expand Up @@ -247,7 +247,7 @@ impl<R: ImportsResolver> SemanticIndexBuilder<R> {
// Eager` never reaches here because it doesn't push a scope.
if matches!(
self.scopes[self.current_scope].kind,
ScopeKind::Nse(NseScope::Current, NseTiming::Lazy)
ScopeKind::Nse(EvalEnv::Current, EvalTiming::Lazy)
) {
self.add_definition_to_owner(name, flags, kind, range);
return;
Expand Down Expand Up @@ -309,7 +309,7 @@ impl<R: ImportsResolver> SemanticIndexBuilder<R> {
let mut scope = self.scopes[self.current_scope].parent?;
while matches!(
self.scopes[scope].kind,
ScopeKind::Nse(NseScope::Current, NseTiming::Lazy)
ScopeKind::Nse(EvalEnv::Current, EvalTiming::Lazy)
) {
scope = self.scopes[scope].parent?;
}
Expand Down Expand Up @@ -819,7 +819,7 @@ impl<R: ImportsResolver> SemanticIndexBuilder<R> {
}

if let Some(target) = match self.scopes[self.current_scope].kind {
ScopeKind::Nse(NseScope::Current, NseTiming::Lazy) => self.definition_owner(),
ScopeKind::Nse(EvalEnv::Current, EvalTiming::Lazy) => self.definition_owner(),
_ => Some(self.current_scope),
} {
self.bound_names[target].add(name, range);
Expand Down
32 changes: 16 additions & 16 deletions crates/oak_semantic/src/builder/builder_nse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ use crate::effects::EffectsHandlers;
use crate::effects::ResolvedArgumentEffect;
use crate::effects::ResolvedArgumentEffects;
use crate::resolver::ImportsResolver;
use crate::semantic_index::NseScope;
use crate::semantic_index::NseTiming;
use crate::semantic_index::EvalEnv;
use crate::semantic_index::EvalTiming;
use crate::semantic_index::ScopeKind;
use crate::semantic_index::SemanticDiagnostic;

Expand Down Expand Up @@ -123,16 +123,16 @@ impl<R: ImportsResolver> SemanticIndexBuilder<R> {
self.scan_expression(hole);
}
},
Some(ResolvedArgumentEffect::Nse { scope, timing }) => match (scope, timing) {
Some(ResolvedArgumentEffect::EvalQ { env, timing }) => match (env, timing) {
// Calls like `evalq()`
(NseScope::Current, NseTiming::Eager) => self.scan_expression(&value),
(EvalEnv::Current, EvalTiming::Eager) => self.scan_expression(&value),

// Calls like `on_load()`. Its body runs later, so its defs
// land in the enclosing scope. We don't resolve the body's
// calls here. The walk does that once it enters the child
// scope. But we do grab the names it defines now, so the
// owner's bound names are complete before the walk reaches a sibling.
(NseScope::Current, NseTiming::Lazy) => {
(EvalEnv::Current, EvalTiming::Lazy) => {
self.record_enclosing_flow(value.syntax().text_trimmed_range());
self.scan_lazy_owner_bindings(&value);
},
Expand All @@ -145,7 +145,7 @@ impl<R: ImportsResolver> SemanticIndexBuilder<R> {
// have seeded.
// No `record_enclosing_flow()`: eager `Nested` bodies are
// never scanned at walk time, so nothing would read it.
(NseScope::Nested, NseTiming::Eager) => {
(EvalEnv::Nested, EvalTiming::Eager) => {
let old = self.flow_state.snapshot();

let range = value.syntax().text_trimmed_range();
Expand All @@ -162,7 +162,7 @@ impl<R: ImportsResolver> SemanticIndexBuilder<R> {
// later time, so it's a child scope scanned when the walk
// enters it. Record the names it inherits for its callee
// resolution, same as a function body.
(NseScope::Nested, NseTiming::Lazy) => {
(EvalEnv::Nested, EvalTiming::Lazy) => {
self.record_enclosing_flow(value.syntax().text_trimmed_range());
},
},
Expand Down Expand Up @@ -505,8 +505,8 @@ impl<R: ImportsResolver> SemanticIndexBuilder<R> {
continue;
};
match argument {
ResolvedArgumentEffect::Nse { scope, timing } => {
self.collect_nse_argument(*scope, *timing, &value)
ResolvedArgumentEffect::EvalQ { env, timing } => {
self.collect_nse_argument(*env, *timing, &value)
},
// Quoted argument: only the unquote holes are live.
ResolvedArgumentEffect::Quote { holes } => {
Expand All @@ -524,17 +524,17 @@ impl<R: ImportsResolver> SemanticIndexBuilder<R> {
/// already scanned by the descent, so we install its pending names and only
/// walk. The remaining lazy bodies are their own scan units that we scan
/// here on entry.
fn collect_nse_argument(&mut self, scope: NseScope, timing: NseTiming, value: &AnyRExpression) {
match (scope, timing) {
fn collect_nse_argument(&mut self, env: EvalEnv, timing: EvalTiming, value: &AnyRExpression) {
match (env, timing) {
// Calls like `evalq()`
(NseScope::Current, NseTiming::Eager) => {
(EvalEnv::Current, EvalTiming::Eager) => {
self.collect_expression(value);
},

// Calls like `local()`
(NseScope::Nested, NseTiming::Eager) => {
(EvalEnv::Nested, EvalTiming::Eager) => {
let range = value.syntax().text_trimmed_range();
let kind = ScopeKind::Nse(NseScope::Nested, NseTiming::Eager);
let kind = ScopeKind::Nse(EvalEnv::Nested, EvalTiming::Eager);
let scope = self.push_scope(kind, range);

// Install the pending names the descent recorded for this body,
Expand Down Expand Up @@ -562,8 +562,8 @@ impl<R: ImportsResolver> SemanticIndexBuilder<R> {
self.pop_scope(scope);
},

(nse_scope, nse_timing) => {
let kind = ScopeKind::Nse(nse_scope, nse_timing);
(env, timing) => {
let kind = ScopeKind::Nse(env, timing);
let scope = self.push_scope(kind, value.syntax().text_trimmed_range());

// Scan the child body before walking it. A `Current + Lazy`
Expand Down
18 changes: 11 additions & 7 deletions crates/oak_semantic/src/effects.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ pub use oak_core::range::RangedAstPtr;
use oak_core::syntax_ext::RIdentifierExt;
use oak_core::syntax_ext::RStringValueExt;

use crate::semantic_index::NseScope;
use crate::semantic_index::NseTiming;
use crate::semantic_index::EvalEnv;
use crate::semantic_index::EvalTiming;

/// Per-package tables of which functions carry effects. Private data behind the
/// `lookup`/`annotates` query API below.
Expand Down Expand Up @@ -235,8 +235,10 @@ pub type ResolvedArgumentEffects = Vec<Option<ResolvedArgumentEffect>>;
/// The resolved, per-call effect of one argument. The builder consumes these.
#[derive(Debug, Clone)]
pub enum ResolvedArgumentEffect {
/// Quote plus Eval in a controlled scope, fused.
Nse { scope: NseScope, timing: NseTiming },
/// Quote the argument, then evaluate it in `env`. `timing` says whether
/// that happens eagerly at the call site (`evalq()`, `local()`) or later
/// at an unknown time (`on_load()`, `reactive()`).
EvalQ { env: EvalEnv, timing: EvalTiming },
/// Captured unevaluated. `holes` are the sub-expressions that escape back to
/// evaluation (e.g. bquote's `.()` contents), walked normally; everything
/// else in the argument is inert. Empty for a plain `quote()`.
Expand All @@ -262,8 +264,10 @@ pub struct Argument {
/// evaluation model.
#[derive(Debug, Clone, Copy)]
pub enum ArgumentEffect {
/// Quote plus Eval in a controlled scope, fused
Nse { scope: NseScope, timing: NseTiming },
/// Quote the argument, then evaluate it in `env`. `timing` says whether
/// that happens eagerly at the call site (`evalq()`, `local()`) or later
/// at an unknown time (`on_load()`, `reactive()`).
EvalQ { env: EvalEnv, timing: EvalTiming },
/// Captured unevaluated, so its symbols are not uses and nothing in it runs.
/// `quote`. A function that unquotes (`bquote()`, whose `.()` holes escape)
/// can't be expressed statically, and must use a custom handler instead of
Expand All @@ -274,7 +278,7 @@ pub enum ArgumentEffect {
impl ArgumentEffect {
fn resolve(self) -> ResolvedArgumentEffect {
match self {
ArgumentEffect::Nse { scope, timing } => ResolvedArgumentEffect::Nse { scope, timing },
ArgumentEffect::EvalQ { env, timing } => ResolvedArgumentEffect::EvalQ { env, timing },
ArgumentEffect::Quote => ResolvedArgumentEffect::Quote { holes: Vec::new() },
}
}
Expand Down
4 changes: 2 additions & 2 deletions crates/oak_semantic/src/effects/contrib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ macro_rules! nse {
arguments: &[$($crate::effects::Argument {
name: $name,
position: $pos,
effect: $crate::effects::ArgumentEffect::Nse {
scope: $scope,
effect: $crate::effects::ArgumentEffect::EvalQ {
env: $scope,
timing: $timing,
},
}),+],
Expand Down
6 changes: 3 additions & 3 deletions crates/oak_semantic/src/effects/contrib/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ use crate::effects::EffectsHandlers;
use crate::effects::Formal;
use crate::effects::ResolvedArgumentEffect;
use crate::effects::ResolvedArgumentEffects;
use crate::semantic_index::NseScope::Current;
use crate::semantic_index::NseScope::Nested;
use crate::semantic_index::NseTiming::Eager;
use crate::semantic_index::EvalEnv::Current;
use crate::semantic_index::EvalEnv::Nested;
use crate::semantic_index::EvalTiming::Eager;

pub(crate) static ENTRIES: &[Entry] = &[
// base NSE
Expand Down
4 changes: 2 additions & 2 deletions crates/oak_semantic/src/effects/contrib/rlang.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ use crate::effects::contrib::assign_op;
use crate::effects::contrib::nse;
use crate::effects::contrib::Entry;
use crate::effects::TargetAccess::Write;
use crate::semantic_index::NseScope::Current;
use crate::semantic_index::NseTiming::Lazy;
use crate::semantic_index::EvalEnv::Current;
use crate::semantic_index::EvalTiming::Lazy;

pub(crate) static ENTRIES: &[Entry] = &[
assign_op!("rlang", "%<~%", Write),
Expand Down
4 changes: 2 additions & 2 deletions crates/oak_semantic/src/effects/contrib/shiny.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::effects::contrib::nse;
use crate::effects::contrib::Entry;
use crate::semantic_index::NseScope::Nested;
use crate::semantic_index::NseTiming::Lazy;
use crate::semantic_index::EvalEnv::Nested;
use crate::semantic_index::EvalTiming::Lazy;

pub(crate) static ENTRIES: &[Entry] = &[
nse!("shiny", "observe", ("x", 0, Nested, Lazy)),
Expand Down
4 changes: 2 additions & 2 deletions crates/oak_semantic/src/effects/contrib/testthat.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::effects::contrib::nse;
use crate::effects::contrib::Entry;
use crate::semantic_index::NseScope::Nested;
use crate::semantic_index::NseTiming::Eager;
use crate::semantic_index::EvalEnv::Nested;
use crate::semantic_index::EvalTiming::Eager;

pub(crate) static ENTRIES: &[Entry] = &[nse!("testthat", "test_that", ("code", 1, Nested, Eager))];
8 changes: 4 additions & 4 deletions crates/oak_semantic/src/semantic_index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -459,12 +459,12 @@ pub enum ScopeKind {
// cross-file resolution (package namespace, session, etc.) takes over.
File,
Function,
Nse(NseScope, NseTiming),
Nse(EvalEnv, EvalTiming),
}

/// Where definitions in an NSE scope land.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum NseScope {
pub enum EvalEnv {
/// Definitions go to the current (parent) environment.
/// e.g. `rlang::on_load()`
Current,
Expand All @@ -476,7 +476,7 @@ pub enum NseScope {
/// Whether an NSE scope evaluates eagerly (at the call site) or lazily
/// (at an unknown later time).
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum NseTiming {
pub enum EvalTiming {
/// Expression that runs at the call site. Free variables resolve against
/// the linear state right there. E.g. `local()`, `evalq()`, `test_that()`.
Eager,
Expand All @@ -495,7 +495,7 @@ impl ScopeKind {
match self {
ScopeKind::File => false,
ScopeKind::Function => true,
ScopeKind::Nse(_, timing) => timing == NseTiming::Lazy,
ScopeKind::Nse(_, timing) => timing == EvalTiming::Lazy,
}
}
}
Expand Down
Loading
Loading