├── tests ├── __init__.py └── transpiler │ ├── context │ ├── __init__.py │ └── test_context.py │ ├── core_module │ ├── __init__.py │ ├── test_control_pod.py │ ├── test_for_loop_pod.py │ ├── test_func_pod.py │ ├── test_statement_pod.py │ └── test_struct_pod.py │ ├── other_module │ ├── __init__.py │ ├── test_annotation.py │ └── test_import_package.py │ ├── others_module │ ├── __init__.py │ └── test_import_package.py │ ├── sub_module │ ├── __init__.py │ └── test_primitive_type.py │ └── __init__.py ├── transpiler ├── context │ ├── __init__.py │ └── noir_context.py ├── sub_module │ ├── __init__.py │ ├── key_words.py │ ├── sign.py │ └── primitive_type.py ├── utils │ ├── __init__.py │ ├── syntax_analysis.py │ └── utils.py ├── core_module │ ├── __init__.py │ ├── for_loop_pod.py │ ├── control_pod.py │ ├── func_pod.py │ ├── struct_pod.py │ └── statement_pod.py ├── others_module │ ├── __init__.py │ ├── annotation.py │ └── import_package.py └── __init__.py ├── setup.py └── README.md /tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /transpiler/context/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /transpiler/sub_module/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/transpiler/context/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/transpiler/core_module/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/transpiler/other_module/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/transpiler/others_module/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/transpiler/sub_module/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /transpiler/utils/__init__.py: -------------------------------------------------------------------------------- 1 | from ..utils.utils import log 2 | -------------------------------------------------------------------------------- /transpiler/core_module/__init__.py: -------------------------------------------------------------------------------- 1 | from ..core_module.struct_pod import Struct, StructGenerics 2 | -------------------------------------------------------------------------------- /transpiler/others_module/__init__.py: -------------------------------------------------------------------------------- 1 | from transpiler.others_module.annotation import Annotation 2 | -------------------------------------------------------------------------------- /tests/transpiler/__init__.py: -------------------------------------------------------------------------------- 1 | __all__ = [ 2 | "context", 3 | "core_module", 4 | "sub_module", 5 | "others_module", 6 | ] -------------------------------------------------------------------------------- /transpiler/__init__.py: -------------------------------------------------------------------------------- 1 | __all__ = [ 2 | "utils", 3 | "context", 4 | "core_module", 5 | "sub_module", 6 | "others_module", 7 | ] -------------------------------------------------------------------------------- /transpiler/others_module/annotation.py: -------------------------------------------------------------------------------- 1 | class Annotation: 2 | def __init__(self, line: int, content: str): 3 | self.line = line 4 | self.content = content 5 | 6 | def get_content(self): 7 | return f'// {self.content}\n' 8 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import setuptools 2 | 3 | setuptools.setup( 4 | name='python2noir', 5 | version='0.1', 6 | description='Easy to quickly convert python libraries to Noir contracts', 7 | author='storswift', 8 | author_email='', 9 | packages=setuptools.find_packages(), 10 | ) 11 | -------------------------------------------------------------------------------- /transpiler/utils/syntax_analysis.py: -------------------------------------------------------------------------------- 1 | from transpiler.sub_module.sign import get_sign4bool 2 | 3 | 4 | def is_bool_expression(expression: str): 5 | # Inspection the expression is a bool expression 6 | for sign in get_sign4bool(): 7 | if sign in expression: 8 | return True 9 | # FIXME: Inspection process too easy. 10 | return False 11 | -------------------------------------------------------------------------------- /tests/transpiler/sub_module/test_primitive_type.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from transpiler.sub_module.primitive_type import custom_type, set_str 3 | 4 | 5 | class test_primitive_type(unittest.TestCase): 6 | def test_custom_type(self): 7 | value = custom_type('u126') 8 | print(value) 9 | 10 | def test_set_str(self): 11 | value = set_str(18) 12 | print(value) 13 | -------------------------------------------------------------------------------- /tests/transpiler/other_module/test_annotation.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | from transpiler.others_module import Annotation 4 | from transpiler.others_module.import_package import Mod, Use 5 | 6 | 7 | class test_annotation(unittest.TestCase): 8 | def test_get_content(self): 9 | annotation = Annotation(0, 'my test annotation') 10 | print(annotation.get_content()) 11 | self.assertTrue(annotation.get_content(), "// my test annotation") 12 | 13 | 14 | if __name__ == '__main__': 15 | unittest.main() 16 | -------------------------------------------------------------------------------- /tests/transpiler/others_module/test_import_package.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from transpiler.others_module.import_package import Mod, Use 3 | 4 | 5 | class test_import_package(unittest.TestCase): 6 | def test_mod(self): 7 | mod = Mod('test').get() 8 | print(mod) 9 | self.assertTrue(mod, "mod test;") 10 | 11 | def test_Use(self): 12 | use = Use() 13 | print(use.standard_library) 14 | self.assertTrue(use.standard_library, "use dep::std;") 15 | 16 | 17 | if __name__ == '__main__': 18 | unittest.main() 19 | -------------------------------------------------------------------------------- /transpiler/sub_module/key_words.py: -------------------------------------------------------------------------------- 1 | USE = 'use' 2 | MOD = 'mod' 3 | LET = 'let' 4 | MUT = 'mut' 5 | ASSERT = 'assert' 6 | THEN = 'then' 7 | RETURN = 'return' 8 | IN = 'in' 9 | PUB = 'pub' 10 | PRINTLN = 'println' 11 | DEP_STD_PRINTLN = f'dep::std::{PRINTLN}' 12 | DEP_STD = 'dep::std' 13 | GLOBAL = 'global' 14 | SELF = 'Self' 15 | T = 'T' 16 | N = 'N' 17 | 18 | # comptime variables 19 | COMPTIME = "comptime" 20 | 21 | """ 22 | "\t" number +1 key words 23 | """ 24 | FOR = 'for' 25 | IF = 'if' 26 | ELSE = 'else' 27 | ELIF = f'{ELSE} {IF}' 28 | FN = 'fn' 29 | STRUCT = 'struct' 30 | IMPL = 'impl' 31 | INLINE = 'inline' 32 | 33 | # GET_TABLE_P_ONE = [FOR, IF, ELSE, ELIF, FN, STRUCT] 34 | -------------------------------------------------------------------------------- /transpiler/sub_module/sign.py: -------------------------------------------------------------------------------- 1 | LEFT_BRACE = '{' 2 | RIGHT_BRACE = '}' 3 | LEFT_PARENTHESIS = '(' 4 | RIGHT_PARENTHESIS = ')' 5 | LEFT_BRACKET = '[' 6 | RIGHT_BRACKET = ']' 7 | COLON = ':' 8 | SEMICOLON = ';' 9 | GREATER_THAN = '>' 10 | LESS_THAN = '<' 11 | ASSIGNMENT = '=' 12 | EQUAL = '==' 13 | NOT_EQUAL = '!=' 14 | GREATER_THAN_OR_EQUAL = '>=' 15 | LESS_THAN_OR_EQUAL = '<=' 16 | ADD = '+' 17 | SUB = '-' 18 | MULTI = '*' 19 | DIV = '/' 20 | REM = '%' 21 | LEFT_SHIFT = '<<' 22 | RIGHT_SHIFT = '>>' 23 | COMMA = ',' 24 | POINT = '.' 25 | NOT = '!' 26 | AND = '&' 27 | OR = '|' 28 | XOR = '^' 29 | RESULT = '->' 30 | 31 | 32 | def get_sign4bool(): 33 | return [EQUAL, NOT_EQUAL, GREATER_THAN_OR_EQUAL, LESS_THAN_OR_EQUAL, AND, OR] 34 | -------------------------------------------------------------------------------- /transpiler/core_module/for_loop_pod.py: -------------------------------------------------------------------------------- 1 | from transpiler.core_module.statement_pod import Statement 2 | from ..sub_module.key_words import FOR, IN 3 | from ..sub_module.sign import LEFT_BRACE, RIGHT_BRACE, SEMICOLON 4 | 5 | 6 | class ForLoop(Statement): 7 | 8 | def __init__(self, variate, start_variate, end_variate, body): 9 | if start_variate == '': 10 | self.for_loop = f"{FOR} {variate} {IN} {end_variate}" \ 11 | f" {LEFT_BRACE} \n{body}\n{RIGHT_BRACE}\n" 12 | else: 13 | self.for_loop = f"{FOR} {variate} {IN} {start_variate}..{end_variate}" \ 14 | f" {LEFT_BRACE} \n{body}\n{RIGHT_BRACE}" 15 | 16 | def get(self): 17 | return self.for_loop 18 | -------------------------------------------------------------------------------- /transpiler/others_module/import_package.py: -------------------------------------------------------------------------------- 1 | from transpiler.core_module.statement_pod import Statement 2 | from transpiler.sub_module.key_words import MOD, USE, DEP_STD, DEP_STD_PRINTLN 3 | from transpiler.sub_module.sign import SEMICOLON 4 | 5 | 6 | class Mod(Statement): 7 | def __init__(self, file_name): 8 | self.mod = f"{MOD} {file_name}{SEMICOLON}\n" 9 | 10 | def get(self): 11 | return self.mod 12 | 13 | 14 | class Use: 15 | custom_use = "" 16 | def __init__(self): 17 | self.standard_library = f"{USE} {DEP_STD}{SEMICOLON}\n" 18 | self.standard_library_println = f"{USE} {DEP_STD_PRINTLN}{SEMICOLON}\n" 19 | 20 | def define_custom_use(self, use): 21 | self.custom_use = f"{USE} {use}{SEMICOLON}\n" 22 | -------------------------------------------------------------------------------- /tests/transpiler/other_module/test_import_package.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from transpiler.others_module.import_package import Mod, Use 3 | 4 | 5 | class test_import_package(unittest.TestCase): 6 | def test_mod(self): 7 | mod = Mod('test').get() 8 | print(mod) 9 | self.assertTrue(mod, "mod test;") 10 | 11 | def test_use_dep_std(self): 12 | use = Use().standard_library 13 | print(use) 14 | self.assertTrue(use, "use dep::std;") 15 | 16 | def test_use_dep_std_println(self): 17 | use = Use().standard_library_println 18 | print(use) 19 | self.assertTrue(use, "use dep::std::println;") 20 | 21 | def test_use_define_custom_use(self): 22 | use = Use() 23 | use.define_custom_use("std::hash") 24 | print(use.custom_use) 25 | self.assertTrue(use.custom_use, "use std::hash;") 26 | 27 | 28 | if __name__ == '__main__': 29 | unittest.main() 30 | -------------------------------------------------------------------------------- /tests/transpiler/core_module/test_control_pod.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from transpiler.core_module.control_pod import IfControl, IfElseControl 3 | from transpiler.sub_module.sign import LESS_THAN, GREATER_THAN 4 | from transpiler.utils.utils import table_format_control 5 | 6 | 7 | class test_control_pod(unittest.TestCase): 8 | 9 | def test_If_Control(self): 10 | left_value = 'a' 11 | right_value = 'b' 12 | sign = LESS_THAN 13 | body = "true" 14 | result = IfControl(left_value, right_value, sign, body).get() 15 | print(result) 16 | self.assertTrue(result, """if a < b { 17 | true 18 | }""") 19 | 20 | def test_If_Else_Control(self): 21 | left_value = 'a' 22 | right_value = 'b' 23 | sign = LESS_THAN 24 | if_body = "true" 25 | else_body = "false" 26 | result = IfElseControl(left_value, right_value, sign, if_body, else_body).get() 27 | print(result) 28 | self.assertTrue(result, """if a < b { 29 | true 30 | } else { 31 | false 32 | } """) 33 | 34 | def test_If_ElIf_Else_Control(self): 35 | pass 36 | -------------------------------------------------------------------------------- /tests/transpiler/core_module/test_for_loop_pod.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from transpiler.core_module.for_loop_pod import ForLoop 3 | from transpiler.core_module.statement_pod import Array 4 | 5 | 6 | class test_for_loop_pod(unittest.TestCase): 7 | 8 | def test_for_loop_base(self): 9 | variate = 'i' 10 | start_variate = '0' 11 | end_variate = '10' 12 | body = 'sum += i;' 13 | result = ForLoop(variate, start_variate, end_variate, body).get() 14 | print(result) 15 | self.assertTrue(result, """for i in 0..10 { 16 | sum += i; 17 | }""") 18 | 19 | def test_for_loop_index(self): 20 | variate = 'i' 21 | start_variate = '0' 22 | arr_variate = 'arr' 23 | exp = [1, 2, 3, 4, 5] 24 | arr = Array(arr_variate, exp, False) 25 | result = ForLoop(variate, start_variate, arr.array_len(), 'println(i);').get() 26 | print(result) 27 | self.assertTrue(result, """for i in 0..arr.len() { 28 | println(i); 29 | }""") 30 | 31 | def test_for_loop_values(self): 32 | variate = 'i' 33 | arr_variate = 'arr' 34 | exp = [1, 2, 3, 4, 5] 35 | arr = Array(arr_variate, exp, False) 36 | result = ForLoop(variate, '', arr.variate, 'println(i);').get() 37 | print(result) 38 | self.assertTrue(result, """for i in arr { 39 | println(i); 40 | }""") 41 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Python2Noir 2 | Generate Noir code through python. 3 | 4 | ## Description 5 | 6 | Easy to quickly convert python libraries to Noir contracts 7 | 8 | ## Directory structure 9 | 10 | - tests: Testcase for transpiler 11 | - transpiler: Python2Noir transpiler, include Noir language diffent module 12 | - context: Process the transformation context to build the complete Noir file 13 | - core_module: Include some core components such as struct and function 14 | - others_module: Include non-core statements 15 | - sub_module: Include some base components such as primitive type sign and key words 16 | - util: tools such as code format and logger 17 | 18 | ## Build guide 19 | 20 | - Python 3.7+ 21 | - Anaconda 22 | 23 | ## Import package 24 | 25 | ### linux 26 | ```shell 27 | pip install setuptools 28 | git clone https://github.com/storswiftlabs/python2noir.git 29 | python setup.py sdist 30 | pip install ./dist/python2noir-0.1.tar.gz 31 | ``` 32 | ### windows 33 | ```shell 34 | pip install setuptools 35 | git clone https://github.com/storswiftlabs/python2noir.git 36 | python setup.py bdist_wininst 37 | # execute exe file 38 | ./python2noir-0.1.win-amd64.exe 39 | ``` 40 | 41 | ## Example 42 | 43 | ```shell 44 | # clone repository 45 | git clone https://github.com/storswiftlabs/python2noir.git 46 | # execute testcase: python generated Noir code 47 | python -m unittest tests/transpiler/context/test_context.py 48 | ``` 49 | -------------------------------------------------------------------------------- /transpiler/core_module/control_pod.py: -------------------------------------------------------------------------------- 1 | from transpiler.core_module.statement_pod import Statement 2 | from ..sub_module.key_words import IF, ELSE, ELIF 3 | from ..sub_module.sign import LEFT_BRACE, RIGHT_BRACE, ASSIGNMENT, SEMICOLON 4 | 5 | 6 | def get_conditional(left_value, right_value, sign): 7 | return f"{left_value} {sign} {right_value}" 8 | 9 | 10 | class IfControl(Statement): 11 | 12 | def __init__(self, left_value, right_value, sign, body): 13 | self.left_value = left_value 14 | self.right_value = right_value 15 | self.sign = sign 16 | self.body = body 17 | 18 | def get(self): 19 | return f"{IF} {get_conditional(self.left_value, self.right_value, self.sign)} {LEFT_BRACE} \n{self.body}" \ 20 | f"\n{RIGHT_BRACE}" 21 | 22 | 23 | class IfElseControl(Statement): 24 | def __init__(self, left_value, right_value, sign, if_body, else_body): 25 | self.left_value = left_value 26 | self.right_value = right_value 27 | self.sign = sign 28 | self.if_body = if_body 29 | self.else_body = else_body 30 | 31 | def get(self) -> str: 32 | return f"{IF} {get_conditional(self.left_value, self.right_value, self.sign)} {LEFT_BRACE}" \ 33 | f"\n{self.if_body}\n" \ 34 | f"{RIGHT_BRACE} {ELSE} {LEFT_BRACE}" \ 35 | f"\n{self.else_body}\n" \ 36 | f"{RIGHT_BRACE}" 37 | 38 | 39 | class IfElifElseControl(Statement): 40 | def __init__(self): 41 | pass 42 | 43 | def get(self): 44 | pass 45 | -------------------------------------------------------------------------------- /tests/transpiler/core_module/test_func_pod.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from transpiler.core_module.func_pod import Function, FunctionGenerics 3 | from transpiler.sub_module.primitive_type import array_type, T, N, FIELD 4 | 5 | 6 | class test_func_pod(unittest.TestCase): 7 | def test_func_pod(self): 8 | inputs_variate_and_type = {'x': 'Field', 'y': 'Field'} 9 | body = ['x + y'] 10 | result = Function("main", inputs_variate_and_type, 'Field', body).get() 11 | print(result) 12 | assert result == """fn main(x : Field,y : Field,) -> pub Field { 13 | x + y 14 | } 15 | """ 16 | 17 | def test_FunctionGenerics(self): 18 | inputs_variate_and_type = {'x': array_type(T, N), 'y': T} 19 | body = ['x[0] + y'] 20 | my_function_generics = FunctionGenerics("bar", inputs_variate_and_type, 'Field', body, generics_type=True, 21 | generics_num=True) 22 | print("Function Generics:", my_function_generics.get()) 23 | assert my_function_generics.get() == """fn bar(x : [T; N],y : T,) -> pub Field { 24 | x[0] + y 25 | } 26 | """ 27 | 28 | def test_FunctionGenerics_impl_struct(self): 29 | inputs_variate_and_type = {'x': array_type(T, N), 'y': T} 30 | body = ['x[0] + y'] 31 | my_function_generics = Function("bar", inputs_variate_and_type, 'Field', body) 32 | print("Function Generics:", my_function_generics.get()) 33 | assert my_function_generics.get() == """fn bar(x : [T; N],y : T,) -> pub Field { 34 | x[0] + y 35 | } 36 | """ 37 | 38 | 39 | if __name__ == '__main__': 40 | unittest.main() 41 | -------------------------------------------------------------------------------- /transpiler/sub_module/primitive_type.py: -------------------------------------------------------------------------------- 1 | from .sign import LESS_THAN, GREATER_THAN 2 | 3 | # Primitive type 4 | INT8 = 'i8' 5 | INT16 = 'i16' 6 | INT32 = 'i32' 7 | INT64 = 'i64' 8 | INT126 = 'i126' 9 | UINT8 = 'u8' 10 | UINT16 = 'u16' 11 | UINT32 = 'u32' 12 | UINT64 = 'u64' 13 | UINT126 = 'u126' 14 | BoolType = 'bool' 15 | FIELD = 'Field' 16 | 17 | PRIMITIVE_TYPE = [INT8, INT16, INT32, INT64, INT126, UINT8, UINT16, UINT32, UINT64, UINT126, BoolType, FIELD] 18 | # Generics 19 | T = 'T' 20 | N = 'N' 21 | GENERICS = [T, N] 22 | 23 | # Boolean values 24 | FALSE = "false" 25 | TRUE = "true" 26 | 27 | 28 | def custom_type(custom: str) -> str: 29 | """ 30 | Custom integer type, the integer type cannot be less than 0 or more than 126. 31 | :param custom: str for integer type. 32 | :return: str for integer type. 33 | """ 34 | 35 | if custom[0] not in ['u', 'i']: 36 | raise Exception("Not a basic type of integer, signed certificate 'i', unsigned integer 'u'.") 37 | if int(custom[1:]) not in list(range(1, 127)): 38 | raise Exception("The integer type cannot be less than 0 or more than 126.") 39 | 40 | return custom 41 | 42 | 43 | def set_str(str_len): 44 | """ 45 | Set string length to form string type 46 | :param str_len: str length 47 | :return: string type 48 | """ 49 | 50 | return f"str{LESS_THAN}{str_len}{GREATER_THAN}" 51 | 52 | 53 | def array_type(arr_type: str, arr_len: int or N) -> str: 54 | """ 55 | Customer define array type 56 | :param arr_type: 57 | :param arr_len 58 | :return: str for array type. 59 | """ 60 | 61 | if arr_type not in PRIMITIVE_TYPE and arr_type not in GENERICS: 62 | raise TypeError("Input \"type\" value is not a primitive type") 63 | 64 | return f"[{arr_type}; {arr_len}]" 65 | -------------------------------------------------------------------------------- /transpiler/utils/utils.py: -------------------------------------------------------------------------------- 1 | from logging import getLogger 2 | 3 | log = getLogger(__name__) 4 | 5 | 6 | def table_format_control(data): 7 | """ 8 | table_format_control: Format output for list [str] 9 | inputs: 10 | data: list[str] 11 | return: 12 | new_data: Formatted list [str] 13 | """ 14 | if type(data) is str: 15 | data = data.split('\n') 16 | else: 17 | all_data = "" 18 | for element in data: 19 | all_data += element 20 | data = all_data.split('\n') 21 | control = 0 22 | new_data = [] 23 | prev = '' 24 | first_key = '' 25 | last_key = '' 26 | for index in range(0, len(data)): 27 | if data[index] != '': 28 | last_key = data[index].rstrip().lstrip()[-1] 29 | first_key = data[index].rstrip().lstrip()[0] 30 | else: 31 | new_data.append(generate_table(control) + data[index] + '\n') 32 | prev = last_key 33 | continue 34 | 35 | if last_key == "}": 36 | control -= 1 37 | new_data.append(generate_table(control) + data[index] + '\n') 38 | prev = last_key 39 | continue 40 | 41 | if prev == "{": 42 | control += 1 43 | new_data.append(generate_table(control) + data[index] + '\n') 44 | prev = last_key 45 | continue 46 | 47 | if prev != "{" and first_key == "}": 48 | control -= 1 49 | new_data.append(generate_table(control) + data[index] + '\n') 50 | prev = last_key 51 | continue 52 | 53 | new_data.append(generate_table(control) + data[index] + '\n') 54 | prev = last_key 55 | return new_data 56 | 57 | 58 | def generate_table(num): 59 | return '\t' * num 60 | -------------------------------------------------------------------------------- /transpiler/core_module/func_pod.py: -------------------------------------------------------------------------------- 1 | from abc import ABC, abstractmethod 2 | 3 | from transpiler.sub_module.key_words import FN, N, PUB, T 4 | from transpiler.sub_module.sign import LEFT_PARENTHESIS, RIGHT_PARENTHESIS, LEFT_BRACE, RIGHT_BRACE, RESULT, COMMA, \ 5 | LESS_THAN, GREATER_THAN 6 | from transpiler.utils import log 7 | 8 | 9 | class Func(ABC): 10 | """ 11 | Code function:The function body contains a set of functions that define the task the function performs. 12 | """ 13 | 14 | @abstractmethod 15 | def get(self): 16 | pass 17 | # Get a line code function 18 | 19 | 20 | class Function(Func): 21 | # Function: {fn} {variate} {global variable} ( {inputs} ) -> output { 22 | 23 | def __init__(self, fn_name: str, inputs_variate_and_type: dict, result_type: str, body: list): 24 | self.inputs_variate_and_type = '' 25 | self.fn_name = fn_name 26 | for key, value in inputs_variate_and_type.items(): 27 | temp = key + " : " + value + "," 28 | self.inputs_variate_and_type += temp 29 | self.result_type = result_type 30 | self.body = '\n'.join(body) 31 | 32 | def get(self): 33 | if self.result_type == '': 34 | return f"{FN} {self.fn_name}{LEFT_PARENTHESIS}{self.inputs_variate_and_type}{RIGHT_PARENTHESIS} " \ 35 | f"{LEFT_BRACE}\n{self.body}\n{RIGHT_BRACE}\n" 36 | else: 37 | return f"{FN} {self.fn_name}{LEFT_PARENTHESIS}{self.inputs_variate_and_type}{RIGHT_PARENTHESIS} " \ 38 | f"{RESULT} {PUB} {self.result_type} {LEFT_BRACE}\n{self.body}\n{RIGHT_BRACE}\n" 39 | 40 | 41 | class FunctionGenerics(Function): 42 | # Function: {fn} {variate} {global variable} ( {inputs} ) -> output { 43 | 44 | def __init__(self, fn_name: str, inputs_variate_and_type: dict, result_type: str, body: list, 45 | generics_type: bool = False, generics_num: bool = False): 46 | super().__init__(fn_name, inputs_variate_and_type, result_type, body) 47 | 48 | self.first_generics = "" 49 | self.second_generics = "" 50 | 51 | if generics_type: 52 | self.first_generics = T 53 | if generics_num: 54 | if self.first_generics: 55 | self.second_generics = f"{COMMA} {N}" 56 | else: 57 | self.first_generics = N 58 | self.generics_str = f"{LESS_THAN}{self.first_generics}{self.second_generics}{GREATER_THAN}" 59 | 60 | def get(self): 61 | if not self.first_generics and not self.second_generics: 62 | log.warning("Inputs generics args is None which both 'generics_type' and 'generics_num'") 63 | return super().get() 64 | 65 | return f"{FN} {self.fn_name}{self.generics_str}{LEFT_PARENTHESIS}{self.inputs_variate_and_type}" \ 66 | f"{RIGHT_PARENTHESIS} {RESULT} {PUB} {self.result_type} {LEFT_BRACE}\n{''.join(self.body)}\n{RIGHT_BRACE}\n" 67 | 68 | 69 | class Closure(Func): 70 | # {FN} {variate}{LEFT_PARENTHESIS}{inputs_dict}{RIGHT_PARENTHESIS} {RESULT} {res_type}{LEFT_BRACE} {exp} {RIGHT_BRACE} 71 | # fn bar(x: Field) -> Field { x + 1 } 72 | def __init__(self, variate, inputs_dict: dict, exp: list, res_type): 73 | self.closure_statement = f"{FN} {variate}{LEFT_PARENTHESIS}{inputs_dict}{RIGHT_PARENTHESIS} " \ 74 | f"{RESULT} {res_type}{LEFT_BRACE} {exp} {RIGHT_BRACE}" 75 | 76 | def get(self): 77 | return self.closure_statement 78 | -------------------------------------------------------------------------------- /transpiler/core_module/struct_pod.py: -------------------------------------------------------------------------------- 1 | from .func_pod import Function, FunctionGenerics 2 | from ..sub_module.key_words import STRUCT, IMPL, T, N 3 | from ..sub_module.sign import LEFT_BRACE, RIGHT_BRACE, COLON, COMMA, LESS_THAN, GREATER_THAN 4 | from ..utils import log 5 | 6 | 7 | class Struct: 8 | def __init__(self, struct_name, name_and_type: dict): 9 | # generate struct for context 10 | self.struct_name = struct_name 11 | self.name_and_type = name_and_type 12 | 13 | def generate_noir_struct(self) -> str: 14 | # return a string, Noir defined code style, for example "" 15 | struct_multi_lines = f"{STRUCT} {str(self.struct_name)} {LEFT_BRACE} \n" 16 | for k, v in self.name_and_type.items(): 17 | struct_multi_lines += f"{k}{COLON} {v}{COMMA}\n" 18 | struct_multi_lines += f"{RIGHT_BRACE}\n" 19 | return struct_multi_lines 20 | 21 | def impl_struct_fn(self, functions: list) -> str: 22 | struct_fn_multi_lines = f"{IMPL} {self.struct_name} {LEFT_BRACE} \n" 23 | for func in functions: 24 | struct_fn_multi_lines += func 25 | struct_fn_multi_lines += f"{RIGHT_BRACE}\n" 26 | return struct_fn_multi_lines 27 | 28 | def generate_struct_fn(self, fn_name: str, inputs_variate_and_type: dict, res: str, body: list) -> str: 29 | fn_str = Function(fn_name, inputs_variate_and_type, res, body).get() 30 | return fn_str 31 | 32 | 33 | class StructGenerics(Struct): 34 | def __init__(self, struct_name, name_and_type: dict, generics_type: bool = False, generics_num: bool = False): 35 | super().__init__(struct_name, name_and_type) 36 | 37 | self.first_generics = "" 38 | self.second_generics = "" 39 | 40 | if generics_type: 41 | self.first_generics = T 42 | if generics_num: 43 | if self.first_generics: 44 | self.second_generics = f"{COMMA} {N}" 45 | else: 46 | self.first_generics = N 47 | self.generics_str = f"{LESS_THAN}{self.first_generics}{self.second_generics}{GREATER_THAN}" 48 | 49 | def generate_noir_struct(self) -> str: 50 | # return a string, Noir defined code style, for example "" 51 | if not self.first_generics and not self.second_generics: 52 | log.warning("Inputs generics args is None which both 'generics_type' and 'generics_num'") 53 | return super().generate_noir_struct() 54 | 55 | struct_multi_lines = f"{STRUCT} {str(self.struct_name)}{self.generics_str} {LEFT_BRACE} \n" 56 | for k, v in self.name_and_type.items(): 57 | struct_multi_lines += f"{k}{COLON} {v}{COMMA}\n" 58 | struct_multi_lines += f"{RIGHT_BRACE}\n" 59 | 60 | return struct_multi_lines 61 | 62 | def impl_struct_fn(self, functions: list) -> str: 63 | if not self.first_generics and not self.second_generics: 64 | log.warning("Inputs generics args is None which both 'generics_type' and 'generics_num'") 65 | return super().impl_struct_fn(functions) 66 | 67 | struct_fn_multi_lines = f"{IMPL}{self.generics_str} {self.struct_name}{self.generics_str} {LEFT_BRACE} \n" 68 | for func in functions: 69 | struct_fn_multi_lines += func 70 | struct_fn_multi_lines += f"{RIGHT_BRACE}\n" 71 | return struct_fn_multi_lines 72 | 73 | def generate_struct_fn(self, fn_name: str, inputs_variate_and_type: dict, res: str, body: list) -> str: 74 | return super().generate_struct_fn(fn_name, inputs_variate_and_type, res, body) 75 | -------------------------------------------------------------------------------- /tests/transpiler/core_module/test_statement_pod.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | from transpiler.core_module.statement_pod import Assert, If_single_raw, Tuple, Array, Lambda, Global, Let_struct 4 | from transpiler.core_module.struct_pod import Struct 5 | 6 | 7 | class test_statement_pod(unittest.TestCase): 8 | def test_assert(self): 9 | conditional = "s.sum() == 42" 10 | my_assert = Assert(conditional) 11 | print(my_assert.get()) 12 | assert "assert(s.sum() == 42);" == my_assert.get() 13 | 14 | def test_if_single_raw(self): 15 | conditional = "s.sum() == 42" 16 | variate = "(a, b)" 17 | bool_exp = "true" 18 | if_exp = "(0, 1)" 19 | else_exp = "(2, 3)" 20 | my_if_single_raw = If_single_raw(variate, bool_exp, if_exp, else_exp) 21 | print(my_if_single_raw.get()) 22 | assert "let (a, b) = if true {(0, 1)} else {(2, 3)};" == my_if_single_raw.get() 23 | 24 | def test_tuple(self): 25 | variate = "(a, b)" 26 | exp = (0, 1) 27 | is_mut = True 28 | my_tuple_mut = Tuple(variate, exp, is_mut) 29 | print(my_tuple_mut.get()) 30 | assert "let mut (a, b) = (0, 1);" == my_tuple_mut.get() 31 | my_tuple = Tuple(variate, exp, not is_mut) 32 | print(my_tuple.get()) 33 | assert "let (a, b) = (0, 1);" == my_tuple.get() 34 | 35 | def test_array(self): 36 | variate = "arr" 37 | exp = [0, 1] 38 | is_mut = True 39 | my_array_mut = Array(variate, exp, is_mut) 40 | print(my_array_mut.get()) 41 | assert "let mut arr = [0, 1];" == my_array_mut.get() 42 | my_array = Array(variate, exp, not is_mut) 43 | print(my_array.get()) 44 | assert "let arr = [0, 1];" == my_array.get() 45 | 46 | def test_array_methods(self): 47 | variate = "arr" 48 | exp = [0, 1] 49 | is_mut = False 50 | my_array = Array(variate, exp, is_mut) 51 | my_len = my_array.array_len() 52 | assert "arr.len()" == my_len 53 | my_sort = my_array.array_sort() 54 | assert "arr.sort()" == my_sort 55 | my_sort_via = my_array.array_sort_via("|a, b| a > b") 56 | assert "arr.sort_via(|a, b| a > b)" == my_sort_via 57 | my_map = my_array.array_map("|a| a * 2") 58 | assert "arr.map(|a| a * 2)" == my_map 59 | my_fold = my_array.array_fold(0, "|a, b| a - b") 60 | assert "arr.fold(0, |a, b| a - b)" == my_fold 61 | my_reduce = my_array.array_reduce("|a, b| a - b") 62 | assert "arr.reduce(|a, b| a - b)" == my_reduce 63 | my_all = my_array.array_all("|a| a == 2") 64 | assert "arr.all(|a| a == 2)" == my_all 65 | my_any = my_array.array_any("|a| a == 2") 66 | assert "arr.any(|a| a == 2)" == my_any 67 | 68 | def test_lambda(self): 69 | variate = "some_closure" 70 | exp = "|x| 42 - x" 71 | is_mut = True 72 | my_lambda_mut = Lambda(variate, exp, is_mut) 73 | print(my_lambda_mut.get()) 74 | assert "let mut some_closure = |x| 42 - x;" == my_lambda_mut.get() 75 | my_lambda = Array(variate, exp, not is_mut) 76 | print(my_lambda.get()) 77 | assert "let some_closure = |x| 42 - x;" == my_lambda.get() 78 | 79 | def test_global_variate(self): 80 | inputs = ('N', 'Field', 5) 81 | result = Global(inputs).get() 82 | print(result) 83 | assert "global N : Field = 5;" == result 84 | 85 | def test_let_struct(self): 86 | struct_name = 'Animal' 87 | struct_input_name_and_type = {'hands': 2, 'legs': 3, 'eyes': 2} 88 | struct = Struct(struct_name, struct_input_name_and_type) 89 | result = Let_struct(struct, 'octopus', 'get_octopus()').get() 90 | print(result) 91 | assert "let octopus = Animal {hands: 2,legs: 3,eyes: 2,};" == result 92 | result = Let_struct(struct, 'octopus', 'get_octopus()').get_for_variate() 93 | print(result) 94 | assert "let Animal {hands,legs,eyes} = get_octopus();" == result 95 | -------------------------------------------------------------------------------- /transpiler/context/noir_context.py: -------------------------------------------------------------------------------- 1 | from typing import Union, List 2 | 3 | from transpiler.core_module.struct_pod import Struct, StructGenerics 4 | from transpiler.core_module.func_pod import Function, FunctionGenerics 5 | from transpiler.core_module.statement_pod import Global 6 | from transpiler.others_module import Annotation 7 | from transpiler.others_module.import_package import Use, Mod 8 | 9 | 10 | class NoirContext: 11 | def __init__(self): 12 | # User init Noir_context, use context structure noir code 13 | """ 14 | function_list []Func (func_type, func_data) 15 | struct_list []Struct 16 | variates {inputs:[], struct: [], map: [], let: []} 17 | """ 18 | self.function_list = [] 19 | self.struct_list = [] 20 | self.variates = dict() 21 | self.global_list = [] 22 | self.use_list = [] 23 | self.mod_list = [] 24 | self.annotations = [] 25 | 26 | def add_struct(self, struct_name, name_and_type: dict): 27 | # Define a structure 28 | noir_struct = Struct(struct_name, name_and_type) 29 | self.struct_list.append(noir_struct) 30 | 31 | def add_struct_generics(self, struct_name, name_and_type: dict, generics_type, generics_num): 32 | # Define a structure 33 | noir_struct = StructGenerics(struct_name, name_and_type, generics_type, generics_num) 34 | self.struct_list.append(noir_struct) 35 | 36 | def generate_struct_and_impl_function(self, funcs: list): 37 | pass 38 | 39 | def get_struct_by_name(self, struct_name): 40 | for struct_obj in self.struct_list: 41 | if struct_obj.struct_name == struct_name: 42 | return struct_obj 43 | 44 | def generate_struct(self): 45 | noir_lines = [] 46 | # Fill struct definition 47 | for struct in self.struct_list: 48 | noir_lines.append(struct.generate_noir_struct()) 49 | return noir_lines 50 | 51 | def add_function(self, variate, inputs: dict, return_type, body): 52 | func = Function(variate, inputs, return_type, body) 53 | self.function_list.append(func) 54 | 55 | def add_function_generics(self, variate, inputs: dict, return_type, body, generics_type, generics_num): 56 | func = FunctionGenerics(variate, inputs, return_type, body, generics_type, generics_num) 57 | self.function_list.append(func) 58 | 59 | def add_global(self, inputs: tuple): 60 | noir_global = Global(inputs) 61 | self.global_list.append(noir_global) 62 | 63 | def generate_global(self): 64 | noir_lines = [] 65 | for global_variate in self.global_list: 66 | noir_lines.append(global_variate.get()) 67 | return noir_lines 68 | 69 | # TODO: There are too few operating methods for `use` 70 | def add_use(self, use_statement): 71 | use = Use() 72 | use.define_custom_use(use_statement) 73 | self.use_list.append(use.custom_use) 74 | 75 | def generate_use(self): 76 | noir_list = [] 77 | for use_variate in self.use_list: 78 | noir_list.append(use_variate) 79 | return noir_list 80 | 81 | def add_mod(self, fn_name): 82 | use = Mod(fn_name) 83 | self.mod_list.append(use) 84 | 85 | def generate_mod(self): 86 | noir_list = [] 87 | for mod_variate in self.mod_list: 88 | noir_list.append(mod_variate.get()) 89 | return noir_list 90 | 91 | def add_annotation(self, line, content): 92 | annotation = Annotation(line, content) 93 | self.annotations.append(annotation) 94 | 95 | def append_annotation(self, noir_lines: list): 96 | for annotation_obj in self.annotations: 97 | noir_lines.insert(annotation_obj.line, annotation_obj.get_content()) 98 | return noir_lines 99 | 100 | def generate_noir_code_list(self): 101 | self.add_annotation(0, "Code generated from Python2Noir") 102 | noir_lines = [] 103 | # Fill struct definition 104 | for use in self.use_list: 105 | noir_lines.append(use) 106 | for mod in self.mod_list: 107 | noir_lines.append(mod.get()) 108 | for variate in self.global_list: 109 | noir_lines.append(variate.get()+'\n') 110 | for struct in self.struct_list: 111 | noir_lines.append(struct.generate_noir_struct()) 112 | # Fill function 113 | for func in self.function_list: 114 | noir_lines.append(func.get()) 115 | noir_lines = self.append_annotation(noir_lines) 116 | return noir_lines 117 | -------------------------------------------------------------------------------- /tests/transpiler/core_module/test_struct_pod.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | from transpiler.core_module import Struct, StructGenerics 4 | from transpiler.sub_module.key_words import SELF 5 | from transpiler.sub_module.primitive_type import FIELD, array_type, N 6 | 7 | 8 | class test_struct_pod(unittest.TestCase): 9 | def test_generate_noir_struct(self): 10 | struct_name = "Dataset" 11 | name_and_type = {"node": "u32", "son_node_nums": "u8", "level": "u8", "weight": "u16"} 12 | my_struct = Struct(struct_name, name_and_type) 13 | print("struct:", my_struct.generate_noir_struct()) 14 | assert my_struct.generate_noir_struct() == """struct Dataset { 15 | node: u32, 16 | son_node_nums: u8, 17 | level: u8, 18 | weight: u16, 19 | } 20 | """ 21 | 22 | def test_generate_noir_struct_generics_all_none(self): 23 | struct_name = "Dataset" 24 | name_and_type = {"node": "u32", "son_node_nums": "u8", "level": "u8", "weight": "u16"} 25 | my_struct = StructGenerics(struct_name, name_and_type) 26 | print("struct:", my_struct.generate_noir_struct()) 27 | assert my_struct.generate_noir_struct() == """struct Dataset { 28 | node: u32, 29 | son_node_nums: u8, 30 | level: u8, 31 | weight: u16, 32 | } 33 | """ 34 | 35 | def test_generate_noir_struct_generics_type_none(self): 36 | struct_name = "Dataset" 37 | name_and_type = {"node": "u32", "son_node_nums": "u8", "level": "u8", "weight": "u16"} 38 | generics_num = True 39 | my_struct = StructGenerics(struct_name, name_and_type, generics_type=False, generics_num=generics_num) 40 | print("struct:", my_struct.generate_noir_struct()) 41 | assert my_struct.generate_noir_struct() == """struct Dataset { 42 | node: u32, 43 | son_node_nums: u8, 44 | level: u8, 45 | weight: u16, 46 | } 47 | """ 48 | 49 | def test_generate_noir_struct_generics_number_none(self): 50 | struct_name = "Dataset" 51 | name_and_type = {"node": "u32", "son_node_nums": "u8", "level": "u8", "weight": "u16"} 52 | generics_type = True 53 | my_struct = StructGenerics(struct_name, name_and_type, generics_type=generics_type) 54 | print("struct:", my_struct.generate_noir_struct()) 55 | assert my_struct.generate_noir_struct() == """struct Dataset { 56 | node: u32, 57 | son_node_nums: u8, 58 | level: u8, 59 | weight: u16, 60 | } 61 | """ 62 | 63 | def test_generate_noir_struct_generics_all(self): 64 | struct_name = "Dataset" 65 | name_and_type = {"node": "u32", "son_node_nums": "u8", "level": "u8", "weight": "u16"} 66 | generics_type = True 67 | generics_num = True 68 | my_struct = StructGenerics(struct_name, name_and_type, generics_type=generics_type, generics_num=generics_num) 69 | print("struct:", my_struct.generate_noir_struct()) 70 | assert my_struct.generate_noir_struct() == """struct Dataset { 71 | node: u32, 72 | son_node_nums: u8, 73 | level: u8, 74 | weight: u16, 75 | } 76 | """ 77 | 78 | def test_impl_struct_fn(self): 79 | struct_name = "Dataset" 80 | name_and_type = {"bar": FIELD, "baz": array_type(FIELD, 3)} 81 | my_struct = Struct(struct_name, name_and_type) 82 | print("struct:\n", my_struct.generate_noir_struct()) 83 | some_fn1 = my_struct.generate_struct_fn("some_fn1", {"self": SELF}, FIELD, 84 | ["self.bar + self.baz[0] + self.baz[1]"]) 85 | some_fn2 = my_struct.generate_struct_fn("some_fn2", {"self": SELF}, FIELD, 86 | ["self.bar + self.baz[0] + self.baz[1]"]) 87 | impl_list = [some_fn1, some_fn2] 88 | print("struct impl:\n", my_struct.impl_struct_fn(impl_list)) 89 | assert my_struct.impl_struct_fn(impl_list) == """impl Dataset { 90 | fn some_fn1(self : Self,) -> pub Field { 91 | self.bar + self.baz[0] + self.baz[1] 92 | } 93 | fn some_fn2(self : Self,) -> pub Field { 94 | self.bar + self.baz[0] + self.baz[1] 95 | } 96 | } 97 | """ 98 | 99 | def test_impl_struct_fn_generics(self): 100 | struct_name = "Dataset" 101 | name_and_type = {"bar": FIELD, "baz": array_type(FIELD, 2)} 102 | my_struct = StructGenerics(struct_name, name_and_type, generics_type=True, generics_num=True) 103 | print("struct:\n", my_struct.generate_noir_struct()) 104 | some_fn1 = my_struct.generate_struct_fn("some_fn1", {"self": SELF}, FIELD, 105 | ["self.bar + self.baz[0] + self.baz[1]"]) 106 | some_fn2 = my_struct.generate_struct_fn("some_fn2", {"self": SELF}, FIELD, 107 | ["self.bar + self.baz[0] + self.baz[1]"]) 108 | impl_list = [some_fn1, some_fn2] 109 | print("struct impl:\n", my_struct.impl_struct_fn(impl_list)) 110 | assert my_struct.impl_struct_fn(impl_list) == """impl Dataset { 111 | fn some_fn1(self : Self,) -> pub Field { 112 | self.bar + self.baz[0] + self.baz[1] 113 | } 114 | fn some_fn2(self : Self,) -> pub Field { 115 | self.bar + self.baz[0] + self.baz[1] 116 | } 117 | } 118 | """ 119 | -------------------------------------------------------------------------------- /tests/transpiler/context/test_context.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from transpiler.context.noir_context import NoirContext 3 | from transpiler.core_module.statement_pod import Let 4 | from transpiler.core_module.for_loop_pod import ForLoop 5 | from transpiler.core_module.control_pod import IfControl 6 | from transpiler.sub_module.primitive_type import UINT32, custom_type, INT64 7 | from transpiler.sub_module.sign import LESS_THAN 8 | from transpiler.utils.utils import table_format_control 9 | 10 | 11 | class test_context(unittest.TestCase): 12 | def test_add_struct(self): 13 | struct_name = "Axis" 14 | name_and_type = {'node_name': 'u8', 'right': 'bool', 'left': 'bool'} 15 | context = NoirContext() 16 | context.add_struct(struct_name, name_and_type) 17 | struct_str = "" 18 | for line in context.generate_struct(): 19 | struct_str += line 20 | print(struct_str) 21 | self.assertTrue(struct_str, """struct Axis { 22 | node_name: u8; 23 | right: bool; 24 | left: bool; 25 | }""") 26 | 27 | def test_generate_noir(self): 28 | context = NoirContext() 29 | array_type = '[i64;6]' 30 | variate = 'sum' 31 | 32 | # Import Standard library 33 | # context.add_use() 34 | 35 | # add obtainEuclideanDistance function 36 | fn_name = 'obtainEuclideanDistance' 37 | fn_inputs_name_and_type = {'inputs': array_type, 'point': array_type} 38 | fn_result = INT64 39 | body = [] 40 | 41 | let = Let(variate, INT64, 0, True).get() 42 | body.append(let) 43 | 44 | for_loop = ForLoop('index', 0, 5, 'sum += (point[index] - inputs[index]) * (point[index] - inputs[index])') \ 45 | .get() 46 | body.append(for_loop) 47 | 48 | body.append(variate) 49 | 50 | context.add_function(fn_name, fn_inputs_name_and_type, fn_result, body) 51 | 52 | # add check_min function 53 | fn_name = 'check_min' 54 | fn_inputs_name_and_type = {'e0': INT64, 'e1': INT64, 'e2': INT64, 'e3': INT64} 55 | fn_result = custom_type('u3') 56 | body = [] 57 | 58 | let_output = Let('output', fn_result, 0, True).get() 59 | body.append(let_output) 60 | let_temp = Let('temp', INT64, 'e0', True).get() 61 | body.append(let_temp) 62 | 63 | sign = LESS_THAN 64 | control_1 = IfControl('e1', 'temp', sign, "temp = e1;\noutput = 1").get() 65 | body.append(control_1) 66 | control_2 = IfControl('e2', 'temp', sign, "temp = e2;\noutput = 2").get() 67 | body.append(control_2) 68 | control_3 = IfControl('e3', 'temp', sign, "temp = e3;\noutput = 3").get() 69 | body.append(control_3) 70 | 71 | body.append('output') 72 | 73 | context.add_function(fn_name, fn_inputs_name_and_type, fn_result, body) 74 | 75 | context.add_function_generics( 76 | fn_name, fn_inputs_name_and_type, fn_result, body, generics_type=True, generics_num=True) 77 | 78 | # add main function 79 | fn_name = 'main' 80 | fn_inputs_name_and_type = {'inputs': array_type, 'point0': array_type, 'point1': array_type, 81 | 'point2': array_type, 'point3': array_type} 82 | fn_result = custom_type('u3') 83 | body = [] 84 | 85 | let_e0 = Let('e0', INT64, 'obtainEuclideanDistance(inputs, point0)', False).get() 86 | body.append(let_e0) 87 | let_e1 = Let('e1', INT64, 'obtainEuclideanDistance(inputs, point1)', False).get() 88 | body.append(let_e1) 89 | let_e2 = Let('e2', INT64, 'obtainEuclideanDistance(inputs, point2)', False).get() 90 | body.append(let_e2) 91 | let_e3 = Let('e3', INT64, 'obtainEuclideanDistance(inputs, point3)', False).get() 92 | body.append(let_e3) 93 | 94 | body.append('check_min(e0,e1,e2,e3)') 95 | 96 | context.add_function(fn_name, fn_inputs_name_and_type, fn_result, body) 97 | 98 | 99 | noir_code = context.generate_noir_code_list() 100 | print(''.join(table_format_control(noir_code))) 101 | assert ''.join(table_format_control(noir_code)) == """// Code generated from Python2Noir 102 | fn obtainEuclideanDistance(inputs : [i64;6],point : [i64;6],) -> pub i64 { 103 | let mut sum: i64 = 0; 104 | for index in 0..5 { 105 | sum += (point[index] - inputs[index]) * (point[index] - inputs[index]) 106 | } 107 | sum 108 | } 109 | fn check_min(e0 : i64,e1 : i64,e2 : i64,e3 : i64,) -> pub u3 { 110 | let mut output: u3 = 0; 111 | let mut temp: i64 = e0; 112 | if e1 < temp { 113 | temp = e1; 114 | output = 1 115 | } 116 | if e2 < temp { 117 | temp = e2; 118 | output = 2 119 | } 120 | if e3 < temp { 121 | temp = e3; 122 | output = 3 123 | } 124 | output 125 | } 126 | fn check_min(e0 : i64,e1 : i64,e2 : i64,e3 : i64,) -> pub u3 { 127 | let mut output: u3 = 0; 128 | let mut temp: i64 = e0; 129 | if e1 < temp { 130 | temp = e1; 131 | output = 1 132 | } 133 | if e2 < temp { 134 | temp = e2; 135 | output = 2 136 | } 137 | if e3 < temp { 138 | temp = e3; 139 | output = 3 140 | } 141 | output 142 | } 143 | fn main(inputs : [i64;6],point0 : [i64;6],point1 : [i64;6],point2 : [i64;6],point3 : [i64;6],) -> pub u3 { 144 | let e0: i64 = obtainEuclideanDistance(inputs, point0); 145 | let e1: i64 = obtainEuclideanDistance(inputs, point1); 146 | let e2: i64 = obtainEuclideanDistance(inputs, point2); 147 | let e3: i64 = obtainEuclideanDistance(inputs, point3); 148 | check_min(e0,e1,e2,e3) 149 | } 150 | 151 | """ 152 | 153 | def test_add_annotation(self): 154 | context = NoirContext() 155 | context.add_annotation(0, "will insert to line 0") 156 | context.add_annotation(2, "will insert to line 2") 157 | 158 | struct_name = "Axis" 159 | name_and_type = {'node_name': 'u8', 'right': 'bool', 'left': 'bool'} 160 | context.add_struct(struct_name, name_and_type) 161 | my_code = context.generate_struct() 162 | my_code = "".join(context.append_annotation(my_code)) 163 | print(my_code) 164 | self.assertTrue(my_code, """// will insert to line 0 165 | struct Axis { 166 | node_name: u8, 167 | right: bool, 168 | left: bool, 169 | } 170 | // will insert to line 2 171 | """) 172 | 173 | 174 | if __name__ == '__main__': 175 | unittest.main() 176 | -------------------------------------------------------------------------------- /transpiler/core_module/statement_pod.py: -------------------------------------------------------------------------------- 1 | from abc import ABC, abstractmethod 2 | 3 | from ..sub_module.key_words import ASSERT, LET, IF, ELSE, MUT, FN, GLOBAL 4 | from ..sub_module.sign import LEFT_PARENTHESIS, RIGHT_PARENTHESIS, SEMICOLON, LEFT_BRACE, RIGHT_BRACE, POINT, COMMA, \ 5 | RESULT, ASSIGNMENT, COLON 6 | from transpiler.core_module.struct_pod import Struct 7 | 8 | 9 | class Statement(ABC): 10 | """ 11 | Code statement:The function body contains a set of statements that define the task the function performs. 12 | """ 13 | 14 | @abstractmethod 15 | def get(self): 16 | pass 17 | # Get a line code statement 18 | 19 | 20 | class Let(Statement): 21 | # let statement: {let} {variate}: {variate_type} = {variate_body}; 22 | 23 | def __init__(self, variate, variate_type, variate_body, is_mut: bool): 24 | # Get a line code statement 25 | self.variate = variate 26 | if is_mut: 27 | self.let_statement = f"{LET} mut {variate}: {variate_type} {ASSIGNMENT} {variate_body}{SEMICOLON}" 28 | else: 29 | self.let_statement = f"{LET} {variate}: {variate_type} {ASSIGNMENT} {variate_body}{SEMICOLON}" 30 | 31 | def get(self): 32 | # Get a line code statement 33 | return self.let_statement 34 | 35 | 36 | class Assert(Statement): 37 | # {assert}{LEFT_PARENTHESIS}{conditional}{RIGHT_PARENTHESIS}{SEMICOLON} 38 | # assert (s.sum() == 42); 39 | # assert(array_eq(array, array, MyStruct::eq)); 40 | # assert (array_eq([1, 2, 3], [1, 2, 3], | a, b | a == b)); 41 | 42 | def __init__(self, conditional): 43 | self.assert_statement = f"{ASSERT}{LEFT_PARENTHESIS}{conditional}{RIGHT_PARENTHESIS}{SEMICOLON}" 44 | 45 | def get(self): 46 | # Get a line code statement 47 | return self.assert_statement 48 | 49 | 50 | class If_single_raw(Statement): 51 | # Ternary expression 52 | # {LET} {variate} = {IF} {exp} {LEFT_BRACE}{if_exp}{RIGHT_BRACE} {ELSE} {LEFT_BRACE}{else_exp}{RIGHT_BRACE}{SEMICOLON} 53 | # let (a, b) = if true { (0, 1) } else { (2, 3) }; 54 | def __init__(self, variate, bool_exp, if_exp, else_exp): 55 | self.variate = variate 56 | self.if_single_raw_statement = f"{LET} {variate} {ASSIGNMENT} {IF} {bool_exp} {LEFT_BRACE}{if_exp}" \ 57 | f"{RIGHT_BRACE} {ELSE} {LEFT_BRACE}{else_exp}{RIGHT_BRACE}{SEMICOLON}" 58 | 59 | def get(self): 60 | return self.if_single_raw_statement 61 | 62 | 63 | class Tuple(Statement): 64 | # {LET} {variate} = {exp}{SEMICOLON} 65 | # let (a, b) = (0, 1); 66 | def __init__(self, variate, exp, is_mut: bool): 67 | self.variate = variate 68 | if is_mut: 69 | self.tuple_statement = f"{LET} {MUT} {variate} {ASSIGNMENT} {exp}{SEMICOLON}" 70 | else: 71 | self.tuple_statement = f"{LET} {variate} {ASSIGNMENT} {exp}{SEMICOLON}" 72 | 73 | def get(self): 74 | return self.tuple_statement 75 | 76 | 77 | class Array(Statement): 78 | # Ternary expression 79 | # {LET} {variate} = {exp}{SEMICOLON} 80 | # let arr = [0, 1]; 81 | # let arr: [Field; 2] = [0, 1]; 82 | # XXX: 1 exp: str; 2 multi_type_check; 3 is_define_type: add a arg 83 | def __init__(self, variate, exp, is_mut): 84 | self.variate = variate 85 | variate = str(variate) 86 | if is_mut: 87 | self.array_statement = f"{LET} {MUT} {variate} {ASSIGNMENT} {exp}{SEMICOLON}" 88 | else: 89 | self.array_statement = f"{LET} {variate} {ASSIGNMENT} {exp}{SEMICOLON}" 90 | 91 | def get(self): 92 | return self.array_statement 93 | 94 | def array_len(self): 95 | array_len = 'len()' 96 | return f"{self.variate}{POINT}{array_len}" 97 | 98 | def array_sort(self): 99 | array_sort = 'sort()' 100 | return f"{self.variate}{POINT}{array_sort}" 101 | 102 | def array_sort_via(self, sort_lambda): 103 | array_sort_via = f'sort_via({sort_lambda})' 104 | return f"{self.variate}{POINT}{array_sort_via}" 105 | 106 | def array_map(self, map_lambda): 107 | array_map = f'map({map_lambda})' 108 | return f"{self.variate}{POINT}{array_map}" 109 | 110 | def array_fold(self, start_index: int, fold_lambda): 111 | array_fold = f'fold({start_index}{COMMA} {fold_lambda})' 112 | return f"{self.variate}{POINT}{array_fold}" 113 | 114 | def array_reduce(self, reduce_lambda): 115 | array_reduce = f'reduce({reduce_lambda})' 116 | return f"{self.variate}{POINT}{array_reduce}" 117 | 118 | def array_all(self, all_lambda): 119 | array_all = f'all({all_lambda})' 120 | return f"{self.variate}{POINT}{array_all}" 121 | 122 | def array_any(self, any_lambda): 123 | array_any = f'any({any_lambda})' 124 | return f"{self.variate}{POINT}{array_any}" 125 | 126 | 127 | class Lambda(Statement): 128 | # Ternary expression 129 | # {LET} {variate} = {exp}{SEMICOLON} 130 | # let some_closure = |x| 42 - x; 131 | # XXX: lambda exp check 132 | def __init__(self, variate, exp, is_mut: bool): 133 | self.variate = variate 134 | if is_mut: 135 | self.lambda_statement = f"{LET} {MUT} {variate} {ASSIGNMENT} {exp}{SEMICOLON}" 136 | else: 137 | self.lambda_statement = f"{LET} {variate} {ASSIGNMENT} {exp}{SEMICOLON}" 138 | 139 | def get(self): 140 | return self.lambda_statement 141 | 142 | 143 | class Let_struct(Statement): 144 | # let_struct statement: {let} {struct_name} 145 | """ 146 | define: 147 | 1. let octopus = Animal {hands: 0,legs: 8,eyes: 2}; 148 | receive 149 | 1. let Animal { hands, legs, eyes } = get_octopus(); 150 | 2. let octopus : Animal = get_octopus(); 151 | """ 152 | 153 | def __init__(self, struct: Struct, variate, body): 154 | self.struct = struct 155 | self.variate = variate 156 | self.body = body 157 | 158 | def get(self): 159 | """ 160 | let octopus = Animal {hands: 0,legs: 8,eyes: 2}; 161 | """ 162 | struct = f"{LET} {self.variate} {ASSIGNMENT} {self.struct.struct_name} {LEFT_BRACE}" 163 | for key, value in self.struct.name_and_type.items(): 164 | struct += f"{key}{COLON} {value}{COMMA}" 165 | struct += f"{RIGHT_BRACE}{SEMICOLON}" 166 | return struct 167 | 168 | def get_for_variate(self): 169 | """ 170 | let Animal { hands, legs, eyes } = get_octopus(); 171 | """ 172 | variate = [] 173 | for key, value in self.struct.name_and_type.items(): 174 | variate.append(key) 175 | return f"{LET} {self.struct.struct_name} {LEFT_BRACE}{','.join(variate)}{RIGHT_BRACE} {ASSIGNMENT} " \ 176 | f"{self.body}{SEMICOLON}" 177 | 178 | 179 | class Global(Statement): 180 | 181 | def __init__(self, inputs: tuple): 182 | self.global_variate = f"{GLOBAL} {inputs[0]} : {inputs[1]} {ASSIGNMENT} {inputs[2]}{SEMICOLON}" 183 | 184 | def get(self): 185 | return self.global_variate 186 | --------------------------------------------------------------------------------