Coder Social home page Coder Social logo

tealish's People

Contributors

aorumbayev avatar barnjamin avatar edizcelik avatar etzellux avatar fergalwalsh avatar gokselcoban avatar obiajulum avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

tealish's Issues

ABI support

Just wondering if ABI not being supported (as stated in FAQ explicitly) is something that is planned for long term (giving more 'flexibility' in some sense) so people deal with abi compliant methods themselves or its just that tealish was developed (started development) before ABI was introduced?

Would be an icing completing the cake if it gets added to tealish as well ;)

Use frame pointer opcodes for functions - part 1

AVM 8+ has support for frame pointers which allow for more efficient stack & slot usage for subroutines (functions in Tealish).

Tealish can generate Teal that uses proto at the start of function definitions instead of stores. frame_dig can be used to access the function args from the stack without having to store them in slots.

Teal example for reference:

pushbytes "ab"
pushbytes "cd"
// log(myfunc("ab", "cd"))
callsub myfunc
log
pushint 1
return


// myfunc(x: bytes, y: bytes) bytes:
myfunc:
// specify that our function takes 2 arguments and has one return value
proto 2 1 // internally puts the first 2 values from the stack into the frame
frame_dig -2 // first arg
frame_dig -1 // second arg
concat
retsub

Refactor Statement and Expression node parent classes

Since Statements and Expressions both inherit from BaseNode some issues arise in accessing attributes that are not defined in one or the other. We can change the inheritance structure to split the different Node types for better type information and prevent issues with inferring attribute availability.

See this comment for more: #27 (review)

Stack type definition

Currently base types (int,bytes,any,none) are strings that we match against.

A new class that subclasses Enum type, and possibly also str would be helpful to prevent us from doing string comparison and provide better type hints in containing classes

See this comment for a bit more: #27 (comment)

Replacing the value of a field of a structured box can keep parts of the replaced value

Describe the bug
{box_name}.{field_name} = {value}. replaces the field {field_name} of box {box_name} created from a struct without considering the size of {value}. This issue tracks the bug when parts of the replaced value remain after replacing it with a byte array of a smaller size than the current value.

To Reproduce

#pragma version 8

struct UserInfo:
    favourite_colour: bytes[20]
end

if Txn.ApplicationID == 0:
    exit(1)
end

box<UserInfo> info_box = CreateBox("foo")
info_box.favourite_colour = "yellow"
info_box.favourite_colour = "red"
exit(1)

Expected behavior
Field favourite_colour of box with key "foo" should have a value of "red" but is instead "redlow".

Additional context
Related issue: #75

for loop direction

I noticed that for loops always expect to increment between the start and end values, only breaking when var equals exactly the end value (which could be a problem if it somehow skips over it). However if you wanted to loop from a higher value to a lower value (e.g. swap the order of for n in 1:5: to for n in 5:1:) it results in TEAL that will hit an AVM error when evaluated ("cost budget exceeded"), since it never breaks.

At first I thought maybe I could quickly modify the tealish/__init__.py file to check if start was greater than end, then write "-" instead of "+"... And then I realised they don't have to be defined values at all, and may be unkonwn until runtime.

int x = btoi(Txn.ApplicationArgs[0])
int y = btoi(Txn.ApplicationArgs[1])
for n in x:y:
  pop(n)
end

Should there be an easy way to define or flip the default direction of a for loop without having to write additional logic to work with an incrementing value?

Need 'template' support similar to PyTeal

My infra works with raw teal, so I use beaker, pyteal, etc. to generate TEAL that's checked-in and built directly into binaries or part of a bootstrapping process.
That raw teal includes 'template' substitutions that are replaced with values specific to each environment (testnet / mainnet contract IDs, or parameter values for eg).

In PyTeal, a reference to a templated int (same w/ Bytes) might be like:
xxx.store( Itob(Tmpl.Int("TMPL_XXX")) )
which might become:

int TMPL_XXXX
itob
store 50

in TEAL. My code converts that prior to compilation, replacing the templates in descending length order.

This is one of the showstoppers for me in using Tealish.

[BUG]

Describe the bug
Order of return vars in code and docs mixed up

To Reproduce
e.g.
box_get(A: bytes) โ†’ bytes, int in https://tealish.tinyman.org/en/latest/avm.html
but in code:

int, bytes = box_get(key)

Expected behavior
box_get(A: bytes) โ†’ int, bytes in docs
xor

bytes, int = box_get(key)

in code

Additional context
this is true for some other opcodes as well

State Schemas

Tealish could allow the developer to define a schema for Global & Local states. The schema would serve two purposes:

  • indicate the number of int & byte slices used by the app
  • naming & typing of state keys

The schema should also allow for dynamically named state fields.

The syntax below is just an idea at this stage

Static state keys could be accessed using a field lookup syntax just like structs & Boxes. e.g

assert(Txn.Sender == GlobalState.manager_address)

Local state keys could use something like this:

assert(Txn.Sender == LocalState[account].manager_address)

When dynamic keys are required the existing opcodes (app_global_get & app_local_get ) should be used unless a good argument can be made for having additional syntactic sugar for these.

The schemas would be queryable from the Tealish language model of the program to allow other tools to export/consume them.

Needs more fleshing out before implementation.

@barnjamin, do correct me if I have mangled your idea :) And please add any further detail you have in mind at this stage.

[BUG] Tealish format error

Describe the bug
Using tealish format converts the following code in wrong way

To Reproduce

bytes frc_proofs = Txn.ApplicationArgs[4]
bytes rewards_proof = extract((index * 32), 32, frc_proofs)

with something with this run
tealish format approval.tl

and outputs this

bytes frc_proofs = Txn.ApplicationArgs[4]
bytes rewards_proof = extract(<tealish.expression_nodes.Group object at 0x7f8a4e7ec790> 32, frc_proofs)

Expected behavior
Just format the code not change the code

Roadmap

Please see the Tealish Roadmap #64 post in Discussions for the current project roadmap.

Comments inside Switch break parser

image

Compiling auction.tl to build/auction.teal
Error: Pattern ((?P<expression>.*): (?P<block_name>.*)) does not match for SwitchOption for line "# test"

Setting the value of a field of a structured box can overflow onto the next field

Describe the bug
{box_name}.{field_name} = {value}. replaces the field {field_name} of box {box_name} created from a struct without considering the size of {value}. This issue tracks the bug when setting the value of a field to a byte array that is larger than the size defined overflowing into the next field.

To Reproduce

#pragma version 8

struct UserInfo:
    birthday: bytes[10]
    favourite_colour: bytes[20]
end

if Txn.ApplicationID == 0:
    exit(1)
end

box<UserInfo> info_box = CreateBox("foo")
info_box.birthday = "06/02/2023OVERFLOW"
exit(1)

Expected behavior
Field favourite_colour of box with key "foo" should have an empty value ("") but is instead "OVERFLOW". You could also argue that info_box.birthday = "06/02/2023OVERFLOW" should fail outright (assigning a value larger than the size defined in the struct).

Additional context
Related issue: #74

ABI support

Is your feature request related to a problem? Please describe.
By the best practicies it is better to write teal code which supports ABI calls.

Describe the solution you'd like
Please implement ABI support to tealish.

Describe alternatives you've considered
All other pyteal compilers support abi. Pyteal, beaker, ...

Additional context
I like idea of tealish that you copy the comments to the teal or that you use the same opcode names as in teal, but it is quite crucial for new projects to use the abi. Soon there will be release of shared resources and this will drive adoption of single abi calls which might be more complex.

VS Code extension?

Is it possible to have this extension in the VS market place?
open source it?
Update readme to include the link instead of the dropbox link?

I just learned about tealish. This is very exciting. Nice work! Thank you.

Struct typing class definition

The structs dictionary provides little information about the types it holds.

A new class should be created to provide information about a given Struct type.

See this comment for more: #27 (comment)

Tealish dont't compile don't give any error just making stuck on terminal with reasigned variable and validated as conditional

Describe the bug
With this code the compiler don't compiles the compiled get stuck.

https://gist.github.com/helderjnpinto/2416f4d5e3f0dc3349ee07d976e15536

To Reproduce
Tealish compile Test.tl

Expected behavior
code compile

Additional context
I think the problem here is in the if statement if returns (line 72 ) something compiles and if is removed compiles as well

https://gist.github.com/helderjnpinto/2416f4d5e3f0dc3349ee07d976e15536#file-test-bug-tealish-L71-L73

with this case compiles:

func calc(from_round: int) int:
    int end_round = Global.Round
    int test = 1
    if end_round > 10:
       test = 10
    end

    return end_round - from_round
end

[BUG] Multiple struct with same field names cause wrong TEAL (confused) code

Describe the bug
Multiple struct with same field names cause wrong TEAL (confused) code

struct StructA:
 fieldname: int
 q: int
end

struct StructB:
 r: int
 fieldname: int
end

block main:
    StructA a = itob(1)
    int x = a.fieldname
end

results in

// block main
main:
  // StructA a = itob(1) [slot 0]
  pushint 1
  itob
  store 0 // a
  // int x = a.fieldname [slot 1]
  load 0 // a
  pushint 8
  extract_uint64 // fieldname
  store 1 // x

because fieldname is in a different place in the different structs

(the pushint 8 is wrong in the TEAL code, should be pushint 0 since fieldname is the first field in StructA

To Reproduce
code above

Expected behavior
perhaps field names need the struct name as a prefix to differentiate

Additional context
Add any other context about the problem here.

Provide better error message (or more specific to situation) for evaluation order issues.

A statement like:
if a == 2 && b ==3:
will yield an error like:
Error: Cannot parse "if a == 2 && b ==3" as Expression at line 100

I had a more involved if statement in my particular case but I fought for quite a bit of time trying to figure out what was wrong (and there's no examples in the repo of an && expression like above) until I realized it wanted
if (a==2) && (b==3):

Tealish should make it extremely clear that the evaluation order isn't defined and needs to be. The error instead reads almost like a generic 'something's wrong' - ie: a syntax error.

Future features

Thank you so much, this project is amazing! Welcome to Costco, I love you. I didn't look really thoroughly but from a glance, I am really hoping to use just about ALL of the things you mentioned in FUTURE.md. It would be amazing if vim or VSCode could eventually have autocomplete for calling public methods in an external tealish contract (module) (maybe autogenerated app call wrappers from the contract JSON?).

Anyway, thanks for all the great work.

Inner Transactions: Comment support

The inner transaction block doesn't support comments.

Problem:

inner_txn:
    # This is a comment
    TypeEnum: Axfer
    ...
end

Possible workaround:

# This is a comment
inner_txn:
    TypeEnum: Axfer
    ...
end

Macro support

algorand/go-algorand#4737 is introducing support for macros in TEAL.

One useful thing to do with macros is use them to define the constants Tealish supports.

I believe the following patch will enable that:

diff --git a/tealish/expression_nodes.py b/tealish/expression_nodes.py
index 4b365ac..409daca 100644
--- a/tealish/expression_nodes.py
+++ b/tealish/expression_nodes.py
@@ -78,9 +78,9 @@ class Constant(BaseNode):
 
     def write_teal(self, writer):
         if self.type == "int":
-            writer.write(self, f"pushint {self.value} // {self.name}")
+            writer.write(self, f"pushint {self.name} // {self.value}")
         elif self.type == "bytes":
-            writer.write(self, f"pushbytes {self.value} // {self.name}")
+            writer.write(self, f"pushbytes {self.name} // {self.value}")
 
     def _tealish(self, formatter=None):
         return f"{self.name}"
diff --git a/tealish/nodes.py b/tealish/nodes.py
index 62f9ce1..d5a53d9 100644
--- a/tealish/nodes.py
+++ b/tealish/nodes.py
@@ -334,6 +334,7 @@ class Const(LineStatement):
         scope["consts"][self.name] = [self.type, self.expression.value]
 
     def write_teal(self, writer):
+        writer.write (self, f"#define {self.name} {self.expression.value}")
         pass
 
     def _tealish(self, formatter=None):

this will result in tealish that goes from

#pragma version 8

struct Item:
    id: int
    foo: int
    name: bytes[10]
end

const int KNOWN_ID = 64738
const bytes BOX_NAME = "tealishbox"
const bytes KNOWN_ITEM = "fearghal"


box<Item> item1 = CreateBox(BOX_NAME)
item1.id = KNOWN_ID
item1.foo = KNOWN_ID + 1
item1.name = KNOWN_ITEM

log(itob(item1.id))
log(itob(item1.foo))
log(item1.name)

to TEAL

#pragma version 8


#define KNOWN_ID 64738
#define BOX_NAME "tealishbox"
#define KNOWN_ITEM "fearghal"


// box<Item> item1 = CreateBox(BOX_NAME) [slot 0]
pushbytes BOX_NAME // "tealishbox"
dup
pushint 26
box_create
assert // assert created
store 0 // item1
// item1.id = KNOWN_ID [box]
load 0 // box key item1
pushint 0 // offset
pushint KNOWN_ID // 64738
itob
box_replace // item1.id
// item1.foo = KNOWN_ID + 1 [box]
load 0 // box key item1
pushint 8 // offset
pushint KNOWN_ID // 64738
pushint 1
+
itob
box_replace // item1.foo
// item1.name = KNOWN_ITEM [box]
load 0 // box key item1
pushint 16 // offset
pushbytes KNOWN_ITEM // "fearghal"
box_replace // item1.name

// log(itob(item1.id))
load 0 // box key item1
pushint 0 // offset
pushint 8 // size
box_extract // item1.id
btoi
itob
log
// log(itob(item1.foo))
load 0 // box key item1
pushint 8 // offset
pushint 8 // size
box_extract // item1.foo
btoi
itob
log
// log(item1.name)
load 0 // box key item1
pushint 16 // offset
pushint 10 // size
box_extract // item1.name
log

Add support for include or import

I have many helper/utility functions that are shared between multiple related contracts. Whether its shared constants, or common helper functions (like beaker/pyteal utils functions), Tealish currently forces everything to be in a single file.

This is forcing copy-paste duplication of large chunks of code in some cases.

A completely fleshed out import mechanism isn't particularly necessary, but a simple C like #include that injected from other files would address this problem well enough.

Scope type definition

Currently the scope on Nodes is a Dict[str, Any] but this doesn't provide much information about what it contains.

A new class should be defined to provide better type information for scope and the nodes should be updated to use it.

Need support for alternative format Bytes values

PyTeal suports Bytes syntax variants like:

Bytes("base16", "0x052001018008010203040506")

I use this to construct TEAL bytcode that's manipulate for LSIG references inside a contract. I don't see any way to do this in Tealish at the moment.

[BUG] cannot parse expression with `const int`

Describe the bug

int x = 1
const int X = 1
int y = 1
 # next line is ok
_ = x * y
 # next line is NOT ok
_ = X * y

Error: Cannot parse "X * y" as Expression

To Reproduce
Steps to reproduce the behavior.

Expected behavior
both lines should compile

Additional context
Add any other context about the problem here.

Comments should be allowed anywhere in the code, including after lines.

Currently, # comments are only allowed on a line by themself.

They should be allowed after lines as well:
const int MY_CONST = 42 # Magic constant

Variations of this same issue are also referenced in #45 and #15

Comments should also be allowed before the #pragma version XX line (ie: templated copyright lines for eg)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.