From 803ae9309f54eaffff1340a81d06ede1969e26b1 Mon Sep 17 00:00:00 2001 From: Laurenz Date: Tue, 18 Jul 2023 21:53:42 +0200 Subject: [PATCH] Support `scope` argument for `eval` --- .../typst-library/src/compute/foundations.rs | 23 +++++++++++++++++- crates/typst/src/eval/mod.rs | 4 ++- crates/typst/src/eval/scope.rs | 11 +++++++-- tests/ref/compute/foundations.png | Bin 0 -> 2344 bytes tests/typ/compute/foundations.typ | 12 ++++++++- 5 files changed, 45 insertions(+), 5 deletions(-) create mode 100644 tests/ref/compute/foundations.png diff --git a/crates/typst-library/src/compute/foundations.rs b/crates/typst-library/src/compute/foundations.rs index ecac3ffad..b76631138 100644 --- a/crates/typst-library/src/compute/foundations.rs +++ b/crates/typst-library/src/compute/foundations.rs @@ -218,9 +218,30 @@ pub fn eval( #[named] #[default(EvalMode::Code)] mode: EvalMode, + /// A scope of definitions that are made available. + /// + /// ```example + /// #eval("x + 1", scope: (x: 2)) \ + /// #eval( + /// "abc/xyz", + /// mode: "math", + /// scope: ( + /// abc: $a + b + c$, + /// xyz: $x + y + z$, + /// ), + /// ) + /// ``` + #[named] + #[default] + scope: Dict, /// The virtual machine. vm: &mut Vm, ) -> SourceResult { let Spanned { v: text, span } = source; - typst::eval::eval_string(vm.world(), &text, mode, span) + let dict = scope; + let mut scope = Scope::new(); + for (key, value) in dict { + scope.define(key, value); + } + typst::eval::eval_string(vm.world(), &text, span, mode, scope) } diff --git a/crates/typst/src/eval/mod.rs b/crates/typst/src/eval/mod.rs index 6f684a7bd..f72eeaa4f 100644 --- a/crates/typst/src/eval/mod.rs +++ b/crates/typst/src/eval/mod.rs @@ -145,8 +145,9 @@ pub fn eval( pub fn eval_string( world: Tracked, string: &str, - mode: EvalMode, span: Span, + mode: EvalMode, + scope: Scope, ) -> SourceResult { let mut root = match mode { EvalMode::Code => parse_code(string), @@ -179,6 +180,7 @@ pub fn eval_string( let id = FileId::detached(); let scopes = Scopes::new(Some(world.library())); let mut vm = Vm::new(vt, route.track(), id, scopes); + vm.scopes.scopes.push(scope); // Evaluate the code. let result = match mode { diff --git a/crates/typst/src/eval/scope.rs b/crates/typst/src/eval/scope.rs index f3e137151..b8d5b75a0 100644 --- a/crates/typst/src/eval/scope.rs +++ b/crates/typst/src/eval/scope.rs @@ -72,7 +72,11 @@ impl<'a> Scopes<'a> { #[cold] fn unknown_variable(var: &str) -> EcoString { if var.contains('-') { - eco_format!("unknown variable: {} - if you meant to use subtraction, try adding spaces around the minus sign.", var) + eco_format!( + "unknown variable: {} - if you meant to use subtraction, \ + try adding spaces around the minus sign.", + var + ) } else { eco_format!("unknown variable: {}", var) } @@ -171,7 +175,10 @@ impl Slot { match self.kind { Kind::Normal => Ok(&mut self.value), Kind::Captured => { - bail!("variables from outside the function are read-only and cannot be modified") + bail!( + "variables from outside the function are \ + read-only and cannot be modified" + ) } } } diff --git a/tests/ref/compute/foundations.png b/tests/ref/compute/foundations.png new file mode 100644 index 0000000000000000000000000000000000000000..5d6ba7441a7ca4f992779f6e61b304476fbb7cd7 GIT binary patch literal 2344 zcmZwJ`#;l*9|!QyY_*{#lu&I$E|sQShlI^s&OwqQUs0g;S&6sY zWSsPJrg$Kj$?^#oinsX`aDPnBOvyxvxl7+*MGyXCZXcbFSJ8qb-ru!59_s{?vi#q$ zVF}A-ARBy84dDyOcw$KvQ8)fQ%=%8fk&iIl_NrR*lApW3z&W6@;dpMD;=SG4d7UL4 zAKVo>XHRZKJAz?}-Gr23JBqdiW*ee>IqyyrqSMsD-#O+oJCmyUT?~&*SvqphB{LLp zm3;Pu3CzE0wns32>_ysQS!nJcTkpI_yl#2Xd9G{QRhkhGqUFczn`*gQ-!nK>2Aq^t z(~s+%Jv)g!KXs*NHFEDzGN$)wWQIQQKIni&|G=9{=AQ9Np?ZeYy+lW8n5!TR=)#9R z9E^L#|K#3laO6}bp0B7RnLl}cz;E5Lq>8(gBG<1a{enjPw5mAjJ|wJIeV9snHGY)1 zL7^=)$+Ny0W{U49QF?y7vLJd%_4v83v|kXPHi-)H2>o)VFK1rSqUm=UyU8;yLdU^A z8zzW?bSmOqid0t3>}eDWd@<(0*xFr zzCgSiyif?=ZC-sh%>x&wPS%e*Rz$%5Ej}32vv9pxza2SJKt^4dPV(gRq40+7F!dn4 z6206xU`HFRmCAn_=A??fU2Rhmz1RK}8lXq-jW~2h9ww6nrkwSor+HJq^-CHJT|=Vm zetRv7K~t=#U1f%p>xPjE&#jcZ=qe3ORAQ0VsGcm0;`W8lNII-S$OmaCb7>R@Kk$%r zpcK}F{#gnzK|>mAEHgx~sVt?PV8pd+1I`hyU(Bw7DwDB9YeI4m8c6oNl%S~r(%~9_ zX7k*RBVIVr$%J$CyG-tUT|ac8VEctXT`ZP~p?}aW(vi<-I#w;w#6mWN!QhvnfDN1Y zBD}V@@hW+AP(|2U6B}2^ry=;Owb5GCLk~UtIlr%;^9M&7)zmrcNwMIJQJ`)rXk5k_ zjnGmikWbrqrMAW zyYeNN(?oW!%i@&tdcghg(TU>a3?bpEhMJ#_@VJ4(fQ<_~>F`AB?SD40k*QoHH#99? z`5OLXUF`+Ui4g4>yQtujJ+`R6^Vdx=b1}!}`;E<7!xGLB;RPK-{VD&Ht+iVkdvv0> z+>gO^CM{ek-kVOK@hdybYmSOBaD7>q-P^gDYn$lK@^xV15^ZH8nzyC}nBjK|pY%w} z8I{?OYmu2R7v2fRhm1PcCgcX$!K{~3MomIeFOHxLDt-+563P>W)Ry-iHpSMe&t%N> zLE;Gq0laSY=}{4fZy8v8J~ZUQfi)15PW8qU^5Orrl^C+eR@sftp$@w8&>_6t{d0 z^7Q)Y0ZV2k^e*nXDi@ z#hY~_BvuJCFs}&BCxHS4WQmJ@;*YiA;=zKc{h+Kg!RfCClENAxj!2|Z+zMD?~6r>&a!F+=jlPs3&zAJ-52?ZR8I_i10*l;&3~ zks_w>L}#dUnS=b1<`7>qqN_gj z?x0H6vD~Us6Ki!5Tk6d2j(Xh9=b>5aQz)X7>(ILM?MGXxRbSV`r%A1Eh*bUAK2W!} zT)HNb2Nfhsr;pCbpY0HX6ba9&W9M&2+z1M|+pk-S%7NB`oxUjm+6pxRpS@JNLPsT1 zulKiJww6K4&*PMDxd}h*aB2Atn7?qdt9~1XQJDwL;d{P})O6^aJJDdH4LA5WiDZKk zdIE6_`wh4-Z3eO5-M;A&^!0bp2$JBh%4*AOqmUj25WPO@9GqT}qXCm9zJ0X7JE;=L zWiH?m$jpKI7HrRdIe`dCe6aMScRs;{a z5|L!xsrd*wI^$|mk5kEsZE0`U2Nqd+da)I%`%TlGhMZt)vPVe?%k`2?&qbo&ESc$4 z5ysp<^=`m8**Zd-B$ctLWUce1|gW-8;@#%x-O2Xrjt{wZ5?Lp3$wFez!+W?exT z>0^M}|CUf|GBCW0+OF&pQ*^=D