analyzer.rs 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537
  1. /* This file is part of DarkFi (https://dark.fi)
  2. *
  3. * Copyright (C) 2020-2023 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. io::{stdin, stdout, Read, Result, Write},
  20. str::Chars,
  21. };
  22. use super::{
  23. ast::{Arg, Constant, Literal, Statement, StatementType, Var, Variable, Witness},
  24. error::ErrorEmitter,
  25. Opcode, VarType,
  26. };
  27. pub struct Analyzer {
  28. pub constants: Vec<Constant>,
  29. pub witnesses: Vec<Witness>,
  30. pub statements: Vec<Statement>,
  31. pub literals: Vec<Literal>,
  32. pub heap: Vec<Variable>,
  33. error: ErrorEmitter,
  34. }
  35. impl Analyzer {
  36. pub fn new(
  37. filename: &str,
  38. source: Chars,
  39. constants: Vec<Constant>,
  40. witnesses: Vec<Witness>,
  41. statements: Vec<Statement>,
  42. ) -> Self {
  43. // For nice error reporting, we'll load everything into a string
  44. // vector so we have references to lines.
  45. let lines: Vec<String> = source.as_str().lines().map(|x| x.to_string()).collect();
  46. let error = ErrorEmitter::new("Semantic", filename, lines);
  47. Self { constants, witnesses, statements, literals: vec![], heap: vec![], error }
  48. }
  49. pub fn analyze_types(&mut self) -> Result<()> {
  50. // To work around the pedantic safety, we'll make new vectors and then
  51. // replace the `statements` and `heap` vectors from the `Analyzer`
  52. // object when we are done.
  53. let mut statements = vec![];
  54. let mut heap = vec![];
  55. for statement in &self.statements {
  56. //println!("{:?}", statement);
  57. let mut stmt = statement.clone();
  58. let (return_types, arg_types) = statement.opcode.arg_types();
  59. let mut rhs = vec![];
  60. // This handling is kinda limiting, but it'll do for now.
  61. if !(arg_types[0] == VarType::BaseArray || arg_types[0] == VarType::ScalarArray) {
  62. // Check that number of args is correct
  63. if statement.rhs.len() != arg_types.len() {
  64. return Err(self.error.abort(
  65. &format!(
  66. "Incorrect number of arguments for statement. Expected {}, got {}.",
  67. arg_types.len(),
  68. statement.rhs.len()
  69. ),
  70. statement.line,
  71. 1,
  72. ))
  73. }
  74. } else {
  75. // In case of arrays, check there's at least one element.
  76. if statement.rhs.is_empty() {
  77. return Err(self.error.abort(
  78. "Expected at least one element for statement using arrays.",
  79. statement.line,
  80. 1,
  81. ))
  82. }
  83. }
  84. // Edge-cases for some opcodes
  85. #[allow(clippy::single_match)]
  86. match &statement.opcode {
  87. Opcode::RangeCheck => {
  88. if let Arg::Lit(arg0) = &statement.rhs[0] {
  89. if &arg0.name != "64" && &arg0.name != "253" {
  90. return Err(self.error.abort(
  91. "Supported range checks are only 64 and 253 bits.",
  92. arg0.line,
  93. arg0.column,
  94. ))
  95. }
  96. } else {
  97. return Err(self.error.abort(
  98. "Invalid argument for range_check opcode.",
  99. statement.line,
  100. 0,
  101. ))
  102. }
  103. }
  104. _ => {}
  105. }
  106. for (idx, arg) in statement.rhs.iter().enumerate() {
  107. // In case an argument is a function call, we will first
  108. // convert it to another statement that will get executed
  109. // before this one. An important assumption is that this
  110. // opcode has a return value. When executed we will push
  111. // this value onto the heap and use it as a reference to
  112. // the actual statement we're parsing at this moment.
  113. // TODO: This needs a recursive algorithm, as this only
  114. // allows a single nested function.
  115. if let Arg::Func(func) = arg {
  116. let (f_return_types, f_arg_types) = func.opcode.arg_types();
  117. if f_return_types.is_empty() {
  118. return Err(self.error.abort(
  119. &format!(
  120. "Used a function argument which doesn't have a return value: {:?}",
  121. func.opcode
  122. ),
  123. statement.line,
  124. 1,
  125. ))
  126. }
  127. let v = Variable {
  128. name: func.lhs.clone().unwrap().name,
  129. typ: f_return_types[0],
  130. line: func.lhs.clone().unwrap().line,
  131. column: func.lhs.clone().unwrap().column,
  132. };
  133. if arg_types[0] == VarType::BaseArray {
  134. if f_return_types[0] != VarType::Base {
  135. return Err(self.error.abort(
  136. &format!(
  137. "Function passed as argument returns wrong type. Expected `{:?}`, got `{:?}`.",
  138. VarType::Base,
  139. f_return_types[0],
  140. ),
  141. v.line,
  142. v.column,
  143. ))
  144. }
  145. } else if arg_types[0] == VarType::ScalarArray {
  146. if f_return_types[0] != VarType::Scalar {
  147. return Err(self.error.abort(
  148. &format!(
  149. "Function passed as argument returns wrong type. Expected `{:?}`, got `{:?}`.",
  150. VarType::Scalar,
  151. f_return_types[0],
  152. ),
  153. v.line,
  154. v.column,
  155. ));
  156. }
  157. } else if f_return_types[0] != arg_types[idx] {
  158. return Err(self.error.abort(
  159. &format!(
  160. "Function passed as argument returns wrong type. Expected `{:?}`, got `{:?}`.",
  161. arg_types[idx],
  162. f_return_types[0],
  163. ),
  164. v.line,
  165. v.column,
  166. ))
  167. }
  168. // Replace the statement function call with the variable from
  169. // the statement we just created to represent this nest.
  170. stmt.rhs[idx] = Arg::Var(v.clone());
  171. let mut rhs_inner = vec![];
  172. for (inner_idx, i) in func.rhs.iter().enumerate() {
  173. // TODO: Implement cases where `i` is type Arg::Literal
  174. // TODO: Implement cases where `i` is type Arg::Func
  175. if let Arg::Var(v) = i {
  176. if let Some(var_ref) = self.lookup_var(&v.name) {
  177. let (var_type, ln, col) = match var_ref {
  178. Var::Constant(c) => (c.typ, c.line, c.column),
  179. Var::Witness(c) => (c.typ, c.line, c.column),
  180. Var::Variable(c) => (c.typ, c.line, c.column),
  181. };
  182. if var_type != f_arg_types[inner_idx] {
  183. return Err(self.error.abort(
  184. &format!(
  185. "Incorrect argument type. Expected `{:?}`, got `{:?}`.",
  186. f_arg_types[inner_idx], var_type
  187. ),
  188. ln,
  189. col,
  190. ))
  191. }
  192. // Apply the proper type.
  193. let mut v_new = v.clone();
  194. v_new.typ = var_type;
  195. rhs_inner.push(Arg::Var(v_new));
  196. continue
  197. }
  198. return Err(self.error.abort(
  199. &format!("Unknown variable reference `{}`.", v.name),
  200. v.line,
  201. v.column,
  202. ))
  203. } else if let Arg::Lit(l) = i {
  204. return Err(self.error.abort(
  205. &format!("Expected argument `{}` to be of type Variable. Literals are not yet supported in nested function calls.", l.name),
  206. l.line,
  207. l.column,
  208. ))
  209. } else if let Arg::Func(f) = i {
  210. return Err(self.error.abort(
  211. &format!("Expected argument `{}` to be of type Variable. Nested function calls are not yet supported beyond a depth of 1.", Opcode::name(&f.opcode)),
  212. f.line,
  213. 0,
  214. ))
  215. } else {
  216. unreachable!();
  217. }
  218. }
  219. let s = Statement {
  220. typ: func.typ,
  221. opcode: func.opcode,
  222. lhs: Some(v.clone()),
  223. rhs: rhs_inner,
  224. line: func.line,
  225. };
  226. // The lhs of the inner function call becomes rhs of the outer one.
  227. rhs.push(Arg::Var(v.clone()));
  228. // Add this to the list of statements.
  229. statements.push(s);
  230. // We replace self.heap here so we can do proper heap lookups.
  231. heap.push(v.clone());
  232. self.heap = heap.clone();
  233. //println!("{:#?}", heap);
  234. //println!("{:#?}", statements);
  235. continue
  236. } // <-- Arg::Func
  237. // The literals get pushed on their own "heap", and
  238. // then the compiler will reference them by their own
  239. // index when it comes to running the statement that
  240. // requires the literal type.
  241. if let Arg::Lit(v) = arg {
  242. // Match this literal type to a VarType for
  243. // type checking.
  244. let var_type = v.typ.to_vartype();
  245. // TODO: Refactor the Array type checks here and in the Arg::Var
  246. // section so that there is less repetition.
  247. // Validation for Array types
  248. if arg_types[0] == VarType::BaseArray {
  249. if var_type != VarType::Base {
  250. return Err(self.error.abort(
  251. &format!(
  252. "Incorrect argument type. Expected `{:?}`, got `{:?}`.",
  253. VarType::Base,
  254. var_type
  255. ),
  256. v.line,
  257. v.column,
  258. ))
  259. }
  260. } else if arg_types[0] == VarType::ScalarArray && var_type != VarType::Scalar {
  261. return Err(self.error.abort(
  262. &format!(
  263. "Incorrect argument type. Expected `{:?}`, got `{:?}`.",
  264. VarType::Scalar,
  265. var_type
  266. ),
  267. v.line,
  268. v.column,
  269. ))
  270. }
  271. // Validation for non-Array types
  272. if var_type != arg_types[idx] {
  273. return Err(self.error.abort(
  274. &format!(
  275. "Incorrect argument type. Expected `{:?}`, got `{:?}`.",
  276. arg_types[idx], var_type
  277. ),
  278. v.line,
  279. v.column,
  280. ))
  281. }
  282. self.literals.push(v.clone());
  283. rhs.push(Arg::Lit(v.clone()));
  284. continue
  285. }
  286. if let Arg::Var(v) = arg {
  287. // Look up variable and check if type is correct.
  288. if let Some(s_var) = self.lookup_var(&v.name) {
  289. let (var_type, _ln, _col) = match s_var {
  290. Var::Constant(c) => (c.typ, c.line, c.column),
  291. Var::Witness(c) => (c.typ, c.line, c.column),
  292. Var::Variable(c) => (c.typ, c.line, c.column),
  293. };
  294. if arg_types[0] == VarType::BaseArray {
  295. if var_type != VarType::Base {
  296. return Err(self.error.abort(
  297. &format!(
  298. "Incorrect argument type. Expected `{:?}`, got `{:?}`.",
  299. VarType::Base,
  300. var_type
  301. ),
  302. v.line,
  303. v.column,
  304. ))
  305. }
  306. } else if arg_types[0] == VarType::ScalarArray {
  307. if var_type != VarType::Scalar {
  308. return Err(self.error.abort(
  309. &format!(
  310. "Incorrect argument type. Expected `{:?}`, got `{:?}`.",
  311. VarType::Scalar,
  312. var_type
  313. ),
  314. v.line,
  315. v.column,
  316. ))
  317. }
  318. } else if var_type != arg_types[idx] && arg_types[idx] != VarType::Any {
  319. return Err(self.error.abort(
  320. &format!(
  321. "Incorrect argument type. Expected `{:?}`, got `{:?}`.",
  322. arg_types[idx], var_type
  323. ),
  324. v.line,
  325. v.column,
  326. ))
  327. }
  328. // Replace Dummy type with correct type.
  329. let mut v_new = v.clone();
  330. v_new.typ = var_type;
  331. rhs.push(Arg::Var(v_new));
  332. continue
  333. }
  334. return Err(self.error.abort(
  335. &format!("Unknown variable reference `{}`.", v.name),
  336. v.line,
  337. v.column,
  338. ))
  339. }
  340. } // <-- statement.rhs.iter().enumerate()
  341. // We now type-checked and assigned types to the statement rhs,
  342. // so now we apply it to the statement.
  343. stmt.rhs = rhs;
  344. // In case this statement is an assignment, we will push its
  345. // result on the heap.
  346. if statement.typ == StatementType::Assign {
  347. let mut var = statement.lhs.clone().unwrap();
  348. // Since we are doing an assignment, ensure that there is a return type.
  349. if return_types.is_empty() {
  350. return Err(self.error.abort(
  351. "Cannot perform assignment without a return type",
  352. var.line,
  353. var.column,
  354. ))
  355. }
  356. var.typ = return_types[0];
  357. stmt.lhs = Some(var.clone());
  358. heap.push(var.clone());
  359. self.heap = heap.clone();
  360. }
  361. //println!("{:#?}", stmt);
  362. statements.push(stmt);
  363. } // <-- for statement in &self.statements
  364. // Here we replace the self.statements and self.heap with what we
  365. // built so far. These can be used later on by the compiler after
  366. // this function is finished.
  367. self.statements = statements;
  368. self.heap = heap;
  369. //println!("=================STATEMENTS===============\n{:#?}", self.statements);
  370. //println!("====================HEAP==================\n{:#?}", self.heap);
  371. //println!("==================LITERALS================\n{:#?}", self.literals);
  372. Ok(())
  373. }
  374. fn lookup_var(&self, name: &str) -> Option<Var> {
  375. if let Some(r) = self.lookup_constant(name) {
  376. return Some(Var::Constant(r))
  377. }
  378. if let Some(r) = self.lookup_witness(name) {
  379. return Some(Var::Witness(r))
  380. }
  381. if let Some(r) = self.lookup_heap(name) {
  382. return Some(Var::Variable(r))
  383. }
  384. None
  385. }
  386. fn lookup_constant(&self, name: &str) -> Option<Constant> {
  387. for i in &self.constants {
  388. if i.name == name {
  389. return Some(i.clone())
  390. }
  391. }
  392. None
  393. }
  394. fn lookup_witness(&self, name: &str) -> Option<Witness> {
  395. for i in &self.witnesses {
  396. if i.name == name {
  397. return Some(i.clone())
  398. }
  399. }
  400. None
  401. }
  402. fn lookup_heap(&self, name: &str) -> Option<Variable> {
  403. for i in &self.heap {
  404. if i.name == name {
  405. return Some(i.clone())
  406. }
  407. }
  408. None
  409. }
  410. pub fn analyze_semantic(&mut self) -> Result<()> {
  411. let mut heap = vec![];
  412. println!("Loading constants...\n-----");
  413. for i in &self.constants {
  414. println!("Adding `{}` to heap", i.name);
  415. heap.push(&i.name);
  416. Analyzer::pause();
  417. }
  418. println!("Heap:\n{:#?}\n-----", heap);
  419. println!("Loading witnesses...\n-----");
  420. for i in &self.witnesses {
  421. println!("Adding `{}` to heap", i.name);
  422. heap.push(&i.name);
  423. Analyzer::pause();
  424. }
  425. println!("Heap:\n{:#?}\n-----", heap);
  426. println!("Loading circuit...");
  427. for i in &self.statements {
  428. let mut argnames = vec![];
  429. for arg in &i.rhs {
  430. if let Arg::Var(arg) = arg {
  431. argnames.push(arg.name.clone());
  432. } else if let Arg::Lit(lit) = arg {
  433. argnames.push(lit.name.clone());
  434. } else {
  435. unreachable!()
  436. }
  437. }
  438. println!("Executing: {:?}({:?})", i.opcode, argnames);
  439. Analyzer::pause();
  440. for arg in &i.rhs {
  441. if let Arg::Var(arg) = arg {
  442. print!("Looking up `{}` on the heap... ", arg.name);
  443. if let Some(index) = heap.iter().position(|&r| r == &arg.name) {
  444. println!("Found at heap index {}", index);
  445. } else {
  446. return Err(self.error.abort(
  447. &format!("Could not find `{}` on the heap", arg.name),
  448. arg.line,
  449. arg.column,
  450. ))
  451. }
  452. } else if let Arg::Lit(lit) = arg {
  453. println!("Using literal `{}`", lit.name);
  454. } else {
  455. println!("{:#?}", arg);
  456. unreachable!();
  457. }
  458. Analyzer::pause();
  459. }
  460. match i.typ {
  461. StatementType::Assign => {
  462. println!("Pushing result as `{}` to heap", &i.lhs.as_ref().unwrap().name);
  463. heap.push(&i.lhs.as_ref().unwrap().name);
  464. println!("Heap:\n{:#?}\n-----", heap);
  465. }
  466. StatementType::Call => {
  467. println!("-----");
  468. }
  469. _ => unreachable!(),
  470. }
  471. }
  472. Ok(())
  473. }
  474. fn pause() {
  475. let msg = b"[Press Enter to continue]\r";
  476. let mut stdout = stdout();
  477. let _ = stdout.write(msg).unwrap();
  478. stdout.flush().unwrap();
  479. let _ = stdin().read(&mut [0]).unwrap();
  480. write!(stdout, "\x1b[1A\r\x1b[K\r").unwrap();
  481. }
  482. }