Skip to content

Commit

Permalink
Update BLAS (#31)
Browse files Browse the repository at this point in the history
* Update testdata: blas

* update blas from lapack

* add test for TESTING

* init

* add integration test

* fix label

* add test for COMMON with initialization

* implementation common

* test is ok
  • Loading branch information
Konstantin8105 committed Oct 17, 2019
1 parent ec82f7a commit 982d19b
Show file tree
Hide file tree
Showing 182 changed files with 29,794 additions and 402 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ testdata/*.out
testdata/*.go
*.o
testdata/other/*
testdata/blas/*.go
testdata/blas/SRC/*.go
testdata/blas/TESTING/*.go
testdata/result
*.txt

Expand Down
50 changes: 39 additions & 11 deletions fortran/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,6 @@ type varInitialization struct {

type varInits []varInitialization

func (v *varInits) reset() {
(*v) = nil
v = nil
}

func (v varInits) get(n string) (varInitialization, bool) {
n = strings.ToUpper(n)
for _, val := range []varInitialization(v) {
Expand Down Expand Up @@ -195,7 +190,7 @@ func (p *parser) init() {
p.initVars = varInits{}
p.parameters = map[string]string{}
p.formats = map[string][]node{}

p.implicit = nil
p.constants = map[string][]node{}
}

Expand Down Expand Up @@ -948,9 +943,7 @@ func (p *parser) parseProgram() (decl goast.Decl) {
p.ns[p.ident].tok = ftSubroutine
decl = p.parseSubroutine()
if fd, ok := decl.(*goast.FuncDecl); ok {
if strings.ToUpper(fd.Name.Name) == "MAIN" {
fd.Name.Name = "main"
}
fd.Name.Name = "main"
}
return
}
Expand All @@ -966,8 +959,7 @@ func (p *parser) parseSubroutine() (decl goast.Decl) {
}

defer func() {
p.resetImplicit()
p.initVars.reset()
p.init()
}()

var fd goast.FuncDecl
Expand Down Expand Up @@ -1675,6 +1667,7 @@ func (p *parser) parseStmt() (stmts []goast.Stmt) {
case token.INT:
labelName := string(p.ns[p.ident].b)
if v, ok := p.endLabelDo[labelName]; ok && v > 0 {
stmts = append(stmts, p.addLabel(p.ns[p.ident].b))
// if after END DO, then remove
for i := p.ident; p.ns[i].tok != ftNewLine; i++ {
p.ns[i].tok, p.ns[i].b = ftNewLine, []byte("\n")
Expand Down Expand Up @@ -2503,6 +2496,41 @@ func (p *parser) parseCommon() (stmts []goast.Stmt) {
// generate stmts
// {{ .name }} = COMMON.{{ .blockName }}.{{ name }}
for i := range names {

// if variable is not initialized
if _, ok := p.initVars.get(names[i]); !ok {
// from:
// COMMON LOC(3), T(1)
// to:
// INTEGER LOC(3)
// INTEGER T(1)
// COMMON LOC(3), T(1)
var inject []node
inject = append(inject, node{tok: ftNewLine, b: []byte("\n")})
if i == 0 {
inject = append(inject, node{tok: ftInteger, b: []byte("INTEGER")})
} else {
inject = append(inject, node{tok: ftReal, b: []byte("REAL")})
}
n := scan([]byte(names[i]))
inject = append(inject, n...)
inject = append(inject, node{tok: ftNewLine, b: []byte("\n")})

if strings.Contains(names[i], "(") {
inject = append(inject, node{tok: ftNewLine, b: []byte("\n")})
if i == 0 {
inject = append(inject, node{tok: ftInteger, b: []byte("INTEGER")})
} else {
inject = append(inject, node{tok: ftReal, b: []byte("REAL")})
}
n[0].b = append([]byte("COMMON."+blockName+"."), n[0].b...)
inject = append(inject, n...)
inject = append(inject, node{tok: ftNewLine, b: []byte("\n")})
}

p.ns = append(p.ns[:p.ident], append(inject, p.ns[p.ident:]...)...)
}

name := names[i]
if index := strings.Index(name, "("); index > 0 {
name = name[:index]
Expand Down
112 changes: 1 addition & 111 deletions fortran/scan.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ type scanner struct {
nodes *list.List
}

const Debug bool = true // false
var Debug bool = true // false

func scan(b []byte) (ns []node) {
if Debug {
Expand Down Expand Up @@ -889,116 +889,6 @@ impl:
goto impl
}

// from:
// COMMON/PDAT/LOC(3), T(1)
// to:
// INTEGER LOC(3)
// INTEGER Common.PDAT.LOC(3)
// INTEGER T(1)
// INTEGER Common.PDAT.T (1)
// COMMON/PDAT/LOC(3), T(1)
// or:
// from:
// COMMON LOC(3), T(1)
// to:
// INTEGER LOC(3)
// INTEGER T(1)
// COMMON LOC(3), T(1)
for e := s.nodes.Front(); e != nil; e = e.Next() {
if e.Value.(*node).tok != ftCommon {
continue
}
n := e.Next()

var blockName string

if n.Value.(*node).tok == token.QUO { // /
n = n.Next()
for ; n != nil && n.Value.(*node).tok != token.QUO; n = n.Next() {
blockName = string(n.Value.(*node).b)
}
n = n.Next()
}

if blockName == "" || blockName == "*" {
blockName = "ALL"
}

isFirst := true
var names []node
inject := func() {
iF := isFirst
// next nodes are names
if isFirst {
s.nodes.InsertBefore(&node{
tok: ftInteger,
}, e)
isFirst = false
} else {
s.nodes.InsertBefore(&node{
tok: ftReal,
}, e)
}
for i := 0; i < len(names); i++ {
s.nodes.InsertBefore(&names[i], e)
}
s.nodes.InsertBefore(&node{tok: ftNewLine, b: []byte{'\n'}}, e)

// do not initialize variables without array
foundParen := false
for i := range names {
if names[i].tok == token.LPAREN {
foundParen = true
break
}
}
if !foundParen {
return
}

// initialize common type
isFirst = iF
if isFirst {
s.nodes.InsertBefore(&node{
tok: ftInteger,
}, e)
isFirst = false
} else {
s.nodes.InsertBefore(&node{
tok: ftReal,
}, e)
}

for i := 0; i < len(names); i++ {
name := names[i]
if i == 0 {
name.b = append([]byte("COMMON."+blockName+"."), name.b...)
}
s.nodes.InsertBefore(&name, e)
}
s.nodes.InsertBefore(&node{tok: ftNewLine, b: []byte{'\n'}}, e)
}
isopen := false
for ; n != nil; n = n.Next() {
if n.Value.(*node).tok == ftNewLine {
inject()
break
}
if n.Value.(*node).tok == token.LPAREN {
isopen = true
}
if n.Value.(*node).tok == token.RPAREN {
isopen = false
}
if n.Value.(*node).tok == token.COMMA && isopen == false {
inject()
names = make([]node, 0)
continue
}
names = append(names, *n.Value.(*node))
}
}

// inject code from INCLUDE
incl:
for e := s.nodes.Front(); e != nil; e = e.Next() {
Expand Down
5 changes: 3 additions & 2 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"go/format"
"go/token"
"io/ioutil"
"os"
"os/exec"
"runtime"
"strings"
Expand All @@ -30,7 +31,7 @@ func run() {
flag.Parse()

if flag.NArg() < 1 {
flag.Usage()
fmt.Fprintln(os.Stdout, "Please run: f4go -h")
return
}

Expand Down Expand Up @@ -97,7 +98,7 @@ func parse(filename, packageName, goFilename string) (errR []errorRow) {
}
}

fmt.Println("\n\ngenerate : ", goFilename)
// fmt.Println("\n\ngenerate : ", goFilename)

// save go source
if err = ioutil.WriteFile(goFilename, buf.Bytes(), 0644); err != nil {
Expand Down
49 changes: 45 additions & 4 deletions main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ import (
)

func TestIntegration(t *testing.T) {

fortran.Debug = testing.Verbose()

// gfortran ./testdata/main.f -o ./testdata/a.out
out, err := exec.Command(
"gfortran",
Expand Down Expand Up @@ -118,6 +121,9 @@ func ShowDiff(a, b string) string {
}

func TestFail(t *testing.T) {

fortran.Debug = testing.Verbose()

// wrong source
errs := parse("./testdata/fortran_fail.f", "", "")
if len(errs) == 0 {
Expand Down Expand Up @@ -176,10 +182,21 @@ func getFortranTestFiles(dir string) (files []string, err error) {
}

func TestBlas(t *testing.T) {
ss, err := filepath.Glob(fmt.Sprintf("./testdata/blas/%s", "*.f"))
if err != nil {

fortran.Debug = testing.Verbose()

ss, err := filepath.Glob(fmt.Sprintf("./testdata/blas/SRC/%s", "*.f"))
if err != nil || len(ss) == 0 {
t.Fatal(err)
}
{
// add TESTING
ss2, err := filepath.Glob(fmt.Sprintf("./testdata/blas/TESTING/%s", "*.f"))
if err != nil || len(ss) == 0 {
t.Fatal(err)
}
ss = append(ss, ss2...)
}

var amount int

Expand All @@ -195,6 +212,27 @@ func TestBlas(t *testing.T) {
t.Logf("Error is not empty")
amount++
}

// TODO: add full implementation
//
// if !strings.Contains(ss[i], "TESTING") {
// return
// }
//
// // Go name
// goname := ss[i]
// if index := strings.LastIndex(goname, "."); index > 0 {
// goname = goname[:index] + ".go"
// }
//
// // run Go test
// cmd := exec.Command(
// "go", "build", goname,
// )
// goOutput, err := cmd.CombinedOutput()
// if err != nil {
// t.Errorf("Cannot go executable file : %v\n%s", err, goOutput)
// }
})
}

Expand All @@ -215,7 +253,7 @@ func TestBlas(t *testing.T) {
readme := lines("./README.md")

// get lines of source fortran file
fortran := lines("./testdata/blas/caxpy.f")
fortran := lines("./testdata/blas/SRC/caxpy.f")
for i := range fortran {
found := false
for j := range readme {
Expand All @@ -230,7 +268,7 @@ func TestBlas(t *testing.T) {
}

// get lines of Go file
gof := lines("./testdata/blas/caxpy.go")
gof := lines("./testdata/blas/SRC/caxpy.go")
for i := range gof {
found := false
for j := range readme {
Expand Down Expand Up @@ -407,6 +445,9 @@ func TestComments(t *testing.T) {
}

func TestCrash(t *testing.T) {

fortran.Debug = testing.Verbose()

var (
in = "./testdata/min_crash.f"
out = "./testdata/min_crash.go"
Expand Down
Loading

0 comments on commit 982d19b

Please sign in to comment.