├── .gitignore ├── LICENSE ├── README.md ├── doc ├── Expressions.md ├── Identifiers.md ├── Statements.md └── Typess.md └── src ├── BinaryOperation.cpp ├── BinaryOperation.h ├── Bits.h ├── BuildContext.cpp ├── BuildContext.h ├── Circuit.cpp ├── Circuit.h ├── CodeBloc.cpp ├── CodeBloc.h ├── Compiler.cpp ├── Compiler.h ├── CompositedGate.cpp ├── CompositedGate.h ├── Connection.cpp ├── Connection.h ├── Error.h ├── Expression.cpp ├── Expression.h ├── Expression_ArrayElement.cpp ├── Expression_ArrayElement.h ├── Expression_StructMember.cpp ├── Expression_StructMember.h ├── Expression_Variable.cpp ├── Expression_Variable.h ├── Function.cpp ├── Function.h ├── Gate.h ├── IGate.h ├── InterfaceInputsMap.h ├── LangageAttributes.cpp ├── LangageAttributes.h ├── LangageGrammar.cpp ├── LangageGrammar.h ├── Literal.cpp ├── Literal.h ├── Main.cpp ├── ParsingContext.cpp ├── ParsingContext.h ├── Program.cpp ├── Program.h ├── Scope.cpp ├── Scope.h ├── ScopeVariable.cpp ├── ScopeVariable.h ├── ShiftOperation.cpp ├── ShiftOperation.h ├── Statement.h ├── Statement_Break.cpp ├── Statement_Break.h ├── Statement_DeclareAndSetVar.cpp ├── Statement_DeclareAndSetVar.h ├── Statement_DeclareStruct.cpp ├── Statement_DeclareStruct.h ├── Statement_DeclareVar.cpp ├── Statement_DeclareVar.h ├── Statement_For.cpp ├── Statement_For.h ├── Statement_Function_Call.cpp ├── Statement_Function_Call.h ├── Statement_If.cpp ├── Statement_If.h ├── Statement_Increment.cpp ├── Statement_Increment.h ├── Statement_Return.cpp ├── Statement_Return.h ├── Statement_SetVar.cpp ├── Statement_SetVar.h ├── TapScriptGate.cpp ├── TapScriptGate.h ├── Test.cpp ├── Test.h ├── TestOperation.cpp ├── TestOperation.h ├── TokenId.h ├── Type.cpp ├── Type.h ├── TypeArray.cpp ├── TypeArray.h ├── TypeStruct.cpp ├── TypeStruct.h ├── UnaryOperation.cpp ├── UnaryOperation.h ├── VariableDefinition.h ├── bitcoin-bitvm-compiler.sln ├── bitcoin-bitvm-compiler.vcxproj ├── bitcoin-bitvm-compiler.vcxproj.filters ├── export.txt ├── sample ├── hello_word.bvc ├── test_add.bvc ├── test_and.bvc ├── test_array.bvc ├── test_array_2.bvc ├── test_array_3.bvc ├── test_complement.bvc ├── test_declare_and_set.bvc ├── test_decrement.bvc ├── test_equal_bool.bvc ├── test_equal_int8.bvc ├── test_for.bvc ├── test_greater.bvc ├── test_greater_or_equal.bvc ├── test_if.bvc ├── test_if_and_stuct.bvc ├── test_include.bvc ├── test_include.bvh ├── test_increment.bvc ├── test_int256.bvc ├── test_int32.bvc ├── test_int64.bvc ├── test_int8.bvc ├── test_literal.bvc ├── test_local_var.bvc ├── test_lower.bvc ├── test_lower_or_equal.bvc ├── test_negate.bvc ├── test_not.bvc ├── test_notequal_int8.bvc ├── test_or.bvc ├── test_parenthesis.bvc ├── test_precedencec.bvc ├── test_proc.bvc ├── test_shit_left.bvc ├── test_shit_right.bvc ├── test_struct.bvc ├── test_sub.bvc └── test_xor.bvc └── test.out /.gitignore: -------------------------------------------------------------------------------- 1 | src/.vs 2 | /x64 3 | *.user 4 | *.tlog 5 | *.log 6 | *.obj 7 | *.exe 8 | *.pdb 9 | *.idb -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # bitcoin-bitvm-compiler 2 | 3 | Generate one or more logical circuits for BitVM Bitcoin from a C like source code 4 | 5 | 6 | ## Example : 7 | 8 | ```c 9 | // simple test program 10 | int8 main(int8 a, int8 b) 11 | { 12 | int8 local_a_and_b = a & b; 13 | return local_a_and_b; 14 | } 15 | ``` 16 | 17 | Generate the circuit(s) with : 18 | ``` 19 | bitvmcompiler.exe source.bvc export.txt 20 | ``` 21 | 22 | Output : 23 | ``` 24 | 16 16 25 | 16 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 26 | 8 17 19 21 23 25 27 29 31 27 | 1 16 1 0 8 NAND 28 | 1 17 1 16 16 NAND 29 | 1 18 1 1 9 NAND 30 | 1 19 1 18 18 NAND 31 | 1 20 1 2 10 NAND 32 | 1 21 1 20 20 NAND 33 | 1 22 1 3 11 NAND 34 | 1 23 1 22 22 NAND 35 | 1 24 1 4 12 NAND 36 | 1 25 1 24 24 NAND 37 | 1 26 1 5 13 NAND 38 | 1 27 1 26 26 NAND 39 | 1 28 1 6 14 NAND 40 | 1 29 1 28 28 NAND 41 | 1 30 1 7 15 NAND 42 | 1 31 1 30 30 NAND 43 | 44 | ``` 45 | 46 | ## Testing 47 | 48 | The circuit can be tested with -run 49 | ex: 50 | ```Batchfile 51 | bitvmcompiler.exe test_int8.bvc -run a=0x73,b=0x5F 52 | ``` 53 | Output : 54 | ``` 55 | Running with : a=0x73,b=0x5F 56 | Simulation result : 0x53 57 | ``` 58 | 59 | Tested and build with Visual Studio 2022 60 | 61 | # Notes 62 | 63 | Bits are in low endian (x86 format) 64 | 65 | # Current todo list : 66 | 67 | - function call ... in progress... 68 | - #include support ... in progress... 69 | - set a limit to the number of gates 70 | - operators : \* / % 71 | - basic function stdlib (sha256, shnor, min, max,... ) 72 | - write a better language documentation 73 | - linux : create a makefile 74 | - wasm support and browser demo site 75 | - check for unused inputs instead of a "no more gates" error 76 | - optimize the generated circuit (use less gates) 77 | - better syntax error messages 78 | - += operator 79 | - save the build circuit in a file, and load it for execution / generation 80 | -------------------------------------------------------------------------------- /doc/Expressions.md: -------------------------------------------------------------------------------- 1 | # Expressions 2 | 3 | An expression is a sequence of operators and their operands 4 | 5 | Expressions can be composed of variables, literals, operators and parenthesis. 6 | 7 | ex : 8 | ```c 9 | local_var + 1 10 | var1 - var2 + var3 11 | (var1 > 1) & (var3 < 2) 12 | ``` 13 | 14 | The following operators are curently supported 15 | 16 | |operator | description | operand type | result | 17 | |---------|----------------|--------------|--------------| 18 | |! |boolean not | int or bool | int or bool | 19 | |& |logical and | int or bool | int or bool | 20 | || |logical or | int or bool | int or bool | 21 | |^ |logical xor | int or bool | int or bool | 22 | |< |lower | int | bool | 23 | |<= |lower or equal | int | bool | 24 | |> |greater | int | bool | 25 | |>= |greater or equal| int | bool | 26 | |<< |bit shit left | int | int | 27 | |>> |bit shit right | int | int | 28 | |+ |addition | int | int | 29 | |- |substaction | int | int | 30 | 31 | operator precedence is the same as C/C++ 32 | 33 | -------------------------------------------------------------------------------- /doc/Identifiers.md: -------------------------------------------------------------------------------- 1 | # Identifiers 2 | 3 | variable names anc be any mix of letters, numbers and underscores, but must start with a letter or underscore. 4 | ex : ``my_var, _my_var, myVar, myVar1, my_var_1 5 | 6 | User defined types must start with an Uppercase char 7 | ex: ``Header STParam My_struct 8 | 9 | Variables names must start whit a lowercase char 10 | ex: ``header stParam my_Struct myParam 11 | -------------------------------------------------------------------------------- /doc/Statements.md: -------------------------------------------------------------------------------- 1 | # Statements 2 | 3 | The current statements are supported: 4 | 5 | ## local variable declaration 6 | 7 | declare a new local var in the current scope 8 | 9 | example : 10 | ```c 11 | int8 local_var; 12 | ``` 13 | 14 | ## Struct type declaration 15 | 16 | declare a new stucrture to be used as a user type 17 | 18 | example : 19 | ```c 20 | struct Header { 21 | int8 a; 22 | int8 b; 23 | }; 24 | int8 main(Header st_ab) 25 | ``` 26 | 27 | 28 | ## Assignment 29 | 30 | set a variable in the current scope 31 | 32 | example: 33 | ```c 34 | var = 1234; 35 | ``` 36 | 37 | ## Increment / Decrement 38 | 39 | Only supported as a single statement 40 | not a operator like in C/C++ 41 | 42 | example: 43 | ```c 44 | var++; 45 | var--; 46 | ``` 47 | 48 | 49 | ## Local variable declaration and assignment 50 | 51 | declare and set a variable in the current scope 52 | 53 | example: 54 | ```c 55 | int8 local_var = 0; 56 | ``` 57 | 58 | ## Return 59 | 60 | set the return value of the circuit 61 | every bloc **must** end with a return statment. 62 | 63 | example: 64 | ```c 65 | return 0; 66 | ``` 67 | 68 | ## If 69 | 70 | execute a code bloc depending of an expression that must be boolean 71 | internally the compiler generate 2 sub circuits for each possible bloc 72 | 73 | example : 74 | ```c 75 | if (val==42) { 76 | return 1; 77 | } 78 | return 0; 79 | ``` 80 | 81 | ## For 82 | 83 | Loops are restricted because a new circuit must be gneerated for each step 84 | 85 | - start and end values must be litteral int 86 | - step statement must be i++ or i-- 87 | - loop variable must be declared in the init statement 88 | - loop variable must be integer 89 | - loop variable is const, it cannot be modified in the loop 90 | 91 | example : 92 | ```c 93 | int32 sum=0; 94 | for (int8 i=0;i<32;i++) { 95 | sum = sum+i; 96 | } 97 | return sum; 98 | ``` 99 | -------------------------------------------------------------------------------- /doc/Typess.md: -------------------------------------------------------------------------------- 1 | # Types 2 | 3 | The following native types are supported : 4 | 5 | | name | description | 6 | |-----------|--------------------------| 7 | | bool | boolean / bit | 8 | | int8 | signed 8 bits integer | 9 | | uint8 | unsigned 8 bits integer | 10 | | int32 | signed 32 bits integer | 11 | | uint32 | unsigned 32 bits integer | 12 | | int64 | signed 64 bits integer | 13 | | uint64 | unsigned 64 bits integer | 14 | | int256 | signed 256 bits integer | 15 | | uint256 | unsigned 256 bits integer| 16 | 17 | # Structures 18 | 19 | Structures are supported, the following syntax is used : 20 | ``` 21 | struct Header { 22 | int8 a; 23 | int8 b; 24 | }; 25 | Header my_header; 26 | my_header.a = 1; 27 | my_header.b = 0; 28 | ``` 29 | 30 | # Arrays 31 | 32 | Fixed sized arrays are supported, the following syntax is used : 33 | ``` 34 | type[] 35 | type can be any of the native types 36 | ``` 37 | 38 | example : 39 | ``` 40 | int8[10] my_array; 41 | int8 sum=0; 42 | for (int8 i=0; i<10;i++) { 43 | sum = sum + my_array[i]; 44 | } 45 | ``` 46 | -------------------------------------------------------------------------------- /src/BinaryOperation.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "Program.h" 3 | #include 4 | #include "Error.h" 5 | #include "Circuit.h" 6 | #include "LangageGrammar.h" 7 | #include "BuildContext.h" 8 | 9 | 10 | // constructor for BinaryOperation 11 | BinaryOperation::BinaryOperation(Operator op, Expression* left, Expression* right) 12 | : operation(op) 13 | , left_operand(left) 14 | , right_operand(right) { 15 | // TODO 16 | // build the expression for debug purposes 17 | } 18 | 19 | // visit all part used in the Expression 20 | void BinaryOperation::visit_epression(IVisitExpression& visitor) { 21 | left_operand->visit_epression(visitor); 22 | right_operand->visit_epression(visitor); 23 | } 24 | 25 | // reorg epxresion tree to ensure operator precedence 26 | // ex: "a + b * c" must be calculad as "a + (b * c)" 27 | // retrun the new root of the expression 28 | BinaryOperation* BinaryOperation::BinaryOperation::reorg_for_precedence(LangageAttributes& language) { 29 | // only if the 1st operand is a binary operation 30 | BinaryOperation* left_operand_2op = left_operand->cast_to_BinaryOperation(); 31 | if (left_operand_2op == nullptr) 32 | return this; // do nothing and keep tree as it is 33 | // if the expression is in (), do nothing 34 | if (left_operand_2op->has_parentesis) 35 | return this; 36 | // if the precedence is ok 37 | // ex: a*b+c 38 | if (left_operand_2op->has_higher_precedence(*this, language)) 39 | return this; // do nothing and keep tree as it is 40 | // if the precedence is not ok 41 | // ex: a*b+c 42 | // regorganize the tree : 43 | // this 44 | // left | 45 | // a + b * c 46 | // => 47 | // result 48 | // | this 49 | // a + b * c 50 | auto a = left_operand_2op->left_operand; 51 | auto b = left_operand_2op->right_operand; 52 | auto c = this->right_operand; 53 | BinaryOperation* result = left_operand_2op; 54 | left_operand_2op->left_operand = a; 55 | this->left_operand = b; 56 | this->right_operand = c; 57 | left_operand_2op->right_operand = this; 58 | return result; 59 | 60 | } 61 | // true is the expression has a higher precedence than the othe expression 62 | bool BinaryOperation::has_higher_precedence(const BinaryOperation& other_expression, LangageAttributes& language) const { 63 | // compare precedence with the other expression 64 | int cmp = language.compare_operator_precedence((int)operation, (int)other_expression.operation); 65 | return cmp < 0; 66 | } 67 | 68 | 69 | // init 70 | void BinaryOperation::init(Scope& parent_scope) { 71 | // init operands 72 | left_operand->init(parent_scope); 73 | right_operand->init(parent_scope); 74 | // left and right operand must have the same type 75 | if (!left_operand->get_type().is_same_type(right_operand->get_type())) 76 | { 77 | // if left if a literal, try to cast right to the type of left 78 | if (left_operand->cast_to_literal() != nullptr) 79 | right_operand->cast_to_literal()->change_type(right_operand->get_type()); 80 | else if (right_operand->cast_to_literal() != nullptr ) 81 | right_operand->cast_to_literal()->change_type(left_operand->get_type()); 82 | else 83 | throw Error("Type mismatch"); 84 | } 85 | // type must ba a basic type 86 | const TypeBasic* type_basic = left_operand->get_type().cast_to_TypeBasic(); 87 | if (type_basic == nullptr) 88 | throw Error("Type must be a basic type"); 89 | // copy basic type 90 | result_type = *type_basic; 91 | } 92 | 93 | // build the circuit for the binairy expression 94 | std::vector BinaryOperation::build_circuit(BuildContext& ctx) { 95 | 96 | // build the L& R operands 97 | std::vector output_left = left_operand->build_circuit(ctx); 98 | std::vector output_right = right_operand->build_circuit(ctx); 99 | 100 | // create the gate for the operation 101 | BinaryGate* gate = nullptr; 102 | switch (operation) 103 | { 104 | case Operator::op_and: 105 | gate = new Gate_AND(); 106 | break; 107 | case Operator::op_or: 108 | gate = new Gate_OR(); 109 | break; 110 | case Operator::op_xor: 111 | gate = new Gate_XOR(); 112 | break; 113 | case Operator::op_add: 114 | // a+b is not bit to bit independant 115 | return build_circuit_add(ctx, output_left, output_right); 116 | case Operator::op_sub: 117 | // a-b is not bit to bit independant 118 | return build_circuit_sub(ctx, output_left, output_right); 119 | default: 120 | assert(false); 121 | throw Error("Internal error : unexpected operator"); 122 | } 123 | 124 | // for each bit connect gate input and output 125 | std::vector result; 126 | int size = get_type().size_in_bit(); 127 | assert(output_left.size() == size); 128 | assert(output_right.size() == size); 129 | for (int i = 0; i < size; i++) { 130 | // IN 131 | std::array input_2_bit = { output_left[i], output_right[i] }; 132 | // OUT = A OP B 133 | std::array bits_result = gate->add_to_circuit(ctx.circuit(), input_2_bit); 134 | //TODO 135 | //delete gate; 136 | result.insert(result.end(), bits_result.begin(), bits_result.end()); 137 | } 138 | return result; 139 | } 140 | // build the circuit for the "a+b" expression 141 | std::vector BinaryOperation::build_circuit_add(BuildContext& ctx, 142 | std::vector& in_a, 143 | std::vector& in_b) 144 | { 145 | assert(in_a.size() == in_b.size()); 146 | ctx.circuit().debug_info.description = "add"; 147 | 148 | std::vector result; 149 | int size = (int)in_a.size(); 150 | Gate_ADD gate_add; // add 2 birs, return carry + 1 bit 151 | Gate_ADDC gate_addc; // add 2 birs + carry, return carry + 1 bit 152 | // start with 1st bit addition 153 | std::array input_2_bit = { in_a[0], in_b[0] }; 154 | std::array low_bits = gate_add.add_to_circuit(ctx.circuit(), input_2_bit); 155 | result.push_back(low_bits[0]); 156 | Connection* carry = low_bits[1]; 157 | for (int i = 1; i < size; i++) { 158 | ctx.circuit().debug_info.description = "add bit " + std::to_string(i); 159 | // IN 160 | std::array input_3_bit = { in_a[i], in_b[i], carry }; 161 | std::array bits_ = gate_addc.add_to_circuit(ctx.circuit(), input_3_bit); 162 | result.push_back(bits_[0]); 163 | carry = bits_[1]; 164 | } 165 | // set debug info fo connexion 166 | for (int i = 0; i < size; i++) { 167 | result[i]->debug_description = "line " + std::to_string(ctx.current_statement ? ctx.current_statement->num_line:0) + " ADD bit " + std::to_string(i); 168 | } 169 | 170 | ctx.circuit().debug_info.description = ""; 171 | assert(result.size() == size); 172 | return result; 173 | } 174 | // build the circuit for the "a-b" expression 175 | std::vector BinaryOperation::build_circuit_sub(BuildContext& ctx, 176 | std::vector& in_a, 177 | std::vector& in_b) { 178 | assert(in_a.size() == in_b.size()); 179 | // implent wita a-b = a+(-b) 180 | // build the circuit for -b 181 | std::vector neg_b = UnaryOperation::build_circuit_negation(ctx, in_b); 182 | // build the circuit for a+(-b) 183 | std::vector a_minus_b = build_circuit_add(ctx, in_a, neg_b); 184 | return a_minus_b; 185 | } 186 | -------------------------------------------------------------------------------- /src/BinaryOperation.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maitrebitcoin/bitcoin-bitvm-compiler/03e3939492b925f1a9d28a05442a77817118b276/src/BinaryOperation.h -------------------------------------------------------------------------------- /src/Bits.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | class Gate; 5 | 6 | 7 | // represents a bit in the circuit 8 | class Bit { 9 | private: 10 | bool value = false; 11 | public: 12 | // get the value of the bit : overrides the cast to bool operator 13 | operator bool() const { 14 | return value; 15 | } 16 | // set the value of the bit 17 | void set_value(bool b) { 18 | value = b; 19 | } 20 | }; 21 | // arrays of bits 22 | using Bits = std::vector; 23 | 24 | -------------------------------------------------------------------------------- /src/BuildContext.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "BuildContext.h" 3 | #include "Circuit.h" 4 | 5 | // constructor 6 | BuildContext::BuildContext(Caller caller) : create_caller(caller) 7 | { 8 | assert(caller == Caller::main_body); 9 | // alloc main circuit 10 | ctx_circuit = new Circuit(); 11 | } 12 | // destructor 13 | BuildContext::~BuildContext() { 14 | build_all_next_statements = nullptr; 15 | } 16 | 17 | 18 | // copy constructor 19 | BuildContext::BuildContext(const BuildContext& source, Caller caller) : create_caller(caller) 20 | { 21 | nested_if = source.nested_if ; 22 | current_statement = source.current_statement; 23 | 24 | assert(caller != Caller::main_body); 25 | switch (caller) 26 | { 27 | case Caller::if_statement: 28 | // create a new sub circuit 29 | ctx_circuit = new Circuit(); 30 | for_statement = source.for_statement; 31 | // action to build after the if statement 32 | build_all_next_statements = source.build_all_next_statements; 33 | build_on_break = source.build_on_break; 34 | nested_if++; 35 | break; 36 | case Caller::for_statement: 37 | // share the same circuit in a for statement 38 | ctx_circuit = source.ctx_circuit; 39 | // action to build after the for statement 40 | build_all_next_statements = source.build_all_next_statements; 41 | build_on_break = source.build_on_break; 42 | 43 | // copy all vaiables 44 | ctx_variables = source.variables(); 45 | break; 46 | case Caller::build_next_lambda: 47 | // sub conterxt to preserve build_all_next_statements 48 | ctx_circuit = source.ctx_circuit; 49 | for_statement = source.for_statement; 50 | parent_ctx_variables = const_cast(&source.variables()); 51 | break; 52 | default: 53 | assert(false); 54 | throw Error("internal error : unknown caller"); 55 | } 56 | } 57 | 58 | 59 | // Init variables and If Gate for a "IF" statmeent 60 | void BuildContext::init_variables_if_gate(BuildContext& ctx_source, class Gate_IF* gate, bool bloc_side) { 61 | assert(create_caller == Caller::if_statement); 62 | 63 | // get all copy parameters from source 64 | BuildContext::InfoCopy infoCopy = ctx_source.get_info_copy(); 65 | 66 | // init variables 67 | ctx_variables = infoCopy.variables_dest; 68 | // inits connexions to the gate 69 | for (Connection* connexion : infoCopy.connexions_dest) { 70 | gate->add_input(connexion, bloc_side); 71 | } 72 | // init circuit inputs 73 | circuit().set_circuit_inputs(infoCopy.nb_bits_in(), infoCopy.input_map); 74 | } 75 | 76 | // get all info needed to create a new copy of acontexte; for "if statement" 77 | BuildContext::InfoCopy BuildContext::get_info_copy(void) const { 78 | 79 | InfoCopy result; 80 | // get all variables to copy 81 | variables().visit_all_variables([&](const ScopeVariable& variable_source) { 82 | 83 | // copy var from source to dest 84 | ScopeVariable* copy_var = result.variables_dest.copy_var(variable_source); 85 | // copy connexions for source to the gate 86 | for (Connection* connexion_copy : copy_var->bits) { 87 | result.connexions_dest.push_back(connexion_copy); 88 | } 89 | }); 90 | 91 | // basic impleation of InterfaceInputsMap 92 | class Void_InterfaceInputsMap : public InterfaceInputsMap { 93 | // InterfaceInputsMap Implementation 94 | // get a parameter info by name 95 | virtual InterfaceInputsMap::Info find_info_by_name(std::string name) const override { 96 | // used by commandline -run ony 97 | assert(false); 98 | throw Error("Internal error, not implemented"); 99 | } 100 | };//InterfaceInputsMap 101 | 102 | // init circuit inputs 103 | result.input_map = new Void_InterfaceInputsMap(); 104 | 105 | return result; 106 | 107 | } 108 | 109 | 110 | // visit all the circuits 111 | void BuildContext::visit_circuits(std::function fnVisit) { 112 | // main circuit 113 | fnVisit(circuit()); 114 | // sub circuits 115 | circuit().visit_sub_circuits(fnVisit); 116 | } 117 | 118 | // get the variables in the contexte 119 | ScopeVariables& BuildContext::variables(void) const 120 | { 121 | // if we share varaibles with the parent context 122 | if (parent_ctx_variables != nullptr) { 123 | assert(create_caller == Caller::build_next_lambda ); 124 | return *parent_ctx_variables; 125 | } 126 | return const_cast(this)->ctx_variables; 127 | 128 | } 129 | 130 | -------------------------------------------------------------------------------- /src/BuildContext.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include "VariableDefinition.h" 6 | #include "ScopeVariable.h" 7 | 8 | 9 | class Circuit; 10 | class ScopeVariables; 11 | class Connection; 12 | class Statement_For; 13 | class IVisitExpression; 14 | class InterfaceInputsMap; 15 | using InputsMap = InterfaceInputsMap*; 16 | 17 | // context for building the circuit 18 | class BuildContext { 19 | public: 20 | // description for debug purpose 21 | std::string debug_description; 22 | // current statement pour debug purpose 23 | class Statement* current_statement = nullptr; 24 | 25 | // creation or copy type 26 | enum class Caller { main_body, if_statement, for_statement, function_call, build_next_lambda}; 27 | // action return, what to do to build all next statements 28 | enum class NextAction { Continue, Break, Return }; 29 | // number of nested if 30 | int nested_if = 0; 31 | 32 | protected: 33 | Caller create_caller; 34 | Circuit* ctx_circuit = nullptr; // the circuit to build 35 | ScopeVariables ctx_variables; // current known variables in the current scope 36 | ScopeVariables* parent_ctx_variables= nullptr; // variables ftom the parent context 37 | 38 | 39 | public: 40 | Statement_For* for_statement = nullptr; // the current for statement if we are building a loop 41 | 42 | // action to do to build all next statementq 43 | std::function < NextAction(BuildContext&) > build_all_next_statements; 44 | // action to do in case a "break" is encountered 45 | std::function < NextAction(BuildContext&) > build_on_break; 46 | 47 | public: 48 | // constructor 49 | BuildContext(Caller caller); 50 | // copy constructor 51 | BuildContext(const BuildContext& source, Caller caller); 52 | // destructor 53 | ~BuildContext(); 54 | 55 | // Init variables and If Gate for a "IF" statmeent 56 | void init_variables_if_gate(BuildContext& ctx_source, class Gate_IF* gate, bool bloc_side); 57 | 58 | // get the current circuit to build in the context 59 | Circuit& circuit(void) { return *ctx_circuit; } 60 | // get the variables in the contexte 61 | ScopeVariables& variables(void) const; 62 | // visit all the circuits 63 | void visit_circuits(std::function fnVisit); 64 | // are we in a for statement ? 65 | bool is_in_for_loop(void) const { return for_statement != nullptr; } 66 | 67 | protected: 68 | // get all info needed to create a new copy of acontexte; for "if statement" 69 | class InfoCopy { 70 | public: 71 | ScopeVariables variables_dest; // copy of all variables t 72 | std::vector connexions_dest; // connexion in the copied var 73 | InputsMap input_map = nullptr; // map for connexions_dest 74 | public: 75 | // number of bits in the new context 76 | int nb_bits_in(void) const { return (int)connexions_dest.size(); } 77 | }; 78 | InfoCopy get_info_copy(void) const; 79 | }; 80 | 81 | -------------------------------------------------------------------------------- /src/Circuit.cpp: -------------------------------------------------------------------------------- 1 | // Gates.cpp 2 | // Implementation of the Circuit class. 3 | 4 | 5 | #include 6 | #include 7 | #include "Circuit.h" 8 | #include "Literal.h" 9 | 10 | // constructor 11 | Circuit::Circuit(void) { 12 | } 13 | 14 | 15 | // set the numbre of bits inputs of the circuit 16 | void Circuit::set_circuit_inputs(int bit_count, InputsMap map) { 17 | assert(!is_fully_constructed); // too late to set inputs 18 | for (int i = 0; i < bit_count; i++) { 19 | Connection* input_i = new Connection(); 20 | inputs.push_back(input_i); 21 | } 22 | correspondance_inputs = map; 23 | } 24 | 25 | // set connections ouput 26 | void Circuit::set_output(std::vector new_outputs) 27 | { 28 | assert(!is_fully_constructed); 29 | assert(outputs.size() == 0); 30 | assert(new_outputs.size() > 0); 31 | assert(output_size_child == 0); 32 | 33 | for (Connection* connexion : new_outputs) { 34 | connexion->is_output = true; 35 | outputs.push_back(connexion); 36 | } 37 | } 38 | // if the circuit have sub circuits (If statement for exemple), set the output size only 39 | void Circuit::set_output_size_child(NbBit size) { 40 | assert(!is_fully_constructed); 41 | assert(outputs.size() == 0); 42 | assert(output_size_child == 0); 43 | assert(size > 0); 44 | 45 | output_size_child = size; 46 | } 47 | 48 | 49 | 50 | // add a gate and its connexions into the circuit 51 | void Circuit::add_gate(TapScriptGate* gate) { 52 | assert(!is_fully_constructed); 53 | // set debug info 54 | gate->debug_info = debug_info; 55 | // add the gate to the circuit 56 | gates.push_back(gate); 57 | // add ouputs to the circuits 58 | std::vector outs = gate->get_outputs(); 59 | for (Connection* ouput_gate_i : outs) { 60 | // +1 connection 61 | connections.push_back(ouput_gate_i); 62 | } 63 | } 64 | // a get connection for a litteral values 65 | Connection* Circuit::get_literal_values(bool b) { 66 | // init at 1st call 67 | if (literals01[b] == nullptr) { 68 | literals01[b] = new Connection(); 69 | literals01[b]->set_value(b); 70 | } 71 | return literals01[b]; 72 | } 73 | // is the circuit usign litteral values ? 74 | bool Circuit::is_using_litteral_values(void) const { 75 | return literals01[0] != nullptr 76 | || literals01[1] != nullptr; 77 | } 78 | 79 | // get all gartes that have calculated inputes but have not been run yet 80 | std::vector Circuit::_get_computable_gate(void) const { 81 | std::vector computable_gates; 82 | for (TapScriptGate* gate : gates) { 83 | if ( gate->all_inputs_calculated() 84 | && !gate->is_computed) { 85 | computable_gates.push_back(gate); 86 | } 87 | } 88 | return computable_gates; 89 | } 90 | 91 | // init the value of a variable 92 | void CRunInputs::set_varaible_value(std::string name, std::string value) { 93 | 94 | assert(correspondance_inputs != nullptr); 95 | // look for the variable 96 | auto info_var = correspondance_inputs->find_info_by_name(name); 97 | if (!info_var.found) 98 | throw Error("Unknown variable name", name); 99 | // get the type of the variable 100 | Type *type = info_var.type; 101 | // muet be a basic type 102 | if (!type->is_basic()) 103 | throw Error("Not a basic type", name); 104 | Type::Native native_type = type->cast_to_TypeBasic()->get_native_type(); 105 | 106 | // convert the value to array of bit 107 | std::vector bits = Literal::get_bools_from_value_str(native_type, value); 108 | int nb_bit = type->size_in_bit(); 109 | assert(nb_bit== bits.size()); 110 | 111 | // set x bits of the value 112 | for (int i = 0; i < nb_bit; i++) { 113 | set_bit_value(info_var.offset_in_bit + i, bits[i]); 114 | } 115 | 116 | } 117 | 118 | 119 | // get inout of the circuit. to set values before running it 120 | CRunInputs Circuit::get_run_inputs(void) const { 121 | assert(is_fully_constructed); 122 | CRunInputs result; 123 | result.init((int)inputs.size(), correspondance_inputs); 124 | return std::move(result); 125 | 126 | 127 | } 128 | 129 | // size in bits of the output 130 | NbBit Circuit::nb_bits_output(void) const 131 | { 132 | // if the size comme from a sub circuit 133 | if (output_size_child != 0) 134 | { 135 | assert(outputs.size() == 0); 136 | return output_size_child; 137 | } 138 | return (NbBit)outputs.size(); 139 | } 140 | 141 | // check if all outputs are computed 142 | bool Circuit::_all_outputs_calculated(void) const { 143 | if (outputs.size() == 0) 144 | return false; 145 | 146 | for (Connection* output : outputs) { 147 | if (!output->is_calculated()) 148 | return false; 149 | } 150 | return true; 151 | } 152 | 153 | 154 | // run the circuit 155 | std::vector Circuit::run(const CRunInputs& in_values) const { 156 | 157 | assert(nb_bits_output() > 0); 158 | //assert(in_values.size() > 0); no in sub circuit. ex : "Return 0" 159 | assert(in_values.size() == inputs.size()); 160 | 161 | // init bits values in input 162 | for (int i = 0; i < in_values.size(); i++) 163 | { 164 | inputs[i]->set_value(in_values[i]); 165 | } 166 | 167 | // run whle we have not a result 168 | int nb_step = 0; 169 | while (true) 170 | { 171 | // if all outputs are computed, we have a result 172 | if (_all_outputs_calculated()) { 173 | // build the result 174 | std::vector result(nb_bits_output()); 175 | int i = 0; 176 | for (Connection* connection_i : outputs) { 177 | assert(connection_i->is_output); 178 | bool value_calculted = connection_i->get_value(); 179 | result[i].set_value(value_calculted); 180 | i++; 181 | } 182 | return result; 183 | } 184 | 185 | // get gates that have calculated intpus 186 | std::vector gate_to_run = _get_computable_gate(); 187 | // if no more gates to run, error 188 | if (gate_to_run.size() == 0) 189 | throw Error( "internal error : no more gates" ); 190 | 191 | // special case If gate 192 | if (gate_to_run.size() == 1 && gate_to_run[0]->cast_to_IF() != nullptr) { 193 | // run the if gate : a sub progrma depending on the value of the condition 194 | Gate_IF* gate_if = gate_to_run[0]->cast_to_IF(); 195 | return gate_if->compute_if(); 196 | } 197 | 198 | // run all the gates, but if gate 199 | for (TapScriptGate* gate : gate_to_run) { 200 | if (!gate->cast_to_IF()) { 201 | gate->compute(); 202 | assert(gate->is_computed); 203 | } 204 | } 205 | 206 | // continue calculation 207 | nb_step++; 208 | 209 | } // while (true) 210 | 211 | } 212 | 213 | // reset the circuit gates before a new run. resursive to all sub circuits 214 | void Circuit::reset(void) const { 215 | _reset_non_recursive(); 216 | // reset sub circuits 217 | visit_sub_circuits([](Circuit& sub_circiut) { 218 | sub_circiut._reset_non_recursive(); 219 | }); 220 | } 221 | 222 | // reset the circuit gate before a new run. non recursive 223 | void Circuit::_reset_non_recursive(void) const 224 | { 225 | for (TapScriptGate* gate : gates) { 226 | gate->is_computed = false; 227 | } 228 | for (Connection* connection_i : connections) { 229 | connection_i->reset(); 230 | } 231 | for (Connection* connection_i : inputs){ 232 | connection_i->reset(); 233 | } 234 | 235 | 236 | } 237 | // init gates and connections ID 238 | void Circuit::init_id_gates_and_connexions(int &connection_id) 239 | { 240 | // give an ID to all gates and all connections 241 | for (int i = 0; i < gates.size(); i++) { 242 | gates[i]->id = i; 243 | } 244 | // init literals 245 | if (literals01[0]) 246 | literals01[0]->id = connection_id++; 247 | if (literals01[1]) 248 | literals01[1]->id = connection_id++; 249 | // init inputs and connections 250 | for (Connection* input_i : inputs) { 251 | input_i->id = connection_id; 252 | connection_id++; 253 | } 254 | for (Connection* connection_i : connections) { 255 | if (connection_i->id != 0) 256 | continue; 257 | connection_i->id = connection_id; 258 | connection_id++; 259 | } 260 | 261 | is_fully_constructed = true; 262 | } 263 | 264 | // get stats on the circuit 265 | Circuit::Stats Circuit::get_stats(void) const { 266 | Circuit::Stats result; 267 | result.nb_gate =(int)gates.size(); 268 | result.nb_connection =(int)connections.size(); 269 | result.nb_input =(int)inputs.size(); 270 | result.nb_output =(int)outputs.size(); 271 | return result; 272 | } 273 | 274 | // export to a string 275 | std::string Circuit::export_to_string(void) const { 276 | //std::string result; 277 | std::ostringstream str_stream; 278 | export_to_stream(str_stream); 279 | return str_stream.str(); 280 | } 281 | // export to a stream in the Bristol Fashion 282 | // inspired from https://github.com/mcbagz/LogicGates/blob/main/Example.ipynb 283 | // format : https://pypi.org/project/circuit/ 284 | // see also https://homes.esat.kuleuven.be/~nsmart/MPC/ 285 | void Circuit::export_to_stream(std::ostream& out) const { 286 | assert(is_fully_constructed); 287 | 288 | //# of gates + # of of wires 289 | out << std::to_string(gates.size()) << ' ' << std::to_string(connections.size()); 290 | out << "\n"; 291 | //# of inputs 292 | out << std::to_string(inputs.size()); 293 | // inputs 294 | for (Connection* input_i : inputs) { 295 | out << " " << std::to_string(input_i->id); 296 | } 297 | out << "\n"; 298 | //# of outputs 299 | out << std::to_string(outputs.size()); 300 | // outputs 301 | for (Connection* output_i : outputs) { 302 | out << " " << std::to_string(output_i->id); 303 | } 304 | 305 | // 0 and 1 for litterals 306 | if (is_using_litteral_values()) 307 | { 308 | // wire 0 is assigned the value 0 and wire 1 the value 1 309 | if (literals01[0]) { 310 | out << "\n" << "1 1 0 " << literals01[0]->id << " EQ"; 311 | } 312 | if (literals01[1]) { 313 | out << "\n" << "1 1 1 " << literals01[1]->id << " EQ"; 314 | } 315 | } 316 | 317 | // Gates 318 | for (TapScriptGate* gate_i : gates) { 319 | out << "\n"; 320 | // # inputs 321 | auto outs = gate_i->get_outputs(); 322 | out << std::to_string(outs.size()); 323 | for (Connection* out_i : outs) { 324 | out << " " << std::to_string(out_i->id); 325 | } 326 | // # outputs 327 | out << " "; 328 | auto ins = gate_i->get_inputs(); 329 | out << std::to_string(outs.size()); 330 | for (Connection* in_i : ins) { 331 | out << " " << std::to_string(in_i->id); 332 | } 333 | // gate type 334 | out << " " << gate_i->get_export_type(); 335 | 336 | } 337 | 338 | out << "\n"; 339 | } 340 | // visit all sub circuits 341 | void Circuit::visit_sub_circuits(std::function visitor) const { 342 | for (TapScriptGate* gate_i : gates) { 343 | // special case If gate 344 | if (gate_i->cast_to_IF()) { 345 | // cast to IF gate 346 | Gate_IF* gate_if = gate_i->cast_to_IF(); 347 | // visit sub circuits of the IF gate 348 | visitor(*gate_if->circuit_if_true); 349 | gate_if->circuit_if_true->visit_sub_circuits(visitor); 350 | visitor(*gate_if->circuit_if_false); 351 | gate_if->circuit_if_false->visit_sub_circuits(visitor); 352 | 353 | } 354 | } 355 | 356 | } -------------------------------------------------------------------------------- /src/Circuit.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include "Bits.h" 5 | #include "Gate.h" 6 | #include "Error.h" 7 | #include "Function.h" 8 | #include "InterfaceInputsMap.h" 9 | 10 | class TapScriptGate; 11 | class Circuit; 12 | class CRunInputs; 13 | 14 | 15 | using InputsMap = InterfaceInputsMap*; 16 | using NbBit = int; 17 | 18 | // represents a virtual circuit 19 | class Circuit { 20 | public: 21 | // debug info 22 | CDebugInfo debug_info; 23 | private: 24 | // circuit id 25 | int id = 0; 26 | // inputs in the circuit 27 | std::vector inputs; 28 | // gates in the circuit 29 | std::vector gates; 30 | // ouputs of the circuit 31 | std::vector outputs; 32 | // if the circuit have sub circuits (If statement for exemple), set the output size only 33 | NbBit output_size_child = 0; 34 | 35 | // connections in the circuit 36 | std::vector connections; 37 | // litteral values : 0 an 1 38 | std::array literals01; 39 | 40 | // set to true when the circuit is connot be modified anymore 41 | bool is_fully_constructed = false; 42 | 43 | // map for input correspondance 44 | InputsMap correspondance_inputs = nullptr; 45 | 46 | public: 47 | 48 | // constructor 49 | Circuit(void); 50 | 51 | // set the number of bits inputs of the circuit 52 | void set_circuit_inputs(int bit_count, InputsMap input_map); 53 | // add a gate into the circuit 54 | void add_gate(TapScriptGate* gate); 55 | // set all connections ouput 56 | void set_output(std::vector new_outputs); 57 | // a get connection for a litteral values 58 | Connection* get_literal_values(bool b); 59 | // get the input gates in the circuit 60 | std::vector getInputs(void) { return inputs; } 61 | // is the circuit usign litteral values ? 62 | bool is_using_litteral_values(void) const; 63 | 64 | // if the circuit have sub circuits (If statement for exemple), set the output size only 65 | void set_output_size_child(NbBit size); 66 | // size in bits of the output 67 | NbBit nb_bits_output(void) const; 68 | 69 | // get inout of the circuit. to set values before running it 70 | CRunInputs get_run_inputs(void) const; 71 | // run the circuit 72 | std::vector run(const CRunInputs& inputs) const; 73 | // reset the circuit gate before a new run 74 | void reset(void) const; 75 | // set id fro the ciruit 76 | void set_id(int id) { this->id = id; } 77 | // init gates and connections ID 78 | void init_id_gates_and_connexions(int& connection_id); 79 | 80 | // export to a string 81 | std::string export_to_string(void) const; 82 | // export to a strem 83 | // inspired from https://github.com/mcbagz/LogicGates/blob/main/Example.ipynb 84 | // format : https://pypi.org/project/circuit/ 85 | void export_to_stream(std::ostream& out) const; 86 | // get stats 87 | struct Stats { 88 | int nb_gate = 0; 89 | int nb_connection = 0; 90 | int nb_input = 0; 91 | int nb_output = 0; 92 | }; 93 | Stats get_stats(void) const; 94 | // visit all sub circuits 95 | void visit_sub_circuits(std::function visitor) const; 96 | 97 | protected: 98 | // get all gates that have calculated inputes 99 | std::vector _get_computable_gate(void) const; 100 | // check if all outputs are computed 101 | bool _all_outputs_calculated(void) const; 102 | // reset the circuit gate before a new run. non recursive 103 | void _reset_non_recursive(void) const; 104 | 105 | }; 106 | 107 | class CRunInputs : public std::vector 108 | { 109 | friend Circuit; 110 | 111 | protected: 112 | // map for inoput correspondance 113 | InputsMap correspondance_inputs = nullptr; 114 | 115 | private: 116 | // construstor, for Circuit ad gate_If only 117 | CRunInputs(void) {}; 118 | // init inpute 119 | void init(int nb_bit, InputsMap _inputs) { 120 | // init the vector 121 | for (int i = 0; i < nb_bit; i++) 122 | this->push_back(Bit()); 123 | correspondance_inputs = _inputs; 124 | } 125 | 126 | public: 127 | // init the value of a variable 128 | void set_varaible_value(std::string name, std::string value); 129 | 130 | // set a 1 bit value 131 | void set_bit_value(int numvar, bool b) { 132 | assert(numvar < (int)this->size()); 133 | // set the value 134 | (*this)[numvar].set_value(b); 135 | } 136 | // set the value of a 8 bit var 137 | void set_int8_value(int numvar, std::vector bits) { 138 | assert(numvar * 8 < (int)this->size()); 139 | assert(bits.size() == 8); 140 | // set 8 bits of the value 141 | for (int i = 0; i < 8; i++) { 142 | set_bit_value(numvar * 8 + i, bits[i]); 143 | } 144 | } 145 | // set the value of a 32 bit var 146 | void set_int32_value(int numvar, std::vector bits) { 147 | assert(numvar * 8 < (int)this->size()); 148 | assert(bits.size() == 32); 149 | // set 8 bitsd of the value 150 | for (int i = 0; i < 32; i++) { 151 | set_bit_value(numvar * 32 + i, bits[i]); 152 | } 153 | } 154 | // set the value of a 64 bit var 155 | void set_int64_value(int numvar, std::vector bits) { 156 | assert(numvar * 8 < (int)this->size()); 157 | assert(bits.size() == 64); 158 | // set 8 bitsd of the value 159 | for (int i = 0; i < 64; i++) { 160 | set_bit_value(numvar * 64 + i, bits[i]); 161 | } 162 | } 163 | // set the value of a 256 bit var 164 | void set_int256_value(int numvar, std::vector bits) { 165 | assert(numvar * 8 < (int)this->size()); 166 | assert(bits.size() == 256); 167 | // set 8 bitsd of the value 168 | for (int i = 0; i < 256; i++) { 169 | set_bit_value(numvar * 256 + i, bits[i]); 170 | } 171 | } 172 | }; 173 | -------------------------------------------------------------------------------- /src/CodeBloc.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "CodeBloc.h" 3 | #include "Program.h" 4 | #include "Error.h" 5 | #include "Circuit.h" 6 | 7 | 8 | // get the return statement of the bloc 9 | Statement_Return* CodeBloc::get_return_statement(void) const { 10 | if (statements.size() == 0) 11 | return nullptr; 12 | // always last in bloc 13 | Statement* last_statement = statements.back(); 14 | return last_statement->cast_to_Statement_Return(); 15 | } 16 | 17 | // init a bloc 18 | void CodeBloc::init(Scope& scope) { 19 | init_ex(scope, InitOption::return_must_be_present); 20 | } 21 | // init a bloc, extentend version used in "for" statement 22 | void CodeBloc::init_ex(Scope& parent_scp, InitOption option) { 23 | // init parent function in the scope 24 | init_CodeBloc(parent_scp); 25 | 26 | // reoorganize the bloc in case of "If" 27 | //_reorganize_bloc_if_statement(); 28 | 29 | // init statemtents 30 | for (Statement* statement_i : statements) { 31 | try { 32 | statement_i->init(*this); 33 | } 34 | catch (Error& e) { 35 | // add the line number 36 | 37 | e.line_number = statement_i->num_line; 38 | throw e; 39 | } 40 | } 41 | 42 | // check statements : 43 | if (statements.size() == 0) 44 | throw Error("Empty function"); 45 | 46 | // if return (or break) is optionnal 47 | if (option == InitOption::return_not_required) 48 | return; 49 | 50 | Statement* last_statement = statements.back(); 51 | // if last statement can be a break and iti is a break 52 | if (option == InitOption::return_or_break_must_be_present 53 | && last_statement->cast_to_Statement_Break() != nullptr) 54 | return; //OK 55 | 56 | // last statement must be a return or if 57 | if ( last_statement->cast_to_Statement_Return() == nullptr 58 | && last_statement->cast_to_Statement_If() == nullptr) 59 | throw Error("Last statement must be a return"); 60 | 61 | 62 | } 63 | 64 | // reoorganize the bloc in case of "If" 65 | void CodeBloc::_reorganize_bloc_if_statement(void) { 66 | 67 | // build the statements before "return" 68 | for (int i = 0; i < statements.size() - 1; i++) { 69 | Statement* statement = statements[i]; 70 | // if it is a if 71 | Statement_If* if_statement = statement->cast_to_Statement_If(); 72 | if (if_statement != nullptr) 73 | { 74 | // get the bloc after the if : else statement 75 | CodeBloc* bloc_after_if = new CodeBloc(); 76 | // add the bloc after the if 77 | for (int k = i + 1; k < statements.size(); k++) 78 | bloc_after_if->statements.push_back(statements[k]); 79 | // remove bloc after the if 80 | statements.erase(statements.begin() + i + 1, statements.end()); 81 | // set the else bloc 82 | if_statement->setElseBloc(bloc_after_if); 83 | // no more statements 84 | return; 85 | } 86 | 87 | } 88 | } 89 | // visit all part used in the bloc 90 | void CodeBloc::visit_all_epressions(IVisitExpression& visitor) 91 | { 92 | for (Statement* statement_i : statements) { 93 | // visit expressions in the statement 94 | statement_i->visit_Expression([&](Expression& expression) { 95 | // visi expression 96 | expression.visit_epression(visitor); 97 | }); 98 | }//for 99 | } 100 | // visit part used in the bloc, fram a given statement 101 | void CodeBloc::visit_all_epressions_from(IVisitExpression& visitor, int statement_index) 102 | { 103 | for (int i = statement_index; i < statements.size(); i++) { 104 | Statement* statement_i = statements[i]; 105 | // visit expressions in the statement 106 | statement_i->visit_Expression([&](Expression& expression) { 107 | // visi expression 108 | expression.visit_epression(visitor); 109 | }); 110 | }//for 111 | 112 | } 113 | 114 | // visit all expression used in all the statement 115 | void CodeBloc::visit_Expression(std::function visitor) const { 116 | 117 | for (Statement* statement_i : statements) { 118 | // visit expressions in the statement 119 | statement_i->visit_Expression(visitor); 120 | }//for 121 | 122 | } 123 | 124 | // build a circuit that represents the bloc 125 | BuildContext::NextAction CodeBloc::build_circuit(BuildContext& ctx) { 126 | // buidl form the first statement 127 | return _build_circuit_from(ctx,0); 128 | } 129 | 130 | 131 | // build a circuit that represents the bloc, from a statement index 132 | BuildContext::NextAction CodeBloc::_build_circuit_from(BuildContext& ctx, int first_statement_index) { 133 | 134 | 135 | // build the statements 136 | for (int i = first_statement_index; i < statements.size(); i++) { 137 | Statement* statement = statements[i]; 138 | try { 139 | 140 | // action in case of if to bluild the circuit from a new position 141 | BuildContext ctx_internal(ctx, BuildContext::Caller::build_next_lambda); 142 | ctx_internal.debug_description = "statement " + std::to_string(i) + " / line " + std::to_string(statement->num_line); 143 | BuildContext* pctx_caller = &ctx; 144 | ctx_internal.build_all_next_statements = [this, pctx_caller, i](BuildContext& context_param) { 145 | auto action = _build_circuit_from(context_param, i + 1); 146 | if (action == BuildContext::NextAction::Return) 147 | return action; 148 | if (action == BuildContext::NextAction::Break) 149 | return pctx_caller->build_on_break(context_param); 150 | assert(pctx_caller->build_all_next_statements != nullptr); 151 | auto sub_action = pctx_caller->build_all_next_statements(context_param); 152 | return sub_action; 153 | }; 154 | ctx_internal.build_on_break = ctx.build_on_break; 155 | ctx_internal.circuit().debug_info.source_line = statement->num_line; 156 | ctx_internal.circuit().debug_info.description = "statement"; 157 | 158 | BuildContext::NextAction action =statement->build_circuit(ctx_internal); 159 | 160 | switch (action) 161 | { 162 | case BuildContext::NextAction::Continue: // proceed to next statement 163 | break; 164 | case BuildContext::NextAction::Break: 165 | //we should be in a from loop 166 | assert(ctx.is_in_for_loop()); 167 | return BuildContext::NextAction::Break; 168 | case BuildContext::NextAction::Return: 169 | // nothing more to do 170 | return BuildContext::NextAction::Return; 171 | default: 172 | assert(false); 173 | break; 174 | } 175 | 176 | } 177 | catch (Error& e) { 178 | //add info to the error 179 | e.line_number = statement->num_line; 180 | throw e; 181 | } 182 | } 183 | return BuildContext::NextAction::Continue; 184 | } 185 | -------------------------------------------------------------------------------- /src/CodeBloc.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "Scope.h" 5 | #include "Statement.h" 6 | 7 | class Function; 8 | class BuildContext; 9 | class Expression; 10 | class Expression_Variable; 11 | class IVisitExpression; 12 | 13 | class CodeBloc : public Scope { 14 | public: 15 | // code statements 16 | std::vector statements; 17 | 18 | public: 19 | // constructors 20 | CodeBloc(void) {} // code reorg for if statement 21 | CodeBloc(Statement* first_statement) { statements.push_back(first_statement); } // parsing 22 | // add a statement 23 | void add_statement(Statement* s) { statements.push_back(s); } 24 | // init a bloc 25 | void init( Scope& global_scope); 26 | // init a bloc, extentend version used in "for" statement 27 | enum class InitOption { return_must_be_present, return_or_break_must_be_present, return_not_required }; 28 | void init_ex(Scope& global_scope, InitOption option); 29 | // build a circuit that represents the bloc 30 | BuildContext::NextAction build_circuit(BuildContext& ctx); 31 | // get the return statement of the bloc 32 | class Statement_Return* get_return_statement(void) const; 33 | // visit all part used in the bloc 34 | void visit_all_epressions(IVisitExpression& visitor); 35 | // visit part used in the bloc, fram a given statement 36 | void visit_all_epressions_from(IVisitExpression& visitor, int statement_index); 37 | // visit all expression used in all the statement 38 | void visit_Expression(std::function visitor) const; 39 | 40 | protected: 41 | // build a circuit that represents the bloc, from a statement index 42 | BuildContext::NextAction _build_circuit_from(BuildContext& ctx, int first_statement_index); 43 | // reoorganize the bloc in case of "If" 44 | void _reorganize_bloc_if_statement(void); 45 | }; -------------------------------------------------------------------------------- /src/Compiler.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maitrebitcoin/bitcoin-bitvm-compiler/03e3939492b925f1a9d28a05442a77817118b276/src/Compiler.cpp -------------------------------------------------------------------------------- /src/Compiler.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maitrebitcoin/bitcoin-bitvm-compiler/03e3939492b925f1a9d28a05442a77817118b276/src/Compiler.h -------------------------------------------------------------------------------- /src/CompositedGate.cpp: -------------------------------------------------------------------------------- 1 | // Gates.cpp 2 | // Implemnetaions of the composoiteds gates logic 3 | //@TODO: Optim, set a a TapRoopScrip 4 | 5 | #include "Gate.h" 6 | #include "Circuit.h" 7 | 8 | 9 | // add a NOT gate into the 10 | 11 | std::array Gate_NOT::add_to_circuit(Circuit& circuit, std::array& _inputs) { 12 | // implemented with a nand gate 13 | Gate_NAND* _nand = new Gate_NAND(); 14 | std::array inputs2 = { _inputs[0], _inputs[0] }; 15 | return _nand->add_to_circuit(circuit, inputs2); 16 | }; 17 | 18 | // compute the output of the AND gate 19 | std::array Gate_AND::add_to_circuit(Circuit& circuit, std::array& _inputs) { 20 | // implemented with a nand + not 21 | Gate_NAND* _nand = new Gate_NAND(); 22 | Gate_NAND* _nand_not = new Gate_NAND(); 23 | std::array output_gate1 = _nand->add_to_circuit(circuit, _inputs); 24 | std::array output_gate2 = { output_gate1[0], output_gate1[0] }; 25 | return _nand_not->add_to_circuit(circuit, output_gate2); 26 | }; 27 | 28 | // compute the output of the OR gate 29 | std::array Gate_OR::add_to_circuit(Circuit& circuit, std::array& _inputs) 30 | { 31 | // implemented with r = not(a) nand not(b) 32 | Gate_NAND* _nand_a = new Gate_NAND(); 33 | Gate_NAND* _nand_b = new Gate_NAND(); 34 | Gate_NAND* _nand_r = new Gate_NAND(); 35 | std::array inputs_a = { _inputs[0], _inputs[0] }; 36 | std::array inputs_b = { _inputs[1], _inputs[1] }; 37 | std::array not_a = _nand_a->add_to_circuit(circuit, inputs_a); 38 | std::array not_b = _nand_b->add_to_circuit(circuit, inputs_b); 39 | std::array not_ab = { not_a[0], not_b[0] }; 40 | return _nand_r->add_to_circuit(circuit, not_ab); 41 | 42 | } 43 | 44 | // compute the output of the XOR gate 45 | std::array Gate_XOR::add_to_circuit(Circuit& circuit, std::array& _inputs) 46 | { 47 | // implemented with 4 nand gates 48 | Gate_NAND* _nand_1 = new Gate_NAND(); 49 | Gate_NAND* _nand_2 = new Gate_NAND(); 50 | Gate_NAND* _nand_3 = new Gate_NAND(); 51 | Gate_NAND* _nand_4 = new Gate_NAND(); 52 | // nand(a, b) 53 | std::array inputs_1 = { _inputs[0], _inputs[1] }; 54 | std::array nand_ab = _nand_1->add_to_circuit(circuit, inputs_1); 55 | // nand(a, nand(a, b)) 56 | std::array inputs_2 = { _inputs[0], nand_ab[0] }; 57 | std::array nand_a_nand_ab = _nand_2->add_to_circuit(circuit, inputs_2); 58 | // nand(b, nand(a, b)) 59 | std::array inputs_3 = { _inputs[1], nand_ab[0] }; 60 | std::array nand_b_nand_ab = _nand_3->add_to_circuit(circuit, inputs_3); 61 | // result 62 | std::array inputs_4 = { nand_a_nand_ab[0], nand_b_nand_ab[0] }; 63 | std::array xor_ab = _nand_4->add_to_circuit(circuit, inputs_4); 64 | 65 | return xor_ab; 66 | 67 | } 68 | // compute the output of the XNOR gate 69 | std::array Gate_XNOR::add_to_circuit(Circuit& circuit, std::array& _inputs) 70 | { 71 | // !(a xor b) 72 | std::array < Connection*, 1> xor_ab = Gate_XOR().add_to_circuit(circuit, _inputs); 73 | // ! 74 | return Gate_NOT().add_to_circuit(circuit, xor_ab); 75 | } 76 | // (r,carry) = a + b 77 | // compute the output of the gate 78 | std::array Gate_ADD::add_to_circuit(Circuit& circuit, std::array& _inputs) { 79 | 80 | std::array _ab = { _inputs[0], _inputs[1] }; 81 | std::array a_xor_b = Gate_XOR().add_to_circuit(circuit, _ab); 82 | std::array a_and_b = Gate_AND().add_to_circuit(circuit, _ab); 83 | // low = a xor b 84 | // carry = a and b 85 | return { a_xor_b[0], a_and_b[0] }; 86 | } 87 | 88 | // full adder 89 | // (r,carry) = a + b + carry_in 90 | // compute the output of the gate 91 | std::array Gate_ADDC::add_to_circuit(Circuit& circuit, std::array& _inputs) { 92 | // easy implentation wirh 2 half adders and an or gate 93 | // source : https://www.geeksforgeeks.org/full-adder-in-digital-logic/ 94 | std::array _ab = { _inputs[0], _inputs[1] }; 95 | std::array add_ab = Gate_ADD().add_to_circuit(circuit, _ab); 96 | std::array _c_add_ab = { _inputs[2], add_ab[0] }; 97 | std::array add_c_addab = Gate_ADD().add_to_circuit(circuit, _c_add_ab); 98 | // carry from the 2 addders 99 | std::array _2c = { add_ab[1], add_c_addab[1] }; 100 | std::array c_out = Gate_OR().add_to_circuit(circuit, _2c); 101 | 102 | // low = a + b + c 103 | return { add_c_addab[0], c_out[0] }; 104 | } 105 | 106 | 107 | // add the gate into the circuir 108 | std::array Gate_IF::add_to_circuit(Circuit& circuit, std::array& _input) 109 | { 110 | circuit.add_gate(this); 111 | set_inputs(_input); 112 | // no raal output 113 | std::array output_void = {}; 114 | return output_void; 115 | 116 | } 117 | 118 | 119 | 120 | 121 | -------------------------------------------------------------------------------- /src/CompositedGate.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "IGate.h" 4 | 5 | // represent a gate implementd with other base gates. ex : a+b 6 | class CompositedGate : public IGate { 7 | public: 8 | 9 | }; 10 | // template to build N/M composite gates 11 | template 12 | class T_CompositedGate : public T_NMGate< N, M, CompositedGate> 13 | { 14 | }; 15 | 16 | 17 | 18 | class UnaryGate : public T_CompositedGate<1, 1> {}; 19 | // r = !a 20 | class Gate_NOT : public UnaryGate 21 | { 22 | public: 23 | // compute the output of the NOT gate 24 | virtual std::array add_to_circuit(Circuit& circuit, std::array& _inputs) override; 25 | }; 26 | class BinaryGate : public T_CompositedGate<2, 1> {}; 27 | // r = a & b 28 | class Gate_AND : public BinaryGate 29 | { 30 | public: 31 | // compute the output of the AND gate 32 | virtual std::array add_to_circuit(Circuit& circuit, std::array& _inputs) override; 33 | }; 34 | // r = a | b 35 | class Gate_OR : public BinaryGate 36 | { 37 | public: 38 | // compute the output of the OR gate 39 | virtual std::array add_to_circuit(Circuit& circuit, std::array& _inputs) override; 40 | }; 41 | // r = a ^ b 42 | class Gate_XOR : public BinaryGate 43 | { 44 | public: 45 | // compute the output of the OR gate 46 | virtual std::array add_to_circuit(Circuit& circuit, std::array& _inputs) override; 47 | }; 48 | // r = (a == b) 49 | class Gate_XNOR : public BinaryGate 50 | { 51 | public: 52 | // compute the output of the OR gate 53 | virtual std::array add_to_circuit(Circuit& circuit, std::array& _inputs) override; 54 | }; 55 | 56 | // (r,carry) = a + b 57 | class Gate_ADD : public T_CompositedGate<2, 2> 58 | { 59 | public: 60 | // compute the output of the OR gate 61 | virtual std::array add_to_circuit(Circuit& circuit, std::array& _inputs) override; 62 | }; 63 | // full adder 64 | // (r,carry) = a + b + c 65 | class Gate_ADDC : public T_CompositedGate<3, 2> 66 | { 67 | public: 68 | // compute the output of the gate 69 | virtual std::array add_to_circuit(Circuit& circuit, std::array& _inputs) override; 70 | }; 71 | 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /src/Connection.cpp: -------------------------------------------------------------------------------- 1 | // implementation of class Connection 2 | 3 | #include "Connection.h" 4 | #include "Gate.h" 5 | 6 | bool Connection::is_calculated(void) const { 7 | return bit_value != nullptr; 8 | } 9 | // get the value of the bit 10 | bool Connection::get_value(void) const { 11 | assert(bit_value != nullptr); 12 | return *bit_value; 13 | } 14 | // set the value of the bit 15 | void Connection::set_value(bool b) { 16 | assert(bit_value == nullptr); 17 | bit_value = new Bit(); 18 | bit_value->set_value(b); 19 | } 20 | // rest the value of the bit for a new run 21 | void Connection::reset(void) { 22 | delete bit_value; 23 | bit_value = nullptr; 24 | } -------------------------------------------------------------------------------- /src/Connection.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include "Bits.h" 7 | class TapScriptGate; 8 | 9 | 10 | // represents a connection in the circuit betwen 2 gates 11 | class Connection { 12 | public: 13 | // description for debug purpose 14 | std::string debug_description; 15 | // gates that set the bit value 16 | TapScriptGate* gate_out = nullptr; 17 | // gates that use the bit value a their input 18 | std::vector tab_gate_in; 19 | // set if this is an output of the circuit 20 | bool is_output = false; 21 | // id of the connection, for export 22 | int id = 0; 23 | private: 24 | // value in the connexion, during calculation only 25 | Bit* bit_value = nullptr; 26 | 27 | public: 28 | bool is_calculated(void) const; 29 | // get the value of the bit 30 | bool get_value(void) const; 31 | // set the value of the bit 32 | void set_value(bool b); 33 | // rest the value of the bit for a new run 34 | void reset(void); 35 | 36 | }; 37 | -------------------------------------------------------------------------------- /src/Error.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | // compiler error 6 | class Error { 7 | public: 8 | std::string file_name; 9 | std::string function_name; 10 | int line_number = 0; 11 | // main error message 12 | std::string message; 13 | public: 14 | // constructor 15 | Error(void) {} 16 | Error(const char* mess) : message(mess) {} 17 | Error(const char* mess, std::string more_info) : message(mess) { message += ' ' + more_info; } 18 | Error(std::string mess, std::string more_info) : message(mess) { message += ' ' + more_info; } 19 | 20 | // format the error message 21 | std::string toString(void) const { 22 | std::string res; 23 | if (function_name != "") 24 | res += function_name + "() :\n"; 25 | if (file_name != "") 26 | res += file_name + "(" + std::to_string(line_number+1) + ") : " + message; 27 | else 28 | res += message; 29 | return res; 30 | } 31 | }; -------------------------------------------------------------------------------- /src/Expression.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "Expression.h" 3 | #include "Literal.h" 4 | 5 | //change the type of all litteral to a give type in the expression 6 | // for the "int64 i = 0" case 7 | void Expression::change_all_litterals_type(const Type& new_type) { 8 | 9 | class Visitor : public IVisitExpression { 10 | protected: 11 | // Closure 12 | const Type& new_type; 13 | public: 14 | // constructor 15 | Visitor(const Type& t) : new_type(t) {} 16 | // -- IVisitExpression implemebtatoin 17 | // epxression part is a literal.ex : 123 18 | virtual void onLiteral(Literal& litteral) override { 19 | // check the type 20 | if (litteral.get_type().is_same_type(new_type)) 21 | return; // nothing to do 22 | // change the litteral type 23 | litteral.change_type(new_type); 24 | } 25 | // expressison part is a varible. ex : a 26 | virtual void onVariable(Expression_Variable&) override {}; 27 | // expressison part is a varible in a struct. ex : a.b 28 | virtual void onVariableInStruct(Expression_StructMember&) override {}; 29 | // expressison part is a varible in a struct. ex : a.b 30 | virtual void onArrayElement(Expression_ArrayElement&) override {}; 31 | 32 | }; 33 | Visitor visitor(new_type); 34 | // visit all part used in the Expression 35 | visit_epression(visitor); 36 | 37 | 38 | } -------------------------------------------------------------------------------- /src/Expression.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maitrebitcoin/bitcoin-bitvm-compiler/03e3939492b925f1a9d28a05442a77817118b276/src/Expression.h -------------------------------------------------------------------------------- /src/Expression_ArrayElement.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "Expression_ArrayElement.h" 3 | #include "Error.h" 4 | #include "Scope.h" 5 | #include "TypeArray.h" 6 | #include "Literal.h" 7 | #include "Expression_Variable.h" 8 | #include "CompositedGate.h" 9 | #include "TestOperation.h" 10 | 11 | // constructor 12 | Expression_ArrayElement::Expression_ArrayElement(std::string name, Expression* index_) 13 | : array_name(name) 14 | , index(index_) { 15 | assert(index != nullptr); 16 | } 17 | 18 | // get element type 19 | const Type& Expression_ArrayElement::get_type(void) const { 20 | if (element_type == nullptr) { 21 | // error :type not yet set 22 | throw Error("Internal error, array type non resolded"); 23 | } 24 | return *element_type; 25 | } 26 | 27 | // visit all part used in the Expression 28 | void Expression_ArrayElement::visit_epression(IVisitExpression& visitor) 29 | { 30 | visitor.onArrayElement(*this); 31 | } 32 | 33 | // init 34 | void Expression_ArrayElement::init(Scope& parent_scope) { 35 | 36 | // init index operand 37 | index->init(parent_scope); 38 | 39 | // get the array type from name 40 | const VariableDefinition* parent_definition = parent_scope.find_variable_by_name(array_name); 41 | if (parent_definition == nullptr) { 42 | // error : 'name' not found 43 | throw Error("identifier not found :", array_name); 44 | } 45 | // must be a an arrau 46 | assert(parent_definition->type != nullptr); 47 | assert(parent_definition->type->is_complete()); 48 | const TypeArray* parent_type_array = parent_definition->type->cast_to_TypeArray(); 49 | if (parent_type_array == nullptr) { 50 | // error : parent is not an array 51 | throw Error("not an array : ", array_name); 52 | } 53 | assert(parent_type_array->element_type != nullptr); 54 | 55 | // keep the type 56 | element_type = parent_type_array->element_type; 57 | } 58 | 59 | // get the array size = number of elements 60 | int Expression_ArrayElement::get_array_size(const ScopeVariable& var_array) const { 61 | // divide the number of bits in the arrya by the size of the element 62 | int element_size = element_type->size_in_bit(); 63 | IndexType array_size = (IndexType)(var_array.bits.size() / element_size); 64 | return array_size; 65 | 66 | } 67 | 68 | // build the circuit for the expression for a int index value 69 | std::vector Expression_ArrayElement::build_circuit_for_int_index(BuildContext& ctx, const ScopeVariable& var_array, IndexType index_value) { 70 | assert(element_type != nullptr); 71 | int element_size = element_type->size_in_bit(); 72 | 73 | // check index value 74 | IndexType array_size = get_array_size(var_array); // (int)var_array.bits.size() / element_size; 75 | if (index_value < 0 || index_value >= array_size) 76 | throw Error("Array index out of range : ", std::to_string(index_value)); 77 | 78 | // get offest in bits in the array 79 | int offset_in_bit = element_size * index_value; 80 | auto begin_member = var_array.bits.begin() + offset_in_bit; 81 | // get the bits of the element 82 | std::vector < Connection*> bits_member(begin_member, begin_member + element_size); 83 | assert(bits_member.size() == element_type->size_in_bit()); 84 | return bits_member; 85 | } 86 | 87 | 88 | // build the circuit for the expression 89 | std::vector Expression_ArrayElement::build_circuit(BuildContext& ctx) { 90 | // get the parent variable type by name 91 | ScopeVariable* var_array = ctx.variables().find_by_name(array_name); 92 | if (var_array == nullptr) 93 | throw Error("Unknonwn variable : ", array_name); 94 | // if variable not set 95 | if (!var_array->is_set()) 96 | throw Error("Uninitialized variable : ", array_name); 97 | 98 | //1. literal value as index. ex : a[3] 99 | Literal* index_literal = index->cast_to_literal(); 100 | if (index_literal != nullptr) { 101 | // set outputs to get the value of the part of variable in the struct 102 | return build_circuit_for_int_index(ctx, *var_array, index_literal->get_int_value()); 103 | } 104 | 105 | //2. expression as index. ex : a[b+1] 106 | 107 | 108 | //2.1 : simmple var, ex : a[i] 109 | Expression_Variable* index_var = index->cast_to_Expression_Variable(); 110 | if (index_var != nullptr) 111 | { 112 | // get the variable type by name 113 | ScopeVariable* var = ctx.variables().find_by_name(index_var->name); 114 | ScopeVariable::STValInt val_int = var->get_int_value(); 115 | if (val_int.is_set) { 116 | return build_circuit_for_int_index(ctx, *var_array, val_int.value ); 117 | } 118 | } 119 | 120 | //2.1 : complex expression, ex : a[i*j+1] 121 | 122 | //TODO 123 | 124 | // generate an expression like this : 125 | // (a[0] & (I==0)) 126 | // | (a[1] & (I==1)) 127 | // | (a[2] & (I==2)) 128 | // ... 129 | // = a[i] 130 | // generte index circuit from its expression 131 | std::vector index_expression = index->build_circuit(ctx); 132 | 133 | std::vector result; 134 | // (a[i] xor (a[i] & (Index == 0))) 135 | IndexType array_size = get_array_size(*var_array); 136 | assert(array_size > 0); 137 | result = generate_expression_for_index( ctx, *var_array, index_expression, 0); 138 | for (IndexType index_to_test = 1; index_to_test < array_size; index_to_test++) { 139 | // (a[i] xor (a[i] & (Index==i))) ... 140 | std::vector next = generate_expression_for_index(ctx, *var_array, index_expression, index_to_test); 141 | // mix input : a = a | b 142 | result = generate_or(ctx, result, next); 143 | } 144 | // final result : 145 | return result; 146 | } 147 | 148 | // return (a | b) addeded to the circuit 149 | std::vector Expression_ArrayElement::generate_or(BuildContext& ctx, const std::vector& a, const std::vector& b) { 150 | assert(a.size() == b.size()); 151 | std::vector result; 152 | 153 | Gate_OR gate_or; 154 | 155 | // for each bit connect gate input and output 156 | int size = (int)a.size(); 157 | for (int i = 0; i < size; i++) { 158 | // IN 159 | std::array input_2_bit = { a[i], b[i] }; 160 | // OUT = A OP B 161 | std::array bits_result = gate_or.add_to_circuit(ctx.circuit(), input_2_bit); 162 | 163 | //result.insert(result.end(), bits_result.begin(), bits_result.end()); 164 | result.push_back(bits_result[0]); 165 | 166 | } 167 | return result; 168 | 169 | } 170 | // generate the expression a[index] & (expression==index) 171 | // the circuite will return a[index] if expression == index , 0 otherwise 172 | std::vector Expression_ArrayElement::generate_expression_for_index(BuildContext& ctx, const ScopeVariable& var_array, std::vector expression, IndexType index_value) 173 | { 174 | // gate for buildinf 175 | Gate_AND gate_and; 176 | 177 | // get a[index] 178 | std::vector a_at_index = build_circuit_for_int_index(ctx, var_array, index_value); 179 | 180 | // (expression==index] ? 181 | // get a type with the number of bits of the index 182 | TypeBasic type_exp = TypeBasic::get_TypeBasic_for_bitsize((int)expression.size()); 183 | Literal index_as_literal(type_exp, std::to_string(index_value) ); 184 | Scope* no_scope = nullptr; 185 | index_as_literal.init(*no_scope); 186 | std::vector index_as_connexions = index_as_literal.build_circuit(ctx); 187 | std::vector exp_eq_i = TestOperation::build_circuit_equal(ctx, expression, index_as_connexions); 188 | 189 | // a[index] & (expression==index) 190 | std::vector result; 191 | int size = (int)a_at_index.size(); 192 | for (int i = 0; i < size; i++) { 193 | // IN : each bit of a[index] and same bit b = (expression==index) 194 | std::array input_2_bit = { a_at_index[i], exp_eq_i[0] }; 195 | 196 | std::array bits_result = gate_and.add_to_circuit(ctx.circuit(), input_2_bit); 197 | result.push_back(bits_result[0]); 198 | } 199 | 200 | return result; 201 | 202 | 203 | 204 | } 205 | 206 | -------------------------------------------------------------------------------- /src/Expression_ArrayElement.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "Expression.h" 5 | #include "BuildContext.h" 6 | 7 | // expression of the form "my_array[3]" 8 | 9 | using IndexType = int; 10 | 11 | class Expression_ArrayElement : public Expression { 12 | public: 13 | std::string array_name; // ex : "my_array" 14 | Expression* index = nullptr; // index in the array 15 | 16 | const Type* element_type = nullptr; // type the element 17 | int member_offest_in_bit = 0; // offset in bit of the member 18 | 19 | public: 20 | // constructor 21 | Expression_ArrayElement(std::string array_name, Expression* index); 22 | 23 | // get expression type 24 | virtual const Type& get_type(void) const override; 25 | // visit all part used in the Expression 26 | virtual void visit_epression(IVisitExpression& visitor) override; 27 | // init 28 | virtual void init(Scope& parent_scope) override; 29 | 30 | // build the circuit for the expression 31 | virtual std::vector build_circuit(BuildContext& ctx) override; 32 | 33 | protected: 34 | // get the array size = number of elements 35 | IndexType get_array_size(const ScopeVariable& var_array) const; 36 | // build the circuit for the expression for a int index value 37 | std::vector build_circuit_for_int_index(BuildContext& ctx, const ScopeVariable& var_array, IndexType index_value); 38 | // return (a & b) addeded to the circuit 39 | std::vector generate_or(BuildContext& ctx, const std::vector& a, const std::vector& b); 40 | // generate a circuite that will return a[index] if expression == index , 0 otherwise 41 | std::vector generate_expression_for_index(BuildContext& ctx, const ScopeVariable& var_array, std::vector expression, IndexType index_value); 42 | }; -------------------------------------------------------------------------------- /src/Expression_StructMember.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "Program.h" 3 | #include "Expression_StructMember.h" 4 | #include "Error.h" 5 | #include "Scope.h" 6 | 7 | // constructor 8 | Expression_StructMember::Expression_StructMember(std::string p, std::string m) 9 | : parent_name(p), member_name(m) 10 | {} 11 | 12 | 13 | 14 | // get expression type 15 | const Type& Expression_StructMember::get_type(void) const { 16 | if (member_type == nullptr) { 17 | // error :type not yet set 18 | throw Error("Internal error, member type non resolded", member_name); 19 | } 20 | return *member_type; 21 | } 22 | // init 23 | void Expression_StructMember::init(Scope& parent_scope) { 24 | // get the struct parent from name 25 | const VariableDefinition *parent_definition = parent_scope.find_variable_by_name(parent_name); 26 | if (parent_definition == nullptr) { 27 | // error : 'name' not found 28 | throw Error("identifier not found :", parent_name); 29 | } 30 | // must be a struct 31 | assert(parent_definition->type != nullptr); 32 | assert(parent_definition->type->is_complete()); 33 | const TypeStruct* parent_type_struct = parent_definition->type->cast_to_TypeStruct(); 34 | if (parent_type_struct == nullptr) { 35 | // error : parent is not a structure 36 | throw Error("not a structure : ", parent_name); 37 | } 38 | 39 | // get the member type by name 40 | TypeStruct::Member member = parent_type_struct->get_member_by_name(member_name); 41 | if (!member.is_valid) { 42 | // error : member not found 43 | throw Error("member not found : ", member_name); 44 | } 45 | // keep the type and the offset 46 | member_type = member.type; 47 | member_offest_in_bit = member.offest_in_bit; 48 | } 49 | 50 | // get all gates used by the parent struct variable 51 | std::vector Expression_StructMember::get_all_connexions_full_struct(BuildContext& ctx) const { 52 | // get the parent variable type by name 53 | ScopeVariable* var = ctx.variables().find_by_name(parent_name); 54 | if (var == nullptr) 55 | return {}; 56 | // if variable not set 57 | if (!var->is_set()) 58 | return {}; 59 | // return all the bits of the variable 60 | return var->bits; 61 | } 62 | 63 | 64 | // build the circuit for the expression 65 | std::vector Expression_StructMember::build_circuit(BuildContext& ctx) { 66 | // get the parent variable type by name 67 | ScopeVariable* var = ctx.variables().find_by_name(parent_name); 68 | if (var == nullptr) 69 | throw Error("Unknonwn variable : ", parent_name); 70 | // if variable not set 71 | if (!var->is_set()) 72 | throw Error("Uninitialized variable : ", parent_name); 73 | 74 | // set outputs to get the value of the part of variable in the struct 75 | assert(member_type != nullptr); 76 | int member_size = member_type->size_in_bit(); 77 | auto begin_member = var->bits.begin() + member_offest_in_bit; 78 | std::vector < Connection*> bits_member(begin_member, begin_member + member_size); 79 | assert(bits_member.size() == member_type->size_in_bit()); 80 | return bits_member; 81 | 82 | } 83 | 84 | 85 | -------------------------------------------------------------------------------- /src/Expression_StructMember.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "Expression.h" 5 | #include "BuildContext.h" 6 | 7 | // expression of the form "mystruct.member" 8 | 9 | class Expression_StructMember : public Expression { 10 | public: 11 | std::string parent_name; // ex : "mystruct" 12 | std::string member_name; // ex : "member" 13 | 14 | Type* member_type = nullptr; // type the var 15 | int member_offest_in_bit = 0; // offset in bit of the member in the struct 16 | 17 | public: 18 | // constructor 19 | Expression_StructMember(std::string parent_var, std::string member_name); 20 | 21 | // get expression type 22 | virtual const Type& get_type(void) const override; 23 | // visit all part used in the Expression 24 | virtual void visit_epression(IVisitExpression& visitor) override { visitor.onVariableInStruct(*this); } 25 | // init 26 | virtual void init(Scope& parent_scope) override; 27 | // get all gates used by the parent struct variable 28 | std::vector get_all_connexions_full_struct(BuildContext& ctx) const; 29 | // build the circuit for the expression 30 | virtual std::vector build_circuit(BuildContext& ctx) override; 31 | }; -------------------------------------------------------------------------------- /src/Expression_Variable.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maitrebitcoin/bitcoin-bitvm-compiler/03e3939492b925f1a9d28a05442a77817118b276/src/Expression_Variable.cpp -------------------------------------------------------------------------------- /src/Expression_Variable.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class BuildContext; 4 | 5 | 6 | // a variable usage in an expression 7 | class Expression_Variable: public VariableDefinition, public Expression { 8 | public: 9 | // constructor 10 | Expression_Variable(std::string n) : VariableDefinition( (Type *)nullptr, n) {} 11 | // cast to Expression_Variable 12 | virtual Expression_Variable* cast_to_Expression_Variable(void) override { return this; } 13 | // get Operand type 14 | const Type& get_type(void) const { assert(type != nullptr); return *type; } 15 | // visit all part used in the Expression 16 | virtual void visit_epression(IVisitExpression& visitor) override { visitor.onVariable(*this); } 17 | 18 | // init, will grag the type from the symbol table 19 | virtual void init(Scope& parent_scope) override; 20 | // get all gates used by the variable 21 | std::vector get_all_connexions(BuildContext& ctx) const; 22 | // build the circuit for the expression 23 | virtual std::vector build_circuit(BuildContext& ctx) override; 24 | }; 25 | 26 | -------------------------------------------------------------------------------- /src/Function.cpp: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | #include 5 | #include "Function.h" 6 | #include "CodeBloc.h" 7 | #include "Error.h" 8 | #include "Circuit.h" 9 | #include "BuildContext.h" 10 | 11 | // function constructor 12 | Function::Function(Definition* def, CodeBloc* fn_body) 13 | : definition(*def) 14 | , body(fn_body) { 15 | } 16 | Function::~Function() { 17 | if (function_scope!=nullptr) 18 | delete function_scope; 19 | } 20 | 21 | // init a function 22 | void Function::init(Scope& parent_scope) { 23 | 24 | // declare function name to the global scope 25 | parent_scope.declare_function(this); 26 | 27 | // create a new scope for the function 28 | function_scope = parent_scope.create_child_scope(); 29 | function_scope->parent_function = this; 30 | 31 | 32 | // init parameters typer 33 | for (Parameter& param : definition.parameters) { 34 | // if the type is just a name, get the real type 35 | if (!param.type->is_complete()) { 36 | const TypeStruct* real_type = parent_scope.find_struct_by_name(param.type->get_name()); 37 | if (real_type == nullptr) 38 | throw Error("Unknown type : ", param.type->get_name()); 39 | param.type = const_cast(real_type); 40 | } 41 | } 42 | 43 | // init body 44 | body->init(*function_scope); 45 | } 46 | 47 | 48 | // return the number of bits needed for the input parameters 49 | int Function::size_in_bit_input(void) const 50 | { 51 | // addd the size of each parameter 52 | int nb_bit = 0; 53 | for (Parameter param_i : definition.parameters) 54 | nb_bit += param_i.type->size_in_bit(); 55 | return nb_bit; 56 | } 57 | // return the number of bits needed to store the return value 58 | int Function::size_in_bit_output(void) const { 59 | // size of the return type 60 | return definition.return_type->size_in_bit(); 61 | } 62 | 63 | // Function Definition constructor 64 | Function::Definition::Definition(Type* type, std::string function_name, Function::AllParameter* all_params) 65 | : return_type(type) 66 | , name(function_name) 67 | { 68 | assert(function_name.size() > 0); 69 | // copy the parameters 70 | for (Parameter param_i : all_params->parameters) 71 | parameters.push_back(param_i); 72 | } 73 | 74 | 75 | // find a parameter by name 76 | const VariableDefinition* Function::find_parameter_by_name(std::string name) const { 77 | for (const Parameter& param_i : definition.parameters) 78 | { 79 | if (param_i.name == name) 80 | return ¶m_i; 81 | } 82 | return nullptr; 83 | } 84 | 85 | 86 | // build a circuit that represents the fuidl 87 | void Function::build_circuit(BuildContext &ctx) const { 88 | // declare inputs 89 | int nb_bits_in = size_in_bit_input(); 90 | InterfaceInputsMap* input_map = getInterfaceInputsMap(); 91 | ctx.circuit().set_circuit_inputs(nb_bits_in, input_map); 92 | // get input 93 | std::vector current_input = ctx.circuit().getInputs(); 94 | 95 | // init scope variables in the contente 96 | ctx.variables().init_from_function_parameters(definition, current_input); 97 | 98 | ctx.build_all_next_statements = [](BuildContext&) { 99 | // error if the generation calls here : 100 | throw Error("Internal error : missing return"); 101 | return BuildContext::NextAction::Return; 102 | }; 103 | ctx.build_on_break = [](BuildContext&) { 104 | // error if the generation calls here : 105 | throw Error("Internal error : unexprected break"); 106 | return BuildContext::NextAction::Break; 107 | }; 108 | 109 | // build the body 110 | try { 111 | BuildContext::NextAction action = body->build_circuit(ctx); 112 | if (action != BuildContext::NextAction::Return) 113 | throw Error("Missing return statement"); 114 | } 115 | catch (Error& e) { 116 | //add fucntion name info to the error 117 | e.function_name = definition.name; 118 | throw e; 119 | } 120 | 121 | } 122 | 123 | class FunctionInputsMap : public InterfaceInputsMap 124 | { 125 | public: 126 | std::map map; 127 | public: 128 | // get a parameter info by name 129 | virtual Info find_info_by_name(std::string name) const override { 130 | InterfaceInputsMap::Info param_info; 131 | auto it = map.find(name); 132 | if (it == map.end()) { 133 | param_info.found = false; 134 | return param_info; 135 | } 136 | else { 137 | return it->second; 138 | } 139 | } 140 | }; 141 | // get a interface n InterfaceInputsMap 142 | InterfaceInputsMap* Function::getInterfaceInputsMap(void) const 143 | { 144 | FunctionInputsMap * new_input_map = new FunctionInputsMap(); 145 | // init map 146 | int offset_in_bit = 0; 147 | for (Parameter param_i : definition.parameters) { 148 | // int param info in map 149 | InterfaceInputsMap::Info param_info; 150 | param_info.found = true; 151 | param_info.type = param_i.type->get_copy(); 152 | param_info.offset_in_bit = offset_in_bit; 153 | new_input_map->map[param_i.name] = param_info; 154 | // update offset 155 | offset_in_bit += param_i.type->size_in_bit(); 156 | } 157 | return new_input_map; 158 | } -------------------------------------------------------------------------------- /src/Function.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include "VariableDefinition.h" 6 | #include "InterfaceInputsMap.h" 7 | class CodeBloc; 8 | class Scope; 9 | class BuildContext; 10 | 11 | // represents a function, ex : bool main(bool a, bool b) { return a & b; } 12 | class Function { 13 | public: 14 | // 1 parameters of the function 15 | struct Parameter : VariableDefinition { 16 | // constructor 17 | Parameter(Type* t, std::string n) : VariableDefinition(t, n) {} 18 | }; 19 | // all the parameters of the function 20 | struct AllParameter { 21 | std::vector parameters; 22 | // constructor : init with 1 parameter 23 | AllParameter(Parameter& p0) { 24 | parameters.push_back(p0); 25 | } 26 | // add 1 parameter 27 | void add(Parameter& p) { 28 | parameters.push_back(p); 29 | } 30 | }; 31 | // Definition of the function 32 | struct Definition { 33 | // name of the function 34 | std::string name; 35 | // return type of the function 36 | Type* return_type; 37 | // parameters of the function 38 | std::vector parameters; 39 | // constructor 40 | Definition(Type* t, std::string n, Function::AllParameter* all_params); 41 | }; 42 | 43 | protected: 44 | // definiton of the function 45 | Definition definition; 46 | // body of the function 47 | CodeBloc* body; 48 | // scope of the function 49 | Scope* function_scope=nullptr; 50 | 51 | public: 52 | // constructor 53 | Function(Definition* def, CodeBloc* body); 54 | ~Function(); 55 | // init a function 56 | void init(Scope& global_scope); 57 | // get the name of the function 58 | std::string get_name(void) const { return definition.name; } 59 | // get the return type of the function 60 | const Type& get_return_type(void) const { return *definition.return_type; } 61 | // definiton of the function 62 | const Definition& get_definition(void) const { return definition; } 63 | // return the number of bits needed for the input parameters 64 | int size_in_bit_input(void) const; 65 | // return the number of bits needed to store the return value 66 | int size_in_bit_output(void) const; 67 | // find a parameter by name 68 | const VariableDefinition* find_parameter_by_name(std::string name) const; 69 | // build a circuit that represents the function 70 | void build_circuit(BuildContext& ctx) const; 71 | 72 | // get a interface n InterfaceInputsMap 73 | InterfaceInputsMap* getInterfaceInputsMap(void) const; 74 | 75 | }; 76 | 77 | -------------------------------------------------------------------------------- /src/Gate.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // all available gates 4 | #include "TapScriptGate.h" 5 | #include "CompositedGate.h" 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/IGate.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "Connection.h" 5 | class Circuit; 6 | 7 | // represents the base class of any logical gatet, basic or composited 8 | class IGate { 9 | 10 | public: 11 | // get the inputs of the gate 12 | virtual std::vector get_inputs(void) const = 0; 13 | // get the outputs of the gate 14 | virtual std::vector get_outputs(void) const = 0; 15 | 16 | }; 17 | 18 | 19 | // tamplate that represents a gate with N inputs and M outputs 20 | // GateBaseClass must be either TapScriptGate or CompositedGate 21 | template 22 | class T_NMGate : public GateBaseClass 23 | { 24 | protected: 25 | // inputs and outputs of the gate 26 | std::array input; 27 | std::array output; 28 | 29 | public: 30 | // constructor 31 | T_NMGate(void) { 32 | _init_output(); 33 | } 34 | // init in connexions ( from others gates ) 35 | void set_inputs(std::array& input) { 36 | this->input = input; 37 | } 38 | 39 | // get the outputs of the gate 40 | virtual std::vector get_outputs(void) const override { 41 | std::vector connections(output.begin(), output.end()); 42 | return std::move(connections); 43 | } 44 | // get the inputs of the gate 45 | virtual std::vector get_inputs(void) const override { 46 | std::vector connections(input.begin(), input.end()); 47 | return std::move(connections); 48 | } 49 | 50 | // to bez implemented by the derived class : 51 | 52 | // add a gate into the circuir 53 | virtual std::array add_to_circuit(Circuit& circuit, std::array& _input) = 0; 54 | 55 | protected: 56 | // init out connexions 57 | void _init_output(void) { 58 | for (int i = 0; i < M; i++) { 59 | output[i] = new Connection(); 60 | } 61 | } 62 | }; //T_NMGate -------------------------------------------------------------------------------- /src/InterfaceInputsMap.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | class Type; 5 | 6 | // interface for input correspondance 7 | class InterfaceInputsMap { 8 | public: 9 | struct Info { 10 | bool found= false; 11 | int index=0; 12 | int offset_in_bit=0; 13 | Type* type=nullptr; 14 | }; 15 | // get a parameter info by name 16 | virtual Info find_info_by_name(std::string name) const = 0; 17 | }; -------------------------------------------------------------------------------- /src/LangageAttributes.cpp: -------------------------------------------------------------------------------- 1 | // definetion of the class LangageAttributes 2 | 3 | #include "LangageAttributes.h" 4 | #include "Program.h" 5 | 6 | /* 7 | enum Operator { 8 | invalid_operator = -1, 9 | op_and, 10 | op_or, 11 | op_xor, 12 | op_add, 13 | op_sub, 14 | op_left_shift, 15 | op_right_shift, 16 | op_test_equal, 17 | op_test_not_equal, 18 | op_test_lower, 19 | op_test_lower_or_equal, 20 | op_test_greater, 21 | op_test_greater_or_equal, 22 | op_mult, 23 | op_div, 24 | op_modulo, 25 | 26 | };*/ 27 | static const int invalid_operator = (int)BinaryOperation::Operator::invalid_operator; 28 | static const int _mult = (int)BinaryOperation::Operator::op_mult; 29 | static const int _div = (int)BinaryOperation::Operator::op_div; 30 | static const int _modulo = (int)BinaryOperation::Operator::op_modulo; 31 | static const int _add = (int)BinaryOperation::Operator::op_add; 32 | static const int _sub = (int)BinaryOperation::Operator::op_sub; 33 | static const int _left_shift = (int)BinaryOperation::Operator::op_left_shift; 34 | static const int _right_shift = (int)BinaryOperation::Operator::op_right_shift; 35 | static const int _test_lower = (int)BinaryOperation::Operator::op_test_lower; 36 | static const int _test_lower_or_equal = (int)BinaryOperation::Operator::op_test_lower_or_equal; 37 | static const int _test_greater = (int)BinaryOperation::Operator::op_test_greater; 38 | static const int _test_greater_or_equal = (int)BinaryOperation::Operator::op_test_greater_or_equal; 39 | static const int _test_equal = (int)BinaryOperation::Operator::op_test_equal; 40 | static const int _test_not_equal = (int)BinaryOperation::Operator::op_test_not_equal; 41 | static const int _op_and = (int)BinaryOperation::Operator::op_and; 42 | static const int _op_xor = (int)BinaryOperation::Operator::op_xor; 43 | static const int _op_or = (int)BinaryOperation::Operator::op_or; 44 | 45 | struct PrecedenceLevel { 46 | BinaryOperation_Operator ops[5]; 47 | }; 48 | // operators precedence : the same a C / C++ 49 | PrecedenceLevel PrecedenceLevels[] = { 50 | // ==> will be evaluated first. 51 | {_mult, _div, _modulo, invalid_operator}, // * / % 52 | {_add, _sub, invalid_operator}, // + - 53 | {_left_shift, _right_shift, invalid_operator}, // << >> 54 | {_test_lower, _test_lower_or_equal, _test_greater, _test_greater_or_equal, invalid_operator}, // < <= > >= 55 | {_test_equal, _test_not_equal, invalid_operator}, // == != 56 | {_op_and, invalid_operator}, // & and 57 | {_op_xor, invalid_operator}, // ^ xor 58 | {_op_or, invalid_operator}, // | or 59 | // will be evaluated last 60 | }; 61 | 62 | 63 | // constructor 64 | LangageAttributes::LangageAttributes(void) { 65 | // init operators precedence 66 | int nb_level = sizeof(PrecedenceLevels) / sizeof(PrecedenceLevels[0]); 67 | int current_level = 1; 68 | for (int i = 0; i < nb_level; i++) { 69 | PrecedenceLevel level = PrecedenceLevels[i]; 70 | for (int j = 0; level.ops[j] != invalid_operator; j++) { 71 | // add the operator to the map 72 | operator_precedence[level.ops[j]] = i + 1; 73 | } 74 | } 75 | } 76 | // comparae operator precedence 77 | int LangageAttributes::compare_operator_precedence(BinaryOperation_Operator a, BinaryOperation_Operator b) const { 78 | // lookup for the precedence of the operator 79 | auto pos_a = operator_precedence.find(a); 80 | if (pos_a == operator_precedence.end()) { 81 | // not found 82 | assert(false); 83 | return 0; 84 | } 85 | int precedence_a = pos_a->second; 86 | auto pos_b = operator_precedence.find(b); 87 | if (pos_b == operator_precedence.end()) { 88 | // not found 89 | assert(false); 90 | return 0; 91 | } 92 | int precedence_b = pos_b->second; 93 | assert(precedence_a >= 0); 94 | assert(precedence_b >= 0); 95 | return (precedence_a - precedence_b); 96 | } 97 | 98 | -------------------------------------------------------------------------------- /src/LangageAttributes.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | // somme attributes of the langage 6 | using BinaryOperation_Operator = int; 7 | class LangageAttributes { 8 | protected: 9 | // return precdence number for a operation token. 0 = highest precedence, 100 = lowest precedence 10 | // key = , value = precedence number 11 | std::map < BinaryOperation_Operator, int > operator_precedence; 12 | 13 | public: 14 | // constructor 15 | LangageAttributes(); 16 | // comparae operator precedence. ex "+" vs "<<" 17 | int compare_operator_precedence(BinaryOperation_Operator operator_1, BinaryOperation_Operator operator_2) const; 18 | }; -------------------------------------------------------------------------------- /src/Literal.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "Program.h" 3 | #include "Error.h" 4 | #include "Circuit.h" 5 | 6 | // constructor 7 | Literal::Literal(TypeBasic t, std::string v) 8 | : type(t) 9 | , value_str(v) 10 | {} 11 | 12 | // lietral init 13 | void Literal::init(Scope&) { 14 | // init value from type ans source string 15 | // ex: "0x12" => 0x12 16 | value_bits = get_bools_from_value_str(type.get_native_type(), value_str); 17 | } 18 | // change literal type. ex int8 to int256 19 | void Literal::change_type(const Type& new_type) 20 | { 21 | // new type must be a basic type 22 | if (!new_type.is_basic()) 23 | throw Error("Invalid literal type"); 24 | // bool cannot be converted to other type 25 | if (type.get_native_type() == Type::Native::bit ) 26 | throw Error("Cannot convert bool to other type"); 27 | assert(new_type.is_integer()); 28 | 29 | // get new type 30 | Type::Native tn = new_type.cast_to_TypeBasic()->get_native_type(); 31 | // set type 32 | type.set_native_type( tn ); 33 | // reset value 34 | value_bits = get_bools_from_value_str(type.get_native_type(), value_str); 35 | 36 | } 37 | 38 | 39 | // get value of liette as a vector of bit 40 | std::vector Literal::get_bools_from_value_str(Type::Native native_type, std::string value_str) { 41 | switch (native_type) 42 | { 43 | case Type::Native::bit: 44 | return _get_bits_value_bool(value_str); 45 | case Type::Native::int8: 46 | return _get_bits_value_int8(value_str, Sign::signed_); 47 | case Type::Native::uint8: 48 | return _get_bits_value_int8(value_str, Sign::unsigned_); 49 | case Type::Native::int32: 50 | return _get_bits_value_int32(value_str, Sign::signed_); 51 | case Type::Native::uint32: 52 | return _get_bits_value_int32(value_str, Sign::unsigned_); 53 | case Type::Native::int64: 54 | return _get_bits_value_int64(value_str, Sign::signed_); 55 | case Type::Native::uint64: 56 | return _get_bits_value_int64(value_str, Sign::unsigned_); 57 | case Type::Native::int256: 58 | return _get_bits_value_int256(value_str, Sign::signed_); 59 | case Type::Native::uint256: 60 | return _get_bits_value_int256(value_str, Sign::unsigned_); 61 | default: 62 | throw Error("Invalid literal type"); 63 | } 64 | } 65 | // get value of an int as a vector of connexions 66 | std::vector Literal::get_connections_from_value_int(BuildContext& ctx, const Type& type, int value_int) { 67 | 68 | assert(type.is_integer()); 69 | 70 | int nbBit = type.size_in_bit(); 71 | 72 | // convert to bits in low endian (x86 format) 73 | std::vector result; 74 | for (int i = 0; i < nbBit; i++) 75 | { 76 | bool b = value_int & 1; 77 | value_int >>= 1; 78 | 79 | // get literal value as a vector of bits 80 | Connection* connection_to_0or1 = ctx.circuit().get_literal_values(b); 81 | result.push_back(connection_to_0or1); 82 | 83 | } 84 | return result; 85 | 86 | } 87 | 88 | 89 | 90 | // convert the value of the literal to a vector of bits for byte type 91 | // convert to bits in low endian (x86 format) 92 | // result[0] is the least significant bit, result[7] is the most significant bit 93 | std::vector Literal::_get_bits_value_int8(std::string str_val, Sign signed_) { 94 | std::vector result; 95 | // conver to integer 96 | int value_int8 = _get_int_value(str_val); 97 | // value must be in 8bit signed range 98 | bool is_signed = (signed_ == Sign::signed_); 99 | int min = is_signed ? -128 : 0; 100 | int max = is_signed ? 127 : 255; 101 | if (value_int8 > max || value_int8 < min) 102 | throw Error("Invalid 8 bit value : ", str_val); 103 | // convert to bits in low endian (x86 format) 104 | for (int i = 0; i < 8; i++) 105 | { 106 | bool b = value_int8 & 1; 107 | result.push_back(b); 108 | value_int8 >>= 1; 109 | } 110 | return result; 111 | } 112 | // convert the value of the literal to a vector of bits for byte type 113 | // convert to bits in low endian (x86 format) 114 | // result[0] is the least significant bit, result[31] is the most significant bit 115 | std::vector Literal::_get_bits_value_int32(std::string str_val, Sign signed_) { 116 | std::vector result; 117 | // conver to integer 118 | int64_t value_int32 = _get_int_value(str_val); 119 | // value must be in 8bit signed range 120 | bool is_signed = (signed_ == Sign::signed_); 121 | int64_t min = is_signed ? -2147483648 : 0; 122 | int64_t max = is_signed ? 0x7FFFFFFF : 0xFFFFFFFF; 123 | if (value_int32 > max || value_int32 < min) 124 | throw Error("Invalid 32 bit value : ", str_val); 125 | 126 | // convert to bits in low endian (x86 format) 127 | for (int i = 0; i < 32; i++) 128 | { 129 | bool b = value_int32 & 1; 130 | result.push_back(b); 131 | value_int32 >>= 1; 132 | } 133 | return result; 134 | } 135 | // convert the value of the literal to a vector of bits for byte type 136 | // convert to bits in low endian (x86 format) 137 | // result[0] is the least significant bit, result[61] is the most significant bit 138 | std::vector Literal::_get_bits_value_int64(std::string str_val, Sign signed_) { 139 | std::vector result; 140 | 141 | // convert to integer 142 | uint64_t value_uint64 = 0; 143 | if (signed_ == Sign::signed_) 144 | value_uint64 = (uint64_t)_get_int64_value(str_val); 145 | else 146 | value_uint64 = _get_uint64_value(str_val); 147 | // convert to bits in low endian (x86 format) 148 | for (int i = 0; i < 32; i++) 149 | { 150 | bool b = value_uint64 & 1; 151 | result.push_back(b); 152 | value_uint64 >>= 1; 153 | } 154 | return result; 155 | } 156 | 157 | // check if the string is in hexa format 158 | // ex: 0x12 159 | bool is_hexa_format(std::string value_str) { 160 | return(value_str.size() > 2 && value_str[0] == '0' && value_str[1] == 'x'); 161 | } 162 | // convert hex char to int 163 | int hex_char_to_int(char c) 164 | { 165 | // convert to int 166 | int value = 0; 167 | if (c >= '0' && c <= '9') 168 | value = c - '0'; 169 | else if (c >= 'a' && c <= 'f') 170 | value = c - 'a' + 10; 171 | else if (c >= 'A' && c <= 'F') 172 | value = c - 'A' + 10; 173 | else 174 | throw Error("Invalid hex string"); 175 | return value; 176 | } 177 | 178 | 179 | // convert the value of the literal to a vector of bits for byte type 180 | // convert to bits in low endian (x86 format) 181 | // result[0] is the least significant bit, result[61] is the most significant bit 182 | std::vector Literal::_get_bits_value_int256(std::string str_val, Sign signed_) { 183 | // only hex string is supported 184 | if (!is_hexa_format(str_val)) 185 | throw Error("Invalid 256 bit value : ", str_val); 186 | // max len si 256 bits = 64 hexa chars 187 | if (str_val.size() > 66) 188 | throw Error("Invalid 256 bit value : ", str_val); 189 | // compute the number with 0 190 | size_t nb_zero = 64 - str_val.size() + 2; 191 | if (nb_zero>0) 192 | str_val.append(nb_zero,'0'); 193 | 194 | // get string wihout prefix "0x" 195 | std::string str_hex_without_prefix = str_val.substr(2); 196 | 197 | // convert to bits in low endian (x86 format) 198 | // being woth low bits first 199 | std::vector result = hex_string_to_bits(str_hex_without_prefix); 200 | assert(result.size() == 256); 201 | return result; 202 | 203 | } 204 | 205 | 206 | // convert hex string to array of bits in low endian 207 | std::vector Literal::hex_string_to_bits(std::string hex_string) { 208 | // for eah char in hex string, starting from the end 209 | std::vector result; 210 | for (int i = (int)hex_string.size() - 1; i >= 0; i--) 211 | { 212 | // get the char 213 | char c = hex_string[i]; 214 | // convert to int 215 | int value = hex_char_to_int(c); 216 | // convert to bits le 217 | for (int j = 0; j < 4; j++) 218 | { 219 | bool b = value & 1; 220 | result.push_back(b); 221 | value >>= 1; 222 | } 223 | } 224 | return result; 225 | } 226 | 227 | 228 | // convert the value of the literal to a vector of bits for bool type 229 | std::vector Literal::_get_bits_value_bool(std::string str_val) { 230 | std::vector result; 231 | if (str_val == "true") 232 | result = { true }; 233 | else if (str_val == "false") 234 | result = { false }; 235 | else 236 | throw Error("Invalid boolean value : ", str_val); 237 | return result; 238 | } 239 | 240 | 241 | // value of the literal has int. only for int type 242 | int Literal::get_int_value(void) { 243 | assert(get_type().is_integer()); 244 | return _get_int_value(value_str); 245 | } 246 | // static version 247 | int Literal::_get_int_value(std::string value_str) { 248 | // if the is hexa. ex :"0xED" 249 | if (value_str.size() > 2 && value_str[0] == '0' && value_str[1] == 'x') 250 | return std::stoi(value_str, nullptr, 16); 251 | // value is decimal ex; "123" 252 | return std::stoi(value_str); 253 | } 254 | int64_t Literal::_get_int64_value(std::string value_str) { 255 | // if the is hexa. ex :"0xED123EDA34" 256 | if (value_str.size() > 2 && value_str[0] == '0' && value_str[1] == 'x') 257 | return std::stoll(value_str, nullptr, 16); 258 | // value is decimal ex; "12344554768041" 259 | return std::stoll(value_str); 260 | 261 | } 262 | uint64_t Literal::_get_uint64_value(std::string str_val) { 263 | // if the is hexa. ex :"0xED123EDA34" 264 | if (str_val.size() > 2 && str_val[0] == '0' && str_val[1] == 'x') 265 | return std::stoull(str_val, nullptr, 16); 266 | // value is decimal ex; "12344554768041" 267 | return std::stoull(str_val); 268 | } 269 | 270 | std::vector Literal::build_circuit(BuildContext& ctx) { 271 | std::vector result; 272 | 273 | assert(type.size_in_bit() == value_bits.size()); 274 | // get a 0 ou 1 connexion for each bit 275 | for (int i = 0; i < type.size_in_bit(); i++) { 276 | // get the bit value 277 | bool b = value_bits[i]; 278 | // get literal value as a vector of bits 279 | Connection* connection_to_0or1 = ctx.circuit().get_literal_values(b); 280 | result.push_back(connection_to_0or1); 281 | } 282 | 283 | return result; 284 | } 285 | -------------------------------------------------------------------------------- /src/Literal.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Expression.h" 4 | #include "Type.h" 5 | 6 | // ex: 123 7 | class Literal : public Expression { 8 | public: 9 | // type of the literal 10 | TypeBasic type; 11 | // value of the literal is string forme 12 | std::string value_str; 13 | // value of the literal in individuals bits 14 | std::vector value_bits; 15 | public: 16 | // constructor 17 | Literal(TypeBasic t, std::string v); 18 | // visit all part used in the Expression 19 | virtual void visit_epression(IVisitExpression& visitor) override { visitor.onLiteral(*this); } 20 | // get Operand type 21 | virtual const Type& get_type(void) const override { return type; } 22 | // if the expression is a littrela, return it 23 | virtual Literal* cast_to_literal(void) override { return this; } 24 | // value of the literal has int. only for int type 25 | int get_int_value(void); 26 | static int _get_int_value(std::string str_val); 27 | static int64_t _get_int64_value(std::string str_val); 28 | static uint64_t _get_uint64_value(std::string str_val); 29 | 30 | // init 31 | virtual void init(Scope& parent_scope) override; 32 | // change literal type. ex int8 to int256 33 | void change_type(const Type& new_type); 34 | // build the circuit for the expression 35 | virtual std::vector build_circuit(BuildContext& ctx) override; 36 | 37 | // get value of litteral string as a vector of bit 38 | static std::vector get_bools_from_value_str(Type::Native native_type, std::string value_str); 39 | // convert hex string of any size to array of bits in low endian 40 | static std::vector hex_string_to_bits(std::string hex_string); 41 | // get value of an int as a vector of connexions 42 | static std::vector get_connections_from_value_int(BuildContext& ctx, const Type& type, int value_int); 43 | 44 | 45 | protected: 46 | // convert the value of the literal to a vector of bits for bool type 47 | static std::vector _get_bits_value_bool(std::string str_val); 48 | // convert the value of the literal to a vector of bits for byte type 49 | // convert to bits in low endian (x86 format) 50 | // result[0] is the least significant bit, result[7] is the most significant bit 51 | enum class Sign { signed_, unsigned_ }; 52 | static std::vector _get_bits_value_int8(std::string str_val, Sign signed_) ; 53 | static std::vector _get_bits_value_int32(std::string str_val, Sign signed_) ; 54 | static std::vector _get_bits_value_int64(std::string str_val, Sign signed_) ; 55 | static std::vector _get_bits_value_int256(std::string str_val, Sign signed_) ; 56 | }; 57 | -------------------------------------------------------------------------------- /src/Main.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maitrebitcoin/bitcoin-bitvm-compiler/03e3939492b925f1a9d28a05442a77817118b276/src/Main.cpp -------------------------------------------------------------------------------- /src/ParsingContext.cpp: -------------------------------------------------------------------------------- 1 | // context durent parsing, 2 | // to help toke identification anad keep line numbers for error messages 3 | 4 | #include "ParsingContext.h" 5 | #include "Compiler.h" 6 | #include "TokenId.h" 7 | #include "Compiler.h" 8 | 9 | // called when '{' is found 10 | void ParsingContext::open_bracket(void) { 11 | opened_bracket++; 12 | in_body = true; 13 | in_set_var_possible = true; 14 | } 15 | void ParsingContext::close_bracket(void) { 16 | opened_bracket--; 17 | if (opened_bracket<0) 18 | throw Error( "unexpected '}' "); 19 | 20 | in_body = (opened_bracket > 0); 21 | } 22 | 23 | // caled for a new line 24 | void ParsingContext::on_new_line(void) { 25 | num_line++; 26 | } 27 | 28 | // caled for each new token 29 | void ParsingContext::on_new_token(const CToken& token, const CLexer& lexer) 30 | { 31 | // bracket counting 32 | if (token.type == '{') 33 | open_bracket(); 34 | if (token.type == '}') { 35 | close_bracket(); 36 | in_declare_struct = false; 37 | } 38 | // parenthesis counting 39 | if (token.type == '(') 40 | opened_parenthesis++; 41 | if (token.type == ')') 42 | { 43 | opened_parenthesis--; 44 | } 45 | 46 | 47 | if (token.type == TOKEN_KEYWORKD_STRUCT) 48 | in_declare_struct = true; 49 | if (token.type == TOKEN_USE_STRUCT) 50 | in_use_struct = true; 51 | else if (token.type != '.' && token.type != TOKEN_USE_STRUCT_MEMBER) 52 | in_use_struct = false; 53 | 54 | // in function declaration 55 | if (!in_body) 56 | { 57 | if (token.type == '(') 58 | in_fn_param = true; 59 | if (token.type == ')') 60 | in_fn_param = false; 61 | } 62 | // in function body 63 | if (in_body) 64 | { 65 | // in declation of type in body 66 | if (is_token_type(token.type)) // frorm TOKEN_TYPE_BOOL to TOKEN_TYPE_UINT256 67 | { 68 | in_decl_localvar = true; 69 | in_set_var_possible = false; 70 | } 71 | // for "bool b=a" case : 72 | if (token.type == TOKEN_IDENTIFIER_DECL) { 73 | in_decl_localvar = false; 74 | } 75 | // end of statement 76 | if (token.type == ';') { 77 | in_decl_localvar = false; 78 | in_set_var_possible = true; 79 | } 80 | if ( (token.type != ';') // after a statement 81 | && (token.type != '{') // begin of block 82 | && (token.type != '}')) // afeter end of block. ex; "if (a) {}\nint8 b=3;" 83 | { 84 | // any token afer ';' or '{' cannot be a affecation 85 | in_set_var_possible = false; 86 | } 87 | // for () : enterind ans exiting 88 | if (token.type == TOKEN_KEYWORKD_FOR) 89 | in_for_statement = true; 90 | if (in_for_statement && token.type == ')' && opened_parenthesis==0) 91 | in_for_statement = false; 92 | 93 | 94 | } 95 | 96 | // to avoid confustion between a and a[2] 97 | CToken next_token = lexer.get_next_token_const(); 98 | next_token_type = next_token.type; 99 | 100 | 101 | } 102 | -------------------------------------------------------------------------------- /src/ParsingContext.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class CToken; 4 | class CLexer; 5 | 6 | // parsing context 7 | class ParsingContext { 8 | public: 9 | int opened_bracket = 0; // number of opened bracket 10 | int opened_parenthesis = 0; // number of opened parenthesis 11 | bool in_body = false; 12 | bool in_declare_struct = false; // in a struct declaration 13 | bool in_use_struct = false; // in struct.membeer 14 | bool in_fn_param = false; 15 | bool in_decl_localvar = false; 16 | bool in_set_var_possible = false; 17 | bool in_for_statement = false; // in the for (a,b,c) statement 18 | int next_token_type = 0; 19 | int num_line = 0; 20 | public: 21 | // caled for each new token 22 | void on_new_token(const CToken& token, const CLexer& lexer); 23 | // caled for a new line 24 | void on_new_line(void); 25 | // get current line number 26 | int get_current_line_number(void) const { return num_line; } 27 | 28 | protected: 29 | // called when '{' is found 30 | void open_bracket(void); 31 | void close_bracket(void); 32 | }; 33 | -------------------------------------------------------------------------------- /src/Program.cpp: -------------------------------------------------------------------------------- 1 | // Implentation of the BtcContract class and its sub-classes 2 | 3 | #include "Program.h" 4 | #include 5 | #include "Error.h" 6 | #include "Circuit.h" 7 | #include "LangageGrammar.h" 8 | #include "BuildContext.h" 9 | 10 | // add structures to the program as bloc before the main function 11 | void Program::add_struct_definition(CodeBloc* bloc ) { 12 | // check that there are only struct definitions 13 | for (Statement* statement : bloc->statements) 14 | { 15 | // if the instruction is not a struct definition 16 | if (statement->cast_to_Statement_DeclareStruct() == nullptr) 17 | throw Error("Only struct definitions are allowed before functions"); 18 | } 19 | // keep the bloc 20 | struct_definitions = bloc; 21 | } 22 | 23 | // add a N function to the program 24 | void Program::add_array_function(std::vector* tabf) { 25 | // add the functions vector 26 | for (Function* f : *tabf) 27 | add_function(f); 28 | } 29 | 30 | // add a function to the program 31 | void Program::add_function(Function* f) { 32 | // si the function name is not already used 33 | if (find_function_by_name(f->get_name())) 34 | { 35 | throw Error("Function name already used"); 36 | } 37 | // add the functions vector 38 | functions.push_back(f); 39 | } 40 | // get a function by name 41 | Function* Program::find_function_by_name(std::string name) const { 42 | for (Function* f : functions) 43 | { 44 | if (f->get_name() == name) 45 | return f; 46 | } 47 | return nullptr; 48 | } 49 | // get main function 50 | Function* Program::main_function(void) const { 51 | return find_function_by_name("main"); 52 | } 53 | 54 | // init program tree, phase 2 of compilation 55 | void Program::init_and_check_program_tree(void) { 56 | // init struct 57 | if (struct_definitions != nullptr) 58 | { 59 | for (Statement* statement_struct : struct_definitions->statements) 60 | statement_struct->init(*this); 61 | } 62 | 63 | // init check functions 64 | for (Function* f : functions) 65 | f->init(*this); 66 | // check main function 67 | if (main_function() == nullptr) 68 | throw Error("No main function"); 69 | // OK 70 | } 71 | 72 | // build a circuit that represents the program 73 | void Program::build_circuit(BuildContext& build_context) { 74 | 75 | // getk main function 76 | Function& fn_main = *main_function(); 77 | 78 | // build the circuit for the main function 79 | fn_main.build_circuit(build_context); 80 | 81 | // init id for all gates and connections of all circuits 82 | int connection_id = 0; 83 | int circuit_id = 20000; // start a 20000 for debug purposes 84 | build_context.visit_circuits([&](Circuit& circuit) { 85 | circuit.set_id(circuit_id); 86 | circuit.init_id_gates_and_connexions(connection_id); 87 | circuit_id++; 88 | }); 89 | } 90 | -------------------------------------------------------------------------------- /src/Program.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // code tree after source code parsing 3 | 4 | #include 5 | #include 6 | #include 7 | #include "Type.h" 8 | #include "VariableDefinition.h" 9 | #include "Expression.h" 10 | #include "Expression_StructMember.h" 11 | #include "CodeBloc.h" 12 | #include "Scope.h" 13 | 14 | class Function; 15 | class CodeBloc; 16 | class BuildContext; 17 | class Connection; 18 | class Literal; 19 | class LangageAttributes; 20 | 21 | #include "Literal.h" 22 | #include "Expression_Variable.h" 23 | #include "BinaryOperation.h" 24 | #include "ShiftOperation.h" 25 | #include "UnaryOperation.h" 26 | #include "TestOperation.h" 27 | #include "ShiftOperation.h" 28 | #include "Statement.h" 29 | #include "Statement_Return.h" 30 | #include "Statement_DeclareVar.h" 31 | #include "Statement_SetVar.h" 32 | #include "Statement_DeclareAndSetVar.h" 33 | #include "Statement_DeclareStruct.h" 34 | #include "Statement_Increment.h" 35 | #include "Statement_If.h" 36 | #include "Statement_For.h" 37 | #include "Statement_Break.h" 38 | #include "Statement_Function_Call.h" 39 | 40 | #include "Function.h" 41 | #include "Scope.h" 42 | 43 | // logical representation of de contract 44 | class Program : public Scope { 45 | // structs definitions 46 | CodeBloc *struct_definitions; 47 | // body of the function 48 | std::vector functions; 49 | public: 50 | 51 | // add structures to the program as bloc before the main function 52 | void add_struct_definition(CodeBloc* bloc); 53 | // add a N function to the program 54 | void add_array_function(std::vector* tabf); 55 | // get a function by name 56 | Function* find_function_by_name( std::string name ) const; 57 | // get main function 58 | Function* main_function(void) const; 59 | // init program tree, phase 2 of compilation 60 | void init_and_check_program_tree(void); 61 | 62 | 63 | // build a circuit that represents the program 64 | void build_circuit(class BuildContext &build_context); 65 | 66 | private: 67 | // add a function to the program 68 | void add_function(Function* f); 69 | 70 | }; 71 | 72 | -------------------------------------------------------------------------------- /src/Scope.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "Scope.h" 3 | #include "Function.h" 4 | 5 | // init scope for a code bloc 6 | void Scope::init_CodeBloc(Scope& parent_scp) 7 | { 8 | // init parent function in the scope 9 | parent_function = parent_scp.get_parent_function(); 10 | parent_for_loop = parent_scp.parent_for_loop; 11 | parent_scope = &parent_scp; 12 | } 13 | 14 | 15 | // create a new child scope 16 | Scope* Scope::create_child_scope(void) { 17 | // create a new empty scope 18 | Scope* child_scope = new Scope(); 19 | 20 | // init new scope 21 | child_scope->init_CodeBloc(*this); 22 | return child_scope; 23 | } 24 | 25 | // declare a local variable 26 | void Scope::declare_local_variable(const VariableDefinition& def) { 27 | // add the variable to the list 28 | local_variables.push_back(VariableDefinition{ def }); 29 | } 30 | 31 | // find a variable by name 32 | const VariableDefinition* Scope::find_variable_by_name(std::string var_name) const { 33 | // is it a fiunction parameter ? 34 | if (parent_function != nullptr) // not in the global scope 35 | { 36 | const VariableDefinition* function_param = parent_function->find_parameter_by_name(var_name); 37 | if (function_param != nullptr) 38 | return function_param; 39 | } 40 | // is it a local variable ? 41 | for (const VariableDefinition& var_i : local_variables) 42 | { 43 | if (var_i.name == var_name) 44 | return &var_i; 45 | } 46 | // louk in the parent scope 47 | if (parent_scope != nullptr) 48 | return parent_scope->find_variable_by_name(var_name); 49 | 50 | // not found 51 | return nullptr; 52 | } 53 | 54 | // find a struct type by name 55 | const TypeStruct* Scope::find_struct_by_name(std::string name) const { 56 | for (const TypeStruct& struct_i : know_types) { 57 | if (struct_i.name == name) 58 | return &struct_i; 59 | } 60 | // search the parent 61 | if (parent_scope != nullptr) 62 | return parent_scope->find_struct_by_name(name); 63 | 64 | // look in the parent scope 65 | if (parent_scope != nullptr) 66 | return parent_scope->find_struct_by_name(name); 67 | 68 | // not found 69 | return nullptr; 70 | } 71 | 72 | // find a function by name 73 | const Function* Scope::find_function_by_name(std::string name) const 74 | { 75 | // look in the known functions 76 | for (const Function* func_i : known_functions) 77 | { 78 | if (func_i->get_name() == name) 79 | return func_i; 80 | } 81 | // ask the parent scope 82 | if (parent_scope != nullptr) 83 | return parent_scope->find_function_by_name(name); 84 | 85 | 86 | // unknown function 87 | return nullptr; 88 | } 89 | -------------------------------------------------------------------------------- /src/Scope.h: -------------------------------------------------------------------------------- 1 | // represents a scope in the program 2 | // .variables 3 | // .structures 4 | 5 | #pragma once 6 | 7 | #include 8 | #include "VariableDefinition.h" 9 | #include "TypeStruct.h" 10 | #include "TypeArray.h" 11 | class Function; 12 | class Statement_For; 13 | 14 | class Scope { 15 | public: 16 | // declared local variables 17 | std::vector local_variables; 18 | // declared struct 19 | std::vector know_types; 20 | // declared function 21 | std::vector known_functions; 22 | 23 | 24 | // parent scrope. null for global scope 25 | Scope* parent_scope = nullptr; 26 | // null for global scope, parent function for local scope 27 | Function* parent_function = nullptr; 28 | // for parent loop scope or null 29 | Statement_For* parent_for_loop = nullptr; 30 | 31 | public: 32 | // init scope for a code bloc 33 | void init_CodeBloc(Scope& parent_scp); 34 | // create a new child scope 35 | Scope* create_child_scope(void); 36 | 37 | // find a variable by name 38 | const VariableDefinition* find_variable_by_name(std::string name) const; 39 | // declare a local variable 40 | void declare_local_variable(const VariableDefinition& def); 41 | // find a struct type by name 42 | const TypeStruct* find_struct_by_name(std::string name) const; 43 | // declare a type struct 44 | void declare_struct(const TypeStruct& struct_type) { know_types.push_back(struct_type); } 45 | // is the scope in a for loop ? 46 | bool is_in_for_loop(void) const { return parent_for_loop != nullptr; } 47 | // declare a function 48 | void declare_function(const Function* func) { known_functions.push_back(func); } 49 | // find a function by name 50 | const Function* find_function_by_name(std::string name) const; 51 | 52 | // get the parent function 53 | // return nullptr if global scope 54 | Function* get_parent_function(void) { return parent_function; } 55 | 56 | }; 57 | 58 | -------------------------------------------------------------------------------- /src/ScopeVariable.cpp: -------------------------------------------------------------------------------- 1 | // variables during cirtuit building. 2 | 3 | #include "ScopeVariable.h" 4 | 5 | // set variable value 6 | void ScopeVariable::set_value(const std::vector& value) { 7 | assert(value.size() == type->size_in_bit()); 8 | // set bits 9 | bits = value; 10 | } 11 | // is the variable assigned ? 12 | bool ScopeVariable::is_set(void) const { 13 | return bits.size() > 0; 14 | } 15 | // get the value of the variable as integer, if set 16 | ScopeVariable::STValInt ScopeVariable::get_int_value(void) const 17 | { 18 | if (!is_set()) 19 | return { false, 0 }; 20 | 21 | // 32 bits max 22 | if (bits.size() > 32) 23 | return { false, 0 }; 24 | 25 | // get value of the bits 26 | int value = 0; 27 | for (int i = (int)bits.size()-1; i>=0; i--) 28 | { 29 | // left shift 30 | value <<= 1; 31 | // get bit value 32 | Connection* conn_i = bits[i]; 33 | // if bit not calculataed, failuree : 34 | if (!conn_i->is_calculated()) 35 | return { false, 0 }; 36 | 37 | bool bit = conn_i->get_value(); 38 | if (bit) 39 | value += 1; // bit; 40 | } 41 | return { true, value }; 42 | } 43 | 44 | // find a variable by name 45 | ScopeVariable* ScopeVariables::find_by_name(std::string name) { 46 | for (ScopeVariable* var_i : *this) 47 | { 48 | if (var_i->name == name) 49 | return var_i; 50 | } 51 | return nullptr; 52 | } 53 | // Init from function defintion ans parameters 54 | void ScopeVariables::init_from_function_parameters( 55 | const Function::Definition& definition, 56 | std::vector& current_input) 57 | { 58 | 59 | // init known variables 60 | int index = 0; 61 | for (const Function::Parameter& param_i : definition.parameters) 62 | { 63 | ScopeVariable* var_i = new ScopeVariable(param_i.type, param_i.name); 64 | int size = param_i.type->size_in_bit(); 65 | var_i->bits.assign(current_input.begin() + index, 66 | current_input.begin() + index + size); 67 | this->push_back(var_i); 68 | index += var_i->type->size_in_bit(); 69 | } 70 | } 71 | 72 | // declare a new local variable 73 | void ScopeVariables::declare_local_var(Type* var_type, std::string var_name) { 74 | 75 | ScopeVariable* new_var = new ScopeVariable( var_type, var_name ); 76 | push_back(new_var); 77 | } 78 | // declare a new parameter variable (function call) 79 | void ScopeVariables::declare_param_var(const VariableDefinition& param_definition, std::vector& value) 80 | { 81 | ScopeVariable* new_var = new ScopeVariable(param_definition.type, param_definition.name); 82 | new_var->set_value(value); 83 | push_back(new_var); 84 | } 85 | 86 | 87 | 88 | // visit all variables 89 | void ScopeVariables::visit_all_variables(std::function visitor) const { 90 | for (auto var_i : *this) 91 | visitor(*var_i); 92 | 93 | } 94 | 95 | // copy a variable for a sub-scope a retrun the copy 96 | ScopeVariable* ScopeVariables::copy_var(const ScopeVariable& var_source) 97 | { 98 | // deep copy : if the var is modified in the sub-scope, the parent scope var is not modified 99 | ScopeVariable* new_var = new ScopeVariable(var_source.type, var_source.name ); 100 | // if the source var ia assigned, copy source bits to the new variable 101 | if (var_source.is_set()) 102 | new_var->set_value(var_source.bits); 103 | 104 | push_back(new_var); 105 | return new_var; 106 | 107 | } 108 | 109 | -------------------------------------------------------------------------------- /src/ScopeVariable.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include "Connection.h" 7 | #include "VariableDefinition.h" 8 | #include "Function.h" 9 | 10 | 11 | // var during building, valid in a scope 12 | class ScopeVariable : public VariableDefinition { 13 | public: 14 | std::vector bits; // current val. emtpy if var not yet assigned 15 | public: 16 | // constructor 17 | ScopeVariable(Type* t, std::string n) : VariableDefinition(t, n) { } 18 | 19 | // set variable value 20 | void set_value(const std::vector& value); 21 | // is the variable assigned ? 22 | bool is_set(void) const; 23 | 24 | // get the value of the variable as integer, if set 25 | struct STValInt { 26 | bool is_set; 27 | int value; 28 | }; 29 | STValInt get_int_value(void) const; 30 | }; 31 | // all the variables in a scope 32 | class ScopeVariables : private std::vector { 33 | public: 34 | // find a variable by name 35 | ScopeVariable* find_by_name(std::string name); 36 | // declare a new local variable 37 | void declare_local_var(Type* var_type, std::string var_name); 38 | // declare a new parameter variable (function call) 39 | void declare_param_var(const VariableDefinition& param_definition, std::vector& value); 40 | 41 | // copy a variable for a sub-scope 42 | ScopeVariable* copy_var(const ScopeVariable& var_source); 43 | // visit all variables 44 | void visit_all_variables(std::function visitor) const; 45 | 46 | // Init from function defintion ans parameters 47 | void init_from_function_parameters(const Function::Definition& definition, std::vector& current_input); 48 | }; 49 | 50 | -------------------------------------------------------------------------------- /src/ShiftOperation.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "Program.h" 3 | #include "Error.h" 4 | #include "Circuit.h" 5 | 6 | // init << and >> 7 | void ShiftOperation::init(Scope& parent_scope) { 8 | // init left operands 9 | left_operand->init(parent_scope); 10 | // type must ba a basic type 11 | const TypeBasic* type_basic = left_operand->get_type().cast_to_TypeBasic(); 12 | if (type_basic == nullptr) 13 | throw Error("Type must be a basic type"); 14 | // copy basic type 15 | result_type = *type_basic; 16 | 17 | 18 | // right operand must be a constant interger 19 | Literal* rigth_litteral = right_operand->cast_to_literal(); 20 | if (rigth_litteral == nullptr) 21 | throw Error("Right operand must be a constant"); 22 | if (!rigth_litteral->get_type().is_integer()) 23 | throw Error("Right operand must be an integer"); 24 | // get the shift value 25 | nb_sihft = rigth_litteral->get_int_value(); 26 | if (nb_sihft < 0) 27 | throw Error("Shift value must be positive"); 28 | } 29 | 30 | 31 | // build the circuit for the shift expression 32 | std::vector ShiftOperation::build_circuit(BuildContext& ctx) { 33 | // build the L operands 34 | std::vector operand = left_operand->build_circuit(ctx); 35 | // if 0 sihft : return operand with modificatiton 36 | if (nb_sihft == 0) 37 | return operand; 38 | assert(nb_sihft > 0); 39 | int op_size = (int)operand.size(); 40 | 41 | //int nb_bit_out = op_size - nb_sihft; 42 | // init result with nullptr 43 | std::vector result(op_size, nullptr); 44 | 45 | // nb of bit in the output for the operand 46 | Connection* _0 = ctx.circuit().get_literal_values(false); 47 | for (int i = 0; i < op_size; i++) { 48 | // right shift : >> 49 | if (operation == Operator::op_right_shift) { 50 | int revese_i = op_size - 1 - i; 51 | if (i < nb_sihft) 52 | result[revese_i] = _0; 53 | else 54 | result[revese_i] = operand[revese_i + nb_sihft]; 55 | } 56 | // left shift : << 57 | else { 58 | if (i < nb_sihft) 59 | result[i] = _0; 60 | else 61 | result[i] = operand[i - nb_sihft]; 62 | } 63 | } 64 | return result; 65 | 66 | } 67 | 68 | -------------------------------------------------------------------------------- /src/ShiftOperation.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "BinaryOperation.h" 4 | 5 | // bit shit expression. ex :"a<<3" 6 | class ShiftOperation : public BinaryOperation { 7 | protected: 8 | // value of the lirreral R agufment 9 | int nb_sihft = 0; 10 | public: 11 | // constructor 12 | ShiftOperation(Operator op, Expression* left, Expression* right) : BinaryOperation(op, left, right) {}; 13 | // init 14 | virtual void init(Scope& parent_scope) override; 15 | // build the circuit for the binairy expression 16 | virtual std::vector build_circuit(BuildContext& ctx) override; 17 | }; 18 | -------------------------------------------------------------------------------- /src/Statement.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "BuildContext.h" 4 | class Scope; 5 | class Expression; 6 | 7 | 8 | // base class for a statement. 9 | // ex "v=a+2" or "return a+2;" 10 | class Statement { 11 | public: 12 | // lgne number in the source code 13 | int num_line = 0; 14 | public: 15 | // constructor 16 | Statement(int line) : num_line(line) {} 17 | // init a statmenet 18 | virtual void init(Scope& parent_scope) {} 19 | // cast in Statement_Return 20 | virtual class Statement_Return* cast_to_Statement_Return(void) { return nullptr; } 21 | // cast in Statement_If 22 | virtual class Statement_If* cast_to_Statement_If(void) { return nullptr; } 23 | // cast in Statement_DeclareVar 24 | virtual class Statement_DeclareVar* cast_to_Statement_DeclareVarr(void) { return nullptr; } 25 | // cast to Statement_DeclareStruct 26 | virtual class Statement_DeclareStruct* cast_to_Statement_DeclareStruct(void) { return nullptr; } 27 | // cast to Statement_DeclareAndSetVar 28 | virtual class Statement_DeclareAndSetVar* cast_to_Statement_DeclareAndSetVar(void) { return nullptr; } 29 | // cast to Statement_Increment 30 | virtual class Statement_Increment* cast_to_Statement_Increment(void) { return nullptr; } 31 | // cast to Statement_Break 32 | virtual class Statement_Break* cast_to_Statement_Break(void) { return nullptr; } 33 | 34 | // visit all expression ueed in the statement 35 | virtual void visit_Expression(std::function visitor) const = 0; 36 | 37 | // build the circuit for the return statelebt 38 | virtual BuildContext::NextAction build_circuit(BuildContext& ctx) const = 0; 39 | 40 | }; 41 | -------------------------------------------------------------------------------- /src/Statement_Break.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "Program.h" 3 | #include "Error.h" 4 | 5 | 6 | // init statmenet 7 | void Statement_Break::init(Scope& parent_scope) { 8 | // nothing 9 | } 10 | // build the circuit 11 | BuildContext::NextAction Statement_Break::build_circuit(BuildContext& ctx) const { 12 | // must be in a loop 13 | if (!ctx.is_in_for_loop()) { 14 | throw Error("break statement must be in a loop"); 15 | } 16 | 17 | // if we reach this point, the rest of the ciruit is the part after the loop 18 | return BuildContext::NextAction::Break; 19 | } 20 | -------------------------------------------------------------------------------- /src/Statement_Break.h: -------------------------------------------------------------------------------- 1 | // the break statement 2 | // in for() loop only 3 | 4 | #pragma once 5 | #include "Statement.h" 6 | 7 | class Statement_Break : public Statement { 8 | 9 | public: 10 | // constructor 11 | Statement_Break(int line) : Statement(line) {} 12 | // cast to Statement_Break 13 | virtual class Statement_Break* cast_to_Statement_Break(void) override { return this; } 14 | 15 | // visit all expression ueed in the statement 16 | virtual void visit_Expression(std::function visitor) const override {}; 17 | // init statmenet 18 | virtual void init(Scope& parent_scope) override; 19 | // build the circuit 20 | virtual BuildContext::NextAction build_circuit(BuildContext& ctx) const override; 21 | 22 | }; 23 | 24 | -------------------------------------------------------------------------------- /src/Statement_DeclareAndSetVar.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "Program.h" 3 | #include "Error.h" 4 | #include "BuildContext.h" 5 | 6 | // declare and set init 7 | void Statement_DeclareAndSetVar::init(Scope& parent_scope) { 8 | // init set and assign 9 | declaration.init(parent_scope); 10 | affectation.init(parent_scope); 11 | 12 | } 13 | 14 | // build the circuit for "int a=3" 15 | BuildContext::NextAction Statement_DeclareAndSetVar::build_circuit(BuildContext& ctx) const { 16 | // declare the variable 17 | declaration.build_circuit(ctx); 18 | // set variable value 19 | affectation.build_circuit(ctx); 20 | return BuildContext::NextAction::Continue; 21 | } 22 | 23 | -------------------------------------------------------------------------------- /src/Statement_DeclareAndSetVar.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maitrebitcoin/bitcoin-bitvm-compiler/03e3939492b925f1a9d28a05442a77817118b276/src/Statement_DeclareAndSetVar.h -------------------------------------------------------------------------------- /src/Statement_DeclareStruct.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "Program.h" 3 | #include "Error.h" 4 | 5 | 6 | // constructor 7 | Statement_DeclareStruct::Statement_DeclareStruct(int line, std::string name, CodeBloc* all_members) 8 | : Statement(line) 9 | , struct_type(name) // init name 10 | { 11 | // init members 12 | for (Statement* statement : all_members->statements) { 13 | // must be a "int i;" ype statement 14 | Statement_DeclareVar* statement_declare_var = statement->cast_to_Statement_DeclareVarr(); 15 | if (statement_declare_var == nullptr) 16 | throw Error("Invalid struct member declaration"); 17 | // add the member 18 | _add_member(statement_declare_var->type, statement_declare_var->name); 19 | } 20 | } 21 | // add a member to the struct 22 | void Statement_DeclareStruct::_add_member(Type* type, std::string name) { 23 | VariableDefinition new_member(type,name); 24 | struct_type.members.push_back(new_member); 25 | } 26 | // init a statmenet 27 | void Statement_DeclareStruct::init(Scope& parent_scope) { 28 | // check if the struct name is already used 29 | if (parent_scope.find_struct_by_name(struct_type.name) != nullptr) 30 | throw Error("Struct name already used : ", struct_type.name); 31 | // add the struct to the parent bloc 32 | parent_scope.declare_struct(this->struct_type); 33 | } 34 | // build the circuit for the declaration statement 35 | BuildContext::NextAction Statement_DeclareStruct::build_circuit(BuildContext& ctx) const { 36 | // nothind to do 37 | return BuildContext::NextAction::Continue; 38 | 39 | } 40 | 41 | -------------------------------------------------------------------------------- /src/Statement_DeclareStruct.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | 4 | 5 | // declare a struct statement 6 | class Statement_DeclareStruct : public Statement { 7 | protected: 8 | // type of the struct 9 | TypeStruct struct_type; 10 | 11 | public: 12 | // constructor 13 | Statement_DeclareStruct(int line, std::string name, CodeBloc* cobe_membres); 14 | // get return type 15 | const Type& get_type(void) const { return struct_type; } 16 | // visit all expression ueed in the statement 17 | virtual void visit_Expression(std::function visitor) const override {} 18 | // cast to Statement_DeclareStruct 19 | virtual Statement_DeclareStruct* cast_to_Statement_DeclareStruct(void) override { return this; } 20 | // init a statmenet 21 | virtual void init(Scope& parent_scope) override; 22 | // build the circuit for the declaration statement 23 | virtual BuildContext::NextAction build_circuit(BuildContext& ctx) const override; 24 | 25 | protected: 26 | // add a member to the struct 27 | void _add_member(Type* type, std::string name); 28 | }; 29 | 30 | 31 | -------------------------------------------------------------------------------- /src/Statement_DeclareVar.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "Program.h" 3 | #include "Error.h" 4 | #include "BuildContext.h" 5 | 6 | // constructor 7 | Statement_DeclareVar::Statement_DeclareVar(int line, Type* type, std::string name) 8 | : Statement(line) 9 | , VariableDefinition(type, name) 10 | {} 11 | 12 | 13 | // init a statmenet 14 | void Statement_DeclareVar::init(Scope& parent_scope) { 15 | // if variable namae already used 16 | const VariableDefinition* existing_variable_definition = parent_scope.find_variable_by_name(name); 17 | if (existing_variable_definition != nullptr) 18 | throw Error("Variable already declared : ", name); 19 | // if the type is just a name, get the real type 20 | if (!type->is_complete()) { 21 | const TypeStruct* real_type = parent_scope.find_struct_by_name(type->get_name()); 22 | if (real_type == nullptr) 23 | throw Error("Unknown type : ", type->get_name()); 24 | type = const_cast(real_type); 25 | } 26 | 27 | // declare the variable type 28 | parent_scope.declare_local_variable(*this); 29 | 30 | } 31 | 32 | // build the circuit for the declaration statement 33 | BuildContext::NextAction Statement_DeclareVar::build_circuit(BuildContext& ctx) const { 34 | // if the variable is already known 35 | if (ctx.variables().find_by_name(name) != nullptr) 36 | { 37 | // in a for loop, the variable can be declared twice, just ignore the second declaration 38 | if (ctx.is_in_for_loop()) 39 | return BuildContext::NextAction::Continue; 40 | 41 | throw Error("Variable already declared : ", name); 42 | } 43 | // declare the variable 44 | ctx.variables().declare_local_var(type, name); 45 | return BuildContext::NextAction::Continue; 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/Statement_DeclareVar.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | 4 | // int i => declaration of a variable statement 5 | class Statement_DeclareVar : public Statement, public VariableDefinition { 6 | 7 | public: 8 | // constructor 9 | Statement_DeclareVar(int line, Type* type, std::string name); 10 | // cast in Statement_DeclareVar 11 | virtual Statement_DeclareVar* cast_to_Statement_DeclareVarr(void) override { return this; } 12 | // get return type 13 | const Type& get_type(void) const { return *type; } 14 | // visit all expression ueed in the statement 15 | virtual void visit_Expression(std::function visitor) const override {} 16 | // init a statmenet 17 | virtual void init(Scope& parent_scope) override; 18 | // build the circuit for the declaration statement 19 | virtual BuildContext::NextAction build_circuit(BuildContext& ctx) const override; 20 | }; -------------------------------------------------------------------------------- /src/Statement_For.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include "Program.h" 4 | #include "Error.h" 5 | #include "Gate.h" 6 | #include "Circuit.h" 7 | 8 | 9 | // constructor 10 | Statement_For::Statement_For(int line, Statement* init, Expression* condition, Statement* increment, CodeBloc* c) 11 | : Statement(line) 12 | , for_init(init) 13 | , for_condition(condition) 14 | , for_increment(increment) 15 | , code(c) 16 | { 17 | 18 | } 19 | // visit all expression ueed in the statement 20 | void Statement_For::visit_Expression(std::function visitor) const { 21 | visitor(*for_condition); 22 | code->visit_Expression(visitor); 23 | } 24 | 25 | // init for statmenet 26 | void Statement_For::init(Scope& parent_scp) { 27 | 28 | // new scope for the for parent_scp 29 | Scope scope_for_loop(parent_scp); 30 | scope_for_loop.init_CodeBloc(parent_scp); 31 | scope_for_loop.parent_for_loop = this; 32 | 33 | // init statement a expressions 34 | for_init->init(scope_for_loop); 35 | for_condition->init(scope_for_loop); 36 | for_increment->init(scope_for_loop); 37 | // init blocs of code 38 | code->init_ex(scope_for_loop, CodeBloc::InitOption::return_not_required); 39 | 40 | // init statement mut be declaration of a variable set to an literal 41 | // ex: int i=0 42 | Statement_DeclareAndSetVar* init_as_declare_var = for_init->cast_to_Statement_DeclareAndSetVar(); 43 | if (init_as_declare_var == nullptr) 44 | throw Error("For init must be a var declaration = literal"); 45 | // must be a litteral 46 | Literal* litteral_init = init_as_declare_var->affectation.expression->cast_to_literal(); 47 | if (init_as_declare_var == nullptr) 48 | throw Error("For init must be a var declaration = literal"); 49 | start_value = litteral_init->get_int_value(); 50 | 51 | // for_increment must be "i++" style 52 | Statement_Increment* increment_as_increment = for_increment->cast_to_Statement_Increment(); 53 | if (increment_as_increment == nullptr) 54 | throw Error("Increment statement must be var++"); 55 | if (increment_as_increment->is_increment) 56 | incr_value = 1;// i++ 57 | else 58 | incr_value = -1; // i-- 59 | 60 | // condition statemetn must be "i<0" style 61 | TestOperation* test_operation = for_condition->cast_to_TestOperationr(); 62 | if (test_operation == nullptr) 63 | throw Error("For condition must be var < literal"); 64 | if (increment_as_increment->is_increment) { 65 | // < or <= only 66 | if ( test_operation->operation != BinaryOperation::Operator::op_test_lower 67 | && test_operation->operation != BinaryOperation::Operator::op_test_lower_or_equal) 68 | throw Error("For condition must be var < literal"); 69 | } 70 | else { 71 | // > or >= only 72 | if ( test_operation->operation != BinaryOperation::Operator::op_test_greater 73 | && test_operation->operation != BinaryOperation::Operator::op_test_greater_or_equal) 74 | throw Error("For condition must be var > literal"); 75 | } 76 | Literal* litteral_end = test_operation->right_operand->cast_to_literal(); 77 | if (litteral_end == nullptr) 78 | throw Error("For condition must be var < literal"); 79 | end_value = litteral_end->get_int_value(); 80 | // <= : loop 1 more time 81 | if (test_operation->operation == BinaryOperation::Operator::op_test_lower_or_equal) 82 | end_value++; 83 | // >= : loop 1 more time 84 | if (test_operation->operation == BinaryOperation::Operator::op_test_greater_or_equal) 85 | end_value--; 86 | 87 | // sanity check on loop values 88 | if (incr_value == 1 && end_value<=start_value) 89 | throw Error("For loop : invalid bounds"); 90 | if (incr_value == -1 && end_value >= start_value) 91 | throw Error("For loop : invalid bounds"); 92 | 93 | // init ok 94 | } 95 | // build the circuit for the for statement 96 | BuildContext::NextAction Statement_For::build_circuit(BuildContext& ctx) const { 97 | // call internal version 98 | return _build_circuit_from(ctx, start_value); 99 | } 100 | 101 | // internal build of the circuit for the for statement 102 | BuildContext::NextAction Statement_For::_build_circuit_from(BuildContext& ctx, int start_value_param) const { 103 | // if lopp ended 104 | if (start_value_param == end_value) 105 | return BuildContext::NextAction::Break; 106 | 107 | 108 | // build a new context for the for loop 109 | BuildContext ctx_for_loop_extern(ctx, BuildContext::Caller::for_statement ); 110 | ctx_for_loop_extern.for_statement = const_cast(this); 111 | ctx_for_loop_extern.debug_description = "ctx_for_loop_extern"; 112 | 113 | 114 | // init : crate loop var and set it to start value 115 | for_init->build_circuit(ctx_for_loop_extern); 116 | Statement_DeclareAndSetVar* for_init_as_declare_var = for_init->cast_to_Statement_DeclareAndSetVar(); 117 | Statement_SetVar& statement_set_var = for_init_as_declare_var->affectation; 118 | 119 | 120 | // for(i) interations, starting at start_value_param 121 | for (int i = start_value_param; i != end_value; i += incr_value) { 122 | 123 | BuildContext ctx_for_loop_internal(ctx_for_loop_extern, BuildContext::Caller::build_next_lambda); 124 | 125 | // set loop var to current value 126 | statement_set_var.build_circuit_set_to_int(ctx_for_loop_internal, i); 127 | ctx_for_loop_internal.debug_description = "ctx_for_loop_internal for (" + std::to_string(i) + ")"; 128 | 129 | // action in case of if to bluild the circuit from a new position 130 | // build all the other loops iterations 131 | BuildContext* pctx_caller = &ctx; 132 | ctx_for_loop_internal.build_all_next_statements = [this, i, pctx_caller](BuildContext& param_context) { 133 | // do the othet iterations of thee loop 134 | auto action = _build_circuit_from(param_context, i + incr_value); 135 | if (action == BuildContext::NextAction::Return) 136 | return action; 137 | if (action == BuildContext::NextAction::Break) 138 | return pctx_caller->build_on_break(param_context); 139 | // continue to the rest of the circuit 140 | if (pctx_caller->build_all_next_statements != nullptr) 141 | { 142 | auto sub_action = pctx_caller->build_all_next_statements(param_context); 143 | return sub_action; 144 | } 145 | return BuildContext::NextAction::Continue; 146 | }; 147 | ctx_for_loop_internal.build_on_break = [this, i, pctx_caller](BuildContext& param_context) { 148 | if (pctx_caller->nested_if>0) 149 | return pctx_caller->build_on_break(param_context); 150 | // continue to the rest of the circuit 151 | auto sub_action = pctx_caller->build_all_next_statements(param_context); 152 | return sub_action; 153 | }; 154 | 155 | // build circuit for the code bloc insiste the for() loop 156 | BuildContext::NextAction action = this->code->build_circuit(ctx_for_loop_internal); 157 | 158 | switch (action) 159 | { 160 | case BuildContext::NextAction::Continue: 161 | // proceed to next statement 162 | continue; 163 | case BuildContext::NextAction::Break: 164 | // stop the loop assert(false); 165 | break; 166 | case BuildContext::NextAction::Return: 167 | // nothing more to do 168 | return BuildContext::NextAction::Return; 169 | default: 170 | assert(false); 171 | break; 172 | } 173 | 174 | } 175 | return BuildContext::NextAction::Continue; 176 | 177 | } 178 | 179 | -------------------------------------------------------------------------------- /src/Statement_For.h: -------------------------------------------------------------------------------- 1 | // the for() statement 2 | 3 | #pragma once 4 | #include "Statement.h" 5 | 6 | class CodeBloc; 7 | class Expression; 8 | // "if" statement 9 | class Statement_For : public Statement { 10 | protected: 11 | // the 3 parts of the for statement 12 | Statement* for_init = nullptr; // ex : int i=0 13 | Expression* for_condition = nullptr; // ex : i<10 14 | Statement* for_increment = nullptr; // ex : i++ 15 | // code bloc executed in the loop 16 | CodeBloc* code = nullptr; 17 | 18 | // start value 19 | int start_value = 0; 20 | // en value 21 | int end_value = 0; 22 | // increment value 1 ou -1 23 | int incr_value = 1; 24 | 25 | public: 26 | // constructor 27 | Statement_For(int line, Statement* init, Expression* condition, Statement* increment, CodeBloc* code); 28 | 29 | // visit all expression ueed in the statement 30 | virtual void visit_Expression(std::function visitor) const override; 31 | // init for statmenet 32 | virtual void init(Scope& parent_scope) override; 33 | // build the circuit for the for statement 34 | virtual BuildContext::NextAction build_circuit(BuildContext& ctx) const override; 35 | 36 | protected: 37 | // internal build of the circuit for the for statement 38 | BuildContext::NextAction _build_circuit_from(BuildContext& ctx, int start_value_param) const; 39 | 40 | 41 | }; 42 | -------------------------------------------------------------------------------- /src/Statement_Function_Call.cpp: -------------------------------------------------------------------------------- 1 | // Function call statement 2 | 3 | #include "Program.h" 4 | #include "Error.h" 5 | 6 | // constructor 7 | Statement_Function_Call::Statement_Function_Call(int line, std::string name) 8 | : Statement(line), function_to_call_name(name) { 9 | } 10 | 11 | // visit all expression used in the statement 12 | void Statement_Function_Call::visit_Expression(std::function visitor) const 13 | { 14 | // visit all parameters expressions 15 | for (Expression* e : list_of_parameters) 16 | visitor(*e); 17 | } 18 | 19 | 20 | // init a statmenet 21 | void Statement_Function_Call::init(Scope& parent_scope) { 22 | // get the function definition by name 23 | function = parent_scope.find_function_by_name(function_to_call_name); 24 | if (function == nullptr) 25 | throw Error("Function not found", function_to_call_name); 26 | 27 | // check the number of parameters 28 | const Function::Definition& func_definition = function->get_definition(); 29 | size_t nb_params = func_definition.parameters.size(); 30 | if ( nb_params > list_of_parameters.size()) 31 | throw Error("Function call with too many parameters", function_to_call_name); 32 | if (nb_params < list_of_parameters.size()) 33 | throw Error("Function call with too few parameters", function_to_call_name); 34 | // check parameters type 35 | for (size_t i = 0; i < nb_params; i++) { 36 | Function::Parameter def_param_i = func_definition.parameters[i]; 37 | Expression* param_i = list_of_parameters[i]; 38 | const Type& type_param_i = param_i->get_type(); 39 | if (!type_param_i.is_same_type(*def_param_i.type)) { 40 | std::string err_message = "Function call with wrong parameter type for parameter " + std::to_string(i + 1) + " : expected " + def_param_i.type->get_name() + " but got " + type_param_i.get_name(); 41 | throw Error(err_message, function_to_call_name); 42 | } 43 | } 44 | 45 | 46 | // set the type 47 | const Type& returned_type = function->get_return_type(); 48 | this->type = &returned_type; 49 | // init parameters 50 | for (Expression* e : list_of_parameters) 51 | e->init(parent_scope); 52 | } 53 | 54 | // build the circuit for the function call statement 55 | BuildContext::NextAction Statement_Function_Call::build_circuit(BuildContext& ctx) const 56 | { 57 | // build the expressions for all input parameters 58 | std::vector> inputs; 59 | for (Expression* e : list_of_parameters) { 60 | std::vector input_i = e->build_circuit(ctx); 61 | // add input_i to the inputs 62 | inputs.push_back(input_i); 63 | } 64 | 65 | // create the context for the function call 66 | BuildContext ctx_function_call(ctx, BuildContext::Caller::function_call); 67 | // set the inputs 68 | const Function::Definition& func_definition = function->get_definition(); 69 | int input_index = 0; 70 | size_t nb_params = func_definition.parameters.size(); 71 | for (input_index = 0; input_index < nb_params; input_index++) { 72 | std::vector& input_i = inputs[input_index]; 73 | Function::Parameter def_param_i = func_definition.parameters[input_index]; 74 | // add var to the context 75 | ctx_function_call.variables().declare_param_var( def_param_i, input_i); 76 | 77 | 78 | // next input 79 | input_index++; 80 | } 81 | // build the circuit for the function call 82 | function->build_circuit(ctx_function_call); 83 | return BuildContext::NextAction::Continue; 84 | } 85 | -------------------------------------------------------------------------------- /src/Statement_Function_Call.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | using FunctionCallParameter = std::vector; 4 | 5 | // func(a,b) statement 6 | class Statement_Function_Call : public Statement { 7 | protected: 8 | // function name to call 9 | std::string function_to_call_name; 10 | // parameters 11 | FunctionCallParameter list_of_parameters; 12 | 13 | // function to call, set by init() : 14 | const Function* function = nullptr; 15 | // type of the function 16 | const Type* type = nullptr; 17 | public: 18 | // constructor 19 | Statement_Function_Call(int line, std::string name); 20 | // init a statmenet 21 | virtual void init(Scope& parent_scope) override; 22 | 23 | // get function return type 24 | const Type& get_type(void) const; 25 | // visit all expression used in the statement 26 | virtual void visit_Expression(std::function visitor) const override; //{ visitor(*expression); } 27 | 28 | // build the circuit for the function call statement 29 | virtual BuildContext::NextAction build_circuit(BuildContext& ctx) const override; 30 | }; 31 | -------------------------------------------------------------------------------- /src/Statement_If.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maitrebitcoin/bitcoin-bitvm-compiler/03e3939492b925f1a9d28a05442a77817118b276/src/Statement_If.cpp -------------------------------------------------------------------------------- /src/Statement_If.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class CodeBloc; 4 | // "if" statement 5 | class Statement_If : public Statement { 6 | protected: 7 | // expression to test 8 | Expression* expression; 9 | // bloc executed if expression if true 10 | CodeBloc* bloc_if_true = nullptr; 11 | // bloc executed if expression if true 12 | CodeBloc* bloc_if_false = nullptr; 13 | 14 | public: 15 | // constructor 16 | Statement_If(int line, Expression* condidtion, CodeBloc* if_true, CodeBloc* if_false); 17 | // cast in Statement_If 18 | virtual class Statement_If* cast_to_Statement_If(void) override { return this; } 19 | // setthe bloc executed if expression if true 20 | void setElseBloc( CodeBloc* bloc_else) { bloc_if_false = bloc_else; } 21 | // visit all expression ueed in the statement 22 | virtual void visit_Expression(std::function visitor) const override; 23 | 24 | // init if statmenet 25 | virtual void init(Scope& parent_scope) override; 26 | // build the circuit for the return statement 27 | virtual BuildContext::NextAction build_circuit(BuildContext& ctx) const override; 28 | 29 | protected: 30 | // Init variables and If Gate for one side 31 | void _init_variables_and_gate(BuildContext& ctx_source, ScopeVariables& variables_dest, class Gate_IF* gate, Circuit& circuit, bool bloc_side) const; 32 | }; 33 | 34 | -------------------------------------------------------------------------------- /src/Statement_Increment.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maitrebitcoin/bitcoin-bitvm-compiler/03e3939492b925f1a9d28a05442a77817118b276/src/Statement_Increment.cpp -------------------------------------------------------------------------------- /src/Statement_Increment.h: -------------------------------------------------------------------------------- 1 | // var++ statement 2 | 3 | #pragma once 4 | #include "Statement.h" 5 | 6 | class Statement_Increment : public Statement { 7 | public: 8 | // name of the variable 9 | std::string var_name; 10 | bool is_increment = true; // true: ++ / false -- 11 | // inter expression usse to calculate ++ or -- 12 | Expression * incr_expression = nullptr; 13 | // type of the variable 14 | Type* type = nullptr; 15 | // 1 vith the same type as the variable 16 | Literal* _1 = nullptr; 17 | 18 | public: 19 | // constructor 20 | Statement_Increment(int line, std::string name, bool increment); 21 | // cast to Statement_Increment 22 | virtual Statement_Increment* cast_to_Statement_Increment(void) override { return this; } 23 | 24 | // get return type 25 | const Type& get_type(void) const; 26 | // visit all expression ueed in the statement 27 | virtual void visit_Expression(std::function visitor) const override; 28 | // init statmenet 29 | virtual void init(Scope& parent_scope) override; 30 | // build the circuit for the statement 31 | virtual BuildContext::NextAction build_circuit(BuildContext& ctx) const override; 32 | }; 33 | -------------------------------------------------------------------------------- /src/Statement_Return.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "Program.h" 3 | #include "Error.h" 4 | #include "BuildContext.h" 5 | #include "Circuit.h" 6 | 7 | // init a return statmenet 8 | void Statement_Return::init(Scope& parent_scope) { 9 | // intialize the expression 10 | expression->init(parent_scope); 11 | // get return type 12 | const Type& returned_type = get_type(); 13 | 14 | // check the return type 15 | Function* parent_function = parent_scope.get_parent_function(); 16 | assert(parent_function != nullptr); // not allowed in global scope 17 | if (!returned_type.is_same_type(parent_function->get_return_type())) 18 | throw Error("Return type mismatch"); 19 | } 20 | 21 | // build the circuit for the return statem-ent 22 | BuildContext::NextAction Statement_Return::build_circuit(BuildContext& ctx) const { 23 | 24 | // build the expression 25 | std::vector outputs = expression->build_circuit(ctx); 26 | int nb_bit_out = (int)outputs.size(); 27 | assert(nb_bit_out == get_type().size_in_bit()); 28 | // connect the output of the expression to the output of the circuit 29 | ctx.circuit().set_output(outputs); 30 | return BuildContext::NextAction::Return; 31 | } 32 | -------------------------------------------------------------------------------- /src/Statement_Return.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // "return" statement 4 | class Statement_Return : public Statement { 5 | protected: 6 | // expression to return 7 | Expression* expression; 8 | public: 9 | // constructor 10 | Statement_Return(int line, Expression* e) : Statement(line), expression(e) {} 11 | // cast in Statement_Return 12 | virtual class Statement_Return* cast_to_Statement_Return(void) override { return this; } 13 | virtual bool is_return(void) const { return true; } 14 | // get return type 15 | const Type& get_type(void) const { return expression->get_type(); } 16 | // visit all expression ueed in the statement 17 | virtual void visit_Expression(std::function visitor) const override { visitor(*expression); } 18 | 19 | // init a statmenet 20 | virtual void init(Scope& parent_scope) override; 21 | // build the circuit for the return statement 22 | virtual BuildContext::NextAction build_circuit(BuildContext& ctx) const override; 23 | }; 24 | 25 | -------------------------------------------------------------------------------- /src/Statement_SetVar.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "Program.h" 3 | #include "Error.h" 4 | #include "BuildContext.h" 5 | 6 | // assignment statement init 7 | void Statement_SetVar::init(Scope& parent_scope) { 8 | expression->init(parent_scope); 9 | 10 | // get the variable type by name 11 | const VariableDefinition* var = parent_scope.find_variable_by_name(var_name); 12 | if (var != nullptr) { 13 | // change type of litterals to match the variable type 14 | Type* var_type = var->type; 15 | expression->change_all_litterals_type(*var_type); 16 | } 17 | 18 | } 19 | 20 | // build the circuit for the assignment to int (for loop) 21 | void Statement_SetVar::build_circuit_set_to_int(BuildContext& ctx, int new_val) const { 22 | // get the variable type by name 23 | ScopeVariable* var = ctx.variables().find_by_name(var_name); 24 | if (var == nullptr) 25 | throw Error("Unknonwn variable : ", var_name); 26 | // check variable type 27 | if (!var->type->is_integer()) 28 | throw Error("Type mismatch : ", var_name); 29 | 30 | // build the R expression 31 | std::vector new_val_connexionst = Literal::get_connections_from_value_int(ctx, *var->type, new_val); 32 | // connect the output of the expression to current value of the variable 33 | var->set_value(new_val_connexionst); 34 | 35 | } 36 | 37 | // build the circuit for the assignment statement 38 | BuildContext::NextAction Statement_SetVar::build_circuit(BuildContext& ctx) const { 39 | // get the variable type by name 40 | ScopeVariable* var = ctx.variables().find_by_name(var_name); 41 | if (var == nullptr) 42 | throw Error("Unknonwn variable : ", var_name); 43 | 44 | // check variable type 45 | if (!var->type->is_same_type(expression->get_type())) 46 | throw Error("Type mismatch : ", var_name); 47 | 48 | // build the R expression 49 | std::vector expression_value = expression->build_circuit(ctx); 50 | // connect the output of the expression to current value of the variable 51 | var->set_value(expression_value); 52 | return BuildContext::NextAction::Continue; 53 | } -------------------------------------------------------------------------------- /src/Statement_SetVar.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // set a variable statement 4 | class Statement_SetVar : public Statement { 5 | public: 6 | // name of the variable 7 | std::string var_name; 8 | Expression* expression; 9 | public: 10 | // constructor 11 | Statement_SetVar(int line, std::string name, Expression* op) : Statement(line), var_name(name), expression(op) {} 12 | // get return type 13 | const Type& get_type(void) const { return expression->get_type(); } 14 | // visit all expression ueed in the statement 15 | virtual void visit_Expression(std::function visitor) const override { visitor(*expression); } 16 | // init a statmenet 17 | virtual void init(Scope& parent_scope) override; 18 | // build the circuit for the declaration statement 19 | virtual BuildContext::NextAction build_circuit(BuildContext& ctx) const override; 20 | // build the circuit for the assignment to int (for loop) 21 | void build_circuit_set_to_int(BuildContext& ctx, int new_val) const; 22 | 23 | }; 24 | -------------------------------------------------------------------------------- /src/TapScriptGate.cpp: -------------------------------------------------------------------------------- 1 | // implemeation of all TapScriptGate logic 2 | 3 | 4 | #include "TapScriptGate.h" 5 | #include "Circuit.h" 6 | 7 | // ---- NAND ---- 8 | 9 | // compute the output of the NAND gate 10 | void Gate_NAND::compute(void) { 11 | // compute the output of the NAND gate 12 | output[0]->set_value(!(input[0]->get_value() & input[1]->get_value())); 13 | is_computed = true; 14 | } 15 | // add the gate into the circuir 16 | std::array Gate_NAND::add_to_circuit(Circuit& circuit, std::array& _input) { 17 | circuit.add_gate(this); 18 | set_inputs(_input); 19 | return this->output; 20 | } 21 | 22 | // --- IF ---- 23 | 24 | // IGate redefinition 25 | // get the inputs of the gate 26 | std::vector Gate_IF::get_inputs(void) const { 27 | // IF gate need 1 input or the condition and MAX inputs for the 2 possible sub circuits 28 | // the first input is the condition 29 | std::vector connections(input.begin(), input.end()); 30 | // add the inputs of the 2 sub circuits 31 | for (Connection* cnx : input_for_circuit_if_true) 32 | connections.push_back(cnx); 33 | for (Connection* cnx : input_for_circuit_if_false) { 34 | // add only if not already present in connections 35 | bool already_present = false; 36 | for (auto c : connections) { 37 | if (cnx == c) 38 | already_present = true; 39 | } 40 | if (!already_present) 41 | connections.push_back(cnx); 42 | } 43 | 44 | // return the inputs 45 | return std::move(connections); 46 | } 47 | 48 | // declare a new input for the gate : to be used by the circuit if_true and/or circuit_if_false 49 | void Gate_IF::add_input(Connection* input, bool if_true) { 50 | // get the good vector 51 | std::vector& inputs = if_true ? input_for_circuit_if_true : input_for_circuit_if_false; 52 | // do not add the same input twice 53 | for (int i = 0; i < inputs.size(); i++) { 54 | if (inputs[i] == input) { 55 | return; 56 | } 57 | } 58 | // add the input 59 | inputs.push_back(input); 60 | 61 | } 62 | 63 | // compute the output of the IF_ gate 64 | void Gate_IF::compute(void) 65 | { 66 | assert(false); 67 | 68 | throw Error("gate IF is not computable"); 69 | } 70 | 71 | // compute the output of the If gate : one of the sub cirusit 72 | std::vector Gate_IF::compute_if(void) const { 73 | bool if_true = input[0]->get_value(); 74 | // get the circuit to compute 75 | Circuit& sub_circuit = if_true ? *circuit_if_true : *circuit_if_false; 76 | const std::vector& inputs = if_true ? input_for_circuit_if_true : input_for_circuit_if_false; 77 | 78 | // build in values for the circuit with all the other inputs 79 | //InputsMap input_map = (InterfaceInputsMap*)this; 80 | CRunInputs in_sub_values = sub_circuit.get_run_inputs(); 81 | int i = 0; 82 | for (Connection* connection : inputs) { 83 | if (connection->is_calculated()) { 84 | bool bit_i = connection->get_value(); 85 | in_sub_values.set_bit_value(i, bit_i); 86 | } 87 | i++; 88 | } 89 | 90 | // compute the sub-circuit 91 | std::vector sub_result = sub_circuit.run(in_sub_values); 92 | assert(sub_result.size() > 0); 93 | return sub_result; 94 | } -------------------------------------------------------------------------------- /src/TapScriptGate.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maitrebitcoin/bitcoin-bitvm-compiler/03e3939492b925f1a9d28a05442a77817118b276/src/TapScriptGate.h -------------------------------------------------------------------------------- /src/Test.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // run all tests 4 | void run_all_test(void); -------------------------------------------------------------------------------- /src/TestOperation.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include "Program.h" 4 | #include "Error.h" 5 | #include "Circuit.h" 6 | 7 | // init '==' 8 | void TestOperation::init(Scope& parent_scope) { 9 | // init operands 10 | left_operand->init(parent_scope); 11 | right_operand->init(parent_scope); 12 | // left and right operand must have the same type 13 | if (!left_operand->get_type().is_same_type(right_operand->get_type())) 14 | throw Error("Type mismatch"); 15 | result_type = TypeBasic(Type::Native::bit); 16 | } 17 | 18 | 19 | // build the circuit for the "== != < > <= >= " expressions 20 | std::vector TestOperation::build_circuit(BuildContext& ctx) { 21 | // build the L& R operands 22 | std::vector op_left = left_operand->build_circuit(ctx); 23 | std::vector op_right = right_operand->build_circuit(ctx); 24 | 25 | // == 26 | if (operation == Operator::op_test_equal) { 27 | return build_circuit_equal(ctx, op_left, op_right); 28 | } 29 | // != 30 | if (operation == Operator::op_test_not_equal) { 31 | // build the circuit for == 32 | std::vector equal = build_circuit_equal(ctx, op_left, op_right); 33 | // negate the result 34 | std::array input_1_bit = { equal[0] }; 35 | std::array bit_not_equal = Gate_NOT().add_to_circuit(ctx.circuit(), input_1_bit); 36 | std::vector result(1, nullptr); 37 | result[0] = bit_not_equal[0]; 38 | return result; 39 | } 40 | // > 41 | if (operation == Operator::op_test_greater) { 42 | // build the circuit for the "b-a" expression 43 | std::vector b_minus_a = build_circuit_sub(ctx, op_right, op_left); 44 | // get the bit sign of b-a : true if (b-a)<0 => a > b 45 | std::vector b_minus_a_is_negative(1, b_minus_a[op_right.size() - 1]); 46 | return b_minus_a_is_negative; 47 | } 48 | // <= 49 | if (operation == Operator::op_test_lower_or_equal) { 50 | // build the circuit for the "a-b" expression 51 | std::vector b_minus_a = build_circuit_sub(ctx, op_right, op_left); 52 | // get the bit sign of b-a : true if (b-a)<0 => a > b 53 | Connection* b_minus_a_is_negative = b_minus_a[op_right.size() - 1]; 54 | // a<=b = !(a>b) 55 | std::array input_1_bit = { b_minus_a_is_negative }; 56 | std::array bit_result = Gate_NOT().add_to_circuit(ctx.circuit(), input_1_bit); 57 | std::vector result(1, bit_result[0]); 58 | return result; 59 | } 60 | // < 61 | if (operation == Operator::op_test_lower) { 62 | // build the circuit for the "a-b" expression 63 | std::vector a_minus_b = build_circuit_sub(ctx, op_left, op_right); 64 | // get the bit sign of b-a : true if (b-a)<0 => a > b 65 | std::vector a_minus_b_is_negative(1, a_minus_b[op_right.size() - 1]); 66 | return a_minus_b_is_negative; 67 | } 68 | // >= 69 | if (operation == Operator::op_test_greater_or_equal) { 70 | // build the circuit for the "a-b" expression 71 | std::vector a_minus_b = build_circuit_sub(ctx, op_left, op_right); 72 | // get the bit sign of b-a : true if (b-a)<0 => a > b 73 | Connection* a_minus_b_is_negative = a_minus_b[op_right.size() - 1]; 74 | // a<=b = !(a>b) 75 | std::array input_1_bit = { a_minus_b_is_negative }; 76 | std::array bit_result = Gate_NOT().add_to_circuit(ctx.circuit(), input_1_bit); 77 | std::vector result(1, bit_result[0]); 78 | return result; 79 | } 80 | 81 | 82 | 83 | 84 | // TODO, implement other operators 85 | // not an available operators 86 | throw(Error("Internal error : unimplemened operator")); 87 | 88 | } 89 | // build the circuit for the "==" expression 90 | std::vector TestOperation::build_circuit_equal(BuildContext& ctx, 91 | std::vector& op_left, 92 | std::vector& op_right) 93 | { 94 | int nb_bit = (int)op_left.size(); 95 | 96 | // build the circuit for the test 97 | std::vector result(1, nullptr); 98 | 99 | // build a array with each bit comparison 100 | std::vector bit_equal_array(nb_bit); 101 | for (int i = 0; i < nb_bit; i++) 102 | { 103 | std::array input_2_bit = { op_left[i], op_right[i] }; 104 | std::array bit_equal = Gate_XNOR().add_to_circuit(ctx.circuit(), input_2_bit); 105 | bit_equal_array[i] = bit_equal[0]; 106 | } 107 | // easy case: compare 2 bools 108 | if (nb_bit == 1) //op_left.size() == 1)) 109 | { 110 | result[0] = bit_equal_array[0]; 111 | return result; 112 | } 113 | // nb_bit must be a power of 2 114 | if ((nb_bit & (nb_bit - 1)) != 0) 115 | throw(Error("Internal error : operand size must be a power of 2")); // TODO, implement array with nb_bit not power of 2 116 | 117 | // cascade test 2 by 2 with AND operator 118 | while (bit_equal_array.size() > 1) { 119 | std::vector bit_equal_array_next(bit_equal_array.size() / 2); 120 | for (int i = 0; i < bit_equal_array_next.size(); i++) 121 | { 122 | std::array input_2_bit = { bit_equal_array[i * 2], bit_equal_array[i * 2 + 1] }; 123 | std::array _equal = Gate_AND().add_to_circuit(ctx.circuit(), input_2_bit); 124 | bit_equal_array_next[i] = _equal[0]; 125 | } 126 | // nesxt cascade 127 | bit_equal_array = bit_equal_array_next; 128 | } 129 | assert(bit_equal_array.size() == 1); 130 | result[0] = bit_equal_array[0]; 131 | return result; 132 | } 133 | -------------------------------------------------------------------------------- /src/TestOperation.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "BinaryOperation.h" 4 | 5 | // test operator ex : "a==b" 6 | // bit shit expression. ex :"a<<3" 7 | class TestOperation : public BinaryOperation { 8 | public: 9 | // constructor 10 | TestOperation(Operator op, Expression* left, Expression* right) : BinaryOperation(op, left, right) {}; 11 | // cast to TestOperation test_operation = for_condition->cast_to_TestOperationr(); 12 | virtual TestOperation* cast_to_TestOperationr(void) override { return this; } 13 | // init 14 | virtual void init(Scope& parent_scope) override; 15 | // build the circuit for the binairy expression 16 | virtual std::vector build_circuit(BuildContext& ctx) override; 17 | // build the circuit for the "==" expression 18 | static std::vector build_circuit_equal(BuildContext& ctx, 19 | std::vector& in_a, 20 | std::vector& in_b); 21 | 22 | }; -------------------------------------------------------------------------------- /src/TokenId.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maitrebitcoin/bitcoin-bitvm-compiler/03e3939492b925f1a9d28a05442a77817118b276/src/TokenId.h -------------------------------------------------------------------------------- /src/Type.cpp: -------------------------------------------------------------------------------- 1 | // type of a variable or function. 2 | 3 | #include "Type.h" 4 | #include "Error.h" 5 | 6 | 7 | // return the size in bits of a type 8 | int TypeBasic::size_in_bit(void) const 9 | { 10 | switch (native_type) 11 | { 12 | case Type::Native::undefined: 13 | assert(false); 14 | return 0; 15 | case Type::Native::bit: return 1; 16 | case Type::Native::int8: return 8; 17 | case Type::Native::uint8: return 8; 18 | case Type::Native::int32: return 32; 19 | case Type::Native::uint32: return 32; 20 | case Type::Native::int64: return 64; 21 | case Type::Native::uint64: return 64; 22 | case Type::Native::int256: return 256; 23 | case Type::Native::uint256:return 256; 24 | default: 25 | assert(false); 26 | return 0; 27 | } 28 | } 29 | 30 | // type is integer ? 31 | bool TypeBasic::is_integer(void) const 32 | { 33 | switch (native_type) 34 | { 35 | case Type::Native::undefined: 36 | assert(false); 37 | return false; 38 | case Type::Native::bit: 39 | return false; 40 | case Type::Native::int8: 41 | case Type::Native::uint8: 42 | case Type::Native::int32: 43 | case Type::Native::uint32: 44 | case Type::Native::int64: 45 | case Type::Native::uint64: 46 | case Type::Native::int256: 47 | case Type::Native::uint256: 48 | return true; 49 | default: 50 | assert(false); 51 | return 0; 52 | } 53 | 54 | } 55 | 56 | // get a TypeBasic for a requested nb of bits 57 | TypeBasic TypeBasic::get_TypeBasic_for_bitsize(int nb_bits) 58 | { 59 | switch (nb_bits) 60 | { 61 | case 1: return TypeBasic(Type::Native::bit); 62 | case 8: return TypeBasic(Type::Native::int8); 63 | case 32: return TypeBasic(Type::Native::int32); 64 | case 64: return TypeBasic(Type::Native::int64); 65 | case 256:return TypeBasic(Type::Native::int256); 66 | default: 67 | assert(false); 68 | throw Error("No type avalaide for nb of bit : ", std::to_string(nb_bits) ); 69 | //return TypeBasic(Type::Native::undefined); 70 | } 71 | }; 72 | 73 | 74 | 75 | // compare 76 | bool TypeBasic::is_same_type(const Type& other) const { 77 | // must be a basic type 78 | const TypeBasic* other_basic = other.cast_to_TypeBasic(); 79 | if (other_basic == nullptr) 80 | return false; 81 | return native_type == other_basic->native_type; 82 | } 83 | 84 | // get type name 85 | std::string TypeBasic::get_name(void) const { 86 | switch (native_type) 87 | { 88 | case Type::Native::undefined: 89 | default: 90 | assert(false); 91 | return "unknown"; 92 | case Type::Native::bit: return "bool"; 93 | case Type::Native::int8: return "int8"; 94 | case Type::Native::uint8: return "uint8"; 95 | case Type::Native::int32: return "int32"; 96 | case Type::Native::uint32: return "uint32"; 97 | case Type::Native::int64: return "int64"; 98 | case Type::Native::uint64: return "uint64"; 99 | case Type::Native::int256: return "int256"; 100 | case Type::Native::uint256: return "uint256"; 101 | } 102 | } 103 | 104 | -------------------------------------------------------------------------------- /src/Type.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | class TypeStruct; 6 | class TypeBasic; 7 | class TypeArray; 8 | 9 | // type of a variable or returned by a function. 10 | //ex : "bool" ou "struct MyStruct" 11 | class Type { 12 | public: 13 | enum class Native { 14 | undefined, // not set/ invalide 15 | bit, // bool 16 | int8, // signed 8 bits integer 17 | uint8, // unsigned 8 bits integer 18 | int32, // signed 32 bits integer 19 | uint32, // 20 | int64, // signed 64 bits integer 21 | uint64, // 22 | int256, // igned 256 bits integer / hash 23 | uint256, // 24 | user_struct,// user defined structure type 25 | }; 26 | 27 | // return the size in bits of the type 28 | virtual int size_in_bit(void) const = 0; 29 | // compare 30 | virtual bool is_same_type(const Type& other) const = 0; 31 | // type is a basic type (ie not a struct) ? 32 | virtual bool is_basic(void) const = 0; 33 | // type is complete type (false : only the name is known) 34 | virtual bool is_complete(void) const = 0; 35 | // type is bool ? 36 | virtual bool is_bool(void) const { return false; } 37 | // type is integer ? 38 | virtual bool is_integer(void) const { return false; } 39 | // get type name 40 | virtual std::string get_name(void) const = 0; 41 | // get a copy of the type 42 | virtual Type* get_copy(void) const = 0; 43 | 44 | // cast to "TypeBasic" 45 | virtual const TypeBasic* cast_to_TypeBasic(void) const { return nullptr; } 46 | // cast to "TypeStruct" 47 | virtual const TypeStruct* cast_to_TypeStruct(void) const { return nullptr; } 48 | // cast to "TypeArray" 49 | virtual const TypeArray* cast_to_TypeArray(void) const { return nullptr; } 50 | 51 | }; 52 | 53 | // basic/native/scalar types. 54 | //ex : "bool" 55 | class TypeBasic : public Type { 56 | 57 | 58 | protected: 59 | Native native_type = Native::undefined; 60 | public: 61 | // constructor 62 | TypeBasic(void) {} 63 | TypeBasic(Native t) : native_type(t) { assert(t != Native::user_struct); } 64 | TypeBasic(const TypeBasic& source) : native_type(source.native_type) {} 65 | // cast to "TypeBasic" 66 | virtual const TypeBasic* cast_to_TypeBasic(void) const override { return this; } 67 | 68 | // return the size in bits of the type 69 | virtual int size_in_bit(void) const override; 70 | // type is bool ? 71 | virtual bool is_bool(void) const override { return native_type == Native::bit; } 72 | // type is integer ? 73 | virtual bool is_integer(void) const override; 74 | // type is a basic type (ie not a struct) ? 75 | virtual bool is_basic(void) const { return true; } 76 | // type is complete type (false : only the name is known) 77 | virtual bool is_complete(void) const { return true; } 78 | // compare 79 | virtual bool is_same_type(const Type& other) const override; 80 | // get type name 81 | virtual std::string get_name(void) const override; 82 | // get a copy of the type 83 | virtual Type* get_copy(void) const override { return new TypeBasic(*this); } 84 | 85 | // get the native type 86 | Native get_native_type(void) const { return native_type; } 87 | // change native type. ex int8 to int256 88 | void set_native_type(Native tn) { native_type = tn; } 89 | 90 | // get a TypeBasic for a requested nb of bits 91 | static TypeBasic get_TypeBasic_for_bitsize(int nb_bits); 92 | }; 93 | 94 | -------------------------------------------------------------------------------- /src/TypeArray.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "TypeArray.h" 3 | 4 | // constructor 5 | TypeArray::TypeArray( Type* type, int array_size) 6 | : element_type(type) 7 | , size(array_size) { 8 | assert(element_type != nullptr); 9 | assert(size >= 1); 10 | } 11 | 12 | // compare types 13 | bool TypeArray::is_same_type(const Type& other) const { 14 | // other must be a array 15 | const TypeArray* other_array = other.cast_to_TypeArray(); 16 | if (other_array == nullptr) 17 | return false; 18 | // compare type and size 19 | return element_type->is_same_type(*other_array->element_type) 20 | && size == other_array->size; 21 | } 22 | 23 | // return the size in bits of the type 24 | int TypeArray::size_in_bit(void) const { 25 | return element_type->size_in_bit() * size; 26 | } 27 | 28 | // get type name 29 | // ex : "int[10]" 30 | std::string TypeArray::get_name(void) const 31 | { 32 | std::string name; 33 | name = element_type->get_name() + "[" + std::to_string(size) + "]"; 34 | return name; 35 | } 36 | 37 | // get a copy of the type 38 | Type* TypeArray::get_copy(void) const 39 | { 40 | return new TypeArray(element_type, size); 41 | } 42 | -------------------------------------------------------------------------------- /src/TypeArray.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include "Type.h" 7 | 8 | 9 | // array on a type 10 | class TypeArray : public Type { 11 | public: 12 | // type on each element 13 | Type *element_type; 14 | // number of elements 15 | int size; 16 | 17 | // constructor 18 | TypeArray(Type* type, int arary_size); 19 | // cast to "TypeArray" 20 | virtual const TypeArray* cast_to_TypeArray(void) const { return this; } 21 | 22 | // type is a basic type (ie not a struct) ? 23 | virtual bool is_basic(void) const { return false; } 24 | // type is complete type (false : only the name is known) 25 | virtual bool is_complete(void) const override { return true; } 26 | // return the size in bits of the type 27 | virtual int size_in_bit(void) const override; 28 | // compare types 29 | virtual bool is_same_type(const Type& other) const override; 30 | // get type name 31 | virtual std::string get_name(void) const override; 32 | // get the member by name 33 | struct Member { 34 | bool is_valid = false; 35 | int index = 0; 36 | Type* type = nullptr; 37 | int offest_in_bit = 0; 38 | }; 39 | Member get_member_by_name(const std::string& name) const; 40 | // get a copy of the type 41 | virtual Type* get_copy(void) const override; 42 | 43 | 44 | }; 45 | -------------------------------------------------------------------------------- /src/TypeStruct.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "TypeStruct.h" 3 | #include "BuildContext.h" 4 | 5 | 6 | 7 | // compare types 8 | bool TypeStruct::is_same_type(const Type& other) const { 9 | // other must be a struct 10 | const TypeStruct *other_struct = other.cast_to_TypeStruct(); 11 | if (other_struct == nullptr) 12 | return false; 13 | // compare the name 14 | return name == other_struct->name; 15 | } 16 | 17 | 18 | // return the size in bits of the type 19 | int TypeStruct::size_in_bit(void) const { 20 | // the summ of the size of all members 21 | int sum = 0; 22 | for (const VariableDefinition& member : members) { 23 | sum += member.type->size_in_bit(); 24 | } 25 | return sum; 26 | } 27 | 28 | // get the member by name 29 | TypeStruct::Member TypeStruct::get_member_by_name(const std::string& name) const { 30 | 31 | int index = 0; 32 | int sum = 0; 33 | for (const VariableDefinition& member : members) { 34 | // is it the member we are looking for ? 35 | if (member.name == name) { 36 | Member result; 37 | result.is_valid = true; 38 | result.index = index; 39 | result.type = member.type; 40 | result.offest_in_bit = sum; 41 | return result; 42 | } 43 | 44 | // next membre 45 | sum += member.type->size_in_bit(); 46 | index++; 47 | 48 | } 49 | // not found 50 | Member result_notfound; 51 | return result_notfound; 52 | } 53 | 54 | -------------------------------------------------------------------------------- /src/TypeStruct.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include "Type.h" 7 | #include "VariableDefinition.h" 8 | class BuildContext; 9 | 10 | // incomplet type at compile time, we only have the name 11 | class IncompleteType : public Type { 12 | protected: 13 | // name of the type 14 | std::string name; 15 | public: 16 | // constructor 17 | IncompleteType(std::string n) : name(n) {} 18 | 19 | // type is a basic type (ie not a struct) ? 20 | virtual bool is_basic(void) const override { return false; } 21 | // type is complete type (false : only the name is known) 22 | virtual bool is_complete(void) const override { return false; } 23 | // return the size in bits of the type 24 | virtual int size_in_bit(void) const override { assert(false); return 0; } 25 | // compare types 26 | virtual bool is_same_type(const Type& other) const override { assert(false); return false; } 27 | // get type name 28 | virtual std::string get_name(void) const override { return name; } 29 | // get a copy of the type 30 | virtual Type* get_copy(void) const override { assert(false); return nullptr; } // non copiable 31 | 32 | }; 33 | 34 | 35 | // usert type structure 36 | class TypeStruct : public Type { 37 | public: 38 | // name of the struct 39 | std::string name; 40 | // meberes of the struct 41 | std::vector members; 42 | 43 | // constructor 44 | TypeStruct(std::string name) : name(name) {} 45 | 46 | // type is a basic type (ie not a struct) ? 47 | virtual bool is_basic(void) const { return false; } 48 | // type is complete type (false : only the name is known) 49 | virtual bool is_complete(void) const override { return true; } 50 | // return the size in bits of the type 51 | virtual int size_in_bit(void) const override; 52 | // compare types 53 | virtual bool is_same_type(const Type& other) const override; 54 | // cast to "TypeStruct" 55 | virtual const TypeStruct* cast_to_TypeStruct(void) const override { return this; } 56 | // get type name 57 | virtual std::string get_name(void) const override {return name ;} 58 | // get the member by name 59 | struct Member { 60 | bool is_valid = false; 61 | int index = 0; 62 | Type* type = nullptr; 63 | int offest_in_bit = 0; 64 | }; 65 | Member get_member_by_name(const std::string& name) const; 66 | // get a copy of the type 67 | virtual Type* get_copy(void) const override { return new TypeStruct(*this); } 68 | 69 | 70 | }; 71 | -------------------------------------------------------------------------------- /src/UnaryOperation.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "Program.h" 3 | #include "Error.h" 4 | #include "Gate.h" 5 | #include "Circuit.h" 6 | 7 | 8 | // constructor 9 | UnaryOperation::UnaryOperation(Operator op, Expression* exp) : operation(op), operand(exp) { 10 | // check 11 | assert(operand != nullptr); 12 | } 13 | // init 14 | void UnaryOperation::init(Scope& parent_scope) { 15 | operand->init(parent_scope); 16 | // type must ba a basic type 17 | const TypeBasic* type_basic = operand->get_type().cast_to_TypeBasic(); 18 | if (type_basic == nullptr) 19 | throw Error("Type must be a basic type"); 20 | // copy basic type 21 | result_type = *type_basic; 22 | } 23 | // build the circuit for the binairy expression 24 | std::vector UnaryOperation::build_circuit(BuildContext& ctx) { 25 | // build the operand 26 | std::vector inputs = operand->build_circuit(ctx); 27 | 28 | // create the gate for the operation 29 | UnaryGate* gate = nullptr; 30 | switch (operation) 31 | { 32 | case Operator::op_not: 33 | // type bool only 34 | if (!get_type().is_bool()) 35 | throw Error("Operator ! is reserved for bool type only"); 36 | return build_circuit_not(ctx, inputs); 37 | case Operator::op_negate: 38 | if (get_type().is_bool()) 39 | throw Error("Operator - is not defined for bool type"); 40 | return build_circuit_negation(ctx, inputs); 41 | case Operator::op_complement: 42 | return build_circuit_not(ctx, inputs); 43 | default: 44 | assert(false); 45 | throw Error("Internal error : unexpected operator"); 46 | } 47 | } 48 | // build the circuit for the not expression 49 | std::vector UnaryOperation::build_circuit_not(BuildContext& ctx, std::vector& inputs) { 50 | 51 | // OUT = !A for each bit 52 | std::vector result; 53 | for (int i = 0; i < inputs.size(); i++) { 54 | std::array input_1_bit = { inputs[i] }; 55 | std::array bits_result = Gate_NOT().add_to_circuit(ctx.circuit(), input_1_bit); 56 | result.push_back(bits_result[0]); 57 | } 58 | return result; 59 | } 60 | 61 | // build the circuit for the negate expression 62 | std::vector UnaryOperation::build_circuit_negation(BuildContext& ctx, std::vector& inputs) { 63 | std::vector result; 64 | // create a 2's complement 65 | std::vector not_inputs = build_circuit_not(ctx, inputs); 66 | // get 1 with the right size 67 | std::vector _1; 68 | for (int i = 0; i < inputs.size(); i++) { 69 | _1.push_back(ctx.circuit().get_literal_values(i == 0)); 70 | } 71 | // add 1 72 | return BinaryOperation::build_circuit_add(ctx, not_inputs, _1); 73 | 74 | } 75 | 76 | -------------------------------------------------------------------------------- /src/UnaryOperation.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maitrebitcoin/bitcoin-bitvm-compiler/03e3939492b925f1a9d28a05442a77817118b276/src/UnaryOperation.h -------------------------------------------------------------------------------- /src/VariableDefinition.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "assert.h" 5 | #include "Type.h" 6 | 7 | 8 | class VariableDefinition { 9 | public: 10 | // type of the variable 11 | Type *type; 12 | // name of the variable 13 | std::string name; 14 | 15 | // constructor 16 | VariableDefinition(Type* t, std::string s) : type(t), name(s) {} 17 | }; -------------------------------------------------------------------------------- /src/bitcoin-bitvm-compiler.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.5.33530.505 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bitcoin-bitvm-compiler", "bitcoin-bitvm-compiler.vcxproj", "{3C662BD1-81FF-43F8-8B00-7C0478A44816}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Release|x64 = Release|x64 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {3C662BD1-81FF-43F8-8B00-7C0478A44816}.Debug|x64.ActiveCfg = Debug|x64 15 | {3C662BD1-81FF-43F8-8B00-7C0478A44816}.Debug|x64.Build.0 = Debug|x64 16 | {3C662BD1-81FF-43F8-8B00-7C0478A44816}.Release|x64.ActiveCfg = Release|x64 17 | {3C662BD1-81FF-43F8-8B00-7C0478A44816}.Release|x64.Build.0 = Release|x64 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {B1909E92-59A7-42B3-8D76-7980AD23CA2E} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /src/bitcoin-bitvm-compiler.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | x64 7 | 8 | 9 | Release 10 | x64 11 | 12 | 13 | 14 | 16.0 15 | Win32Proj 16 | {3c662bd1-81ff-43f8-8b00-7c0478a44816} 17 | bitVMcompiler 18 | 10.0 19 | bitcoin-bitvm-compiler 20 | 21 | 22 | 23 | Application 24 | true 25 | v143 26 | Unicode 27 | 28 | 29 | Application 30 | false 31 | v143 32 | true 33 | Unicode 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | ..\$(Platform)\$(Configuration)\obj\ 49 | $(SolutionDir)\..\$(Platform)\$(Configuration)\ 50 | bitvmcompiler 51 | 52 | 53 | ..\$(Platform)\$(Configuration)\obj\ 54 | $(SolutionDir)\..\$(Platform)\$(Configuration)\ 55 | bitvmcompiler 56 | 57 | 58 | 59 | Level3 60 | true 61 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 62 | true 63 | stdcpp17 64 | 65 | 66 | Console 67 | true 68 | 69 | 70 | 71 | 72 | Level3 73 | true 74 | true 75 | true 76 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 77 | true 78 | stdcpp17 79 | 80 | 81 | Console 82 | true 83 | true 84 | true 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | -------------------------------------------------------------------------------- /src/export.txt: -------------------------------------------------------------------------------- 1 | 16 16 2 | 16 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 3 | 8 17 19 21 23 25 27 29 31 4 | 1 16 1 0 8 NAND 5 | 1 17 1 16 16 NAND 6 | 1 18 1 1 9 NAND 7 | 1 19 1 18 18 NAND 8 | 1 20 1 2 10 NAND 9 | 1 21 1 20 20 NAND 10 | 1 22 1 3 11 NAND 11 | 1 23 1 22 22 NAND 12 | 1 24 1 4 12 NAND 13 | 1 25 1 24 24 NAND 14 | 1 26 1 5 13 NAND 15 | 1 27 1 26 26 NAND 16 | 1 28 1 6 14 NAND 17 | 1 29 1 28 28 NAND 18 | 1 30 1 7 15 NAND 19 | 1 31 1 30 30 NAND 20 | -------------------------------------------------------------------------------- /src/sample/hello_word.bvc: -------------------------------------------------------------------------------- 1 | // most simple program : return the 1 bit input 2 | bool main(bool a) 3 | { 4 | return a; 5 | } -------------------------------------------------------------------------------- /src/sample/test_add.bvc: -------------------------------------------------------------------------------- 1 | // test the + operator 2 | int8 main(int8 a,int8 b) 3 | { 4 | return a+b; 5 | } -------------------------------------------------------------------------------- /src/sample/test_and.bvc: -------------------------------------------------------------------------------- 1 | // test the & operator 2 | bool main(bool a,bool b) 3 | { 4 | return a&b; 5 | } -------------------------------------------------------------------------------- /src/sample/test_array.bvc: -------------------------------------------------------------------------------- 1 | // test array usage 2 | int8 main(int8[3] my_array) 3 | { 4 | int8 b = 0; 5 | b = my_array[1]; 6 | return my_array[0] + b; 7 | } -------------------------------------------------------------------------------- /src/sample/test_array_2.bvc: -------------------------------------------------------------------------------- 1 | // test array usage, 2nd case 2 | int8 main(int8[3] my_array) 3 | { 4 | int8 sum = 0; 5 | for (int8 i=0; i<3;i++) { 6 | sum = sum + my_array[i]; 7 | } 8 | return sum; 9 | } 10 | -------------------------------------------------------------------------------- /src/sample/test_array_3.bvc: -------------------------------------------------------------------------------- 1 | // test array usage, 3rd case 2 | int8 main(int8[6] my_array, int8 index) 3 | { 4 | int8 result = my_array[index+1]; 5 | return result; 6 | } 7 | -------------------------------------------------------------------------------- /src/sample/test_complement.bvc: -------------------------------------------------------------------------------- 1 | // test the complement operator : ~ 2 | int8 main(int8 a) 3 | { 4 | return ~a; 5 | } -------------------------------------------------------------------------------- /src/sample/test_declare_and_set.bvc: -------------------------------------------------------------------------------- 1 | // test the ^ operator with local var declaration and assigment 2 | bool main(bool a,bool b) 3 | { 4 | bool local_a_xor_b = a ^ b; 5 | return local_a_xor_b; 6 | } -------------------------------------------------------------------------------- /src/sample/test_decrement.bvc: -------------------------------------------------------------------------------- 1 | // test the var-- statement 2 | int8 main(int8 var) 3 | { 4 | var--; 5 | return var; 6 | } -------------------------------------------------------------------------------- /src/sample/test_equal_bool.bvc: -------------------------------------------------------------------------------- 1 | // test the == operator with bool operands 2 | bool main(bool a,bool b) 3 | { 4 | return a==b; 5 | } -------------------------------------------------------------------------------- /src/sample/test_equal_int8.bvc: -------------------------------------------------------------------------------- 1 | // test the == operator with byte operands 2 | bool main(int8 a,int8 b) 3 | { 4 | return a==b; 5 | } -------------------------------------------------------------------------------- /src/sample/test_for.bvc: -------------------------------------------------------------------------------- 1 | // test the for and if nested statement 2 | int8 main(int8 max_i) 3 | { 4 | // return the sum of int form 1 to max_i, up to 10 5 | int8 sum=0; 6 | for (int8 i=0;i<=10;i++) { 7 | if (i==max_i) 8 | { 9 | int8 local = sum + i; 10 | sum = local; 11 | break; 12 | } 13 | sum = sum + i; 14 | } 15 | return sum; 16 | } -------------------------------------------------------------------------------- /src/sample/test_greater.bvc: -------------------------------------------------------------------------------- 1 | // test the > operator 2 | bool main(int8 a,int8 b) 3 | { 4 | return a>b; 5 | } -------------------------------------------------------------------------------- /src/sample/test_greater_or_equal.bvc: -------------------------------------------------------------------------------- 1 | // test the >= operator 2 | bool main(int8 a,int8 b) 3 | { 4 | return a>=b; 5 | } -------------------------------------------------------------------------------- /src/sample/test_if.bvc: -------------------------------------------------------------------------------- 1 | // test the if statement 2 | int8 main(int8 a) 3 | { 4 | if (a<10) 5 | { 6 | return 5; 7 | } 8 | if (a==10) 9 | { 10 | return 127; 11 | } 12 | return a+1; 13 | } -------------------------------------------------------------------------------- /src/sample/test_if_and_stuct.bvc: -------------------------------------------------------------------------------- 1 | // test the if statemetn and struct together 2 | 3 | struct Header { 4 | int8 a; 5 | int8 b; 6 | }; 7 | 8 | int8 main(Header st) 9 | { 10 | if (st.a<10) 11 | { 12 | return 5; 13 | } 14 | if (st.a==10) 15 | { 16 | int8 c= st.b & 0x0F; 17 | return c; 18 | } 19 | return st.a+1; 20 | } -------------------------------------------------------------------------------- /src/sample/test_include.bvc: -------------------------------------------------------------------------------- 1 | // test the #include preprocessor directive 2 | #include "test_include.bvh" 3 | bool main(bool a,bool b) 4 | { 5 | return xor(a,b); 6 | } -------------------------------------------------------------------------------- /src/sample/test_include.bvh: -------------------------------------------------------------------------------- 1 | // include file for test_include.bvc 2 | bool xor(bool a,bool b) 3 | { 4 | return a^b; 5 | } -------------------------------------------------------------------------------- /src/sample/test_increment.bvc: -------------------------------------------------------------------------------- 1 | // test the var++ statement 2 | int8 main(int8 a) 3 | { 4 | a++; 5 | return a; 6 | } -------------------------------------------------------------------------------- /src/sample/test_int256.bvc: -------------------------------------------------------------------------------- 1 | // test the int64 native type 2 | int256 main(int256 a,int256 b) 3 | { 4 | int256 local_a_and_b = a & b; 5 | return local_a_and_b; 6 | } -------------------------------------------------------------------------------- /src/sample/test_int32.bvc: -------------------------------------------------------------------------------- 1 | // test the int32 native type 2 | int32 main(int32 a,int32 b) 3 | { 4 | int32 local_unused = 0; // test liteal cast to int32 5 | int32 local_a_and_b = a & b; 6 | return local_a_and_b; 7 | } -------------------------------------------------------------------------------- /src/sample/test_int64.bvc: -------------------------------------------------------------------------------- 1 | // test the int64 native type 2 | int64 main(int64 a,int64 b) 3 | { 4 | int64 local_a_and_b = a & b; 5 | return local_a_and_b; 6 | } -------------------------------------------------------------------------------- /src/sample/test_int8.bvc: -------------------------------------------------------------------------------- 1 | // test the int8 native type 2 | int8 main(int8 a,int8 b) 3 | { 4 | int8 local_a_and_b = a & b; 5 | return local_a_and_b; 6 | } -------------------------------------------------------------------------------- /src/sample/test_literal.bvc: -------------------------------------------------------------------------------- 1 | // test literals 2 | int8 main(int8 a) 3 | { 4 | bool b=true; 5 | int8 c=31; 6 | int8 local_a_modulo32 = a & 0x1F; 7 | return local_a_modulo32; 8 | } -------------------------------------------------------------------------------- /src/sample/test_local_var.bvc: -------------------------------------------------------------------------------- 1 | // test the ^ operator with local var assigment 2 | bool main(bool a,bool b) 3 | { 4 | bool local_c; 5 | bool d; 6 | local_c = a; 7 | d = b; 8 | return local_c^d; 9 | } -------------------------------------------------------------------------------- /src/sample/test_lower.bvc: -------------------------------------------------------------------------------- 1 | // test the < operator 2 | bool main(int8 a,int8 b) 3 | { 4 | return a> 1); 6 | } -------------------------------------------------------------------------------- /src/sample/test_proc.bvc: -------------------------------------------------------------------------------- 1 | // test procedure usage 2 | int8 proc_plus1( int8 a ) 3 | { 4 | return a+1; 5 | } 6 | // return a+2 7 | int8 main(int a) 8 | { 9 | int8 b; 10 | b = proc_plus1(a); 11 | b = proc_plus1(b); 12 | return b; 13 | } 14 | -------------------------------------------------------------------------------- /src/sample/test_shit_left.bvc: -------------------------------------------------------------------------------- 1 | // test the << operator 2 | int8 main(int8 a) 3 | { 4 | return (a<<3)|0; 5 | } -------------------------------------------------------------------------------- /src/sample/test_shit_right.bvc: -------------------------------------------------------------------------------- 1 | // test the << operator 2 | int8 main(int8 a) 3 | { 4 | return (a>>3)|0; 5 | } -------------------------------------------------------------------------------- /src/sample/test_struct.bvc: -------------------------------------------------------------------------------- 1 | // test struct usage 2 | 3 | struct Header { 4 | int8 a; 5 | int8 b; 6 | }; 7 | 8 | int8 main(Header st_ab, int8 c) 9 | { 10 | int8 d; 11 | d = st_ab.b; 12 | return st_ab.b + c; 13 | } 14 | -------------------------------------------------------------------------------- /src/sample/test_sub.bvc: -------------------------------------------------------------------------------- 1 | // test the a-b operator 2 | int8 main(int8 a,int8 b) 3 | { 4 | return a-b; 5 | } -------------------------------------------------------------------------------- /src/sample/test_xor.bvc: -------------------------------------------------------------------------------- 1 | // test the ^ operator 2 | bool main(bool a,bool b) 3 | { 4 | return a^b; 5 | } -------------------------------------------------------------------------------- /src/test.out: -------------------------------------------------------------------------------- 1 | 231 230 2 | 8 2 3 4 5 6 7 8 9 3 | 0 4 | 1 1 0 0 EQ 5 | 1 1 1 1 EQ 6 | 1 10 1 0 0 NAND 7 | 1 11 1 1 1 NAND 8 | 1 12 1 0 0 NAND 9 | 1 13 1 1 1 NAND 10 | 1 14 1 0 0 NAND 11 | 1 15 1 0 0 NAND 12 | 1 16 1 0 0 NAND 13 | 1 17 1 0 0 NAND 14 | 1 18 1 10 1 NAND 15 | 1 19 1 10 18 NAND 16 | 1 20 1 1 18 NAND 17 | 1 21 1 19 20 NAND 18 | 1 22 1 10 1 NAND 19 | 1 23 1 22 22 NAND 20 | 1 24 1 11 0 NAND 21 | 1 25 1 11 24 NAND 22 | 1 26 1 0 24 NAND 23 | 1 27 1 25 26 NAND 24 | 1 28 1 11 0 NAND 25 | 1 29 1 28 28 NAND 26 | 1 30 1 23 27 NAND 27 | 1 31 1 23 30 NAND 28 | 1 32 1 27 30 NAND 29 | 1 33 1 31 32 NAND 30 | 1 34 1 23 27 NAND 31 | 1 35 1 34 34 NAND 32 | 1 36 1 29 29 NAND 33 | 1 37 1 35 35 NAND 34 | 1 38 1 36 37 NAND 35 | 1 39 1 12 0 NAND 36 | 1 40 1 12 39 NAND 37 | 1 41 1 0 39 NAND 38 | 1 42 1 40 41 NAND 39 | 1 43 1 12 0 NAND 40 | 1 44 1 43 43 NAND 41 | 1 45 1 38 42 NAND 42 | 1 46 1 38 45 NAND 43 | 1 47 1 42 45 NAND 44 | 1 48 1 46 47 NAND 45 | 1 49 1 38 42 NAND 46 | 1 50 1 49 49 NAND 47 | 1 51 1 44 44 NAND 48 | 1 52 1 50 50 NAND 49 | 1 53 1 51 52 NAND 50 | 1 54 1 13 0 NAND 51 | 1 55 1 13 54 NAND 52 | 1 56 1 0 54 NAND 53 | 1 57 1 55 56 NAND 54 | 1 58 1 13 0 NAND 55 | 1 59 1 58 58 NAND 56 | 1 60 1 53 57 NAND 57 | 1 61 1 53 60 NAND 58 | 1 62 1 57 60 NAND 59 | 1 63 1 61 62 NAND 60 | 1 64 1 53 57 NAND 61 | 1 65 1 64 64 NAND 62 | 1 66 1 59 59 NAND 63 | 1 67 1 65 65 NAND 64 | 1 68 1 66 67 NAND 65 | 1 69 1 14 0 NAND 66 | 1 70 1 14 69 NAND 67 | 1 71 1 0 69 NAND 68 | 1 72 1 70 71 NAND 69 | 1 73 1 14 0 NAND 70 | 1 74 1 73 73 NAND 71 | 1 75 1 68 72 NAND 72 | 1 76 1 68 75 NAND 73 | 1 77 1 72 75 NAND 74 | 1 78 1 76 77 NAND 75 | 1 79 1 68 72 NAND 76 | 1 80 1 79 79 NAND 77 | 1 81 1 74 74 NAND 78 | 1 82 1 80 80 NAND 79 | 1 83 1 81 82 NAND 80 | 1 84 1 15 0 NAND 81 | 1 85 1 15 84 NAND 82 | 1 86 1 0 84 NAND 83 | 1 87 1 85 86 NAND 84 | 1 88 1 15 0 NAND 85 | 1 89 1 88 88 NAND 86 | 1 90 1 83 87 NAND 87 | 1 91 1 83 90 NAND 88 | 1 92 1 87 90 NAND 89 | 1 93 1 91 92 NAND 90 | 1 94 1 83 87 NAND 91 | 1 95 1 94 94 NAND 92 | 1 96 1 89 89 NAND 93 | 1 97 1 95 95 NAND 94 | 1 98 1 96 97 NAND 95 | 1 99 1 16 0 NAND 96 | 1 100 1 16 99 NAND 97 | 1 101 1 0 99 NAND 98 | 1 102 1 100 101 NAND 99 | 1 103 1 16 0 NAND 100 | 1 104 1 103 103 NAND 101 | 1 105 1 98 102 NAND 102 | 1 106 1 98 105 NAND 103 | 1 107 1 102 105 NAND 104 | 1 108 1 106 107 NAND 105 | 1 109 1 98 102 NAND 106 | 1 110 1 109 109 NAND 107 | 1 111 1 104 104 NAND 108 | 1 112 1 110 110 NAND 109 | 1 113 1 111 112 NAND 110 | 1 114 1 17 0 NAND 111 | 1 115 1 17 114 NAND 112 | 1 116 1 0 114 NAND 113 | 1 117 1 115 116 NAND 114 | 1 118 1 17 0 NAND 115 | 1 119 1 118 118 NAND 116 | 1 120 1 113 117 NAND 117 | 1 121 1 113 120 NAND 118 | 1 122 1 117 120 NAND 119 | 1 123 1 121 122 NAND 120 | 1 124 1 113 117 NAND 121 | 1 125 1 124 124 NAND 122 | 1 126 1 119 119 NAND 123 | 1 127 1 125 125 NAND 124 | 1 128 1 126 127 NAND 125 | 1 129 1 2 21 NAND 126 | 1 130 1 2 129 NAND 127 | 1 131 1 21 129 NAND 128 | 1 132 1 130 131 NAND 129 | 1 133 1 2 21 NAND 130 | 1 134 1 133 133 NAND 131 | 1 135 1 3 33 NAND 132 | 1 136 1 3 135 NAND 133 | 1 137 1 33 135 NAND 134 | 1 138 1 136 137 NAND 135 | 1 139 1 3 33 NAND 136 | 1 140 1 139 139 NAND 137 | 1 141 1 134 138 NAND 138 | 1 142 1 134 141 NAND 139 | 1 143 1 138 141 NAND 140 | 1 144 1 142 143 NAND 141 | 1 145 1 134 138 NAND 142 | 1 146 1 145 145 NAND 143 | 1 147 1 140 140 NAND 144 | 1 148 1 146 146 NAND 145 | 1 149 1 147 148 NAND 146 | 1 150 1 4 48 NAND 147 | 1 151 1 4 150 NAND 148 | 1 152 1 48 150 NAND 149 | 1 153 1 151 152 NAND 150 | 1 154 1 4 48 NAND 151 | 1 155 1 154 154 NAND 152 | 1 156 1 149 153 NAND 153 | 1 157 1 149 156 NAND 154 | 1 158 1 153 156 NAND 155 | 1 159 1 157 158 NAND 156 | 1 160 1 149 153 NAND 157 | 1 161 1 160 160 NAND 158 | 1 162 1 155 155 NAND 159 | 1 163 1 161 161 NAND 160 | 1 164 1 162 163 NAND 161 | 1 165 1 5 63 NAND 162 | 1 166 1 5 165 NAND 163 | 1 167 1 63 165 NAND 164 | 1 168 1 166 167 NAND 165 | 1 169 1 5 63 NAND 166 | 1 170 1 169 169 NAND 167 | 1 171 1 164 168 NAND 168 | 1 172 1 164 171 NAND 169 | 1 173 1 168 171 NAND 170 | 1 174 1 172 173 NAND 171 | 1 175 1 164 168 NAND 172 | 1 176 1 175 175 NAND 173 | 1 177 1 170 170 NAND 174 | 1 178 1 176 176 NAND 175 | 1 179 1 177 178 NAND 176 | 1 180 1 6 78 NAND 177 | 1 181 1 6 180 NAND 178 | 1 182 1 78 180 NAND 179 | 1 183 1 181 182 NAND 180 | 1 184 1 6 78 NAND 181 | 1 185 1 184 184 NAND 182 | 1 186 1 179 183 NAND 183 | 1 187 1 179 186 NAND 184 | 1 188 1 183 186 NAND 185 | 1 189 1 187 188 NAND 186 | 1 190 1 179 183 NAND 187 | 1 191 1 190 190 NAND 188 | 1 192 1 185 185 NAND 189 | 1 193 1 191 191 NAND 190 | 1 194 1 192 193 NAND 191 | 1 195 1 7 93 NAND 192 | 1 196 1 7 195 NAND 193 | 1 197 1 93 195 NAND 194 | 1 198 1 196 197 NAND 195 | 1 199 1 7 93 NAND 196 | 1 200 1 199 199 NAND 197 | 1 201 1 194 198 NAND 198 | 1 202 1 194 201 NAND 199 | 1 203 1 198 201 NAND 200 | 1 204 1 202 203 NAND 201 | 1 205 1 194 198 NAND 202 | 1 206 1 205 205 NAND 203 | 1 207 1 200 200 NAND 204 | 1 208 1 206 206 NAND 205 | 1 209 1 207 208 NAND 206 | 1 210 1 8 108 NAND 207 | 1 211 1 8 210 NAND 208 | 1 212 1 108 210 NAND 209 | 1 213 1 211 212 NAND 210 | 1 214 1 8 108 NAND 211 | 1 215 1 214 214 NAND 212 | 1 216 1 209 213 NAND 213 | 1 217 1 209 216 NAND 214 | 1 218 1 213 216 NAND 215 | 1 219 1 217 218 NAND 216 | 1 220 1 209 213 NAND 217 | 1 221 1 220 220 NAND 218 | 1 222 1 215 215 NAND 219 | 1 223 1 221 221 NAND 220 | 1 224 1 222 223 NAND 221 | 1 225 1 9 123 NAND 222 | 1 226 1 9 225 NAND 223 | 1 227 1 123 225 NAND 224 | 1 228 1 226 227 NAND 225 | 1 229 1 9 123 NAND 226 | 1 230 1 229 229 NAND 227 | 1 231 1 224 228 NAND 228 | 1 232 1 224 231 NAND 229 | 1 233 1 228 231 NAND 230 | 1 234 1 232 233 NAND 231 | 1 235 1 224 228 NAND 232 | 1 236 1 235 235 NAND 233 | 1 237 1 230 230 NAND 234 | 1 238 1 236 236 NAND 235 | 1 239 1 237 238 NAND 236 | 0 0 234 2 3 4 5 6 7 8 9 IF 237 | 238 | 0 0 239 | 0 240 | 8 241 240 241 240 240 240 240 240 241 | 1 1 0 240 EQ 242 | 1 1 1 241 EQ 243 | 244 | 111 111 245 | 8 244 245 246 247 248 249 250 251 246 | 8 255 267 282 297 312 327 342 357 247 | 1 1 0 242 EQ 248 | 1 1 1 243 EQ 249 | 1 252 1 2 243 NAND 250 | 1 253 1 2 252 NAND 251 | 1 254 1 243 252 NAND 252 | 1 255 1 253 254 NAND 253 | 1 256 1 2 243 NAND 254 | 1 257 1 256 256 NAND 255 | 1 258 1 3 242 NAND 256 | 1 259 1 3 258 NAND 257 | 1 260 1 242 258 NAND 258 | 1 261 1 259 260 NAND 259 | 1 262 1 3 242 NAND 260 | 1 263 1 262 262 NAND 261 | 1 264 1 257 261 NAND 262 | 1 265 1 257 264 NAND 263 | 1 266 1 261 264 NAND 264 | 1 267 1 265 266 NAND 265 | 1 268 1 257 261 NAND 266 | 1 269 1 268 268 NAND 267 | 1 270 1 263 263 NAND 268 | 1 271 1 269 269 NAND 269 | 1 272 1 270 271 NAND 270 | 1 273 1 4 242 NAND 271 | 1 274 1 4 273 NAND 272 | 1 275 1 242 273 NAND 273 | 1 276 1 274 275 NAND 274 | 1 277 1 4 242 NAND 275 | 1 278 1 277 277 NAND 276 | 1 279 1 272 276 NAND 277 | 1 280 1 272 279 NAND 278 | 1 281 1 276 279 NAND 279 | 1 282 1 280 281 NAND 280 | 1 283 1 272 276 NAND 281 | 1 284 1 283 283 NAND 282 | 1 285 1 278 278 NAND 283 | 1 286 1 284 284 NAND 284 | 1 287 1 285 286 NAND 285 | 1 288 1 5 242 NAND 286 | 1 289 1 5 288 NAND 287 | 1 290 1 242 288 NAND 288 | 1 291 1 289 290 NAND 289 | 1 292 1 5 242 NAND 290 | 1 293 1 292 292 NAND 291 | 1 294 1 287 291 NAND 292 | 1 295 1 287 294 NAND 293 | 1 296 1 291 294 NAND 294 | 1 297 1 295 296 NAND 295 | 1 298 1 287 291 NAND 296 | 1 299 1 298 298 NAND 297 | 1 300 1 293 293 NAND 298 | 1 301 1 299 299 NAND 299 | 1 302 1 300 301 NAND 300 | 1 303 1 6 242 NAND 301 | 1 304 1 6 303 NAND 302 | 1 305 1 242 303 NAND 303 | 1 306 1 304 305 NAND 304 | 1 307 1 6 242 NAND 305 | 1 308 1 307 307 NAND 306 | 1 309 1 302 306 NAND 307 | 1 310 1 302 309 NAND 308 | 1 311 1 306 309 NAND 309 | 1 312 1 310 311 NAND 310 | 1 313 1 302 306 NAND 311 | 1 314 1 313 313 NAND 312 | 1 315 1 308 308 NAND 313 | 1 316 1 314 314 NAND 314 | 1 317 1 315 316 NAND 315 | 1 318 1 7 242 NAND 316 | 1 319 1 7 318 NAND 317 | 1 320 1 242 318 NAND 318 | 1 321 1 319 320 NAND 319 | 1 322 1 7 242 NAND 320 | 1 323 1 322 322 NAND 321 | 1 324 1 317 321 NAND 322 | 1 325 1 317 324 NAND 323 | 1 326 1 321 324 NAND 324 | 1 327 1 325 326 NAND 325 | 1 328 1 317 321 NAND 326 | 1 329 1 328 328 NAND 327 | 1 330 1 323 323 NAND 328 | 1 331 1 329 329 NAND 329 | 1 332 1 330 331 NAND 330 | 1 333 1 8 242 NAND 331 | 1 334 1 8 333 NAND 332 | 1 335 1 242 333 NAND 333 | 1 336 1 334 335 NAND 334 | 1 337 1 8 242 NAND 335 | 1 338 1 337 337 NAND 336 | 1 339 1 332 336 NAND 337 | 1 340 1 332 339 NAND 338 | 1 341 1 336 339 NAND 339 | 1 342 1 340 341 NAND 340 | 1 343 1 332 336 NAND 341 | 1 344 1 343 343 NAND 342 | 1 345 1 338 338 NAND 343 | 1 346 1 344 344 NAND 344 | 1 347 1 345 346 NAND 345 | 1 348 1 9 242 NAND 346 | 1 349 1 9 348 NAND 347 | 1 350 1 242 348 NAND 348 | 1 351 1 349 350 NAND 349 | 1 352 1 9 242 NAND 350 | 1 353 1 352 352 NAND 351 | 1 354 1 347 351 NAND 352 | 1 355 1 347 354 NAND 353 | 1 356 1 351 354 NAND 354 | 1 357 1 355 356 NAND 355 | 1 358 1 347 351 NAND 356 | 1 359 1 358 358 NAND 357 | 1 360 1 353 353 NAND 358 | 1 361 1 359 359 NAND 359 | 1 362 1 360 361 NAND 360 | 361 | --------------------------------------------------------------------------------