/* Copyright 2018 0KIMS association. This file is part of circom (Zero Knowledge Circuit Compiler). circom is a free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. circom is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with circom. If not, see . */ const path = require("path"); const fs = require("fs"); const bigInt = require("big-integer"); const __P__ = new bigInt("21888242871839275222246405745257275088548364400416034343698204186575808495617"); const __MASK__ = new bigInt(2).pow(253).minus(1); const lc = require("./lcalgebra"); const parser = require("../parser/jaz.js").parser; /* TODO: Add lines information function setLines(dst, first, last) { last = last || first; dst.first_line = first.first_line; dst.first_column = first.first_column; dst.last_line = last.last_line; dst.last_column = last.last_column; } */ module.exports = exec; function exec(ctx, ast) { if (!ast) { return error(ctx, ast, "Null AST"); } if ((ast.type == "NUMBER") || (ast.type == "LINEARCOMBINATION") || (ast.type =="SIGNAL") || (ast.type == "QEQ")) { return ast; } else if (ast.type == "VARIABLE") { return execVariable(ctx, ast); } else if (ast.type == "PIN") { return execPin(ctx, ast); } else if (ast.type == "OP") { if (ast.op == "=") { return execVarAssignement(ctx, ast); } else if (ast.op == "<--") { return execSignalAssign(ctx, ast); } else if (ast.op == "<==") { return execSignalAssignConstrain(ctx, ast); } else if (ast.op == "===") { return execConstrain(ctx, ast); } else if (ast.op == "+=") { return execVarAddAssignement(ctx, ast); } else if (ast.op == "*=") { return execVarMulAssignement(ctx, ast); } else if (ast.op == "+") { return execAdd(ctx, ast); } else if (ast.op == "-") { return execSub(ctx, ast); } else if (ast.op == "UMINUS") { return execUMinus(ctx, ast); } else if (ast.op == "*") { return execMul(ctx, ast); } else if (ast.op == "%") { return execMod(ctx, ast); } else if (ast.op == "PLUSPLUSRIGHT") { return execPlusPlusRight(ctx, ast); } else if (ast.op == "PLUSPLUSLEFT") { return execPlusPlusLeft(ctx, ast); } else if (ast.op == "MINUSMINUSRIGHT") { return execMinusMinusRight(ctx, ast); } else if (ast.op == "MINUSMINUSLEFT") { return execMinusMinusLeft(ctx, ast); } else if (ast.op == "/") { return execDiv(ctx, ast); } else if (ast.op == "\\") { return execIDiv(ctx, ast); } else if (ast.op == "**") { return execExp(ctx, ast); } else if (ast.op == "&") { return execBAnd(ctx, ast); } else if (ast.op == "&&") { return execAnd(ctx, ast); } else if (ast.op == "||") { return execOr(ctx, ast); } else if (ast.op == "<<") { return execShl(ctx, ast); } else if (ast.op == ">>") { return execShr(ctx, ast); } else if (ast.op == "<") { return execLt(ctx, ast); } else if (ast.op == ">") { return execGt(ctx, ast); } else if (ast.op == "<=") { return execLte(ctx, ast); } else if (ast.op == ">=") { return execGte(ctx, ast); } else if (ast.op == "==") { return execEq(ctx, ast); } else if (ast.op == "!=") { return execNeq(ctx, ast); } else if (ast.op == "?") { return execTerCon(ctx, ast); } else { error(ctx, ast, "Invalid operation: " + ast.op); } } else if (ast.type == "DECLARE") { if (ast.declareType == "COMPONENT") { return execDeclareComponent(ctx, ast); } else if ((ast.declareType == "SIGNALIN")|| (ast.declareType == "SIGNALOUT")|| (ast.declareType == "SIGNAL")) { return execDeclareSignal(ctx, ast); } else if (ast.declareType == "VARIABLE") { return execDeclareVariable(ctx, ast); } else { error(ctx, ast, "Invalid declaration: " + ast.declareType); } } else if (ast.type == "FUNCTIONCALL") { return execFunctionCall(ctx, ast); } else if (ast.type == "BLOCK") { return execBlock(ctx, ast); } else if (ast.type == "COMPUTE") { return ; } else if (ast.type == "FOR") { return execFor(ctx, ast); } else if (ast.type == "WHILE") { return execWhile(ctx, ast); } else if (ast.type == "IF") { return execIf(ctx, ast); } else if (ast.type == "RETURN") { return execReturn(ctx, ast); } else if (ast.type == "TEMPLATEDEF") { return execTemplateDef(ctx, ast); } else if (ast.type == "FUNCTIONDEF") { return execFunctionDef(ctx, ast); } else if (ast.type == "INCLUDE") { return execInclude(ctx, ast); } else if (ast.type == "ARRAY") { return execArray(ctx, ast); } else { error(ctx, ast, "Invalid AST node type: " + ast.type); } } function error(ctx, ast, errStr) { ctx.error = { pos: { first_line: ast.first_line, first_column: ast.first_column, last_line: ast.last_line, last_column: ast.last_column }, errStr: errStr, errFile: ctx.fileName, ast: ast, message: errStr }; } function iterateSelectors(ctx, sizes, baseName, fn) { if (sizes.length == 0) { return fn(baseName); } const res = []; for (let i=0; i=0; i--) { if (ctx.scopes[i][name]) return select(ctx.scopes[i][name], sels); } return null; } function getScopeLevel(ctx, name) { for (let i=ctx.scopes.length-1; i>=0; i--) { if (ctx.scopes[i][name]) return i; } return -1; } function execBlock(ctx, ast) { for (let i=0; i