Files
aego/script/checker/analysis.go
T

264 lines
5.0 KiB
Go

package checker
import (
"aego/script/abi"
"aego/script/ast"
"aego/script/diag"
"aego/script/resolver"
"aego/script/types"
)
type TypeAndValue struct {
Type *types.Type
Const *types.Const
Addr bool
}
type CallKind uint8
const (
CallFunc CallKind = iota
CallMethod
CallHost
CallHostMethod
CallLen
CallAppend
CallConvert
CallGetComponent
CallHasComponent
CallStart
CallEmit
CallConnect
CallDisconnect
CallConnected
CallCoStop
CallCoRunning
CallGetScript
CallScriptMethod
CallComponentMethod
CallHostConnect
)
type Call struct {
Kind CallKind
Func *Func
Module string
Name string
Sig abi.Signature
Component *abi.Component
Type *types.Type
Recv ast.Expr
Signal *ScriptSignal
Host *HostSignal
Handler *Func
HandlerRecv ast.Expr
Target string
}
type SelKind uint8
const (
SelField SelKind = iota
SelLane
SelPackage
SelEnumMember
SelComponentField
SelHostConst
SelSignal
SelScriptField
SelDataField
)
type Selection struct {
Kind SelKind
Field *types.Field
Object *resolver.Object
Value int64
Comp *abi.Field
Script *ScriptType
ScriptField *ScriptField
Signal *ScriptSignal
Data *types.Type
}
type Hints struct {
Min, Max, Step float64
HasMin, HasMax bool
Unit string
Display string
Tip string
Category string
Gizmo string
Space string
}
type ScriptField struct {
Name string
Former []string
Type *types.Type
Export bool
Persist bool
Hints Hints
Default *types.Const
Index int
Slot int
Decl *ast.ScriptVar
}
type ScriptSignal struct {
Name string
Params []*types.Type
Names []string
Index int
Script *ScriptType
Decl *ast.SignalDecl
}
type HostSignal struct {
Name string
Index int
Params []*types.Type
Comp *abi.Component
Handle string
}
type ScriptType struct {
Name string
Pkg string
FullName string
Former []string
Hidden bool
Pause uint8
Fields []*ScriptField
Signals []*ScriptSignal
Funcs []*Func
Methods map[string]*Func
Ready *Func
FixedUpdate *Func
Update *Func
Reloaded *Func
Events []*Func
Slots int
Decl *ast.ScriptDecl
scope *resolver.Scope
}
func (st *ScriptType) Field(name string) *ScriptField {
for _, f := range st.Fields {
if f.Name == name {
return f
}
}
return nil
}
func (st *ScriptType) Signal(name string) *ScriptSignal {
for _, s := range st.Signals {
if s.Name == name {
return s
}
}
return nil
}
func (st *ScriptType) IsEvent(f *Func) bool {
for _, e := range st.Events {
if e == f {
return true
}
}
return false
}
func (st *ScriptType) IsLifecycle(f *Func) bool {
return f != nil && (f == st.Ready || f == st.FixedUpdate || f == st.Update || f == st.Reloaded || st.IsEvent(f))
}
type Func struct {
Name string
Pkg string
Decl *ast.FuncDecl
Params []*resolver.Object
Result *types.Type
Script *ScriptType
Locals []*resolver.Object
}
func (f *Func) FullName() string {
if f.Script != nil {
return f.Script.FullName + "." + f.Name
}
return f.Pkg + "." + f.Name
}
type Package struct {
Path string
Res *resolver.Package
Funcs []*Func
Scripts []*ScriptType
Consts []*resolver.Object
Structs []*types.Type
Enums []*types.Type
Imports []string
}
type Reference struct {
Ident *ast.Ident
Object *resolver.Object
Def bool
}
type Analysis struct {
Packages map[string]*Package
Order []string
Symbols *resolver.Table
Types map[ast.Expr]TypeAndValue
Defs map[*ast.Ident]*resolver.Object
Uses map[*ast.Ident]*resolver.Object
Calls map[*ast.CallExpr]*Call
Selections map[*ast.SelectorExpr]*Selection
Composites map[*ast.CompositeLit]*types.Type
Coroutines map[*ast.FuncDecl]bool
Starts map[*ast.StartExpr]*Func
References []Reference
Diagnostics []diag.Diagnostic
Scripts []*ScriptType
Universe *types.Interner
Surface abi.Surface
scripts map[string]*ScriptType
}
func newAnalysis(tab *resolver.Table, s abi.Surface) *Analysis {
return &Analysis{
Packages: map[string]*Package{},
Order: tab.Order,
Symbols: tab,
Types: map[ast.Expr]TypeAndValue{},
Defs: map[*ast.Ident]*resolver.Object{},
Uses: map[*ast.Ident]*resolver.Object{},
Calls: map[*ast.CallExpr]*Call{},
Selections: map[*ast.SelectorExpr]*Selection{},
Composites: map[*ast.CompositeLit]*types.Type{},
Coroutines: map[*ast.FuncDecl]bool{},
Starts: map[*ast.StartExpr]*Func{},
Universe: types.NewInterner(),
Surface: s,
scripts: map[string]*ScriptType{},
}
}
func (a *Analysis) HasErrors() bool {
return diag.HasErrors(a.Diagnostics)
}
func (a *Analysis) TypeOf(e ast.Expr) *types.Type {
if tv, ok := a.Types[e]; ok {
return tv.Type
}
return types.Invalid
}
func (a *Analysis) ScriptByName(full string) *ScriptType {
return a.scripts[full]
}