parser.rs 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053
  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 std::{
  19. borrow::Borrow, collections::HashMap, hash::Hash, io::Result, iter::Peekable, str::Chars,
  20. };
  21. use super::{
  22. ast::{Arg, Constant, Literal, Statement, StatementType, Variable, Witness},
  23. constants::{ALLOWED_FIELDS, MAX_K, MAX_NS_LEN},
  24. error::ErrorEmitter,
  25. lexer::{Token, TokenType},
  26. LitType, Opcode, VarType,
  27. };
  28. /// zkas language builtin keywords.
  29. /// These can not be used anywhere except where they are expected.
  30. const KEYWORDS: [&str; 5] = ["k", "field", "constant", "witness", "circuit"];
  31. /// Forbidden namespaces
  32. const NOPE_NS: [&str; 4] = [".constant", ".literal", ".witness", ".circuit"];
  33. /// Valid constant types and their allowed names.
  34. const CONSTANT_TYPES: &[(&str, VarType, &[&str])] = &[
  35. ("EcFixedPoint", VarType::EcFixedPoint, &["VALUE_COMMIT_RANDOM"]),
  36. ("EcFixedPointShort", VarType::EcFixedPointShort, &["VALUE_COMMIT_VALUE"]),
  37. ("EcFixedPointBase", VarType::EcFixedPointBase, &["VALUE_COMMIT_RANDOM_BASE", "NULLIFIER_K"]),
  38. ];
  39. #[derive(Clone)]
  40. struct IndexMap<K, V> {
  41. pub order: Vec<K>,
  42. pub map: HashMap<K, V>,
  43. }
  44. impl<K, V> IndexMap<K, V> {
  45. fn new() -> Self {
  46. Self { order: vec![], map: HashMap::new() }
  47. }
  48. }
  49. impl<K, V> IndexMap<K, V>
  50. where
  51. K: Eq + Hash + Send + Sync + Clone + 'static,
  52. V: Send + Sync + Clone + 'static,
  53. {
  54. fn contains_key<Q: Hash + Eq + ?Sized>(&self, k: &Q) -> bool
  55. where
  56. K: Borrow<Q>,
  57. {
  58. self.map.contains_key(k)
  59. }
  60. fn get<Q: Hash + Eq + ?Sized>(&self, k: &Q) -> Option<&V>
  61. where
  62. K: Borrow<Q>,
  63. {
  64. self.map.get(k)
  65. }
  66. fn insert(&mut self, k: K, v: V) -> Option<V> {
  67. self.order.push(k.clone());
  68. self.map.insert(k, v)
  69. }
  70. fn scam_iter(&self) -> Vec<(K, V)> {
  71. self.order.iter().map(|k| (k.clone(), self.get(k).unwrap().clone())).collect()
  72. }
  73. }
  74. // Valid witness types
  75. impl TryFrom<&Token> for VarType {
  76. type Error = String;
  77. fn try_from(token: &Token) -> std::result::Result<Self, String> {
  78. match token.token.as_str() {
  79. "EcPoint" => Ok(Self::EcPoint),
  80. "EcNiPoint" => Ok(Self::EcNiPoint),
  81. "Base" => Ok(Self::Base),
  82. "Scalar" => Ok(Self::Scalar),
  83. "MerklePath" => Ok(Self::MerklePath),
  84. "SparseMerklePath" => Ok(Self::SparseMerklePath),
  85. "Uint32" => Ok(Self::Uint32),
  86. "Uint64" => Ok(Self::Uint64),
  87. x => Err(format!("{x} is an unsupported witness type")),
  88. }
  89. }
  90. }
  91. pub struct Parser {
  92. tokens: Vec<Token>,
  93. error: ErrorEmitter,
  94. }
  95. type Parsed = (String, u32, Vec<Constant>, Vec<Witness>, Vec<Statement>);
  96. /// Intermediate structure to hold parsed section tokens.
  97. /// The tokens gathered from each of the sections are stored here
  98. /// before being converted into AST nodes.
  99. struct SectionTokens {
  100. constant: Vec<Token>,
  101. witness: Vec<Token>,
  102. circuit: Vec<Token>,
  103. }
  104. impl SectionTokens {
  105. fn new() -> Self {
  106. Self { constant: vec![], witness: vec![], circuit: vec![] }
  107. }
  108. }
  109. impl Parser {
  110. pub fn new(filename: &str, source: Chars, tokens: Vec<Token>) -> Self {
  111. // For nice error reporting, we'll load everything into a string
  112. // vector so we have references to lines.
  113. let lines: Vec<String> = source.as_str().lines().map(|x| x.to_string()).collect();
  114. let error = ErrorEmitter::new("Parser", filename, lines);
  115. Self { tokens, error }
  116. }
  117. pub fn parse(&self) -> Result<Parsed> {
  118. if self.tokens.is_empty() {
  119. return Err(self.error.abort("Source file does not contain any valid tokens.", 0, 0))
  120. }
  121. if self.tokens[0].token_type != TokenType::Symbol {
  122. return Err(self.error.abort(
  123. "Source file does not start with a section. Expected `constant/witness/circuit`.",
  124. 0,
  125. 0,
  126. ))
  127. }
  128. let mut iter = self.tokens.iter();
  129. // Parse header (k and field declarations)
  130. let declared_k = self.parse_header(&mut iter)?;
  131. // Parse all sections and collect their tokens
  132. let (namespace, section_tokens) = self.parse_sections(&mut iter)?;
  133. // Build AST from section tokens
  134. let constants = self.build_constants(&section_tokens.constant)?;
  135. let witnesses = self.build_witnesses(&section_tokens.witness)?;
  136. let statements = self.parse_ast_circuit(&section_tokens.circuit)?;
  137. if statements.is_empty() {
  138. return Err(self.error.abort("Circuit section is empty.", 0, 0))
  139. }
  140. Ok((namespace, declared_k, constants, witnesses, statements))
  141. }
  142. /// Parse the file header: k=N; field="...";
  143. ///
  144. /// The first thing that has to be declared in the source code is the
  145. /// constant "k" which defines 2^k rows that the circuit needs to
  146. /// successfully execute.
  147. ///
  148. /// Then we declare the field we're working in.
  149. fn parse_header<'a>(&self, iter: &mut impl Iterator<Item = &'a Token>) -> Result<u32> {
  150. let Some((k, equal, number, semicolon)) = Self::next_tuple4(iter) else {
  151. return Err(self.error.abort("Source file does not start with k=n;", 0, 0))
  152. };
  153. self.expect_token_type(k, TokenType::Symbol)?;
  154. self.expect_token_type(equal, TokenType::Assign)?;
  155. self.expect_token_type(number, TokenType::Number)?;
  156. self.expect_token_type(semicolon, TokenType::Semicolon)?;
  157. if k.token != "k" {
  158. return Err(self.error.abort("Source file does not start with k=n;", k.line, k.column))
  159. }
  160. // Ensure that the value for k can be parsed correctly into the token type.
  161. let declared_k: u32 = number.token.parse().map_err(|e| {
  162. self.error.abort(
  163. &format!("k param is invalid, max allowed is {MAX_K}. Error: {e}"),
  164. number.line,
  165. number.column,
  166. )
  167. })?;
  168. if declared_k > MAX_K {
  169. return Err(self.error.abort(
  170. &format!("k param is too high, max allowed is {MAX_K}"),
  171. number.line,
  172. number.column,
  173. ))
  174. }
  175. // Parse field declaration
  176. let Some((field, equal, field_name, semicolon)) = Self::next_tuple4(iter) else {
  177. return Err(self.error.abort("Source file does not declare field after k", 0, 0))
  178. };
  179. self.expect_token_type(field, TokenType::Symbol)?;
  180. self.expect_token_type(equal, TokenType::Assign)?;
  181. self.expect_token_type(field_name, TokenType::String)?;
  182. self.expect_token_type(semicolon, TokenType::Semicolon)?;
  183. if field.token != "field" {
  184. return Err(self.error.abort(
  185. "Source file does not declare field after k",
  186. field.line,
  187. field.column,
  188. ))
  189. }
  190. if !ALLOWED_FIELDS.contains(&field_name.token.as_str()) {
  191. return Err(self.error.abort(
  192. &format!(
  193. "Declared field \"{}\" is not supported. Use any of: {ALLOWED_FIELDS:?}",
  194. field_name.token
  195. ),
  196. field_name.line,
  197. field_name.column,
  198. ))
  199. }
  200. Ok(declared_k)
  201. }
  202. /// Parse all sections (constant, witness, circuit) and return their tokens.
  203. ///
  204. /// Sections "constant", "witness", and "circuit" are the sections we must
  205. /// be declaring in our source code. When we find one, we'll take all the
  206. /// tokens found in the section and place them in their respective vec.
  207. ///
  208. /// NOTE: Currently this logic depends on the fact that the sections are
  209. /// closed off with braces. This should be revisited later when we decide
  210. /// to add other lang functionality that also depends on using braces.
  211. fn parse_sections<'a>(
  212. &self,
  213. iter: &mut impl Iterator<Item = &'a Token>,
  214. ) -> Result<(String, SectionTokens)> {
  215. let mut sections = SectionTokens::new();
  216. let mut namespace: Option<String> = None;
  217. let mut declared = (false, false, false); // constant, witness, circuit
  218. while let Some(t) = iter.next() {
  219. let section_tokens = match t.token.as_str() {
  220. "constant" => {
  221. if declared.0 {
  222. return Err(self.error.abort(
  223. "Duplicate `constant` section found.",
  224. t.line,
  225. t.column,
  226. ))
  227. }
  228. declared.0 = true;
  229. &mut sections.constant
  230. }
  231. "witness" => {
  232. if declared.1 {
  233. return Err(self.error.abort(
  234. "Duplicate `witness` section found.",
  235. t.line,
  236. t.column,
  237. ))
  238. }
  239. declared.1 = true;
  240. &mut sections.witness
  241. }
  242. "circuit" => {
  243. if declared.2 {
  244. return Err(self.error.abort(
  245. "Duplicate `circuit` section found.",
  246. t.line,
  247. t.column,
  248. ))
  249. }
  250. declared.2 = true;
  251. &mut sections.circuit
  252. }
  253. x => {
  254. return Err(self.error.abort(
  255. &format!("Section `{x}` is not a valid section"),
  256. t.line,
  257. t.column,
  258. ))
  259. }
  260. };
  261. // Absorb all tokens until closing brace
  262. self.absorb_section_tokens(iter, section_tokens)?;
  263. // Validate and extract namespace
  264. namespace =
  265. Some(self.validate_section_namespace(&t.token, section_tokens, namespace)?);
  266. }
  267. let ns =
  268. namespace.ok_or_else(|| self.error.abort("Missing namespace in .zk source.", 0, 0))?;
  269. if !declared.0 {
  270. return Err(self.error.abort("Missing `constant` section in .zk source.", 0, 0))
  271. }
  272. if !declared.1 {
  273. return Err(self.error.abort("Missing `witness` section in .zk source.", 0, 0))
  274. }
  275. if !declared.2 {
  276. return Err(self.error.abort("Missing `circuit` section in .zk source.", 0, 0))
  277. }
  278. Ok((ns, sections))
  279. }
  280. /// Absorb tokens from iterator until a closing brace is found.
  281. /// Validates that no keywords are used in improper places.
  282. fn absorb_section_tokens<'a>(
  283. &self,
  284. iter: &mut impl Iterator<Item = &'a Token>,
  285. dest: &mut Vec<Token>,
  286. ) -> Result<()> {
  287. for inner in iter {
  288. if KEYWORDS.contains(&inner.token.as_str()) && inner.token_type == TokenType::Symbol {
  289. return Err(self.error.abort(
  290. &format!("Keyword '{}' used in improper place.", inner.token),
  291. inner.line,
  292. inner.column,
  293. ))
  294. }
  295. dest.push(inner.clone());
  296. if inner.token_type == TokenType::RightBrace {
  297. break
  298. }
  299. }
  300. Ok(())
  301. }
  302. /// Validate namespace consistency across sections.
  303. /// All sections must use the same namespace, and it must not be a reserved name.
  304. fn validate_section_namespace(
  305. &self,
  306. section_name: &str,
  307. tokens: &[Token],
  308. existing_ns: Option<String>,
  309. ) -> Result<String> {
  310. if tokens.is_empty() {
  311. return Err(self.error.abort(&format!("Section `{section_name}` has no tokens"), 0, 0))
  312. }
  313. let ns_token = &tokens[0];
  314. if let Some(ns) = existing_ns {
  315. if ns != ns_token.token {
  316. return Err(self.error.abort(
  317. &format!("Found '{}' namespace, expected '{ns}'.", ns_token.token),
  318. ns_token.line,
  319. ns_token.column,
  320. ))
  321. }
  322. return Ok(ns)
  323. }
  324. if NOPE_NS.contains(&ns_token.token.as_str()) {
  325. return Err(self.error.abort(
  326. &format!("'{}' cannot be a namespace.", ns_token.token),
  327. ns_token.line,
  328. ns_token.column,
  329. ))
  330. }
  331. if ns_token.token.len() > MAX_NS_LEN {
  332. return Err(self.error.abort(
  333. &format!("Namespace too long, max {MAX_NS_LEN} bytes"),
  334. ns_token.line,
  335. ns_token.column,
  336. ))
  337. }
  338. Ok(ns_token.token.clone())
  339. }
  340. /// Build constants from section tokens.
  341. /// Validates constant types against the CONSTANT_TYPES table.
  342. fn build_constants(&self, tokens: &[Token]) -> Result<Vec<Constant>> {
  343. self.check_section_structure("constant", tokens)?;
  344. let parsed = self.parse_typed_section("constant", tokens)?;
  345. let mut ret = vec![];
  346. // name = constant name
  347. for (name, (name_token, type_token)) in parsed.scam_iter() {
  348. self.validate_section_entry("Constant", &name, &name_token, &type_token)?;
  349. // Look up the constant type in our table
  350. let type_name = type_token.token.as_str();
  351. let constant_def = CONSTANT_TYPES.iter().find(|(t, _, _)| *t == type_name);
  352. match constant_def {
  353. Some((_, var_type, valid_names)) => {
  354. if !valid_names.contains(&name_token.token.as_str()) {
  355. return Err(self.error.abort(
  356. &format!(
  357. "`{}` is not a valid {type_name} constant. Supported: {valid_names:?}",
  358. name_token.token
  359. ),
  360. name_token.line,
  361. name_token.column,
  362. ))
  363. }
  364. ret.push(Constant {
  365. name: name.to_string(),
  366. typ: *var_type,
  367. line: type_token.line,
  368. column: type_token.column,
  369. });
  370. }
  371. None => {
  372. return Err(self.error.abort(
  373. &format!("`{type_name}` is an unsupported constant type."),
  374. type_token.line,
  375. type_token.column,
  376. ))
  377. }
  378. }
  379. }
  380. Ok(ret)
  381. }
  382. /// Build witnesses from section tokens.
  383. fn build_witnesses(&self, tokens: &[Token]) -> Result<Vec<Witness>> {
  384. self.check_section_structure("witness", tokens)?;
  385. let parsed = self.parse_typed_section("witness", tokens)?;
  386. let mut ret = vec![];
  387. // name = witness name
  388. for (name, (name_token, type_token)) in parsed.scam_iter() {
  389. self.validate_section_entry("Witness", &name, &name_token, &type_token)?;
  390. match VarType::try_from(&type_token) {
  391. Ok(typ) => {
  392. ret.push(Witness {
  393. name: name.to_string(),
  394. typ,
  395. line: name_token.line,
  396. column: name_token.column,
  397. });
  398. }
  399. Err(e) => return Err(self.error.abort(&e, type_token.line, type_token.column)),
  400. }
  401. }
  402. Ok(ret)
  403. }
  404. /// Parse a typed section (constant or witness) into an IndexMap.
  405. /// Both sections have the same structure: pairs of `<Type> <n>` separated by commas.
  406. fn parse_typed_section(
  407. &self,
  408. section_name: &str,
  409. tokens: &[Token],
  410. ) -> Result<IndexMap<String, (Token, Token)>> {
  411. let mut result = IndexMap::new();
  412. // Skip namespace and braces: tokens[0] is namespace, tokens[1] is {, last is }
  413. // This is everything between the braces: { ... }
  414. let inner_tokens = &tokens[2..tokens.len() - 1];
  415. let mut iter = inner_tokens.iter();
  416. while let Some((typ, name, comma)) = Self::next_tuple3(&mut iter) {
  417. if comma.token_type != TokenType::Comma {
  418. return Err(self.error.abort("Separator is not a comma.", comma.line, comma.column))
  419. }
  420. // No variable shadowing
  421. if result.contains_key(name.token.as_str()) {
  422. return Err(self.error.abort(
  423. &format!(
  424. "Section `{section_name}` already contains the token `{}`.",
  425. &name.token
  426. ),
  427. name.line,
  428. name.column,
  429. ))
  430. }
  431. result.insert(name.token.clone(), (name.clone(), typ.clone()));
  432. }
  433. if iter.next().is_some() {
  434. return Err(self.error.abort(
  435. &format!("Internal error, leftovers in '{section_name}' iterator"),
  436. 0,
  437. 0,
  438. ))
  439. }
  440. Ok(result)
  441. }
  442. /// Common validation for constant/witness entries.
  443. /// Ensures name and type tokens are symbols and match expected values.
  444. fn validate_section_entry(
  445. &self,
  446. section_type: &str,
  447. name: &str,
  448. name_token: &Token,
  449. type_token: &Token,
  450. ) -> Result<()> {
  451. if name_token.token != name {
  452. return Err(self.error.abort(
  453. &format!(
  454. "{section_type} name `{}` doesn't match token `{name}`.",
  455. name_token.token
  456. ),
  457. name_token.line,
  458. name_token.column,
  459. ))
  460. }
  461. if name_token.token_type != TokenType::Symbol {
  462. return Err(self.error.abort(
  463. &format!("{section_type} name `{}` is not a symbol.", name_token.token),
  464. name_token.line,
  465. name_token.column,
  466. ))
  467. }
  468. if type_token.token_type != TokenType::Symbol {
  469. return Err(self.error.abort(
  470. &format!("{section_type} type `{}` is not a symbol.", type_token.token),
  471. type_token.line,
  472. type_token.column,
  473. ))
  474. }
  475. Ok(())
  476. }
  477. /// Routine checks on section structure.
  478. /// Validates that sections have proper opening/closing braces and correct element counts.
  479. fn check_section_structure(&self, section: &str, tokens: &[Token]) -> Result<()> {
  480. // Offsets 0 and 1 are accessed directly below, so we need a length of at
  481. // least 2 in order to avoid an index-out-of-bounds panic.
  482. if tokens.len() < 2 {
  483. return Err(self.error.abort("Insufficient number of tokens in section.", 0, 0))
  484. }
  485. if tokens[0].token_type != TokenType::String {
  486. return Err(self.error.abort(
  487. "Section declaration must start with a naming string.",
  488. tokens[0].line,
  489. tokens[0].column,
  490. ))
  491. }
  492. if tokens[1].token_type != TokenType::LeftBrace {
  493. return Err(self.error.abort(
  494. "Section must be opened with a left brace '{'",
  495. tokens[0].line,
  496. tokens[0].column,
  497. ))
  498. }
  499. if tokens.last().unwrap().token_type != TokenType::RightBrace {
  500. return Err(self.error.abort(
  501. "Section must be closed with a right brace '}'",
  502. tokens[0].line,
  503. tokens[0].column,
  504. ))
  505. }
  506. match section {
  507. "constant" | "witness" => {
  508. if tokens.len() == 3 {
  509. self.error.warn(&format!("{section} section is empty."), 0, 0);
  510. }
  511. if !tokens[2..tokens.len() - 1].len().is_multiple_of(3) {
  512. return Err(self.error.abort(
  513. &format!("Invalid number of elements in '{section}' section. Must be pairs of '<Type> <n>' separated with a comma ','."),
  514. tokens[0].line,
  515. tokens[0].column
  516. ))
  517. }
  518. }
  519. "circuit" => {
  520. if tokens.len() == 3 {
  521. return Err(self.error.abort("circuit section is empty.", 0, 0))
  522. }
  523. if tokens[tokens.len() - 2].token_type != TokenType::Semicolon {
  524. return Err(self.error.abort(
  525. "Circuit section does not end with a semicolon. Would never finish parsing.",
  526. tokens[tokens.len()-2].line,
  527. tokens[tokens.len()-2].column,
  528. ))
  529. }
  530. }
  531. _ => unreachable!(),
  532. };
  533. Ok(())
  534. }
  535. /// Parse the circuit section into statements.
  536. ///
  537. /// The statement layouts/syntax in the language are as follows:
  538. ///
  539. /// ```text
  540. /// C = poseidon_hash(pub_x, pub_y, value, token, serial);
  541. /// | | | | |
  542. /// V V V V V
  543. /// variable opcode arg arg
  544. /// assign
  545. ///
  546. /// constrain_instance(C);
  547. /// | |
  548. /// V V
  549. /// opcode arg
  550. ///
  551. /// inner opcode arg
  552. /// |
  553. /// constrain_instance(ec_get_x(foo));
  554. /// | |
  555. /// V V
  556. /// opcode arg as opcode
  557. /// ```
  558. ///
  559. /// In the latter, we want to support nested function calls, e.g.:
  560. ///
  561. /// ```text
  562. /// constrain_instance(ec_get_x(token_commit));
  563. /// ```
  564. ///
  565. /// The inner call's result would still get pushed on the heap,
  566. /// but it will not be accessible in any other scope.
  567. ///
  568. /// In certain opcodes, we also support literal types, and the
  569. /// opcodes can return a variable type after running the operation.
  570. /// e.g.
  571. /// ```text
  572. /// one = witness_base(1);
  573. /// zero = witness_base(0);
  574. /// ```
  575. ///
  576. /// The literal type is used only in the function call's scope, but
  577. /// the result is then accessible on the heap to be used by further
  578. /// computation.
  579. ///
  580. /// Regarding multiple return values from opcodes, this is perhaps
  581. /// not necessary for the current language scope, as this is a low
  582. /// level representation. Note that it could be relatively easy to
  583. /// modify the parsing logic to support that here. For now we'll
  584. /// defer it, and if at some point we decide that the language is
  585. /// too expressive and noisy, we'll consider having multiple return
  586. /// types. It also very much depends on the type of functions/opcodes
  587. /// that we want to support.
  588. fn parse_ast_circuit(&self, tokens: &[Token]) -> Result<Vec<Statement>> {
  589. self.check_section_structure("circuit", tokens)?;
  590. // Split circuit tokens into statements (delimited by semicolons).
  591. // Here, our statements tokens have been parsed and delimited by
  592. // semicolons (;) in the source file. This iterator contains each
  593. // of those statements as an array of tokens we then consume and
  594. // build the AST further.
  595. let mut circuit_stmts: Vec<Vec<Token>> = vec![];
  596. let mut current_stmt: Vec<Token> = vec![];
  597. for token in tokens[2..tokens.len() - 1].iter() {
  598. if token.token_type == TokenType::Semicolon {
  599. // Push completed statement to the heap
  600. circuit_stmts.push(current_stmt);
  601. current_stmt = vec![];
  602. continue
  603. }
  604. current_stmt.push(token.clone());
  605. }
  606. // Vec of statements to return from this entire parsing operation.
  607. let mut ret = vec![];
  608. for statement in circuit_stmts {
  609. if statement.is_empty() {
  610. continue
  611. }
  612. self.validate_statement_brackets(&statement)?;
  613. // Peekable iterator so we can see tokens in advance
  614. // without consuming the iterator.
  615. let mut iter = statement.iter().peekable();
  616. let stmt = self.parse_statement(&mut iter)?;
  617. ret.push(stmt);
  618. }
  619. Ok(ret)
  620. }
  621. /// Validate matching brackets in a statement.
  622. /// Ensures parentheses and brackets are balanced and properly nested.
  623. fn validate_statement_brackets(&self, statement: &[Token]) -> Result<()> {
  624. let (mut left_paren, mut right_paren, mut left_bracket, mut right_bracket) = (0, 0, 0, 0);
  625. for token in statement {
  626. match token.token.as_str() {
  627. "(" => left_paren += 1,
  628. ")" => right_paren += 1,
  629. "[" => left_bracket += 1,
  630. "]" => right_bracket += 1,
  631. _ => {}
  632. }
  633. }
  634. if (left_paren == 0 && right_paren == 0) && (left_bracket == 0 && right_bracket == 0) {
  635. return Err(self.error.abort(
  636. "Statement must include a function call or array initialization. No parentheses or square brackets present.",
  637. statement[0].line,
  638. statement[0].column,
  639. ))
  640. }
  641. if (left_bracket != right_bracket) || (left_paren != right_paren) {
  642. return Err(self.error.abort(
  643. "Parentheses or brackets are not matched.",
  644. statement[0].line,
  645. statement[0].column,
  646. ))
  647. }
  648. // Is there a valid use-case for defining nested arrays? For now,
  649. // if square brackets are present, raise an error unless there is
  650. // exactly one pair.
  651. if left_bracket > 1 {
  652. return Err(self.error.abort(
  653. "Only one pair of brackets allowed for array declaration",
  654. statement[0].line,
  655. statement[0].column,
  656. ))
  657. }
  658. Ok(())
  659. }
  660. /// Parse a single statement from tokens.
  661. /// Determines if this is an assignment (var = ...) or a direct call (opcode(...)).
  662. fn parse_statement(
  663. &self,
  664. iter: &mut Peekable<std::slice::Iter<'_, Token>>,
  665. ) -> Result<Statement> {
  666. // Dummy statement that we'll hopefully fill now.
  667. let mut stmt = Statement::default();
  668. let Some(token) = iter.next() else {
  669. return Err(self.error.abort("Empty statement", 0, 0))
  670. };
  671. // TODO: MAKE SURE IT'S A SYMBOL
  672. // Check if this is an assignment (var = ...) or a direct call (opcode(...))
  673. // This logic must be changed if we want to support multiple return values.
  674. if let Some(next_token) = iter.peek() {
  675. if next_token.token_type == TokenType::Assign {
  676. // Assignment statement
  677. stmt.line = token.line;
  678. stmt.typ = StatementType::Assign;
  679. stmt.lhs = Some(Variable {
  680. name: token.token.clone(),
  681. typ: VarType::Dummy,
  682. line: token.line,
  683. column: token.column,
  684. });
  685. // Skip over the `=` token.
  686. iter.next();
  687. // Get the opcode token
  688. let Some(opcode_token) = iter.next() else {
  689. return Err(self.error.abort(
  690. "Expected opcode after assignment",
  691. token.line,
  692. token.column,
  693. ))
  694. };
  695. self.parse_opcode_call(opcode_token, iter, &mut stmt)?;
  696. } else if next_token.token_type == TokenType::LeftParen {
  697. // Direct call statement
  698. stmt.line = token.line;
  699. stmt.typ = StatementType::Call;
  700. stmt.lhs = None;
  701. self.parse_opcode_call(token, iter, &mut stmt)?;
  702. } else if next_token.token_type == TokenType::LeftBracket {
  703. // Array declaration.
  704. // TODO: Support function calls in array declarations.
  705. // Currently only literals can be used to construct an array.
  706. return Err(self.error.abort(
  707. "Arrays are not implemented yet.",
  708. token.line,
  709. token.column,
  710. ))
  711. } else {
  712. return Err(self.error.abort(
  713. &format!("Illegal token `{}`.", next_token.token),
  714. next_token.line,
  715. next_token.column,
  716. ))
  717. }
  718. }
  719. // At this stage of parsing, we should have assigned `stmt` a
  720. // StatementType that is not a Noop. If we have failed to do so, we
  721. // cannot proceed because Noops must never be passed to the compiler.
  722. // This can occur when multiple independent statements are passed on
  723. // one line, or if a statement is not terminated by a semicolon.
  724. if stmt.typ == StatementType::Noop {
  725. return Err(self.error.abort(
  726. "Statement is a NOOP; not allowed. (Did you miss a semicolon?)",
  727. token.line,
  728. token.column,
  729. ))
  730. }
  731. Ok(stmt)
  732. }
  733. /// Parse an opcode call and fill in the statement.
  734. /// The assumption here is that the current token is a function call,
  735. /// so we check if it's legit and start digging.
  736. fn parse_opcode_call(
  737. &self,
  738. token: &Token,
  739. iter: &mut Peekable<std::slice::Iter<'_, Token>>,
  740. stmt: &mut Statement,
  741. ) -> Result<()> {
  742. let func_name = token.token.as_str();
  743. // Ensure the current function is a symbol
  744. if token.token_type != TokenType::Symbol {
  745. return Err(self.error.abort("This token is not a symbol.", token.line, token.column))
  746. }
  747. if let Some(op) = Opcode::from_name(func_name) {
  748. let rhs = self.parse_function_call(token, iter)?;
  749. stmt.opcode = op;
  750. stmt.rhs = rhs;
  751. Ok(())
  752. } else {
  753. Err(self.error.abort(
  754. &format!("Unimplemented opcode `{func_name}`."),
  755. token.line,
  756. token.column,
  757. ))
  758. }
  759. }
  760. /// Parse a function call and its arguments.
  761. /// Handles nested function calls recursively, creating intermediate
  762. /// variables for inner call results.
  763. fn parse_function_call(
  764. &self,
  765. token: &Token,
  766. iter: &mut Peekable<std::slice::Iter<'_, Token>>,
  767. ) -> Result<Vec<Arg>> {
  768. if let Some(next_token) = iter.peek() {
  769. if next_token.token_type != TokenType::LeftParen {
  770. return Err(self.error.abort(
  771. "Invalid function call opening. Must start with a '('.",
  772. next_token.line,
  773. next_token.column,
  774. ))
  775. }
  776. // Skip the opening parenthesis
  777. iter.next();
  778. } else {
  779. return Err(self.error.abort("Premature ending of statement.", token.line, token.column))
  780. }
  781. let mut ret = vec![];
  782. // The next element in the iter now hopefully contains an opcode
  783. // argument. If it's another opcode, we'll recurse into this
  784. // function's logic.
  785. // Otherwise, we look for variable and literal types.
  786. while let Some(arg) = iter.next() {
  787. // ============================
  788. // Parse a nested function call
  789. // ============================
  790. if let Some(op_inner) = Opcode::from_name(&arg.token) {
  791. if let Some(paren) = iter.peek() {
  792. if paren.token_type != TokenType::LeftParen {
  793. return Err(self.error.abort(
  794. "Invalid function call opening. Must start with a '('.",
  795. paren.line,
  796. paren.column,
  797. ))
  798. }
  799. // Recurse this function to get the params of the nested one.
  800. let args = self.parse_function_call(arg, iter)?;
  801. // Then we assign a "fake" variable that serves as a heap
  802. // reference.
  803. let var = Variable {
  804. name: format!("_op_inner_{}_{}", arg.line, arg.column),
  805. typ: VarType::Dummy,
  806. line: arg.line,
  807. column: arg.column,
  808. };
  809. let arg = Arg::Func(Statement {
  810. typ: StatementType::Assign,
  811. opcode: op_inner,
  812. lhs: Some(var),
  813. rhs: args,
  814. line: arg.line,
  815. });
  816. ret.push(arg);
  817. continue
  818. }
  819. return Err(self.error.abort(
  820. "Missing tokens in statement, there's a syntax error here.",
  821. arg.line,
  822. arg.column,
  823. ))
  824. }
  825. // ==========================================
  826. // Parse normal argument, not a function call
  827. // ==========================================
  828. if let Some(sep) = iter.next() {
  829. // See if we have a variable or a literal type.
  830. match arg.token_type {
  831. TokenType::Symbol => ret.push(Arg::Var(Variable {
  832. name: arg.token.clone(),
  833. typ: VarType::Dummy,
  834. line: arg.line,
  835. column: arg.column,
  836. })),
  837. TokenType::Number => {
  838. // Check if we can actually convert this into a number.
  839. arg.token.parse::<u64>().map_err(|e| {
  840. self.error.abort(
  841. &format!("Failed to convert literal into u64: {e}"),
  842. arg.line,
  843. arg.column,
  844. )
  845. })?;
  846. ret.push(Arg::Lit(Literal {
  847. name: arg.token.clone(),
  848. typ: LitType::Uint64,
  849. line: arg.line,
  850. column: arg.column,
  851. }))
  852. }
  853. TokenType::RightParen => {
  854. if let Some(comma) = iter.peek() {
  855. if comma.token_type == TokenType::Comma {
  856. iter.next();
  857. }
  858. }
  859. break
  860. }
  861. // Note: Unimplemented symbols throw an error now instead of a panic.
  862. // This assists with fuzz testing as existing features can still be tested
  863. // without causing the fuzzer to choke due to the panic created
  864. // by unimplmented!().
  865. _ => {
  866. return Err(self.error.abort(
  867. "Character is illegal/unimplemented in this context",
  868. arg.line,
  869. arg.column,
  870. ))
  871. }
  872. };
  873. if sep.token_type == TokenType::RightParen {
  874. if let Some(comma) = iter.peek() {
  875. if comma.token_type == TokenType::Comma {
  876. iter.next();
  877. }
  878. }
  879. // Reached end of args
  880. break
  881. }
  882. if sep.token_type != TokenType::Comma {
  883. return Err(self.error.abort(
  884. "Argument separator is not a comma (`,`)",
  885. sep.line,
  886. sep.column,
  887. ))
  888. }
  889. }
  890. }
  891. Ok(ret)
  892. }
  893. /// Check that a token has the expected type.
  894. fn expect_token_type(&self, token: &Token, expected: TokenType) -> Result<()> {
  895. if token.token_type != expected {
  896. return Err(self.error.abort(
  897. &format!("Expected {:?}, got {:?}", expected, token.token_type),
  898. token.line,
  899. token.column,
  900. ))
  901. }
  902. Ok(())
  903. }
  904. /// Get next 3 items from an iterator as a tuple.
  905. fn next_tuple3<I, T>(iter: &mut I) -> Option<(T, T, T)>
  906. where
  907. I: Iterator<Item = T>,
  908. {
  909. let a = iter.next()?;
  910. let b = iter.next()?;
  911. let c = iter.next()?;
  912. Some((a, b, c))
  913. }
  914. /// Get next 4 items from an iterator as a tuple.
  915. fn next_tuple4<I, T>(iter: &mut I) -> Option<(T, T, T, T)>
  916. where
  917. I: Iterator<Item = T>,
  918. {
  919. let a = iter.next()?;
  920. let b = iter.next()?;
  921. let c = iter.next()?;
  922. let d = iter.next()?;
  923. Some((a, b, c, d))
  924. }
  925. }