compile.rs 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710
  1. /* This file is part of DarkFi (https://dark.fi)
  2. *
  3. * Copyright (C) 2020-2026 Dyne.org foundation
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU Affero General Public License as
  7. * published by the Free Software Foundation, either version 3 of the
  8. * License, or (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU Affero General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Affero General Public License
  16. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  17. */
  18. use crate::{
  19. error::{Error, Result},
  20. //prop::{Property, PropertySubType, PropertyType, PropertySExprValue},
  21. };
  22. use std::collections::HashMap;
  23. use super::{Op, SExprCode};
  24. #[derive(Debug, Clone)]
  25. enum Token {
  26. LoadVar(String),
  27. Add,
  28. Sub,
  29. Mul,
  30. Div,
  31. LeftParen,
  32. RightParen,
  33. ConstFloat32(f32),
  34. NestedExpr(Box<Vec<Token>>),
  35. SubExpr(Box<Vec<Token>>),
  36. If,
  37. Else,
  38. LeftBrace,
  39. RightBrace,
  40. LessThan,
  41. IfElse((Box<Vec<Token>>, Box<Vec<Token>>, Box<Vec<Token>>)),
  42. LessThanCompare((Box<Vec<Token>>, Box<Vec<Token>>)),
  43. Equals,
  44. SetValue((String, Box<Vec<Token>>)),
  45. }
  46. impl Token {
  47. fn flatten(self) -> Vec<Self> {
  48. match self {
  49. Self::NestedExpr(tokens) => {
  50. let tokens: Vec<_> = *tokens;
  51. tokens.into_iter().map(|t| t.flatten()).flatten().collect()
  52. }
  53. _ => vec![self],
  54. }
  55. }
  56. }
  57. #[derive(Clone)]
  58. pub struct Compiler {
  59. table: HashMap<String, Token>,
  60. }
  61. impl Compiler {
  62. pub fn new() -> Self {
  63. Self { table: HashMap::new() }
  64. }
  65. pub fn add_const_f32<S: Into<String>>(&mut self, name: S, val: f32) {
  66. self.table.insert(name.into(), Token::ConstFloat32(val));
  67. }
  68. /*
  69. pub fn get_const_f32<S: AsRef<str>>(&self, name: S) -> Option<f32> {
  70. let name = name.as_ref();
  71. let val = self.table.get(name)?;
  72. match val {
  73. Token::ConstFloat32(v) => Some(v)
  74. _ => None
  75. }
  76. }
  77. */
  78. pub fn compile<S: AsRef<str>>(&self, prestmts: S) -> Result<SExprCode> {
  79. let prestmts = prestmts.as_ref();
  80. // Strip all comments
  81. let mut stmts = String::new();
  82. for line in prestmts.lines() {
  83. if let Some(chr) = line.trim_start().chars().next() {
  84. if chr != '#' {
  85. stmts.push_str(line);
  86. }
  87. }
  88. }
  89. let mut code = vec![];
  90. for stmt in stmts.split(';') {
  91. code.push(self.compile_line(stmt)?);
  92. }
  93. Ok(code)
  94. }
  95. fn compile_line(&self, stmt: &str) -> Result<Op> {
  96. let tokens = self.tokenize(&stmt);
  97. //println!("{tokens:#?}");
  98. let tokens = to_rpn(tokens)?;
  99. //println!("{tokens:#?}");
  100. Ok(convert(&mut tokens.into_iter())?)
  101. }
  102. fn tokenize(&self, stmt: &str) -> Vec<Token> {
  103. let mut tokens = Vec::new();
  104. let mut current_token = String::new();
  105. for chr in stmt.chars() {
  106. match chr {
  107. ' ' | '\t' | '\n' => {
  108. self.clear_accum(&mut current_token, &mut tokens);
  109. }
  110. '+' => {
  111. self.clear_accum(&mut current_token, &mut tokens);
  112. tokens.push(Token::Add);
  113. }
  114. '-' => {
  115. self.clear_accum(&mut current_token, &mut tokens);
  116. tokens.push(Token::Sub);
  117. }
  118. '*' => {
  119. self.clear_accum(&mut current_token, &mut tokens);
  120. tokens.push(Token::Mul);
  121. }
  122. '/' => {
  123. self.clear_accum(&mut current_token, &mut tokens);
  124. tokens.push(Token::Div);
  125. }
  126. '(' => {
  127. self.clear_accum(&mut current_token, &mut tokens);
  128. tokens.push(Token::LeftParen);
  129. }
  130. ')' => {
  131. self.clear_accum(&mut current_token, &mut tokens);
  132. tokens.push(Token::RightParen);
  133. }
  134. '{' => {
  135. self.clear_accum(&mut current_token, &mut tokens);
  136. tokens.push(Token::LeftBrace);
  137. }
  138. '}' => {
  139. self.clear_accum(&mut current_token, &mut tokens);
  140. tokens.push(Token::RightBrace);
  141. }
  142. '<' => {
  143. self.clear_accum(&mut current_token, &mut tokens);
  144. tokens.push(Token::LessThan);
  145. }
  146. '=' => {
  147. self.clear_accum(&mut current_token, &mut tokens);
  148. tokens.push(Token::Equals);
  149. }
  150. _ => current_token.push(chr),
  151. }
  152. }
  153. self.clear_accum(&mut current_token, &mut tokens);
  154. tokens
  155. }
  156. fn clear_accum(&self, current_token: &mut String, tokens: &mut Vec<Token>) {
  157. let prev_token = std::mem::replace(current_token, String::new());
  158. if prev_token.is_empty() {
  159. return
  160. }
  161. if let Some(token) = self.table.get(&prev_token) {
  162. tokens.push(token.clone());
  163. return
  164. }
  165. match prev_token.as_str() {
  166. "if" => {
  167. tokens.push(Token::If);
  168. return
  169. }
  170. "else" => {
  171. tokens.push(Token::Else);
  172. return
  173. }
  174. _ => {}
  175. }
  176. // Number or var?
  177. match prev_token.parse::<f32>() {
  178. Ok(v) => tokens.push(Token::ConstFloat32(v)),
  179. Err(_) => tokens.push(Token::LoadVar(prev_token)),
  180. }
  181. }
  182. }
  183. /// Convert from infix to reverse polish notation
  184. fn to_rpn(tokens: Vec<Token>) -> Result<Vec<Token>> {
  185. //println!("to_rpn = {tokens:#?}");
  186. let mut out;
  187. let mut stack = Vec::new();
  188. // equals
  189. let mut iter = tokens.into_iter();
  190. let mut var = String::new();
  191. let mut lhs = vec![];
  192. let mut rhs = vec![];
  193. let mut comparison = 0;
  194. // 0: none
  195. // 1: =
  196. while let Some(token) = iter.next() {
  197. match token {
  198. Token::Equals => {
  199. if comparison != 0 {
  200. return Err(Error::UnexpectedToken)
  201. }
  202. comparison = 1;
  203. if lhs.len() != 1 {
  204. return Err(Error::UnexpectedToken)
  205. }
  206. let lhs = std::mem::take(&mut lhs);
  207. match lhs.into_iter().next().unwrap() {
  208. Token::LoadVar(v) => var = v,
  209. _ => return Err(Error::UnexpectedToken),
  210. }
  211. }
  212. token => {
  213. if comparison == 0 {
  214. lhs.push(token);
  215. } else {
  216. rhs.push(token);
  217. }
  218. }
  219. }
  220. }
  221. if comparison == 1 {
  222. let stack = std::mem::take(&mut rhs);
  223. let rpn = to_rpn(stack)?;
  224. out = vec![Token::SetValue((var, Box::new(rpn)))];
  225. } else {
  226. assert!(rhs.is_empty());
  227. out = lhs;
  228. }
  229. // Parens
  230. let tokens = std::mem::take(&mut out);
  231. let mut paren = 0;
  232. for token in tokens {
  233. match token {
  234. Token::LeftParen => {
  235. // Is this the first opening paren for this subexpr?
  236. if paren > 0 {
  237. stack.push(token);
  238. }
  239. paren += 1;
  240. continue
  241. }
  242. Token::RightParen => {
  243. paren -= 1;
  244. // Whoops non-matching number of parens!
  245. if paren < 0 {
  246. return Err(Error::UnexpectedToken)
  247. }
  248. // Did we finally reach the closing paren for this subexpr?
  249. if paren == 0 {
  250. let stack = std::mem::take(&mut stack);
  251. let rpn = to_rpn(stack)?;
  252. out.push(Token::NestedExpr(Box::new(rpn)));
  253. } else {
  254. stack.push(token);
  255. }
  256. continue
  257. }
  258. _ => {}
  259. }
  260. if paren > 0 {
  261. stack.push(token);
  262. } else {
  263. out.push(token);
  264. }
  265. }
  266. out.append(&mut stack);
  267. // Braces
  268. let tokens = std::mem::take(&mut out);
  269. assert!(stack.is_empty());
  270. let mut paren = 0;
  271. for token in tokens {
  272. match token {
  273. Token::LeftBrace => {
  274. // Is this the first opening paren for this subexpr?
  275. if paren > 0 {
  276. stack.push(token);
  277. }
  278. paren += 1;
  279. continue
  280. }
  281. Token::RightBrace => {
  282. paren -= 1;
  283. // Whoops non-matching number of parens!
  284. if paren < 0 {
  285. return Err(Error::UnexpectedToken)
  286. }
  287. // Did we finally reach the closing paren for this subexpr?
  288. if paren == 0 {
  289. let stack = std::mem::take(&mut stack);
  290. let rpn = to_rpn(stack)?;
  291. out.push(Token::SubExpr(Box::new(rpn)));
  292. } else {
  293. stack.push(token);
  294. }
  295. continue
  296. }
  297. _ => {}
  298. }
  299. if paren > 0 {
  300. stack.push(token);
  301. } else {
  302. out.push(token);
  303. }
  304. }
  305. out.append(&mut stack);
  306. let tokens = std::mem::take(&mut out);
  307. assert!(stack.is_empty());
  308. let mut iter = tokens.into_iter();
  309. 'mainloop: while let Some(token) = iter.next() {
  310. match token {
  311. Token::If => {
  312. let mut section = 0;
  313. let mut cond_expr = vec![];
  314. let mut if_expr = vec![];
  315. let mut else_expr = vec![];
  316. while let Some(token) = iter.next() {
  317. match token {
  318. Token::SubExpr(tokens) => {
  319. if section == 0 {
  320. let cexpr = std::mem::take(&mut cond_expr);
  321. cond_expr = to_rpn(cexpr)?;
  322. if_expr = *tokens;
  323. } else if section == 1 {
  324. else_expr = *tokens;
  325. } else {
  326. return Err(Error::UnexpectedToken)
  327. }
  328. section += 1;
  329. }
  330. Token::Else => {
  331. if section != 1 {
  332. return Err(Error::UnexpectedToken)
  333. }
  334. }
  335. token => {
  336. if section != 0 {
  337. out.push(Token::IfElse((
  338. Box::new(cond_expr),
  339. Box::new(if_expr),
  340. Box::new(else_expr),
  341. )));
  342. out.push(token);
  343. continue 'mainloop;
  344. }
  345. cond_expr.push(token);
  346. }
  347. }
  348. }
  349. // We reached the end
  350. out.push(Token::IfElse((
  351. Box::new(cond_expr),
  352. Box::new(if_expr),
  353. Box::new(else_expr),
  354. )));
  355. }
  356. token => out.push(token),
  357. }
  358. }
  359. // comparisons <>=
  360. let tokens = std::mem::take(&mut out);
  361. let mut iter = tokens.into_iter();
  362. let mut lhs = vec![];
  363. let mut rhs = vec![];
  364. let mut comparison = 0;
  365. // 0: none
  366. // 1: <
  367. while let Some(token) = iter.next() {
  368. match token {
  369. Token::LessThan => {
  370. if comparison != 0 {
  371. return Err(Error::UnexpectedToken)
  372. }
  373. comparison = 1;
  374. }
  375. token => {
  376. if comparison == 0 {
  377. lhs.push(token);
  378. } else {
  379. rhs.push(token);
  380. }
  381. }
  382. }
  383. }
  384. if comparison == 1 {
  385. out = vec![Token::LessThanCompare((Box::new(lhs), Box::new(rhs)))];
  386. } else {
  387. assert!(rhs.is_empty());
  388. out = lhs;
  389. }
  390. // */
  391. let tokens = std::mem::take(&mut out);
  392. assert!(stack.is_empty());
  393. let mut is_op = false;
  394. for token in tokens {
  395. match token {
  396. Token::Mul | Token::Div => {
  397. if is_op {
  398. return Err(Error::UnexpectedToken)
  399. }
  400. is_op = true;
  401. let Some(prev_item) = out.pop() else { return Err(Error::UnexpectedToken) };
  402. stack.push(token);
  403. stack.push(prev_item);
  404. }
  405. _ => {
  406. if is_op {
  407. is_op = false;
  408. let mut expr = std::mem::take(&mut stack);
  409. expr.push(token);
  410. out.push(Token::NestedExpr(Box::new(expr)));
  411. continue
  412. }
  413. out.push(token)
  414. }
  415. }
  416. }
  417. //println!("out = {out:#?}");
  418. //println!("stack = {stack:#?}");
  419. //assert!(!is_op);
  420. //assert!(stack.is_empty());
  421. if is_op || !stack.is_empty() {
  422. return Err(Error::UnexpectedToken)
  423. }
  424. // +-
  425. let tokens = std::mem::take(&mut out);
  426. let mut is_op = false;
  427. for token in tokens {
  428. match token {
  429. Token::Add | Token::Sub => {
  430. if is_op {
  431. return Err(Error::UnexpectedToken)
  432. }
  433. is_op = true;
  434. let Some(prev_item) = out.pop() else { return Err(Error::UnexpectedToken) };
  435. stack.push(token);
  436. stack.push(prev_item);
  437. }
  438. _ => {
  439. if is_op {
  440. is_op = false;
  441. let mut expr = std::mem::take(&mut stack);
  442. expr.push(token);
  443. out.push(Token::NestedExpr(Box::new(expr)));
  444. continue
  445. }
  446. out.push(token)
  447. }
  448. }
  449. }
  450. //assert!(!is_op);
  451. //assert!(stack.is_empty());
  452. if is_op || !stack.is_empty() {
  453. return Err(Error::UnexpectedToken)
  454. }
  455. // Flatten everything
  456. let out = out.into_iter().map(|t| t.flatten()).flatten().collect();
  457. Ok(out)
  458. }
  459. fn convert<I: Iterator<Item = Token>>(iter: &mut I) -> Result<Op> {
  460. let Some(token) = iter.next() else { return Err(Error::UnexpectedToken) };
  461. let op = match token {
  462. Token::ConstFloat32(v) => Op::ConstFloat32(v),
  463. Token::LoadVar(v) => Op::LoadVar(v),
  464. Token::Add => {
  465. let lhs = convert(iter)?;
  466. let rhs = convert(iter)?;
  467. Op::Add((Box::new(lhs), Box::new(rhs)))
  468. }
  469. Token::Sub => {
  470. let lhs = convert(iter)?;
  471. let rhs = convert(iter)?;
  472. Op::Sub((Box::new(lhs), Box::new(rhs)))
  473. }
  474. Token::Mul => {
  475. let lhs = convert(iter)?;
  476. let rhs = convert(iter)?;
  477. Op::Mul((Box::new(lhs), Box::new(rhs)))
  478. }
  479. Token::Div => {
  480. let lhs = convert(iter)?;
  481. let rhs = convert(iter)?;
  482. Op::Div((Box::new(lhs), Box::new(rhs)))
  483. }
  484. Token::IfElse((cond, if_val, else_val)) => {
  485. let cond = convert(&mut cond.into_iter())?;
  486. let if_val = convert(&mut if_val.into_iter())?;
  487. let else_val = convert(&mut else_val.into_iter())?;
  488. Op::IfElse((Box::new(cond), vec![if_val], vec![else_val]))
  489. }
  490. Token::LessThanCompare((lhs, rhs)) => {
  491. let lhs = convert(&mut lhs.into_iter())?;
  492. let rhs = convert(&mut rhs.into_iter())?;
  493. Op::LessThan((Box::new(lhs), Box::new(rhs)))
  494. }
  495. Token::SetValue((var, expr)) => {
  496. let expr = convert(&mut expr.into_iter())?;
  497. Op::StoreVar((var, Box::new(expr)))
  498. }
  499. _ => return Err(Error::UnexpectedToken),
  500. };
  501. Ok(op)
  502. }
  503. #[cfg(test)]
  504. mod tests {
  505. use super::*;
  506. #[test]
  507. fn single_line() {
  508. let compiler = Compiler::new();
  509. let code = compiler.compile("h/2 - 200").unwrap();
  510. #[rustfmt::skip]
  511. let code2 = vec![Op::Sub((
  512. Box::new(Op::Div((
  513. Box::new(Op::LoadVar("h".to_string())),
  514. Box::new(Op::ConstFloat32(2.)),
  515. ))),
  516. Box::new(Op::ConstFloat32(200.)),
  517. ))];
  518. assert_eq!(code, code2);
  519. let code = compiler.compile("(x + h/2 + (y + 7)/5) - 200").unwrap();
  520. #[rustfmt::skip]
  521. let code2 = vec![Op::Sub((
  522. Box::new(Op::Add((
  523. Box::new(Op::Add((
  524. Box::new(Op::LoadVar("x".to_string())),
  525. Box::new(Op::Div((
  526. Box::new(Op::LoadVar("h".to_string())),
  527. Box::new(Op::ConstFloat32(2.))
  528. ))),
  529. ))),
  530. Box::new(Op::Div((
  531. Box::new(Op::Add((
  532. Box::new(Op::LoadVar("y".to_string())),
  533. Box::new(Op::ConstFloat32(7.))
  534. ))),
  535. Box::new(Op::ConstFloat32(5.))
  536. ))),
  537. ))),
  538. Box::new(Op::ConstFloat32(200.))
  539. ))];
  540. assert_eq!(code, code2);
  541. }
  542. #[test]
  543. fn h_minus_1() {
  544. let mut compiler = Compiler::new();
  545. let code = compiler.compile("h - 1").unwrap();
  546. #[rustfmt::skip]
  547. let code2 = vec![Op::Sub((
  548. Box::new(Op::LoadVar("h".to_string())),
  549. Box::new(Op::ConstFloat32(1.))
  550. ))];
  551. assert_eq!(code, code2);
  552. }
  553. #[test]
  554. fn dosub() {
  555. let mut compiler = Compiler::new();
  556. compiler.add_const_f32("HELLO", 110.);
  557. let code = compiler.compile("HELLO").unwrap();
  558. let code2 = vec![Op::ConstFloat32(110.)];
  559. assert_eq!(code, code2);
  560. }
  561. #[test]
  562. fn if_else() {
  563. let mut compiler = Compiler::new();
  564. let code = compiler
  565. .compile(
  566. "
  567. if h < 4 {
  568. h - 1
  569. } else {
  570. 2 * h + 5
  571. }
  572. ",
  573. )
  574. .unwrap();
  575. let code2 = vec![Op::IfElse((
  576. Box::new(Op::LessThan((
  577. Box::new(Op::LoadVar("h".to_string())),
  578. Box::new(Op::ConstFloat32(4.)),
  579. ))),
  580. vec![Op::Sub((Box::new(Op::LoadVar("h".to_string())), Box::new(Op::ConstFloat32(1.))))],
  581. vec![Op::Add((
  582. Box::new(Op::Mul((
  583. Box::new(Op::ConstFloat32(2.)),
  584. Box::new(Op::LoadVar("h".to_string())),
  585. ))),
  586. Box::new(Op::ConstFloat32(5.)),
  587. ))],
  588. ))];
  589. assert_eq!(code, code2);
  590. }
  591. #[test]
  592. fn set_val() {
  593. let mut compiler = Compiler::new();
  594. let code = compiler
  595. .compile(
  596. "
  597. r = 10 / 4
  598. ",
  599. )
  600. .unwrap();
  601. let code2 = vec![Op::StoreVar((
  602. "r".to_string(),
  603. Box::new(Op::Div((Box::new(Op::ConstFloat32(10.)), Box::new(Op::ConstFloat32(4.))))),
  604. ))];
  605. assert_eq!(code, code2);
  606. }
  607. #[test]
  608. fn multiline() {
  609. let mut compiler = Compiler::new();
  610. let code = compiler
  611. .compile(
  612. "
  613. # This is a comment
  614. r = 10 / 4;
  615. s = if h < 4 {
  616. h - 1
  617. } else {
  618. 2 * h + 5
  619. };
  620. r + 1
  621. ",
  622. )
  623. .unwrap();
  624. let code2 = vec![
  625. Op::StoreVar((
  626. "r".to_string(),
  627. Box::new(Op::Div((
  628. Box::new(Op::ConstFloat32(10.)),
  629. Box::new(Op::ConstFloat32(4.)),
  630. ))),
  631. )),
  632. Op::StoreVar((
  633. "s".to_string(),
  634. Box::new(Op::IfElse((
  635. Box::new(Op::LessThan((
  636. Box::new(Op::LoadVar("h".to_string())),
  637. Box::new(Op::ConstFloat32(4.)),
  638. ))),
  639. vec![Op::Sub((
  640. Box::new(Op::LoadVar("h".to_string())),
  641. Box::new(Op::ConstFloat32(1.)),
  642. ))],
  643. vec![Op::Add((
  644. Box::new(Op::Mul((
  645. Box::new(Op::ConstFloat32(2.)),
  646. Box::new(Op::LoadVar("h".to_string())),
  647. ))),
  648. Box::new(Op::ConstFloat32(5.)),
  649. ))],
  650. ))),
  651. )),
  652. Op::Add((Box::new(Op::LoadVar("r".to_string())), Box::new(Op::ConstFloat32(1.)))),
  653. ];
  654. assert_eq!(code, code2);
  655. }
  656. }