github.com/goplus/igop@v0.25.0/binop_shift_gen.go (about)

     1  //go:build ignore
     2  // +build ignore
     3  
     4  /*
     5   * Copyright (c) 2022 The GoPlus Authors (goplus.org). All rights reserved.
     6   *
     7   * Licensed under the Apache License, Version 2.0 (the "License");
     8   * you may not use this file except in compliance with the License.
     9   * You may obtain a copy of the License at
    10   *
    11   *     http://www.apache.org/licenses/LICENSE-2.0
    12   *
    13   * Unless required by applicable law or agreed to in writing, software
    14   * distributed under the License is distributed on an "AS IS" BASIS,
    15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    16   * See the License for the specific language governing permissions and
    17   * limitations under the License.
    18   */
    19  
    20  package main
    21  
    22  import (
    23  	"bytes"
    24  	"fmt"
    25  	"go/format"
    26  	"io/ioutil"
    27  	"os"
    28  	"strings"
    29  )
    30  
    31  var (
    32  	ints = []string{"int", "int8", "int16", "int32", "int64",
    33  		"uint", "uint8", "uint16", "uint32", "uint64", "uintptr"}
    34  )
    35  
    36  type TypeKind struct {
    37  	typ  string
    38  	kind string
    39  }
    40  
    41  func main() {
    42  	var buf bytes.Buffer
    43  	buf.WriteString(pkg_head)
    44  	var kinds []*TypeKind
    45  	for _, v := range ints {
    46  		kinds = append(kinds, &TypeKind{v, strings.Title(v)})
    47  	}
    48  
    49  	var lbuf bytes.Buffer
    50  	makeFuncSHL(&lbuf, kinds)
    51  	buf.Write(lbuf.Bytes())
    52  	r := strings.NewReplacer("makeBinOpSHL", "makeBinOpSHR", "<<", ">>")
    53  	r.WriteString(&buf, lbuf.String())
    54  
    55  	data, err := format.Source(buf.Bytes())
    56  	if err != nil {
    57  		fmt.Println("format error", err)
    58  		fmt.Println(buf.String())
    59  		os.Exit(2)
    60  	}
    61  	ioutil.WriteFile("./binop_shift.go", data, 0666)
    62  }
    63  
    64  func makeFuncSHL(buf *bytes.Buffer, kinds []*TypeKind) {
    65  	buf.WriteString(func_head_op)
    66  	// check x const && y const
    67  	buf.WriteString(`if kx == kindConst && ky == kindConst {
    68  	t := xtype.TypeOfType(xtyp)
    69  	switch xkind {
    70  `)
    71  	for _, kx := range kinds {
    72  		buf.WriteString(fmt.Sprintf(`	case reflect.%v:
    73  		x := xtype.%v(vx)
    74  		switch ykind {
    75  `, kx.kind, kx.kind))
    76  		for _, ky := range kinds {
    77  			buf.WriteString(fmt.Sprintf(`case reflect.%v:
    78  			v := xtype.Make(t, x << xtype.%v(vy))
    79  			return func(fr *frame) { fr.setReg(ir,v) }
    80  `, ky.kind, ky.kind))
    81  		}
    82  		// end switch ykind
    83  		buf.WriteString("}\n")
    84  	}
    85  
    86  	// end switch xkind
    87  	buf.WriteString("}\n")
    88  	// end x const && y const
    89  	buf.WriteString("}\n")
    90  
    91  	buf.WriteString(`if xtyp.PkgPath() == "" {
    92  	switch xkind {
    93  `)
    94  	for _, kx := range kinds {
    95  		buf.WriteString(fmt.Sprintf(`	case reflect.%v:
    96  `, kx.kind))
    97  		// if x const
    98  		buf.WriteString(fmt.Sprintf(`	if kx == kindConst {
    99  		x := vx.(%v)
   100  `, kx.typ))
   101  		buf.WriteString(fmt.Sprintf("\t\t\tswitch ykind {\n"))
   102  		for _, ky := range kinds {
   103  			buf.WriteString(fmt.Sprintf(`case reflect.%v:
   104  			return func(fr *frame) { fr.setReg(ir,x<<fr.%v(iy)) }
   105  `, ky.kind, ky.typ))
   106  		}
   107  
   108  		buf.WriteString(fmt.Sprintf("\t\t\t}\n"))
   109  
   110  		// else if y const
   111  		buf.WriteString("\t\t} else if ky == kindConst {\n")
   112  		buf.WriteString(fmt.Sprintf("\t\t\tswitch ykind {\n"))
   113  		for _, ky := range kinds {
   114  			buf.WriteString(fmt.Sprintf(`case reflect.%v:
   115  			y := xtype.%v(vy)
   116  			return func(fr *frame) { fr.setReg(ir,fr.reg(ix).(%v)<<y) }
   117  `, ky.kind, ky.kind, kx.typ))
   118  		}
   119  		buf.WriteString(fmt.Sprintf("\t\t\t}\n"))
   120  
   121  		// else x no const and y no const
   122  		buf.WriteString("\t} else {\n")
   123  		buf.WriteString("switch ykind {\n")
   124  
   125  		for _, ky := range kinds {
   126  			buf.WriteString(fmt.Sprintf(`case reflect.%v:
   127  			return func(fr *frame) { fr.setReg(ir,fr.reg(ix).(%v)<<fr.%v(iy)) }
   128  `, ky.kind, kx.typ, ky.typ))
   129  		}
   130  		buf.WriteString("}\n") // end swith ykind
   131  		buf.WriteString("}\n")
   132  	}
   133  	buf.WriteString("\t\t};") // end xkind
   134  
   135  	buf.WriteString("} else {") //end xtypIsBasic
   136  
   137  	// begin not xtype
   138  	buf.WriteString(`
   139  		t := xtype.TypeOfType(xtyp)
   140  		switch xkind {
   141  	`)
   142  	for _, kx := range kinds {
   143  		buf.WriteString(fmt.Sprintf(`	case reflect.%v:
   144  `, kx.kind))
   145  		// if x const
   146  		buf.WriteString(fmt.Sprintf(`	if kx == kindConst {
   147  			x := xtype.%v(vx)
   148  	`, kx.kind))
   149  		buf.WriteString(fmt.Sprintf("\t\t\tswitch ykind {\n"))
   150  		for _, ky := range kinds {
   151  			buf.WriteString(fmt.Sprintf(`case reflect.%v:
   152  				return func(fr *frame) { fr.setReg(ir,xtype.Make(t,x<<fr.%v(iy))) }
   153  `, ky.kind, ky.typ))
   154  		}
   155  
   156  		buf.WriteString(fmt.Sprintf("\t\t\t}\n"))
   157  
   158  		// else if y const
   159  		buf.WriteString("\t\t} else if ky == kindConst {\n")
   160  		buf.WriteString(fmt.Sprintf("\t\t\tswitch ykind {\n"))
   161  		for _, ky := range kinds {
   162  			buf.WriteString(fmt.Sprintf(`case reflect.%v:
   163  				y := xtype.%v(vy)
   164  				return func(fr *frame) { fr.setReg(ir,xtype.Make(t,fr.%v(ix)<<y)) }
   165  `, ky.kind, ky.kind, kx.typ))
   166  		}
   167  		buf.WriteString(fmt.Sprintf("\t\t\t}\n"))
   168  
   169  		// else x no const and y no const
   170  		buf.WriteString("\t} else {\n")
   171  		buf.WriteString("switch ykind {\n")
   172  
   173  		for _, ky := range kinds {
   174  			buf.WriteString(fmt.Sprintf(`case reflect.%v:
   175  				return func(fr *frame) { fr.setReg(ir,xtype.Make(t,fr.%v(ix)<<fr.%v(iy))) }
   176  `, ky.kind, kx.typ, ky.typ))
   177  		}
   178  		buf.WriteString("}\n") // end swith ykind
   179  		buf.WriteString("}\n")
   180  	}
   181  	buf.WriteString("\t\t};") // end xkind
   182  
   183  	buf.WriteString("};") // end not xtype
   184  
   185  	buf.WriteString("\tpanic(\"unreachable\")\n}\n")
   186  }
   187  
   188  var pkg_head = `package igop
   189  
   190  import (
   191  	"reflect"
   192  
   193  	"github.com/visualfc/xtype"
   194  	"golang.org/x/tools/go/ssa"
   195  )
   196  `
   197  
   198  var func_head_op = `
   199  func makeBinOpSHL(pfn *function, instr *ssa.BinOp) func(fr *frame) {
   200  	ir := pfn.regIndex(instr)
   201  	ix, kx, vx := pfn.regIndex3(instr.X)
   202  	iy, ky, vy := pfn.regIndex3(instr.Y)
   203  	xtyp := pfn.Interp.preToType(instr.X.Type())
   204  	ytyp := pfn.Interp.preToType(instr.Y.Type())
   205  	xkind := xtyp.Kind()
   206  	ykind := ytyp.Kind()
   207  `