Skip to content

Commit

Permalink
Merge pull request #1662 from xushiwei/class
Browse files Browse the repository at this point in the history
add _test.gox (classfile for testing)
  • Loading branch information
xushiwei authored Jan 24, 2024
2 parents abce1a4 + 75353f1 commit 17069c4
Show file tree
Hide file tree
Showing 15 changed files with 332 additions and 107 deletions.
19 changes: 9 additions & 10 deletions cl/builtin.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,23 +25,22 @@ import (

// -----------------------------------------------------------------------------

func initMathBig(pkg *gox.Package, conf *gox.Config, big *gox.PkgRef) {
big.EnsureImported()
func initMathBig(pkg *gox.Package, conf *gox.Config, big gox.PkgRef) {
conf.UntypedBigInt = big.Ref("UntypedBigint").Type().(*types.Named)
conf.UntypedBigRat = big.Ref("UntypedBigrat").Type().(*types.Named)
conf.UntypedBigFloat = big.Ref("UntypedBigfloat").Type().(*types.Named)
}

func initBuiltinFns(builtin *types.Package, scope *types.Scope, pkg *gox.PkgRef, fns []string) {
func initBuiltinFns(builtin *types.Package, scope *types.Scope, pkg gox.PkgRef, fns []string) {
for _, fn := range fns {
fnTitle := string(fn[0]-'a'+'A') + fn[1:]
scope.Insert(gox.NewOverloadFunc(token.NoPos, builtin, fn, pkg.Ref(fnTitle)))
}
}

func initBuiltin(pkg *gox.Package, builtin *types.Package, os, fmt, ng, iox, buil *gox.PkgRef) {
func initBuiltin(pkg *gox.Package, builtin *types.Package, os, fmt, ng, iox, buil gox.PkgRef) {
scope := builtin.Scope()
if ng != nil {
if ng.Types != nil {
typs := []string{"bigint", "bigrat", "bigfloat"}
for _, typ := range typs {
name := string(typ[0]-('a'-'A')) + typ[1:]
Expand All @@ -50,26 +49,26 @@ func initBuiltin(pkg *gox.Package, builtin *types.Package, os, fmt, ng, iox, bui
scope.Insert(types.NewTypeName(token.NoPos, builtin, "uint128", ng.Ref("Uint128").Type()))
scope.Insert(types.NewTypeName(token.NoPos, builtin, "int128", ng.Ref("Int128").Type()))
}
if fmt != nil {
if fmt.Types != nil {
scope.Insert(gox.NewOverloadFunc(token.NoPos, builtin, "echo", fmt.Ref("Println")))
initBuiltinFns(builtin, scope, fmt, []string{
"print", "println", "printf", "errorf",
"fprint", "fprintln", "fprintf",
"sprint", "sprintln", "sprintf",
})
}
if os != nil {
if os.Types != nil {
initBuiltinFns(builtin, scope, os, []string{
"open", "create",
})
}
if iox != nil {
if iox.Types != nil {
initBuiltinFns(builtin, scope, iox, []string{
"lines",
})
scope.Insert(gox.NewOverloadFunc(token.NoPos, builtin, "blines", iox.Ref("BLines")))
}
if buil != nil {
if buil.Types != nil {
scope.Insert(gox.NewOverloadFunc(token.NoPos, builtin, "newRange", buil.Ref("NewRange__0")))
}
scope.Insert(types.NewTypeName(token.NoPos, builtin, "any", gox.TyEmptyInterface))
Expand All @@ -84,7 +83,7 @@ func newBuiltinDefault(pkg *gox.Package, conf *gox.Config) *types.Package {
iox := pkg.TryImport("github.com/goplus/gop/builtin/iox")
pkg.TryImport("strconv")
pkg.TryImport("strings")
if ng != nil {
if ng.Types != nil {
initMathBig(pkg, conf, ng)
}
initBuiltin(pkg, builtin, os, fmt, ng, iox, buil)
Expand Down
21 changes: 16 additions & 5 deletions cl/builtin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,14 @@ func TestErrStringLit(t *testing.T) {
})
}

func TestGmxMainFunc(t *testing.T) {
gmxMainFunc(nil, &pkgCtx{
projs: map[string]*gmxProject{
".a": {}, ".b": {},
},
}, false)
}

func TestNodeInterp(t *testing.T) {
ni := &nodeInterp{}
if v := ni.Caller(&ast.Ident{}); v != "the function call" {
Expand Down Expand Up @@ -206,7 +214,7 @@ func TestClRangeStmt(t *testing.T) {
// -----------------------------------------------------------------------------

func TestGetStringConst(t *testing.T) {
spx := &gox.PkgRef{Types: types.NewPackage("", "foo")}
spx := gox.PkgRef{Types: types.NewPackage("", "foo")}
if v := getStringConst(spx, "unknown"); v != "" {
t.Fatal("getStringConst:", v)
}
Expand All @@ -218,7 +226,7 @@ func TestSpxRef(t *testing.T) {
t.Fatal("TestSpxRef:", e)
}
}()
pkg := &gox.PkgRef{
pkg := gox.PkgRef{
Types: types.NewPackage("foo", "foo"),
}
spxRef(pkg, "bar")
Expand Down Expand Up @@ -277,7 +285,7 @@ func TestGmxProject(t *testing.T) {
}()
func() {
defer func() {
if e := recover(); e != "TODO: multiple project files found" {
if e := recover(); e != "multiple project files found: Game Game\n" {
t.Fatal("TestGmxProject failed:", e)
}
}()
Expand Down Expand Up @@ -319,10 +327,13 @@ func lookupClassErr(ext string) (c *modfile.Project, ok bool) {
}

func TestGetGoFile(t *testing.T) {
if f := genGoFile("a_test.gop", true); f != testingGoFile {
if f := genGoFile("a_test.gop", false); f != testingGoFile {
t.Fatal("TestGetGoFile:", f)
}
if f := genGoFile("a_test.gox", true); f != testingGoFile {
t.Fatal("TestGetGoFile:", f)
}
if f := genGoFile("a_test.gop", false); f != skippingGoFile {
if f := genGoFile("a.gop", false); f != defaultGoFile {
t.Fatal("TestGetGoFile:", f)
}
}
Expand Down
4 changes: 2 additions & 2 deletions cl/c.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,12 @@ func c2goBase(base string) string {

// -----------------------------------------------------------------------------

func loadC2goPkg(ctx *blockCtx, realPath string, src *ast.BasicLit) *gox.PkgRef {
func loadC2goPkg(ctx *blockCtx, realPath string, src *ast.BasicLit) (ret gox.PkgRef) {
cpkg, err := ctx.cpkgs.Import(realPath)
if err != nil {
ctx.handleErrorf(src.Pos(),
"%v not found or not a valid C package (c2go.a.pub file not found).\n", realPath)
return nil
return
}
ctx.clookups = append(ctx.clookups, cpkg)
return cpkg.Pkg()
Expand Down
80 changes: 61 additions & 19 deletions cl/classfile.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,11 @@ type gmxProject struct {
sptypes []string // <sptype>.spx
scheds []string
schedStmts []goast.Stmt // nil or len(scheds) == 2 (delayload)
pkgImps []*gox.PkgRef
pkgImps []gox.PkgRef
pkgPaths []string
hasScheds bool
gameIsPtr bool
isTest bool
}

func (p *gmxProject) getScheds(cb *gox.CodeBuilder) []goast.Stmt {
Expand Down Expand Up @@ -77,6 +78,10 @@ func ClassNameAndExt(file string) (name, ext string) {
return
}

func isGoxTestFile(ext string) bool {
return strings.HasSuffix(ext, "test.gox")
}

func loadClass(ctx *pkgCtx, pkg *gox.Package, file string, f *ast.File, conf *Config) *gmxProject {
tname, ext := ClassNameAndExt(file)
gt, ok := conf.LookupClass(ext)
Expand All @@ -89,10 +94,11 @@ func loadClass(ctx *pkgCtx, pkg *gox.Package, file string, f *ast.File, conf *Co
p = &gmxProject{pkgPaths: pkgPaths}
ctx.projs[gt.Ext] = p

p.pkgImps = make([]*gox.PkgRef, len(pkgPaths))
p.pkgImps = make([]gox.PkgRef, len(pkgPaths))
for i, pkgPath := range pkgPaths {
p.pkgImps[i] = pkg.Import(pkgPath)
}

spx := p.pkgImps[0]
if gt.Class != "" {
p.game, p.gameIsPtr = spxRef(spx, gt.Class)
Expand All @@ -107,12 +113,12 @@ func loadClass(ctx *pkgCtx, pkg *gox.Package, file string, f *ast.File, conf *Co
}
}
if f.IsProj {
if p.gameClass != "" {
panic("TODO: multiple project files found")
}
if tname == "main" {
tname = gt.Class
}
if p.gameClass != "" {
log.Panicln("multiple project files found:", tname, p.gameClass)
}
p.gameClass = tname
} else {
p.sptypes = append(p.sptypes, tname)
Expand All @@ -124,7 +130,7 @@ func loadClass(ctx *pkgCtx, pkg *gox.Package, file string, f *ast.File, conf *Co
return p
}

func spxLookup(pkgImps []*gox.PkgRef, name string) gox.Ref {
func spxLookup(pkgImps []gox.PkgRef, name string) gox.Ref {
for _, pkg := range pkgImps {
if o := pkg.TryRef(name); o != nil {
return o
Expand All @@ -133,23 +139,23 @@ func spxLookup(pkgImps []*gox.PkgRef, name string) gox.Ref {
panic("spxLookup: symbol not found - " + name)
}

func spxTryRef(spx *gox.PkgRef, typ string) (obj types.Object, isPtr bool) {
func spxTryRef(spx gox.PkgRef, typ string) (obj types.Object, isPtr bool) {
if strings.HasPrefix(typ, "*") {
typ, isPtr = typ[1:], true
}
obj = spx.TryRef(typ)
return
}

func spxRef(spx *gox.PkgRef, typ string) (obj gox.Ref, isPtr bool) {
func spxRef(spx gox.PkgRef, typ string) (obj gox.Ref, isPtr bool) {
obj, isPtr = spxTryRef(spx, typ)
if obj == nil {
panic(spx.Path() + "." + typ + " not found")
}
return
}

func getStringConst(spx *gox.PkgRef, name string) string {
func getStringConst(spx gox.PkgRef, name string) string {
if o := spx.TryRef(name); o != nil {
if c, ok := o.(*types.Const); ok {
return constant.StringVal(c.Val())
Expand Down Expand Up @@ -185,14 +191,50 @@ func setBodyHandler(ctx *blockCtx) {
}
}

func gmxMainFunc(p *gox.Package, ctx *pkgCtx, noAutoGenMain bool) func() {
if len(ctx.projs) == 1 { // only one project file
var proj *gmxProject
for _, v := range ctx.projs {
proj = v
break
const (
casePrefix = "case"
)

func testNameSuffix(testType string) string {
if c := testType[0]; c >= 'A' && c <= 'Z' {
return testType
}
return "_" + testType
}

func gmxTestFunc(pkg *gox.Package, testType string, isProj bool) {
if isProj {
genTestFunc(pkg, "TestMain", testType, "m", "M")
} else {
name := testNameSuffix(testType)
genTestFunc(pkg, "Test"+name, casePrefix+name, "t", "T")
}
}

func genTestFunc(pkg *gox.Package, name, testType, param, paramType string) {
testing := pkg.Import("testing")
objT := testing.Ref(paramType)
paramT := types.NewParam(token.NoPos, pkg.Types, param, types.NewPointer(objT.Type()))
params := types.NewTuple(paramT)

pkg.NewFunc(nil, name, params, nil, false).BodyStart(pkg).
Val(pkg.Builtin().Ref("new")).Val(pkg.Ref(testType)).Call(1).
MemberVal("TestMain").Val(paramT).Call(1).EndStmt().
End()
}

func gmxMainFunc(pkg *gox.Package, ctx *pkgCtx, noAutoGenMain bool) func() {
var proj *gmxProject
for _, v := range ctx.projs {
if v.isTest {
continue
} else if proj != nil {
return nil
}
scope := p.Types.Scope()
proj = v
}
if proj != nil { // only one project file
scope := pkg.Types.Scope()
var o types.Object
if proj.gameClass != "" {
o = scope.Lookup(proj.gameClass)
Expand All @@ -205,10 +247,10 @@ func gmxMainFunc(p *gox.Package, ctx *pkgCtx, noAutoGenMain bool) func() {
if !noAutoGenMain && o != nil {
// new(Game).Main()
// new(Game).Main(workers...)
fn := p.NewFunc(nil, "main", nil, nil, false)
fn := pkg.NewFunc(nil, "main", nil, nil, false)
return func() {
new := p.Builtin().Ref("new")
cb := fn.BodyStart(p).Val(new).Val(o).Call(1).MemberVal("Main")
new := pkg.Builtin().Ref("new")
cb := fn.BodyStart(pkg).Val(new).Val(o).Call(1).MemberVal("Main")

sig := cb.Get(-1).Type.(*types.Signature)
narg := gmxMainNarg(sig)
Expand Down
Loading

0 comments on commit 17069c4

Please sign in to comment.