Skip to content

Commit

Permalink
feat: add binary integer literal
Browse files Browse the repository at this point in the history
  • Loading branch information
Gusarich committed Nov 29, 2023
1 parent 53d68b3 commit 7165d0f
Show file tree
Hide file tree
Showing 17 changed files with 1,087 additions and 2 deletions.
5 changes: 4 additions & 1 deletion src/grammar/grammar.ohm
Original file line number Diff line number Diff line change
Expand Up @@ -173,10 +173,13 @@ Tact {
// Integer Literal
// hexDigit defined in Ohm's built-in rules (otherwise: hexDigit = "0".."9" | "a".."f" | "A".."F")
// digit defined in Ohm's built-in rules (otherwise: digit = "0".."9")
integerLiteral = integerLiteralHex | integerLiteralDec // Order is important
integerLiteral = integerLiteralHex | integerLiteralBin | integerLiteralDec // Order is important
integerLiteralDec = digit+
integerLiteralHex = "0x" hexDigit+
| "0X" hexDigit+
integerLiteralBin = "0b" binDigit+
| "0B" binDigit+
binDigit = "0" | "1"

// Letters
letterAsciiLC = "a".."z"
Expand Down
2 changes: 2 additions & 0 deletions src/grammar/grammar.ohm-bundle.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,8 @@ export interface TactActionDict<T> extends ActionDict<T> {
integerLiteral?: (this: NonterminalNode, arg0: NonterminalNode) => T;
integerLiteralDec?: (this: NonterminalNode, arg0: IterationNode) => T;
integerLiteralHex?: (this: NonterminalNode, arg0: TerminalNode, arg1: IterationNode) => T;
integerLiteralBin?: (this: NonterminalNode, arg0: TerminalNode, arg1: IterationNode) => T;
binDigit?: (this: NonterminalNode, arg0: TerminalNode) => T;
letterAsciiLC?: (this: NonterminalNode, arg0: TerminalNode) => T;
letterAsciiUC?: (this: NonterminalNode, arg0: TerminalNode) => T;
letterAscii?: (this: NonterminalNode, arg0: NonterminalNode) => T;
Expand Down
2 changes: 1 addition & 1 deletion src/grammar/grammar.ohm-bundle.js

Large diffs are not rendered by default.

28 changes: 28 additions & 0 deletions src/test/feature-integer-literals.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { toNano } from 'ton-core';
import { ContractSystem } from '@tact-lang/emulator';
import { __DANGER_resetNodeId } from '../grammar/ast';
import { IntegerLiteralsTester } from './features/output/integer-literals_IntegerLiteralsTester';

describe('feature-integer-literals', () => {
beforeEach(() => {
__DANGER_resetNodeId();
});
it('should implement integer literals correctly', async () => {
// Init
let system = await ContractSystem.create();
let treasure = system.treasure('treasure');
let contract = system.open(await IntegerLiteralsTester.fromInit());
await contract.send(treasure, { value: toNano('10') }, null);
await system.run();

// Check methods
expect(await contract.getDecLiteral1()).toEqual(123n);
expect(await contract.getDecLiteral2()).toEqual(-123n);

expect(await contract.getHexLiteral1()).toEqual(0x123n);
expect(await contract.getHexLiteral2()).toEqual(-0x123n);

expect(await contract.getBinLiteral1()).toEqual(0b101010n);
expect(await contract.getBinLiteral2()).toEqual(-0b101010n);
});
});
34 changes: 34 additions & 0 deletions src/test/features/integer-literals.tact
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
contract IntegerLiteralsTester {

init() {

}

receive() {
// Deploy
}

get fun decLiteral1(): Int {
return 123;
}

get fun decLiteral2(): Int {
return -123;
}

get fun hexLiteral1(): Int {
return 0x123;
}

get fun hexLiteral2(): Int {
return -0x123;
}

get fun binLiteral1(): Int {
return 0b101010;
}

get fun binLiteral2(): Int {
return -0b101010;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"name":"IntegerLiteralsTester","types":[{"name":"StateInit","header":null,"fields":[{"name":"code","type":{"kind":"simple","type":"cell","optional":false}},{"name":"data","type":{"kind":"simple","type":"cell","optional":false}}]},{"name":"Context","header":null,"fields":[{"name":"bounced","type":{"kind":"simple","type":"bool","optional":false}},{"name":"sender","type":{"kind":"simple","type":"address","optional":false}},{"name":"value","type":{"kind":"simple","type":"int","optional":false,"format":257}},{"name":"raw","type":{"kind":"simple","type":"slice","optional":false}}]},{"name":"SendParameters","header":null,"fields":[{"name":"bounce","type":{"kind":"simple","type":"bool","optional":false}},{"name":"to","type":{"kind":"simple","type":"address","optional":false}},{"name":"value","type":{"kind":"simple","type":"int","optional":false,"format":257}},{"name":"mode","type":{"kind":"simple","type":"int","optional":false,"format":257}},{"name":"body","type":{"kind":"simple","type":"cell","optional":true}},{"name":"code","type":{"kind":"simple","type":"cell","optional":true}},{"name":"data","type":{"kind":"simple","type":"cell","optional":true}}]}],"receivers":[{"receiver":"internal","message":{"kind":"empty"}}],"getters":[{"name":"decLiteral1","arguments":[],"returnType":{"kind":"simple","type":"int","optional":false,"format":257}},{"name":"decLiteral2","arguments":[],"returnType":{"kind":"simple","type":"int","optional":false,"format":257}},{"name":"hexLiteral1","arguments":[],"returnType":{"kind":"simple","type":"int","optional":false,"format":257}},{"name":"hexLiteral2","arguments":[],"returnType":{"kind":"simple","type":"int","optional":false,"format":257}},{"name":"binLiteral1","arguments":[],"returnType":{"kind":"simple","type":"int","optional":false,"format":257}},{"name":"binLiteral2","arguments":[],"returnType":{"kind":"simple","type":"int","optional":false,"format":257}}],"errors":{"2":{"message":"Stack undeflow"},"3":{"message":"Stack overflow"},"4":{"message":"Integer overflow"},"5":{"message":"Integer out of expected range"},"6":{"message":"Invalid opcode"},"7":{"message":"Type check error"},"8":{"message":"Cell overflow"},"9":{"message":"Cell underflow"},"10":{"message":"Dictionary error"},"13":{"message":"Out of gas error"},"32":{"message":"Method ID not found"},"34":{"message":"Action is invalid or not supported"},"37":{"message":"Not enough TON"},"38":{"message":"Not enough extra-currencies"},"128":{"message":"Null reference exception"},"129":{"message":"Invalid serialization prefix"},"130":{"message":"Invalid incoming message"},"131":{"message":"Constraints error"},"132":{"message":"Access denied"},"133":{"message":"Contract stopped"},"134":{"message":"Invalid argument"},"135":{"message":"Code of a contract was not found"},"136":{"message":"Invalid address"},"137":{"message":"Masterchain support is not enabled for this contract"}},"interfaces":["org.ton.introspection.v0","org.ton.abi.ipfs.v0","org.ton.deploy.lazy.v0","org.ton.debug.v0","org.ton.chain.workchain.v0"]}
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
#pragma version =0.4.3;
#pragma allow-post-modification;
#pragma compute-asm-ltr;

#include "integer-literals_IntegerLiteralsTester.headers.fc";
#include "integer-literals_IntegerLiteralsTester.stdlib.fc";
#include "integer-literals_IntegerLiteralsTester.storage.fc";

;;
;; Contract IntegerLiteralsTester functions
;;

tuple $IntegerLiteralsTester$_contract_init() impure inline_ref {
tuple $self = null();
return $self;
}

(tuple, int) $IntegerLiteralsTester$_fun_decLiteral1(tuple $self) impure inline_ref {
var ($self) = $self;
return ($self, 123);
}

(tuple, int) $IntegerLiteralsTester$_fun_decLiteral2(tuple $self) impure inline_ref {
var ($self) = $self;
return ($self, (- 123));
}

(tuple, int) $IntegerLiteralsTester$_fun_hexLiteral1(tuple $self) impure inline_ref {
var ($self) = $self;
return ($self, 291);
}

(tuple, int) $IntegerLiteralsTester$_fun_hexLiteral2(tuple $self) impure inline_ref {
var ($self) = $self;
return ($self, (- 291));
}

(tuple, int) $IntegerLiteralsTester$_fun_binLiteral1(tuple $self) impure inline_ref {
var ($self) = $self;
return ($self, 42);
}

(tuple, int) $IntegerLiteralsTester$_fun_binLiteral2(tuple $self) impure inline_ref {
var ($self) = $self;
return ($self, (- 42));
}

;;
;; Receivers of a Contract IntegerLiteralsTester
;;

((tuple), ()) %$IntegerLiteralsTester$_internal_empty(tuple $self) impure inline {
var $self = $self;
return ($self, ());
}

;;
;; Get methods of a Contract IntegerLiteralsTester
;;

_ %decLiteral1() method_id(102042) {
var self = $IntegerLiteralsTester$_contract_load();
var res = self~$IntegerLiteralsTester$_fun_decLiteral1();
return res;
}

_ %decLiteral2() method_id(114425) {
var self = $IntegerLiteralsTester$_contract_load();
var res = self~$IntegerLiteralsTester$_fun_decLiteral2();
return res;
}

_ %hexLiteral1() method_id(76310) {
var self = $IntegerLiteralsTester$_contract_load();
var res = self~$IntegerLiteralsTester$_fun_hexLiteral1();
return res;
}

_ %hexLiteral2() method_id(72309) {
var self = $IntegerLiteralsTester$_contract_load();
var res = self~$IntegerLiteralsTester$_fun_hexLiteral2();
return res;
}

_ %binLiteral1() method_id(116259) {
var self = $IntegerLiteralsTester$_contract_load();
var res = self~$IntegerLiteralsTester$_fun_binLiteral1();
return res;
}

_ %binLiteral2() method_id(128576) {
var self = $IntegerLiteralsTester$_contract_load();
var res = self~$IntegerLiteralsTester$_fun_binLiteral2();
return res;
}

_ supported_interfaces() method_id {
return (
"org.ton.introspection.v0"H >> 128,
"org.ton.abi.ipfs.v0"H >> 128,
"org.ton.deploy.lazy.v0"H >> 128,
"org.ton.debug.v0"H >> 128,
"org.ton.chain.workchain.v0"H >> 128
);
}

_ get_abi_ipfs() method_id {
return "ipfs://QmVmyo6powuj49BDo3NwkUwouAXS9zFRRcZ6drqt3LUcot";
}

_ lazy_deployment_completed() method_id {
return get_data().begin_parse().load_int(1);
}

;;
;; Routing of a Contract IntegerLiteralsTester
;;

(tuple, int) $IntegerLiteralsTester$_contract_router_internal(tuple self, int msg_bounced, slice in_msg) impure inline_ref {
;; Handle bounced messages
if (msg_bounced) {
return (self, true);
}

;; Parse incoming message
int op = 0;
if (slice_bits(in_msg) >= 32) {
op = in_msg.preload_uint(32);
}


;; Receive empty message
if ((op == 0) & (slice_bits(in_msg) <= 32)) {
self~%$IntegerLiteralsTester$_internal_empty();
return (self, true);
}

return (self, false);
}

() recv_internal(int msg_value, cell in_msg_cell, slice in_msg) impure {

;; Context
var cs = in_msg_cell.begin_parse();
var msg_flags = cs~load_uint(4);
var msg_bounced = -(msg_flags & 1);
slice msg_sender_addr = __tact_verify_address(cs~load_msg_addr());
__tact_context = (msg_bounced, msg_sender_addr, msg_value, cs);
__tact_context_sender = msg_sender_addr;

;; Load contract data
var self = $IntegerLiteralsTester$_contract_load();

;; Handle operation
int handled = self~$IntegerLiteralsTester$_contract_router_internal(msg_bounced, in_msg);

;; Throw if not handled
throw_unless(130, handled);

;; Persist state
$IntegerLiteralsTester$_contract_store(self);
}
Loading

0 comments on commit 7165d0f

Please sign in to comment.