Skip to main content

Program

Struct Program 

Source
pub struct Program<'e> { /* private fields */ }
Expand description

Several units resolved against each other (Tier 3): the in-memory multi-unit driver. Each unit may be given a root name, by which every unit (itself included) can reach its root module as a path’s first segment (util::helper, import util). Imports may form cycles across units.

§Examples

use hir_lang::{Builder, Def, Expr, FnDef, Item, ItemKind, Name, Ns, Path, Res, Segment, UnitId, Vis};
use intern_lang::Interner;
use resolve_lang::{Policy, Program};

let mut names = Interner::new();
let (util, helper) = (Name::new(names.intern("util")), Name::new(names.intern("helper")));

// Unit 1, reachable as `util`: pub fn helper() {}
let mut b = Builder::for_unit(UnitId::new(1));
let body = b.block(&[], None);
let f = b.item(Item::new(Some(helper), ItemKind::Fn(FnDef { body: Some(body), ..FnDef::default() })).with_vis(Vis::Public));
let root = b.module(None, &[f]);
let util_hir = b.finish(root)?;

// Unit 2: fn main() { util::helper }
let mut b = Builder::for_unit(UnitId::new(2));
let segs = [Segment::new(util, b.origin()), Segment::new(helper, b.origin())];
let segs = b.list(&segs);
let path = b.path(Path::new(segs, Ns::Value));
let call = b.expr(Expr::Path(path));
let body = b.block(&[], Some(call));
let main = b.func(Name::new(names.intern("main")), &[], body);
let root = b.module(None, &[main]);
let app_hir = b.finish(root)?;

let mut program = Program::new(Policy::kraken());
program.add_unit(Some(util), util_hir);
program.add_unit(None, app_hir);
let res = program.resolve(&names)?;
assert!(res.is_clean());
let app = res.hir(UnitId::new(2)).unwrap();
let Res::Def(d) = app.path(path).res else { panic!("unresolved") };
assert_eq!((d.unit(), d.def()), (UnitId::new(1), Def::Item(f)));

Implementations§

Source§

impl Program<'static>

Source

pub fn new(policy: Policy) -> Self

An empty program with policy, no environment, and the default budget.

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

let p = Program::new(Policy::kraken());
assert_eq!(p.len(), 0);
Source§

impl Program<'_>

Source

pub fn with_env(self, env: &dyn Env) -> Program<'_>

Uses env for names outside the program.

§Examples
use resolve_lang::{MapEnv, Policy, Program};

let env = MapEnv::new();
let _p = Program::new(Policy::new()).with_env(&env);
Source

pub fn with_budget(self, budget: Budget) -> Self

Sets the budget.

§Examples
use resolve_lang::{Budget, Policy, Program};

let _p = Program::new(Policy::new()).with_budget(Budget::default().with_glob_bindings(10));
Source

pub fn add_unit(&mut self, name: Option<Name>, hir: Hir)

Adds a unit in package 0, reachable by name (if given) from every unit.

§Examples
use hir_lang::Builder;
use resolve_lang::{Policy, Program};

let mut b = Builder::new();
let root = b.module(None, &[]);
let mut p = Program::new(Policy::new());
p.add_unit(None, b.finish(root)?);
assert_eq!(p.len(), 1);
Source

pub fn add_unit_in(&mut self, package: u32, name: Option<Name>, hir: Hir)

Adds a unit to a package: Vis::Package items are visible across units of the same package only.

§Examples
use hir_lang::Builder;
use resolve_lang::{Policy, Program};

let mut b = Builder::new();
let root = b.module(None, &[]);
let mut p = Program::new(Policy::new());
p.add_unit_in(7, None, b.finish(root)?);
assert!(!p.is_empty());
Source

pub fn len(&self) -> usize

The number of units added.

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

assert_eq!(Program::new(Policy::new()).len(), 0);
Source

pub fn is_empty(&self) -> bool

Whether no unit was added.

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

assert!(Program::new(Policy::new()).is_empty());
Source

pub fn resolve<L: Lookup>(self, names: &L) -> Result<Resolution, ResolveError>

Resolves every unit.

§Errors
§Examples
use hir_lang::{Builder, UnitId};
use intern_lang::Interner;
use resolve_lang::{Policy, Program, ResolveError};

let mut p = Program::new(Policy::new());
for _ in 0..2 {
    let mut b = Builder::for_unit(UnitId::new(1));
    let root = b.module(None, &[]);
    p.add_unit(None, b.finish(root)?);
}
assert_eq!(p.resolve(&Interner::new()).unwrap_err(), ResolveError::DuplicateUnit { unit: UnitId::new(1) });

Trait Implementations§

Source§

impl Debug for Program<'_>

Source§

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

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<'e> !RefUnwindSafe for Program<'e>

§

impl<'e> !Send for Program<'e>

§

impl<'e> !Sync for Program<'e>

§

impl<'e> !UnwindSafe for Program<'e>

§

impl<'e> Freeze for Program<'e>

§

impl<'e> Unpin for Program<'e>

§

impl<'e> UnsafeUnpin for Program<'e>

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> 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, 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.