mirror of
https://github.com/typst/typst
synced 2025-05-15 01:25:28 +08:00
Small refactorings
This commit is contained in:
parent
fd417da04f
commit
6ea98dd940
@ -64,7 +64,7 @@
|
|||||||
|
|
||||||
- name: lr
|
- name: lr
|
||||||
display: Left/Right
|
display: Left/Right
|
||||||
functions: ["lr", "abs", "norm", "floor", "ceil"]
|
functions: ["lr", "abs", "norm", "floor", "ceil", "round"]
|
||||||
description: |
|
description: |
|
||||||
Delimiter matching.
|
Delimiter matching.
|
||||||
|
|
||||||
|
@ -43,10 +43,10 @@ pub fn module() -> Module {
|
|||||||
scope.define("rem", rem_func());
|
scope.define("rem", rem_func());
|
||||||
scope.define("mod", mod_func());
|
scope.define("mod", mod_func());
|
||||||
scope.define("quo", quo_func());
|
scope.define("quo", quo_func());
|
||||||
scope.define("inf", Value::Float(f64::INFINITY));
|
scope.define("inf", f64::INFINITY);
|
||||||
scope.define("nan", Value::Float(f64::NAN));
|
scope.define("nan", f64::NAN);
|
||||||
scope.define("pi", Value::Float(std::f64::consts::PI));
|
scope.define("pi", std::f64::consts::PI);
|
||||||
scope.define("e", Value::Float(std::f64::consts::E));
|
scope.define("e", std::f64::consts::E);
|
||||||
Module::new("calc").with_scope(scope)
|
Module::new("calc").with_scope(scope)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ use comemo::Tracked;
|
|||||||
use crate::syntax::{ErrorPos, Span, Spanned};
|
use crate::syntax::{ErrorPos, Span, Spanned};
|
||||||
use crate::World;
|
use crate::World;
|
||||||
|
|
||||||
/// Early-return with a [`StrError`] or [`SourceError`].
|
/// Early-return with a [`StrResult`] or [`SourceResult`].
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
macro_rules! __bail {
|
macro_rules! __bail {
|
||||||
@ -35,7 +35,7 @@ macro_rules! __bail {
|
|||||||
#[doc(inline)]
|
#[doc(inline)]
|
||||||
pub use crate::__bail as bail;
|
pub use crate::__bail as bail;
|
||||||
|
|
||||||
/// Construct a [`StrError`] or [`SourceError`].
|
/// Construct an [`EcoString`] or [`SourceError`].
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
macro_rules! __error {
|
macro_rules! __error {
|
||||||
|
@ -7,7 +7,8 @@ use ecow::eco_format;
|
|||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
cast, Args, CastInfo, Eval, Flow, IntoValue, Route, Scope, Scopes, Tracer, Value, Vm,
|
cast, Args, CastInfo, Eval, FlowEvent, IntoValue, Route, Scope, Scopes, Tracer,
|
||||||
|
Value, Vm,
|
||||||
};
|
};
|
||||||
use crate::diag::{bail, SourceResult, StrResult};
|
use crate::diag::{bail, SourceResult, StrResult};
|
||||||
use crate::model::{ElemFunc, Introspector, Locator, Vt};
|
use crate::model::{ElemFunc, Introspector, Locator, Vt};
|
||||||
@ -404,8 +405,8 @@ impl Closure {
|
|||||||
// Handle control flow.
|
// Handle control flow.
|
||||||
let result = closure.body.eval(&mut vm);
|
let result = closure.body.eval(&mut vm);
|
||||||
match vm.flow {
|
match vm.flow {
|
||||||
Some(Flow::Return(_, Some(explicit))) => return Ok(explicit),
|
Some(FlowEvent::Return(_, Some(explicit))) => return Ok(explicit),
|
||||||
Some(Flow::Return(_, None)) => {}
|
Some(FlowEvent::Return(_, None)) => {}
|
||||||
Some(flow) => bail!(flow.forbidden()),
|
Some(flow) => bail!(flow.forbidden()),
|
||||||
None => {}
|
None => {}
|
||||||
}
|
}
|
||||||
|
@ -191,7 +191,7 @@ pub struct Vm<'a> {
|
|||||||
/// The current location.
|
/// The current location.
|
||||||
location: SourceId,
|
location: SourceId,
|
||||||
/// A control flow event that is currently happening.
|
/// A control flow event that is currently happening.
|
||||||
flow: Option<Flow>,
|
flow: Option<FlowEvent>,
|
||||||
/// The stack of scopes.
|
/// The stack of scopes.
|
||||||
scopes: Scopes<'a>,
|
scopes: Scopes<'a>,
|
||||||
/// The current call depth.
|
/// The current call depth.
|
||||||
@ -257,7 +257,7 @@ impl<'a> Vm<'a> {
|
|||||||
|
|
||||||
/// A control flow event that occurred during evaluation.
|
/// A control flow event that occurred during evaluation.
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub enum Flow {
|
pub enum FlowEvent {
|
||||||
/// Stop iteration in a loop.
|
/// Stop iteration in a loop.
|
||||||
Break(Span),
|
Break(Span),
|
||||||
/// Skip the remainder of the current iteration in a loop.
|
/// Skip the remainder of the current iteration in a loop.
|
||||||
@ -267,7 +267,7 @@ pub enum Flow {
|
|||||||
Return(Span, Option<Value>),
|
Return(Span, Option<Value>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Flow {
|
impl FlowEvent {
|
||||||
/// Return an error stating that this control flow is forbidden.
|
/// Return an error stating that this control flow is forbidden.
|
||||||
pub fn forbidden(&self) -> SourceError {
|
pub fn forbidden(&self) -> SourceError {
|
||||||
match *self {
|
match *self {
|
||||||
@ -328,7 +328,7 @@ impl<'a> Route<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Traces which values existed for the expression at a span.
|
/// Traces which values existed for an expression at a span.
|
||||||
#[derive(Default, Clone)]
|
#[derive(Default, Clone)]
|
||||||
pub struct Tracer {
|
pub struct Tracer {
|
||||||
span: Option<Span>,
|
span: Option<Span>,
|
||||||
@ -1286,17 +1286,18 @@ impl Eval for ast::Closure {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ast::Pattern {
|
impl ast::Pattern {
|
||||||
fn destruct_array<T>(
|
fn destruct_array<F>(
|
||||||
&self,
|
&self,
|
||||||
vm: &mut Vm,
|
vm: &mut Vm,
|
||||||
value: Array,
|
value: Array,
|
||||||
f: T,
|
f: F,
|
||||||
destruct: &ast::Destructuring,
|
destruct: &ast::Destructuring,
|
||||||
) -> SourceResult<Value>
|
) -> SourceResult<Value>
|
||||||
where
|
where
|
||||||
T: Fn(&mut Vm, ast::Expr, Value) -> SourceResult<Value>,
|
F: Fn(&mut Vm, ast::Expr, Value) -> SourceResult<Value>,
|
||||||
{
|
{
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
|
let len = value.as_slice().len();
|
||||||
for p in destruct.bindings() {
|
for p in destruct.bindings() {
|
||||||
match p {
|
match p {
|
||||||
ast::DestructuringKind::Normal(expr) => {
|
ast::DestructuringKind::Normal(expr) => {
|
||||||
@ -1307,14 +1308,11 @@ impl ast::Pattern {
|
|||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
ast::DestructuringKind::Sink(spread) => {
|
ast::DestructuringKind::Sink(spread) => {
|
||||||
let sink_size =
|
let sink_size = (1 + len).checked_sub(destruct.bindings().count());
|
||||||
(1 + value.len()).checked_sub(destruct.bindings().count());
|
let sink = sink_size.and_then(|s| value.as_slice().get(i..i + s));
|
||||||
let sink = sink_size
|
|
||||||
.and_then(|s| value.slice(i as i64, Some((i + s) as i64)).ok());
|
|
||||||
|
|
||||||
if let (Some(sink_size), Some(sink)) = (sink_size, sink) {
|
if let (Some(sink_size), Some(sink)) = (sink_size, sink) {
|
||||||
if let Some(expr) = spread.expr() {
|
if let Some(expr) = spread.expr() {
|
||||||
f(vm, expr, Value::Array(sink.clone()))?;
|
f(vm, expr, Value::Array(sink.into()))?;
|
||||||
}
|
}
|
||||||
i += sink_size;
|
i += sink_size;
|
||||||
} else {
|
} else {
|
||||||
@ -1325,7 +1323,7 @@ impl ast::Pattern {
|
|||||||
bail!(named.span(), "cannot destructure named elements from an array")
|
bail!(named.span(), "cannot destructure named elements from an array")
|
||||||
}
|
}
|
||||||
ast::DestructuringKind::Placeholder(underscore) => {
|
ast::DestructuringKind::Placeholder(underscore) => {
|
||||||
if i < value.len() {
|
if i < len {
|
||||||
i += 1
|
i += 1
|
||||||
} else {
|
} else {
|
||||||
bail!(underscore.span(), "not enough elements to destructure")
|
bail!(underscore.span(), "not enough elements to destructure")
|
||||||
@ -1333,41 +1331,44 @@ impl ast::Pattern {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if i < value.len() {
|
if i < len {
|
||||||
bail!(self.span(), "too many elements to destructure");
|
bail!(self.span(), "too many elements to destructure");
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Value::None)
|
Ok(Value::None)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn destruct_dict<T>(
|
fn destruct_dict<F>(
|
||||||
&self,
|
&self,
|
||||||
vm: &mut Vm,
|
vm: &mut Vm,
|
||||||
value: Dict,
|
dict: Dict,
|
||||||
f: T,
|
f: F,
|
||||||
destruct: &ast::Destructuring,
|
destruct: &ast::Destructuring,
|
||||||
) -> SourceResult<Value>
|
) -> SourceResult<Value>
|
||||||
where
|
where
|
||||||
T: Fn(&mut Vm, ast::Expr, Value) -> SourceResult<Value>,
|
F: Fn(&mut Vm, ast::Expr, Value) -> SourceResult<Value>,
|
||||||
{
|
{
|
||||||
let mut sink = None;
|
let mut sink = None;
|
||||||
let mut used = HashSet::new();
|
let mut used = HashSet::new();
|
||||||
for p in destruct.bindings() {
|
for p in destruct.bindings() {
|
||||||
match p {
|
match p {
|
||||||
ast::DestructuringKind::Normal(ast::Expr::Ident(ident)) => {
|
ast::DestructuringKind::Normal(ast::Expr::Ident(ident)) => {
|
||||||
let Ok(v) = value.at(&ident, None) else {
|
let v = dict
|
||||||
bail!(ident.span(), "destructuring key not found in dictionary");
|
.at(&ident, None)
|
||||||
};
|
.map_err(|_| "destructuring key not found in dictionary")
|
||||||
|
.at(ident.span())?;
|
||||||
f(vm, ast::Expr::Ident(ident.clone()), v.clone())?;
|
f(vm, ast::Expr::Ident(ident.clone()), v.clone())?;
|
||||||
used.insert(ident.take());
|
used.insert(ident.take());
|
||||||
}
|
}
|
||||||
ast::DestructuringKind::Sink(spread) => sink = spread.expr(),
|
ast::DestructuringKind::Sink(spread) => sink = spread.expr(),
|
||||||
ast::DestructuringKind::Named(named) => {
|
ast::DestructuringKind::Named(named) => {
|
||||||
let Ok(v) = value.at(named.name().as_str(), None) else {
|
let name = named.name();
|
||||||
bail!(named.name().span(), "destructuring key not found in dictionary");
|
let v = dict
|
||||||
};
|
.at(&name, None)
|
||||||
|
.map_err(|_| "destructuring key not found in dictionary")
|
||||||
|
.at(name.span())?;
|
||||||
f(vm, named.expr(), v.clone())?;
|
f(vm, named.expr(), v.clone())?;
|
||||||
used.insert(named.name().take());
|
used.insert(name.take());
|
||||||
}
|
}
|
||||||
ast::DestructuringKind::Placeholder(_) => {}
|
ast::DestructuringKind::Placeholder(_) => {}
|
||||||
ast::DestructuringKind::Normal(expr) => {
|
ast::DestructuringKind::Normal(expr) => {
|
||||||
@ -1378,7 +1379,7 @@ impl ast::Pattern {
|
|||||||
|
|
||||||
if let Some(expr) = sink {
|
if let Some(expr) = sink {
|
||||||
let mut sink = Dict::new();
|
let mut sink = Dict::new();
|
||||||
for (key, value) in value {
|
for (key, value) in dict {
|
||||||
if !used.contains(key.as_str()) {
|
if !used.contains(key.as_str()) {
|
||||||
sink.insert(key, value);
|
sink.insert(key, value);
|
||||||
}
|
}
|
||||||
@ -1549,12 +1550,12 @@ impl Eval for ast::WhileLoop {
|
|||||||
output = ops::join(output, value).at(body.span())?;
|
output = ops::join(output, value).at(body.span())?;
|
||||||
|
|
||||||
match vm.flow {
|
match vm.flow {
|
||||||
Some(Flow::Break(_)) => {
|
Some(FlowEvent::Break(_)) => {
|
||||||
vm.flow = None;
|
vm.flow = None;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Some(Flow::Continue(_)) => vm.flow = None,
|
Some(FlowEvent::Continue(_)) => vm.flow = None,
|
||||||
Some(Flow::Return(..)) => break,
|
Some(FlowEvent::Return(..)) => break,
|
||||||
None => {}
|
None => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1612,12 +1613,12 @@ impl Eval for ast::ForLoop {
|
|||||||
output = ops::join(output, value).at(body.span())?;
|
output = ops::join(output, value).at(body.span())?;
|
||||||
|
|
||||||
match vm.flow {
|
match vm.flow {
|
||||||
Some(Flow::Break(_)) => {
|
Some(FlowEvent::Break(_)) => {
|
||||||
vm.flow = None;
|
vm.flow = None;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Some(Flow::Continue(_)) => vm.flow = None,
|
Some(FlowEvent::Continue(_)) => vm.flow = None,
|
||||||
Some(Flow::Return(..)) => break,
|
Some(FlowEvent::Return(..)) => break,
|
||||||
None => {}
|
None => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1781,7 +1782,7 @@ impl Eval for ast::LoopBreak {
|
|||||||
#[tracing::instrument(name = "LoopBreak::eval", skip_all)]
|
#[tracing::instrument(name = "LoopBreak::eval", skip_all)]
|
||||||
fn eval(&self, vm: &mut Vm) -> SourceResult<Self::Output> {
|
fn eval(&self, vm: &mut Vm) -> SourceResult<Self::Output> {
|
||||||
if vm.flow.is_none() {
|
if vm.flow.is_none() {
|
||||||
vm.flow = Some(Flow::Break(self.span()));
|
vm.flow = Some(FlowEvent::Break(self.span()));
|
||||||
}
|
}
|
||||||
Ok(Value::None)
|
Ok(Value::None)
|
||||||
}
|
}
|
||||||
@ -1793,7 +1794,7 @@ impl Eval for ast::LoopContinue {
|
|||||||
#[tracing::instrument(name = "LoopContinue::eval", skip_all)]
|
#[tracing::instrument(name = "LoopContinue::eval", skip_all)]
|
||||||
fn eval(&self, vm: &mut Vm) -> SourceResult<Self::Output> {
|
fn eval(&self, vm: &mut Vm) -> SourceResult<Self::Output> {
|
||||||
if vm.flow.is_none() {
|
if vm.flow.is_none() {
|
||||||
vm.flow = Some(Flow::Continue(self.span()));
|
vm.flow = Some(FlowEvent::Continue(self.span()));
|
||||||
}
|
}
|
||||||
Ok(Value::None)
|
Ok(Value::None)
|
||||||
}
|
}
|
||||||
@ -1806,7 +1807,7 @@ impl Eval for ast::FuncReturn {
|
|||||||
fn eval(&self, vm: &mut Vm) -> SourceResult<Self::Output> {
|
fn eval(&self, vm: &mut Vm) -> SourceResult<Self::Output> {
|
||||||
let value = self.body().map(|body| body.eval(vm)).transpose()?;
|
let value = self.body().map(|body| body.eval(vm)).transpose()?;
|
||||||
if vm.flow.is_none() {
|
if vm.flow.is_none() {
|
||||||
vm.flow = Some(Flow::Return(self.span(), value));
|
vm.flow = Some(FlowEvent::Return(self.span(), value));
|
||||||
}
|
}
|
||||||
Ok(Value::None)
|
Ok(Value::None)
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
use std::mem;
|
|
||||||
|
|
||||||
/// Produce shapes that together make up a rounded rectangle.
|
/// Produce shapes that together make up a rounded rectangle.
|
||||||
pub fn rounded_rect(
|
pub fn rounded_rect(
|
||||||
size: Size,
|
size: Size,
|
||||||
@ -69,7 +67,7 @@ fn stroke_segments(
|
|||||||
);
|
);
|
||||||
|
|
||||||
if !continuous {
|
if !continuous {
|
||||||
res.push((mem::take(&mut path), stroke.get_ref(side).clone()));
|
res.push((std::mem::take(&mut path), stroke.get_ref(side).clone()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,6 +34,21 @@ impl Debug for Scalar {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Eq for Scalar {}
|
||||||
|
|
||||||
|
impl PartialEq for Scalar {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
assert!(!self.0.is_nan() && !other.0.is_nan(), "float is NaN");
|
||||||
|
self.0 == other.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialEq<f64> for Scalar {
|
||||||
|
fn eq(&self, other: &f64) -> bool {
|
||||||
|
self == &Self(*other)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Ord for Scalar {
|
impl Ord for Scalar {
|
||||||
fn cmp(&self, other: &Self) -> Ordering {
|
fn cmp(&self, other: &Self) -> Ordering {
|
||||||
self.partial_cmp(other).expect("float is NaN")
|
self.partial_cmp(other).expect("float is NaN")
|
||||||
@ -62,21 +77,6 @@ impl PartialOrd for Scalar {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Eq for Scalar {}
|
|
||||||
|
|
||||||
impl PartialEq for Scalar {
|
|
||||||
fn eq(&self, other: &Self) -> bool {
|
|
||||||
assert!(!self.0.is_nan() && !other.0.is_nan(), "float is NaN");
|
|
||||||
self.0 == other.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PartialEq<f64> for Scalar {
|
|
||||||
fn eq(&self, other: &f64) -> bool {
|
|
||||||
self == &Self(*other)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Hash for Scalar {
|
impl Hash for Scalar {
|
||||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
debug_assert!(!self.0.is_nan(), "float is NaN");
|
debug_assert!(!self.0.is_nan(), "float is NaN");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user