package parse import ( "github.com/goplus/llgo/c" "github.com/goplus/llgo/c/cjson" "github.com/goplus/llgo/chore/llcppg/ast" ) func MarshalASTFiles(files map[string]*ast.File) *cjson.JSON { root := cjson.Object() for path, file := range files { root.SetItem(c.AllocaCStr(path), MarshalASTFile(file)) } return root } func MarshalDeclList(list []ast.Decl) *cjson.JSON { if list == nil { return cjson.Null() } root := cjson.Array() for _, item := range list { root.AddItem(MarshalASTDecl(item)) } return root } func MarshalFieldList(list []*ast.Field) *cjson.JSON { if list == nil { return cjson.Null() } root := cjson.Array() for _, item := range list { root.AddItem(MarshalASTExpr(item)) } return root } func MarshalIncludeList(list []*ast.Include) *cjson.JSON { if list == nil { return cjson.Null() } root := cjson.Array() for _, item := range list { include := cjson.Object() include.SetItem(c.Str("_Type"), stringField("Include")) include.SetItem(c.Str("Path"), stringField(item.Path)) root.AddItem(include) } return root } func MarshalMacroList(list []*ast.Macro) *cjson.JSON { if list == nil { return cjson.Null() } root := cjson.Array() for _, item := range list { macro := cjson.Object() macro.SetItem(c.Str("_Type"), stringField("Macro")) macro.SetItem(c.Str("Name"), stringField(item.Name)) macro.SetItem(c.Str("Tokens"), MarshalTokenList(item.Tokens)) root.AddItem(macro) } return root } func MarshalTokenList(list []*ast.Token) *cjson.JSON { if list == nil { return cjson.Null() } root := cjson.Array() for _, item := range list { root.AddItem(MarshalToken(item)) } return root } func MarshalIdentList(list []*ast.Ident) *cjson.JSON { if list == nil { return cjson.Null() } root := cjson.Array() for _, item := range list { root.AddItem(MarshalASTExpr(item)) } return root } func MarshalASTFile(file *ast.File) *cjson.JSON { root := cjson.Object() root.SetItem(c.Str("_Type"), stringField("File")) root.SetItem(c.Str("decls"), MarshalDeclList(file.Decls)) root.SetItem(c.Str("includes"), MarshalIncludeList(file.Includes)) root.SetItem(c.Str("macros"), MarshalMacroList(file.Macros)) return root } func MarshalToken(tok *ast.Token) *cjson.JSON { root := cjson.Object() root.SetItem(c.Str("_Type"), stringField("Token")) root.SetItem(c.Str("Token"), numberField(uint(tok.Token))) root.SetItem(c.Str("Lit"), stringField(tok.Lit)) return root } func MarshalASTDecl(decl ast.Decl) *cjson.JSON { if decl == nil { return cjson.Null() } root := cjson.Object() switch d := decl.(type) { case *ast.EnumTypeDecl: root.SetItem(c.Str("_Type"), stringField("EnumTypeDecl")) MarshalASTDeclBase(d.DeclBase, root) root.SetItem(c.Str("Name"), MarshalASTExpr(d.Name)) root.SetItem(c.Str("Type"), MarshalASTExpr(d.Type)) case *ast.TypedefDecl: root.SetItem(c.Str("_Type"), stringField("TypedefDecl")) MarshalASTDeclBase(d.DeclBase, root) root.SetItem(c.Str("Name"), MarshalASTExpr(d.Name)) root.SetItem(c.Str("Type"), MarshalASTExpr(d.Type)) case *ast.FuncDecl: root.SetItem(c.Str("_Type"), stringField("FuncDecl")) MarshalASTDeclBase(d.DeclBase, root) root.SetItem(c.Str("Name"), MarshalASTExpr(d.Name)) root.SetItem(c.Str("Type"), MarshalASTExpr(d.Type)) root.SetItem(c.Str("IsInline"), boolField(d.IsInline)) root.SetItem(c.Str("IsStatic"), boolField(d.IsStatic)) root.SetItem(c.Str("IsConst"), boolField(d.IsConst)) root.SetItem(c.Str("IsExplicit"), boolField(d.IsExplicit)) root.SetItem(c.Str("IsConstructor"), boolField(d.IsConstructor)) root.SetItem(c.Str("IsDestructor"), boolField(d.IsDestructor)) root.SetItem(c.Str("IsVirtual"), boolField(d.IsVirtual)) root.SetItem(c.Str("IsOverride"), boolField(d.IsOverride)) case *ast.TypeDecl: root.SetItem(c.Str("_Type"), stringField("TypeDecl")) MarshalASTDeclBase(d.DeclBase, root) root.SetItem(c.Str("Name"), MarshalASTExpr(d.Name)) root.SetItem(c.Str("Type"), MarshalASTExpr(d.Type)) } return root } func MarshalASTDeclBase(decl ast.DeclBase, root *cjson.JSON) { loc := cjson.Object() loc.SetItem(c.Str("_Type"), stringField("Location")) loc.SetItem(c.Str("File"), stringField(decl.Loc.File)) root.SetItem(c.Str("Loc"), loc) root.SetItem(c.Str("Doc"), MarshalASTExpr(decl.Doc)) root.SetItem(c.Str("Parent"), MarshalASTExpr(decl.Parent)) } func MarshalASTExpr(t ast.Expr) *cjson.JSON { if t == nil { return cjson.Null() } root := cjson.Object() switch d := t.(type) { case *ast.EnumType: root.SetItem(c.Str("_Type"), stringField("EnumType")) items := cjson.Array() for _, e := range d.Items { items.AddItem(MarshalASTExpr(e)) } root.SetItem(c.Str("Items"), items) case *ast.EnumItem: root.SetItem(c.Str("_Type"), stringField("EnumItem")) root.SetItem(c.Str("Name"), MarshalASTExpr(d.Name)) root.SetItem(c.Str("Value"), MarshalASTExpr(d.Value)) case *ast.RecordType: root.SetItem(c.Str("_Type"), stringField("RecordType")) root.SetItem(c.Str("Tag"), numberField(uint(d.Tag))) root.SetItem(c.Str("Fields"), MarshalASTExpr(d.Fields)) methods := cjson.Array() for _, m := range d.Methods { methods.AddItem(MarshalASTDecl(m)) } root.SetItem(c.Str("Methods"), methods) case *ast.FuncType: root.SetItem(c.Str("_Type"), stringField("FuncType")) root.SetItem(c.Str("Params"), MarshalASTExpr(d.Params)) root.SetItem(c.Str("Ret"), MarshalASTExpr(d.Ret)) case *ast.FieldList: root.SetItem(c.Str("_Type"), stringField("FieldList")) root.SetItem(c.Str("List"), MarshalFieldList(d.List)) case *ast.Field: root.SetItem(c.Str("_Type"), stringField("Field")) root.SetItem(c.Str("Type"), MarshalASTExpr(d.Type)) root.SetItem(c.Str("Doc"), MarshalASTExpr(d.Doc)) root.SetItem(c.Str("Comment"), MarshalASTExpr(d.Comment)) root.SetItem(c.Str("IsStatic"), boolField(d.IsStatic)) root.SetItem(c.Str("Access"), numberField(uint(d.Access))) root.SetItem(c.Str("Names"), MarshalIdentList(d.Names)) case *ast.Variadic: root.SetItem(c.Str("_Type"), stringField("Variadic")) case *ast.Ident: root.SetItem(c.Str("_Type"), stringField("Ident")) if d == nil { return cjson.Null() } root.SetItem(c.Str("Name"), stringField(d.Name)) case *ast.TagExpr: root.SetItem(c.Str("_Type"), stringField("TagExpr")) root.SetItem(c.Str("Name"), MarshalASTExpr(d.Name)) root.SetItem(c.Str("Tag"), numberField(uint(d.Tag))) case *ast.BasicLit: root.SetItem(c.Str("_Type"), stringField("BasicLit")) root.SetItem(c.Str("Kind"), numberField(uint(d.Kind))) root.SetItem(c.Str("Value"), stringField(d.Value)) case *ast.LvalueRefType: root.SetItem(c.Str("_Type"), stringField("LvalueRefType")) root.SetItem(c.Str("X"), MarshalASTExpr(d.X)) case *ast.RvalueRefType: root.SetItem(c.Str("_Type"), stringField("RvalueRefType")) root.SetItem(c.Str("X"), MarshalASTExpr(d.X)) case *ast.PointerType: root.SetItem(c.Str("_Type"), stringField("PointerType")) root.SetItem(c.Str("X"), MarshalASTExpr(d.X)) case *ast.ArrayType: root.SetItem(c.Str("_Type"), stringField("ArrayType")) root.SetItem(c.Str("Elt"), MarshalASTExpr(d.Elt)) root.SetItem(c.Str("Len"), MarshalASTExpr(d.Len)) case *ast.BuiltinType: root.SetItem(c.Str("_Type"), stringField("BuiltinType")) root.SetItem(c.Str("Kind"), numberField(uint(d.Kind))) root.SetItem(c.Str("Flags"), numberField(uint(d.Flags))) case *ast.Comment: root.SetItem(c.Str("_Type"), stringField("Comment")) if d == nil { return cjson.Null() } root.SetItem(c.Str("Text"), stringField(d.Text)) case *ast.CommentGroup: root.SetItem(c.Str("_Type"), stringField("CommentGroup")) if d == nil { return cjson.Null() } list := cjson.Array() for _, c := range d.List { list.AddItem(MarshalASTExpr(c)) } root.SetItem(c.Str("List"), list) case *ast.ScopingExpr: root.SetItem(c.Str("_Type"), stringField("ScopingExpr")) root.SetItem(c.Str("X"), MarshalASTExpr(d.X)) root.SetItem(c.Str("Parent"), MarshalASTExpr(d.Parent)) default: return cjson.Null() } return root } func stringField(s string) *cjson.JSON { return cjson.String(c.AllocaCStr(s)) } func numberField(n uint) *cjson.JSON { return cjson.Number(float64(n)) } func boolField(b bool) *cjson.JSON { if b { return cjson.True() } return cjson.False() }