From 69fa9daa1222c0371ed42a9bc3652fed7f83759c Mon Sep 17 00:00:00 2001 From: Ben Guidarelli Date: Sun, 15 Jan 2023 08:41:05 -0500 Subject: [PATCH 1/6] add vscode gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 289cfb3..80999c2 100644 --- a/.gitignore +++ b/.gitignore @@ -130,3 +130,4 @@ dmypy.json .DS_Store .idea +.vscode/ From 0f1d3bc31c99a2903b8e6dbf5c060cbfcdbd1908 Mon Sep 17 00:00:00 2001 From: Ben Guidarelli Date: Sun, 29 Jan 2023 09:29:34 -0500 Subject: [PATCH 2/6] adding ability to declare bytes as a hex literal --- tealish/nodes.py | 21 +++- tealish/tealish_expressions.tx | 3 +- tests/everything.teal | 188 +++++++++++++++++---------------- tests/everything.tl | 3 +- 4 files changed, 117 insertions(+), 98 deletions(-) diff --git a/tealish/nodes.py b/tealish/nodes.py index b1b7353..00d0f5a 100644 --- a/tealish/nodes.py +++ b/tealish/nodes.py @@ -22,7 +22,8 @@ from .scope import Scope, VarType LITERAL_INT = r"[0-9]+" -LITERAL_BYTES = r'"(.+)"' +LITERAL_BYTE_STRING = r'"(.+)"' +LITERAL_BYTE_HEX = r"0x([a-zA-Z0-9]+)" VARIABLE_NAME = r"[a-z_][a-zA-Z0-9_]*" if TYPE_CHECKING: @@ -140,7 +141,7 @@ class Literal(Expression): @classmethod def parse(cls, line: str, parent: Node, compiler: "TealishCompiler") -> Node: - matchable: List[Type[Expression]] = [LiteralInt, LiteralBytes] + matchable: List[Type[Expression]] = [LiteralInt, LiteralBytes, LiteralHex] for expr in matchable: if expr.match(line): return expr(line, parent, compiler) @@ -162,7 +163,21 @@ def _tealish(self) -> str: class LiteralBytes(Literal): - pattern = rf"(?P{LITERAL_BYTES})$" + pattern = rf"(?P{LITERAL_BYTE_STRING})$" + value: str + + def write_teal(self, writer: "TealWriter") -> None: + writer.write(self, f"pushbytes {self.value}") + + def type(self) -> AVMType: + return AVMType.bytes + + def _tealish(self) -> str: + return f"{self.value}" + + +class LiteralHex(Literal): + pattern = rf"(?P{LITERAL_BYTE_HEX})$" value: str def write_teal(self, writer: "TealWriter") -> None: diff --git a/tealish/tealish_expressions.tx b/tealish/tealish_expressions.tx index 1bea043..c80a82e 100644 --- a/tealish/tealish_expressions.tx +++ b/tealish/tealish_expressions.tx @@ -34,5 +34,6 @@ Name: (/([a-z][A-Za-z_0-9]*)/ | /_/); GroupIndex: NegativeGroupIndex | PositiveGroupIndex | Expression; NegativeGroupIndex: '-' index=INT; PositiveGroupIndex: '+' index=INT; +HexBytes: value=/0x([a-zA-Z0-9]+)/; Integer: value=/[0-9_]+/; -Bytes: value=STRING; +Bytes: value=STRING | HexBytes; diff --git a/tests/everything.teal b/tests/everything.teal index 994ea7e..56fc35e 100644 --- a/tests/everything.teal +++ b/tests/everything.teal @@ -17,54 +17,56 @@ store 0 // a // bytes b = BAR [slot 1] pushbytes "bar" // BAR store 1 // b - +// bytes c = BAZ [slot 2] +pushbytes 0xDEADBEEF // BAZ +store 2 // c // Structs -// Item item1 = bzero(46) [slot 2] +// Item item1 = bzero(46) [slot 3] pushint 46 bzero -store 2 // item1 -// item1.id = 123 [slot 2] -load 2 // item1 +store 3 // item1 +// item1.id = 123 [slot 3] +load 3 // item1 pushint 123 itob replace 0 // item1.id -store 2 // item1 -// item1.name = "xyz" [slot 2] -load 2 // item1 +store 3 // item1 +// item1.name = "xyz" [slot 3] +load 3 // item1 pushbytes "xyz" replace 16 // item1.name -store 2 // item1 +store 3 // item1 // assert(item1.id > 0) -load 2 // item1 +load 3 // item1 pushint 0 extract_uint64 // id pushint 0 > assert // log(item1.name) -load 2 // item1 +load 3 // item1 extract 16 10 // name log // Delcaration without assignment -// int balance [slot 3] -// int exists [slot 4] +// int balance [slot 4] +// int exists [slot 5] // Multiple assignment // Opcode with immediate arg // exists, balance = asset_holding_get(AssetBalance, 0, 5) pushint 0 pushint 5 asset_holding_get AssetBalance -store 4 // exists -store 3 // balance +store 5 // exists +store 4 // balance // Use of _ to ignore a return value // _, balance = asset_holding_get(AssetBalance, 1, 5) pushint 1 pushint 5 asset_holding_get AssetBalance pop // discarding value for _ -store 3 // balance +store 4 // balance // if FOO > 1: @@ -116,20 +118,20 @@ store 3 // balance // Boxes -// box box1 = CreateBox("a") [slot 5] +// box box1 = CreateBox("a") [slot 6] pushbytes "a" dup pushint 26 box_create assert // assert created -store 5 // box1 +store 6 // box1 // box1.name = "xyz" [box] -load 5 // box key box1 +load 6 // box key box1 pushint 16 // offset pushbytes "xyz" box_replace // box1.name // assert(box1.id) -load 5 // box key box1 +load 6 // box key box1 pushint 0 // offset pushint 8 // size box_extract // box1.id @@ -151,14 +153,14 @@ b fail // else // block main main: - // int amount = sum(2, 3) [slot 6] + // int amount = sum(2, 3) [slot 7] pushint 2 pushint 3 callsub __func__sum - store 6 // amount + store 7 // amount // transfer(0, amount, Gtxn[-1].Sender, Txn.Accounts[1]) pushint 0 - load 6 // amount + load 7 // amount txn GroupIndex pushint 1 - @@ -166,36 +168,36 @@ main: txna Accounts 1 callsub __func__transfer - // int sum = teal_sum(2, 3) [slot 7] + // int sum = teal_sum(2, 3) [slot 8] pushint 2 pushint 3 callsub __func__teal_sum - store 7 // sum + store 8 // sum // assert(amount == sum) - load 6 // amount - load 7 // sum + load 7 // amount + load 8 // sum == assert - // int z = add_amount(5) [slot 8] + // int z = add_amount(5) [slot 9] pushint 5 callsub main__func__add_amount - store 8 // z + store 9 // z - // int i = 0 [slot 9] + // int i = 0 [slot 10] pushint 0 - store 9 // i + store 10 // i // while i < z: l3_while: - load 9 // i - load 8 // z + load 10 // i + load 9 // z < bz l3_end // i = i + 1 - load 9 // i + load 10 // i pushint 1 + - store 9 // i + store 10 // i b l3_while l3_end: // end @@ -207,10 +209,10 @@ main: == bnz l4_end // i = i + 1 - load 9 // i + load 10 // i pushint 1 + - store 9 // i + store 10 // i pushint 1 + dup @@ -220,60 +222,60 @@ main: // for x in 1:10: pushint 1 - store 10 // x + store 11 // x l5_for: - load 10 // x + load 11 // x pushint 10 == bnz l5_end // log(itob(x)) - load 10 // x + load 11 // x itob log - load 10 // x + load 11 // x pushint 1 + - store 10 // x + store 11 // x b l5_for l5_end: // end - // int first = 1 [slot 10] + // int first = 1 [slot 11] pushint 1 - store 10 // first - // int last = 5 + 5 [slot 11] + store 11 // first + // int last = 5 + 5 [slot 12] pushint 5 pushint 5 + - store 11 // last + store 12 // last // For loop with variables // for x in first:last: - load 10 // first - store 12 // x + load 11 // first + store 13 // x l6_for: - load 12 // x - load 11 // last + load 13 // x + load 12 // last == bnz l6_end // log(itob(x)) - load 12 // x + load 13 // x itob log - load 12 // x + load 13 // x pushint 1 + - store 12 // x + store 13 // x b l6_for l6_end: // end // Function with multiple return values - // int fx [slot 12] - // int fy [slot 13] + // int fx [slot 13] + // int fy [slot 14] // fx, fy = foo(1, 2) pushint 1 pushint 2 callsub __func__foo - store 12 // fx - store 13 // fy + store 13 // fx + store 14 // fy // exit(1) pushint 1 @@ -282,14 +284,14 @@ main: // Locally scoped function using variable from parent scope // func add_amount(x: int) int: main__func__add_amount: - store 14 // x - // int result = amount + x [slot 15] - load 6 // amount - load 14 // x + store 15 // x + // int result = amount + x [slot 16] + load 7 // amount + load 15 // x + - store 15 // result + store 16 // result // return result - load 15 // result + load 16 // result retsub @@ -357,12 +359,12 @@ retsub // Function with args but no return value // func transfer(asset_id: int, amount: int, sender: bytes, receiver: bytes): __func__transfer: -store 16 // receiver -store 17 // sender -store 18 // amount -store 19 // asset_id +store 17 // receiver +store 18 // sender +store 19 // amount +store 20 // asset_id // if asset_id == 0: - load 19 // asset_id + load 20 // asset_id pushint 0 == bz l8_else @@ -373,13 +375,13 @@ store 19 // asset_id pushint 1 // Pay itxn_field TypeEnum // Sender: sender - load 17 // sender + load 18 // sender itxn_field Sender // Receiver: receiver - load 16 // receiver + load 17 // receiver itxn_field Receiver // Amount: amount - load 18 // amount + load 19 // amount itxn_field Amount // Fee: 0 pushint 0 @@ -395,16 +397,16 @@ store 19 // asset_id pushint 4 // Axfer itxn_field TypeEnum // Sender: sender - load 17 // sender + load 18 // sender itxn_field Sender // AssetReceiver: receiver - load 16 // receiver + load 17 // receiver itxn_field AssetReceiver // AssetAmount: amount - load 18 // amount + load 19 // amount itxn_field AssetAmount // XferAsset: asset_id - load 19 // asset_id + load 20 // asset_id itxn_field XferAsset // Fee: 0 pushint 0 @@ -418,45 +420,45 @@ retsub // Function with return value // func sum(x: int, y: int) int: __func__sum: -store 20 // y -store 21 // x -// int result = x + y [slot 22] -load 21 // x -load 20 // y +store 21 // y +store 22 // x +// int result = x + y [slot 23] +load 22 // x +load 21 // y + -store 22 // result +store 23 // result // return result -load 22 // result +load 23 // result retsub // func teal_sum(x: int, y: int) int: __func__teal_sum: -store 23 // y -store 24 // x +store 24 // y +store 25 // x // push(x) -load 24 // x +load 25 // x // push // push(y) -load 23 // y +load 24 // y // push pop pop + -// int result = pop() [slot 25] +// int result = pop() [slot 26] // pop -store 25 // result +store 26 // result // return result -load 25 // result +load 26 // result retsub // Function with multiple return values // func foo(x: int, y: int) int, int: __func__foo: -store 26 // y -store 27 // x +store 27 // y +store 28 // x // return x, y -load 26 // y -load 27 // x +load 27 // y +load 28 // x retsub diff --git a/tests/everything.tl b/tests/everything.tl index 38d6a6c..dbfd6b9 100644 --- a/tests/everything.tl +++ b/tests/everything.tl @@ -16,11 +16,12 @@ end # Consts const int FOO = 100 const bytes BAR = "bar" +const bytes BAZ = 0xDEADBEEF # Assignments int a = FOO bytes b = BAR - +bytes c = BAZ # Structs Item item1 = bzero(46) From c01e2953467aa214dffda50dd5f32d7ca988ccdf Mon Sep 17 00:00:00 2001 From: Ben Guidarelli Date: Sun, 29 Jan 2023 10:41:19 -0500 Subject: [PATCH 3/6] adding address literal to consts --- tealish/nodes.py | 33 +++++- tealish/tealish_expressions.tx | 5 +- tests/everything.teal | 187 +++++++++++++++++---------------- tests/everything.tl | 2 + 4 files changed, 131 insertions(+), 96 deletions(-) diff --git a/tealish/nodes.py b/tealish/nodes.py index 00d0f5a..dd0738c 100644 --- a/tealish/nodes.py +++ b/tealish/nodes.py @@ -24,6 +24,7 @@ LITERAL_INT = r"[0-9]+" LITERAL_BYTE_STRING = r'"(.+)"' LITERAL_BYTE_HEX = r"0x([a-zA-Z0-9]+)" +LITERAL_BYTE_ADDR = r"([A-Z2-7]+)" VARIABLE_NAME = r"[a-z_][a-zA-Z0-9_]*" if TYPE_CHECKING: @@ -141,7 +142,12 @@ class Literal(Expression): @classmethod def parse(cls, line: str, parent: Node, compiler: "TealishCompiler") -> Node: - matchable: List[Type[Expression]] = [LiteralInt, LiteralBytes, LiteralHex] + matchable: List[Type[Expression]] = [ + LiteralAddr, + LiteralHex, + LiteralInt, + LiteralBytes, + ] for expr in matchable: if expr.match(line): return expr(line, parent, compiler) @@ -176,6 +182,20 @@ def _tealish(self) -> str: return f"{self.value}" +class LiteralAddr(Literal): + pattern = rf"addr\((?P{LITERAL_BYTE_ADDR})\)$" + value: str + + def write_teal(self, writer: "TealWriter") -> None: + writer.write(self, f"addr {self.value}") + + def type(self) -> AVMType: + return AVMType.bytes + + def _tealish(self) -> str: + return f"addr({self.value})" + + class LiteralHex(Literal): pattern = rf"(?P{LITERAL_BYTE_HEX})$" value: str @@ -394,7 +414,16 @@ class Const(LineStatement): def process(self) -> None: scope = self.get_current_scope() - scope.declare_const(self.name, (self.type, self.expression.value)) + if isinstance(self.expression, LiteralAddr): + # requires post processing + from algosdk.encoding import decode_address + + scope.declare_const( + self.name, + (self.type, f"0x{decode_address(self.expression.value).hex()}"), + ) + else: + scope.declare_const(self.name, (self.type, self.expression.value)) def write_teal(self, writer: "TealWriter") -> None: pass diff --git a/tealish/tealish_expressions.tx b/tealish/tealish_expressions.tx index c80a82e..4010969 100644 --- a/tealish/tealish_expressions.tx +++ b/tealish/tealish_expressions.tx @@ -34,6 +34,7 @@ Name: (/([a-z][A-Za-z_0-9]*)/ | /_/); GroupIndex: NegativeGroupIndex | PositiveGroupIndex | Expression; NegativeGroupIndex: '-' index=INT; PositiveGroupIndex: '+' index=INT; -HexBytes: value=/0x([a-zA-Z0-9]+)/; Integer: value=/[0-9_]+/; -Bytes: value=STRING | HexBytes; +HexBytes: value=/0x([a-zA-Z0-9]+)/; +AddrBytes: value='addr('/([A-Z2-7]+)/ ')'; +Bytes: value=STRING | HexBytes | AddrBytes; diff --git a/tests/everything.teal b/tests/everything.teal index 56fc35e..48389fb 100644 --- a/tests/everything.teal +++ b/tests/everything.teal @@ -20,53 +20,56 @@ store 1 // b // bytes c = BAZ [slot 2] pushbytes 0xDEADBEEF // BAZ store 2 // c +// bytes d = ADDR [slot 3] +pushbytes 0x8a14b874e4adc0e05b12b696681706b55dc4f9680421fd663459f3c54bad8bc4 // ADDR +store 3 // d // Structs -// Item item1 = bzero(46) [slot 3] +// Item item1 = bzero(46) [slot 4] pushint 46 bzero -store 3 // item1 -// item1.id = 123 [slot 3] -load 3 // item1 +store 4 // item1 +// item1.id = 123 [slot 4] +load 4 // item1 pushint 123 itob replace 0 // item1.id -store 3 // item1 -// item1.name = "xyz" [slot 3] -load 3 // item1 +store 4 // item1 +// item1.name = "xyz" [slot 4] +load 4 // item1 pushbytes "xyz" replace 16 // item1.name -store 3 // item1 +store 4 // item1 // assert(item1.id > 0) -load 3 // item1 +load 4 // item1 pushint 0 extract_uint64 // id pushint 0 > assert // log(item1.name) -load 3 // item1 +load 4 // item1 extract 16 10 // name log // Delcaration without assignment -// int balance [slot 4] -// int exists [slot 5] +// int balance [slot 5] +// int exists [slot 6] // Multiple assignment // Opcode with immediate arg // exists, balance = asset_holding_get(AssetBalance, 0, 5) pushint 0 pushint 5 asset_holding_get AssetBalance -store 5 // exists -store 4 // balance +store 6 // exists +store 5 // balance // Use of _ to ignore a return value // _, balance = asset_holding_get(AssetBalance, 1, 5) pushint 1 pushint 5 asset_holding_get AssetBalance pop // discarding value for _ -store 4 // balance +store 5 // balance // if FOO > 1: @@ -118,20 +121,20 @@ store 4 // balance // Boxes -// box box1 = CreateBox("a") [slot 6] +// box box1 = CreateBox("a") [slot 7] pushbytes "a" dup pushint 26 box_create assert // assert created -store 6 // box1 +store 7 // box1 // box1.name = "xyz" [box] -load 6 // box key box1 +load 7 // box key box1 pushint 16 // offset pushbytes "xyz" box_replace // box1.name // assert(box1.id) -load 6 // box key box1 +load 7 // box key box1 pushint 0 // offset pushint 8 // size box_extract // box1.id @@ -153,14 +156,14 @@ b fail // else // block main main: - // int amount = sum(2, 3) [slot 7] + // int amount = sum(2, 3) [slot 8] pushint 2 pushint 3 callsub __func__sum - store 7 // amount + store 8 // amount // transfer(0, amount, Gtxn[-1].Sender, Txn.Accounts[1]) pushint 0 - load 7 // amount + load 8 // amount txn GroupIndex pushint 1 - @@ -168,36 +171,36 @@ main: txna Accounts 1 callsub __func__transfer - // int sum = teal_sum(2, 3) [slot 8] + // int sum = teal_sum(2, 3) [slot 9] pushint 2 pushint 3 callsub __func__teal_sum - store 8 // sum + store 9 // sum // assert(amount == sum) - load 7 // amount - load 8 // sum + load 8 // amount + load 9 // sum == assert - // int z = add_amount(5) [slot 9] + // int z = add_amount(5) [slot 10] pushint 5 callsub main__func__add_amount - store 9 // z + store 10 // z - // int i = 0 [slot 10] + // int i = 0 [slot 11] pushint 0 - store 10 // i + store 11 // i // while i < z: l3_while: - load 10 // i - load 9 // z + load 11 // i + load 10 // z < bz l3_end // i = i + 1 - load 10 // i + load 11 // i pushint 1 + - store 10 // i + store 11 // i b l3_while l3_end: // end @@ -209,10 +212,10 @@ main: == bnz l4_end // i = i + 1 - load 10 // i + load 11 // i pushint 1 + - store 10 // i + store 11 // i pushint 1 + dup @@ -222,60 +225,60 @@ main: // for x in 1:10: pushint 1 - store 11 // x + store 12 // x l5_for: - load 11 // x + load 12 // x pushint 10 == bnz l5_end // log(itob(x)) - load 11 // x + load 12 // x itob log - load 11 // x + load 12 // x pushint 1 + - store 11 // x + store 12 // x b l5_for l5_end: // end - // int first = 1 [slot 11] + // int first = 1 [slot 12] pushint 1 - store 11 // first - // int last = 5 + 5 [slot 12] + store 12 // first + // int last = 5 + 5 [slot 13] pushint 5 pushint 5 + - store 12 // last + store 13 // last // For loop with variables // for x in first:last: - load 11 // first - store 13 // x + load 12 // first + store 14 // x l6_for: - load 13 // x - load 12 // last + load 14 // x + load 13 // last == bnz l6_end // log(itob(x)) - load 13 // x + load 14 // x itob log - load 13 // x + load 14 // x pushint 1 + - store 13 // x + store 14 // x b l6_for l6_end: // end // Function with multiple return values - // int fx [slot 13] - // int fy [slot 14] + // int fx [slot 14] + // int fy [slot 15] // fx, fy = foo(1, 2) pushint 1 pushint 2 callsub __func__foo - store 13 // fx - store 14 // fy + store 14 // fx + store 15 // fy // exit(1) pushint 1 @@ -284,14 +287,14 @@ main: // Locally scoped function using variable from parent scope // func add_amount(x: int) int: main__func__add_amount: - store 15 // x - // int result = amount + x [slot 16] - load 7 // amount - load 15 // x + store 16 // x + // int result = amount + x [slot 17] + load 8 // amount + load 16 // x + - store 16 // result + store 17 // result // return result - load 16 // result + load 17 // result retsub @@ -359,12 +362,12 @@ retsub // Function with args but no return value // func transfer(asset_id: int, amount: int, sender: bytes, receiver: bytes): __func__transfer: -store 17 // receiver -store 18 // sender -store 19 // amount -store 20 // asset_id +store 18 // receiver +store 19 // sender +store 20 // amount +store 21 // asset_id // if asset_id == 0: - load 20 // asset_id + load 21 // asset_id pushint 0 == bz l8_else @@ -375,13 +378,13 @@ store 20 // asset_id pushint 1 // Pay itxn_field TypeEnum // Sender: sender - load 18 // sender + load 19 // sender itxn_field Sender // Receiver: receiver - load 17 // receiver + load 18 // receiver itxn_field Receiver // Amount: amount - load 19 // amount + load 20 // amount itxn_field Amount // Fee: 0 pushint 0 @@ -397,16 +400,16 @@ store 20 // asset_id pushint 4 // Axfer itxn_field TypeEnum // Sender: sender - load 18 // sender + load 19 // sender itxn_field Sender // AssetReceiver: receiver - load 17 // receiver + load 18 // receiver itxn_field AssetReceiver // AssetAmount: amount - load 19 // amount + load 20 // amount itxn_field AssetAmount // XferAsset: asset_id - load 20 // asset_id + load 21 // asset_id itxn_field XferAsset // Fee: 0 pushint 0 @@ -420,45 +423,45 @@ retsub // Function with return value // func sum(x: int, y: int) int: __func__sum: -store 21 // y -store 22 // x -// int result = x + y [slot 23] -load 22 // x -load 21 // y +store 22 // y +store 23 // x +// int result = x + y [slot 24] +load 23 // x +load 22 // y + -store 23 // result +store 24 // result // return result -load 23 // result +load 24 // result retsub // func teal_sum(x: int, y: int) int: __func__teal_sum: -store 24 // y -store 25 // x +store 25 // y +store 26 // x // push(x) -load 25 // x +load 26 // x // push // push(y) -load 24 // y +load 25 // y // push pop pop + -// int result = pop() [slot 26] +// int result = pop() [slot 27] // pop -store 26 // result +store 27 // result // return result -load 26 // result +load 27 // result retsub // Function with multiple return values // func foo(x: int, y: int) int, int: __func__foo: -store 27 // y -store 28 // x +store 28 // y +store 29 // x // return x, y -load 27 // y -load 28 // x +load 28 // y +load 29 // x retsub diff --git a/tests/everything.tl b/tests/everything.tl index dbfd6b9..baaeb77 100644 --- a/tests/everything.tl +++ b/tests/everything.tl @@ -17,11 +17,13 @@ end const int FOO = 100 const bytes BAR = "bar" const bytes BAZ = 0xDEADBEEF +const bytes ADDR = addr(RIKLQ5HEVXAOAWYSW2LGQFYGWVO4J6LIAQQ72ZRULHZ4KS5NRPCCKYPCUU) # Assignments int a = FOO bytes b = BAR bytes c = BAZ +bytes d = ADDR # Structs Item item1 = bzero(46) From d5c6628b359e228fc3908fb3dcf1d2243267acf3 Mon Sep 17 00:00:00 2001 From: Ben Guidarelli Date: Sun, 29 Jan 2023 11:06:37 -0500 Subject: [PATCH 4/6] refactor const def to allow Literal nodes --- tealish/base.py | 6 +++--- tealish/expression_nodes.py | 17 +++++++++++------ tealish/nodes.py | 11 +---------- tealish/scope.py | 8 ++++---- tests/everything.teal | 12 ++++++------ 5 files changed, 25 insertions(+), 29 deletions(-) diff --git a/tealish/base.py b/tealish/base.py index 1e11f28..4e60c56 100644 --- a/tealish/base.py +++ b/tealish/base.py @@ -7,7 +7,7 @@ if TYPE_CHECKING: from . import TealWriter - from .nodes import Block, Node, Func + from .nodes import Block, Node, Func, Literal lang_spec = get_active_langspec() @@ -154,10 +154,10 @@ def lookup_func(self, name: str) -> "Func": def lookup_var(self, name: str) -> Any: return self.get_scope().lookup_var(name) - def lookup_const(self, name: str) -> Tuple["AVMType", ConstValue]: + def lookup_const(self, name: str) -> Tuple["AVMType", Union["Literal", ConstValue]]: return self.get_scope().lookup_const(name) - def lookup_avm_constant(self, name: str) -> Tuple["AVMType", Any]: + def lookup_avm_constant(self, name: str) -> Tuple["AVMType", ConstValue]: return lang_spec.lookup_avm_constant(name) # TODO: these attributes are only available on Node and other children types diff --git a/tealish/expression_nodes.py b/tealish/expression_nodes.py index 22f2e92..ad95f38 100644 --- a/tealish/expression_nodes.py +++ b/tealish/expression_nodes.py @@ -4,11 +4,12 @@ from .errors import CompileError from .tealish_builtins import AVMType, get_struct from .langspec import Op, type_lookup +from .scope import ConstValue if TYPE_CHECKING: from . import TealWriter - from .nodes import Node, Func, GenericExpression + from .nodes import Node, Func, GenericExpression, Literal class Integer(BaseNode): @@ -68,7 +69,8 @@ def __init__(self, name: str, parent: Optional[BaseNode] = None) -> None: self.parent = parent def process(self) -> None: - type, value = None, None + type: AVMType = AVMType.none + value: Union[ConstValue, "Literal"] = None # type: ignore try: # user defined const type, value = self.lookup_const(self.name) @@ -87,10 +89,13 @@ def process(self) -> None: self.value = value def write_teal(self, writer: "TealWriter") -> None: - if self.type == AVMType.int: - writer.write(self, f"pushint {self.value} // {self.name}") # type: ignore - elif self.type == AVMType.bytes: - writer.write(self, f"pushbytes {self.value} // {self.name}") # type: ignore + if isinstance(self.value, ConstValue): + if self.type == AVMType.int: + writer.write(self, f"pushint {self.value} // {self.name}") # type: ignore + elif self.type == AVMType.bytes: + writer.write(self, f"pushbytes {self.value} // {self.name}") # type: ignore + else: + self.value.write_teal(writer) def _tealish(self) -> str: return f"{self.name}" diff --git a/tealish/nodes.py b/tealish/nodes.py index dd0738c..b45c095 100644 --- a/tealish/nodes.py +++ b/tealish/nodes.py @@ -414,16 +414,7 @@ class Const(LineStatement): def process(self) -> None: scope = self.get_current_scope() - if isinstance(self.expression, LiteralAddr): - # requires post processing - from algosdk.encoding import decode_address - - scope.declare_const( - self.name, - (self.type, f"0x{decode_address(self.expression.value).hex()}"), - ) - else: - scope.declare_const(self.name, (self.type, self.expression.value)) + scope.declare_const(self.name, (self.type, self.expression)) def write_teal(self, writer: "TealWriter") -> None: pass diff --git a/tealish/scope.py b/tealish/scope.py index a3619ca..ffd03ff 100644 --- a/tealish/scope.py +++ b/tealish/scope.py @@ -3,7 +3,7 @@ if TYPE_CHECKING: from .tealish_builtins import AVMType - from .nodes import Func, Block + from .nodes import Func, Block, Literal VarType = Union["AVMType", Tuple[str, str]] @@ -25,7 +25,7 @@ def __init__( slot_range if slot_range is not None else (0, 200) ) - self.consts: Dict[str, Tuple["AVMType", ConstValue]] = {} + self.consts: Dict[str, Tuple["AVMType", Union[ConstValue, "Literal"]]] = {} self.blocks: Dict[str, "Block"] = {} self.functions: Dict[str, "Func"] = {} @@ -63,11 +63,11 @@ def delete_var(self, name: str) -> None: del self.slots[name] def declare_const( - self, name: str, const_data: Tuple["AVMType", ConstValue] + self, name: str, const_data: Tuple["AVMType", Union["Literal", ConstValue]] ) -> None: self.consts[name] = const_data - def lookup_const(self, name: str) -> Tuple["AVMType", ConstValue]: + def lookup_const(self, name: str) -> Tuple["AVMType", Union["Literal", ConstValue]]: if name not in self.consts: raise KeyError(f'Const "{name}" not declared in current scope') return self.consts[name] diff --git a/tests/everything.teal b/tests/everything.teal index 48389fb..9119a02 100644 --- a/tests/everything.teal +++ b/tests/everything.teal @@ -12,16 +12,16 @@ // Assignments // int a = FOO [slot 0] -pushint 100 // FOO +pushint 100 store 0 // a // bytes b = BAR [slot 1] -pushbytes "bar" // BAR +pushbytes "bar" store 1 // b // bytes c = BAZ [slot 2] -pushbytes 0xDEADBEEF // BAZ +pushbytes 0xDEADBEEF store 2 // c // bytes d = ADDR [slot 3] -pushbytes 0x8a14b874e4adc0e05b12b696681706b55dc4f9680421fd663459f3c54bad8bc4 // ADDR +addr RIKLQ5HEVXAOAWYSW2LGQFYGWVO4J6LIAQQ72ZRULHZ4KS5NRPCCKYPCUU store 3 // d // Structs @@ -73,13 +73,13 @@ store 5 // balance // if FOO > 1: - pushint 100 // FOO + pushint 100 pushint 1 > bz l0_else // then: // log(BAR) - pushbytes "bar" // BAR + pushbytes "bar" log b l0_end l0_else: From 15a92083916463e815269e39129ac8113e67fe92 Mon Sep 17 00:00:00 2001 From: Ben Guidarelli Date: Sun, 29 Jan 2023 11:13:53 -0500 Subject: [PATCH 5/6] improve typing for python3.9 --- tealish/expression_nodes.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/tealish/expression_nodes.py b/tealish/expression_nodes.py index ad95f38..8bf26a4 100644 --- a/tealish/expression_nodes.py +++ b/tealish/expression_nodes.py @@ -67,10 +67,11 @@ def __init__(self, name: str, parent: Optional[BaseNode] = None) -> None: self.name = name self.type: AVMType = AVMType.none self.parent = parent + self.value: Union[ConstValue, "Literal"] def process(self) -> None: type: AVMType = AVMType.none - value: Union[ConstValue, "Literal"] = None # type: ignore + value: Union[ConstValue, "Literal"] = 0 try: # user defined const type, value = self.lookup_const(self.name) @@ -89,11 +90,12 @@ def process(self) -> None: self.value = value def write_teal(self, writer: "TealWriter") -> None: - if isinstance(self.value, ConstValue): - if self.type == AVMType.int: - writer.write(self, f"pushint {self.value} // {self.name}") # type: ignore - elif self.type == AVMType.bytes: - writer.write(self, f"pushbytes {self.value} // {self.name}") # type: ignore + if isinstance(self.value, str) or isinstance(self.value, bytes): + assert self.type == AVMType.bytes + writer.write(self, f"pushbytes {self.value} // {self.name}") # type: ignore + elif isinstance(self.value, int): + assert self.type == AVMType.int + writer.write(self, f"pushint {self.value} // {self.name}") else: self.value.write_teal(writer) From c4facf38bc4ebd9287923b3841de00e3eb8c9555 Mon Sep 17 00:00:00 2001 From: Ben Guidarelli Date: Mon, 30 Jan 2023 05:50:04 -0500 Subject: [PATCH 6/6] fix hex alphabet --- tealish/nodes.py | 2 +- tealish/tealish_expressions.tx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tealish/nodes.py b/tealish/nodes.py index b45c095..8973b72 100644 --- a/tealish/nodes.py +++ b/tealish/nodes.py @@ -23,7 +23,7 @@ LITERAL_INT = r"[0-9]+" LITERAL_BYTE_STRING = r'"(.+)"' -LITERAL_BYTE_HEX = r"0x([a-zA-Z0-9]+)" +LITERAL_BYTE_HEX = r"0x([a-fA-F0-9]+)" LITERAL_BYTE_ADDR = r"([A-Z2-7]+)" VARIABLE_NAME = r"[a-z_][a-zA-Z0-9_]*" diff --git a/tealish/tealish_expressions.tx b/tealish/tealish_expressions.tx index 4010969..3af49d0 100644 --- a/tealish/tealish_expressions.tx +++ b/tealish/tealish_expressions.tx @@ -35,6 +35,6 @@ GroupIndex: NegativeGroupIndex | PositiveGroupIndex | Expression; NegativeGroupIndex: '-' index=INT; PositiveGroupIndex: '+' index=INT; Integer: value=/[0-9_]+/; -HexBytes: value=/0x([a-zA-Z0-9]+)/; +HexBytes: value=/0x([a-fA-F0-9]+)/; AddrBytes: value='addr('/([A-Z2-7]+)/ ')'; Bytes: value=STRING | HexBytes | AddrBytes;