Skip to content

Commit

Permalink
preprocessor addressability work
Browse files Browse the repository at this point in the history
  • Loading branch information
deelawn committed Aug 27, 2024
1 parent 651f5aa commit c8462ec
Show file tree
Hide file tree
Showing 2 changed files with 137 additions and 9 deletions.
122 changes: 113 additions & 9 deletions gnovm/pkg/gnolang/nodes.go
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,7 @@ var (
type Expr interface {
Node
assertExpr()
isAddressable() bool
}

type Exprs []Expr
Expand Down Expand Up @@ -374,6 +375,10 @@ type NameExpr struct {
Name
}

func (x *NameExpr) isAddressable() bool {
return true
}

type NameExprs []NameExpr

type BasicLitExpr struct {
Expand All @@ -385,19 +390,32 @@ type BasicLitExpr struct {
Value string
}

func (x *BasicLitExpr) isAddressable() bool {
return false
}

type BinaryExpr struct { // (Left Op Right)
Attributes
Left Expr // left operand
Op Word // operator
Right Expr // right operand
}

func (x *BinaryExpr) isAddressable() bool {
return false
}

type CallExpr struct { // Func(Args<Varg?...>)
Attributes
Func Expr // function expression
Args Exprs // function arguments, if any.
Varg bool // if true, final arg is variadic.
NumArgs int // len(Args) or len(Args[0].Results)
Func Expr // function expression
Args Exprs // function arguments, if any.
Varg bool // if true, final arg is variadic.
NumArgs int // len(Args) or len(Args[0].Results)
IsAddressable bool
}

func (x *CallExpr) isAddressable() bool {
return x.IsAddressable
}

type IndexExpr struct { // X[Index]
Expand All @@ -407,11 +425,20 @@ type IndexExpr struct { // X[Index]
HasOK bool // if true, is form: `value, ok := <X>[<Key>]
}

func (x *IndexExpr) isAddressable() bool {
return x.X.isAddressable()
}

type SelectorExpr struct { // X.Sel
Attributes
X Expr // expression
Path ValuePath // set by preprocessor.
Sel Name // field selector
X Expr // expression
Path ValuePath // set by preprocessor.
Sel Name // field selector
IsAddressable bool
}

func (x *SelectorExpr) isAddressable() bool {
return x.IsAddressable
}

type SliceExpr struct { // X[Low:High:Max]
Expand All @@ -422,6 +449,10 @@ type SliceExpr struct { // X[Low:High:Max]
Max Expr // maximum capacity of slice; or nil; added in Go 1.2
}

func (x *SliceExpr) isAddressable() bool {
return x.X.isAddressable()
}

// A StarExpr node represents an expression of the form
// "*" Expression. Semantically it could be a unary "*"
// expression, or a pointer type.
Expand All @@ -430,18 +461,30 @@ type StarExpr struct { // *X
X Expr // operand
}

func (x *StarExpr) isAddressable() bool {
return false
}

type RefExpr struct { // &X
Attributes
X Expr // operand
}

func (x *RefExpr) isAddressable() bool {
return x.X.isAddressable()
}

type TypeAssertExpr struct { // X.(Type)
Attributes
X Expr // expression.
Type Expr // asserted type, never nil.
HasOK bool // if true, is form: `_, ok := <X>.(<Type>)`.
}

func (x *TypeAssertExpr) isAddressable() bool {
return x.X.isAddressable()
}

// A UnaryExpr node represents a unary expression. Unary
// "*" expressions (dereferencing and pointer-types) are
// represented with StarExpr nodes. Unary & expressions
Expand All @@ -452,12 +495,21 @@ type UnaryExpr struct { // (Op X)
Op Word // operator
}

func (x *UnaryExpr) isAddressable() bool {
return x.X.isAddressable()
}

// MyType{<key>:<value>} struct, array, slice, and map
// expressions.
type CompositeLitExpr struct {
Attributes
Type Expr // literal type; or nil
Elts KeyValueExprs // list of struct fields; if any
Type Expr // literal type; or nil
Elts KeyValueExprs // list of struct fields; if any
IsAddressable bool
}

func (x *CompositeLitExpr) isAddressable() bool {
return x.IsAddressable
}

// Returns true if any elements are keyed.
Expand Down Expand Up @@ -490,6 +542,10 @@ type KeyValueExpr struct {
Value Expr // never nil
}

func (x *KeyValueExpr) isAddressable() bool {
return false
}

type KeyValueExprs []KeyValueExpr

// A FuncLitExpr node represents a function literal. Here one
Expand All @@ -502,6 +558,10 @@ type FuncLitExpr struct {
Body // function body
}

func (x *FuncLitExpr) isAddressable() bool {
return false
}

// The preprocessor replaces const expressions
// with *ConstExpr nodes.
type ConstExpr struct {
Expand All @@ -510,6 +570,10 @@ type ConstExpr struct {
TypedValue
}

func (x *ConstExpr) isAddressable() bool {
return false
}

// ----------------------------------------
// Type(Expressions)
//
Expand Down Expand Up @@ -574,6 +638,10 @@ type FieldTypeExpr struct {
Tag Expr
}

func (x *FieldTypeExpr) isAddressable() bool {
return false
}

type FieldTypeExprs []FieldTypeExpr

func (ftxz FieldTypeExprs) IsNamed() bool {
Expand All @@ -598,18 +666,30 @@ type ArrayTypeExpr struct {
Elt Expr // element type
}

func (x *ArrayTypeExpr) isAddressable() bool {
return false
}

type SliceTypeExpr struct {
Attributes
Elt Expr // element type
Vrd bool // variadic arg expression
}

func (x *SliceTypeExpr) isAddressable() bool {
return false
}

type InterfaceTypeExpr struct {
Attributes
Methods FieldTypeExprs // list of methods
Generic Name // for uverse generics
}

func (x *InterfaceTypeExpr) isAddressable() bool {
return false
}

type ChanDir int

const (
Expand All @@ -627,36 +707,60 @@ type ChanTypeExpr struct {
Value Expr // value type
}

func (x *ChanTypeExpr) isAddressable() bool {
return false
}

type FuncTypeExpr struct {
Attributes
Params FieldTypeExprs // (incoming) parameters, if any.
Results FieldTypeExprs // (outgoing) results, if any.
}

func (x *FuncTypeExpr) isAddressable() bool {
return false
}

type MapTypeExpr struct {
Attributes
Key Expr // const
Value Expr // value type
}

func (x *MapTypeExpr) isAddressable() bool {
return false
}

type StructTypeExpr struct {
Attributes
Fields FieldTypeExprs // list of field declarations
}

func (x *StructTypeExpr) isAddressable() bool {
return false
}

// Like ConstExpr but for types.
type constTypeExpr struct {
Attributes
Source Expr
Type Type
}

func (x *constTypeExpr) isAddressable() bool {
return false
}

// Only used for native func arguments
type MaybeNativeTypeExpr struct {
Attributes
Type Expr
}

func (x *MaybeNativeTypeExpr) isAddressable() bool {
return false
}

// ----------------------------------------
// Stmt
//
Expand Down
24 changes: 24 additions & 0 deletions gnovm/pkg/gnolang/preprocess.go
Original file line number Diff line number Diff line change
Expand Up @@ -1341,6 +1341,13 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node {
}
}

if len(ft.Results) == 1 {
switch ft.Results[0].Type.(type) {
case *PointerType, *InterfaceType:
n.IsAddressable = true
}
}

// Continue with general case.
hasVarg := ft.HasVarg()
isVarg := n.Varg
Expand Down Expand Up @@ -1603,6 +1610,10 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node {
convertType(store, last, &n.Elts[i].Key, IntType)
checkOrConvertType(store, last, &n.Elts[i].Value, cclt.Elt, false)
}

// Slices are always addressable because the underlying array
// is added to the heap during initialization.
n.IsAddressable = true
case *MapType:
for i := 0; i < len(n.Elts); i++ {
checkOrConvertType(store, last, &n.Elts[i].Key, cclt.Key, false)
Expand Down Expand Up @@ -1642,6 +1653,10 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node {
}
}

if ftype == TRANS_REF_X {
n.IsAddressable = true
}

// TRANS_LEAVE -----------------------
case *KeyValueExpr:
// NOTE: For simplicity we just
Expand All @@ -1650,6 +1665,10 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node {
// TRANS_LEAVE -----------------------
case *SelectorExpr:
xt := evalStaticTypeOf(store, last, n.X)
switch xt.(type) {
case *PointerType, *InterfaceType:
n.IsAddressable = true
}

// Set selector path based on xt's type.
switch cxt := xt.(type) {
Expand Down Expand Up @@ -2360,6 +2379,11 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node {
// Replace the type with *constTypeExpr{},
// otherwise methods would be un at runtime.
n.Type = constType(n.Type, dst)

case *RefExpr:
if !n.X.isAddressable() {
panic(fmt.Sprintf("cannot take address of %s", n.X.String()))
}
}
// end type switch statement
// END TRANS_LEAVE -----------------------
Expand Down

0 comments on commit c8462ec

Please sign in to comment.