Skip to content
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

Introduce TypelessStructLiteralArg and NewConstructorArg interfaces #183

Merged
merged 22 commits into from
Oct 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
216 changes: 170 additions & 46 deletions ast/ast.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,38 +150,43 @@ type Expr interface {
isExpr()
}

func (BinaryExpr) isExpr() {}
func (UnaryExpr) isExpr() {}
func (InExpr) isExpr() {}
func (IsNullExpr) isExpr() {}
func (IsBoolExpr) isExpr() {}
func (BetweenExpr) isExpr() {}
func (SelectorExpr) isExpr() {}
func (IndexExpr) isExpr() {}
func (CallExpr) isExpr() {}
func (CountStarExpr) isExpr() {}
func (CastExpr) isExpr() {}
func (ExtractExpr) isExpr() {}
func (CaseExpr) isExpr() {}
func (ParenExpr) isExpr() {}
func (ScalarSubQuery) isExpr() {}
func (ArraySubQuery) isExpr() {}
func (ExistsSubQuery) isExpr() {}
func (Param) isExpr() {}
func (Ident) isExpr() {}
func (Path) isExpr() {}
func (ArrayLiteral) isExpr() {}
func (StructLiteral) isExpr() {}
func (NullLiteral) isExpr() {}
func (BoolLiteral) isExpr() {}
func (IntLiteral) isExpr() {}
func (FloatLiteral) isExpr() {}
func (StringLiteral) isExpr() {}
func (BytesLiteral) isExpr() {}
func (DateLiteral) isExpr() {}
func (TimestampLiteral) isExpr() {}
func (NumericLiteral) isExpr() {}
func (JSONLiteral) isExpr() {}
func (BinaryExpr) isExpr() {}
func (UnaryExpr) isExpr() {}
func (InExpr) isExpr() {}
func (IsNullExpr) isExpr() {}
func (IsBoolExpr) isExpr() {}
func (BetweenExpr) isExpr() {}
func (SelectorExpr) isExpr() {}
func (IndexExpr) isExpr() {}
func (CallExpr) isExpr() {}
func (CountStarExpr) isExpr() {}
func (CastExpr) isExpr() {}
func (ExtractExpr) isExpr() {}
func (CaseExpr) isExpr() {}
func (ParenExpr) isExpr() {}
func (ScalarSubQuery) isExpr() {}
func (ArraySubQuery) isExpr() {}
func (ExistsSubQuery) isExpr() {}
func (Param) isExpr() {}
func (Ident) isExpr() {}
func (Path) isExpr() {}
func (ArrayLiteral) isExpr() {}
func (TupleStructLiteral) isExpr() {}
func (TypelessStructLiteral) isExpr() {}
func (TypedStructLiteral) isExpr() {}
func (NullLiteral) isExpr() {}
func (BoolLiteral) isExpr() {}
func (IntLiteral) isExpr() {}
func (FloatLiteral) isExpr() {}
func (StringLiteral) isExpr() {}
func (BytesLiteral) isExpr() {}
func (DateLiteral) isExpr() {}
func (TimestampLiteral) isExpr() {}
func (NumericLiteral) isExpr() {}
func (JSONLiteral) isExpr() {}
func (NewConstructor) isExpr() {}
func (BracedNewConstructor) isExpr() {}
func (BracedConstructor) isExpr() {}

// Arg represents argument of function call.
type Arg interface {
Expand Down Expand Up @@ -221,6 +226,24 @@ func (UnnestInCondition) isInCondition() {}
func (SubQueryInCondition) isInCondition() {}
func (ValuesInCondition) isInCondition() {}

// TypelessStructLiteralArg represents an argument of typeless STRUCT literals.
type TypelessStructLiteralArg interface {
Node
isTypelessStructLiteralArg()
}

func (ExprArg) isTypelessStructLiteralArg() {}
func (Alias) isTypelessStructLiteralArg() {}

// NewConstructorArg represents an argument of NEW constructors.
type NewConstructorArg interface {
Node
isNewConstructorArg()
}

func (ExprArg) isNewConstructorArg() {}
func (Alias) isNewConstructorArg() {}

// Type represents type node.
type Type interface {
Node
Expand Down Expand Up @@ -607,7 +630,10 @@ type DotStar struct {
Expr Expr
}

// Alias is aliased expression by AS clause in SELECT result columns list.
// Alias is aliased expression by AS clause.
//
// Typically, this appears in SELECT result columns list, but this can appear in typeless STRUCT literals
// and NEW constructors.
//
// {{.Expr | sql}} {{.As | sql}}
type Alias struct {
Expand All @@ -622,16 +648,12 @@ type Alias struct {
//
// It is used in Alias node and some JoinExpr nodes.
//
// NOTE: Sometime keyword AS can be omited.
//
// In this case, it.token.Pos() == it.Alias.token.Pos(), so we can detect this.
//
// AS {{.Alias | sql}}
// {{if not .As.Invalid}}AS {{end}}{{.Alias | sql}}
type AsAlias struct {
// pos = As || Alias.pos
// end = Alias.end

As token.Pos // position of "AS" keyword
As token.Pos // position of "AS" keyword, optional

Alias *Ident
}
Expand Down Expand Up @@ -1376,22 +1398,45 @@ type ArrayLiteral struct {
Values []Expr
}

// StructLiteral is struct literal node.
// TupleStructLiteral is tuple syntax struct literal node.
//
// STRUCT{{if not (isnil .Fields)}}<{{.Fields | sqlJoin ","}}>{{end}}({{.Values | sqlJoin ","}})
type StructLiteral struct {
// pos = Struct || Lparen
// ({{.Values | sqlJoin ","}})
type TupleStructLiteral struct {
// pos = Lparen
// end = Rparen + 1

Struct token.Pos // position of "STRUCT"
Lparen, Rparen token.Pos // position of "(" and ")"

// NOTE: Distinguish nil from len(Fields) == 0 case.
// nil means type is not specified, or empty slice means this struct has 0 fields.
Values []Expr // len(Values) > 1
}

// TypedStructLiteral is typed struct literal node.
//
// STRUCT<{{.Fields | sqlJoin ","}}>({{.Values | sqlJoin ","}})
type TypedStructLiteral struct {
// pos = Struct
// end = Rparen + 1

Struct token.Pos // position of "STRUCT"
Rparen token.Pos // position of ")"

Fields []*StructField
Values []Expr
}

// TypelessStructLiteral is typeless struct literal node.
//
// STRUCT({{.Values | sqlJoin ","}})
type TypelessStructLiteral struct {
// pos = Struct
// end = Rparen + 1

Struct token.Pos // position of "STRUCT"
Rparen token.Pos // position of ")"

Values []TypelessStructLiteralArg
}

// NullLiteral is just NULL literal.
//
// NULL
Expand Down Expand Up @@ -1511,6 +1556,85 @@ type JSONLiteral struct {
Value *StringLiteral
}

// ================================================================================
//
// NEW constructors
//
// ================================================================================

// BracedConstructorFieldValue represents value part of fields in BracedNewConstructor.
type BracedConstructorFieldValue interface {
Node
isBracedConstructorFieldValue()
}

func (*BracedConstructor) isBracedConstructorFieldValue() {}
func (*BracedConstructorFieldValueExpr) isBracedConstructorFieldValue() {}

// NewConstructor represents NEW operator which creates a protocol buffer using a parenthesized list of arguments.
//
// NEW {{.Type | sql}} ({{.Args | sqlJoin ", "}})
type NewConstructor struct {
// pos = New
// end = Rparen + 1

New token.Pos
Type *NamedType

Args []NewConstructorArg

Rparen token.Pos
}

// BracedNewConstructor represents NEW operator which creates a protocol buffer using a map constructor.
//
// NEW {{.Type | sql}} {{"{"}}{{"}"}}
type BracedNewConstructor struct {
// pos = New
// end = Body.end

New token.Pos

Type *NamedType
Body *BracedConstructor
}

// BracedConstructor represents a single map constructor which is used in BracedNewConstructor.
// Actually, it is a top level Expr in syntax, but it is not permitted semantically in other place.
//
// {{"{"}}{{.Fields | sqlJoin ", "}}{{"}"}}
type BracedConstructor struct {
// pos = Lbrace
// end = Rbrace + 1

Lbrace, Rbrace token.Pos

Fields []*BracedConstructorField
}

// BracedConstructorField represents a single field in BracedConstructor.
//
// {{.Name | sql}} {{.Value | sql}}
type BracedConstructorField struct {
// pos = Name.pos
// end = Value.end

Name *Ident
Value BracedConstructorFieldValue
}

// BracedConstructorFieldValueExpr represents a field value node.
//
// : {{.Expr | sql}}
type BracedConstructorFieldValueExpr struct {
// pos = Colon
// end = Expr.end

Colon token.Pos

Expr Expr
}

// ================================================================================
//
// Type
Expand Down
2 changes: 1 addition & 1 deletion ast/ast_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ func TestExpr(t *testing.T) {
Expr(&Ident{}).isExpr()
Expr(&Path{}).isExpr()
Expr(&ArrayLiteral{}).isExpr()
Expr(&StructLiteral{}).isExpr()
Expr(&TypedStructLiteral{}).isExpr()
Expr(&NullLiteral{}).isExpr()
Expr(&BoolLiteral{}).isExpr()
Expr(&IntLiteral{}).isExpr()
Expand Down
64 changes: 60 additions & 4 deletions ast/pos.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading