You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1119 lines
33 KiB

6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
5 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
5 years ago
6 years ago
6 years ago
5 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
5 years ago
5 years ago
6 years ago
6 years ago
6 years ago
6 years ago
5 years ago
6 years ago
6 years ago
6 years ago
6 years ago
5 years ago
5 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
5 years ago
6 years ago
6 years ago
6 years ago
6 years ago
  1. /*
  2. Copyright 2018 0KIMS association.
  3. This file is part of circom (Zero Knowledge Circuit Compiler).
  4. circom is a free software: you can redistribute it and/or modify it
  5. under the terms of the GNU General Public License as published by
  6. the Free Software Foundation, either version 3 of the License, or
  7. (at your option) any later version.
  8. circom is distributed in the hope that it will be useful, but WITHOUT
  9. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  10. or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
  11. License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with circom. If not, see <https://www.gnu.org/licenses/>.
  14. */
  15. const path = require("path");
  16. const fs = require("fs");
  17. const bigInt = require("big-integer");
  18. const __P__ = new bigInt("21888242871839275222246405745257275088548364400416034343698204186575808495617");
  19. const __MASK__ = new bigInt(2).pow(253).minus(1);
  20. const lc = require("./lcalgebra");
  21. const parser = require("../parser/jaz.js").parser;
  22. /* TODO: Add lines information
  23. function setLines(dst, first, last) {
  24. last = last || first;
  25. dst.first_line = first.first_line;
  26. dst.first_column = first.first_column;
  27. dst.last_line = last.last_line;
  28. dst.last_column = last.last_column;
  29. }
  30. */
  31. module.exports = exec;
  32. function exec(ctx, ast) {
  33. if (!ast) {
  34. return error(ctx, ast, "Null AST");
  35. }
  36. if ((ast.type == "NUMBER") || (ast.type == "LINEARCOMBINATION") || (ast.type =="SIGNAL") || (ast.type == "QEQ")) {
  37. return ast;
  38. } else if (ast.type == "VARIABLE") {
  39. return execVariable(ctx, ast);
  40. } else if (ast.type == "PIN") {
  41. return execPin(ctx, ast);
  42. } else if (ast.type == "OP") {
  43. if (ast.op == "=") {
  44. return execVarAssignement(ctx, ast);
  45. } else if (ast.op == "<--") {
  46. return execSignalAssign(ctx, ast);
  47. } else if (ast.op == "<==") {
  48. return execSignalAssignConstrain(ctx, ast);
  49. } else if (ast.op == "===") {
  50. return execConstrain(ctx, ast);
  51. } else if (ast.op == "+=") {
  52. return execVarAddAssignement(ctx, ast);
  53. } else if (ast.op == "*=") {
  54. return execVarMulAssignement(ctx, ast);
  55. } else if (ast.op == "+") {
  56. return execAdd(ctx, ast);
  57. } else if (ast.op == "-") {
  58. return execSub(ctx, ast);
  59. } else if (ast.op == "UMINUS") {
  60. return execUMinus(ctx, ast);
  61. } else if (ast.op == "*") {
  62. return execMul(ctx, ast);
  63. } else if (ast.op == "%") {
  64. return execMod(ctx, ast);
  65. } else if (ast.op == "PLUSPLUSRIGHT") {
  66. return execPlusPlusRight(ctx, ast);
  67. } else if (ast.op == "PLUSPLUSLEFT") {
  68. return execPlusPlusLeft(ctx, ast);
  69. } else if (ast.op == "MINUSMINUSRIGHT") {
  70. return execMinusMinusRight(ctx, ast);
  71. } else if (ast.op == "MINUSMINUSLEFT") {
  72. return execMinusMinusLeft(ctx, ast);
  73. } else if (ast.op == "/") {
  74. return execDiv(ctx, ast);
  75. } else if (ast.op == "\\") {
  76. return execIDiv(ctx, ast);
  77. } else if (ast.op == "**") {
  78. return execExp(ctx, ast);
  79. } else if (ast.op == "&") {
  80. return execBAnd(ctx, ast);
  81. } else if (ast.op == "&&") {
  82. return execAnd(ctx, ast);
  83. } else if (ast.op == "||") {
  84. return execOr(ctx, ast);
  85. } else if (ast.op == "<<") {
  86. return execShl(ctx, ast);
  87. } else if (ast.op == ">>") {
  88. return execShr(ctx, ast);
  89. } else if (ast.op == "<") {
  90. return execLt(ctx, ast);
  91. } else if (ast.op == ">") {
  92. return execGt(ctx, ast);
  93. } else if (ast.op == "<=") {
  94. return execLte(ctx, ast);
  95. } else if (ast.op == ">=") {
  96. return execGte(ctx, ast);
  97. } else if (ast.op == "==") {
  98. return execEq(ctx, ast);
  99. } else if (ast.op == "!=") {
  100. return execNeq(ctx, ast);
  101. } else if (ast.op == "?") {
  102. return execTerCon(ctx, ast);
  103. } else {
  104. error(ctx, ast, "Invalid operation: " + ast.op);
  105. }
  106. } else if (ast.type == "DECLARE") {
  107. if (ast.declareType == "COMPONENT") {
  108. return execDeclareComponent(ctx, ast);
  109. } else if ((ast.declareType == "SIGNALIN")||
  110. (ast.declareType == "SIGNALOUT")||
  111. (ast.declareType == "SIGNAL")) {
  112. return execDeclareSignal(ctx, ast);
  113. } else if (ast.declareType == "VARIABLE") {
  114. return execDeclareVariable(ctx, ast);
  115. } else {
  116. error(ctx, ast, "Invalid declaration: " + ast.declareType);
  117. }
  118. } else if (ast.type == "FUNCTIONCALL") {
  119. return execFunctionCall(ctx, ast);
  120. } else if (ast.type == "BLOCK") {
  121. return execBlock(ctx, ast);
  122. } else if (ast.type == "COMPUTE") {
  123. return ;
  124. } else if (ast.type == "FOR") {
  125. return execFor(ctx, ast);
  126. } else if (ast.type == "WHILE") {
  127. return execWhile(ctx, ast);
  128. } else if (ast.type == "IF") {
  129. return execIf(ctx, ast);
  130. } else if (ast.type == "RETURN") {
  131. return execReturn(ctx, ast);
  132. } else if (ast.type == "TEMPLATEDEF") {
  133. return execTemplateDef(ctx, ast);
  134. } else if (ast.type == "FUNCTIONDEF") {
  135. return execFunctionDef(ctx, ast);
  136. } else if (ast.type == "INCLUDE") {
  137. return execInclude(ctx, ast);
  138. } else if (ast.type == "ARRAY") {
  139. return execArray(ctx, ast);
  140. } else {
  141. error(ctx, ast, "Invalid AST node type: " + ast.type);
  142. }
  143. }
  144. function error(ctx, ast, errStr) {
  145. ctx.error = {
  146. pos: {
  147. first_line: ast.first_line,
  148. first_column: ast.first_column,
  149. last_line: ast.last_line,
  150. last_column: ast.last_column
  151. },
  152. errStr: errStr,
  153. errFile: ctx.fileName,
  154. ast: ast,
  155. message: errStr
  156. };
  157. }
  158. function iterateSelectors(ctx, sizes, baseName, fn) {
  159. if (sizes.length == 0) {
  160. return fn(baseName);
  161. }
  162. const res = [];
  163. for (let i=0; i<sizes[0]; i++) {
  164. res.push(iterateSelectors(ctx, sizes.slice(1), baseName+"["+i+"]", fn));
  165. if (ctx.error) return null;
  166. }
  167. return res;
  168. }
  169. function setScope(ctx, name, selectors, value) {
  170. let l = getScopeLevel(ctx, name);
  171. if (l==-1) l= ctx.scopes.length-1;
  172. if (selectors.length == 0) {
  173. ctx.scopes[l][name] = value;
  174. } else {
  175. setScopeArray(ctx.scopes[l][name], selectors);
  176. }
  177. function setScopeArray(a, sels) {
  178. if (sels.length == 1) {
  179. a[sels[0].value] = value;
  180. } else {
  181. setScopeArray(a[sels[0]], sels.slice(1));
  182. }
  183. }
  184. }
  185. function getScope(ctx, name, selectors) {
  186. const sels = [];
  187. if (selectors) {
  188. for (let i=0; i< selectors.length; i++) {
  189. const idx = exec(ctx, selectors[i]);
  190. if (ctx.error) return;
  191. if (idx.type != "NUMBER") return error(ctx, selectors[i], "expected a number");
  192. sels.push( idx.value.toJSNumber() );
  193. }
  194. }
  195. function select(v, s) {
  196. s = s || [];
  197. if (s.length == 0) return v;
  198. return select(v[s[0]], s.slice(1));
  199. }
  200. for (let i=ctx.scopes.length-1; i>=0; i--) {
  201. if (ctx.scopes[i][name]) return select(ctx.scopes[i][name], sels);
  202. }
  203. return null;
  204. }
  205. function getScopeLevel(ctx, name) {
  206. for (let i=ctx.scopes.length-1; i>=0; i--) {
  207. if (ctx.scopes[i][name]) return i;
  208. }
  209. return -1;
  210. }
  211. function execBlock(ctx, ast) {
  212. for (let i=0; i<ast.statements.length; i++) {
  213. exec(ctx, ast.statements[i]);
  214. if (ctx.returnValue) return;
  215. if (ctx.error) return;
  216. }
  217. }
  218. function execTemplateDef(ctx, ast) {
  219. const scope = ctx.scopes[0]; // Lets put templates always in top scope.
  220. // const scope = ctx.scopes[ctx.scopes.length-1];
  221. if (getScope(ctx, ast.name)) {
  222. return error(ctx, ast, "Name already exists: "+ast.name);
  223. }
  224. scope[ast.name] = {
  225. type: "TEMPLATE",
  226. params: ast.params,
  227. block: ast.block,
  228. fileName: ctx.fileName,
  229. filePath: ctx.filePath,
  230. scopes: copyScope(ctx.scopes)
  231. };
  232. }
  233. function execFunctionDef(ctx, ast) {
  234. const scope = ctx.scopes[0]; // Lets put functions always in top scope.
  235. // const scope = ctx.scopes[ctx.scopes.length-1];
  236. if (getScope(ctx, ast.name)) {
  237. return error(ctx, ast, "Name already exists: "+ast.name);
  238. }
  239. ctx.functionParams[ast.name] = ast.params;
  240. scope[ast.name] = {
  241. type: "FUNCTION",
  242. params: ast.params,
  243. block: ast.block,
  244. fileName: ctx.fileName,
  245. filePath: ctx.filePath,
  246. scopes: copyScope(ctx.scopes)
  247. };
  248. }
  249. function execDeclareComponent(ctx, ast) {
  250. const scope = ctx.scopes[ctx.scopes.length-1];
  251. if (ast.name.type != "VARIABLE") return error(ctx, ast, "Invalid component name");
  252. if (getScope(ctx, ast.name.name)) return error(ctx, ast, "Name already exists: "+ast.name.name);
  253. const baseName = ctx.currentComponent ? ctx.currentComponent + "." + ast.name.name : ast.name.name;
  254. const sizes=[];
  255. for (let i=0; i< ast.name.selectors.length; i++) {
  256. const size = exec(ctx, ast.name.selectors[i]);
  257. if (ctx.error) return;
  258. if (size.type != "NUMBER") return error(ctx, ast.name.selectors[i], "expected a number");
  259. sizes.push( size.value.toJSNumber() );
  260. }
  261. scope[ast.name.name] = iterateSelectors(ctx, sizes, baseName, function(fullName) {
  262. ctx.components[fullName] = "UNINSTANTIATED";
  263. return {
  264. type: "COMPONENT",
  265. fullName: fullName
  266. };
  267. });
  268. return {
  269. type: "VARIABLE",
  270. name: ast.name.name,
  271. selectors: []
  272. };
  273. }
  274. function execInstantiateComponet(ctx, vr, fn) {
  275. if (vr.type != "VARIABLE") return error(ctx, fn, "Left hand instatiate component must be a variable");
  276. if (fn.type != "FUNCTIONCALL") return error(ctx, fn, "Right type of instantiate component must be a function call");
  277. const componentName = vr.name;
  278. const templateName = fn.name;
  279. const scopeLevel = getScopeLevel(ctx, templateName);
  280. if (scopeLevel == -1) return error(ctx,fn, "Invalid Template");
  281. const template = getScope(ctx, templateName);
  282. if (template.type != "TEMPLATE") return error(ctx, fn, "Invalid Template");
  283. const paramValues = [];
  284. for (let i=0; i< fn.params.length; i++) {
  285. const v = exec(ctx, fn.params[i]);
  286. if (ctx.error) return;
  287. paramValues.push(v);
  288. }
  289. if (template.params.length != paramValues.length) error(ctx, fn, "Invalid Number of parameters");
  290. const vv = getScope(ctx, componentName, vr.selectors);
  291. if (!vv) return error(ctx, vr, "Component not defined"+ componentName);
  292. instantiateComponent(vv);
  293. function instantiateComponent(varVal) {
  294. function extractValue(v) {
  295. if (Array.isArray(v)) {
  296. return v.map(extractValue);
  297. } else {
  298. return v.value.toString();
  299. }
  300. }
  301. if (Array.isArray(varVal)) {
  302. for (let i =0; i<varVal.length; i++) {
  303. instantiateComponent(varVal[i]);
  304. }
  305. return;
  306. }
  307. if (ctx.components[varVal.fullName] != "UNINSTANTIATED") error(ctx, fn, "Component already instantiated");
  308. const oldComponent = ctx.currentComponent;
  309. const oldFileName = ctx.fileName;
  310. const oldFilePath = ctx.filePath;
  311. ctx.currentComponent = varVal.fullName;
  312. ctx.components[ctx.currentComponent] = {
  313. signals: [],
  314. params: {}
  315. };
  316. const oldScopes = ctx.scopes;
  317. ctx.scopes = oldScopes.slice(0, scopeLevel+1);
  318. if (template.params.length != paramValues.length) return error(ctx, fn, "Invalid number of parameters: " + templateName);
  319. const scope = {};
  320. for (let i=0; i< template.params.length; i++) {
  321. scope[template.params[i]] = paramValues[i];
  322. ctx.components[ctx.currentComponent].params[template.params[i]] = extractValue(paramValues[i]);
  323. }
  324. ctx.components[ctx.currentComponent].template = templateName;
  325. ctx.fileName = template.fileName;
  326. ctx.filePath = template.filePath;
  327. ctx.scopes = copyScope( template.scopes );
  328. ctx.scopes.push(scope);
  329. execBlock(ctx, template.block);
  330. ctx.fileName = oldFileName;
  331. ctx.filePath = oldFilePath;
  332. ctx.currentComponent = oldComponent;
  333. ctx.scopes = oldScopes;
  334. }
  335. }
  336. function execFunctionCall(ctx, ast) {
  337. if (ast.name == "log") {
  338. const v = exec(ctx, ast.params[0]);
  339. console.log(v.value.toString());
  340. return;
  341. }
  342. const scopeLevel = getScopeLevel(ctx, ast.name);
  343. if (scopeLevel == -1) return error(ctx, ast, "Function not defined: " + ast.name);
  344. const fnc = getScope(ctx, ast.name);
  345. if (fnc.type != "FUNCTION") return error(ctx, ast, "Not a function: " + ast.name);
  346. const paramValues = [];
  347. for (let i=0; i< ast.params.length; i++) {
  348. const v = exec(ctx, ast.params[i]);
  349. if (ctx.error) return;
  350. paramValues.push(v);
  351. }
  352. if (ast.params.length != paramValues.length) error(ctx, ast, "Invalid Number of parameters");
  353. const oldFileName = ctx.fileName;
  354. const oldFilePath = ctx.filePath;
  355. const oldScopes = ctx.scopes;
  356. ctx.scopes = oldScopes.slice(0, scopeLevel+1);
  357. const scope = {};
  358. for (let i=0; i< fnc.params.length; i++) {
  359. scope[fnc.params[i]] = paramValues[i];
  360. }
  361. ctx.fileName = fnc.fileName;
  362. ctx.filePath = fnc.filePath;
  363. ctx.scopes = copyScope( fnc.scopes );
  364. ctx.scopes.push(scope);
  365. execBlock(ctx, fnc.block);
  366. const res = ctx.returnValue;
  367. ctx.returnValue = null;
  368. ctx.fileName = oldFileName;
  369. ctx.filePath = oldFilePath;
  370. ctx.scopes = oldScopes;
  371. return res;
  372. }
  373. function execReturn(ctx, ast) {
  374. ctx.returnValue = exec(ctx, ast.value);
  375. return;
  376. }
  377. function execDeclareSignal(ctx, ast) {
  378. const scope = ctx.scopes[ctx.scopes.length-1];
  379. if (ast.name.type != "VARIABLE") return error(ctx, ast, "Invalid component name");
  380. if (getScope(ctx, ast.name.name)) return error(ctx, ast, "Name already exists: "+ast.name.name);
  381. const baseName = ctx.currentComponent ? ctx.currentComponent + "." + ast.name.name : ast.name.name;
  382. const sizes=[];
  383. for (let i=0; i< ast.name.selectors.length; i++) {
  384. const size = exec(ctx, ast.name.selectors[i]);
  385. if (ctx.error) return;
  386. if (size.type != "NUMBER") return error(ctx, ast.name.selectors[i], "expected a number");
  387. sizes.push( size.value.toJSNumber() );
  388. }
  389. scope[ast.name.name] = iterateSelectors(ctx, sizes, baseName, function(fullName) {
  390. ctx.signals[fullName] = {
  391. fullName: fullName,
  392. direction: ast.declareType == "SIGNALIN" ? "IN" : (ast.declareType == "SIGNALOUT" ? "OUT" : ""),
  393. private: ast.private,
  394. component: ctx.currentComponent,
  395. equivalence: "",
  396. alias: [fullName]
  397. };
  398. ctx.components[ctx.currentComponent].signals.push(fullName);
  399. return {
  400. type: "SIGNAL",
  401. fullName: fullName,
  402. };
  403. });
  404. return {
  405. type: "VARIABLE",
  406. name: ast.name.name,
  407. selectors: []
  408. };
  409. }
  410. function execDeclareVariable(ctx, ast) {
  411. const scope = ctx.scopes[ctx.scopes.length-1];
  412. if (ast.name.type != "VARIABLE") return error(ctx, ast, "Invalid linear combination name");
  413. if (getScope(ctx, ast.name.name)) return error(ctx, ast, "Name already exists: "+ast.name.name);
  414. const sizes=[];
  415. for (let i=0; i< ast.name.selectors.length; i++) {
  416. const size = exec(ctx, ast.name.selectors[i]);
  417. if (ctx.error) return;
  418. if (size.type != "NUMBER") return error(ctx, ast.name.selectors[i], "expected a number");
  419. sizes.push( size.value.toJSNumber() );
  420. }
  421. scope[ast.name.name] = iterateSelectors(ctx, sizes, "", function() {
  422. return {
  423. type: "NUMBER",
  424. value: bigInt(0)
  425. };
  426. });
  427. return {
  428. type: "VARIABLE",
  429. name: ast.name.name,
  430. selectors: []
  431. };
  432. }
  433. function execVariable(ctx, ast) {
  434. let v;
  435. try {
  436. v = getScope(ctx, ast.name, ast.selectors);
  437. } catch(err) {
  438. console.log(JSON.stringify(ast, null,1));
  439. }
  440. if (ctx.error) return;
  441. if (!v) return error(ctx, ast, "Variable not defined");
  442. // If the signal has an assigned value (constant) just return the constant
  443. if ((v.type == "SIGNAL") && (ctx.signals[v.fullName].value)) {
  444. return {
  445. type: "NUMBER",
  446. value: ctx.signals[v.fullName].value
  447. };
  448. }
  449. let res;
  450. res=v;
  451. return res;
  452. }
  453. function execPin(ctx, ast) {
  454. const component = getScope(ctx, ast.component.name, ast.component.selectors);
  455. if (!component) return error(ctx, ast.component, "Component does not exists: "+ast.component.name);
  456. if (ctx.error) return;
  457. let signalFullName = component.fullName + "." + ast.pin.name;
  458. for (let i=0; i< ast.pin.selectors.length; i++) {
  459. const sel = exec(ctx, ast.pin.selectors[i]);
  460. if (ctx.error) return;
  461. if (sel.type != "NUMBER") return error(ctx, ast.pin.selectors[i], "expected a number");
  462. signalFullName += "[" + sel.value.toJSNumber() + "]";
  463. }
  464. if (!ctx.signals[signalFullName]) error(ctx, ast, "Signal not defined:" + signalFullName);
  465. return {
  466. type: "SIGNAL",
  467. fullName: signalFullName
  468. };
  469. }
  470. function execFor(ctx, ast) {
  471. ctx.scopes.push({});
  472. exec(ctx, ast.init);
  473. if (ctx.error) return;
  474. let v = exec(ctx, ast.condition);
  475. if (ctx.error) return;
  476. if (typeof v.value != "undefined") {
  477. while ((v.value.neq(0))&&(!ctx.returnValue)) {
  478. exec(ctx, ast.body);
  479. if (ctx.error) return;
  480. exec(ctx, ast.step);
  481. if (ctx.error) return;
  482. v = exec(ctx, ast.condition);
  483. if (ctx.error) return;
  484. }
  485. }
  486. ctx.scopes.pop();
  487. }
  488. function execWhile(ctx, ast) {
  489. let v = exec(ctx, ast.condition);
  490. if (ctx.error) return;
  491. if (typeof v.value != "undefined") {
  492. while ((v.value.neq(0))&&(!ctx.returnValue)) {
  493. exec(ctx, ast.body);
  494. if (ctx.error) return;
  495. v = exec(ctx, ast.condition);
  496. if (ctx.error) return;
  497. }
  498. }
  499. }
  500. function execIf(ctx, ast) {
  501. let v = exec(ctx, ast.condition);
  502. if (ctx.error) return;
  503. if (typeof v.value != "undefined") {
  504. if ((v.value.neq(0))&&(!ctx.returnValue)) {
  505. exec(ctx, ast.then);
  506. if (ctx.error) return;
  507. } else {
  508. if (ast.else) {
  509. exec(ctx, ast.else);
  510. if (ctx.error) return;
  511. }
  512. }
  513. }
  514. }
  515. function execVarAssignement(ctx, ast) {
  516. let v;
  517. if (ast.values[0].type == "DECLARE") {
  518. v = exec(ctx, ast.values[0]);
  519. if (ctx.error) return;
  520. } else {
  521. v = ast.values[0];
  522. }
  523. const num = getScope(ctx, v.name, v.selectors);
  524. if (ctx.error) return;
  525. if ((typeof(num) != "object")||(num == null)) return error(ctx, ast, "Variable not defined");
  526. if (num.type == "COMPONENT") return execInstantiateComponet(ctx, v, ast.values[1]);
  527. if (ctx.error) return;
  528. // if (num.type == "SIGNAL") return error(ctx, ast, "Cannot assign to a signal with `=` use <-- or <== ops");
  529. const res = exec(ctx, ast.values[1]);
  530. if (ctx.error) return;
  531. setScope(ctx, v.name, v.selectors, res);
  532. return v;
  533. }
  534. function execLt(ctx, ast) {
  535. const a = exec(ctx, ast.values[0]);
  536. if (ctx.error) return;
  537. if (a.type != "NUMBER") return { type: "NUMBER" };
  538. const b = exec(ctx, ast.values[1]);
  539. if (ctx.error) return;
  540. if (b.type != "NUMBER") return { type: "NUMBER" };
  541. if (!a.value || !b.value) return { type: "NUMBER" };
  542. return {
  543. type: "NUMBER",
  544. value: a.value.lt(b.value) ? bigInt(1) : bigInt(0)
  545. };
  546. }
  547. function execGt(ctx, ast) {
  548. const a = exec(ctx, ast.values[0]);
  549. if (ctx.error) return;
  550. if (a.type != "NUMBER") return { type: "NUMBER" };
  551. const b = exec(ctx, ast.values[1]);
  552. if (ctx.error) return;
  553. if (b.type != "NUMBER") return { type: "NUMBER" };
  554. if (!a.value || !b.value) return { type: "NUMBER" };
  555. return {
  556. type: "NUMBER",
  557. value: a.value.gt(b.value) ? bigInt(1) : bigInt(0)
  558. };
  559. }
  560. function execLte(ctx, ast) {
  561. const a = exec(ctx, ast.values[0]);
  562. if (ctx.error) return;
  563. if (a.type != "NUMBER") return { type: "NUMBER" };
  564. const b = exec(ctx, ast.values[1]);
  565. if (ctx.error) return;
  566. if (b.type != "NUMBER") return { type: "NUMBER" };
  567. if (!a.value || !b.value) return { type: "NUMBER" };
  568. return {
  569. type: "NUMBER",
  570. value: a.value.lesserOrEquals(b.value) ? bigInt(1) : bigInt(0)
  571. };
  572. }
  573. function execGte(ctx, ast) {
  574. const a = exec(ctx, ast.values[0]);
  575. if (ctx.error) return;
  576. if (a.type != "NUMBER") return { type: "NUMBER" };
  577. const b = exec(ctx, ast.values[1]);
  578. if (ctx.error) return;
  579. if (b.type != "NUMBER") return { type: "NUMBER" };
  580. if (!a.value || !b.value) return { type: "NUMBER" };
  581. return {
  582. type: "NUMBER",
  583. value: a.value.greaterOrEquals(b.value) ? bigInt(1) : bigInt(0)
  584. };
  585. }
  586. function execEq(ctx, ast) {
  587. const a = exec(ctx, ast.values[0]);
  588. if (ctx.error) return;
  589. if (a.type != "NUMBER") return { type: "NUMBER" };
  590. const b = exec(ctx, ast.values[1]);
  591. if (ctx.error) return;
  592. if (b.type != "NUMBER") return { type: "NUMBER" };
  593. if (!a.value || !b.value) return { type: "NUMBER" };
  594. return {
  595. type: "NUMBER",
  596. value: a.value.eq(b.value) ? bigInt(1) : bigInt(0)
  597. };
  598. }
  599. function execNeq(ctx, ast) {
  600. const a = exec(ctx, ast.values[0]);
  601. if (ctx.error) return;
  602. if (a.type != "NUMBER") return { type: "NUMBER" };
  603. const b = exec(ctx, ast.values[1]);
  604. if (ctx.error) return;
  605. if (b.type != "NUMBER") return { type: "NUMBER" };
  606. if (!a.value || !b.value) return { type: "NUMBER" };
  607. return {
  608. type: "NUMBER",
  609. value: a.value.eq(b.value) ? bigInt(0) : bigInt(1)
  610. };
  611. }
  612. function execBAnd(ctx, ast) {
  613. const a = exec(ctx, ast.values[0]);
  614. if (ctx.error) return;
  615. if (a.type != "NUMBER") return { type: "NUMBER" };
  616. const b = exec(ctx, ast.values[1]);
  617. if (ctx.error) return;
  618. if (b.type != "NUMBER") return { type: "NUMBER" };
  619. if (!a.value || !b.value) return { type: "NUMBER" };
  620. return {
  621. type: "NUMBER",
  622. value: a.value.and(b.value).and(__MASK__)
  623. };
  624. }
  625. function execAnd(ctx, ast) {
  626. const a = exec(ctx, ast.values[0]);
  627. if (ctx.error) return;
  628. if (a.type != "NUMBER") return { type: "NUMBER" };
  629. const b = exec(ctx, ast.values[1]);
  630. if (ctx.error) return;
  631. if (b.type != "NUMBER") return { type: "NUMBER" };
  632. if (!a.value || !b.value) return { type: "NUMBER" };
  633. return {
  634. type: "NUMBER",
  635. value: (a.value.neq(0) && b.value.neq(0)) ? bigInt(1) : bigInt(0)
  636. };
  637. }
  638. function execOr(ctx, ast) {
  639. const a = exec(ctx, ast.values[0]);
  640. if (ctx.error) return;
  641. if (a.type != "NUMBER") return { type: "NUMBER" };
  642. const b = exec(ctx, ast.values[1]);
  643. if (ctx.error) return;
  644. if (b.type != "NUMBER") return { type: "NUMBER" };
  645. if (!a.value || !b.value) return { type: "NUMBER" };
  646. return {
  647. type: "NUMBER",
  648. value: (a.value.neq(0) || b.value.neq(0)) ? bigInt(1) : bigInt(0)
  649. };
  650. }
  651. function execShl(ctx, ast) {
  652. const a = exec(ctx, ast.values[0]);
  653. if (ctx.error) return;
  654. if (a.type != "NUMBER") return { type: "NUMBER" };
  655. const b = exec(ctx, ast.values[1]);
  656. if (ctx.error) return;
  657. if (b.type != "NUMBER") return { type: "NUMBER" };
  658. if (!a.value || !b.value) return { type: "NUMBER" };
  659. const v = b.value.greater(256) ? 256 : b.value.value;
  660. return {
  661. type: "NUMBER",
  662. value: a.value.shiftLeft(v).and(__MASK__)
  663. };
  664. }
  665. function execShr(ctx, ast) {
  666. const a = exec(ctx, ast.values[0]);
  667. if (ctx.error) return;
  668. if (a.type != "NUMBER") return { type: "NUMBER" };
  669. const b = exec(ctx, ast.values[1]);
  670. if (ctx.error) return;
  671. if (b.type != "NUMBER") return { type: "NUMBER" };
  672. if (!a.value || !b.value) return { type: "NUMBER" };
  673. const v = b.value.greater(256) ? 256 : b.value.value;
  674. return {
  675. type: "NUMBER",
  676. value: a.value.shiftRight(v).and(__MASK__)
  677. };
  678. }
  679. function execMod(ctx, ast) {
  680. const a = exec(ctx, ast.values[0]);
  681. if (ctx.error) return;
  682. if (a.type != "NUMBER") return { type: "NUMBER" };
  683. const b = exec(ctx, ast.values[1]);
  684. if (ctx.error) return;
  685. if (b.type != "NUMBER") return { type: "NUMBER" };
  686. if (!a.value || !b.value) return { type: "NUMBER" };
  687. return {
  688. type: "NUMBER",
  689. value: a.value.mod(b.value)
  690. };
  691. }
  692. function execExp(ctx, ast) {
  693. const a = exec(ctx, ast.values[0]);
  694. if (ctx.error) return;
  695. if (a.type != "NUMBER") return { type: "NUMBER" };
  696. const b = exec(ctx, ast.values[1]);
  697. if (ctx.error) return;
  698. if (b.type != "NUMBER") return { type: "NUMBER" };
  699. if (!a.value || !b.value) return { type: "NUMBER" };
  700. return {
  701. type: "NUMBER",
  702. value: a.value.modPow(b.value, __P__)
  703. };
  704. }
  705. function execDiv(ctx, ast) {
  706. const a = exec(ctx, ast.values[0]);
  707. if (ctx.error) return;
  708. if (a.type != "NUMBER") return { type: "NUMBER" };
  709. const b = exec(ctx, ast.values[1]);
  710. if (ctx.error) return;
  711. if (b.type != "NUMBER") return { type: "NUMBER" };
  712. if (!a.value || !b.value) return { type: "NUMBER" };
  713. if (b.value.isZero()) return error(ctx, ast, "Division by zero");
  714. return {
  715. type: "NUMBER",
  716. value: a.value.times(b.value.modInv(__P__)).mod(__P__)
  717. };
  718. }
  719. function execIDiv(ctx, ast) {
  720. const a = exec(ctx, ast.values[0]);
  721. if (ctx.error) return;
  722. if (a.type != "NUMBER") return { type: "NUMBER" };
  723. const b = exec(ctx, ast.values[1]);
  724. if (ctx.error) return;
  725. if (b.type != "NUMBER") return { type: "NUMBER" };
  726. if (!a.value || !b.value) return { type: "NUMBER" };
  727. if (b.value.isZero()) return error(ctx, ast, "Division by zero");
  728. return {
  729. type: "NUMBER",
  730. value: a.value.divide(b.value)
  731. };
  732. }
  733. function execAdd(ctx, ast) {
  734. const a = exec(ctx, ast.values[0]);
  735. if (ctx.error) return;
  736. const b = exec(ctx, ast.values[1]);
  737. if (ctx.error) return;
  738. const res = lc.add(a,b);
  739. if (res.type == "ERROR") return error(ctx, ast, res.errStr);
  740. return res;
  741. }
  742. function execSub(ctx, ast) {
  743. const a = exec(ctx, ast.values[0]);
  744. if (ctx.error) return;
  745. const b = exec(ctx, ast.values[1]);
  746. if (ctx.error) return;
  747. const res = lc.sub(a,b);
  748. if (res.type == "ERROR") return error(ctx, ast, res.errStr);
  749. return res;
  750. }
  751. function execUMinus(ctx, ast) {
  752. const a = exec(ctx, ast.values[0]);
  753. if (ctx.error) return;
  754. const res = lc.negate(a);
  755. if (res.type == "ERROR") return error(ctx, ast, res.errStr);
  756. return res;
  757. }
  758. function execMul(ctx, ast) {
  759. const a = exec(ctx, ast.values[0]);
  760. if (ctx.error) return;
  761. const b = exec(ctx, ast.values[1]);
  762. if (ctx.error) return;
  763. const res = lc.mul(a,b);
  764. if (res.type == "ERROR") return error(ctx, ast, res.errStr);
  765. return res;
  766. }
  767. function execVarAddAssignement(ctx, ast) {
  768. const res = execAdd(ctx,{ values: [ast.values[0], ast.values[1]] } );
  769. if (ctx.error) return;
  770. return execVarAssignement(ctx, { values: [ast.values[0], res] });
  771. }
  772. function execVarMulAssignement(ctx, ast) {
  773. const res = execMul(ctx,{ values: [ast.values[0], ast.values[1]] } );
  774. if (ctx.error) return;
  775. return execVarAssignement(ctx, { values: [ast.values[0], res] });
  776. }
  777. function execPlusPlusRight(ctx, ast) {
  778. const resBefore = exec(ctx, ast.values[0]);
  779. if (ctx.error) return;
  780. const resAfter = execAdd(ctx,{ values: [ast.values[0], {type: "NUMBER", value: bigInt(1)}] } );
  781. if (ctx.error) return;
  782. execVarAssignement(ctx, { values: [ast.values[0], resAfter] });
  783. return resBefore;
  784. }
  785. function execPlusPlusLeft(ctx, ast) {
  786. if (ctx.error) return;
  787. const resAfter = execAdd(ctx,{ values: [ast.values[0], {type: "NUMBER", value: bigInt(1)}] } );
  788. if (ctx.error) return;
  789. execVarAssignement(ctx, { values: [ast.values[0], resAfter] });
  790. return resAfter;
  791. }
  792. function execMinusMinusRight(ctx, ast) {
  793. const resBefore = exec(ctx, ast.values[0]);
  794. if (ctx.error) return;
  795. const resAfter = execSub(ctx,{ values: [ast.values[0], {type: "NUMBER", value: bigInt(1)}] } );
  796. if (ctx.error) return;
  797. execVarAssignement(ctx, { values: [ast.values[0], resAfter] });
  798. return resBefore;
  799. }
  800. function execMinusMinusLeft(ctx, ast) {
  801. if (ctx.error) return;
  802. const resAfter = execSub(ctx,{ values: [ast.values[0], {type: "NUMBER", value: bigInt(1)}] } );
  803. if (ctx.error) return;
  804. execVarAssignement(ctx, { values: [ast.values[0], resAfter] });
  805. return resAfter;
  806. }
  807. function execTerCon(ctx, ast) {
  808. const cond = exec(ctx, ast.values[0]);
  809. if (ctx.error) return;
  810. if (!cond.value) return { type: "NUMBER" };
  811. if (cond.value.neq(0)) {
  812. return exec(ctx, ast.values[1]);
  813. } else {
  814. return exec(ctx, ast.values[2]);
  815. }
  816. }
  817. function execSignalAssign(ctx, ast) {
  818. let vDest;
  819. if (ast.values[0].type == "DECLARE") {
  820. vDest = exec(ctx, ast.values[0]);
  821. if (ctx.error) return;
  822. } else {
  823. vDest = ast.values[0];
  824. }
  825. let dst;
  826. if (vDest.type == "VARIABLE") {
  827. dst = getScope(ctx, vDest.name, vDest.selectors);
  828. if (ctx.error) return;
  829. } else if (vDest.type == "PIN") {
  830. dst = execPin(ctx, vDest);
  831. if (ctx.error) return;
  832. } else {
  833. error(ctx, ast, "Bad assignement");
  834. }
  835. if (!dst) return error(ctx, ast, "Signal not defined");
  836. if (dst.type != "SIGNAL") return error(ctx, ast, "Signal assigned to a non signal");
  837. let sDest=ctx.signals[dst.fullName];
  838. if (!sDest) return error(ctx, ast, "Invalid signal: "+dst.fullName);
  839. while (sDest.equivalence) sDest=ctx.signals[sDest.equivalence];
  840. if (sDest.value) return error(ctx, ast, "Signals cannot be assigned twice");
  841. let src = exec(ctx, ast.values[1]);
  842. if (ctx.error) return;
  843. /*
  844. let vSrc;
  845. if (ast.values[1].type == "DECLARE") {
  846. vSrc = exec(ctx, ast.values[1]);
  847. if (ctx.error) return;
  848. } else {
  849. vSrc = ast.values[1];
  850. }
  851. if (vSrc.type == "VARIABLE") {
  852. src = getScope(ctx, vSrc.name, vSrc.selectors);
  853. if (!src) error(ctx, ast, "Variable not defined: " + vSrc.name);
  854. if (ctx.error) return;
  855. } else if (vSrc.type == "PIN") {
  856. src = execPin(ctx, vSrc);
  857. }
  858. */
  859. let assignValue = true;
  860. if (src.type == "SIGNAL") {
  861. sDest.equivalence = src.fullName;
  862. sDest.alias = sDest.alias.concat(src.alias);
  863. while (sDest.equivalence) sDest=ctx.signals[sDest.equivalence];
  864. assignValue = false;
  865. }
  866. if (assignValue) {
  867. // const resLC = exec(ctx, vSrc);
  868. if (ctx.error) return;
  869. // const v = lc.evaluate(ctx, resLC);
  870. const v = lc.evaluate(ctx, src);
  871. if (v.value) {
  872. sDest.value = v.value;
  873. }
  874. }
  875. return vDest;
  876. }
  877. function execConstrain(ctx, ast) {
  878. ast.fileName = ctx.fileName;
  879. ast.filePath = ctx.filePath;
  880. const a = exec(ctx, ast.values[0]);
  881. if (ctx.error) return;
  882. const b = exec(ctx, ast.values[1]);
  883. if (ctx.error) return;
  884. const res = lc.sub(a,b);
  885. if (res.type == "ERROR") return error(ctx, ast, res.errStr);
  886. if (!lc.isZero(res)) {
  887. ctx.constraints.push(lc.toQEQ(res));
  888. }
  889. return res;
  890. }
  891. function execSignalAssignConstrain(ctx, ast) {
  892. const v = execSignalAssign(ctx,ast);
  893. if (ctx.error) return;
  894. execConstrain(ctx, ast);
  895. if (ctx.error) return;
  896. return v;
  897. }
  898. function execInclude(ctx, ast) {
  899. const incFileName = path.resolve(ctx.filePath, ast.file);
  900. const incFilePath = path.dirname(incFileName);
  901. ctx.includedFiles = ctx.includedFiles || [];
  902. if (ctx.includedFiles[incFileName]) return;
  903. ctx.includedFiles[incFileName] = true;
  904. const src = fs.readFileSync(incFileName, "utf8");
  905. if (!src) return error(ctx, ast, "Include file not found: "+incFileName);
  906. const incAst = parser.parse(src);
  907. const oldFilePath = ctx.filePath;
  908. const oldFileName = ctx.fileName;
  909. ctx.filePath = incFilePath;
  910. ctx.fileName = incFileName;
  911. exec(ctx, incAst);
  912. ast.block = incAst;
  913. ctx.filePath = oldFilePath;
  914. ctx.fileName = oldFileName;
  915. }
  916. function execArray(ctx, ast) {
  917. const res = [];
  918. for (let i=0; i<ast.values.length; i++) {
  919. res.push(exec(ctx, ast.values[i]));
  920. }
  921. return res;
  922. }
  923. function copyScope(scope) {
  924. var scopesClone = [];
  925. for (let i=0; i<scope.length; i++) {
  926. scopesClone.push(scope[i]);
  927. }
  928. return scopesClone;
  929. }