analyzer.rs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445
  1. use std::{
  2. io::{stdin, stdout, Read, Write},
  3. str::Chars,
  4. };
  5. use super::{
  6. ast::{Arg, Constant, Literal, Statement, StatementType, Var, Variable, Witness},
  7. error::ErrorEmitter,
  8. VarType,
  9. };
  10. pub struct Analyzer {
  11. pub constants: Vec<Constant>,
  12. pub witnesses: Vec<Witness>,
  13. pub statements: Vec<Statement>,
  14. pub literals: Vec<Literal>,
  15. pub stack: Vec<Variable>,
  16. error: ErrorEmitter,
  17. }
  18. impl Analyzer {
  19. pub fn new(
  20. filename: &str,
  21. source: Chars,
  22. constants: Vec<Constant>,
  23. witnesses: Vec<Witness>,
  24. statements: Vec<Statement>,
  25. ) -> Self {
  26. // For nice error reporting, we'll load everything into a string
  27. // vector so we have references to lines.
  28. let lines: Vec<String> = source.as_str().lines().map(|x| x.to_string()).collect();
  29. let error = ErrorEmitter::new("Semantic", filename, lines);
  30. Self { constants, witnesses, statements, literals: vec![], stack: vec![], error }
  31. }
  32. pub fn analyze_types(&mut self) {
  33. // To work around the pedantic safety, we'll make new vectors and then
  34. // replace the `statements` and `stack` vectors from the `Analyzer`
  35. // object when we are done.
  36. let mut statements = vec![];
  37. let mut stack = vec![];
  38. for statement in &self.statements {
  39. //println!("{:?}", statement);
  40. let mut stmt = statement.clone();
  41. let (return_types, arg_types) = statement.opcode.arg_types();
  42. let mut rhs = vec![];
  43. // This handling is kinda limiting, but it'll do for now.
  44. if !(arg_types[0] == VarType::BaseArray || arg_types[0] == VarType::ScalarArray) {
  45. // Check that number of args is correct
  46. if statement.rhs.len() != arg_types.len() {
  47. self.error.abort(
  48. &format!(
  49. "Incorrect number of arguments for statement. Expected {}, got {}.",
  50. arg_types.len(),
  51. statement.rhs.len()
  52. ),
  53. statement.line,
  54. 1,
  55. );
  56. }
  57. } else {
  58. // In case of arrays, check there's at least one element.
  59. if statement.rhs.is_empty() {
  60. self.error.abort(
  61. "Expected at least one element for statement using arrays.",
  62. statement.line,
  63. 1,
  64. );
  65. }
  66. }
  67. for (idx, arg) in statement.rhs.iter().enumerate() {
  68. // In case an argument is a function call, we will first
  69. // convert it to another statement that will get executed
  70. // before this one. An important assumption is that this
  71. // opcode has a return value. When executed we will push
  72. // this value onto the stack and use it as a reference to
  73. // the actual statement we're parsing at this moment.
  74. // TODO: FIXME: This needs a recursive algorithm, as this
  75. // only allows a single nested function.
  76. if let Arg::Func(func) = arg {
  77. let (f_return_types, f_arg_types) = func.opcode.arg_types();
  78. if f_return_types.is_empty() {
  79. self.error.abort(
  80. &format!(
  81. "Used a function argument which doesn't have a return value: {:?}",
  82. func.opcode
  83. ),
  84. statement.line,
  85. 1,
  86. );
  87. }
  88. let v = Variable {
  89. name: func.lhs.clone().unwrap().name,
  90. typ: f_return_types[0],
  91. line: func.lhs.clone().unwrap().line,
  92. column: func.lhs.clone().unwrap().column,
  93. };
  94. // FIXME: Needs better *Array handling.
  95. if arg_types[0] == VarType::BaseArray {
  96. if f_return_types[0] != VarType::Base {
  97. self.error.abort(
  98. &format!(
  99. "Function passed as argument returns wrong type. Expected `{:?}`, got `{:?}`.",
  100. VarType::Base,
  101. f_return_types[0],
  102. ),
  103. v.line,
  104. v.column,
  105. );
  106. }
  107. } else if arg_types[0] == VarType::ScalarArray {
  108. if f_return_types[0] != VarType::Scalar {
  109. self.error.abort(
  110. &format!(
  111. "Function passed as argument returns wrong type. Expected `{:?}`, got `{:?}`.",
  112. VarType::Scalar,
  113. f_return_types[0],
  114. ),
  115. v.line,
  116. v.column,
  117. );
  118. }
  119. } else if f_return_types[0] != arg_types[idx] {
  120. self.error.abort(
  121. &format!(
  122. "Function passed as argument returns wrong type. Expected `{:?}`, got `{:?}`.",
  123. arg_types[idx],
  124. f_return_types[0],
  125. ),
  126. v.line,
  127. v.column,
  128. );
  129. } else {
  130. panic!();
  131. }
  132. // Replace the statement function call with the variable from
  133. // the statement we just created to represent this nest.
  134. stmt.rhs[idx] = Arg::Var(v.clone());
  135. let mut rhs_inner = vec![];
  136. for i in &func.rhs {
  137. if let Arg::Var(v) = i {
  138. if let Some(var_ref) = self.lookup_var(&v.name) {
  139. let (var_type, ln, col) = match var_ref {
  140. Var::Constant(c) => (c.typ, c.line, c.column),
  141. Var::Witness(c) => (c.typ, c.line, c.column),
  142. Var::Variable(c) => (c.typ, c.line, c.column),
  143. };
  144. if var_type != f_arg_types[idx] {
  145. self.error.abort(
  146. &format!(
  147. "Incorrect argument type. Expected `{:?}`, got `{:?}`.",
  148. f_arg_types[idx], var_type
  149. ),
  150. ln,
  151. col,
  152. );
  153. }
  154. // Apply the proper type.
  155. let mut v_new = v.clone();
  156. v_new.typ = var_type;
  157. rhs_inner.push(Arg::Var(v_new));
  158. continue
  159. }
  160. self.error.abort(
  161. &format!("Unknown variable reference `{}`.", v.name),
  162. v.line,
  163. v.column,
  164. );
  165. } else {
  166. unimplemented!()
  167. }
  168. }
  169. let s = Statement {
  170. typ: func.typ,
  171. opcode: func.opcode,
  172. lhs: Some(v.clone()),
  173. rhs: rhs_inner,
  174. line: func.line,
  175. };
  176. // The lhs of the inner function call becomes rhs of the outer one.
  177. rhs.push(Arg::Var(v.clone()));
  178. // Add this to the list of statements.
  179. statements.push(s);
  180. // We replace self.stack here so we can do proper stack lookups.
  181. stack.push(v.clone());
  182. self.stack = stack.clone();
  183. //println!("{:#?}", stack);
  184. //println!("{:#?}", statements);
  185. continue
  186. } // <-- Arg::Func
  187. // The literals get pushed on their own "stack", and
  188. // then the compiler will reference them by their own
  189. // index when it comes to running the statement that
  190. // requires the literal type.
  191. if let Arg::Lit(v) = arg {
  192. // Match this literal type to a VarType for
  193. // type checking.
  194. let var_type = v.typ.to_vartype();
  195. if var_type != arg_types[idx] {
  196. self.error.abort(
  197. &format!(
  198. "Incorrect argument type. Expected `{:?}`, got `{:?}`.",
  199. arg_types[idx], var_type
  200. ),
  201. v.line,
  202. v.column,
  203. );
  204. }
  205. self.literals.push(v.clone());
  206. rhs.push(Arg::Lit(v.clone()));
  207. continue
  208. }
  209. if let Arg::Var(v) = arg {
  210. // Look up variable and check if type is correct.
  211. if let Some(s_var) = self.lookup_var(&v.name) {
  212. let (var_type, _ln, _col) = match s_var {
  213. Var::Constant(c) => (c.typ, c.line, c.column),
  214. Var::Witness(c) => (c.typ, c.line, c.column),
  215. Var::Variable(c) => (c.typ, c.line, c.column),
  216. };
  217. // FIXME: Better array handling
  218. if arg_types[0] == VarType::BaseArray {
  219. if var_type != VarType::Base {
  220. self.error.abort(
  221. &format!(
  222. "Incorrect argument type. Expected `{:?}`, got `{:?}`.",
  223. VarType::Base,
  224. var_type
  225. ),
  226. v.line,
  227. v.column,
  228. );
  229. }
  230. } else if arg_types[0] == VarType::ScalarArray {
  231. if var_type != VarType::Scalar {
  232. self.error.abort(
  233. &format!(
  234. "Incorrect argument type. Expected `{:?}`, got `{:?}`.",
  235. VarType::Scalar,
  236. var_type
  237. ),
  238. v.line,
  239. v.column,
  240. );
  241. }
  242. } else if var_type != arg_types[idx] {
  243. self.error.abort(
  244. &format!(
  245. "Incorrect argument type. Expected `{:?}`, got `{:?}`.",
  246. arg_types[idx], var_type
  247. ),
  248. v.line,
  249. v.column,
  250. );
  251. }
  252. // Replace Dummy type with correct type.
  253. let mut v_new = v.clone();
  254. v_new.typ = var_type;
  255. rhs.push(Arg::Var(v_new));
  256. continue
  257. }
  258. self.error.abort(
  259. &format!("Unknown variable reference `{}`.", v.name),
  260. v.line,
  261. v.column,
  262. );
  263. }
  264. } // <-- statement.rhs.iter().enumerate()
  265. // We now type-checked and assigned types to the statement rhs,
  266. // so now we apply it to the statement.
  267. stmt.rhs = rhs;
  268. // In case this statement is an assignment, we will push its
  269. // result on the stack.
  270. if statement.typ == StatementType::Assign {
  271. let mut var = statement.lhs.clone().unwrap();
  272. var.typ = return_types[0];
  273. stmt.lhs = Some(var.clone());
  274. stack.push(var.clone());
  275. self.stack = stack.clone();
  276. }
  277. //println!("{:#?}", stmt);
  278. statements.push(stmt);
  279. } // <-- for statement in &self.statements
  280. // Here we replace the self.statements and self.stack with what we
  281. // built so far. These can be used later on by the compiler after
  282. // this function is finished.
  283. self.statements = statements;
  284. self.stack = stack;
  285. //println!("=================STATEMENTS===============\n{:#?}", self.statements);
  286. //println!("===================STACK==================\n{:#?}", self.stack);
  287. //println!("==================LITERALS================\n{:#?}", self.literals);
  288. }
  289. fn lookup_var(&self, name: &str) -> Option<Var> {
  290. if let Some(r) = self.lookup_constant(name) {
  291. return Some(Var::Constant(r))
  292. }
  293. if let Some(r) = self.lookup_witness(name) {
  294. return Some(Var::Witness(r))
  295. }
  296. if let Some(r) = self.lookup_stack(name) {
  297. return Some(Var::Variable(r))
  298. }
  299. None
  300. }
  301. fn lookup_constant(&self, name: &str) -> Option<Constant> {
  302. for i in &self.constants {
  303. if i.name == name {
  304. return Some(i.clone())
  305. }
  306. }
  307. None
  308. }
  309. fn lookup_witness(&self, name: &str) -> Option<Witness> {
  310. for i in &self.witnesses {
  311. if i.name == name {
  312. return Some(i.clone())
  313. }
  314. }
  315. None
  316. }
  317. fn lookup_stack(&self, name: &str) -> Option<Variable> {
  318. for i in &self.stack {
  319. if i.name == name {
  320. return Some(i.clone())
  321. }
  322. }
  323. None
  324. }
  325. pub fn analyze_semantic(&mut self) {
  326. let mut stack = vec![];
  327. println!("Loading constants...\n-----");
  328. for i in &self.constants {
  329. println!("Adding `{}` to stack", i.name);
  330. stack.push(&i.name);
  331. Analyzer::pause();
  332. }
  333. println!("Stack:\n{:#?}\n-----", stack);
  334. println!("Loading witnesses...\n-----");
  335. for i in &self.witnesses {
  336. println!("Adding `{}` to stack", i.name);
  337. stack.push(&i.name);
  338. Analyzer::pause();
  339. }
  340. println!("Stack:\n{:#?}\n-----", stack);
  341. println!("Loading circuit...");
  342. for i in &self.statements {
  343. let mut argnames = vec![];
  344. for arg in &i.rhs {
  345. if let Arg::Var(arg) = arg {
  346. argnames.push(arg.name.clone());
  347. } else if let Arg::Lit(lit) = arg {
  348. argnames.push(lit.name.clone());
  349. } else {
  350. unreachable!()
  351. }
  352. }
  353. println!("Executing: {:?}({:?})", i.opcode, argnames);
  354. Analyzer::pause();
  355. for arg in &i.rhs {
  356. if let Arg::Var(arg) = arg {
  357. print!("Looking up `{}` on the stack... ", arg.name);
  358. if let Some(index) = stack.iter().position(|&r| r == &arg.name) {
  359. println!("Found at stack index {}", index);
  360. } else {
  361. self.error.abort(
  362. &format!("Could not find `{}` on the stack", arg.name),
  363. arg.line,
  364. arg.column,
  365. );
  366. }
  367. } else if let Arg::Lit(lit) = arg {
  368. println!("Using literal `{}`", lit.name);
  369. } else {
  370. println!("{:#?}", arg);
  371. unreachable!();
  372. }
  373. Analyzer::pause();
  374. }
  375. match i.typ {
  376. StatementType::Assign => {
  377. println!("Pushing result as `{}` to stack", &i.lhs.as_ref().unwrap().name);
  378. stack.push(&i.lhs.as_ref().unwrap().name);
  379. println!("Stack:\n{:#?}\n-----", stack);
  380. }
  381. StatementType::Call => {
  382. println!("-----");
  383. }
  384. _ => unreachable!(),
  385. }
  386. }
  387. }
  388. fn pause() {
  389. let msg = b"[Press Enter to continue]\r";
  390. let mut stdout = stdout();
  391. let _ = stdout.write(msg).unwrap();
  392. stdout.flush().unwrap();
  393. let _ = stdin().read(&mut [0]).unwrap();
  394. write!(stdout, "{}{}\r", termion::cursor::Up(1), termion::clear::CurrentLine).unwrap();
  395. }
  396. }