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        if (v.type != "NUMBER") return error(ctx, fn.params[i], "expected a number");
 322        paramValues.push( v.value);
 323    }
 324    if (template.params.length != paramValues.length) error(ctx, fn, "Invalid Number of parameters");
 325
 326    const vv = getScope(ctx, componentName, vr.selectors);
 327
 328    if (!vv) return error(ctx, vr, "Component not defined"+ componentName);
 329
 330    instantiateComponent(vv);
 331
 332    function instantiateComponent(varVal) {
 333        if (Array.isArray(varVal)) {
 334            for (let i =0; i<varVal.length; i++) {
 335                instantiateComponent(varVal[i]);
 336            }
 337            return;
 338        }
 339
 340        if (ctx.components[varVal.fullName] != "UNINSTANTIATED") error(ctx, fn, "Component already instantiated");
 341
 342        const oldComponent = ctx.currentComponent;
 343        const oldFileName = ctx.fileName;
 344        const oldFilePath = ctx.filePath;
 345        ctx.currentComponent = varVal.fullName;
 346
 347        ctx.components[ctx.currentComponent] = {
 348            signals: [],
 349            params: {}
 350        };
 351
 352        const oldScopes = ctx.scopes;
 353
 354        ctx.scopes = oldScopes.slice(0, scopeLevel+1);
 355
 356        const scope = {};
 357        for (let i=0; i< template.params.length; i++) {
 358            scope[template.params[i]] = {
 359                type: "NUMBER",
 360                value: paramValues[i]
 361            };
 362            ctx.components[ctx.currentComponent].params[template.params[i]] = paramValues[i];
 363        }
 364
 365        ctx.components[ctx.currentComponent].template = templateName;
 366        ctx.fileName = template.fileName;
 367        ctx.filePath = template.filePath;
 368        ctx.scopes = copyScope( template.scopes );
 369        ctx.scopes.push(scope);
 370
 371        execBlock(ctx, template.block);
 372
 373        ctx.fileName = oldFileName;
 374        ctx.filePath = oldFilePath;
 375        ctx.currentComponent = oldComponent;
 376        ctx.scopes = oldScopes;
 377    }
 378}
 379
 380function execFunctionCall(ctx, ast) {
 381
 382    const scopeLevel = getScopeLevel(ctx, ast.name);
 383    if (scopeLevel == -1) return error(ctx, ast, "Function not defined: " + ast.name);
 384    const fnc = getScope(ctx, ast.name);
 385
 386    if (fnc.type != "FUNCTION") return error(ctx, ast, "Not a function: " + ast.name);
 387
 388    const paramValues = [];
 389    for (let i=0; i< ast.params.length; i++) {
 390        const v = exec(ctx, ast.params[i]);
 391        if (ctx.error) return;
 392
 393        paramValues.push(v);
 394    }
 395
 396    if (ast.params.length != paramValues.length) error(ctx, ast, "Invalid Number of parameters");
 397
 398    const oldFileName = ctx.fileName;
 399    const oldFilePath = ctx.filePath;
 400
 401    const oldScopes = ctx.scopes;
 402
 403    ctx.scopes = oldScopes.slice(0, scopeLevel+1);
 404
 405    const scope = {};
 406    for (let i=0; i< fnc.params.length; i++) {
 407        scope[fnc.params[i]] = paramValues[i];
 408    }
 409
 410    ctx.fileName = fnc.fileName;
 411    ctx.filePath = fnc.filePath;
 412    ctx.scopes = copyScope( fnc.scopes );
 413    ctx.scopes.push(scope);
 414
 415    execBlock(ctx, fnc.block);
 416
 417    const res = ctx.returnValue;
 418    ctx.returnValue = null;
 419
 420    ctx.fileName = oldFileName;
 421    ctx.filePath = oldFilePath;
 422    ctx.scopes = oldScopes;
 423
 424    return res;
 425}
 426
 427function execReturn(ctx, ast) {
 428    ctx.returnValue = exec(ctx, ast.value);
 429    return;
 430}
 431
 432function execDeclareSignal(ctx, ast) {
 433    const scope = ctx.scopes[ctx.scopes.length-1];
 434
 435    if (ast.name.type != "VARIABLE") return error(ctx, ast, "Invalid component name");
 436    if (getScope(ctx, ast.name.name)) return error(ctx, ast, "Name already exists: "+ast.name.name);
 437
 438    const baseName = ctx.currentComponent ? ctx.currentComponent + "." + ast.name.name : ast.name.name;
 439
 440    const sizes=[];
 441    for (let i=0; i< ast.name.selectors.length; i++) {
 442        const size = exec(ctx, ast.name.selectors[i]);
 443        if (ctx.error) return;
 444
 445        if (size.type != "NUMBER") return error(ctx, ast.name.selectors[i], "expected a number");
 446        sizes.push( size.value.toJSNumber() );
 447    }
 448
 449    scope[ast.name.name] = iterateSelectors(ctx, sizes, baseName, function(fullName) {
 450        ctx.signals[fullName] = {
 451            fullName: fullName,
 452            direction: ast.declareType == "SIGNALIN" ? "IN" : (ast.declareType == "SIGNALOUT" ? "OUT" : ""),
 453            private: ast.private,
 454            component: ctx.currentComponent,
 455            equivalence: "",
 456            alias: [fullName]
 457        };
 458        ctx.components[ctx.currentComponent].signals.push(fullName);
 459        return {
 460            type: "SIGNAL",
 461            fullName: fullName,
 462        };
 463    });
 464    return {
 465        type: "VARIABLE",
 466        name: ast.name.name,
 467        selectors: []
 468    };
 469}
 470
 471function execDeclareVariable(ctx, ast) {
 472    const scope = ctx.scopes[ctx.scopes.length-1];
 473
 474    if (ast.name.type != "VARIABLE") return error(ctx, ast, "Invalid linear combination name");
 475    if (getScope(ctx, ast.name.name)) return error(ctx, ast, "Name already exists: "+ast.name.name);
 476
 477    const sizes=[];
 478    for (let i=0; i< ast.name.selectors.length; i++) {
 479        const size = exec(ctx, ast.name.selectors[i]);
 480        if (ctx.error) return;
 481
 482        if (size.type != "NUMBER") return error(ctx, ast.name.selectors[i], "expected a number");
 483        sizes.push( size.value.toJSNumber() );
 484    }
 485
 486    scope[ast.name.name] = iterateSelectors(ctx, sizes, "", function() {
 487        return {
 488            type: "NUMBER",
 489            value: bigInt(0)
 490        };
 491    });
 492
 493    return {
 494        type: "VARIABLE",
 495        name: ast.name.name,
 496        selectors: []
 497    };
 498}
 499
 500function execVariable(ctx, ast) {
 501    let v;
 502    try {
 503        v = getScope(ctx, ast.name, ast.selectors);
 504    } catch(err) {
 505        console.log(JSON.stringify(ast, null,1));
 506    }
 507    if (ctx.error) return;
 508
 509    if (!v) return error(ctx, ast, "Variable not defined");
 510
 511    // If the signal has an assigned value (constant) just return the constant
 512    if ((v.type == "SIGNAL") && (ctx.signals[v.fullName].value)) {
 513        return {
 514            type: "NUMBER",
 515            value: ctx.signals[v.fullName].value
 516        };
 517    }
 518    let res;
 519    res=v;
 520    return res;
 521}
 522
 523function execPin(ctx, ast) {
 524    const component = getScope(ctx, ast.component.name, ast.component.selectors);
 525    if (!component) return error(ctx, ast.component, "Component does not exists: "+ast.component.name);
 526    if (ctx.error) return;
 527    let signalFullName = component.fullName + "." + ast.pin.name;
 528    for (let i=0; i< ast.pin.selectors.length; i++) {
 529        const sel = exec(ctx, ast.pin.selectors[i]);
 530        if (ctx.error) return;
 531
 532        if (sel.type != "NUMBER") return error(ctx, ast.pin.selectors[i], "expected a number");
 533
 534        signalFullName += "[" + sel.value.toJSNumber() + "]";
 535    }
 536    if (!ctx.signals[signalFullName]) error(ctx, ast, "Signal not defined:" + signalFullName);
 537    return {
 538        type: "SIGNAL",
 539        fullName: signalFullName
 540    };
 541}
 542
 543function execFor(ctx, ast) {
 544    exec(ctx, ast.init);
 545    if (ctx.error) return;
 546
 547    let v = exec(ctx, ast.condition);
 548    if (ctx.error) return;
 549
 550    if (typeof v.value != "undefined") {
 551        while ((v.value.neq(0))&&(!ctx.returnValue)) {
 552            exec(ctx, ast.body);
 553            if (ctx.error) return;
 554
 555            exec(ctx, ast.step);
 556            if (ctx.error) return;
 557
 558            v = exec(ctx, ast.condition);
 559            if (ctx.error) return;
 560        }
 561    }
 562}
 563
 564function execWhile(ctx, ast) {
 565    let v = exec(ctx, ast.condition);
 566    if (ctx.error) return;
 567
 568    if (typeof v.value != "undefined") {
 569        while ((v.value.neq(0))&&(!ctx.returnValue)) {
 570            exec(ctx, ast.body);
 571            if (ctx.error) return;
 572
 573            v = exec(ctx, ast.condition);
 574            if (ctx.error) return;
 575        }
 576    }
 577}
 578
 579function execIf(ctx, ast) {
 580    let v = exec(ctx, ast.condition);
 581    if (ctx.error) return;
 582
 583    if (typeof v.value != "undefined") {
 584        if ((v.value.neq(0))&&(!ctx.returnValue)) {
 585            exec(ctx, ast.then);
 586            if (ctx.error) return;
 587        } else {
 588            if (ast.else) {
 589                exec(ctx, ast.else);
 590                if (ctx.error) return;
 591            }
 592        }
 593    }
 594}
 595
 596
 597function execVarAssignement(ctx, ast) {
 598    let v;
 599    if (ast.values[0].type == "DECLARE") {
 600        v = exec(ctx, ast.values[0]);
 601        if (ctx.error) return;
 602    } else {
 603        v = ast.values[0];
 604    }
 605    const num = getScope(ctx, v.name, v.selectors);
 606    if (ctx.error) return;
 607
 608    if ((typeof(num) != "object")||(num == null)) return  error(ctx, ast, "Variable not defined");
 609
 610    if (num.type == "COMPONENT") return execInstantiateComponet(ctx, v, ast.values[1]);
 611
 612    const res = exec(ctx, ast.values[1]);
 613    if (ctx.error) return;
 614
 615    setScope(ctx, v.name, v.selectors, res);
 616
 617    return v;
 618}
 619
 620function execLt(ctx, ast) {
 621    const a = exec(ctx, ast.values[0]);
 622    if (ctx.error) return;
 623    if (a.type != "NUMBER") return { type: "NUMBER" };
 624    const b = exec(ctx, ast.values[1]);
 625    if (ctx.error) return;
 626    if (b.type != "NUMBER") return { type: "NUMBER" };
 627    if (!a.value || !b.value) return { type: "NUMBER" };
 628    return {
 629        type: "NUMBER",
 630        value: a.value.lt(b.value) ? bigInt(1) : bigInt(0)
 631    };
 632}
 633
 634function execGt(ctx, ast) {
 635    const a = exec(ctx, ast.values[0]);
 636    if (ctx.error) return;
 637    if (a.type != "NUMBER") return { type: "NUMBER" };
 638    const b = exec(ctx, ast.values[1]);
 639    if (ctx.error) return;
 640    if (b.type != "NUMBER") return { type: "NUMBER" };
 641    if (!a.value || !b.value) return { type: "NUMBER" };
 642    return {
 643        type: "NUMBER",
 644        value: a.value.gt(b.value) ? bigInt(1) : bigInt(0)
 645    };
 646}
 647
 648function execLte(ctx, ast) {
 649    const a = exec(ctx, ast.values[0]);
 650    if (ctx.error) return;
 651    if (a.type != "NUMBER") return { type: "NUMBER" };
 652    const b = exec(ctx, ast.values[1]);
 653    if (ctx.error) return;
 654    if (b.type != "NUMBER") return { type: "NUMBER" };
 655    if (!a.value || !b.value) return { type: "NUMBER" };
 656    return {
 657        type: "NUMBER",
 658        value: a.value.lesserOrEquals(b.value) ? bigInt(1) : bigInt(0)
 659    };
 660}
 661
 662function execGte(ctx, ast) {
 663    const a = exec(ctx, ast.values[0]);
 664    if (ctx.error) return;
 665    if (a.type != "NUMBER") return { type: "NUMBER" };
 666    const b = exec(ctx, ast.values[1]);
 667    if (ctx.error) return;
 668    if (b.type != "NUMBER") return { type: "NUMBER" };
 669    if (!a.value || !b.value) return { type: "NUMBER" };
 670    return {
 671        type: "NUMBER",
 672        value: a.value.greaterOrEquals(b.value) ? bigInt(1) : bigInt(0)
 673    };
 674}
 675
 676
 677function execEq(ctx, ast) {
 678    const a = exec(ctx, ast.values[0]);
 679    if (ctx.error) return;
 680    if (a.type != "NUMBER") return { type: "NUMBER" };
 681    const b = exec(ctx, ast.values[1]);
 682    if (ctx.error) return;
 683    if (b.type != "NUMBER") return { type: "NUMBER" };
 684    if (!a.value || !b.value) return { type: "NUMBER" };
 685    return {
 686        type: "NUMBER",
 687        value: a.value.eq(b.value) ? bigInt(1) : bigInt(0)
 688    };
 689}
 690
 691function execNeq(ctx, ast) {
 692    const a = exec(ctx, ast.values[0]);
 693    if (ctx.error) return;
 694    if (a.type != "NUMBER") return { type: "NUMBER" };
 695    const b = exec(ctx, ast.values[1]);
 696    if (ctx.error) return;
 697    if (b.type != "NUMBER") return { type: "NUMBER" };
 698    if (!a.value || !b.value) return { type: "NUMBER" };
 699    return {
 700        type: "NUMBER",
 701        value: a.value.eq(b.value) ? bigInt(0) : bigInt(1)
 702    };
 703}
 704
 705
 706function execBAnd(ctx, ast) {
 707    const a = exec(ctx, ast.values[0]);
 708    if (ctx.error) return;
 709    if (a.type != "NUMBER") return { type: "NUMBER" };
 710    const b = exec(ctx, ast.values[1]);
 711    if (ctx.error) return;
 712    if (b.type != "NUMBER") return { type: "NUMBER" };
 713    if (!a.value || !b.value) return { type: "NUMBER" };
 714    return {
 715        type: "NUMBER",
 716        value: a.value.and(b.value).and(__MASK__)
 717    };
 718}
 719
 720function execShl(ctx, ast) {
 721    const a = exec(ctx, ast.values[0]);
 722    if (ctx.error) return;
 723    if (a.type != "NUMBER") return { type: "NUMBER" };
 724    const b = exec(ctx, ast.values[1]);
 725    if (ctx.error) return;
 726    if (b.type != "NUMBER") return { type: "NUMBER" };
 727    if (!a.value || !b.value) return { type: "NUMBER" };
 728    const v = b.value.greater(256) ? 256 : b.value.value;
 729    return {
 730        type: "NUMBER",
 731        value: a.value.shiftLeft(v).and(__MASK__)
 732    };
 733}
 734
 735function execShr(ctx, ast) {
 736    const a = exec(ctx, ast.values[0]);
 737    if (ctx.error) return;
 738    if (a.type != "NUMBER") return { type: "NUMBER" };
 739    const b = exec(ctx, ast.values[1]);
 740    if (ctx.error) return;
 741    if (b.type != "NUMBER") return { type: "NUMBER" };
 742    if (!a.value || !b.value) return { type: "NUMBER" };
 743    const v = b.value.greater(256) ? 256 : b.value.value;
 744    return {
 745        type: "NUMBER",
 746        value: a.value.shiftRight(v).and(__MASK__)
 747    };
 748}
 749
 750function execMod(ctx, ast) {
 751    const a = exec(ctx, ast.values[0]);
 752    if (ctx.error) return;
 753    if (a.type != "NUMBER") return { type: "NUMBER" };
 754    const b = exec(ctx, ast.values[1]);
 755    if (ctx.error) return;
 756    if (b.type != "NUMBER") return { type: "NUMBER" };
 757    if (!a.value || !b.value) return { type: "NUMBER" };
 758    return {
 759        type: "NUMBER",
 760        value: a.value.mod(b.value)
 761    };
 762}
 763
 764
 765function execExp(ctx, ast) {
 766    const a = exec(ctx, ast.values[0]);
 767    if (ctx.error) return;
 768    if (a.type != "NUMBER") return { type: "NUMBER" };
 769    const b = exec(ctx, ast.values[1]);
 770    if (ctx.error) return;
 771    if (b.type != "NUMBER") return { type: "NUMBER" };
 772    if (!a.value || !b.value) return { type: "NUMBER" };
 773    return {
 774        type: "NUMBER",
 775        value: a.value.modPow(b.value, __P__)
 776    };
 777}
 778
 779function execDiv(ctx, ast) {
 780    const a = exec(ctx, ast.values[0]);
 781    if (ctx.error) return;
 782    if (a.type != "NUMBER") return { type: "NUMBER" };
 783    const b = exec(ctx, ast.values[1]);
 784    if (ctx.error) return;
 785    if (b.type != "NUMBER") return { type: "NUMBER" };
 786    if (!a.value || !b.value) return { type: "NUMBER" };
 787    if (b.value.isZero()) return error(ctx, ast, "Division by zero");
 788    return {
 789        type: "NUMBER",
 790        value: a.value.times(b.value.modInv(__P__)).mod(__P__)
 791    };
 792}
 793
 794function execAdd(ctx, ast) {
 795    const a = exec(ctx, ast.values[0]);
 796    if (ctx.error) return;
 797    const b = exec(ctx, ast.values[1]);
 798    if (ctx.error) return;
 799
 800    const res = lc.add(a,b);
 801    if (res.type == "ERROR") return error(ctx, ast, res.errStr);
 802
 803    return res;
 804}
 805
 806function execSub(ctx, ast) {
 807    const a = exec(ctx, ast.values[0]);
 808    if (ctx.error) return;
 809    const b = exec(ctx, ast.values[1]);
 810    if (ctx.error) return;
 811
 812    const res = lc.sub(a,b);
 813    if (res.type == "ERROR") return error(ctx, ast, res.errStr);
 814
 815    return res;
 816}
 817
 818function execUMinus(ctx, ast) {
 819    const a = exec(ctx, ast.values[0]);
 820    if (ctx.error) return;
 821
 822    const res = lc.negate(a);
 823    if (res.type == "ERROR") return error(ctx, ast, res.errStr);
 824
 825    return res;
 826}
 827
 828function execMul(ctx, ast) {
 829    const a = exec(ctx, ast.values[0]);
 830    if (ctx.error) return;
 831    const b = exec(ctx, ast.values[1]);
 832    if (ctx.error) return;
 833
 834    const res = lc.mul(a,b);
 835    if (res.type == "ERROR") return error(ctx, ast, res.errStr);
 836
 837    return res;
 838}
 839
 840
 841function execVarAddAssignement(ctx, ast) {
 842    const res = execAdd(ctx,{ values: [ast.values[0], ast.values[1]] } );
 843    if (ctx.error) return;
 844    return execVarAssignement(ctx, { values: [ast.values[0], res] });
 845}
 846
 847function execVarMulAssignement(ctx, ast) {
 848    const res = execMul(ctx,{ values: [ast.values[0], ast.values[1]] } );
 849    if (ctx.error) return;
 850    return execVarAssignement(ctx, { values: [ast.values[0], res] });
 851}
 852
 853function execPlusPlusRight(ctx, ast) {
 854    const resBefore = exec(ctx, ast.values[0]);
 855    if (ctx.error) return;
 856    const resAfter = execAdd(ctx,{ values: [ast.values[0], {type: "NUMBER", value: bigInt(1)}] } );
 857    if (ctx.error) return;
 858    execVarAssignement(ctx, { values: [ast.values[0], resAfter] });
 859    return resBefore;
 860}
 861
 862function execPlusPlusLeft(ctx, ast) {
 863    if (ctx.error) return;
 864    const resAfter = execAdd(ctx,{ values: [ast.values[0], {type: "NUMBER", value: bigInt(1)}] } );
 865    if (ctx.error) return;
 866    execVarAssignement(ctx, { values: [ast.values[0], resAfter] });
 867    return resAfter;
 868}
 869
 870function execTerCon(ctx, ast) {
 871    const cond = exec(ctx, ast.values[0]);
 872    if (ctx.error) return;
 873
 874    if (!cond.value) return { type: "NUMBER" };
 875
 876    if (cond.value.neq(0)) {
 877        return exec(ctx, ast.values[1]);
 878    } else {
 879        return exec(ctx, ast.values[2]);
 880    }
 881}
 882
 883function execSignalAssign(ctx, ast) {
 884    let vDest;
 885    if (ast.values[0].type == "DECLARE") {
 886        vDest = exec(ctx, ast.values[0]);
 887        if (ctx.error) return;
 888    } else {
 889        vDest = ast.values[0];
 890    }
 891
 892    let dst;
 893    if (vDest.type == "VARIABLE") {
 894        dst = getScope(ctx, vDest.name, vDest.selectors);
 895        if (ctx.error) return;
 896    } else if (vDest.type == "PIN") {
 897        dst = execPin(ctx, vDest);
 898        if (ctx.error) return;
 899    } else {
 900        error(ctx, ast, "Bad assignement");
 901    }
 902
 903    if (!dst) return  error(ctx, ast, "Signal not defined");
 904    if (dst.type != "SIGNAL") return  error(ctx, ast, "Signal assigned to a non signal");
 905
 906    let sDest=ctx.signals[dst.fullName];
 907    if (!sDest) return error(ctx, ast, "Invalid signal: "+dst.fullName);
 908    while (sDest.equivalence) sDest=ctx.signals[sDest.equivalence];
 909
 910    if (sDest.value) return error(ctx, ast, "Signals cannot be assigned twice");
 911
 912    let src = exec(ctx, ast.values[1]);
 913    if (ctx.error) return;
 914
 915
 916    /*
 917    let vSrc;
 918    if (ast.values[1].type == "DECLARE") {
 919        vSrc = exec(ctx, ast.values[1]);
 920        if (ctx.error) return;
 921    } else {
 922        vSrc = ast.values[1];
 923    }
 924
 925    if (vSrc.type == "VARIABLE") {
 926        src = getScope(ctx, vSrc.name, vSrc.selectors);
 927        if (!src) error(ctx, ast, "Variable not defined: " + vSrc.name);
 928        if (ctx.error) return;
 929    } else if (vSrc.type == "PIN") {
 930        src = execPin(ctx, vSrc);
 931    }
 932    */
 933
 934    let assignValue = true;
 935    if (src.type == "SIGNAL") {
 936        sDest.equivalence = src.fullName;
 937        sDest.alias = sDest.alias.concat(src.alias);
 938        while (sDest.equivalence) sDest=ctx.signals[sDest.equivalence];
 939        assignValue = false;
 940    }
 941
 942    if (assignValue) {
 943        //        const resLC = exec(ctx, vSrc);
 944        if (ctx.error) return;
 945
 946        //        const v = lc.evaluate(ctx, resLC);
 947        const v = lc.evaluate(ctx, src);
 948
 949        if (v.value) {
 950            sDest.value = v.value;
 951        }
 952    }
 953
 954    return vDest;
 955}
 956
 957function execConstrain(ctx, ast) {
 958    const a = exec(ctx, ast.values[0]);
 959    if (ctx.error) return;
 960    const b = exec(ctx, ast.values[1]);
 961    if (ctx.error) return;
 962
 963    const res = lc.sub(a,b);
 964    if (res.type == "ERROR") return error(ctx, ast, res.errStr);
 965
 966    if (!lc.isZero(res)) {
 967        ctx.constraints.push(lc.toQEQ(res));
 968    }
 969
 970    return res;
 971}
 972
 973function execSignalAssignConstrain(ctx, ast) {
 974    const v = execSignalAssign(ctx,ast);
 975    if (ctx.error) return;
 976    execConstrain(ctx, ast);
 977    if (ctx.error) return;
 978    return v;
 979}
 980
 981function execInclude(ctx, ast) {
 982    const incFileName = path.resolve(ctx.filePath, ast.file);
 983    const incFilePath = path.dirname(incFileName);
 984
 985    ctx.includedFiles = ctx.includedFiles || [];
 986    if (ctx.includedFiles[incFileName]) return;
 987
 988    ctx.includedFiles[incFileName] = true;
 989
 990    const src = fs.readFileSync(incFileName, "utf8");
 991
 992    if (!src) return error(ctx, ast, "Include file not found: "+incFileName);
 993
 994    const incAst = parser.parse(src);
 995
 996    const oldFilePath = ctx.filePath;
 997    const oldFileName = ctx.fileName;
 998    ctx.filePath = incFilePath;
 999    ctx.fileName = incFileName;
1000
1001    exec(ctx, incAst);
1002
1003    ast.block = incAst;
1004
1005    ctx.filePath = oldFilePath;
1006    ctx.fileName = oldFileName;
1007}
1008
1009function execArray(ctx, ast) {
1010    const res = [];
1011
1012    for (let i=0; i<ast.values.length; i++) {
1013        res.push(exec(ctx, ast.values[i]));
1014    }
1015
1016    return res;
1017}
1018
1019function copyScope(scope) {
1020    var scopesClone = [];
1021    for (let i=0; i<scope.length; i++) {
1022        scopesClone.push(scope[i]);
1023    }
1024    return scopesClone;
1025}
1026