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