package semantic

import (
	"encoding/json"
	"regexp"
	"time"

	"github.com/influxdata/flux/ast"
	"github.com/influxdata/flux/semantic/types"
)

type Node interface {
	node()
	NodeType() string
	Copy() Node

	Location() ast.SourceLocation

	json.Marshaler
}

type loc ast.SourceLocation

func (l loc) Location() ast.SourceLocation {
	return ast.SourceLocation(l)
}

func (*Package) node()           {}
func (*File) node()              {}
func (*Extern) node()            {}
func (*ExternBlock) node()       {}
func (*Block) node()             {}
func (*PackageClause) node()     {}
func (*ImportDeclaration) node() {}

func (*OptionStatement) node()            {}
func (*BuiltinStatement) node()           {}
func (*TestStatement) node()              {}
func (*ExpressionStatement) node()        {}
func (*ReturnStatement) node()            {}
func (*MemberAssignment) node()           {}
func (*NativeVariableAssignment) node()   {}
func (*ExternalVariableAssignment) node() {}

func (*StringExpression) node()      {}
func (*ArrayExpression) node()       {}
func (*FunctionExpression) node()    {}
func (*BinaryExpression) node()      {}
func (*CallExpression) node()        {}
func (*ConditionalExpression) node() {}
func (*IdentifierExpression) node()  {}
func (*LogicalExpression) node()     {}
func (*MemberExpression) node()      {}
func (*IndexExpression) node()       {}
func (*ObjectExpression) node()      {}
func (*UnaryExpression) node()       {}

func (*Identifier) node() {}
func (*Property) node()   {}

func (*TextPart) node()         {}
func (*InterpolatedPart) node() {}

func (*FunctionParameters) node() {}
func (*FunctionParameter) node()  {}
func (*FunctionBlock) node()      {}

func (*BooleanLiteral) node()         {}
func (*DateTimeLiteral) node()        {}
func (*DurationLiteral) node()        {}
func (*FloatLiteral) node()           {}
func (*IntegerLiteral) node()         {}
func (*StringLiteral) node()          {}
func (*RegexpLiteral) node()          {}
func (*UnsignedIntegerLiteral) node() {}

type Statement interface {
	Node
	stmt()
}

func (*OptionStatement) stmt()          {}
func (*BuiltinStatement) stmt()         {}
func (*TestStatement) stmt()            {}
func (*ExpressionStatement) stmt()      {}
func (*ReturnStatement) stmt()          {}
func (*NativeVariableAssignment) stmt() {}
func (*MemberAssignment) stmt()         {}

type Assignment interface {
	Statement
	assignment()
}

func (*MemberAssignment) assignment()         {}
func (*NativeVariableAssignment) assignment() {}

type Expression interface {
	Node
	expression()
	TypeOf() *types.MonoType
}

func (*StringExpression) expression()       {}
func (*ArrayExpression) expression()        {}
func (*BinaryExpression) expression()       {}
func (*BooleanLiteral) expression()         {}
func (*CallExpression) expression()         {}
func (*ConditionalExpression) expression()  {}
func (*DateTimeLiteral) expression()        {}
func (*DurationLiteral) expression()        {}
func (*FloatLiteral) expression()           {}
func (*FunctionExpression) expression()     {}
func (*IdentifierExpression) expression()   {}
func (*IntegerLiteral) expression()         {}
func (*LogicalExpression) expression()      {}
func (*MemberExpression) expression()       {}
func (*IndexExpression) expression()        {}
func (*ObjectExpression) expression()       {}
func (*RegexpLiteral) expression()          {}
func (*StringLiteral) expression()          {}
func (*UnaryExpression) expression()        {}
func (*UnsignedIntegerLiteral) expression() {}

type Literal interface {
	Expression
	literal()
}

func (*BooleanLiteral) literal()         {}
func (*DateTimeLiteral) literal()        {}
func (*DurationLiteral) literal()        {}
func (*FloatLiteral) literal()           {}
func (*IntegerLiteral) literal()         {}
func (*RegexpLiteral) literal()          {}
func (*StringLiteral) literal()          {}
func (*UnsignedIntegerLiteral) literal() {}

type PropertyKey interface {
	Node
	Key() string
}

func (n *Identifier) Key() string {
	return n.Name
}
func (n *StringLiteral) Key() string {
	return n.Value
}

type Package struct {
	loc `json:"-"`

	Package string  `json:"package"`
	Files   []*File `json:"files"`
}

func (*Package) NodeType() string { return "Package" }

func (p *Package) Copy() Node {
	if p == nil {
		return p
	}
	np := new(Package)
	*np = *p

	if len(p.Files) > 0 {
		np.Files = make([]*File, len(p.Files))
		for i, f := range p.Files {
			np.Files[i] = f.Copy().(*File)
		}
	}

	return np
}

type File struct {
	loc `json:"-"`

	Package *PackageClause       `json:"package"`
	Imports []*ImportDeclaration `json:"imports"`
	Body    []Statement          `json:"body"`
}

func (*File) NodeType() string { return "File" }

func (p *File) Copy() Node {
	if p == nil {
		return p
	}
	np := new(File)
	*np = *p

	if len(p.Body) > 0 {
		np.Body = make([]Statement, len(p.Body))
		for i, s := range p.Body {
			np.Body[i] = s.Copy().(Statement)
		}
	}

	return np
}

type PackageClause struct {
	loc `json:"-"`

	Name *Identifier `json:"name"`
}

func (*PackageClause) NodeType() string { return "PackageClause" }

func (p *PackageClause) Copy() Node {
	if p == nil {
		return p
	}
	np := new(PackageClause)
	*np = *p

	np.Name = p.Name.Copy().(*Identifier)

	return np
}

type ImportDeclaration struct {
	loc `json:"-"`

	As   *Identifier    `json:"as"`
	Path *StringLiteral `json:"path"`
}

func (*ImportDeclaration) NodeType() string { return "ImportDeclaration" }

func (d *ImportDeclaration) Copy() Node {
	if d == nil {
		return d
	}
	nd := new(ImportDeclaration)
	*nd = *d

	nd.As = d.As.Copy().(*Identifier)
	nd.Path = d.Path.Copy().(*StringLiteral)

	return nd
}

type Block struct {
	loc `json:"-"`

	Body []Statement `json:"body"`
}

func (*Block) NodeType() string { return "Block" }

func (s *Block) ReturnStatement() *ReturnStatement {
	return s.Body[len(s.Body)-1].(*ReturnStatement)
}

func (s *Block) Copy() Node {
	if s == nil {
		return s
	}
	ns := new(Block)
	*ns = *s

	if len(s.Body) > 0 {
		ns.Body = make([]Statement, len(s.Body))
		for i, stmt := range s.Body {
			ns.Body[i] = stmt.Copy().(Statement)
		}
	}

	return ns
}

type OptionStatement struct {
	loc `json:"-"`

	Assignment Assignment `json:"assignment"`
}

func (s *OptionStatement) NodeType() string { return "OptionStatement" }

func (s *OptionStatement) Copy() Node {
	if s == nil {
		return s
	}
	ns := new(OptionStatement)
	*ns = *s

	ns.Assignment = s.Assignment.Copy().(Assignment)

	return ns
}

type BuiltinStatement struct {
	loc `json:"-"`

	ID *Identifier `json:"id"`
}

func (s *BuiltinStatement) NodeType() string { return "BuiltinStatement" }

func (s *BuiltinStatement) Copy() Node {
	if s == nil {
		return s
	}
	ns := new(BuiltinStatement)
	*ns = *s

	ns.ID = s.ID.Copy().(*Identifier)

	return ns
}

type TestStatement struct {
	loc `json:"-"`

	Assignment *NativeVariableAssignment `json:"assignment"`
}

func (s *TestStatement) NodeType() string { return "TestStatement" }

func (s *TestStatement) Copy() Node {
	if s == nil {
		return s
	}
	ns := new(TestStatement)
	*ns = *s

	ns.Assignment = s.Assignment.Copy().(*NativeVariableAssignment)

	return ns
}

type ExpressionStatement struct {
	loc `json:"-"`

	Expression Expression `json:"expression"`
}

func (*ExpressionStatement) NodeType() string { return "ExpressionStatement" }

func (s *ExpressionStatement) Copy() Node {
	if s == nil {
		return s
	}
	ns := new(ExpressionStatement)
	*ns = *s

	ns.Expression = s.Expression.Copy().(Expression)

	return ns
}

type ReturnStatement struct {
	loc `json:"-"`

	Argument Expression `json:"argument"`
}

func (*ReturnStatement) NodeType() string { return "ReturnStatement" }

func (s *ReturnStatement) Copy() Node {
	if s == nil {
		return s
	}
	ns := new(ReturnStatement)
	*ns = *s

	ns.Argument = s.Argument.Copy().(Expression)

	return ns
}

type NativeVariableAssignment struct {
	loc `json:"-"`

	Identifier *Identifier `json:"identifier"`
	Init       Expression  `json:"init"`

	Typ *types.PolyType `json:"polytype,omitempty"`
}

func (*NativeVariableAssignment) NodeType() string { return "NativeVariableAssignment" }

func (s *NativeVariableAssignment) Copy() Node {
	if s == nil {
		return s
	}
	ns := new(NativeVariableAssignment)
	*ns = *s

	ns.Identifier = s.Identifier.Copy().(*Identifier)

	if s.Init != nil {
		ns.Init = s.Init.Copy().(Expression)
	}

	return ns
}

type MemberAssignment struct {
	loc `json:"-"`

	Member *MemberExpression `json:"member"`
	Init   Expression        `json:"init"`
}

func (*MemberAssignment) NodeType() string { return "MemberAssignment" }

func (s *MemberAssignment) Copy() Node {
	if s == nil {
		return s
	}
	ns := new(MemberAssignment)
	*ns = *s

	if s.Member != nil {
		ns.Member = s.Member.Copy().(*MemberExpression)
	}
	if s.Init != nil {
		ns.Init = s.Init.Copy().(Expression)
	}

	return ns
}

// Extern is a node that represents a node with a set of external assignments defined.
type Extern struct {
	loc `json:"-"`

	Assignments []*ExternalVariableAssignment `json:"assignments"`
	Block       *ExternBlock                  `json:"block"`
}

func (*Extern) NodeType() string { return "Extern" }

func (e *Extern) Copy() Node {
	if e == nil {
		return e
	}
	ne := new(Extern)
	*ne = *e

	if len(e.Assignments) > 0 {
		ne.Assignments = make([]*ExternalVariableAssignment, len(e.Assignments))
		for i, d := range e.Assignments {
			ne.Assignments[i] = d.Copy().(*ExternalVariableAssignment)
		}
	}

	ne.Block = e.Block.Copy().(*ExternBlock)

	return ne
}

// ExternalVariableAssignment represents an externaly defined identifier and its type.
type ExternalVariableAssignment struct {
	loc `json:"-"`

	Identifier *Identifier `json:"identifier"`
	ExternType PolyType    `json:""`
}

func (*ExternalVariableAssignment) NodeType() string { return "ExternalVariableAssignment" }

func (s *ExternalVariableAssignment) Copy() Node {
	if s == nil {
		return s
	}
	ns := new(ExternalVariableAssignment)
	*ns = *s

	ns.Identifier = s.Identifier.Copy().(*Identifier)

	return ns
}

// ExternBlock is a node that represents a node with a set of external declarations defined.
type ExternBlock struct {
	loc `json:"-"`

	Node Node
}

func (*ExternBlock) NodeType() string { return "ExternBlock" }

func (e *ExternBlock) Copy() Node {
	if e == nil {
		return e
	}
	ne := new(ExternBlock)
	*ne = *e

	if ne.Node != nil {
		ne.Node = e.Node.Copy()
	}

	return ne
}

type StringExpression struct {
	loc `json:"-"`

	Parts []StringExpressionPart `json:"parts"`

	typ *types.MonoType
}

func (*StringExpression) NodeType() string {
	return "StringExpression"
}
func (e *StringExpression) Copy() Node {
	if e == nil {
		return e
	}
	ne := new(StringExpression)
	*ne = *e

	parts := make([]StringExpressionPart, len(e.Parts))
	for i, p := range e.Parts {
		parts[i] = p.Copy().(StringExpressionPart)
	}
	ne.Parts = parts
	return ne
}
func (e *StringExpression) TypeOf() *types.MonoType {
	return e.typ
}

type StringExpressionPart interface {
	Node

	stringPart()
}

func (*TextPart) stringPart()         {}
func (*InterpolatedPart) stringPart() {}

type TextPart struct {
	loc   `json:"-"`
	Value string `json:"value"`
}

func (*TextPart) NodeType() string {
	return "TextPart"
}
func (p *TextPart) Copy() Node {
	if p == nil {
		return p
	}
	np := new(TextPart)
	*np = *p
	return np
}

type InterpolatedPart struct {
	loc        `json:"-"`
	Expression Expression `json:"expression"`
}

func (*InterpolatedPart) NodeType() string {
	return "InterpolatedPart"
}
func (p *InterpolatedPart) Copy() Node {
	if p == nil {
		return p
	}
	np := new(InterpolatedPart)
	*np = *p

	if p.Expression != nil {
		np.Expression = p.Expression.Copy().(Expression)
	}
	return np
}

type ArrayExpression struct {
	loc `json:"-"`

	Elements []Expression `json:"elements"`

	typ *types.MonoType
}

func (*ArrayExpression) NodeType() string { return "ArrayExpression" }

func (e *ArrayExpression) Copy() Node {
	if e == nil {
		return e
	}
	ne := new(ArrayExpression)
	*ne = *e

	if len(e.Elements) > 0 {
		ne.Elements = make([]Expression, len(e.Elements))
		for i, elem := range e.Elements {
			ne.Elements[i] = elem.Copy().(Expression)
		}
	}

	return ne
}
func (e *ArrayExpression) TypeOf() *types.MonoType {
	return e.typ
}

// FunctionExpression represents the definition of a function
type FunctionExpression struct {
	loc `json:"-"`

	Defaults *ObjectExpression `json:"defaults,omitempty"`
	Block    *FunctionBlock    `json:"block"`

	typ *types.MonoType
}

func (*FunctionExpression) NodeType() string { return "FunctionExpression" }

func (e *FunctionExpression) Copy() Node {
	if e == nil {
		return e
	}
	ne := new(FunctionExpression)
	*ne = *e

	if e.Defaults != nil {
		ne.Defaults = e.Defaults.Copy().(*ObjectExpression)
	}
	ne.Block = e.Block.Copy().(*FunctionBlock)

	return ne
}
func (e *FunctionExpression) TypeOf() *types.MonoType {
	return e.typ
}

// FunctionBlock represents the function parameters and the function body.
type FunctionBlock struct {
	loc `json:"-"`

	Parameters *FunctionParameters `json:"parameters"`
	Body       Node                `json:"body"`
}

func (*FunctionBlock) NodeType() string { return "FunctionBlock" }
func (b *FunctionBlock) Copy() Node {
	if b == nil {
		return b
	}
	nb := new(FunctionBlock)
	*nb = *b

	nb.Body = b.Body.Copy()

	return nb
}

// FunctionParameters represents the list of function parameters and which if any parameter is the pipe parameter.
type FunctionParameters struct {
	loc `json:"-"`

	List []*FunctionParameter `json:"list"`
	Pipe *Identifier          `json:"pipe"`
}

func (*FunctionParameters) NodeType() string { return "FunctionParameters" }

func (p *FunctionParameters) Copy() Node {
	if p == nil {
		return p
	}
	np := new(FunctionParameters)
	*np = *p

	if len(p.List) > 0 {
		np.List = make([]*FunctionParameter, len(p.List))
		for i, k := range p.List {
			np.List[i] = k.Copy().(*FunctionParameter)
		}
	}
	if p.Pipe != nil {
		np.Pipe = p.Pipe.Copy().(*Identifier)
	}

	return np
}

// FunctionParameter represents a function parameter.
type FunctionParameter struct {
	loc `json:"-"`

	Key *Identifier `json:"key"`
}

func (*FunctionParameter) NodeType() string { return "FunctionParameter" }

func (p *FunctionParameter) Copy() Node {
	if p == nil {
		return p
	}
	np := new(FunctionParameter)
	*np = *p

	np.Key = p.Key.Copy().(*Identifier)

	return np
}

type BinaryExpression struct {
	loc `json:"-"`

	Operator ast.OperatorKind `json:"operator"`
	Left     Expression       `json:"left"`
	Right    Expression       `json:"right"`

	typ *types.MonoType
}

func (*BinaryExpression) NodeType() string { return "BinaryExpression" }

func (e *BinaryExpression) Copy() Node {
	if e == nil {
		return e
	}
	ne := new(BinaryExpression)
	*ne = *e

	ne.Left = e.Left.Copy().(Expression)
	ne.Right = e.Right.Copy().(Expression)

	return ne
}
func (e *BinaryExpression) TypeOf() *types.MonoType {
	return e.typ
}

type CallExpression struct {
	loc `json:"-"`

	Callee    Expression        `json:"callee"`
	Arguments *ObjectExpression `json:"arguments"`
	Pipe      Expression        `json:"pipe,omitempty"`

	typ *types.MonoType
}

func (*CallExpression) NodeType() string { return "CallExpression" }

func (e *CallExpression) Copy() Node {
	if e == nil {
		return e
	}
	ne := new(CallExpression)
	*ne = *e

	ne.Callee = e.Callee.Copy().(Expression)
	ne.Arguments = e.Arguments.Copy().(*ObjectExpression)
	if e.Pipe != nil {
		ne.Pipe = e.Pipe.Copy().(Expression)
	}

	return ne
}
func (e *CallExpression) TypeOf() *types.MonoType {
	return e.typ
}

type ConditionalExpression struct {
	loc `json:"-"`

	Test       Expression `json:"test"`
	Alternate  Expression `json:"alternate"`
	Consequent Expression `json:"consequent"`

	typ *types.MonoType
}

func (*ConditionalExpression) NodeType() string { return "ConditionalExpression" }

func (e *ConditionalExpression) Copy() Node {
	if e == nil {
		return e
	}
	ne := new(ConditionalExpression)
	*ne = *e

	ne.Test = e.Test.Copy().(Expression)
	ne.Alternate = e.Alternate.Copy().(Expression)
	ne.Consequent = e.Consequent.Copy().(Expression)

	return ne
}
func (e *ConditionalExpression) TypeOf() *types.MonoType {
	return e.typ
}

type LogicalExpression struct {
	loc `json:"-"`

	Operator ast.LogicalOperatorKind `json:"operator"`
	Left     Expression              `json:"left"`
	Right    Expression              `json:"right"`

	typ *types.MonoType
}

func (*LogicalExpression) NodeType() string { return "LogicalExpression" }

func (e *LogicalExpression) Copy() Node {
	if e == nil {
		return e
	}
	ne := new(LogicalExpression)
	*ne = *e

	ne.Left = e.Left.Copy().(Expression)
	ne.Right = e.Right.Copy().(Expression)

	return ne
}
func (e *LogicalExpression) TypeOf() *types.MonoType {
	return e.typ
}

type MemberExpression struct {
	loc `json:"-"`

	Object   Expression `json:"object"`
	Property string     `json:"property"`

	typ *types.MonoType
}

func (*MemberExpression) NodeType() string { return "MemberExpression" }

func (e *MemberExpression) Copy() Node {
	if e == nil {
		return e
	}
	ne := new(MemberExpression)
	*ne = *e

	ne.Object = e.Object.Copy().(Expression)

	return ne
}
func (e *MemberExpression) TypeOf() *types.MonoType {
	return e.typ
}

type IndexExpression struct {
	loc `json:"-"`

	Array Expression `json:"array"`
	Index Expression `json:"index"`

	typ *types.MonoType
}

func (*IndexExpression) NodeType() string { return "IndexExpression" }

func (e *IndexExpression) Copy() Node {
	if e == nil {
		return e
	}
	ne := new(IndexExpression)
	*ne = *e
	ne.Array = e.Array.Copy().(Expression)
	ne.Index = e.Index.Copy().(Expression)
	return ne
}
func (e *IndexExpression) TypeOf() *types.MonoType {
	return e.typ
}

type ObjectExpression struct {
	loc `json:"-"`

	With       *IdentifierExpression `json:"with,omitempty"`
	Properties []*Property           `json:"properties"`

	typ *types.MonoType
}

func (*ObjectExpression) NodeType() string { return "ObjectExpression" }

func (e *ObjectExpression) Copy() Node {
	if e == nil {
		return e
	}
	ne := new(ObjectExpression)
	*ne = *e

	ne.With = e.With.Copy().(*IdentifierExpression)

	if len(e.Properties) > 0 {
		ne.Properties = make([]*Property, len(e.Properties))
		for i, prop := range e.Properties {
			ne.Properties[i] = prop.Copy().(*Property)
		}
	}

	return ne
}
func (e *ObjectExpression) TypeOf() *types.MonoType {
	return e.typ
}

type UnaryExpression struct {
	loc `json:"-"`

	Operator ast.OperatorKind `json:"operator"`
	Argument Expression       `json:"argument"`

	typ *types.MonoType
}

func (*UnaryExpression) NodeType() string { return "UnaryExpression" }

func (e *UnaryExpression) Copy() Node {
	if e == nil {
		return e
	}
	ne := new(UnaryExpression)
	*ne = *e

	ne.Argument = e.Argument.Copy().(Expression)

	return ne
}
func (e *UnaryExpression) TypeOf() *types.MonoType {
	return e.typ
}

type Property struct {
	loc `json:"-"`

	Key   PropertyKey `json:"key"`
	Value Expression  `json:"value"`
}

func (*Property) NodeType() string { return "Property" }

func (p *Property) Copy() Node {
	if p == nil {
		return p
	}
	np := new(Property)
	*np = *p

	np.Value = p.Value.Copy().(Expression)

	return np
}

type IdentifierExpression struct {
	loc `json:"-"`

	Name string `json:"name"`

	typ *types.MonoType
}

func (*IdentifierExpression) NodeType() string { return "IdentifierExpression" }

func (e *IdentifierExpression) Copy() Node {
	if e == nil {
		return e
	}
	ne := new(IdentifierExpression)
	*ne = *e

	return ne
}
func (e *IdentifierExpression) TypeOf() *types.MonoType {
	return e.typ
}

type Identifier struct {
	loc `json:"-"`

	Name string `json:"name"`
}

func (*Identifier) NodeType() string { return "Identifier" }

func (i *Identifier) Copy() Node {
	if i == nil {
		return i
	}
	ni := new(Identifier)
	*ni = *i

	return ni
}

type BooleanLiteral struct {
	loc `json:"-"`

	Value bool `json:"value"`

	typ *types.MonoType
}

func (*BooleanLiteral) NodeType() string { return "BooleanLiteral" }

func (l *BooleanLiteral) Copy() Node {
	if l == nil {
		return l
	}
	nl := new(BooleanLiteral)
	*nl = *l

	return nl
}
func (e *BooleanLiteral) TypeOf() *types.MonoType {
	return e.typ
}

type DateTimeLiteral struct {
	loc `json:"-"`

	Value time.Time `json:"value"`

	typ *types.MonoType
}

func (*DateTimeLiteral) NodeType() string { return "DateTimeLiteral" }

func (l *DateTimeLiteral) Copy() Node {
	if l == nil {
		return l
	}
	nl := new(DateTimeLiteral)
	*nl = *l

	return nl
}
func (e *DateTimeLiteral) TypeOf() *types.MonoType {
	return e.typ
}

type DurationLiteral struct {
	loc `json:"-"`

	Values []ast.Duration `json:"values"`

	typ *types.MonoType
}

func (*DurationLiteral) NodeType() string { return "DurationLiteral" }

func (l *DurationLiteral) Copy() Node {
	if l == nil {
		return l
	}
	nl := new(DurationLiteral)
	*nl = *l

	return nl
}
func (e *DurationLiteral) TypeOf() *types.MonoType {
	return e.typ
}

type IntegerLiteral struct {
	loc `json:"-"`

	Value int64 `json:"value"`

	typ *types.MonoType
}

func (*IntegerLiteral) NodeType() string { return "IntegerLiteral" }

func (l *IntegerLiteral) Copy() Node {
	if l == nil {
		return l
	}
	nl := new(IntegerLiteral)
	*nl = *l

	return nl
}
func (e *IntegerLiteral) TypeOf() *types.MonoType {
	return e.typ
}

type FloatLiteral struct {
	loc `json:"-"`

	Value float64 `json:"value"`

	typ *types.MonoType
}

func (*FloatLiteral) NodeType() string { return "FloatLiteral" }

func (l *FloatLiteral) Copy() Node {
	if l == nil {
		return l
	}
	nl := new(FloatLiteral)
	*nl = *l

	return nl
}
func (e *FloatLiteral) TypeOf() *types.MonoType {
	return e.typ
}

type RegexpLiteral struct {
	loc `json:"-"`

	Value *regexp.Regexp `json:"value"`

	typ *types.MonoType
}

func (*RegexpLiteral) NodeType() string { return "RegexpLiteral" }

func (l *RegexpLiteral) Copy() Node {
	if l == nil {
		return l
	}
	nl := new(RegexpLiteral)
	*nl = *l

	nl.Value = l.Value

	return nl
}
func (e *RegexpLiteral) TypeOf() *types.MonoType {
	return e.typ
}

type StringLiteral struct {
	loc `json:"-"`

	Value string `json:"value"`

	typ *types.MonoType
}

func (*StringLiteral) NodeType() string { return "StringLiteral" }

func (l *StringLiteral) Copy() Node {
	if l == nil {
		return l
	}
	nl := new(StringLiteral)
	*nl = *l

	return nl
}
func (e *StringLiteral) TypeOf() *types.MonoType {
	return e.typ
}

type UnsignedIntegerLiteral struct {
	loc `json:"-"`

	Value uint64 `json:"value"`

	typ *types.MonoType
}

func (*UnsignedIntegerLiteral) NodeType() string { return "UnsignedIntegerLiteral" }

func (l *UnsignedIntegerLiteral) Copy() Node {
	if l == nil {
		return l
	}
	nl := new(UnsignedIntegerLiteral)
	*nl = *l

	return nl
}
func (e *UnsignedIntegerLiteral) TypeOf() *types.MonoType {
	return e.typ
}
