Repository URL to install this package:
Version:
1.3.6-1 ▾
|
/*
* Copyright (c) 2022 The GoPlus Authors (goplus.org). All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package togo
import (
"go/ast"
"go/token"
"log"
"reflect"
gopast "github.com/goplus/gop/ast"
goptoken "github.com/goplus/gop/token"
)
// ----------------------------------------------------------------------------
func goExpr(val gopast.Expr) ast.Expr {
if val == nil {
return nil
}
switch v := val.(type) {
case *gopast.Ident:
return goIdent(v)
case *gopast.SelectorExpr:
return &ast.SelectorExpr{
X: goExpr(v.X),
Sel: goIdent(v.Sel),
}
case *gopast.SliceExpr:
return &ast.SliceExpr{
X: goExpr(v.X),
Lbrack: v.Lbrack,
Low: goExpr(v.Low),
High: goExpr(v.High),
Max: goExpr(v.Max),
Slice3: v.Slice3,
Rbrack: v.Rbrack,
}
case *gopast.StarExpr:
return &ast.StarExpr{
Star: v.Star,
X: goExpr(v.X),
}
case *gopast.MapType:
return &ast.MapType{
Map: v.Map,
Key: goType(v.Key),
Value: goType(v.Value),
}
case *gopast.StructType:
return &ast.StructType{
Struct: v.Struct,
Fields: goFieldList(v.Fields),
}
case *gopast.FuncType:
return goFuncType(v)
case *gopast.InterfaceType:
return &ast.InterfaceType{
Interface: v.Interface,
Methods: goFieldList(v.Methods),
}
case *gopast.ArrayType:
return &ast.ArrayType{
Lbrack: v.Lbrack,
Len: goExpr(v.Len),
Elt: goType(v.Elt),
}
case *gopast.ChanType:
return &ast.ChanType{
Begin: v.Begin,
Arrow: v.Arrow,
Dir: ast.ChanDir(v.Dir),
Value: goType(v.Value),
}
case *gopast.BasicLit:
return goBasicLit(v)
case *gopast.BinaryExpr:
return &ast.BinaryExpr{
X: goExpr(v.X),
OpPos: v.OpPos,
Op: token.Token(v.Op),
Y: goExpr(v.Y),
}
case *gopast.UnaryExpr:
return &ast.UnaryExpr{
OpPos: v.OpPos,
Op: token.Token(v.Op),
X: goExpr(v.X),
}
case *gopast.CallExpr:
return &ast.CallExpr{
Fun: goExpr(v.Fun),
Lparen: v.Lparen,
Args: goExprs(v.Args),
Ellipsis: v.Ellipsis,
Rparen: v.Rparen,
}
case *gopast.IndexExpr:
return &ast.IndexExpr{
X: goExpr(v.X),
Lbrack: v.Lbrack,
Index: goExpr(v.Index),
Rbrack: v.Rbrack,
}
case *gopast.ParenExpr:
return &ast.ParenExpr{
Lparen: v.Lparen,
X: goExpr(v.X),
Rparen: v.Rparen,
}
case *gopast.CompositeLit:
return &ast.CompositeLit{
Type: goType(v.Type),
Lbrace: v.Lbrace,
Elts: goExprs(v.Elts),
Rbrace: v.Rbrace,
}
case *gopast.FuncLit:
return &ast.FuncLit{
Type: goFuncType(v.Type),
Body: &ast.BlockStmt{}, // skip closure body
}
case *gopast.TypeAssertExpr:
return &ast.TypeAssertExpr{
X: goExpr(v.X),
Lparen: v.Lparen,
Type: goType(v.Type),
Rparen: v.Rparen,
}
case *gopast.KeyValueExpr:
return &ast.KeyValueExpr{
Key: goExpr(v.Key),
Colon: v.Colon,
Value: goExpr(v.Value),
}
case *gopast.Ellipsis:
return &ast.Ellipsis{
Ellipsis: v.Ellipsis,
Elt: goExpr(v.Elt),
}
}
log.Panicln("goExpr: unknown expr -", reflect.TypeOf(val))
return nil
}
func goExprs(vals []gopast.Expr) []ast.Expr {
n := len(vals)
if n == 0 {
return nil
}
ret := make([]ast.Expr, n)
for i, v := range vals {
ret[i] = goExpr(v)
}
return ret
}
// ----------------------------------------------------------------------------
func goFuncType(v *gopast.FuncType) *ast.FuncType {
return &ast.FuncType{
Func: v.Func,
Params: goFieldList(v.Params),
Results: goFieldList(v.Results),
}
}
func goType(v gopast.Expr) ast.Expr {
return goExpr(v)
}
func goBasicLit(v *gopast.BasicLit) *ast.BasicLit {
if v == nil {
return nil
}
return &ast.BasicLit{
ValuePos: v.ValuePos,
Kind: token.Token(v.Kind),
Value: v.Value,
}
}
func goIdent(v *gopast.Ident) *ast.Ident {
if v == nil {
return nil
}
return &ast.Ident{
NamePos: v.NamePos,
Name: v.Name,
}
}
func goIdents(names []*gopast.Ident) []*ast.Ident {
ret := make([]*ast.Ident, len(names))
for i, v := range names {
ret[i] = goIdent(v)
}
return ret
}
// ----------------------------------------------------------------------------
func goField(v *gopast.Field) *ast.Field {
return &ast.Field{
Names: goIdents(v.Names),
Type: goType(v.Type),
Tag: goBasicLit(v.Tag),
}
}
func goFieldList(v *gopast.FieldList) *ast.FieldList {
if v == nil {
return nil
}
list := make([]*ast.Field, len(v.List))
for i, item := range v.List {
list[i] = goField(item)
}
return &ast.FieldList{Opening: v.Opening, List: list, Closing: v.Closing}
}
func goFuncDecl(v *gopast.FuncDecl) *ast.FuncDecl {
return &ast.FuncDecl{
Recv: goFieldList(v.Recv),
Name: goIdent(v.Name),
Type: goFuncType(v.Type),
Body: &ast.BlockStmt{}, // ignore function body
}
}
// ----------------------------------------------------------------------------
func goImportSpec(spec *gopast.ImportSpec) *ast.ImportSpec {
return &ast.ImportSpec{
Name: goIdent(spec.Name),
Path: goBasicLit(spec.Path),
EndPos: spec.EndPos,
}
}
func goTypeSpec(spec *gopast.TypeSpec) *ast.TypeSpec {
return &ast.TypeSpec{
Name: goIdent(spec.Name),
Assign: spec.Assign,
Type: goType(spec.Type),
}
}
func goValueSpec(spec *gopast.ValueSpec) *ast.ValueSpec {
return &ast.ValueSpec{
Names: goIdents(spec.Names),
Type: goType(spec.Type),
Values: goExprs(spec.Values),
}
}
func goGenDecl(v *gopast.GenDecl) *ast.GenDecl {
specs := make([]ast.Spec, len(v.Specs))
for i, spec := range v.Specs {
switch v.Tok {
case goptoken.IMPORT:
specs[i] = goImportSpec(spec.(*gopast.ImportSpec))
case goptoken.TYPE:
specs[i] = goTypeSpec(spec.(*gopast.TypeSpec))
case goptoken.VAR, goptoken.CONST:
specs[i] = goValueSpec(spec.(*gopast.ValueSpec))
default:
log.Panicln("goGenDecl: unknown spec -", v.Tok)
}
}
return &ast.GenDecl{
TokPos: v.TokPos,
Tok: token.Token(v.Tok),
Lparen: v.Lparen,
Specs: specs,
Rparen: v.Rparen,
}
}
// ----------------------------------------------------------------------------
func goDecl(decl gopast.Decl) ast.Decl {
switch v := decl.(type) {
case *gopast.GenDecl:
return goGenDecl(v)
case *gopast.FuncDecl:
return goFuncDecl(v)
}
log.Panicln("goDecl: unkown decl -", reflect.TypeOf(decl))
return nil
}
func goDecls(decls []gopast.Decl) []ast.Decl {
ret := make([]ast.Decl, len(decls))
for i, decl := range decls {
ret[i] = goDecl(decl)
}
return ret
}
// ----------------------------------------------------------------------------
const (
KeepFuncBody = 1 << iota
)
func ASTFile(f *gopast.File, mode int) *ast.File {
if (mode & KeepFuncBody) != 0 {
log.Panicln("ASTFile: doesn't support keeping func body now")
}
return &ast.File{
Package: f.Package,
Name: goIdent(f.Name),
Decls: goDecls(f.Decls),
}
}
// ----------------------------------------------------------------------------