Designing a language¶
The first step to adding a new front end for Puya is designing the language itself.
Will you build on top of an existing language (as Algorand Python and Algorand TypeScript do), or define an entirely new language from scratch
Building on top of an existing language allows you to leverage existing developer tools and presents a familiar developer experience for your users; but limitations of the source language will constrain your solution.
Defining a language from scratch gives you the ultimate in flexibility to build something fit for the purpose of writing smart contracts and logic signatures but represents a significantly larger undertaking. Developer experience will be heavily influenced by the effort put into accompanying developer tools (linter, formatter, language-service/autocomplete etc)
If building on an existing language, will you strive for semantic compatibility with the source language - or match the language only in syntax.
Maintaining semantic compatibility can be more restrictive than the alternative, but it ensures existing developer tooling such as code quick fixes are still relevant to code written in your dialect.
Regardless of which option is chosen, the language will be composed of a set of supported syntax (likely a subset of the source language if based on an existing one), and a library of types and functions representing the full API of your solution.
Primitive and compound types¶
AWST defines a number of different primitive and compound types. You will need to decide how your language represents these types and how they interact. Notably your language will need to support a range of binary expressions for math operations on integers, and operations for slicing and dicing byte arrays. It should also define types for arrays and tuples.
Contract and logic signature paradigms¶
Next you should decide how your language will represent contracts and logic signatures. Algorand Python and Algorand TypeScript use classes to represent contracts - newing up a contract class is akin to creating the application with instance members used to define contract methods and state. For Algorand Python, logic signatures are implemented as a pure function whilst Algorand TypeScript uses a class again due to technical limitations of the language.
The paradigm your language uses should be tailored to what is idiomatic in the base language.
Other key abstractions¶
In no particular order, your language will need abstractions for:
Reading and writing Application (Global) Storage, Account (Local) storage, Box storage, and scratch space.
Executing utility op codes (eg. elliptic curve verification, hashing etc)
Reading application/account/asset metadata
Reading group transaction data
Composing inner transactions
Reading global fields (eg. min txn fee, current round etc)
Template variables
Algorand Python’s algopy
module and Algorand TypeScript’s @algorandfoundation/algorand-typescript
modules are helpful resources for designing a public API. Both make use of a sanitised lang spec file to generate the operation types. The unsanitised lang spec file being an artifact generated by go-algorand.