Add std module for names in the standard library (#4038)

This commit is contained in:
PgBiel 2024-04-30 09:49:18 -03:00 committed by GitHub
parent 44bc51ba4f
commit 1247c6d8e1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 58 additions and 5 deletions

View File

@ -48,8 +48,14 @@ impl<'a> Scopes<'a> {
pub fn get(&self, var: &str) -> HintedStrResult<&Value> {
std::iter::once(&self.top)
.chain(self.scopes.iter().rev())
.chain(self.base.map(|base| base.global.scope()))
.find_map(|scope| scope.get(var))
.or_else(|| {
self.base.and_then(|base| match base.global.scope().get(var) {
Some(value) => Some(value),
None if var == "std" => Some(&base.std),
None => None,
})
})
.ok_or_else(|| unknown_variable(var))
}
@ -57,8 +63,14 @@ impl<'a> Scopes<'a> {
pub fn get_in_math(&self, var: &str) -> HintedStrResult<&Value> {
std::iter::once(&self.top)
.chain(self.scopes.iter().rev())
.chain(self.base.map(|base| base.math.scope()))
.find_map(|scope| scope.get(var))
.or_else(|| {
self.base.and_then(|base| match base.math.scope().get(var) {
Some(value) => Some(value),
None if var == "std" => Some(&base.std),
None => None,
})
})
.ok_or_else(|| unknown_variable(var))
}
@ -69,13 +81,19 @@ impl<'a> Scopes<'a> {
.find_map(|scope| scope.get_mut(var))
.ok_or_else(|| {
match self.base.and_then(|base| base.global.scope().get(var)) {
Some(_) => eco_format!("cannot mutate a constant: {}", var).into(),
Some(_) => cannot_mutate_constant(var),
_ if var == "std" => cannot_mutate_constant(var),
_ => unknown_variable(var),
}
})?
}
}
#[cold]
fn cannot_mutate_constant(var: &str) -> HintedString {
eco_format!("cannot mutate a constant: {}", var).into()
}
/// The error message when a variable is not found.
#[cold]
fn unknown_variable(var: &str) -> HintedString {

View File

@ -67,7 +67,7 @@ use crate::diag::{warning, FileResult, SourceDiagnostic, SourceResult};
use crate::engine::{Engine, Route};
use crate::eval::Tracer;
use crate::foundations::{
Array, Bytes, Content, Datetime, Dict, Module, Scope, StyleChain, Styles,
Array, Bytes, Content, Datetime, Dict, Module, Scope, StyleChain, Styles, Value,
};
use crate::introspection::{Introspector, Locator};
use crate::layout::{Alignment, Dir, LayoutRoot};
@ -297,6 +297,9 @@ pub struct Library {
/// The default style properties (for page size, font selection, and
/// everything else configurable via set and show rules).
pub styles: Styles,
/// The standard library as a value.
/// Used to provide the `std` variable.
pub std: Value,
}
impl Library {
@ -333,7 +336,8 @@ impl LibraryBuilder {
let math = math::module();
let inputs = self.inputs.unwrap_or_default();
let global = global(math.clone(), inputs);
Library { global, math, styles: Styles::new() }
let std = Value::Module(global.clone());
Library { global, math, styles: Styles::new(), std }
}
}

BIN
tests/ref/std-math.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 298 B

View File

@ -0,0 +1,31 @@
// Test 'std', a module with the standard library
--- std-basic-access ---
#test(std.grid, grid)
#test(std.calc, calc)
--- std-import ---
#import std: grid as banana
#test(grid, banana)
--- std-of-shadowed ---
#let my-grid = grid[a][b]
#let grid = "oh no!"
#test(my-grid.func(), std.grid)
--- std-shadowing ---
#let std = 5
// Error: 6-10 cannot access fields on type integer
#std.grid
--- std-mutation ---
// Error: 3-6 cannot mutate a constant: std
#(std = 10)
--- std-shadowed-mutation ---
#let std = 10
#(std = 7)
#test(std, 7)
--- std-math ---
$ std.rect(x + y = 5) $