Skip to content

Commit 40e67a4

Browse files
committed
TestBinaryOp
1 parent 89894fc commit 40e67a4

File tree

4 files changed

+189
-12
lines changed

4 files changed

+189
-12
lines changed

ast.go

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -156,10 +156,7 @@ func toExpr(pkg *Package, val interface{}) internal.Elem {
156156
Type: types.Typ[types.UntypedFloat],
157157
}
158158
case types.Object:
159-
return internal.Elem{
160-
Val: toObject(pkg, v),
161-
Type: v.Type(),
162-
}
159+
return toObject(pkg, v)
163160
}
164161
panic("TODO: toExpr")
165162
}
@@ -180,7 +177,14 @@ func toBasicKind(tok token.Token) types.BasicKind {
180177
panic("TODO: unknown Token")
181178
}
182179

183-
func toObject(pkg *Package, v types.Object) ast.Expr {
180+
func toObject(pkg *Package, v types.Object) internal.Elem {
181+
return internal.Elem{
182+
Val: toObjectExpr(pkg, v),
183+
Type: v.Type(),
184+
}
185+
}
186+
187+
func toObjectExpr(pkg *Package, v types.Object) ast.Expr {
184188
atPkg := v.Pkg()
185189
if atPkg == pkg.Types { // at this package
186190
return ident(v.Name())

codebuild.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,41 @@ func (p *CodeBuilder) Call(n int) *CodeBuilder {
106106
return p
107107
}
108108

109+
// BinaryOp func
110+
func (p *CodeBuilder) BinaryOp(op token.Token) *CodeBuilder {
111+
pkg := p.pkg
112+
args := p.stk.GetArgs(2)
113+
if typ, ok := pkg.checkBuiltin(args[0].Type); ok {
114+
name := pkg.prefix.Operator + typ + binaryOps[op]
115+
fn := pkg.builtin.Scope().Lookup(name)
116+
if fn == nil {
117+
panic("TODO: operator not matched")
118+
}
119+
ret := toFuncCall(toObject(pkg, fn), args)
120+
p.stk.Ret(2, ret)
121+
} else {
122+
panic("TODO: BinaryOp")
123+
}
124+
return p
125+
}
126+
127+
var (
128+
binaryOps = [...]string{
129+
token.ADD: "_Add", // +
130+
token.SUB: "_Sub", // -
131+
token.MUL: "_Mul", // *
132+
token.QUO: "_Quo", // /
133+
token.REM: "_Rem", // %
134+
135+
token.AND: "_And", // &
136+
token.OR: "_Or", // |
137+
token.XOR: "_Xor", // ^
138+
token.SHL: "_Lsh", // <<
139+
token.SHR: "_Rsh", // >>
140+
token.AND_NOT: "_AndNot", // &^
141+
}
142+
)
143+
109144
// Defer func
110145
func (p *CodeBuilder) Defer() *CodeBuilder {
111146
panic("CodeBuilder.Defer")

package.go

Lines changed: 129 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,14 @@ import (
99

1010
// ----------------------------------------------------------------------------
1111

12+
// NamePrefix config
13+
type NamePrefix struct {
14+
BuiltinType string // builtin type
15+
TypeExtend string // type extend
16+
Operator string // operator
17+
TypeConv string // type convert
18+
}
19+
1220
// Config type
1321
type Config struct {
1422
// Context specifies the context for the load operation.
@@ -62,30 +70,144 @@ type Config struct {
6270

6371
// LoadPkgs is called to load all import packages.
6472
LoadPkgs func(at *Package, importPkgs map[string]*PkgRef, pkgPaths ...string) int
73+
74+
// Prefix is name prefix.
75+
Prefix *NamePrefix
76+
77+
// Builtin is the builin package.
78+
Builtin *types.Package
79+
80+
// CheckBuiltinType checks a type is builtin type or not.
81+
CheckBuiltinType func(typ types.Type) (name string, is bool)
6582
}
6683

6784
// Package type
6885
type Package struct {
6986
PkgRef
70-
decls []ast.Decl
71-
cb CodeBuilder
72-
importPkgs map[string]*PkgRef
73-
pkgPaths []string
74-
conf *Config
87+
decls []ast.Decl
88+
cb CodeBuilder
89+
importPkgs map[string]*PkgRef
90+
pkgPaths []string
91+
conf *Config
92+
prefix *NamePrefix
93+
builtin *types.Package
94+
checkBuiltin func(typ types.Type) (name string, ok bool)
7595
}
7696

7797
// NewPackage func
7898
func NewPackage(pkgPath, name string, conf *Config) *Package {
7999
if conf == nil {
80100
conf = &Config{}
81101
}
102+
prefix := conf.Prefix
103+
if prefix == nil {
104+
prefix = defaultNamePrefix
105+
}
106+
builtin := conf.Builtin
107+
if builtin == nil {
108+
builtin = newBuiltinDefault(prefix)
109+
}
110+
checkBuiltin := conf.CheckBuiltinType
111+
if checkBuiltin == nil {
112+
checkBuiltin = defaultCheckBuiltinType
113+
}
82114
pkg := &Package{
83-
importPkgs: make(map[string]*PkgRef),
84-
conf: conf,
115+
importPkgs: make(map[string]*PkgRef),
116+
conf: conf,
117+
prefix: prefix,
118+
builtin: builtin,
119+
checkBuiltin: checkBuiltin,
85120
}
86121
pkg.Types = types.NewPackage(pkgPath, name)
87122
pkg.cb.init(pkg)
88123
return pkg
89124
}
90125

126+
func Init_untyped_uint(builtin *types.Package, prefix *NamePrefix) types.Type {
127+
name := types.NewTypeName(token.NoPos, builtin, prefix.BuiltinType+"untyped_uint", nil)
128+
typ := types.NewNamed(name, types.Typ[types.Uint], nil)
129+
builtin.Scope().Insert(name)
130+
return typ
131+
}
132+
133+
// ----------------------------------------------------------------------------
134+
135+
var (
136+
defaultNamePrefix = &NamePrefix{
137+
BuiltinType: "Gopb_",
138+
TypeExtend: "Gope_",
139+
Operator: "Gopo_",
140+
TypeConv: "Gopc_",
141+
}
142+
)
143+
144+
var (
145+
intBinaryOps = []string{
146+
"_Add", "_Sub", "_Mul", "_Quo", "_Rem", "_Or", "_Xor", "_And", "_AndNot"}
147+
intBooleanOps = []string{
148+
"_LT", "_LE", "_GT", "_GE", "_EQ", "_NE"}
149+
intTypes = []types.BasicKind{
150+
types.Int, types.Int64, types.Int32, types.Int16, types.Int8,
151+
types.Uint, types.Uintptr, types.Uint64, types.Uint32, types.Uint16, types.Uint8,
152+
}
153+
)
154+
155+
func addIntType(builtin *types.Package, typ, untypedUint types.Type, prefix *NamePrefix) {
156+
gbl := builtin.Scope()
157+
opPrefix := prefix.Operator + typ.String()
158+
159+
a := types.NewVar(token.NoPos, builtin, "a", typ)
160+
b := types.NewVar(token.NoPos, builtin, "b", typ)
161+
args := types.NewTuple(a, b)
162+
ret := types.NewTuple(types.NewVar(token.NoPos, builtin, "", typ))
163+
sig := types.NewSignature(nil, args, ret, false)
164+
165+
// func opPrefix_type_op(a, b type) type
166+
for _, op := range intBinaryOps {
167+
gbl.Insert(types.NewFunc(token.NoPos, builtin, opPrefix+op, sig))
168+
}
169+
170+
// func opPrefix_type_op(a type, n untyped_uint) type
171+
n := types.NewVar(token.NoPos, builtin, "n", untypedUint)
172+
args2 := types.NewTuple(a, n)
173+
sig2 := types.NewSignature(nil, args2, ret, false)
174+
gbl.Insert(types.NewFunc(token.NoPos, builtin, opPrefix+"Lsh", sig2))
175+
gbl.Insert(types.NewFunc(token.NoPos, builtin, opPrefix+"Rsh", sig2))
176+
177+
// func opPrefix_type_op(a, b type) bool
178+
ret3 := types.NewTuple(types.NewVar(token.NoPos, builtin, "", types.Typ[types.Bool]))
179+
sig3 := types.NewSignature(nil, args, ret3, false)
180+
for _, op := range intBooleanOps {
181+
gbl.Insert(types.NewFunc(token.NoPos, builtin, opPrefix+op, sig3))
182+
}
183+
184+
// func opPrefix_type_op(a type) type
185+
args4 := types.NewTuple(a)
186+
sig4 := types.NewSignature(nil, args4, ret, false)
187+
gbl.Insert(types.NewFunc(token.NoPos, builtin, opPrefix+"Neg", sig4))
188+
gbl.Insert(types.NewFunc(token.NoPos, builtin, opPrefix+"Not", sig4))
189+
}
190+
191+
func addUntypedType(builtin *types.Package, typ types.Type, prefix *NamePrefix) {
192+
}
193+
194+
func newBuiltinDefault(prefix *NamePrefix) *types.Package {
195+
builtin := types.NewPackage("", "")
196+
untypedUint := Init_untyped_uint(builtin, prefix)
197+
for _, intTy := range intTypes {
198+
addIntType(builtin, types.Typ[intTy], untypedUint, prefix)
199+
}
200+
return builtin
201+
}
202+
203+
func defaultCheckBuiltinType(typ types.Type) (name string, is bool) {
204+
if t, ok := typ.(*types.Basic); ok {
205+
if t.Kind() == types.UnsafePointer {
206+
return
207+
}
208+
return t.Name(), true
209+
}
210+
return
211+
}
212+
91213
// ----------------------------------------------------------------------------

package_test.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,22 @@ func main() {
155155
`)
156156
}
157157

158+
func TestBinaryOp(t *testing.T) {
159+
var a *gox.Var
160+
pkg := gox.NewPackage("", "main", nil)
161+
pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
162+
NewVar("a", &a).
163+
Val("Hi").Val("!").BinaryOp(token.ADD).EndStmt().
164+
End()
165+
domTest(t, pkg, `package main
166+
167+
func main() {
168+
var a string
169+
a = "Hi" + "!"
170+
}
171+
`)
172+
}
173+
158174
func TestClosure(t *testing.T) {
159175
pkg := gox.NewPackage("", "main", nil)
160176
fmt := pkg.Import("fmt")

0 commit comments

Comments
 (0)