-
Notifications
You must be signed in to change notification settings - Fork 0
Print ast
to Solidity Source Code
#201
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
5567710
7850787
e2fda85
0304c61
a1bae10
89482cf
74d3a24
f226fc3
e95e1d6
e72e982
49d2ec4
7077282
adb19ed
b34296e
9711c18
ec75618
8808357
dc7e7c7
223edcb
be5144b
ab6a4a8
62e058a
9e0b00a
03d551e
6582c55
08eb0e2
87b6576
9855ea1
e6bc022
e6bf8ab
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -438,5 +438,5 @@ func (p *Parameter) getStorageLocationFromCtx(ctx *parser.ParameterDeclarationCo | |
} | ||
} | ||
|
||
return ast_pb.StorageLocation_MEMORY | ||
return ast_pb.StorageLocation_DEFAULT | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I changed this from There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We print "" on There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good catch! |
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,6 +22,7 @@ type StateVariableDeclaration struct { | |
Visibility ast_pb.Visibility `json:"visibility"` // Visibility of the state variable declaration | ||
StorageLocation ast_pb.StorageLocation `json:"storage_location"` // Storage location of the state variable declaration | ||
StateMutability ast_pb.Mutability `json:"mutability"` // State mutability of the state variable declaration | ||
Override bool `json:"is_override"` // Indicates if the state variable is an override | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Introduced an Override for StateVariableDeclaration, eg There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice one, I missed that one 🎃 |
||
TypeName *TypeName `json:"type_name"` // Type name of the state variable | ||
InitialValue Node[NodeType] `json:"initial_value"` // Initial value of the state variable | ||
} | ||
|
@@ -207,6 +208,8 @@ func (v *StateVariableDeclaration) Parse( | |
v.Constant = constantCtx != nil | ||
} | ||
|
||
v.Override = ctx.GetOverrideSpecifierSet() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could this panic in case that there's no specifier set? basically if not nil to set it? |
||
|
||
typeName := NewTypeName(v.ASTBuilder) | ||
|
||
typeName.Parse(unit, nil, v.Id, ctx.GetType_()) | ||
|
@@ -270,6 +273,8 @@ func (v *StateVariableDeclaration) ParseGlobal( | |
v.Constant = constantCtx != nil | ||
} | ||
|
||
v.Override = ctx.GetOverrideSpecifierSet() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same as above |
||
|
||
typeName := NewTypeName(v.ASTBuilder) | ||
typeName.Parse(nil, nil, v.Id, ctx.GetType_()) | ||
v.TypeName = typeName | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package ast_printer | ||
|
||
import ( | ||
"strings" | ||
|
||
"github.com/unpackdev/solgo/ast" | ||
) | ||
|
||
func printAndOperation(node *ast.AndOperation, sb *strings.Builder, depth int) bool { | ||
expressions := []string{} | ||
success := true | ||
for _, exp := range node.GetExpressions() { | ||
s, ok := Print(exp) | ||
success = ok && success | ||
expressions = append(expressions, s) | ||
} | ||
writeSeperatedList(sb, " && ", expressions) | ||
return success | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
package ast_printer | ||
|
||
import ( | ||
"strings" | ||
|
||
ast_pb "github.com/unpackdev/protos/dist/go/ast" | ||
"github.com/unpackdev/solgo/ast" | ||
) | ||
|
||
func getAssignOperatorString(op ast_pb.Operator) string { | ||
switch op { | ||
case ast_pb.Operator_EQUAL: | ||
return "=" | ||
case ast_pb.Operator_PLUS_EQUAL: | ||
return "+=" | ||
case ast_pb.Operator_MINUS_EQUAL: | ||
return "-=" | ||
case ast_pb.Operator_MUL_EQUAL: | ||
return "*=" | ||
case ast_pb.Operator_DIV_EQUAL: | ||
return "/=" | ||
case ast_pb.Operator_MOD_EQUAL: | ||
return "%=" | ||
case ast_pb.Operator_AND_EQUAL: | ||
return "&=" | ||
case ast_pb.Operator_OR_EQUAL: | ||
return "|=" | ||
case ast_pb.Operator_XOR_EQUAL: | ||
return "^=" | ||
case ast_pb.Operator_SHIFT_LEFT_EQUAL: | ||
return "<<=" | ||
case ast_pb.Operator_SHIFT_RIGHT_EQUAL: | ||
return ">>=" | ||
case ast_pb.Operator_BIT_AND_EQUAL: | ||
return "&=" | ||
case ast_pb.Operator_BIT_OR_EQUAL: | ||
return "|=" | ||
case ast_pb.Operator_BIT_XOR_EQUAL: | ||
return "^=" | ||
case ast_pb.Operator_POW_EQUAL: | ||
return "**=" | ||
default: | ||
return "" | ||
} | ||
} | ||
|
||
func printAssignment(node *ast.Assignment, sb *strings.Builder, depth int) bool { | ||
success := true | ||
if node.Expression != nil { | ||
return PrintRecursive(node.Expression, sb, depth) | ||
} | ||
if node.LeftExpression == nil || node.RightExpression == nil { | ||
return false | ||
} | ||
op := getAssignOperatorString(node.Operator) | ||
if op == "" { | ||
success = false | ||
} | ||
success = PrintRecursive(node.LeftExpression, sb, depth) && success | ||
sb.WriteString(" ") | ||
sb.WriteString(op) | ||
sb.WriteString(" ") | ||
success = PrintRecursive(node.RightExpression, sb, depth) && success | ||
return success | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,195 @@ | ||
package ast_printer | ||
|
||
import ( | ||
"strings" | ||
|
||
ast_pb "github.com/unpackdev/protos/dist/go/ast" | ||
"github.com/unpackdev/solgo/ast" | ||
"go.uber.org/zap" | ||
) | ||
|
||
const INDENT_SIZE = 2 | ||
|
||
// Print is a function that prints the AST nodes to source code | ||
func Print(node ast.Node[ast.NodeType]) (string, bool) { | ||
sb := strings.Builder{} | ||
success := PrintRecursive(node, &sb, 0) | ||
return sb.String(), success | ||
} | ||
|
||
// PrintRecursive is a function that prints the AST nodes to source code recursively | ||
func PrintRecursive(node ast.Node[ast.NodeType], sb *strings.Builder, depth int) bool { | ||
0x19 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if node == nil { | ||
zap.S().Error("Node is nil") | ||
return false | ||
} | ||
switch node := node.(type) { | ||
case *ast.AndOperation: | ||
return printAndOperation(node, sb, depth) | ||
case *ast.BodyNode: | ||
return printBody(node, sb, depth) | ||
case *ast.Conditional: | ||
return printConditional(node, sb, depth) | ||
case *ast.Constructor: | ||
return printConstructor(node, sb, depth) | ||
case *ast.Pragma: | ||
return printPragma(node, sb, depth) | ||
case *ast.Contract: | ||
return printContract(node, sb, depth) | ||
case *ast.Function: | ||
return printFunction(node, sb, depth) | ||
case *ast.Parameter: | ||
return printParameter(node, sb, depth) | ||
case *ast.Assignment: | ||
return printAssignment(node, sb, depth) | ||
case *ast.TypeName: | ||
return printTypeName(node, sb, depth) | ||
case *ast.BinaryOperation: | ||
return printBinaryOperation(node, sb, depth) | ||
case *ast.StateVariableDeclaration: | ||
return printStateVariableDeclaration(node, sb, depth) | ||
case *ast.Emit: | ||
return printEmit(node, sb, depth) | ||
case *ast.ForStatement: | ||
return printFor(node, sb, depth) | ||
case *ast.PrimaryExpression: | ||
return printPrimaryExpression(node, sb, depth) | ||
case *ast.FunctionCall: | ||
return printFunctionCall(node, sb, depth) | ||
case *ast.Import: | ||
return printImport(node, sb, depth) | ||
case *ast.MemberAccessExpression: | ||
return printMemberAccessExpression(node, sb, depth) | ||
case *ast.VariableDeclaration: | ||
return printVariableDeclaration(node, sb, depth) | ||
case *ast.Declaration: | ||
return printDeclaration(node, sb, depth) | ||
case *ast.UnaryPrefix: | ||
return printUnaryPrefix(node, sb, depth) | ||
case *ast.UnarySuffix: | ||
return printUnarySuffix(node, sb, depth) | ||
case *ast.IndexAccess: | ||
return printIndexAccess(node, sb, depth) | ||
case *ast.ReturnStatement: | ||
return printReturn(node, sb, depth) | ||
case *ast.TupleExpression: | ||
return printTupleExpression(node, sb, depth) | ||
case *ast.StructDefinition: | ||
return printStructDefinition(node, sb, depth) | ||
case *ast.IfStatement: | ||
return printIfStatement(node, sb, depth) | ||
case *ast.EnumDefinition: | ||
return printEnumDefinition(node, sb, depth) | ||
case *ast.ModifierDefinition: | ||
return printModifierDefinition(node, sb, depth) | ||
case *ast.EventDefinition: | ||
return printEventDefinition(node, sb, depth) | ||
case *ast.ErrorDefinition: | ||
return printErrorDefinition(node, sb, depth) | ||
case *ast.PayableConversion: | ||
return printPayableConversion(node, sb, depth) | ||
case *ast.RevertStatement: | ||
return printRevertStatement(node, sb, depth) | ||
case *ast.ContinueStatement: | ||
return printContinueStatement(node, sb, depth) | ||
case *ast.InlineArray: | ||
return printInlineArray(node, sb, depth) | ||
default: | ||
if node.GetType() == ast_pb.NodeType_SOURCE_UNIT { | ||
return printSourceUnit(node, sb, depth) | ||
} | ||
zap.S().Errorf("Unknown node type: %T\n", node) | ||
return false | ||
} | ||
} | ||
|
||
func writeSeperatedStrings(sb *strings.Builder, seperator string, s ...string) { | ||
count := 0 | ||
for _, item := range s { | ||
// Skip empty strings | ||
if item == "" { | ||
continue | ||
} | ||
|
||
if count > 0 { | ||
sb.WriteString(seperator) | ||
sb.WriteString(item) | ||
} else { | ||
sb.WriteString(item) | ||
} | ||
count++ | ||
} | ||
} | ||
|
||
func writeSeperatedList(sb *strings.Builder, seperator string, s []string) { | ||
count := 0 | ||
for _, item := range s { | ||
// Skip empty strings | ||
if item == "" { | ||
continue | ||
} | ||
|
||
if count > 0 { | ||
sb.WriteString(seperator) | ||
sb.WriteString(item) | ||
} else { | ||
sb.WriteString(item) | ||
} | ||
count++ | ||
} | ||
} | ||
|
||
func writeStrings(sb *strings.Builder, s ...string) { | ||
for _, item := range s { | ||
sb.WriteString(item) | ||
} | ||
} | ||
|
||
func indentString(s string, depth int) string { | ||
return strings.Repeat(" ", depth*INDENT_SIZE) + s | ||
} | ||
|
||
func getStorageLocationString(storage ast_pb.StorageLocation) string { | ||
switch storage { | ||
case ast_pb.StorageLocation_DEFAULT: | ||
return "" | ||
case ast_pb.StorageLocation_MEMORY: | ||
return "memory" | ||
case ast_pb.StorageLocation_STORAGE: | ||
return "storage" | ||
case ast_pb.StorageLocation_CALLDATA: | ||
return "calldata" | ||
default: | ||
return "" | ||
} | ||
} | ||
|
||
func getVisibilityString(visibility ast_pb.Visibility) string { | ||
switch visibility { | ||
case ast_pb.Visibility_INTERNAL: | ||
return "internal" | ||
case ast_pb.Visibility_PUBLIC: | ||
return "public" | ||
case ast_pb.Visibility_EXTERNAL: | ||
return "external" | ||
case ast_pb.Visibility_PRIVATE: | ||
return "private" | ||
default: | ||
return "" | ||
} | ||
} | ||
|
||
func getStateMutabilityString(mut ast_pb.Mutability) string { | ||
switch mut { | ||
case ast_pb.Mutability_PURE: | ||
return "pure" | ||
case ast_pb.Mutability_VIEW: | ||
return "view" | ||
case ast_pb.Mutability_NONPAYABLE: | ||
return "" | ||
case ast_pb.Mutability_PAYABLE: | ||
return "payable" | ||
default: | ||
return "" | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This too me sounds like that it could have potential side-effects. It should probably be checked if block itself is not nil? Going to test it as well and should for sure, as we started be part of the different PR, not this one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will remove this from the PR!