GCULpy adalah subset Python yang diketik secara statis dan ketat, yang dirancang agar aman, mudah dibaca, dan dapat diaudit. Desainnya sengaja membatasi fitur dinamis tertentu dari Python untuk mencegah kerentanan smart contract yang umum dan memastikan bahwa perilaku kontrak selalu dapat diprediksi.
Halaman ini memberikan referensi untuk spesifikasi bahasa GCULpy, yang mencakup konsep inti dan siklus proses kontrak di jaringan Universal Ledger.
Konsep inti
Kontrak berikut menentukan contoh token ERC20 di GCULpy:
import gcul
class ERC20Token(gcul.Contract):
"""Sample ERC20 implementation for the Universal Ledger."""
symbol: str
total_supply: int
balance: gcul.AccountField[int]
def __init__(self, symbol: str):
self.symbol = symbol
self.total_supply = 0
def mint(self, beneficiary: gcul.Account, value: int) -> int:
"""Mints tokens to the given beneficiary."""
assert self.is_owner(gcul.sender), "Only the owner can mint"
assert value >= 0, "Mint amount must be non-negative"
self.total_supply += value
self.balance[beneficiary] += value
return value
def transfer(self, beneficiary: gcul.Account, value: int) -> int:
"""Transfers tokens from the sender to the given beneficiary."""
assert value >= 0, "Transfer amount must be non-negative"
assert (
value <= self.balance[gcul.sender]
), "Sender does not have enough balance"
self.balance[gcul.sender] -= value
self.balance[beneficiary] += value
return value
Kontrak GCULpy adalah class yang diwarisi dari gcul.Contract. Class ini
berisi kolom (menyimpan status) dan metode (logika pemrosesan yang
beroperasi pada kolom).
Kolom
Status dalam kontrak GCULpy disimpan dalam kolom. Semua kolom harus dideklarasikan dengan jenis statis di tingkat class. Ada dua jenis kolom:
Kolom kontrak menyimpan satu nilai yang disimpan bersama kontrak itu sendiri. Dalam contoh
ERC20Token,symbol: strdantotal_supply: intadalah kolom kontrak.Kolom akun menyimpan nilai terpisah untuk setiap akun yang berinteraksi dengan kontrak. Variabel ini dideklarasikan dengan
gcul.AccountField[T], denganTsebagai jenis nilai per akun. Dalam contohERC20Token,balance: gcul.AccountField[int]adalah kolom akun. Sebelum kontrak dapat menulis ke ruang penyimpanan yang dicadangkan untuk akun tersebut, izin penyimpanan harus secara eksplisit diberikan ke kontrak. Setelah data disimpan, hanya instance kontrak yang dapat mengubahnya—akun tidak dapat melakukannya.
Batasan Kolom memiliki batas penyimpanan berikut. Transaksi yang melebihi salah satu batas akan gagal.
- Semua kolom kontrak dari sebuah kontrak menggunakan satu entri penyimpanan, yang dapat menampung total sekitar 5 MiB data yang diserialisasi.
- Semua kolom akun yang disimpan kontrak untuk setiap akun individu dapat menampung maksimal 1 MiB data serial secara total.
Metode
Metode menentukan logika kontrak yang dapat dieksekusi. Fungsi ini berperilaku seperti metode Python dan dapat membaca atau mengubah kolom kontrak.
__init__: Konstruktor hanya dipanggil sekali saat kontrak pertama kali di-deploy. Setiap kolom kontrak harus diberi nilai di konstruktor. Konstruktor tidak melakukan inisialisasi kolom akun; nilai setiap akun dibuat saat akun tersebut memberikan izin penyimpanan.Metode pribadi: Metode yang diawali dengan garis bawah (misalnya,
_internal_logic) bersifat pribadi dan hanya dapat dipanggil oleh metode lain dalam kontrak yang sama. Penafsir Universal Ledger menerapkan batasan ini.Metode publik: Metode apa pun yang tidak diawali dengan garis bawah (
_) bersifat publik. Metode publik dapat dipanggil oleh pengguna mana pun denganROLE_CONTRACT_PARTICIPANTdengan mengirimkan transaksi InvokeContractMethod.
Batasan Metode publik dan semua metode @gcul.readonly tidak dapat menggunakan jenis yang dapat diubah dalam tanda tangannya, misalnya list atau dict. Sebagai gantinya, gunakan deklarasi jenis hanya baca seperti Sequence atau Mapping.
Batasan Selama eksekusi, metode dibatasi hingga batas atas penggunaan komputasi di seluruh jaringan. Melebihi batas ini akan menyebabkan kegagalan transaksi.
Siklus proses kontrak
Bagian berikut membahas operasi umum yang terlibat dalam siklus proses kontrak GCULpy.
Men-deploy kontrak
Pertama, kompilasi kode sumber GCULpy Anda menggunakan compiler gculpyc. Kemudian, pengguna dengan ROLE_CONTRACT_CREATOR dapat mengirimkan transaksi CreateContract untuk men-deploy bytecode yang telah dikompilasi ke jaringan Universal Ledger. Untuk mengetahui petunjuk mendetail, lihat tutorial Men-deploy kontrak yang dapat diprogram.
Transaksi tersebut akan terlihat seperti:
client_transaction {
sender_id: "OWNER_ACCOUNT_ID"
create_contract_transaction {
contract_bytes: "COMPILED_BYTECODE"
init_arguments {
key: "symbol"
value: { string_value: "US02079K1079" }
}
}
}
Saat jaringan memproses transaksi ini:
- Konstruktor, yaitu metode
__init__, dijalankan dengan argumen yang disediakan untuk membuat instance kontrak baru. - Pengirim transaksi menjadi pemilik kontrak.
- Instance kontrak disimpan secara permanen di ledger dan diberi ID kontrak unik yang ditampilkan sebagai bagian dari output transaksi.
Memberikan izin
Sebelum kontrak dapat menyimpan data di kolom akun atas nama akun, baik akun untuk pengguna maupun kontrak lain, izin penyimpanan harus diberikan ke kontrak yang menyimpan data. Ini adalah langkah keamanan yang penting.
Memberikan izin untuk akun pengguna
Pengguna dengan ROLE_CONTRACT_PARTICIPANT dapat mengirimkan transaksi GrantContractPermissions untuk ID kontrak tertentu:
client_transaction {
sender_id: "PARTICIPANT_ACCOUNT_ID"
grant_contract_permissions_transaction {
contract_id: "CONTRACT_ID"
permissions: CONTRACT_PERMISSION_STORAGE
}
}
Saat jaringan memproses transaksi ini:
- Jika kontrak tidak menentukan kolom akun, transaksi akan ditolak.
- Jika kontrak menentukan kolom akun, semuanya akan diisi dengan nilai default (misalnya,
contract.balance[gcul.sender] = 0). Nilai ini kemudian disimpan dalam status dunia sebagai bagian dari data akun.
Memberikan izin untuk kontrak delegasi
Pengguna dengan ROLE_CONTRACT_PARTICIPANT dapat mengirimkan transaksi
GrantContractPermissions
untuk mengizinkan satu kontrak menyimpan data atas nama kontrak lain
yang mereka miliki:
client_transaction {
sender_id: "OWNER_ACCOUNT_ID"
grant_contract_permissions_transaction {
contract_id: "TARGET_CONTRACT_ID"
delegate_contract_id: "DELEGATE_CONTRACT_ID"
permissions: CONTRACT_PERMISSION_STORAGE
}
}
Saat jaringan memproses transaksi ini:
- Pengirim transaksi, yaitu
sender_id, harus merupakan pemilik kontrak yang diidentifikasi olehdelegate_contract_id. - Kontrak tidak dapat memberikan izin penyimpanan kepada dirinya sendiri, sehingga
delegate_contract_idharus berbeda daricontract_id. - Izin penyimpanan diberikan secara eksklusif ke kontrak yang ditentukan dalam
delegate_contract_id, bukan pengirim transaksi. - Kolom akun yang ditentukan pada kontrak target,
contract_id, diinisialisasi untuk kontrak delegasi,delegate_contract_id, sehingga memungkinkan metode pada kontrak target mengakses kolom akun dengan aman yang dikunci olehgcul.callerataugcul.senderselama pemanggilan lintas kontrak.
Memanggil metode kontrak
Setelah kontrak di-deploy dan izin yang diperlukan diberikan, pengguna dapat
berinteraksi dengan kontrak tersebut dengan memanggil metode publiknya. Pengguna dengan
ROLE_CONTRACT_PARTICIPANT dapat mengirimkan transaksi
InvokeContractMethod
yang menentukan ID kontrak, nama metode, dan nilai argumen metode.
client_transaction {
sender_id: "PARTICIPANT_ACCOUNT_ID"
invoke_contract_method_transaction {
contract_id: "CONTRACT_ID"
method_name: "mint"
method_arguments {
key: "beneficiary"
value: { account_id: "BENEFICIARY_ID" }
}
method_arguments {
key: "value"
value: { int64_value: 10 }
}
}
}
Saat jaringan memproses transaksi ini:
- Instance kontrak yang terkait dengan
CONTRACT_IDyang diberikan akan diambil. - Metode
mint(beneficiary=Account("BENEFICIARY_ID"), value=10)dijalankan. ObjekAccountuntuk penerima manfaat dibuat dan divalidasi oleh runtime. Logika metode dapat mengasumsikan dengan aman bahwa ID yang diberikan valid dan merujuk ke akun yang ada di ledger. - Jika metode gagal karena alasan apa pun, transaksi akan gagal dan tidak ada pembaruan yang akan dilakukan pada status kontrak.
- Jika metode berhasil, status kontrak yang diperbarui akan dicatat dalam status dunia.
Spesifikasi bahasa
GCULpy dirancang untuk keamanan dan prediktabilitas, sehingga tidak mengizinkan beberapa fitur Python; fitur ini akan ditandai dengan label Restriction. Batasan ini dimaksudkan sebagai fitur bahasa permanen, yang diperkenalkan untuk membuat logika kontrak lebih mudah dibaca, diaudit, dan dianalisis secara statis, sehingga membatasi perilaku yang mengejutkan atau tidak aman.
Fitur lainnya ditandai dengan label Roadmap, fitur ini ada dalam roadmap implementasi, tetapi belum didukung oleh compiler gculpyc.
Jenis
GCULpy mendukung berbagai jenis variabel umum dengan penekanan kuat pada pengetikan statis.
Jenis nilai utama:
int,bool,str,Nonesudah didukung.- Roadmap
Decimal,bytes,Enumada dalam roadmap. - Pembatasan
floatdancomplextidak diizinkan. - Nilai Restriction
intadalah bilangan bulat 64-bit bertanda, dari -263 hingga 263 - 1. Literal bilangan bulat di luar rentang ini akan menghasilkan error waktu kompilasi, dan operasi yang hasilnya di luar rentang ini akan menghasilkan error runtime. - Nilai Restriction
strdapat memiliki panjang maksimal 1.000.000 karakter. Literal string yang lebih panjang akan menyebabkan error waktu kompilasi. Meneruskan string yang lebih panjang sebagai argumen metode, atau menghasilkan string yang lebih panjang sebagai hasil operasi, akan menyebabkan error runtime.
Jenis penampung:
listdandict:list[T]: Urutan yang dapat diubah. Mendukung pengindeksan, misalnyamy_list[0], dan metodeappend().dict[K, V]: Pemetaan yang dapat diubah. Mendukung pengindeksan, misalnyamy_dict[key], dan metodepop().
collections.abc.Sequencedancollections.abc.Mapping:collections.abc.Sequence[T]: Referensi hanya baca ke urutan. Mendukung pembacaan elemen berdasarkan indeks, misalnyamy_seq[0], tetapi elemen tidak dapat diubah atau dihapus.list[T]adalah subjenis dariSequence[T], sehingga Anda dapat meneruskan, menampilkan, atau menetapkan nilailist[T]atau literal daftar ke target yang diketik sebagaiSequence[T], tetapi Anda tidak dapat menetapkanSequence[T]kelist[T].collections.abc.Mapping[K, V]: Referensi hanya baca ke pemetaan. Mendukung pembacaan entri berdasarkan kunci, misalnyamy_map[key], tetapi entri tidak dapat diubah atau dihapus.dict[K, V]adalah subjenis dariMapping[K, V], sehingga Anda dapat meneruskan, menampilkan, atau menetapkan nilaidict[K, V]atau literal kamus ke target yang diketik sebagaiMapping[K, V], tetapi Anda tidak dapat menetapkanMapping[K, V]kedict[K, V].
- Roadmap
tuple,set,dataclassada dalam roadmap. - Batasan Jenis konkret harus ditentukan untuk nilai dalam
penampung, misalnya
dict[str, int]diizinkan, tetapidictataudict[str, Any]biasa tidak diizinkan. - Roadmap Pemotongan daftar, misalnya
my_list[1:3]. - Roadmap Metode lain, seperti
.get(),.keys(),.values(),.items(),.clear(), atau.extend().
Batasan Semua variabel—termasuk kolom kontrak dan akun, parameter fungsi, dan jenis nilai yang ditampilkan—harus ditentukan dan diketik secara statis. Jenisnya tidak dapat diubah saat runtime dan hanya jenis konkret yang didukung. Jenis tidak dapat digunakan sebagai nilai, misalnya tidak dapat disimpan dalam variabel atau diteruskan ke fungsi sebagai argumen. Mencoba menetapkan nilai ke kolom yang tidak dideklarasikan akan menghasilkan error waktu kompilasi.
Batasan Variabel lokal harus ditetapkan sebelum dibaca. Variabel lokal tidak memiliki nilai default, sehingga membacanya sebelum ditetapkan akan menghasilkan error runtime.
Class dan pewarisan
Anda hanya dapat menentukan class yang merupakan subclass langsung dari
gcul.Contract atau gcul.ContractInterface.
Aturan ketat ini mencegah kompleksitas pewarisan Python
penuh, yang dapat menimbulkan bug yang sulit ditemukan dan membuat kode sulit
dipahami. Demi keamanan, upaya untuk mengganti properti atau metode dari
class induk akan memunculkan error, sehingga memberikan perlindungan yang jelas terhadap perilaku
yang tidak terduga.
Roadmap GCULpy akan menawarkan lebih banyak fleksibilitas sekaligus mempertahankan prinsip intinya. Roadmap ini mencakup dukungan untuk
single inheritance pada class yang ditentukan pengguna dengan penggantian metode yang dikelola secara eksplisit
dengan dekorator @override. Selain itu, fungsi bawaan super() hanya akan didukung dalam bentuk tanpa argumen, untuk memastikan operasi yang langsung dan dapat diprediksi.
Modul gcul
GCULpy menyediakan modul gcul bawaan dengan jenis, dekorator, dan variabel penting untuk pengembangan kontrak.
class gcul.Contract
Class dasar untuk semua kontrak. Anda tidak dapat membuat instance-nya secara langsung;
kontrak hanya dibuat melalui
transaksi CreateContract. Metode dan properti dari class gcul.Contract dasar tidak dapat
diganti di subclass.
Contract.is_owner(account: Account) -> boolMenampilkan
Truejika akun yang diberikan adalah pemilik kontrak.Contract.call(target: ContractInterface, payment: Amount | None = None) -> ContractMethodsMemulai interaksi lintas kontrak dengan
target. Daripada memanggil metode pada target secara langsung (misalnya,target.foo()), Anda harus menggunakanself.call()untuk merutekan pemanggilan secara eksplisit melalui runtime ledger. Mekanisme ini menampilkan objek proxy aman yang digunakan untuk memanggil metode publik yang sesuai pada kontrak target, sehingga memastikan bahwa batas eksekusi diterapkan secara ketat danpaymentapa pun dikirimkan dengan aman. Lihat ContractInterface untuk mengetahui detailnya.paymentharus diberikan saat memanggil metode yang didekorasi dengan@gcul.payable; dan harus dihilangkan untuk metode yang tidak dapat dibayar.targetharus berupa kontrak yang berbeda. Memanggil kontrak saat ini melaluiself.call()akan memunculkan error runtime. Untuk memanggil metode lain pada kontrak yang sama, panggil secara langsung, misalnya,self.foo().Contract.native_transfer(beneficiary: Account, amount: Amount) -> NoneMentransfer jumlah on-ledger langsung dari saldo kontrak ke
beneficiary.Contract.id: strID string unik kontrak.
class gcul.Account
Jenis bawaan yang mewakili akun pengguna atau kontrak di ledger. Anda tidak dapat membuat objek gcul.Account secara langsung; lingkungan runtime membuatnya untuk Anda dan menyediakannya sebagai argumen fungsi atau metode. Untuk meneruskan akun sebagai argumen transaksi, berikan AccountValue yang menyimpan ID akun. Runtime memvalidasi ID dan mengonversinya menjadi
objek akun lengkap. Jika ID bukan milik akun terdaftar, transaksi akan gagal. Hal ini memastikan Anda hanya menggunakan akun yang valid.
Definisi class ini kira-kira setara dengan:
@dataclasses.dataclass(frozen=True)
class Account:
"""A valid account on the ledger."""
id: str # The ID of the account as a string.
Account.id: strID string unik akun.
class gcul.Amount
Mewakili nilai uang yang dinyatakan dalam mata uang buku besar tertentu.
Buat instance jumlah menggunakan
gcul.Amount(value: int, currency: gcul.Currency). Definisi class ini kira-kira setara dengan:
@dataclasses.dataclass(frozen=True)
class Amount:
"""Represents an amount denominated in a ledger currency."""
value: int
currency: Currency
class gcul.Currency
Mewakili mata uang yang sepenuhnya memenuhi syarat di ledger. Definisi class ini kira-kira setara dengan:
@dataclasses.dataclass(frozen=True)
class Currency:
"""Represents a fully qualified currency on the ledger."""
code: str
operator_id: str
class gcul.ContractInterface
Class dasar untuk mendeklarasikan antarmuka publik kontrak.
Metode dan properti dari class gcul.ContractInterface dasar tidak dapat
diganti di subclass. Selain itu, metode dalam deklarasi antarmuka
tidak boleh menyertakan kode apa pun, hanya
... yang diizinkan.
Agar kontrak dapat memanggil metode pada kontrak lain yang di-deploy di ledger,
deklarasikan class antarmuka yang mewarisi dari gcul.ContractInterface. Stub metode harus cocok dengan deklarasi yang sesuai dalam kontrak target. Hal ini
mencakup argumen, jenis nilai yang ditampilkan, dan anotasi dekorator seperti
@gcul.readonly atau @gcul.payable.
Di dalam kode kontrak Anda, gunakan self.call(target, payment) untuk
memanggil metode dari kontrak lain.
Contoh berikut mengilustrasikan cara kontrak TokenVendor berinteraksi
dengan kontrak lain yang mengimplementasikan ERC20Interface. Smart contract ini menggunakan
self.call() untuk mentransfer token kepada pembeli sebagai imbalan atas pembayaran mata uang
on-ledger:
class ERC20Interface(gcul.ContractInterface):
"""Interface for an external ERC20 token contract."""
def transfer(self, beneficiary: gcul.Account, value: int) -> int:
...
class TokenVendor(gcul.Contract):
"""A vendor contract that distributes ERC20 tokens."""
price_per_token: int
def __init__(self, price_per_token: int) -> None:
self.price_per_token = price_per_token
@gcul.payable
def purchase_tokens(self, token: ERC20Interface, quantity: int) -> int:
"""Accepts on-ledger currency for a specific quantity of ERC20 tokens."""
# Enforce positive quantity.
assert quantity > 0, "Quantity must be positive"
# Calculate the required payment.
required_payment = quantity * self.price_per_token
assert gcul.payment.value == required_payment, "Incorrect payment amount"
# Invokes `transfer` on the external ERC20 token contract
# to move tokens from the vendor's own balance to the caller.
return self.call(token).transfer(gcul.caller, quantity)
Jenis antarmuka juga dapat digunakan sebagai kolom kontrak, bukan hanya sebagai parameter metode. Menyimpan antarmuka dalam kolom memungkinkan kontrak menyimpan referensi ke
kontrak lain di seluruh transaksi, dan mengganti referensi tersebut nanti. Contoh kontrak berikut menggunakan ERC20Interface yang dideklarasikan sebelumnya:
class Router(gcul.Contract):
"""Holds a replaceable reference to an ERC20 token contract."""
target: ERC20Interface
def __init__(self, target: ERC20Interface) -> None:
self.target = target
def set_target(self, new_target: ERC20Interface) -> None:
assert self.is_owner(gcul.sender), "Only the owner can set the target"
self.target = new_target
class gcul.AccountField
Jenis generik bawaan untuk mendeklarasikan kolom akun. gcul.AccountField[T]
menyimpan nilai terpisah dari jenis T untuk setiap akun yang telah memberikan
izin penyimpanan kepada kontrak. Fungsi ini berperilaku sebagai pemetaan dengan kunci gcul.Account,
yang dapat Anda gunakan untuk membaca atau menulis nilai untuk setiap akun tertentu.
Contoh:
class Token(gcul.Contract):
balance: gcul.AccountField[int]
def deposit(self, account: gcul.Account, value: int) -> None:
self.balance[account] = value # Writes the value for one account.
def get_balance(self, account: gcul.Account) -> int:
return self.balance[account] # Reads the value for one account.
T harus berupa jenis yang memiliki nilai default, sehingga gcul.Account, gcul.Amount,
gcul.Currency, dan jenis antarmuka tidak dapat digunakan sebagai nilai kolom akun. Saat akun memberikan izin penyimpanan ke kontrak, setiap kolom akun akan diisi dengan nilai default jenisnya untuk akun tersebut.
Batasan Pengindeksan dengan akun adalah satu-satunya operasi yang didukung kolom akun. Kolom itu sendiri tidak dapat ditetapkan ke variabel, diteruskan sebagai argumen, ditampilkan dari fungsi, atau diiterasi.
Pembatasan Entri kolom akun tidak dapat dihapus. Nilai yang disimpan dapat ditimpa, tetapi entri itu sendiri bersifat permanen.
Kolom akun Pembatasan untuk gcul.sender, gcul.caller, dan
gcul.Account apa pun yang diteruskan sebagai argumen metode (termasuk di dalam daftar atau penampung
lainnya) dimuat sebelum eksekusi metode. Untuk akun lain, satu transaksi dapat memuat kolom akun secara lambat untuk maksimal 15 pasangan (contract, account) yang berbeda; mengakses kolom akun untuk pasangan yang sama beberapa kali dalam satu transaksi hanya dihitung sekali. Transaksi yang melebihi batas ini akan gagal.
@gcul.readonly
Memberi anotasi pada metode kontrak sebagai hanya baca. Deklarasi metode dengan dekorator ini tidak dapat mengubah status kontrak atau melakukan transfer mata uang di ledger. Fungsi tersebut
juga tidak dapat menggunakan jenis penampung yang dapat diubah dalam tanda tangannya, misalnya list
atau dict; fungsi tersebut harus menggunakan deklarasi jenis hanya baca seperti Sequence atau
Mapping.
@gcul.payable
Menganotasi metode kontrak sebagai memerlukan pembayaran untuk dieksekusi. Jika suatu metode
berharap menerima pembayaran mata uang on-ledger menggunakan gcul.payment, metode tersebut harus
ditandai dengan dekorator ini, jika tidak, transaksi akan gagal.
gcul.sender: gcul.Account
Menyimpan referensi ke akun yang menandatangani dan mengirimkan transaksi
InvokeContractMethod
saat ini. Nilai gcul.sender tidak berubah selama eksekusi transaksi, meskipun melibatkan panggilan lintas kontrak, tidak seperti gcul.caller yang merujuk ke pemanggil langsung.
gcul.caller: gcul.Account
Menyimpan referensi ke pemanggil langsung dari metode saat ini. Untuk transaksi pengguna langsung, gcul.caller cocok dengan gcul.sender yang mengarah ke siapa pun yang mengirimkan transaksi. Untuk panggilan lintas kontrak, gcul.caller sesuai dengan ID akun kontrak panggilan. Panggilan internal dalam kontrak tidak mengubah nilai gcul.caller.
gcul.payment: gcul.Amount
Menyimpan pembayaran yang ditransfer ke metode yang didekorasi dengan @gcul.payable.
Mengakses gcul.payment di dalam metode yang tidak dapat dibayar akan memunculkan error waktu kompilasi.
Operator
Sebagian besar operator yang tersedia di Python didukung di GCULpy dan berfungsi seperti yang diharapkan.
- Penambahan (
+) dan pengurangan (-), termasuk bentuk unary dan biner. - Perkalian (
*), pembagian bilangan bulat (//), dan modulo (%). - Eksponensial (
**) untuk eksponen positif. - Perbandingan (
<,<=,>,>=,==,!=). - Bitwise and (
&), or (|), xor (^), left shift (<<), right shift (>>), negation (~). - Operasi Boolean (
and,or,not). - Roadmap Identitas objek (
is). - Batasan Eksponen negatif tidak diizinkan dan akan memunculkan error runtime.
- Batasan Pembagian sebenarnya (
/), karena memiliki jenis nilai yang ditampilkanfloat, tidak diizinkan dan akan menghasilkan error waktu kompilasi.
Alur kontrol
Sebagian besar pernyataan alur kontrol dari Python berfungsi di GCULpy dengan semantik yang sama:
- Laporan
pass. - panggilan fungsi internal (kontrak yang sama, non-rekursif).
- Laporan
assert. - Laporan
if ... then .. else .... - Laporan
for VAR in CONTAINER. - panggilan fungsi eksternal (ke kontrak lain, non-rekursif).
- Pernyataan
breakdancontinue. - Laporan
raise. - Roadmap
try ... exceptpernyataan. - Roadmap
matchpernyataan. - Roadmap pernyataan
generatorsdanyield. - Roadmap pengelola konteks dan pernyataan
with.
Batasan GCULpy sengaja dibuat tidak lengkap Turing untuk mencegah loop tanpa batas dan memfasilitasi analisis statis. Berikut cara penerapannya:
- Tidak ada loop tak terbatas: Iterasi hanya diizinkan menggunakan loop
forpada container terbatas atau urutan terbatas denganrange(...); loopwhiletidak diizinkan. Beberapa update container, misalnya menambahkan atau menghapus elemen ke daftar atau kunci ke kamus, tidak diizinkan saat melakukan iterasi. - Tidak ada pengulangan: Fungsi tidak dapat memanggil dirinya sendiri, baik secara langsung maupun tidak langsung. Lingkungan runtime melakukan pemeriksaan statis dan runtime untuk mendeteksi dan menolak penggunaan rekursi.
- Tidak ada alur kontrol asinkron: Penggunaan primitif
asynctidak diizinkan untuk mempertahankan prinsip desain inti, yaitu prediktabilitas, keamanan, dan eksekusi deterministik. Operasi asinkron menyulitkan penalaran tentang alur kontrol program, yang sering kali menyebabkan kerentanan dan kondisi race.
Fungsi bawaan
GCULpy mendukung fungsi bawaan berikut:
abs(x)Menampilkan nilai absolut dari bilangan bulat
x. Argumen harus berjenisint.len(s)Menampilkan panjang, yaitu jumlah item, dari string atau penampung terbatas.
max(iterable)
max(arg1, arg2, *args)Menampilkan item terbesar dalam iterable atau yang terbesar dari dua argumen atau lebih. Memanggil
max()pada iterable kosong akan memunculkan error runtime.min(iterable)
min(arg1, arg2, *args)Menampilkan item terkecil dalam iterable atau yang terkecil dari dua argumen atau lebih. Memanggil
min()pada iterable kosong akan memunculkan error runtime.range(stop)
range(start, stop[, step=1])Menghasilkan urutan aritmetika bilangan bulat dengan bilangan bulat bukan nol
step.Batasan Hanya dapat digunakan secara inline dengan loop
for, misalnyafor i in range(10): .... Objek rentang tidak dapat ditetapkan ke variabel atau disimpan dalam kolom, diteruskan sebagai argumen ke fungsi, atau dikueri denganlen().
Roadmap Fungsi bawaan berikut ada dalam roadmap implementasi:
|
A
B
C
D |
E
F
H
I
L |
O
P
R |
S
T
Z |
Catatan rilis
03 Nov 2026. Merilis versi GA compiler
gculpyc(v0.2.0), termasuk dukungan untuk panggilan lintas kontrak, transfer dan pembayaran mata uang on-ledger, metode@gcul.readonly,list, pernyataan alur kontrol tambahan, dan fungsi bawaan.28 Jan 2026. Versi awal compiler
gculpyctersedia untuk peserta dalam pratinjau pribadi Universal Ledger. Untuk tutorial menggunakan compiler, lihat Men-deploy kontrak yang dapat diprogram.