summaryrefslogtreecommitdiff
path: root/src/eval
diff options
context:
space:
mode:
Diffstat (limited to 'src/eval')
-rw-r--r--src/eval/mod.rs9
-rw-r--r--src/eval/scope.rs20
-rw-r--r--src/eval/value.rs33
3 files changed, 34 insertions, 28 deletions
diff --git a/src/eval/mod.rs b/src/eval/mod.rs
index 4992f70c..dc4ab7ee 100644
--- a/src/eval/mod.rs
+++ b/src/eval/mod.rs
@@ -17,6 +17,7 @@ use std::rc::Rc;
use crate::cache::Cache;
use crate::diag::{Diag, DiagSet, Pass};
+use crate::eco::EcoString;
use crate::geom::{Angle, Fractional, Length, Relative};
use crate::loading::{FileHash, Loader};
use crate::parse::parse;
@@ -528,7 +529,7 @@ impl Eval for ClosureExpr {
visitor.finish()
};
- let name = self.name.as_ref().map(|id| id.to_string());
+ let name = self.name.as_ref().map(|name| name.string.clone());
Value::Func(FuncValue::new(name, move |ctx, args| {
// Don't leak the scopes from the call site. Instead, we use the
// scope of captured variables we collected earlier.
@@ -555,7 +556,7 @@ impl Eval for WithExpr {
let callee = self.callee.eval(ctx);
if let Some(func) = ctx.cast::<FuncValue>(callee, self.callee.span()) {
let applied = self.args.eval(ctx);
- let name = func.name().map(|s| s.to_string());
+ let name = func.name().cloned();
Value::Func(FuncValue::new(name, move |ctx, args| {
// Remove named arguments that were overridden.
let kept: Vec<_> = applied
@@ -698,7 +699,7 @@ impl Eval for ImportExpr {
fn eval(&self, ctx: &mut EvalContext) -> Self::Output {
let path = self.path.eval(ctx);
- if let Some(path) = ctx.cast::<String>(path, self.path.span()) {
+ if let Some(path) = ctx.cast::<EcoString>(path, self.path.span()) {
if let Some(hash) = ctx.import(&path, self.path.span()) {
let mut module = &ctx.modules[&hash];
match &self.imports {
@@ -734,7 +735,7 @@ impl Eval for IncludeExpr {
fn eval(&self, ctx: &mut EvalContext) -> Self::Output {
let path = self.path.eval(ctx);
- if let Some(path) = ctx.cast::<String>(path, self.path.span()) {
+ if let Some(path) = ctx.cast::<EcoString>(path, self.path.span()) {
if let Some(hash) = ctx.import(&path, self.path.span()) {
return Value::Template(ctx.modules[&hash].template.clone());
}
diff --git a/src/eval/scope.rs b/src/eval/scope.rs
index 3f7c4c62..05bbeda2 100644
--- a/src/eval/scope.rs
+++ b/src/eval/scope.rs
@@ -4,7 +4,7 @@ use std::fmt::{self, Debug, Display, Formatter};
use std::iter;
use std::rc::Rc;
-use super::{AnyValue, EvalContext, FuncArgs, FuncValue, Type, Value};
+use super::{AnyValue, EcoString, EvalContext, FuncArgs, FuncValue, Type, Value};
/// A slot where a variable is stored.
pub type Slot = Rc<RefCell<Value>>;
@@ -39,17 +39,17 @@ impl<'a> Scopes<'a> {
}
/// Define a constant variable with a value in the active scope.
- pub fn def_const(&mut self, var: impl Into<String>, value: impl Into<Value>) {
+ pub fn def_const(&mut self, var: impl Into<EcoString>, value: impl Into<Value>) {
self.top.def_const(var, value);
}
/// Define a mutable variable with a value in the active scope.
- pub fn def_mut(&mut self, var: impl Into<String>, value: impl Into<Value>) {
+ pub fn def_mut(&mut self, var: impl Into<EcoString>, value: impl Into<Value>) {
self.top.def_mut(var, value);
}
/// Define a variable with a slot in the active scope.
- pub fn def_slot(&mut self, var: impl Into<String>, slot: Slot) {
+ pub fn def_slot(&mut self, var: impl Into<EcoString>, slot: Slot) {
self.top.def_slot(var, slot);
}
@@ -66,7 +66,7 @@ impl<'a> Scopes<'a> {
#[derive(Default, Clone, PartialEq)]
pub struct Scope {
/// The mapping from names to slots.
- values: HashMap<String, Slot>,
+ values: HashMap<EcoString, Slot>,
}
impl Scope {
@@ -76,7 +76,7 @@ impl Scope {
}
/// Define a constant variable with a value.
- pub fn def_const(&mut self, var: impl Into<String>, value: impl Into<Value>) {
+ pub fn def_const(&mut self, var: impl Into<EcoString>, value: impl Into<Value>) {
let cell = RefCell::new(value.into());
// Make it impossible to write to this value again.
@@ -87,7 +87,7 @@ impl Scope {
}
/// Define a constant function.
- pub fn def_func<F>(&mut self, name: impl Into<String>, f: F)
+ pub fn def_func<F>(&mut self, name: impl Into<EcoString>, f: F)
where
F: Fn(&mut EvalContext, &mut FuncArgs) -> Value + 'static,
{
@@ -96,7 +96,7 @@ impl Scope {
}
/// Define a constant variable with a value of variant `Value::Any`.
- pub fn def_any<T>(&mut self, var: impl Into<String>, any: T)
+ pub fn def_any<T>(&mut self, var: impl Into<EcoString>, any: T)
where
T: Type + Debug + Display + Clone + PartialEq + 'static,
{
@@ -104,12 +104,12 @@ impl Scope {
}
/// Define a mutable variable with a value.
- pub fn def_mut(&mut self, var: impl Into<String>, value: impl Into<Value>) {
+ pub fn def_mut(&mut self, var: impl Into<EcoString>, value: impl Into<Value>) {
self.values.insert(var.into(), Rc::new(RefCell::new(value.into())));
}
/// Define a variable with a slot.
- pub fn def_slot(&mut self, var: impl Into<String>, slot: Slot) {
+ pub fn def_slot(&mut self, var: impl Into<EcoString>, slot: Slot) {
self.values.insert(var.into(), slot);
}
diff --git a/src/eval/value.rs b/src/eval/value.rs
index 07552c84..2881399b 100644
--- a/src/eval/value.rs
+++ b/src/eval/value.rs
@@ -5,8 +5,7 @@ use std::fmt::{self, Debug, Display, Formatter};
use std::ops::Deref;
use std::rc::Rc;
-use super::ops;
-use super::EvalContext;
+use super::*;
use crate::color::{Color, RgbaColor};
use crate::exec::ExecContext;
use crate::geom::{Angle, Fractional, Length, Linear, Relative};
@@ -38,7 +37,7 @@ pub enum Value {
/// A color value: `#f79143ff`.
Color(Color),
/// A string: `"string"`.
- Str(String),
+ Str(EcoString),
/// An array value: `(1, "hi", 12cm)`.
Array(ArrayValue),
/// A dictionary value: `(color: #f79143, pattern: dashed)`.
@@ -76,7 +75,7 @@ impl Value {
Self::Linear(_) => Linear::TYPE_NAME,
Self::Fractional(_) => Fractional::TYPE_NAME,
Self::Color(_) => Color::TYPE_NAME,
- Self::Str(_) => String::TYPE_NAME,
+ Self::Str(_) => EcoString::TYPE_NAME,
Self::Array(_) => ArrayValue::TYPE_NAME,
Self::Dict(_) => DictValue::TYPE_NAME,
Self::Template(_) => TemplateValue::TYPE_NAME,
@@ -151,7 +150,7 @@ impl Default for Value {
pub type ArrayValue = Vec<Value>;
/// A dictionary value: `(color: #f79143, pattern: dashed)`.
-pub type DictValue = BTreeMap<String, Value>;
+pub type DictValue = BTreeMap<EcoString, Value>;
/// A template value: `[*Hi* there]`.
pub type TemplateValue = Rc<Vec<TemplateNode>>;
@@ -171,7 +170,7 @@ pub enum TemplateNode {
map: ExprMap,
},
/// A template that was converted from a string.
- Str(String),
+ Str(EcoString),
/// A function template that can implement custom behaviour.
Func(TemplateFunc),
}
@@ -224,14 +223,14 @@ impl Debug for TemplateFunc {
pub struct FuncValue {
/// The string is boxed to make the whole struct fit into 24 bytes, so that
/// a [`Value`] fits into 32 bytes.
- name: Option<Box<String>>,
+ name: Option<Box<EcoString>>,
/// The closure that defines the function.
f: Rc<dyn Fn(&mut EvalContext, &mut FuncArgs) -> Value>,
}
impl FuncValue {
/// Create a new function value from a rust function or closure.
- pub fn new<F>(name: Option<String>, f: F) -> Self
+ pub fn new<F>(name: Option<EcoString>, f: F) -> Self
where
F: Fn(&mut EvalContext, &mut FuncArgs) -> Value + 'static,
{
@@ -239,8 +238,8 @@ impl FuncValue {
}
/// The name of the function.
- pub fn name(&self) -> Option<&str> {
- self.name.as_ref().map(|s| s.as_str())
+ pub fn name(&self) -> Option<&EcoString> {
+ self.name.as_ref().map(|s| &**s)
}
}
@@ -342,7 +341,7 @@ impl FuncArgs {
let index = self
.items
.iter()
- .position(|arg| arg.name.as_ref().map_or(false, |other| name == other))?;
+ .position(|arg| arg.name.as_ref().map_or(false, |other| other == name))?;
let value = self.items.remove(index).value;
let span = value.span;
@@ -381,7 +380,7 @@ pub struct FuncArg {
/// The span of the whole argument.
pub span: Span,
/// The name of the argument (`None` for positional arguments).
- pub name: Option<String>,
+ pub name: Option<EcoString>,
/// The value of the argument.
pub value: Spanned<Value>,
}
@@ -608,7 +607,7 @@ primitive! {
}
primitive! { Fractional: "fractional", Value::Fractional }
primitive! { Color: "color", Value::Color }
-primitive! { String: "string", Value::Str }
+primitive! { EcoString: "string", Value::Str }
primitive! { ArrayValue: "array", Value::Array }
primitive! { DictValue: "dictionary", Value::Dict }
primitive! {
@@ -624,9 +623,15 @@ impl From<usize> for Value {
}
}
+impl From<String> for Value {
+ fn from(v: String) -> Self {
+ Self::Str(v.into())
+ }
+}
+
impl From<&str> for Value {
fn from(v: &str) -> Self {
- Self::Str(v.to_string())
+ Self::Str(v.into())
}
}