Skip to main content

Policy

Struct Policy 

Source
pub struct Policy { /* private fields */ }
Expand description

A language’s complete scoping policy.

Start from a preset (kraken, php, python) or new (the lexical default, the same as Kraken), then adjust with the with_* setters. The policy is plain data, normally read from the language’s sketch.

§Examples

use resolve_lang::{ClassScope, Hoist, ItemClass, Namespace, Policy};

let p = Policy::new()
    .with_hoisting(ItemClass::Fn, Hoist::AfterDecl)
    .with_class_scope(ClassScope::BodyOnly)
    .with_merge(Namespace::Type, Namespace::Value);
assert_eq!(p.hoisting(ItemClass::Fn), Hoist::AfterDecl);
assert_eq!(p.table(Namespace::Type), Namespace::Value);

Implementations§

Source§

impl Policy

Source

pub const fn new() -> Self

The lexical default (equal to kraken): every item hoisted to its scope; separate value, type, and macro tables with modules sharing the type table and constants sharing the value table; every table case-sensitive; class members (own and inherited) visible in methods; isolated nested modules; Self:: early, parent::/static:: unsupported; visibility enforced with private items visible to child modules; globs, aliases, and declared re-exports.

§Examples
use resolve_lang::{ItemClass, Namespace, NsSet, Policy};

let p = Policy::new();
assert_eq!(p.occupies(ItemClass::Record), NsSet::of(&[Namespace::Type, Namespace::Value]));
assert!(p.visibility_enforced());
Source

pub const fn kraken() -> Self

Kraken and Iron: lexical scoping, modules with imports and visibility. Equal to new.

§Examples
use resolve_lang::Policy;

assert_eq!(Policy::kraken(), Policy::new());
Source

pub const fn php() -> Self

PHP (and Mox): functions, classes, interfaces, enums, and constants are visible in their whole namespace wherever declared; class members are reached only through self::/parent::/static:: (late static binding for static::); use imports are file-local and have no globs; global $x may name a global that does not exist yet.

Names follow PHP 8’s tables and case rules:

TableHoldsCase
Valuefunctions, methodsASCII-insensitive
Type (with Module)classes, interfaces, traits, enums, namespacesASCII-insensitive
Constconstants, class constants, globals, static propertiessensitive

So a function and a constant, or a method and a class constant, may share a name; strlen and STRLEN are one function; and a class lives in the type table only. A class named where a value goes (new C, x instanceof C, as the Mox sketch lowers them) still resolves, through class_values; a class reaches its interfaces’ constants and methods through interface_members. HIR paths carry no $ sigil, so a sketch that strips it from static property names makes a static property and a class constant of the same name collide; keep the sigil in property names ($count) to keep them apart.

§Examples
use resolve_lang::{Case, Hoist, ItemClass, Namespace, NsSet, Policy};

let p = Policy::php();
assert_eq!(p.hoisting(ItemClass::Class), Hoist::Module);
assert_eq!(p.occupies(ItemClass::Class), NsSet::single(Namespace::Type));
assert_ne!(p.table(Namespace::Const), p.table(Namespace::Value));
assert_eq!(p.case(Namespace::Type), Case::AsciiInsensitive);
assert!(!p.globs_allowed());
assert!(p.implicit_globals());
assert!(p.class_values() && p.interface_members());
Source

pub const fn python() -> Self

Python (and Mercury): one case-sensitive table for every kind of name; a name bound anywhere in a scope belongs to the whole scope; class bodies are not visible to methods; members are inherited in C3 method resolution order (as under every policy; an inconsistent hierarchy is reported, as Python raises TypeError at class creation); redefinition rebinds; visibility is convention only; imports become module attributes.

§Examples
use resolve_lang::{Namespace, Policy};

let p = Policy::python();
assert_eq!(p.table(Namespace::Type), Namespace::Value);
assert_eq!(p.table(Namespace::Module), Namespace::Value);
assert!(!p.visibility_enforced());
Source

pub const fn with_hoisting(self, class: ItemClass, hoist: Hoist) -> Self

Sets when items of class become visible.

§Examples
use resolve_lang::{Hoist, ItemClass, Policy};

let p = Policy::new().with_hoisting(ItemClass::Global, Hoist::AfterDecl);
assert_eq!(p.hoisting(ItemClass::Global), Hoist::AfterDecl);
Source

pub const fn with_occupies(self, class: ItemClass, set: NsSet) -> Self

Sets the namespaces items of class define their name in. Imports ignore this (an import binds whatever its target defines).

§Examples
use resolve_lang::{ItemClass, Namespace, NsSet, Policy};

// Rust: a braced struct defines no constructor value.
let p = Policy::new().with_occupies(ItemClass::Record, NsSet::single(Namespace::Type));
assert!(!p.occupies(ItemClass::Record).contains(Namespace::Value));
Source

pub const fn with_merge(self, from: Namespace, into: Namespace) -> Self

Merges namespace from into the table of into: afterwards both (and everything already merged with either) share one table, so a name defined in one conflicts with and is found by the other. The merged table keeps into’s Case.

§Examples
use resolve_lang::{Namespace, Policy};

let p = Policy::new().with_merge(Namespace::Value, Namespace::Type);
// Modules already share the type table, so all three are one table now.
assert_eq!(p.table(Namespace::Value), p.table(Namespace::Module));
Source

pub const fn with_case(self, ns: Namespace, case: Case) -> Self

Sets how the table of ns (and every namespace merged with it) compares names. Merge first, then set the case: a later merge keeps the target table’s case.

§Examples
use resolve_lang::{Case, Namespace, Policy};

let p = Policy::new().with_case(Namespace::Type, Case::AsciiInsensitive);
// Modules share the type table, so they fold too.
assert_eq!(p.case(Namespace::Module), Case::AsciiInsensitive);
assert_eq!(p.case(Namespace::Value), Case::Sensitive);
Source

pub const fn with_shadowing(self, shadowing: Shadowing) -> Self

Sets the shadowing rule for binders.

§Examples
use resolve_lang::{Policy, Shadowing};

assert_eq!(Policy::new().with_shadowing(Shadowing::DenyLocals).shadowing(), Shadowing::DenyLocals);
Source

pub const fn with_redefinition(self, redefinition: Redefinition) -> Self

Sets what duplicate definitions mean.

§Examples
use resolve_lang::{Policy, Redefinition};

let p = Policy::new().with_redefinition(Redefinition::LastWins);
assert_eq!(p.redefinition(), Redefinition::LastWins);
Source

pub const fn with_class_scope(self, class_scope: ClassScope) -> Self

Sets what code inside a class sees of its members.

§Examples
use resolve_lang::{ClassScope, Policy};

let p = Policy::new().with_class_scope(ClassScope::Qualified);
assert_eq!(p.class_scope(), ClassScope::Qualified);
Source

pub const fn with_module_scope(self, module_scope: ModuleScope) -> Self

Sets whether nested modules see outer names.

§Examples
use resolve_lang::{ModuleScope, Policy};

let p = Policy::new().with_module_scope(ModuleScope::Lexical);
assert_eq!(p.module_scope(), ModuleScope::Lexical);
Source

pub const fn with_roots( self, self_root: RootBinding, parent_root: RootBinding, static_root: RootBinding, ) -> Self

Sets how self::, parent::, and static:: bind.

§Examples
use resolve_lang::{Policy, RootBinding};

let p = Policy::new().with_roots(RootBinding::Early, RootBinding::Early, RootBinding::Late);
assert_eq!(p.parent_root(), RootBinding::Early);
Source

pub const fn with_visibility( self, enforce: bool, private_to_descendants: bool, ) -> Self

Sets whether visibility is enforced, and whether private items of a module are visible to its descendant modules.

§Examples
use resolve_lang::Policy;

let p = Policy::new().with_visibility(true, false);
assert!(p.visibility_enforced());
assert!(!p.private_to_descendants());
Source

pub const fn with_imports( self, globs: bool, aliases: bool, reexport: Reexport, ) -> Self

Sets which import forms the language has, and how imports re-export.

§Examples
use resolve_lang::{Policy, Reexport};

let p = Policy::new().with_imports(false, true, Reexport::Never);
assert!(!p.globs_allowed());
assert!(p.aliases_allowed());
Source

pub const fn with_implicit_globals(self, implicit: bool) -> Self

Sets whether a global declaration naming no known global binds a host global (Res::Extern) instead of being reported.

§Examples
use resolve_lang::Policy;

assert!(Policy::new().with_implicit_globals(true).implicit_globals());
Source

pub const fn with_class_values(self, on: bool) -> Self

Sets whether a class may be named in value position.

Languages whose classes are not values still write class names where a value goes: new Foo(1) lowers to a call whose first operand is Foo, and $x instanceof Foo takes it as its right operand. With this set, a value path that finds nothing in the value tables falls back to the type table and resolves to a class (or record) item there, or to a class the host defines. It applies to unqualified names (Foo), module-qualified ones (App\Foo, \App\Foo), and imported ones, folded by the type table’s case rule. A constant or function of the same name wins, and a path that is the callee of a call does not fall back (Foo() is not new Foo). Foo::bar, Foo::C, and Foo::class need no fallback: their first segment is already looked up as a container.

An interface (or a sum) stays an error in value position: hir-lang refuses a value path that resolves to one, so a lowering names an interface through a type argument.

Off by default; php turns it on.

§Examples
use resolve_lang::Policy;

assert!(Policy::php().class_values());
assert!(!Policy::kraken().class_values());
assert!(Policy::kraken().with_class_values(true).class_values());
Source

pub const fn with_interface_members(self, on: bool) -> Self

Sets whether a class inherits the members of the interfaces it implements.

With this set, Impl::NAME finds a constant (or method) declared on an interface Impl implements, directly or through a base class or a super-interface, when neither the class nor its base classes declare it; PHP’s lookup order. Without it, interfaces contribute no members to the classes implementing them.

Off by default; php turns it on.

§Examples
use resolve_lang::Policy;

assert!(Policy::php().interface_members());
assert!(!Policy::python().interface_members());
Source

pub const fn hoisting(&self, class: ItemClass) -> Hoist

When items of class become visible.

§Examples
use resolve_lang::{Hoist, ItemClass, Policy};

assert_eq!(Policy::new().hoisting(ItemClass::Fn), Hoist::Scope);
Source

pub const fn occupies(&self, class: ItemClass) -> NsSet

The namespaces items of class define their name in (before merging).

§Examples
use resolve_lang::{ItemClass, Namespace, Policy};

assert!(Policy::new().occupies(ItemClass::Fn).contains(Namespace::Value));
Source

pub const fn table(&self, ns: Namespace) -> Namespace

The table namespace ns is stored in after merging.

§Examples
use resolve_lang::{Namespace, Policy};

assert_eq!(Policy::new().table(Namespace::Module), Namespace::Type);
assert_eq!(Policy::new().table(Namespace::Value), Namespace::Value);
Source

pub const fn case(&self, ns: Namespace) -> Case

How the table of ns compares names.

§Examples
use resolve_lang::{Case, Namespace, Policy};

assert_eq!(Policy::new().case(Namespace::Value), Case::Sensitive);
Source

pub const fn shadowing(&self) -> Shadowing

The shadowing rule.

§Examples
use resolve_lang::{Policy, Shadowing};

assert_eq!(Policy::new().shadowing(), Shadowing::Allow);
Source

pub const fn redefinition(&self) -> Redefinition

What duplicate definitions mean.

§Examples
use resolve_lang::{Policy, Redefinition};

assert_eq!(Policy::php().redefinition(), Redefinition::Error);
Source

pub const fn class_scope(&self) -> ClassScope

What code inside a class sees of its members.

§Examples
use resolve_lang::{ClassScope, Policy};

assert_eq!(Policy::new().class_scope(), ClassScope::Lexical);
Source

pub const fn module_scope(&self) -> ModuleScope

Whether nested modules see outer names.

§Examples
use resolve_lang::{ModuleScope, Policy};

assert_eq!(Policy::php().module_scope(), ModuleScope::Lexical);
Source

pub const fn self_root(&self) -> RootBinding

How self:: binds.

§Examples
use resolve_lang::{Policy, RootBinding};

assert_eq!(Policy::python().self_root(), RootBinding::Unsupported);
Source

pub const fn parent_root(&self) -> RootBinding

How parent:: binds.

§Examples
use resolve_lang::{Policy, RootBinding};

assert_eq!(Policy::kraken().parent_root(), RootBinding::Unsupported);
Source

pub const fn static_root(&self) -> RootBinding

How static:: binds.

§Examples
use resolve_lang::{Policy, RootBinding};

assert_eq!(Policy::php().static_root(), RootBinding::Late);
Source

pub const fn visibility_enforced(&self) -> bool

Whether visibility (Vis) is enforced.

§Examples
use resolve_lang::Policy;

assert!(Policy::php().visibility_enforced());
Source

pub const fn private_to_descendants(&self) -> bool

Whether private items of a module are visible in its descendant modules (Rust’s rule).

§Examples
use resolve_lang::Policy;

assert!(Policy::new().private_to_descendants());
Source

pub const fn globs_allowed(&self) -> bool

Whether glob imports are allowed.

§Examples
use resolve_lang::Policy;

assert!(Policy::python().globs_allowed());
Source

pub const fn aliases_allowed(&self) -> bool

Whether aliased imports (use x as y) are allowed.

§Examples
use resolve_lang::Policy;

assert!(Policy::php().aliases_allowed());
Source

pub const fn reexport(&self) -> Reexport

How imports re-export.

§Examples
use resolve_lang::{Policy, Reexport};

assert_eq!(Policy::php().reexport(), Reexport::Never);
Source

pub const fn implicit_globals(&self) -> bool

Whether an unknown global name binds a host global.

§Examples
use resolve_lang::Policy;

assert!(!Policy::kraken().implicit_globals());
Source

pub const fn class_values(&self) -> bool

Whether a class-like item may be named in value position (with_class_values).

§Examples
use resolve_lang::Policy;

assert!(Policy::php().class_values());
Source

pub const fn interface_members(&self) -> bool

Whether classes inherit the members of their interfaces (with_interface_members).

§Examples
use resolve_lang::Policy;

assert!(Policy::php().interface_members());

Trait Implementations§

Source§

impl Clone for Policy

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Copy for Policy

Source§

impl Debug for Policy

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for Policy

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl Eq for Policy

Source§

impl Hash for Policy

Source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
Source§

impl PartialEq for Policy

Source§

fn eq(&self, other: &Self) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl StructuralPartialEq for Policy

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.