Skip to content

Commit

Permalink
Abstract Syntax Tree (AST) Assembly Support (#125)
Browse files Browse the repository at this point in the history
* First skeleton for AST Assembly statements

* Basic Yul Literal implementation

* Implementing unmarshal skeleton

* Adding yul switch case statement

* Fixing YulLiteral, YulIf, YulAssignment, YulFunctionCall and YulExpression

* Fixing YulBreak, YulContinue, YulLeave

* Fixing out YulVariable and cleanup of YulIdentifier

* Fixing up AssemblyStatement, YulFor and YulBlock

* Fixing YulLiteral kind

* Fixing YulFunctionDefinition

* Fixing YulSwitch and YulSwitchCase as well as YulFunctionDefinition. First version of Assembly parsing logic is completed

* Assembly protocol buffers including protos version bump

* Improving ast coverage, implementing json unmarshaler for ast yul, bumping protos

* YulAssignment and YulBlock docs

* Docs for YulBreak, YulContinue, YulExpression and YulFor

* Yul docs and fixes
  • Loading branch information
0x19 authored Oct 17, 2023
1 parent 4ddc068 commit 993fc9b
Show file tree
Hide file tree
Showing 218 changed files with 551,013 additions and 365,606 deletions.
115 changes: 0 additions & 115 deletions ast/assembly.go

This file was deleted.

2 changes: 1 addition & 1 deletion ast/body.go
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,7 @@ func (b *BodyNode) parseStatements(
unit, contractNode, fnNode, b, childCtx,
))
case *parser.AssemblyStatementContext:
statement := NewAssemblyStatement(b.ASTBuilder)
statement := NewYul(b.ASTBuilder)
b.Statements = append(b.Statements, statement.Parse(
unit, contractNode, fnNode, b, childCtx,
))
Expand Down
2 changes: 2 additions & 0 deletions ast/builder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,8 @@ func TestAstBuilderFromSourceAsString(t *testing.T) {
assert.Equal(t, sourceUnit.GetName(), testCase.sources.EntrySourceUnitName)
}

assert.NotNil(t, astRoot.GetGlobalNodes())

assert.True(t, astRoot.HasSourceUnits())
assert.NotNil(t, astRoot.GetSourceUnitByName(sourceUnit.GetName()))
assert.NotNil(t, astRoot.GetSourceUnitById(sourceUnit.GetId()))
Expand Down
10 changes: 0 additions & 10 deletions ast/pragma.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,16 +108,6 @@ func CreatePragmaFromCtx(b *ASTBuilder, unit *SourceUnit[Node[ast_pb.SourceUnit]
}
}

// EnterPragmaDirective is called when production pragmaDirective is entered.
// However, it won't return pragma directives properly. For example, if we have
// experimental pragma, it won't return it. It will return only the pragma.
// Because of it, we are parsing pragmas in EnterSourceUnit to be able capture all of the
// pragmas and assign them based on the contract they belong to. Source file can have multiple
// contracts and multiple files and therefore we need to be able to assign pragmas to the
// correct contract.
// @WARN: DO NOT USE THIS METHOD.
func (b *ASTBuilder) EnterPragmaDirective(ctx *parser.PragmaDirectiveContext) {}

// FindPragmasForSourceUnit traverses the children of the provided source unit until
// it finds the library, contract, or interface definition. It collects all pragma
// directives encountered along the way and returns them as a slice of Node.
Expand Down
11 changes: 9 additions & 2 deletions ast/unary_prefix.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ type UnaryPrefix struct {

Id int64 `json:"id"`
NodeType ast_pb.NodeType `json:"node_type"`
Kind NodeType `json:"kind"`
Kind ast_pb.NodeType `json:"kind"`
Src SrcNode `json:"src"`
Operator ast_pb.Operator `json:"operator"`
Prefix bool `json:"prefix"`
Expand Down Expand Up @@ -55,7 +55,7 @@ func (u *UnaryPrefix) GetType() ast_pb.NodeType {
}

// GetKind returns the node type of the UnaryPrefix.
func (u *UnaryPrefix) GetKind() NodeType {
func (u *UnaryPrefix) GetKind() ast_pb.NodeType {
return u.Kind
}

Expand Down Expand Up @@ -132,6 +132,12 @@ func (u *UnaryPrefix) UnmarshalJSON(data []byte) error {
}
}

if kind, ok := tempMap["kind"]; ok {
if err := json.Unmarshal(kind, &u.Kind); err != nil {
return err
}
}

if src, ok := tempMap["src"]; ok {
if err := json.Unmarshal(src, &u.Src); err != nil {
return err
Expand Down Expand Up @@ -214,6 +220,7 @@ func (u *UnaryPrefix) ToProto() NodeType {
proto := ast_pb.UnaryPrefix{
Id: u.GetId(),
NodeType: u.GetType(),
Kind: u.GetKind(),
Src: u.GetSrc().ToProto(),
Operator: u.GetOperator(),
Prefix: u.GetPrefix(),
Expand Down
7 changes: 7 additions & 0 deletions ast/unary_suffix.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,12 @@ func (u *UnarySuffix) UnmarshalJSON(data []byte) error {
}
}

if kind, ok := tempMap["kind"]; ok {
if err := json.Unmarshal(kind, &u.Kind); err != nil {
return err
}
}

if src, ok := tempMap["src"]; ok {
if err := json.Unmarshal(src, &u.Src); err != nil {
return err
Expand Down Expand Up @@ -214,6 +220,7 @@ func (u *UnarySuffix) ToProto() NodeType {
proto := ast_pb.UnarySuffix{
Id: u.GetId(),
NodeType: u.GetType(),
Kind: u.GetKind(),
Src: u.GetSrc().ToProto(),
Operator: u.GetOperator(),
Prefix: u.GetPrefix(),
Expand Down
94 changes: 92 additions & 2 deletions ast/unmarshaler.go
Original file line number Diff line number Diff line change
Expand Up @@ -390,11 +390,11 @@ func unmarshalNode(data []byte, nodeType ast_pb.NodeType) (Node[NodeType], error
return toReturn, nil

//
// FUTURE IMPLEMENTATIONS....
// ASSEMBLY / YUL NODES
//

case ast_pb.NodeType_ASSEMBLY_STATEMENT:
var toReturn *AssemblyStatement
var toReturn *Yul
if err := json.Unmarshal(data, &toReturn); err != nil {
return nil, err
}
Expand All @@ -405,6 +405,96 @@ func unmarshalNode(data []byte, nodeType ast_pb.NodeType) (Node[NodeType], error
return nil, err
}
return toReturn, nil
case ast_pb.NodeType_YUL_VARIABLE_DECLARATION:
var toReturn *YulAssignment
if err := json.Unmarshal(data, &toReturn); err != nil {
return nil, err
}
return toReturn, nil
case ast_pb.NodeType_YUL_ASSIGNMENT:
var toReturn *YulAssignment
if err := json.Unmarshal(data, &toReturn); err != nil {
return nil, err
}
return toReturn, nil
case ast_pb.NodeType_YUL_BLOCK:
var toReturn *YulBlockStatement
if err := json.Unmarshal(data, &toReturn); err != nil {
return nil, err
}
return toReturn, nil
case ast_pb.NodeType_YUL_FOR:
var toReturn *YulForStatement
if err := json.Unmarshal(data, &toReturn); err != nil {
return nil, err
}
return toReturn, nil
case ast_pb.NodeType_YUL_IF:
var toReturn *YulIfStatement
if err := json.Unmarshal(data, &toReturn); err != nil {
return nil, err
}
return toReturn, nil
case ast_pb.NodeType_YUL_SWITCH:
var toReturn *YulSwitchStatement
if err := json.Unmarshal(data, &toReturn); err != nil {
return nil, err
}
return toReturn, nil
case ast_pb.NodeType_YUL_SWITCH_CASE:
var toReturn *YulSwitchCaseStatement
if err := json.Unmarshal(data, &toReturn); err != nil {
return nil, err
}
return toReturn, nil
case ast_pb.NodeType_YUL_LITERAL:
var toReturn *YulLiteralStatement
if err := json.Unmarshal(data, &toReturn); err != nil {
return nil, err
}
return toReturn, nil
case ast_pb.NodeType_YUL_FUNCTION_CALL:
var toReturn *YulFunctionCallStatement
if err := json.Unmarshal(data, &toReturn); err != nil {
return nil, err
}
return toReturn, nil
case ast_pb.NodeType_YUL_EXPRESSION:
var toReturn *YulExpressionStatement
if err := json.Unmarshal(data, &toReturn); err != nil {
return nil, err
}
return toReturn, nil
case ast_pb.NodeType_YUL_FUNCTION_DEFINITION:
var toReturn *YulFunctionDefinition
if err := json.Unmarshal(data, &toReturn); err != nil {
return nil, err
}
return toReturn, nil
case ast_pb.NodeType_YUL_BREAK:
var toReturn *YulBreakStatement
if err := json.Unmarshal(data, &toReturn); err != nil {
return nil, err
}
return toReturn, nil
case ast_pb.NodeType_YUL_CONTINUE:
var toReturn *YulContinueStatement
if err := json.Unmarshal(data, &toReturn); err != nil {
return nil, err
}
return toReturn, nil
case ast_pb.NodeType_YUL_LEAVE:
var toReturn *YulLeaveStatement
if err := json.Unmarshal(data, &toReturn); err != nil {
return nil, err
}
return toReturn, nil
case ast_pb.NodeType_YUL_IDENTIFIER:
var toReturn *YulIdentifier
if err := json.Unmarshal(data, &toReturn); err != nil {
return nil, err
}
return toReturn, nil
default:
zap.L().Error(
"unknown node type while importing JSON",
Expand Down
Loading

0 comments on commit 993fc9b

Please sign in to comment.