mirror of
https://gitee.com/wa-lang/wa.git
synced 2025-12-06 09:18:53 +08:00
CI 添加 fmt 并包含更多测试
This commit is contained in:
@@ -39,7 +39,7 @@ func Fmt(path string) error {
|
||||
for _, s := range waFileList {
|
||||
changed, err := fmtFile(s)
|
||||
if err != nil {
|
||||
return err
|
||||
return fmt.Errorf("%s: %w", s, err)
|
||||
}
|
||||
if changed {
|
||||
changedFileList = append(changedFileList, s)
|
||||
|
||||
@@ -1,142 +0,0 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package format
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"wa-lang.org/wa/internal/parser"
|
||||
"wa-lang.org/wa/internal/token"
|
||||
)
|
||||
|
||||
const testfile = "format_test.go.wa"
|
||||
|
||||
func diff(t *testing.T, dst, src []byte) {
|
||||
line := 1
|
||||
offs := 0 // line offset
|
||||
for i := 0; i < len(dst) && i < len(src); i++ {
|
||||
d := dst[i]
|
||||
s := src[i]
|
||||
if d != s {
|
||||
t.Errorf("dst:%d: %s\n", line, dst[offs:i+1])
|
||||
t.Errorf("src:%d: %s\n", line, src[offs:i+1])
|
||||
return
|
||||
}
|
||||
if s == '\n' {
|
||||
line++
|
||||
offs = i + 1
|
||||
}
|
||||
}
|
||||
if len(dst) != len(src) {
|
||||
t.Errorf("len(dst) = %d, len(src) = %d\nsrc = %q", len(dst), len(src), src)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNode(t *testing.T) {
|
||||
src, err := ioutil.ReadFile(testfile)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
fset := token.NewFileSet()
|
||||
file, err := parser.ParseFile(nil, fset, testfile, src, parser.ParseComments)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
|
||||
if err = Node(&buf, fset, file); err != nil {
|
||||
t.Fatal("Node failed:", err)
|
||||
}
|
||||
|
||||
diff(t, buf.Bytes(), src)
|
||||
}
|
||||
|
||||
func TestSource(t *testing.T) {
|
||||
src, err := ioutil.ReadFile(testfile)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
res, err := Source(src)
|
||||
if err != nil {
|
||||
t.Fatal("Source failed:", err)
|
||||
}
|
||||
|
||||
diff(t, res, src)
|
||||
}
|
||||
|
||||
// Test cases that are expected to fail are marked by the prefix "ERROR".
|
||||
// The formatted result must look the same as the input for successful tests.
|
||||
var tests = []string{
|
||||
// declaration lists
|
||||
`import "wa-lang.org/wa/internal/format"`,
|
||||
"var x int",
|
||||
"var x int\n\ntype T struct{}",
|
||||
|
||||
// statement lists
|
||||
"x := 0",
|
||||
"f(a, b, c)\nvar x int = f(1, 2, 3)",
|
||||
|
||||
// indentation, leading and trailing space
|
||||
"\n\t\t\n\n\t\t\tx := 0\n\t\t\tconst s = `\nfoo\n`\n\n\n", // no indentation added inside raw strings
|
||||
"\n\t\t\n\n\t\t\tx := 0\n\t\t\tconst s = `\n\t\tfoo\n`\n\n\n", // no indentation removed inside raw strings
|
||||
|
||||
// comments
|
||||
"/* Comment */",
|
||||
"\t/* Comment */ ",
|
||||
"\n/* Comment */ ",
|
||||
"i := 5 /* Comment */", // issue #5551
|
||||
"\ta()\n//line :1", // issue #11276
|
||||
"\t//xxx\n\ta()\n//line :2", // issue #11276
|
||||
"\ta() //line :1\n\tb()\n", // issue #11276
|
||||
"x := 0\n//line :1\n//line :2", // issue #11276
|
||||
|
||||
// whitespace
|
||||
"", // issue #11275
|
||||
" ", // issue #11275
|
||||
"\t", // issue #11275
|
||||
"\t\t", // issue #11275
|
||||
"\n", // issue #11275
|
||||
"\n\n", // issue #11275
|
||||
"\t\n", // issue #11275
|
||||
|
||||
// erroneous programs
|
||||
"ERROR1 + 2 +",
|
||||
"ERRORx := 0",
|
||||
}
|
||||
|
||||
func String(s string) (string, error) {
|
||||
res, err := Source([]byte(s))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(res), nil
|
||||
}
|
||||
|
||||
func TestPartial(t *testing.T) {
|
||||
for _, src := range tests {
|
||||
if strings.HasPrefix(src, "ERROR") {
|
||||
// test expected to fail
|
||||
src = src[5:] // remove ERROR prefix
|
||||
res, err := String(src)
|
||||
if err == nil && res == src {
|
||||
t.Errorf("formatting succeeded but was expected to fail:\n%q", src)
|
||||
}
|
||||
} else {
|
||||
// test expected to succeed
|
||||
res, err := String(src)
|
||||
if err != nil {
|
||||
t.Errorf("formatting failed (%s):\n%q", err, src)
|
||||
} else if res != src {
|
||||
t.Errorf("formatting incorrect:\nsource: %q\nresult: %q", src, res)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,189 +0,0 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This file implements a parser test harness. The files in the testdata
|
||||
// directory are parsed and the errors reported are compared against the
|
||||
// error messages expected in the test files. The test files must end in
|
||||
// .src rather than .go so that they are not disturbed by gofmt runs.
|
||||
//
|
||||
// Expected errors are indicated in the test files by putting a comment
|
||||
// of the form /* ERROR "rx" */ immediately following an offending token.
|
||||
// The harness will verify that an error matching the regular expression
|
||||
// rx is reported at that source position.
|
||||
//
|
||||
// For instance, the following test file indicates that a "not declared"
|
||||
// error should be reported for the undeclared variable x:
|
||||
//
|
||||
// package p
|
||||
// func f() {
|
||||
// _ = x /* ERROR "not declared" */ + 1
|
||||
// }
|
||||
|
||||
package parser
|
||||
|
||||
import (
|
||||
"io/fs"
|
||||
"io/ioutil"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"wa-lang.org/wa/internal/scanner"
|
||||
"wa-lang.org/wa/internal/token"
|
||||
)
|
||||
|
||||
const testdata = "testdata"
|
||||
|
||||
// getFile assumes that each filename occurs at most once
|
||||
func getFile(fset *token.FileSet, filename string) (file *token.File) {
|
||||
fset.Iterate(func(f *token.File) bool {
|
||||
if f.Name() == filename {
|
||||
if file != nil {
|
||||
panic(filename + " used multiple times")
|
||||
}
|
||||
file = f
|
||||
}
|
||||
return true
|
||||
})
|
||||
return file
|
||||
}
|
||||
|
||||
func getPos(fset *token.FileSet, filename string, offset int) token.Pos {
|
||||
if f := getFile(fset, filename); f != nil {
|
||||
return f.Pos(offset)
|
||||
}
|
||||
return token.NoPos
|
||||
}
|
||||
|
||||
// ERROR comments must be of the form /* ERROR "rx" */ and rx is
|
||||
// a regular expression that matches the expected error message.
|
||||
// The special form /* ERROR HERE "rx" */ must be used for error
|
||||
// messages that appear immediately after a token, rather than at
|
||||
// a token's position.
|
||||
//
|
||||
var errRx = regexp.MustCompile(`^/\* *ERROR *(HERE)? *"([^"]*)" *\*/$`)
|
||||
|
||||
// expectedErrors collects the regular expressions of ERROR comments found
|
||||
// in files and returns them as a map of error positions to error messages.
|
||||
//
|
||||
func expectedErrors(fset *token.FileSet, filename string, src []byte) map[token.Pos]string {
|
||||
errors := make(map[token.Pos]string)
|
||||
|
||||
var s scanner.Scanner
|
||||
// file was parsed already - do not add it again to the file
|
||||
// set otherwise the position information returned here will
|
||||
// not match the position information collected by the parser
|
||||
s.Init(getFile(fset, filename), src, nil, scanner.ScanComments)
|
||||
var prev token.Pos // position of last non-comment, non-semicolon token
|
||||
var here token.Pos // position immediately after the token at position prev
|
||||
|
||||
for {
|
||||
pos, tok, lit := s.Scan()
|
||||
switch tok {
|
||||
case token.EOF:
|
||||
return errors
|
||||
case token.COMMENT:
|
||||
s := errRx.FindStringSubmatch(lit)
|
||||
if len(s) == 3 {
|
||||
pos := prev
|
||||
if s[1] == "HERE" {
|
||||
pos = here
|
||||
}
|
||||
errors[pos] = string(s[2])
|
||||
}
|
||||
case token.SEMICOLON:
|
||||
// don't use the position of auto-inserted (invisible) semicolons
|
||||
if lit != ";" {
|
||||
break
|
||||
}
|
||||
fallthrough
|
||||
default:
|
||||
prev = pos
|
||||
var l int // token length
|
||||
if tok.IsLiteral() {
|
||||
l = len(lit)
|
||||
} else {
|
||||
l = len(tok.String())
|
||||
}
|
||||
here = prev + token.Pos(l)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// compareErrors compares the map of expected error messages with the list
|
||||
// of found errors and reports discrepancies.
|
||||
//
|
||||
func compareErrors(t *testing.T, fset *token.FileSet, expected map[token.Pos]string, found scanner.ErrorList) {
|
||||
for _, error := range found {
|
||||
// error.Pos is a token.Position, but we want
|
||||
// a token.Pos so we can do a map lookup
|
||||
pos := getPos(fset, error.Pos.Filename, error.Pos.Offset)
|
||||
if msg, found := expected[pos]; found {
|
||||
// we expect a message at pos; check if it matches
|
||||
rx, err := regexp.Compile(msg)
|
||||
if err != nil {
|
||||
t.Errorf("%s: %v", error.Pos, err)
|
||||
continue
|
||||
}
|
||||
if match := rx.MatchString(error.Msg); !match {
|
||||
t.Errorf("%s: %q does not match %q", error.Pos, error.Msg, msg)
|
||||
continue
|
||||
}
|
||||
// we have a match - eliminate this error
|
||||
delete(expected, pos)
|
||||
} else {
|
||||
// To keep in mind when analyzing failed test output:
|
||||
// If the same error position occurs multiple times in errors,
|
||||
// this message will be triggered (because the first error at
|
||||
// the position removes this position from the expected errors).
|
||||
t.Errorf("%s: unexpected error: %s", error.Pos, error.Msg)
|
||||
}
|
||||
}
|
||||
|
||||
// there should be no expected errors left
|
||||
if len(expected) > 0 {
|
||||
t.Errorf("%d errors not reported:", len(expected))
|
||||
for pos, msg := range expected {
|
||||
t.Errorf("%s: %s\n", fset.Position(pos), msg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func checkErrors(vfs fs.FS, t *testing.T, filename string, input interface{}) {
|
||||
src, err := readSource(vfs, filename, input)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
fset := token.NewFileSet()
|
||||
_, err = ParseFile(vfs, fset, filename, src, DeclarationErrors|AllErrors)
|
||||
found, ok := err.(scanner.ErrorList)
|
||||
if err != nil && !ok {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
found.RemoveMultiples()
|
||||
|
||||
// we are expecting the following errors
|
||||
// (collect these after parsing a file so that it is found in the file set)
|
||||
expected := expectedErrors(fset, filename, src)
|
||||
|
||||
// verify errors returned by the parser
|
||||
compareErrors(t, fset, expected, found)
|
||||
}
|
||||
|
||||
func TestErrors(t *testing.T) {
|
||||
list, err := ioutil.ReadDir(testdata)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for _, fi := range list {
|
||||
name := fi.Name()
|
||||
if !fi.IsDir() && !strings.HasPrefix(name, ".") && strings.HasSuffix(name, ".src") {
|
||||
checkErrors(nil, t, filepath.Join(testdata, name), nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,248 +0,0 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This file contains the exported entry points for invoking the parser.
|
||||
|
||||
package parser
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"io"
|
||||
"io/fs"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"wa-lang.org/wa/internal/ast"
|
||||
"wa-lang.org/wa/internal/token"
|
||||
)
|
||||
|
||||
// If src != nil, readSource converts src to a []byte if possible;
|
||||
// otherwise it returns an error. If src == nil, readSource returns
|
||||
// the result of reading the file specified by filename.
|
||||
//
|
||||
func readSource(vfs fs.FS, filename string, src interface{}) ([]byte, error) {
|
||||
if src != nil {
|
||||
switch s := src.(type) {
|
||||
case string:
|
||||
return []byte(s), nil
|
||||
case []byte:
|
||||
return s, nil
|
||||
case *bytes.Buffer:
|
||||
// is io.Reader, but src is already available in []byte form
|
||||
if s != nil {
|
||||
return s.Bytes(), nil
|
||||
}
|
||||
case io.Reader:
|
||||
return ioutil.ReadAll(s)
|
||||
}
|
||||
return nil, errors.New("invalid source")
|
||||
}
|
||||
if vfs != nil {
|
||||
return fs.ReadFile(vfs, filename)
|
||||
}
|
||||
return os.ReadFile(filename)
|
||||
}
|
||||
|
||||
// A Mode value is a set of flags (or 0).
|
||||
// They control the amount of source code parsed and other optional
|
||||
// parser functionality.
|
||||
//
|
||||
type Mode uint
|
||||
|
||||
const (
|
||||
PackageClauseOnly Mode = 1 << iota // stop parsing after package clause
|
||||
ImportsOnly // stop parsing after import declarations
|
||||
ParseComments // parse comments and add them to AST
|
||||
Trace // print a trace of parsed productions
|
||||
DeclarationErrors // report declaration errors
|
||||
SpuriousErrors // same as AllErrors, for backward-compatibility
|
||||
AllErrors = SpuriousErrors // report all errors (not just the first 10 on different lines)
|
||||
)
|
||||
|
||||
// ParseFile parses the source code of a single Go source file and returns
|
||||
// the corresponding ast.File node. The source code may be provided via
|
||||
// the filename of the source file, or via the src parameter.
|
||||
//
|
||||
// If src != nil, ParseFile parses the source from src and the filename is
|
||||
// only used when recording position information. The type of the argument
|
||||
// for the src parameter must be string, []byte, or io.Reader.
|
||||
// If src == nil, ParseFile parses the file specified by filename.
|
||||
//
|
||||
// The mode parameter controls the amount of source text parsed and other
|
||||
// optional parser functionality. Position information is recorded in the
|
||||
// file set fset, which must not be nil.
|
||||
//
|
||||
// If the source couldn't be read, the returned AST is nil and the error
|
||||
// indicates the specific failure. If the source was read but syntax
|
||||
// errors were found, the result is a partial AST (with ast.Bad* nodes
|
||||
// representing the fragments of erroneous source code). Multiple errors
|
||||
// are returned via a scanner.ErrorList which is sorted by file position.
|
||||
//
|
||||
func ParseFile(vfs fs.FS, fset *token.FileSet, filename string, src interface{}, mode Mode) (f *ast.File, err error) {
|
||||
if fset == nil {
|
||||
panic("parser.ParseFile: no token.FileSet provided (fset == nil)")
|
||||
}
|
||||
|
||||
// get source
|
||||
text, err := readSource(vfs, filename, src)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var p parser
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
// resume same panic if it's not a bailout
|
||||
if _, ok := e.(bailout); !ok {
|
||||
panic(e)
|
||||
}
|
||||
}
|
||||
|
||||
// set result values
|
||||
if f == nil {
|
||||
// source is not a valid Go source file - satisfy
|
||||
// ParseFile API and return a valid (but) empty
|
||||
// *ast.File
|
||||
f = &ast.File{
|
||||
Name: new(ast.Ident),
|
||||
Scope: ast.NewScope(nil),
|
||||
}
|
||||
}
|
||||
|
||||
p.errors.Sort()
|
||||
err = p.errors.Err()
|
||||
}()
|
||||
|
||||
// parse source
|
||||
p.init(fset, filename, text, mode)
|
||||
f = p.parseFile()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// ParseDir calls ParseFile for all files with names ending in ".wa" in the
|
||||
// directory specified by path and returns a map of package name -> package
|
||||
// AST with all the packages found.
|
||||
//
|
||||
// If filter != nil, only the files with os.FileInfo entries passing through
|
||||
// the filter (and ending in ".wa") are considered. The mode bits are passed
|
||||
// to ParseFile unchanged. Position information is recorded in fset, which
|
||||
// must not be nil.
|
||||
//
|
||||
// If the directory couldn't be read, a nil map and the respective error are
|
||||
// returned. If a parse error occurred, a non-nil but incomplete map and the
|
||||
// first error encountered are returned.
|
||||
//
|
||||
func ParseDir(vfs fs.FS, fset *token.FileSet, path string, filter func(os.FileInfo) bool, mode Mode) (pkgs map[string]*ast.Package, first error) {
|
||||
fd, err := os.Open(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer fd.Close()
|
||||
|
||||
list, err := fd.Readdir(-1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pkgs = make(map[string]*ast.Package)
|
||||
for _, d := range list {
|
||||
if strHasSuffix(d.Name(), ".wa") {
|
||||
if filter == nil || filter(d) {
|
||||
filename := filepath.Join(path, d.Name())
|
||||
if src, err := ParseFile(vfs, fset, filename, nil, mode); err == nil {
|
||||
name := src.Name.Name
|
||||
pkg, found := pkgs[name]
|
||||
if !found {
|
||||
pkg = &ast.Package{
|
||||
Name: name,
|
||||
Files: make(map[string]*ast.File),
|
||||
}
|
||||
pkgs[name] = pkg
|
||||
}
|
||||
pkg.Files[filename] = src
|
||||
} else if first == nil {
|
||||
first = err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func strHasSuffix(s string, ext ...string) bool {
|
||||
for _, suffix := range ext {
|
||||
if strings.HasSuffix(s, suffix) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// ParseExprFrom is a convenience function for parsing an expression.
|
||||
// The arguments have the same meaning as for ParseFile, but the source must
|
||||
// be a valid Go (type or value) expression. Specifically, fset must not
|
||||
// be nil.
|
||||
//
|
||||
func ParseExprFrom(fset *token.FileSet, filename string, src interface{}, mode Mode) (ast.Expr, error) {
|
||||
if fset == nil {
|
||||
panic("parser.ParseExprFrom: no token.FileSet provided (fset == nil)")
|
||||
}
|
||||
|
||||
// get source
|
||||
text, err := readSource(nil, filename, src)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var p parser
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
// resume same panic if it's not a bailout
|
||||
if _, ok := e.(bailout); !ok {
|
||||
panic(e)
|
||||
}
|
||||
}
|
||||
p.errors.Sort()
|
||||
err = p.errors.Err()
|
||||
}()
|
||||
|
||||
// parse expr
|
||||
p.init(fset, filename, text, mode)
|
||||
// Set up pkg-level scopes to avoid nil-pointer errors.
|
||||
// This is not needed for a correct expression x as the
|
||||
// parser will be ok with a nil topScope, but be cautious
|
||||
// in case of an erroneous x.
|
||||
p.openScope()
|
||||
p.pkgScope = p.topScope
|
||||
e := p.parseRhsOrType()
|
||||
p.closeScope()
|
||||
assert(p.topScope == nil, "unbalanced scopes")
|
||||
|
||||
// If a semicolon was inserted, consume it;
|
||||
// report an error if there's more tokens.
|
||||
if p.tok == token.SEMICOLON && p.lit == "\n" {
|
||||
p.next()
|
||||
}
|
||||
p.expect(token.EOF)
|
||||
|
||||
if p.errors.Len() > 0 {
|
||||
p.errors.Sort()
|
||||
return nil, p.errors.Err()
|
||||
}
|
||||
|
||||
return e, nil
|
||||
}
|
||||
|
||||
// ParseExpr is a convenience function for obtaining the AST of an expression x.
|
||||
// The position information recorded in the AST is undefined. The filename used
|
||||
// in error messages is the empty string.
|
||||
//
|
||||
func ParseExpr(x string) (ast.Expr, error) {
|
||||
return ParseExprFrom(token.NewFileSet(), "", []byte(x), 0)
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,549 +0,0 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package parser
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"wa-lang.org/wa/internal/ast"
|
||||
"wa-lang.org/wa/internal/token"
|
||||
)
|
||||
|
||||
var validFiles = []string{
|
||||
"parser.go.wa",
|
||||
"parser_test.go.wa",
|
||||
"error_test.go.wa",
|
||||
"short_test.go.wa",
|
||||
}
|
||||
|
||||
func TestParse(t *testing.T) {
|
||||
for _, filename := range validFiles {
|
||||
_, err := ParseFile(nil, token.NewFileSet(), filename, nil, DeclarationErrors)
|
||||
if err != nil {
|
||||
t.Fatalf("ParseFile(%s): %v", filename, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func nameFilter(filename string) bool {
|
||||
switch filename {
|
||||
case "parser.go", "interface.go", "parser_test.go":
|
||||
return true
|
||||
case "parser.go.orig":
|
||||
return true // permit but should be ignored by ParseDir
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func dirFilter(f os.FileInfo) bool { return nameFilter(f.Name()) }
|
||||
|
||||
func TestParseDir(t *testing.T) {
|
||||
path := "."
|
||||
pkgs, err := ParseDir(nil, token.NewFileSet(), path, dirFilter, 0)
|
||||
if err != nil {
|
||||
t.Fatalf("ParseDir(%s): %v", path, err)
|
||||
}
|
||||
if n := len(pkgs); n != 1 {
|
||||
t.Errorf("got %d packages; want 1", n)
|
||||
}
|
||||
pkg := pkgs["parser"]
|
||||
if pkg == nil {
|
||||
t.Errorf(`package "parser" not found`)
|
||||
return
|
||||
}
|
||||
if n := len(pkg.Files); n != 3 {
|
||||
t.Errorf("got %d package files; want 3", n)
|
||||
}
|
||||
for filename := range pkg.Files {
|
||||
if !nameFilter(filename) {
|
||||
t.Errorf("unexpected package file: %s", filename)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseExpr(t *testing.T) {
|
||||
// just kicking the tires:
|
||||
// a valid arithmetic expression
|
||||
src := "a + b"
|
||||
x, err := ParseExpr(src)
|
||||
if err != nil {
|
||||
t.Errorf("ParseExpr(%q): %v", src, err)
|
||||
}
|
||||
// sanity check
|
||||
if _, ok := x.(*ast.BinaryExpr); !ok {
|
||||
t.Errorf("ParseExpr(%q): got %T, want *ast.BinaryExpr", src, x)
|
||||
}
|
||||
|
||||
// a valid type expression
|
||||
src = "struct{x *int}"
|
||||
x, err = ParseExpr(src)
|
||||
if err != nil {
|
||||
t.Errorf("ParseExpr(%q): %v", src, err)
|
||||
}
|
||||
// sanity check
|
||||
if _, ok := x.(*ast.StructType); !ok {
|
||||
t.Errorf("ParseExpr(%q): got %T, want *ast.StructType", src, x)
|
||||
}
|
||||
|
||||
// an invalid expression
|
||||
src = "a + *"
|
||||
if _, err := ParseExpr(src); err == nil {
|
||||
t.Errorf("ParseExpr(%q): got no error", src)
|
||||
}
|
||||
|
||||
// a valid expression followed by extra tokens is invalid
|
||||
src = "a[i] := x"
|
||||
if _, err := ParseExpr(src); err == nil {
|
||||
t.Errorf("ParseExpr(%q): got no error", src)
|
||||
}
|
||||
|
||||
// a semicolon is not permitted unless automatically inserted
|
||||
src = "a + b\n"
|
||||
if _, err := ParseExpr(src); err != nil {
|
||||
t.Errorf("ParseExpr(%q): got error %s", src, err)
|
||||
}
|
||||
src = "a + b;"
|
||||
if _, err := ParseExpr(src); err == nil {
|
||||
t.Errorf("ParseExpr(%q): got no error", src)
|
||||
}
|
||||
|
||||
// various other stuff following a valid expression
|
||||
const validExpr = "a + b"
|
||||
const anything = "dh3*#D)#_"
|
||||
for _, c := range "!)]};," {
|
||||
src := validExpr + string(c) + anything
|
||||
if _, err := ParseExpr(src); err == nil {
|
||||
t.Errorf("ParseExpr(%q): got no error", src)
|
||||
}
|
||||
}
|
||||
|
||||
// ParseExpr must not crash
|
||||
for _, src := range valids {
|
||||
ParseExpr(src)
|
||||
}
|
||||
}
|
||||
|
||||
func TestColonEqualsScope(t *testing.T) {
|
||||
f, err := ParseFile(nil, token.NewFileSet(), "", `package p; func f() { x, y, z := x, y, z }`, 0)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// RHS refers to undefined globals; LHS does not.
|
||||
as := f.Decls[0].(*ast.FuncDecl).Body.List[0].(*ast.AssignStmt)
|
||||
for _, v := range as.Rhs {
|
||||
id := v.(*ast.Ident)
|
||||
if id.Obj != nil {
|
||||
t.Errorf("rhs %s has Obj, should not", id.Name)
|
||||
}
|
||||
}
|
||||
for _, v := range as.Lhs {
|
||||
id := v.(*ast.Ident)
|
||||
if id.Obj == nil {
|
||||
t.Errorf("lhs %s does not have Obj, should", id.Name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestVarScope(t *testing.T) {
|
||||
f, err := ParseFile(nil, token.NewFileSet(), "", `package p; func f() { var x, y, z = x, y, z }`, 0)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// RHS refers to undefined globals; LHS does not.
|
||||
as := f.Decls[0].(*ast.FuncDecl).Body.List[0].(*ast.DeclStmt).Decl.(*ast.GenDecl).Specs[0].(*ast.ValueSpec)
|
||||
for _, v := range as.Values {
|
||||
id := v.(*ast.Ident)
|
||||
if id.Obj != nil {
|
||||
t.Errorf("rhs %s has Obj, should not", id.Name)
|
||||
}
|
||||
}
|
||||
for _, id := range as.Names {
|
||||
if id.Obj == nil {
|
||||
t.Errorf("lhs %s does not have Obj, should", id.Name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestObjects(t *testing.T) {
|
||||
const src = `
|
||||
package p
|
||||
import fmt "fmt"
|
||||
const pi = 3.14
|
||||
type T struct{}
|
||||
var x int
|
||||
func f() { L: }
|
||||
`
|
||||
|
||||
f, err := ParseFile(nil, token.NewFileSet(), "", src, 0)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
objects := map[string]ast.ObjKind{
|
||||
"p": ast.Bad, // not in a scope
|
||||
"fmt": ast.Bad, // not resolved yet
|
||||
"pi": ast.Con,
|
||||
"T": ast.Typ,
|
||||
"x": ast.Var,
|
||||
"int": ast.Bad, // not resolved yet
|
||||
"f": ast.Fun,
|
||||
"L": ast.Lbl,
|
||||
}
|
||||
|
||||
ast.Inspect(f, func(n ast.Node) bool {
|
||||
if ident, ok := n.(*ast.Ident); ok {
|
||||
obj := ident.Obj
|
||||
if obj == nil {
|
||||
if objects[ident.Name] != ast.Bad {
|
||||
t.Errorf("no object for %s", ident.Name)
|
||||
}
|
||||
return true
|
||||
}
|
||||
if obj.Name != ident.Name {
|
||||
t.Errorf("names don't match: obj.Name = %s, ident.Name = %s", obj.Name, ident.Name)
|
||||
}
|
||||
kind := objects[ident.Name]
|
||||
if obj.Kind != kind {
|
||||
t.Errorf("%s: obj.Kind = %s; want %s", ident.Name, obj.Kind, kind)
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
func TestUnresolved(t *testing.T) {
|
||||
f, err := ParseFile(nil, token.NewFileSet(), "", `
|
||||
package p
|
||||
//
|
||||
func f1a(int)
|
||||
func f2a(byte, int, float)
|
||||
func f3a(a, b int, c float)
|
||||
func f4a(...complex)
|
||||
func f5a(a s1a, b ...complex)
|
||||
//
|
||||
func f1b(*int)
|
||||
func f2b([]byte, (int), *float)
|
||||
func f3b(a, b *int, c []float)
|
||||
func f4b(...*complex)
|
||||
func f5b(a s1a, b ...[]complex)
|
||||
//
|
||||
type s1a struct { int }
|
||||
type s2a struct { byte; int; s1a }
|
||||
type s3a struct { a, b int; c float }
|
||||
//
|
||||
type s1b struct { *int }
|
||||
type s2b struct { byte; int; *float }
|
||||
type s3b struct { a, b *s3b; c []float }
|
||||
`, 0)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
want := "int " + // f1a
|
||||
"byte int float " + // f2a
|
||||
"int float " + // f3a
|
||||
"complex " + // f4a
|
||||
"complex " + // f5a
|
||||
//
|
||||
"int " + // f1b
|
||||
"byte int float " + // f2b
|
||||
"int float " + // f3b
|
||||
"complex " + // f4b
|
||||
"complex " + // f5b
|
||||
//
|
||||
"int " + // s1a
|
||||
"byte int " + // s2a
|
||||
"int float " + // s3a
|
||||
//
|
||||
"int " + // s1a
|
||||
"byte int float " + // s2a
|
||||
"float " // s3a
|
||||
|
||||
// collect unresolved identifiers
|
||||
var buf bytes.Buffer
|
||||
for _, u := range f.Unresolved {
|
||||
buf.WriteString(u.Name)
|
||||
buf.WriteByte(' ')
|
||||
}
|
||||
got := buf.String()
|
||||
|
||||
if got != want {
|
||||
t.Errorf("\ngot: %s\nwant: %s", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
var imports = map[string]bool{
|
||||
`"a"`: true,
|
||||
"`a`": true,
|
||||
`"a/b"`: true,
|
||||
`"a.b"`: true,
|
||||
`"m\x61th"`: true,
|
||||
`"greek/αβ"`: true,
|
||||
`""`: false,
|
||||
|
||||
// Each of these pairs tests both `` vs "" strings
|
||||
// and also use of invalid characters spelled out as
|
||||
// escape sequences and written directly.
|
||||
// For example `"\x00"` tests import "\x00"
|
||||
// while "`\x00`" tests import `<actual-NUL-byte>`.
|
||||
`"\x00"`: false,
|
||||
"`\x00`": false,
|
||||
`"\x7f"`: false,
|
||||
"`\x7f`": false,
|
||||
`"a!"`: false,
|
||||
"`a!`": false,
|
||||
`"a b"`: false,
|
||||
"`a b`": false,
|
||||
`"a\\b"`: false,
|
||||
"`a\\b`": false,
|
||||
"\"`a`\"": false,
|
||||
"`\"a\"`": false,
|
||||
`"\x80\x80"`: false,
|
||||
"`\x80\x80`": false,
|
||||
`"\xFFFD"`: false,
|
||||
"`\xFFFD`": false,
|
||||
}
|
||||
|
||||
func TestImports(t *testing.T) {
|
||||
for path, isValid := range imports {
|
||||
src := fmt.Sprintf("package p; import %s", path)
|
||||
_, err := ParseFile(nil, token.NewFileSet(), "", src, 0)
|
||||
switch {
|
||||
case err != nil && isValid:
|
||||
t.Errorf("ParseFile(%s): got %v; expected no error", src, err)
|
||||
case err == nil && !isValid:
|
||||
t.Errorf("ParseFile(%s): got no error; expected one", src)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestCommentGroups(t *testing.T) {
|
||||
f, err := ParseFile(nil, token.NewFileSet(), "", `
|
||||
package p /* 1a */ /* 1b */ /* 1c */ // 1d
|
||||
/* 2a
|
||||
*/
|
||||
// 2b
|
||||
const pi = 3.1415
|
||||
/* 3a */ // 3b
|
||||
/* 3c */ const e = 2.7182
|
||||
|
||||
// Example from issue 3139
|
||||
func ExampleCount() {
|
||||
fmt.Println(strings.Count("cheese", "e"))
|
||||
fmt.Println(strings.Count("five", "")) // before & after each rune
|
||||
// Output:
|
||||
// 3
|
||||
// 5
|
||||
}
|
||||
`, ParseComments)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
expected := [][]string{
|
||||
{"/* 1a */", "/* 1b */", "/* 1c */", "// 1d"},
|
||||
{"/* 2a\n*/", "// 2b"},
|
||||
{"/* 3a */", "// 3b", "/* 3c */"},
|
||||
{"// Example from issue 3139"},
|
||||
{"// before & after each rune"},
|
||||
{"// Output:", "// 3", "// 5"},
|
||||
}
|
||||
if len(f.Comments) != len(expected) {
|
||||
t.Fatalf("got %d comment groups; expected %d", len(f.Comments), len(expected))
|
||||
}
|
||||
for i, exp := range expected {
|
||||
got := f.Comments[i].List
|
||||
if len(got) != len(exp) {
|
||||
t.Errorf("got %d comments in group %d; expected %d", len(got), i, len(exp))
|
||||
continue
|
||||
}
|
||||
for j, exp := range exp {
|
||||
got := got[j].Text
|
||||
if got != exp {
|
||||
t.Errorf("got %q in group %d; expected %q", got, i, exp)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func getField(file *ast.File, fieldname string) *ast.Field {
|
||||
parts := strings.Split(fieldname, ".")
|
||||
for _, d := range file.Decls {
|
||||
if d, ok := d.(*ast.GenDecl); ok && d.Tok == token.TYPE {
|
||||
for _, s := range d.Specs {
|
||||
if s, ok := s.(*ast.TypeSpec); ok && s.Name.Name == parts[0] {
|
||||
if s, ok := s.Type.(*ast.StructType); ok {
|
||||
for _, f := range s.Fields.List {
|
||||
for _, name := range f.Names {
|
||||
if name.Name == parts[1] {
|
||||
return f
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Don't use ast.CommentGroup.Text() - we want to see exact comment text.
|
||||
func commentText(c *ast.CommentGroup) string {
|
||||
var buf bytes.Buffer
|
||||
if c != nil {
|
||||
for _, c := range c.List {
|
||||
buf.WriteString(c.Text)
|
||||
}
|
||||
}
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
func checkFieldComments(t *testing.T, file *ast.File, fieldname, lead, line string) {
|
||||
f := getField(file, fieldname)
|
||||
if f == nil {
|
||||
t.Fatalf("field not found: %s", fieldname)
|
||||
}
|
||||
if got := commentText(f.Doc); got != lead {
|
||||
t.Errorf("got lead comment %q; expected %q", got, lead)
|
||||
}
|
||||
if got := commentText(f.Comment); got != line {
|
||||
t.Errorf("got line comment %q; expected %q", got, line)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLeadAndLineComments(t *testing.T) {
|
||||
f, err := ParseFile(nil, token.NewFileSet(), "", `
|
||||
package p
|
||||
type T struct {
|
||||
/* F1 lead comment */
|
||||
//
|
||||
F1 int /* F1 */ // line comment
|
||||
// F2 lead
|
||||
// comment
|
||||
F2 int // F2 line comment
|
||||
// f3 lead comment
|
||||
f3 int // f3 line comment
|
||||
}
|
||||
`, ParseComments)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
checkFieldComments(t, f, "T.F1", "/* F1 lead comment *///", "/* F1 */// line comment")
|
||||
checkFieldComments(t, f, "T.F2", "// F2 lead// comment", "// F2 line comment")
|
||||
checkFieldComments(t, f, "T.f3", "// f3 lead comment", "// f3 line comment")
|
||||
ast.FileExports(f)
|
||||
checkFieldComments(t, f, "T.F1", "/* F1 lead comment *///", "/* F1 */// line comment")
|
||||
checkFieldComments(t, f, "T.F2", "// F2 lead// comment", "// F2 line comment")
|
||||
if getField(f, "T.f3") != nil {
|
||||
t.Error("not expected to find T.f3")
|
||||
}
|
||||
}
|
||||
|
||||
// TestIssue9979 verifies that empty statements are contained within their enclosing blocks.
|
||||
func TestIssue9979(t *testing.T) {
|
||||
for _, src := range []string{
|
||||
"package p; func f() {;}",
|
||||
"package p; func f() {L:}",
|
||||
"package p; func f() {L:;}",
|
||||
"package p; func f() {L:\n}",
|
||||
"package p; func f() {L:\n;}",
|
||||
"package p; func f() { ; }",
|
||||
"package p; func f() { L: }",
|
||||
"package p; func f() { L: ; }",
|
||||
"package p; func f() { L: \n}",
|
||||
"package p; func f() { L: \n; }",
|
||||
} {
|
||||
fset := token.NewFileSet()
|
||||
f, err := ParseFile(nil, fset, "", src, 0)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
var pos, end token.Pos
|
||||
ast.Inspect(f, func(x ast.Node) bool {
|
||||
switch s := x.(type) {
|
||||
case *ast.BlockStmt:
|
||||
pos, end = s.Pos()+1, s.End()-1 // exclude "{", "}"
|
||||
case *ast.LabeledStmt:
|
||||
pos, end = s.Pos()+2, s.End() // exclude "L:"
|
||||
case *ast.EmptyStmt:
|
||||
// check containment
|
||||
if s.Pos() < pos || s.End() > end {
|
||||
t.Errorf("%s: %T[%d, %d] not inside [%d, %d]", src, s, s.Pos(), s.End(), pos, end)
|
||||
}
|
||||
// check semicolon
|
||||
offs := fset.Position(s.Pos()).Offset
|
||||
if ch := src[offs]; ch != ';' != s.Implicit {
|
||||
want := "want ';'"
|
||||
if s.Implicit {
|
||||
want = "but ';' is implicit"
|
||||
}
|
||||
t.Errorf("%s: found %q at offset %d; %s", src, ch, offs, want)
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestIncompleteSelection ensures that an incomplete selector
|
||||
// expression is parsed as a (blank) *ast.SelectorExpr, not a
|
||||
// *ast.BadExpr.
|
||||
func TestIncompleteSelection(t *testing.T) {
|
||||
for _, src := range []string{
|
||||
"package p; var _ = fmt.", // at EOF
|
||||
"package p; var _ = fmt.\ntype X int", // not at EOF
|
||||
} {
|
||||
fset := token.NewFileSet()
|
||||
f, err := ParseFile(nil, fset, "", src, 0)
|
||||
if err == nil {
|
||||
t.Errorf("ParseFile(%s) succeeded unexpectedly", src)
|
||||
continue
|
||||
}
|
||||
|
||||
const wantErr = "expected selector or type assertion"
|
||||
if !strings.Contains(err.Error(), wantErr) {
|
||||
t.Errorf("ParseFile returned wrong error %q, want %q", err, wantErr)
|
||||
}
|
||||
|
||||
var sel *ast.SelectorExpr
|
||||
ast.Inspect(f, func(n ast.Node) bool {
|
||||
if n, ok := n.(*ast.SelectorExpr); ok {
|
||||
sel = n
|
||||
}
|
||||
return true
|
||||
})
|
||||
if sel == nil {
|
||||
t.Error("found no *ast.SelectorExpr")
|
||||
continue
|
||||
}
|
||||
const wantSel = "&{fmt _}"
|
||||
if fmt.Sprint(sel) != wantSel {
|
||||
t.Errorf("found selector %s, want %s", sel, wantSel)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestLastLineComment(t *testing.T) {
|
||||
const src = `package main
|
||||
type x int // comment
|
||||
`
|
||||
fset := token.NewFileSet()
|
||||
f, err := ParseFile(nil, fset, "", src, ParseComments)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
comment := f.Decls[0].(*ast.GenDecl).Specs[0].(*ast.TypeSpec).Comment.List[0].Text
|
||||
if comment != "// comment" {
|
||||
t.Errorf("got %q, want %q", comment, "// comment")
|
||||
}
|
||||
}
|
||||
@@ -1,122 +0,0 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This file contains test cases for short valid and invalid programs.
|
||||
|
||||
package parser
|
||||
|
||||
import "testing"
|
||||
|
||||
var valids = []string{
|
||||
"package p\n",
|
||||
`package p;`,
|
||||
`package p; import "fmt"; func f() { fmt.Println("Hello, World!") };`,
|
||||
`package p; func f() { if f(T{}) {} };`,
|
||||
`package p; func f(func() func() func());`,
|
||||
`package p; func f(...T);`,
|
||||
`package p; func f(float, ...int);`,
|
||||
`package p; func f(x int, a ...int) { f(0, a...); f(1, a...,) };`,
|
||||
`package p; func f(int,) {};`,
|
||||
`package p; func f(...int,) {};`,
|
||||
`package p; func f(x ...int,) {};`,
|
||||
`package p; type T []int; var a []bool; func f() { if a[T{42}[0]] {} };`,
|
||||
`package p; type T []int; func g(int) bool { return true }; func f() { if g(T{42}[0]) {} };`,
|
||||
`package p; type T []int; func f() { for _ = range []int{T{42}[0]} {} };`,
|
||||
`package p; var a = T{{1, 2}, {3, 4}}`,
|
||||
`package p; func f() { if ; true {} };`,
|
||||
`package p; func f() { switch ; {} };`,
|
||||
`package p; func f() { for _ = range "foo" + "bar" {} };`,
|
||||
`package p; func f() { var s []int; g(s[:], s[i:], s[:j], s[i:j], s[i:j:k], s[:j:k]) };`,
|
||||
`package p; var ( _ = (struct {*T}).m; _ = (interface {T}).m )`,
|
||||
`package p; func ((T),) m() {}`,
|
||||
`package p; func ((*T),) m() {}`,
|
||||
`package p; func (*(T),) m() {}`,
|
||||
`package p; func _(x []int) { for range x {} }`,
|
||||
`package p; func _() { if [T{}.n]int{} {} }`,
|
||||
`package p; func _() { map[int]int{}[0]++; map[int]int{}[0] += 1 }`,
|
||||
`package p; func _(x interface{f()}) { interface{f()}(x).f() }`,
|
||||
`package p; const (x = 0; y; z)`, // issue 9639
|
||||
`package p; var _ = map[P]int{P{}:0, {}:1}`,
|
||||
`package p; var _ = map[*P]int{&P{}:0, {}:1}`,
|
||||
`package p; type T = int`,
|
||||
`package p; type (T = p.T; _ = struct{}; x = *T)`,
|
||||
}
|
||||
|
||||
func TestValid(t *testing.T) {
|
||||
for _, src := range valids {
|
||||
checkErrors(nil, t, src, src)
|
||||
}
|
||||
}
|
||||
|
||||
var invalids = []string{
|
||||
// `foo /* ERROR "expected 'package'" */ !`,
|
||||
`package p; func f() { if { /* ERROR "missing condition" */ } };`,
|
||||
`package p; func f() { if ; /* ERROR "missing condition" */ {} };`,
|
||||
`package p; func f() { if f(); /* ERROR "missing condition" */ {} };`,
|
||||
`package p; func f() { if _ = range /* ERROR "expected operand" */ x; true {} };`,
|
||||
`package p; func f() { switch _ /* ERROR "expected switch expression" */ = range x; true {} };`,
|
||||
`package p; func f() { for _ = range x ; /* ERROR "expected '{'" */ ; {} };`,
|
||||
`package p; func f() { for ; ; _ = range /* ERROR "expected operand" */ x {} };`,
|
||||
`package p; func f() { for ; _ /* ERROR "expected boolean or range expression" */ = range x ; {} };`,
|
||||
`package p; func f() { switch t = /* ERROR "expected ':=', found '='" */ t.(type) {} };`,
|
||||
`package p; func f() { switch t /* ERROR "expected switch expression" */ , t = t.(type) {} };`,
|
||||
`package p; func f() { switch t /* ERROR "expected switch expression" */ = t.(type), t {} };`,
|
||||
`package p; var a = [ /* ERROR "expected expression" */ 1]int;`,
|
||||
`package p; var a = [ /* ERROR "expected expression" */ ...]int;`,
|
||||
`package p; var a = struct /* ERROR "expected expression" */ {}`,
|
||||
`package p; var a = func /* ERROR "expected expression" */ ();`,
|
||||
`package p; var a = interface /* ERROR "expected expression" */ {}`,
|
||||
`package p; var a = [ /* ERROR "expected expression" */ ]int`,
|
||||
`package p; var a = map /* ERROR "expected expression" */ [int]int`,
|
||||
`package p; var a = []int{[ /* ERROR "expected expression" */ ]int};`,
|
||||
`package p; var a = ( /* ERROR "expected expression" */ []int);`,
|
||||
`package p; var a = a[[ /* ERROR "expected expression" */ ]int:[]int];`,
|
||||
`package p; func f() { var t []int; t /* ERROR "expected identifier on left side of :=" */ [0] := 0 };`,
|
||||
`package p; func f() { if x := g(); x /* ERROR "expected boolean expression" */ = 0 {}};`,
|
||||
`package p; func f() { _ = x = /* ERROR "expected '=='" */ 0 {}};`,
|
||||
`package p; func f() { _ = 1 == func()int { var x bool; x = x = /* ERROR "expected '=='" */ true; return x }() };`,
|
||||
`package p; func f() { var s []int; _ = s[] /* ERROR "expected operand" */ };`,
|
||||
`package p; func f() { var s []int; _ = s[i:j: /* ERROR "3rd index required" */ ] };`,
|
||||
`package p; func f() { var s []int; _ = s[i: /* ERROR "2nd index required" */ :k] };`,
|
||||
`package p; func f() { var s []int; _ = s[i: /* ERROR "2nd index required" */ :] };`,
|
||||
`package p; func f() { var s []int; _ = s[: /* ERROR "2nd index required" */ :] };`,
|
||||
`package p; func f() { var s []int; _ = s[: /* ERROR "2nd index required" */ ::] };`,
|
||||
`package p; func f() { var s []int; _ = s[i:j:k: /* ERROR "expected ']'" */ l] };`,
|
||||
`package p; func f() { for x /* ERROR "boolean or range expression" */ = []string {} }`,
|
||||
`package p; func f() { for x /* ERROR "boolean or range expression" */ := []string {} }`,
|
||||
`package p; func f() { for i /* ERROR "boolean or range expression" */ , x = []string {} }`,
|
||||
`package p; func f() { for i /* ERROR "boolean or range expression" */ , x := []string {} }`,
|
||||
`package p; func f() { defer func() {} /* ERROR HERE "function must be invoked" */ }`,
|
||||
`package p; func f(x func(), u v func /* ERROR "missing ','" */ ()){}`,
|
||||
|
||||
// issue 8656
|
||||
`package p; func f() (a b string /* ERROR "missing ','" */ , ok bool)`,
|
||||
|
||||
// issue 9639
|
||||
`package p; var x /* ERROR "missing variable type or initialization" */ , y, z;`,
|
||||
`package p; const x /* ERROR "missing constant value" */ ;`,
|
||||
`package p; const x /* ERROR "missing constant value" */ int;`,
|
||||
`package p; const (x = 0; y; z /* ERROR "missing constant value" */ int);`,
|
||||
|
||||
// issue 12437
|
||||
`package p; var _ = struct { x int, /* ERROR "expected ';', found ','" */ }{};`,
|
||||
`package p; var _ = struct { x int, /* ERROR "expected ';', found ','" */ y float }{};`,
|
||||
|
||||
// issue 11611
|
||||
`package p; type _ struct { int, } /* ERROR "expected type, found '}'" */ ;`,
|
||||
`package p; type _ struct { int, float } /* ERROR "expected type, found '}'" */ ;`,
|
||||
`package p; type _ struct { ( /* ERROR "expected anonymous field" */ int) };`,
|
||||
`package p; func _()(x, y, z ... /* ERROR "expected '\)', found '...'" */ int){}`,
|
||||
`package p; func _()(... /* ERROR "expected type, found '...'" */ int){}`,
|
||||
|
||||
// issue 13475
|
||||
`package p; func f() { if true {} else ; /* ERROR "expected if statement or block" */ }`,
|
||||
`package p; func f() { if true {} else defer /* ERROR "expected if statement or block" */ f() }`,
|
||||
}
|
||||
|
||||
func TestInvalid(t *testing.T) {
|
||||
for _, src := range invalids {
|
||||
checkErrors(nil, t, src, src)
|
||||
}
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package printer_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"wa-lang.org/wa/internal/ast"
|
||||
"wa-lang.org/wa/internal/parser"
|
||||
"wa-lang.org/wa/internal/printer"
|
||||
"wa-lang.org/wa/internal/token"
|
||||
)
|
||||
|
||||
// Dummy test function so that godoc does not use the entire file as example.
|
||||
func Test(*testing.T) {}
|
||||
|
||||
func parseFunc(filename, functionname string) (fun *ast.FuncDecl, fset *token.FileSet) {
|
||||
fset = token.NewFileSet()
|
||||
if file, err := parser.ParseFile(nil, fset, filename, nil, 0); err == nil {
|
||||
for _, d := range file.Decls {
|
||||
if f, ok := d.(*ast.FuncDecl); ok && f.Name.Name == functionname {
|
||||
fun = f
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
panic("function not found")
|
||||
}
|
||||
|
||||
func ExampleFprint() {
|
||||
// Parse source file and extract the AST without comments for
|
||||
// this function, with position information referring to the
|
||||
// file set fset.
|
||||
funcAST, fset := parseFunc("example_test.go", "ExampleFprint")
|
||||
|
||||
// Print the function body into buffer buf.
|
||||
// The file set is provided to the printer so that it knows
|
||||
// about the original source formatting and can add additional
|
||||
// line breaks where they were present in the source.
|
||||
var buf bytes.Buffer
|
||||
printer.Fprint(&buf, fset, funcAST.Body)
|
||||
|
||||
// Remove braces {} enclosing the function body, unindent,
|
||||
// and trim leading and trailing white space.
|
||||
s := buf.String()
|
||||
s = s[1 : len(s)-1]
|
||||
s = strings.TrimSpace(strings.ReplaceAll(s, "\n\t", "\n"))
|
||||
|
||||
// Print the cleaned-up body text to stdout.
|
||||
fmt.Println(s)
|
||||
|
||||
// output:
|
||||
// funcAST, fset := parseFunc("example_test.go", "ExampleFprint")
|
||||
//
|
||||
// var buf bytes.Buffer
|
||||
// printer.Fprint(&buf, fset, funcAST.Body)
|
||||
//
|
||||
// s := buf.String()
|
||||
// s = s[1 : len(s)-1]
|
||||
// s = strings.TrimSpace(strings.ReplaceAll(s, "\n\t", "\n"))
|
||||
//
|
||||
// fmt.Println(s)
|
||||
}
|
||||
@@ -469,10 +469,10 @@ func (p *printer) fieldList(fields *ast.FieldList, isStruct, isIncomplete bool)
|
||||
}
|
||||
p.expr(x)
|
||||
}
|
||||
p.print(token.COLON)
|
||||
if len(f.Names) > 0 {
|
||||
p.print(blank)
|
||||
}
|
||||
p.print(token.COLON)
|
||||
p.expr(f.Type)
|
||||
} else { // interface
|
||||
if ftyp, isFtyp := f.Type.(*ast.FuncType); isFtyp {
|
||||
@@ -512,8 +512,8 @@ func (p *printer) fieldList(fields *ast.FieldList, isStruct, isIncomplete bool)
|
||||
if len(f.Names) > 0 {
|
||||
// named fields
|
||||
p.identList(f.Names, false)
|
||||
p.print(sep)
|
||||
p.print(token.COLON)
|
||||
p.print(sep)
|
||||
p.expr(f.Type)
|
||||
extraTabs = 1
|
||||
} else {
|
||||
@@ -1401,6 +1401,7 @@ func (p *printer) valueSpec(s *ast.ValueSpec, keepType bool) {
|
||||
extraTabs--
|
||||
}
|
||||
if s.Type != nil {
|
||||
p.print(token.COLON)
|
||||
p.expr(s.Type)
|
||||
}
|
||||
if s.Values != nil {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -3,6 +3,9 @@
|
||||
default:
|
||||
|
||||
ci-test-all:
|
||||
@echo "== fmt examples/... =="
|
||||
go run ../../main.go fmt ./...
|
||||
|
||||
@echo "== examples test begin =="
|
||||
|
||||
# loop forever
|
||||
@@ -12,6 +15,7 @@ ci-test-all:
|
||||
cd ./brainfuck && make
|
||||
cd ./expr && make
|
||||
cd ./hello && make
|
||||
cd ./misc && make
|
||||
cd ./pkg && make
|
||||
cd ./prime && make
|
||||
cd ./reftoptr && make
|
||||
|
||||
@@ -8,10 +8,10 @@ func main() {
|
||||
}
|
||||
|
||||
type BrainFuck struct {
|
||||
mem :[30000]byte
|
||||
code :string
|
||||
pos :int
|
||||
pc :int
|
||||
mem: [30000]byte
|
||||
code: string
|
||||
pos: int
|
||||
pc: int
|
||||
}
|
||||
|
||||
func NewBrainFuck(code: string) => *BrainFuck {
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
|
||||
// BF 虚拟机
|
||||
type BrainFuck struct {
|
||||
mem :[30000]byte
|
||||
code :string
|
||||
pos :int
|
||||
pc :int
|
||||
mem: [30000]byte
|
||||
code: string
|
||||
pos: int
|
||||
pc: int
|
||||
}
|
||||
|
||||
func NewBrainFuck(code: string) => *BrainFuck {
|
||||
|
||||
@@ -1,22 +1,23 @@
|
||||
// 版权 @2021 凹语言 作者。保留所有权利。
|
||||
|
||||
var s = []int{1, 2, 3, 4, 5, 6}
|
||||
|
||||
func main() {
|
||||
d := make([]int, 3)
|
||||
copy(d, s)
|
||||
for i, v := range d {
|
||||
println("d[", i, "]=", v)
|
||||
}
|
||||
|
||||
a := s[0:4]
|
||||
|
||||
a := s[0:4]
|
||||
b := s[1:5]
|
||||
copy(a, b)
|
||||
for i, v := range s {
|
||||
println("s[", i, "]=", v)
|
||||
}
|
||||
|
||||
|
||||
copy(b, a)
|
||||
for i, v := range s {
|
||||
println("s[", i, "]=", v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,9 +7,9 @@ func main {
|
||||
println("你好,凹语言!", runtime.WAOS)
|
||||
println(add(40, 2))
|
||||
|
||||
fmt.Println(1+1)
|
||||
fmt.Println(1 + 1)
|
||||
}
|
||||
|
||||
func add(a: i32, b: i32) => i32 {
|
||||
return a+b
|
||||
return a + b
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ type T1 struct {
|
||||
b: string
|
||||
}
|
||||
|
||||
func T1.print(){
|
||||
func T1.print() {
|
||||
println("a: ", this.a)
|
||||
}
|
||||
|
||||
@@ -18,8 +18,8 @@ type T2 struct {
|
||||
}
|
||||
|
||||
func main() {
|
||||
v1, v2: T1
|
||||
|
||||
var v1, v2: T1
|
||||
|
||||
v1.a = 13
|
||||
v2.a = 42
|
||||
if v1 == v2 {
|
||||
@@ -27,21 +27,21 @@ func main() {
|
||||
} else {
|
||||
println("ne")
|
||||
}
|
||||
|
||||
|
||||
v2.a = 13
|
||||
if v1 == v2 {
|
||||
println("eq")
|
||||
} else {
|
||||
println("ne")
|
||||
}
|
||||
|
||||
|
||||
v1.b = "abc"
|
||||
if v1 == v2 {
|
||||
println("eq")
|
||||
} else {
|
||||
println("ne")
|
||||
}
|
||||
|
||||
|
||||
v2.b = "abc"
|
||||
if v1 == v2 {
|
||||
println("eq")
|
||||
@@ -49,20 +49,20 @@ func main() {
|
||||
println("ne")
|
||||
}
|
||||
|
||||
i1, i2: interface{}
|
||||
var i1, i2: interface{}
|
||||
i1 = "abc"
|
||||
if i1 == nil{
|
||||
if i1 == nil {
|
||||
println("i1 == nil:eq")
|
||||
} else {
|
||||
println("i1 == nil:ne")
|
||||
}
|
||||
i1 = nil
|
||||
if i1 == nil{
|
||||
if i1 == nil {
|
||||
println("i1 == nil:eq")
|
||||
} else {
|
||||
println("i1 == nil:ne")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
i1 = i32(13)
|
||||
i2 = i32(42)
|
||||
if i1 == i2 {
|
||||
@@ -76,20 +76,20 @@ func main() {
|
||||
} else {
|
||||
println("ne")
|
||||
}
|
||||
|
||||
|
||||
i2 = "abc"
|
||||
if i1 == i2 {
|
||||
println("eq")
|
||||
} else {
|
||||
println("ne")
|
||||
}
|
||||
i1 = "abc"
|
||||
i1 = "abc"
|
||||
if i1 == i2 {
|
||||
println("eq")
|
||||
} else {
|
||||
println("ne")
|
||||
}
|
||||
|
||||
|
||||
i1 = v1
|
||||
if i1 == i2 {
|
||||
println("eq")
|
||||
@@ -102,35 +102,33 @@ func main() {
|
||||
} else {
|
||||
println("ne")
|
||||
}
|
||||
|
||||
i3: I
|
||||
|
||||
var i3: I
|
||||
i3 = &v1
|
||||
if i1 == i3 {
|
||||
if i1 == i3 {
|
||||
println("eq")
|
||||
} else {
|
||||
println("ne")
|
||||
}
|
||||
i1 = &v1
|
||||
if i1 == i3 {
|
||||
if i1 == i3 {
|
||||
println("eq")
|
||||
} else {
|
||||
println("ne")
|
||||
}
|
||||
|
||||
v3, v4: T2
|
||||
|
||||
var v3, v4: T2
|
||||
//if v3 == v4 {
|
||||
// println("eq")
|
||||
//} else {
|
||||
// println("ne")
|
||||
//}
|
||||
|
||||
|
||||
i1 = v3
|
||||
i2 = v4
|
||||
if i1 == i2 { //panic
|
||||
if i1 == i2 { //panic
|
||||
println("eq")
|
||||
} else {
|
||||
println("ne")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
import "strconv" => __yystrconv__
|
||||
|
||||
type exprSymType struct {
|
||||
yys :int
|
||||
num :int
|
||||
yys: int
|
||||
num: int
|
||||
}
|
||||
|
||||
const NUM = 57346
|
||||
@@ -36,13 +36,13 @@ const exprInitialStackSize = 16
|
||||
const eof = 0
|
||||
|
||||
type exprToken struct {
|
||||
Kind :int
|
||||
Value :int
|
||||
Kind: int
|
||||
Value: int
|
||||
}
|
||||
|
||||
type exprLexer struct {
|
||||
tokens :[]exprToken
|
||||
pos :int
|
||||
tokens: []exprToken
|
||||
pos: int
|
||||
}
|
||||
|
||||
func exprLexer.Lex(yylval: *exprSymType) => int {
|
||||
@@ -144,9 +144,9 @@ global exprTok3 = [...]int{
|
||||
}
|
||||
|
||||
type exprErrorMessageInfo struct {
|
||||
state :int
|
||||
token :int
|
||||
msg :string
|
||||
state: int
|
||||
token: int
|
||||
msg: string
|
||||
}
|
||||
|
||||
global exprErrorMessages = [...]exprErrorMessageInfo{}
|
||||
@@ -159,9 +159,9 @@ global (
|
||||
)
|
||||
|
||||
type exprParser struct {
|
||||
lval :exprSymType
|
||||
stack :[exprInitialStackSize]exprSymType
|
||||
char :int
|
||||
lval: exprSymType
|
||||
stack: [exprInitialStackSize]exprSymType
|
||||
char: int
|
||||
}
|
||||
|
||||
func exprParser.Lookahead => int {
|
||||
|
||||
@@ -5,8 +5,8 @@ import "3rdparty/pkg"
|
||||
import "myapp/mymath"
|
||||
|
||||
func main {
|
||||
fmt.Println(40+2)
|
||||
pkg.Println(100+2)
|
||||
fmt.Println(40 + 2)
|
||||
pkg.Println(100 + 2)
|
||||
println(mymath.I8Max)
|
||||
|
||||
println(sum(100))
|
||||
@@ -14,7 +14,7 @@ func main {
|
||||
}
|
||||
|
||||
func sum(n: int) => int {
|
||||
v: int
|
||||
var v: int
|
||||
for i := 1; i <= n; i++ {
|
||||
v += i
|
||||
}
|
||||
|
||||
@@ -20,44 +20,44 @@ func T1.f() {
|
||||
println("This is T1, this.a==", this.a)
|
||||
}
|
||||
|
||||
func T2.f(){
|
||||
func T2.f() {
|
||||
println("This is T2, this.b==", this.b)
|
||||
}
|
||||
|
||||
func main() {
|
||||
v1 := T1{a: 13}
|
||||
|
||||
i1: I1 = &v1 //具体类型到具名接口
|
||||
v1.f() //直接调用
|
||||
i1.f() //接口调用
|
||||
var i1: I1 = &v1 //具体类型到具名接口
|
||||
v1.f() //直接调用
|
||||
i1.f() //接口调用
|
||||
doConcreteType(i1)
|
||||
i1.f()
|
||||
|
||||
v2 := T2{b: 42}
|
||||
i1 = &v2 //具体类型到具名接口
|
||||
i1.f()
|
||||
doConcreteType(i1)
|
||||
i1.f()
|
||||
|
||||
ni: interface{} = &v1 //具体类型到空接口
|
||||
i1 = ni.(I1) //接口动态互转
|
||||
i1.f()
|
||||
|
||||
ni = &v2 //具体类型到空接口
|
||||
i1 = ni.(I1) //接口动态互转
|
||||
i1.f()
|
||||
|
||||
ival: i32 = 777
|
||||
v2 := T2{b: 42}
|
||||
i1 = &v2 //具体类型到具名接口
|
||||
i1.f()
|
||||
doConcreteType(i1)
|
||||
i1.f()
|
||||
|
||||
var ni: interface{} = &v1 //具体类型到空接口
|
||||
i1 = ni.(I1) //接口动态互转
|
||||
i1.f()
|
||||
|
||||
ni = &v2 //具体类型到空接口
|
||||
i1 = ni.(I1) //接口动态互转
|
||||
i1.f()
|
||||
|
||||
var ival: i32 = 777
|
||||
ni = ival
|
||||
doConcreteType(ni)
|
||||
doConcreteType(v1)
|
||||
doConcreteType(v2)
|
||||
doConcreteType("你好凹语言")
|
||||
|
||||
|
||||
//i2 := ni.(I2) //接口互转,由于v2未实现I2,这会触发异常
|
||||
//i2.f2()
|
||||
|
||||
anoni: interface{ f() } = &v1 //具体类型到匿名接口
|
||||
|
||||
var anoni: interface{ f() } = &v1 //具体类型到匿名接口
|
||||
anoni.f()
|
||||
i1 = anoni //匿名接口向具名接口转换
|
||||
i1.f()
|
||||
@@ -65,25 +65,25 @@ func main() {
|
||||
|
||||
func doConcreteType(i: interface{}) {
|
||||
//接口到具体类型断言
|
||||
switch c := i.(type){
|
||||
case *T1:
|
||||
println("*T1")
|
||||
c.a *= 2
|
||||
|
||||
case *T2:
|
||||
println("*T2")
|
||||
c.b *= 2
|
||||
switch c := i.(type) {
|
||||
case *T1:
|
||||
println("*T1")
|
||||
c.a *= 2
|
||||
|
||||
case i32:
|
||||
println("i32: ", c)
|
||||
case *T2:
|
||||
println("*T2")
|
||||
c.b *= 2
|
||||
|
||||
case string:
|
||||
println("string: ", c)
|
||||
case i32:
|
||||
println("i32: ", c)
|
||||
|
||||
case T1:
|
||||
println("T1, T1.a==", c.a)
|
||||
case string:
|
||||
println("string: ", c)
|
||||
|
||||
case T2:
|
||||
println("T2, T2.b==", c.b)
|
||||
case T1:
|
||||
println("T1, T1.a==", c.a)
|
||||
|
||||
case T2:
|
||||
println("T2, T2.b==", c.b)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ func main() {
|
||||
}
|
||||
|
||||
func test_array(a: int, b: int) {
|
||||
arr: [10][10]int
|
||||
var arr: [10][10]int
|
||||
for i := 0; i < 10; i++ {
|
||||
for j := 0; j < 10; j++ {
|
||||
arr[i][j] = i * j
|
||||
|
||||
@@ -8,7 +8,7 @@ type fff32 f32
|
||||
var arr1: [size]fff32
|
||||
|
||||
func makearr0a(i: int) => [size]fff32 {
|
||||
r: [size]fff32
|
||||
var r: [size]fff32
|
||||
for j := 0; j < size; j++ {
|
||||
r[j] = fff32(i * j)
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
// Test read/write global variables.
|
||||
|
||||
type ty0 struct {
|
||||
v0 :int
|
||||
v1 :f64
|
||||
v0: int
|
||||
v1: f64
|
||||
}
|
||||
|
||||
var gv0: ty0 = ty0{5555, 3.1415926}
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
// Test read/write global variables.
|
||||
|
||||
type ty0 struct {
|
||||
v0 :int
|
||||
v1 :f64
|
||||
v0: int
|
||||
v1: f64
|
||||
}
|
||||
|
||||
var gv0: ty0 = ty0{5555, 3.1415926}
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
// Test anonymous functions and closure functions.
|
||||
|
||||
type pair struct {
|
||||
i :f32
|
||||
j :f32
|
||||
i: f32
|
||||
j: f32
|
||||
}
|
||||
|
||||
func main() {
|
||||
@@ -12,9 +12,9 @@ func main() {
|
||||
println("World!")
|
||||
}()
|
||||
|
||||
i: int = 31
|
||||
j: [4]f32 = [4]f32{1, 2.2, 5.5, 9.8}
|
||||
k: pair = pair{3.14, 2.718}
|
||||
var i: int = 31
|
||||
var j: [4]f32 = [4]f32{1, 2.2, 5.5, 9.8}
|
||||
var k: pair = pair{3.14, 2.718}
|
||||
show := func(q: int) {
|
||||
println(i, " + ", q, " = ", i+q)
|
||||
println("{", j[0], ", ", j[1], ", ", j[2], ", ", j[3], "}")
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
// Test multiple return values.
|
||||
|
||||
type pair struct {
|
||||
a :f32
|
||||
b :f32
|
||||
a: f32
|
||||
b: f32
|
||||
}
|
||||
|
||||
func calc() => ([4]f32, pair, f32) {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
func main() {
|
||||
for n := 2; n <= 30; n = n + 1 {
|
||||
isPrime: int = 1
|
||||
var isPrime: int = 1
|
||||
for i := 2; i*i <= n; i = i + 1 {
|
||||
if x := n % i; x == 0 {
|
||||
isPrime = 0
|
||||
|
||||
@@ -10,10 +10,10 @@ func main() {
|
||||
}
|
||||
|
||||
type t0 struct {
|
||||
a :i64
|
||||
b :i32
|
||||
c :[4]f64
|
||||
d :u32
|
||||
a: i64
|
||||
b: i32
|
||||
c: [4]f64
|
||||
d: u32
|
||||
}
|
||||
|
||||
func test_struct(a: int) {
|
||||
|
||||
@@ -10,10 +10,10 @@ func main() {
|
||||
}
|
||||
|
||||
type t0 struct {
|
||||
a :i64
|
||||
b :i32
|
||||
c :[4]f64
|
||||
d :u32
|
||||
a: i64
|
||||
b: i32
|
||||
c: [4]f64
|
||||
d: u32
|
||||
}
|
||||
|
||||
func test_struct1(a: int, b: int, c: int) {
|
||||
|
||||
@@ -6,8 +6,8 @@ type fff32 f32
|
||||
const size = 16
|
||||
|
||||
type struct_t0 struct {
|
||||
arr0 :[size]int
|
||||
arr1 :[size]fff32
|
||||
arr0: [size]int
|
||||
arr1: [size]fff32
|
||||
}
|
||||
|
||||
var st0: struct_t0
|
||||
|
||||
@@ -4,14 +4,14 @@
|
||||
const size = 16
|
||||
|
||||
type struct_t0 struct {
|
||||
arr0 :[size]int
|
||||
arr1 :[size]f32
|
||||
arr0: [size]int
|
||||
arr1: [size]f32
|
||||
}
|
||||
|
||||
var st1: struct_t0
|
||||
|
||||
func maket0a(i: int) => struct_t0 {
|
||||
r: struct_t0
|
||||
var r: struct_t0
|
||||
for j := 0; j < 16; j++ {
|
||||
r.arr0[j] = 100 - j - i
|
||||
r.arr1[j] = 200.0 - f32(j+i)
|
||||
|
||||
18
waroot/examples/misc/Makefile
Normal file
18
waroot/examples/misc/Makefile
Normal file
@@ -0,0 +1,18 @@
|
||||
# 版权 @2023 凹语言 作者。保留所有权利。
|
||||
|
||||
default:
|
||||
go run ../../../main.go array.wa
|
||||
go run ../../../main.go array_1.wa
|
||||
go run ../../../main.go closure.wa
|
||||
go run ../../../main.go global.wa
|
||||
go run ../../../main.go heart.wa
|
||||
go run ../../../main.go multi_ret.wa
|
||||
#go run ../../../main.go native_test.wa
|
||||
go run ../../../main.go prime.wa
|
||||
go run ../../../main.go ref.wa
|
||||
go run ../../../main.go slice.wa
|
||||
go run ../../../main.go string.wa
|
||||
go run ../../../main.go struct.wa
|
||||
|
||||
clean:
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
// 版权 @2021 凹语言 作者。保留所有权利。
|
||||
|
||||
package main
|
||||
|
||||
var I: [8]i32
|
||||
|
||||
func Gen_arr(param: [8]i32) => [8]i32 {
|
||||
@@ -10,7 +8,7 @@ func Gen_arr(param: [8]i32) => [8]i32 {
|
||||
}
|
||||
|
||||
func main() {
|
||||
j: [8]i32
|
||||
var j: [8]i32
|
||||
j[3] = 40
|
||||
I = Gen_arr(j)
|
||||
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
// 版权 @2022 凹语言 作者。保留所有权利。
|
||||
|
||||
func main {
|
||||
test_array(2, 4)
|
||||
test_array(7, 9)
|
||||
test_array(2, 4)
|
||||
test_array(7, 9)
|
||||
}
|
||||
|
||||
func test_array(a: int, b: int) {
|
||||
arr: [10][10]int
|
||||
for i := 0; i < 10; i++ {
|
||||
for j := 0; j < 10; j++ {
|
||||
arr[i][j] = i * j
|
||||
}
|
||||
}
|
||||
var arr: [10][10]int
|
||||
for i := 0; i < 10; i++ {
|
||||
for j := 0; j < 10; j++ {
|
||||
arr[i][j] = i * j
|
||||
}
|
||||
}
|
||||
|
||||
println("arr[", a, "][", b, "] = ", arr[a][b])
|
||||
println("arr[", b, "][", a, "] = ", arr[b][a])
|
||||
println("arr[", a, "][", b, "] = ", arr[a][b])
|
||||
println("arr[", b, "][", a, "] = ", arr[b][a])
|
||||
}
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
// 版权 @2021 凹语言 作者。保留所有权利。
|
||||
|
||||
type FP func (i: i32) => i32
|
||||
type FP func(i: i32) => i32
|
||||
|
||||
type ST struct {
|
||||
i: i32
|
||||
}
|
||||
|
||||
func (t *ST) meth_p(p: i32) => i32 {
|
||||
t.i += p
|
||||
return t.i
|
||||
func ST.meth_p(p: i32) => i32 {
|
||||
this.i += p
|
||||
return this.i
|
||||
}
|
||||
|
||||
func (t ST) meth_v(p: i32) => i32 {
|
||||
t.i += p
|
||||
return t.i
|
||||
func ST.meth_v(p: i32) => i32 {
|
||||
this.i += p
|
||||
return this.i
|
||||
}
|
||||
|
||||
var g_f: FP
|
||||
global g_f: FP
|
||||
|
||||
func main() {
|
||||
o: ST
|
||||
func main() {
|
||||
var o: ST
|
||||
o.i = 11
|
||||
g_f = o.meth_p
|
||||
println(g_f(11))
|
||||
@@ -27,20 +27,20 @@ func main() {
|
||||
g_f = o.meth_v
|
||||
println(g_f(11))
|
||||
println(o.i)
|
||||
|
||||
|
||||
n := i32(21)
|
||||
g_f = func(i: i32) => i32{
|
||||
g_f = func(i: i32) => i32 {
|
||||
n += i
|
||||
return n
|
||||
}
|
||||
println(g_f(22))
|
||||
println(n)
|
||||
|
||||
|
||||
func(i: i32) {
|
||||
n += i
|
||||
}(22)
|
||||
println(n)
|
||||
|
||||
|
||||
g_f = Double
|
||||
println(g_f(13))
|
||||
}
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
// 版权 @2021 凹语言 作者。保留所有权利。
|
||||
|
||||
package main
|
||||
|
||||
var counter: i32 = 13
|
||||
var G: *i32
|
||||
|
||||
func gen_i() => *i32{
|
||||
i: i32
|
||||
func gen_i() => *i32 {
|
||||
var i: i32
|
||||
i = counter
|
||||
counter++
|
||||
return &i
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
// 版权 @2021 凹语言 作者。保留所有权利。
|
||||
|
||||
func main() {
|
||||
i := ST{i: 1, j:2}
|
||||
j := ST{i: 3, j:4}
|
||||
i := ST{i: 1, j: 2}
|
||||
j := ST{i: 3, j: 4}
|
||||
i, j = Swap(i, j)
|
||||
println(i.i)
|
||||
println(i.j)
|
||||
@@ -10,10 +10,10 @@ func main() {
|
||||
println(j.j)
|
||||
}
|
||||
|
||||
func Swap(i, j: ST) => (ST, ST){
|
||||
func Swap(i, j: ST) => (ST, ST) {
|
||||
return j, i
|
||||
}
|
||||
|
||||
type ST struct{
|
||||
type ST struct {
|
||||
i, j: i32
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,431 +0,0 @@
|
||||
// 版权 @2022 凹语言 作者。保留所有权利。
|
||||
|
||||
func main {
|
||||
println("您好,凹语言!\nHello, wa-lang!")
|
||||
println("幸运整数:", test_calc1(6, 9, 8), ", ", 5, ", ", test_calc5(6, 9, 8))
|
||||
println("幸运浮点数:", 5.44, ", ", test_calc3(6, 9, 8))
|
||||
|
||||
test_print(-100, 100, -100, 100, 5)
|
||||
|
||||
test_cmp0(20, 19)
|
||||
test_cmp0(20, 20)
|
||||
test_cmp1(-3, -3)
|
||||
test_cmp1(-3, -4)
|
||||
test_cmp2(10, 10)
|
||||
test_cmp2(10, 10.0001)
|
||||
|
||||
test_jmp(4)
|
||||
test_loop0(10)
|
||||
test_loop1(10, 10)
|
||||
|
||||
test_array(2, 4)
|
||||
test_array(7, 9)
|
||||
|
||||
test_struct0(10)
|
||||
test_struct0(11)
|
||||
test_struct0(2)
|
||||
test_struct0(13)
|
||||
test_struct0(0)
|
||||
|
||||
test_struct1(10, 0, 0)
|
||||
test_struct1(11, 1, 0)
|
||||
test_struct1(2, 0, 1)
|
||||
test_struct1(13, 1, 0)
|
||||
test_struct1(2, 1, 0)
|
||||
|
||||
test_convert0()
|
||||
test_convert1()
|
||||
test_convert2()
|
||||
test_convert3()
|
||||
|
||||
test_global_consts()
|
||||
test_global_variables_0()
|
||||
test_global_variables_1()
|
||||
|
||||
test_pointer(1)
|
||||
test_pointer(-1)
|
||||
|
||||
test_f32()
|
||||
|
||||
test_struct2()
|
||||
test_struct3()
|
||||
test_struct4()
|
||||
|
||||
test_array2()
|
||||
test_array3()
|
||||
test_array4()
|
||||
|
||||
bye()
|
||||
}
|
||||
|
||||
func bye() {
|
||||
println("再见!\nbye!")
|
||||
}
|
||||
|
||||
func test_calc0(a i32, b i32, c i32) i32 {
|
||||
return (-a) * 5 / (b - c + 2)
|
||||
}
|
||||
|
||||
func test_calc1(a i32, b i32, c i32) i32 {
|
||||
return test_calc0(a, b, c)
|
||||
}
|
||||
|
||||
func test_calc2(a f64, b f64, c f64) f64 {
|
||||
return (-a) * 5 / (b - c + 2)
|
||||
}
|
||||
|
||||
func test_calc3(a f64, b f64, c f64) f64 {
|
||||
return test_calc2(a, b, c)
|
||||
}
|
||||
|
||||
func test_calc4(a u16, b u16, c u16) u16 {
|
||||
return (-a) * 5 / (b - c + 2)
|
||||
}
|
||||
|
||||
func test_calc5(a u16, b u16, c u16) u16 {
|
||||
return test_calc4(-a, b, c)
|
||||
}
|
||||
|
||||
func test_cmp0(a u16, b u16) {
|
||||
if a > b {
|
||||
println(a, " > ", b)
|
||||
} else {
|
||||
println(a, " <= ", b)
|
||||
}
|
||||
}
|
||||
|
||||
func test_cmp1(a i64, b i64) {
|
||||
if a <= b {
|
||||
println(a, " <= ", b)
|
||||
} else {
|
||||
println(a, " > ", b)
|
||||
}
|
||||
}
|
||||
|
||||
func test_cmp2(a f64, b f64) {
|
||||
if a != b {
|
||||
println(a, " != ", b)
|
||||
} else {
|
||||
println(a, " == ", b)
|
||||
}
|
||||
}
|
||||
|
||||
func test_jmp(a i32) {
|
||||
for {
|
||||
if a > 10 {
|
||||
return
|
||||
}
|
||||
println(a)
|
||||
a++
|
||||
}
|
||||
}
|
||||
|
||||
func test_loop0(a i16) {
|
||||
for i := i16(0); i < a; i++ {
|
||||
println(i, " * ", i, " = ", i * i)
|
||||
}
|
||||
}
|
||||
|
||||
func test_loop1(a u64, b u64) {
|
||||
for i := u64(0); i < a; i++ {
|
||||
for j := u64(0); j < b; j++ {
|
||||
println(i, " * ", j, " = ", i * j)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func test_array(a int, b int) {
|
||||
arr: [10][10]int
|
||||
for i := 0; i < 10; i++ {
|
||||
for j := 0; j < 10; j++ {
|
||||
arr[i][j] = i * j
|
||||
}
|
||||
}
|
||||
|
||||
println("arr[", a, "][", b, "] = ", arr[a][b])
|
||||
println("arr[", b, "][", a, "] = ", arr[b][a])
|
||||
}
|
||||
|
||||
type t0 struct {
|
||||
a i64
|
||||
b i32
|
||||
c [4]f64
|
||||
d u32
|
||||
}
|
||||
|
||||
func test_struct0(a int) {
|
||||
s0 := t0{17, -668, [4]f64{2.71828, 0.717, 3.14159}, 234}
|
||||
switch a {
|
||||
case 10:
|
||||
println(s0.a)
|
||||
case 11:
|
||||
println(s0.b)
|
||||
case 13:
|
||||
println(s0.d)
|
||||
default:
|
||||
println(s0.c[a])
|
||||
}
|
||||
}
|
||||
|
||||
func test_struct1(a int, b int, c int) {
|
||||
s0 := [2]t0{{11, -12, [4]f64{0.1, -0.2}, 13}, {21, -22, [4]f64{1.1, -1.2}, 24}}
|
||||
switch a {
|
||||
case 10:
|
||||
println(s0[b].a)
|
||||
case 11:
|
||||
println(s0[b].b)
|
||||
case 13:
|
||||
println(s0[b].d)
|
||||
default:
|
||||
println(s0[b].c[c])
|
||||
}
|
||||
}
|
||||
|
||||
type struct_t0 struct {
|
||||
arr0 [16]int
|
||||
arr1 [16]f32
|
||||
}
|
||||
|
||||
var st0: struct_t0
|
||||
var st1: struct_t0
|
||||
|
||||
func test_struct2() {
|
||||
for i := 0; i < 16; i++ {
|
||||
st0.arr0[i] = i * i
|
||||
st0.arr1[i] = f32(i) * 2.0
|
||||
}
|
||||
}
|
||||
|
||||
func getst0int(st0 struct_t0, i int) int {
|
||||
return st0.arr0[i]
|
||||
}
|
||||
|
||||
func getst0f32(st0 *struct_t0, i int) f32 {
|
||||
return st0.arr1[i]
|
||||
}
|
||||
|
||||
func test_struct3() {
|
||||
for i := 6; i < 14; i += 2 {
|
||||
println(getst0int(st0, i), ", ", getst0f32(&st0, i + 1))
|
||||
}
|
||||
}
|
||||
|
||||
func maket0a(i int) struct_t0 {
|
||||
r: struct_t0
|
||||
for j := 0; j < 16; j++ {
|
||||
r.arr0[j] = 100 - j - i
|
||||
r.arr1[j] = 200.0 - f32(j + i)
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func maket0b(i int) *struct_t0 {
|
||||
for j := 0; j < 16; j++ {
|
||||
st1.arr0[j] = 100 - j - i
|
||||
st1.arr1[j] = 200.0 - f32(j + i)
|
||||
}
|
||||
return &st1
|
||||
}
|
||||
|
||||
func test_struct4() {
|
||||
r0, r1 := maket0a(20), maket0b(30)
|
||||
for i := 0; i < 16; i++ {
|
||||
println(r0.arr0[i], ", ", r0.arr1[i], " : ", r1.arr0[i], ", ", r1.arr1[i])
|
||||
}
|
||||
}
|
||||
|
||||
type fff32 f32
|
||||
|
||||
var arr0: [32]fff32
|
||||
var arr1: [32]fff32
|
||||
|
||||
func test_array2() {
|
||||
for i := 0; i < 32; i++ {
|
||||
arr0[i] = fff32(i * i)
|
||||
}
|
||||
}
|
||||
|
||||
func getarr0a(arr [32]fff32, i int) fff32 {
|
||||
return arr[i]
|
||||
}
|
||||
|
||||
func getarr0b(arr *[32]fff32, i int) fff32 {
|
||||
return arr[i]
|
||||
}
|
||||
|
||||
func makearr0a(i int) [32]fff32 {
|
||||
r: [32]fff32
|
||||
for j := 0; j < 32; j++ {
|
||||
r[j] = fff32(i * j)
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func makearr0b(i int) *[32]fff32 {
|
||||
for j := 0; j < 32; j++ {
|
||||
arr1[j] = 2000 - fff32(i * j)
|
||||
}
|
||||
return &arr1
|
||||
}
|
||||
|
||||
func test_array3() {
|
||||
for i := 6; i < 20; i += 2 {
|
||||
println(getarr0a(arr0, i), ", ", getarr0b(&arr0, i + 1))
|
||||
}
|
||||
}
|
||||
|
||||
func test_array4() {
|
||||
r0, r1 := makearr0a(10), makearr0b(20)
|
||||
for i := 6; i < 20; i += 2 {
|
||||
println(r0[i], ", ", r1[i])
|
||||
}
|
||||
}
|
||||
|
||||
func convert_i32_to_i16(a i32) i16 {
|
||||
return i16(a)
|
||||
}
|
||||
|
||||
func convert_i32_to_u16(a i32) u16 {
|
||||
return u16(a)
|
||||
}
|
||||
|
||||
func convert_i16_to_i32(a i16) i32 {
|
||||
return i32(a)
|
||||
}
|
||||
|
||||
func convert_u16_to_i32(a u16) i32 {
|
||||
return i32(a)
|
||||
}
|
||||
|
||||
func test_convert0() {
|
||||
println(i32(convert_i32_to_i16(65537)))
|
||||
println(u32(convert_i32_to_u16(65537)))
|
||||
println(convert_i16_to_i32(100))
|
||||
println(convert_i16_to_i32(-100))
|
||||
println(convert_u16_to_i32(100))
|
||||
println(convert_u16_to_i32(65530))
|
||||
}
|
||||
|
||||
func convert_f64_to_f32(a f64) f32 {
|
||||
return f32(a)
|
||||
}
|
||||
|
||||
func test_convert1() {
|
||||
println(f64(convert_f64_to_f32(3.1415926535)))
|
||||
}
|
||||
|
||||
func convert_i16_to_f64(a i16) f64 {
|
||||
return f64(a)
|
||||
}
|
||||
|
||||
func convert_u16_to_f64(a u16) f64 {
|
||||
return f64(a)
|
||||
}
|
||||
|
||||
func test_convert2() {
|
||||
println(convert_i16_to_f64(100))
|
||||
println(convert_i16_to_f64(-100))
|
||||
println(convert_u16_to_f64(100))
|
||||
println(convert_u16_to_f64(65530))
|
||||
}
|
||||
|
||||
func convert_f64_to_i32(a f64) i32 {
|
||||
return i32(a)
|
||||
}
|
||||
|
||||
func convert_f64_to_u32(a f64) u32 {
|
||||
return u32(a)
|
||||
}
|
||||
|
||||
func test_convert3() {
|
||||
println(convert_f64_to_i32(100.001))
|
||||
println(convert_f64_to_u32(100.001))
|
||||
println(convert_f64_to_i32(99.99))
|
||||
println(convert_f64_to_u32(99.99))
|
||||
println(convert_f64_to_i32(-100.001))
|
||||
println(convert_f64_to_u32(-100.001))
|
||||
}
|
||||
|
||||
func test_print(a i16, b u16, c i8, d u8, e f32) {
|
||||
println(a, ", ", b, ", ", c, ", ", d, ", ", e/2)
|
||||
}
|
||||
|
||||
const gbegin = 10
|
||||
const gend = 20
|
||||
|
||||
func test_global_consts() {
|
||||
for i := gbegin; i < gend; i++ {
|
||||
println(i, " - ", gbegin, " = ", i - gbegin)
|
||||
}
|
||||
}
|
||||
|
||||
type ty0 struct {
|
||||
v0 int
|
||||
v1 f64
|
||||
}
|
||||
|
||||
var gv0: ty0 = ty0{5555, 3.1415926}
|
||||
var gv1: [4]int = [4]int{81, 82, 17, 76}
|
||||
|
||||
func test_global_variables_0() {
|
||||
println("gv0: {", gv0.v0, ", ", gv0.v1, "}")
|
||||
println("gv1: {", gv1[0], ", ", gv1[1], ", ", gv1[2], ", ", gv1[3], "}")
|
||||
}
|
||||
|
||||
func test_global_variables_1() {
|
||||
gv0.v0 = 8888
|
||||
gv0.v1 = 2.71828
|
||||
gv1[0] += 2
|
||||
gv1[1] += 3
|
||||
gv1[2] += 4
|
||||
gv1[3] += 5
|
||||
println("gv0: {", gv0.v0, ", ", gv0.v1, "}")
|
||||
println("gv1: {", gv1[0], ", ", gv1[1], ", ", gv1[2], ", ", gv1[3], "}")
|
||||
}
|
||||
|
||||
var gint0: int = 100
|
||||
var gint1: int = 200
|
||||
|
||||
func get_int_addr(a int) *int {
|
||||
if a > 0 {
|
||||
return &gint0
|
||||
} else {
|
||||
return &gint1
|
||||
}
|
||||
}
|
||||
|
||||
func set_int(a *int) {
|
||||
*a += 10
|
||||
}
|
||||
|
||||
func test_pointer(a int) {
|
||||
println(gint0, ", ", gint1)
|
||||
p := get_int_addr(a)
|
||||
set_int(p)
|
||||
println(gint0, ", ", gint1)
|
||||
}
|
||||
|
||||
func getPi() f32 {
|
||||
return 3.1415926535
|
||||
}
|
||||
|
||||
func getE() f32 {
|
||||
return 2.71828
|
||||
}
|
||||
|
||||
func minusf32(a f32) f32 {
|
||||
return 0 - a
|
||||
}
|
||||
|
||||
func circle_area(r f32) f32 {
|
||||
return r * r * 3.1415926
|
||||
}
|
||||
|
||||
func test_f32() {
|
||||
println(getPi())
|
||||
println(getE())
|
||||
println(minusf32(getPi()))
|
||||
println(minusf32(-1.3))
|
||||
println(circle_area(1.1))
|
||||
println(circle_area(getE()))
|
||||
}
|
||||
431
waroot/examples/misc/native_test_.wa
Normal file
431
waroot/examples/misc/native_test_.wa
Normal file
@@ -0,0 +1,431 @@
|
||||
// 版权 @2022 凹语言 作者。保留所有权利。
|
||||
|
||||
func main {
|
||||
println("您好,凹语言!\nHello, wa-lang!")
|
||||
println("幸运整数:", test_calc1(6, 9, 8), ", ", 5, ", ", test_calc5(6, 9, 8))
|
||||
println("幸运浮点数:", 5.44, ", ", test_calc3(6, 9, 8))
|
||||
|
||||
test_print(100, 100, 5)
|
||||
|
||||
test_cmp0(20, 19)
|
||||
test_cmp0(20, 20)
|
||||
//test_cmp1(-3, -3)
|
||||
//test_cmp1(-3, -4)
|
||||
test_cmp2(10, 10)
|
||||
test_cmp2(10, 10.0001)
|
||||
|
||||
test_jmp(4)
|
||||
test_loop0(10)
|
||||
test_loop1(10, 10)
|
||||
|
||||
test_array(2, 4)
|
||||
test_array(7, 9)
|
||||
|
||||
test_struct0(10)
|
||||
test_struct0(11)
|
||||
test_struct0(2)
|
||||
test_struct0(13)
|
||||
test_struct0(0)
|
||||
|
||||
test_struct1(10, 0, 0)
|
||||
test_struct1(11, 1, 0)
|
||||
test_struct1(2, 0, 1)
|
||||
test_struct1(13, 1, 0)
|
||||
test_struct1(2, 1, 0)
|
||||
|
||||
test_convert0()
|
||||
test_convert1()
|
||||
test_convert2()
|
||||
test_convert3()
|
||||
|
||||
test_global_consts()
|
||||
test_global_variables_0()
|
||||
test_global_variables_1()
|
||||
|
||||
test_pointer(1)
|
||||
test_pointer(-1)
|
||||
|
||||
test_f32()
|
||||
|
||||
test_struct2()
|
||||
test_struct3()
|
||||
test_struct4()
|
||||
|
||||
test_array2()
|
||||
test_array3()
|
||||
test_array4()
|
||||
|
||||
bye()
|
||||
}
|
||||
|
||||
func bye {
|
||||
println("再见!\nbye!")
|
||||
}
|
||||
|
||||
func test_calc0(a: i32, b: i32, c: i32) => i32 {
|
||||
return (-a) * 5 / (b - c + 2)
|
||||
}
|
||||
|
||||
func test_calc1(a: i32, b: i32, c: i32) => i32 {
|
||||
return test_calc0(a, b, c)
|
||||
}
|
||||
|
||||
func test_calc2(a: f64, b: f64, c: f64) => f64 {
|
||||
return (-a) * 5 / (b - c + 2)
|
||||
}
|
||||
|
||||
func test_calc3(a: f64, b: f64, c: f64) => f64 {
|
||||
return test_calc2(a, b, c)
|
||||
}
|
||||
|
||||
func test_calc4(a: u16, b: u16, c: u16) => u16 {
|
||||
return (-a) * 5 / (b - c + 2)
|
||||
}
|
||||
|
||||
func test_calc5(a: u16, b: u16, c: u16) => u16 {
|
||||
return test_calc4(-a, b, c)
|
||||
}
|
||||
|
||||
func test_cmp0(a: u16, b: u16) {
|
||||
if a > b {
|
||||
println(a, " > ", b)
|
||||
} else {
|
||||
println(a, " <= ", b)
|
||||
}
|
||||
}
|
||||
|
||||
//func test_cmp1(a: i64, b: i64) {
|
||||
// if a <= b {
|
||||
// println(a, " <= ", b)
|
||||
// } else {
|
||||
// println(a, " > ", b)
|
||||
// }
|
||||
//}
|
||||
|
||||
func test_cmp2(a: f64, b: f64) {
|
||||
if a != b {
|
||||
println(a, " != ", b)
|
||||
} else {
|
||||
println(a, " == ", b)
|
||||
}
|
||||
}
|
||||
|
||||
func test_jmp(a: i32) {
|
||||
for {
|
||||
if a > 10 {
|
||||
return
|
||||
}
|
||||
println(a)
|
||||
a++
|
||||
}
|
||||
}
|
||||
|
||||
func test_loop0(a: u16) {
|
||||
for i := u16(0); i < a; i++ {
|
||||
println(i, " * ", i, " = ", i*i)
|
||||
}
|
||||
}
|
||||
|
||||
func test_loop1(a: u64, b: u64) {
|
||||
for i := u64(0); i < a; i++ {
|
||||
for j := u64(0); j < b; j++ {
|
||||
println(i, " * ", j, " = ", i*j)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func test_array(a: int, b: int) {
|
||||
var arr: [10][10]int
|
||||
for i := 0; i < 10; i++ {
|
||||
for j := 0; j < 10; j++ {
|
||||
arr[i][j] = i * j
|
||||
}
|
||||
}
|
||||
|
||||
println("arr[", a, "][", b, "] = ", arr[a][b])
|
||||
println("arr[", b, "][", a, "] = ", arr[b][a])
|
||||
}
|
||||
|
||||
type t0 struct {
|
||||
a: i64
|
||||
b: i32
|
||||
c: [4]f64
|
||||
d: u32
|
||||
}
|
||||
|
||||
func test_struct0(a: int) {
|
||||
s0 := t0{17, -668, [4]f64{2.71828, 0.717, 3.14159}, 234}
|
||||
switch a {
|
||||
case 10:
|
||||
println(s0.a)
|
||||
case 11:
|
||||
println(s0.b)
|
||||
case 13:
|
||||
println(s0.d)
|
||||
default:
|
||||
println(s0.c[a])
|
||||
}
|
||||
}
|
||||
|
||||
func test_struct1(a: int, b: int, c: int) {
|
||||
s0 := [2]t0{{11, -12, [4]f64{0.1, -0.2}, 13}, {21, -22, [4]f64{1.1, -1.2}, 24}}
|
||||
switch a {
|
||||
case 10:
|
||||
println(s0[b].a)
|
||||
case 11:
|
||||
println(s0[b].b)
|
||||
case 13:
|
||||
println(s0[b].d)
|
||||
default:
|
||||
println(s0[b].c[c])
|
||||
}
|
||||
}
|
||||
|
||||
type struct_t0 struct {
|
||||
arr0: [16]int
|
||||
arr1: [16]f32
|
||||
}
|
||||
|
||||
global st0: struct_t0
|
||||
global st1: struct_t0
|
||||
|
||||
func test_struct2 {
|
||||
for i := 0; i < 16; i++ {
|
||||
st0.arr0[i] = i * i
|
||||
st0.arr1[i] = f32(i) * 2.0
|
||||
}
|
||||
}
|
||||
|
||||
func getst0int(st0: struct_t0, i: int) => int {
|
||||
return st0.arr0[i]
|
||||
}
|
||||
|
||||
func getst0f32(st0: *struct_t0, i: int) => f32 {
|
||||
return st0.arr1[i]
|
||||
}
|
||||
|
||||
func test_struct3 {
|
||||
for i := 6; i < 14; i += 2 {
|
||||
println(getst0int(st0, i), ", ", getst0f32(&st0, i+1))
|
||||
}
|
||||
}
|
||||
|
||||
func maket0a(i: int) => struct_t0 {
|
||||
var r: struct_t0
|
||||
for j := 0; j < 16; j++ {
|
||||
r.arr0[j] = 100 - j - i
|
||||
r.arr1[j] = 200.0 - f32(j+i)
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func maket0b(i: int) => *struct_t0 {
|
||||
for j := 0; j < 16; j++ {
|
||||
st1.arr0[j] = 100 - j - i
|
||||
st1.arr1[j] = 200.0 - f32(j+i)
|
||||
}
|
||||
return &st1
|
||||
}
|
||||
|
||||
func test_struct4 {
|
||||
r0, r1 := maket0a(20), maket0b(30)
|
||||
for i := 0; i < 16; i++ {
|
||||
println(r0.arr0[i], ", ", r0.arr1[i], " : ", r1.arr0[i], ", ", r1.arr1[i])
|
||||
}
|
||||
}
|
||||
|
||||
type fff32 f32
|
||||
|
||||
global arr0: [32]fff32
|
||||
global arr1: [32]fff32
|
||||
|
||||
func test_array2() {
|
||||
for i := 0; i < 32; i++ {
|
||||
arr0[i] = fff32(i * i)
|
||||
}
|
||||
}
|
||||
|
||||
func getarr0a(arr: [32]fff32, i: int) => fff32 {
|
||||
return arr[i]
|
||||
}
|
||||
|
||||
func getarr0b(arr: *[32]fff32, i: int) => fff32 {
|
||||
return arr[i]
|
||||
}
|
||||
|
||||
func makearr0a(i: int) => [32]fff32 {
|
||||
var r: [32]fff32
|
||||
for j := 0; j < 32; j++ {
|
||||
r[j] = fff32(i * j)
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func makearr0b(i: int) => *[32]fff32 {
|
||||
for j := 0; j < 32; j++ {
|
||||
arr1[j] = 2000 - fff32(i*j)
|
||||
}
|
||||
return &arr1
|
||||
}
|
||||
|
||||
func test_array3 {
|
||||
for i := 6; i < 20; i += 2 {
|
||||
println(getarr0a(arr0, i), ", ", getarr0b(&arr0, i+1))
|
||||
}
|
||||
}
|
||||
|
||||
func test_array4 {
|
||||
r0, r1 := makearr0a(10), makearr0b(20)
|
||||
for i := 6; i < 20; i += 2 {
|
||||
println(r0[i], ", ", r1[i])
|
||||
}
|
||||
}
|
||||
|
||||
//func convert_i32_to_i16(a: i32) => i16 {
|
||||
// return i16(a)
|
||||
//}
|
||||
|
||||
func convert_i32_to_u16(a: i32) => u16 {
|
||||
return u16(a)
|
||||
}
|
||||
|
||||
//func convert_i16_to_i32(a: i16) => i32 {
|
||||
// return i32(a)
|
||||
//}
|
||||
|
||||
func convert_u16_to_i32(a: u16) => i32 {
|
||||
return i32(a)
|
||||
}
|
||||
|
||||
func test_convert0 {
|
||||
//println(i32(convert_i32_to_i16(65537)))
|
||||
println(u32(convert_i32_to_u16(65537)))
|
||||
//println(convert_i16_to_i32(100))
|
||||
//println(convert_i16_to_i32(-100))
|
||||
println(convert_u16_to_i32(100))
|
||||
println(convert_u16_to_i32(65530))
|
||||
}
|
||||
|
||||
func convert_f64_to_f32(a: f64) => f32 {
|
||||
return f32(a)
|
||||
}
|
||||
|
||||
func test_convert1() {
|
||||
println(f64(convert_f64_to_f32(3.1415926535)))
|
||||
}
|
||||
|
||||
//func convert_i16_to_f64(a: i16) => f64 {
|
||||
// return f64(a)
|
||||
//}
|
||||
|
||||
func convert_u16_to_f64(a: u16) => f64 {
|
||||
return f64(a)
|
||||
}
|
||||
|
||||
func test_convert2() {
|
||||
//println(convert_i16_to_f64(100))
|
||||
//println(convert_i16_to_f64(-100))
|
||||
println(convert_u16_to_f64(100))
|
||||
println(convert_u16_to_f64(65530))
|
||||
}
|
||||
|
||||
func convert_f64_to_i32(a: f64) => i32 {
|
||||
return i32(a)
|
||||
}
|
||||
|
||||
func convert_f64_to_u32(a: f64) => u32 {
|
||||
return u32(a)
|
||||
}
|
||||
|
||||
func test_convert3() {
|
||||
println(convert_f64_to_i32(100.001))
|
||||
println(convert_f64_to_u32(100.001))
|
||||
println(convert_f64_to_i32(99.99))
|
||||
println(convert_f64_to_u32(99.99))
|
||||
println(convert_f64_to_i32(-100.001))
|
||||
println(convert_f64_to_u32(-100.001))
|
||||
}
|
||||
|
||||
func test_print(b: u16, d: u8, e: f32) {
|
||||
println(b, ", ", d, ", ", e/2)
|
||||
}
|
||||
|
||||
const gbegin = 10
|
||||
const gend = 20
|
||||
|
||||
func test_global_consts() {
|
||||
for i := gbegin; i < gend; i++ {
|
||||
println(i, " - ", gbegin, " = ", i-gbegin)
|
||||
}
|
||||
}
|
||||
|
||||
type ty0 struct {
|
||||
v0: int
|
||||
v1: f64
|
||||
}
|
||||
|
||||
global gv0: ty0 = ty0{5555, 3.1415926}
|
||||
global gv1: [4]int = [4]int{81, 82, 17, 76}
|
||||
|
||||
func test_global_variables_0() {
|
||||
println("gv0: {", gv0.v0, ", ", gv0.v1, "}")
|
||||
println("gv1: {", gv1[0], ", ", gv1[1], ", ", gv1[2], ", ", gv1[3], "}")
|
||||
}
|
||||
|
||||
func test_global_variables_1 {
|
||||
gv0.v0 = 8888
|
||||
gv0.v1 = 2.71828
|
||||
gv1[0] += 2
|
||||
gv1[1] += 3
|
||||
gv1[2] += 4
|
||||
gv1[3] += 5
|
||||
println("gv0: {", gv0.v0, ", ", gv0.v1, "}")
|
||||
println("gv1: {", gv1[0], ", ", gv1[1], ", ", gv1[2], ", ", gv1[3], "}")
|
||||
}
|
||||
|
||||
global gint0: int = 100
|
||||
global gint1: int = 200
|
||||
|
||||
func get_int_addr(a: int) => *int {
|
||||
if a > 0 {
|
||||
return &gint0
|
||||
} else {
|
||||
return &gint1
|
||||
}
|
||||
}
|
||||
|
||||
func set_int(a: *int) {
|
||||
*a += 10
|
||||
}
|
||||
|
||||
func test_pointer(a: int) {
|
||||
println(gint0, ", ", gint1)
|
||||
p := get_int_addr(a)
|
||||
set_int(p)
|
||||
println(gint0, ", ", gint1)
|
||||
}
|
||||
|
||||
func getPi => f32 {
|
||||
return 3.1415926535
|
||||
}
|
||||
|
||||
func getE => f32 {
|
||||
return 2.71828
|
||||
}
|
||||
|
||||
func minusf32(a: f32) => f32 {
|
||||
return 0 - a
|
||||
}
|
||||
|
||||
func circle_area(r: f32) => f32 {
|
||||
return r * r * 3.1415926
|
||||
}
|
||||
|
||||
func test_f32() {
|
||||
println(getPi())
|
||||
println(getE())
|
||||
println(minusf32(getPi()))
|
||||
println(minusf32(-1.3))
|
||||
println(circle_area(1.1))
|
||||
println(circle_area(getE()))
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
func main() {
|
||||
for n := 2; n <= 30; n = n + 1 {
|
||||
isPrime: int = 1
|
||||
var isPrime: int = 1
|
||||
for i := 2; i*i <= n; i = i + 1 {
|
||||
if x := n % i; x == 0 {
|
||||
isPrime = 0
|
||||
|
||||
@@ -8,7 +8,7 @@ func main() {
|
||||
}
|
||||
|
||||
func new_int() => *i32 {
|
||||
i: i32
|
||||
var i: i32
|
||||
i = 42
|
||||
return &i
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ func main() {
|
||||
println(a[1]) # 13
|
||||
println(len(s)) # 2
|
||||
|
||||
k: []i32
|
||||
var k: []i32
|
||||
k = append(k, 99, 81, 170)
|
||||
println(k[0]) # 99
|
||||
|
||||
@@ -22,4 +22,4 @@ func main() {
|
||||
l[0] = 111
|
||||
println(l[0]) #111
|
||||
println(k[0]) #99
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
|
||||
func gen_str() => string {
|
||||
return "123456"
|
||||
}
|
||||
|
||||
func main() {
|
||||
println("你好,凹语言!")
|
||||
|
||||
|
||||
s1 := gen_str()
|
||||
s2 := s1[0:3]
|
||||
s2 = s2 + "abc"
|
||||
println(s1)
|
||||
println(s2)
|
||||
println(s2)
|
||||
}
|
||||
|
||||
@@ -20,8 +20,8 @@ type sc struct {
|
||||
}
|
||||
|
||||
func gen_scref() => *sc {
|
||||
v: sc
|
||||
i: i32
|
||||
var v: sc
|
||||
var i: i32
|
||||
i = 13
|
||||
v.a = &i
|
||||
v.b = 42
|
||||
@@ -29,8 +29,8 @@ func gen_scref() => *sc {
|
||||
}
|
||||
|
||||
func gen_sc() => sc {
|
||||
i: i32 = 26
|
||||
v: sc
|
||||
var i: i32 = 26
|
||||
var v: sc
|
||||
v.a = &i
|
||||
v.b = 58
|
||||
return v
|
||||
|
||||
@@ -24,7 +24,7 @@ func main {
|
||||
Do()
|
||||
println(G.A)
|
||||
println(G.B)
|
||||
|
||||
|
||||
println(mypkg.G.A)
|
||||
println(mypkg.G.B)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// 版权 @2022 _examples/hello 作者。保留所有权利。
|
||||
|
||||
func Println(x int) {
|
||||
func Println(x: int) {
|
||||
println(x)
|
||||
}
|
||||
|
||||
@@ -7,8 +7,8 @@ func refToPtr_i32(p: *i32) => i32
|
||||
func refToPtr_byteSlice(t: []byte) => i32
|
||||
|
||||
func main() {
|
||||
i: i32
|
||||
j: []byte
|
||||
var i: i32
|
||||
var j: []byte
|
||||
println(refToPtr_i32(&i))
|
||||
println(refToPtr_byteSlice(j))
|
||||
j = append(j, 33)
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
// 版权 @2023 凹语言 作者。保留所有权利。
|
||||
|
||||
func main {
|
||||
L0: bool
|
||||
L: int = 123
|
||||
var L0: bool
|
||||
var L: int = 123
|
||||
|
||||
Loop:
|
||||
for 1 > 0 {
|
||||
|
||||
@@ -22,24 +22,24 @@ type OnKey func(key: u32)
|
||||
|
||||
//画布对象
|
||||
type Canvas struct {
|
||||
device_id :u32 //画布对象对应的网页DOM对象id
|
||||
width :u32 //画布宽度,以像素为单位
|
||||
height :u32 //画布高度,以像素为单位
|
||||
frame_buf :[]u32 //画布帧缓存,容量为Width * Height
|
||||
device_id: u32 //画布对象对应的网页DOM对象id
|
||||
width: u32 //画布宽度,以像素为单位
|
||||
height: u32 //画布高度,以像素为单位
|
||||
frame_buf: []u32 //画布帧缓存,容量为Width * Height
|
||||
}
|
||||
|
||||
//画布事件
|
||||
type CanvasEvents struct {
|
||||
Device_id :u32 //画布设备ID
|
||||
OnMouseDown :OnTouch //鼠标按下时的回调处理函数
|
||||
OnMouseUp :OnTouch //鼠标松开时的回调处理函数
|
||||
OnKeyDown :OnKey //键盘按下时的回调处理函数
|
||||
OnKeyUp :OnKey //键盘弹起时的回调处理函数
|
||||
Device_id: u32 //画布设备ID
|
||||
OnMouseDown: OnTouch //鼠标按下时的回调处理函数
|
||||
OnMouseUp: OnTouch //鼠标松开时的回调处理函数
|
||||
OnKeyDown: OnKey //键盘按下时的回调处理函数
|
||||
OnKeyUp: OnKey //键盘弹起时的回调处理函数
|
||||
}
|
||||
|
||||
//创建一个宽度为w像素、高度为h像素的画布对象
|
||||
func NewCanvas(w, h: u32) => *Canvas {
|
||||
canvas: Canvas
|
||||
var canvas: Canvas
|
||||
canvas.device_id = newCanvas_JS(w, h)
|
||||
canvas.width = w
|
||||
canvas.height = h
|
||||
|
||||
@@ -5,7 +5,7 @@ import "snake/canvas"
|
||||
var ca: *canvas.Canvas
|
||||
|
||||
type Position struct {
|
||||
x, y :i32
|
||||
x, y: i32
|
||||
}
|
||||
|
||||
const DefaultColor = 0x00000000
|
||||
@@ -13,13 +13,13 @@ const BodyColor = 0xFF202020
|
||||
const FoodColor = 0xFF00FF00
|
||||
|
||||
const (
|
||||
GridNull: u8 = iota
|
||||
GridNull :u8 = iota
|
||||
GridBody
|
||||
GridFood
|
||||
)
|
||||
|
||||
const (
|
||||
DirNull: i32 = iota
|
||||
DirNull :i32 = iota
|
||||
DirLeft
|
||||
DirUp
|
||||
DirRight
|
||||
@@ -29,13 +29,13 @@ const (
|
||||
var Dirs: [5]Position
|
||||
|
||||
type GameState struct {
|
||||
w, h :i32
|
||||
scale :i32
|
||||
grid :[]u8
|
||||
body :[]Position
|
||||
dir :i32
|
||||
w, h: i32
|
||||
scale: i32
|
||||
grid: []u8
|
||||
body: []Position
|
||||
dir: i32
|
||||
|
||||
ca :*canvas.Canvas
|
||||
ca: *canvas.Canvas
|
||||
}
|
||||
|
||||
var gameState: GameState
|
||||
@@ -47,7 +47,7 @@ func GameState.Init(w, h: i32, scale: i32) {
|
||||
this.grid = make([]u8, u32(w*h))
|
||||
this.ca = canvas.NewCanvas(u32(w*scale), u32(h*scale))
|
||||
|
||||
caev: canvas.CanvasEvents
|
||||
var caev: canvas.CanvasEvents
|
||||
caev.Device_id = this.ca.GetDeviceID()
|
||||
caev.OnMouseDown = func(x, y: u32) {}
|
||||
caev.OnMouseUp = func(x, y: u32) {}
|
||||
@@ -80,7 +80,7 @@ func GameState.Start() {
|
||||
|
||||
func GameState.SetGridType(p: Position, t: u8) {
|
||||
this.grid[p.y*this.w+p.x] = t
|
||||
color: u32
|
||||
var color: u32
|
||||
switch t {
|
||||
case GridBody:
|
||||
color = BodyColor
|
||||
@@ -92,7 +92,7 @@ func GameState.SetGridType(p: Position, t: u8) {
|
||||
color = DefaultColor
|
||||
}
|
||||
|
||||
x, y: i32
|
||||
var x, y: i32
|
||||
for y = 0; y < this.scale; y++ {
|
||||
for x = 0; x < this.scale; x++ {
|
||||
this.ca.SetPixel(u32(p.x*this.scale+x), u32(p.y*this.scale+y), color)
|
||||
@@ -103,7 +103,7 @@ func GameState.SetGridType(p: Position, t: u8) {
|
||||
#wa:import wa_js_env rand
|
||||
func rand_JS(_: i32) => i32
|
||||
func GameState.GenFood() => Position {
|
||||
p: Position
|
||||
var p: Position
|
||||
for {
|
||||
p = Position{x: rand_JS(this.w), y: rand_JS(this.h)}
|
||||
if this.grid[p.y*this.w+p.x] == GridNull {
|
||||
|
||||
@@ -8,7 +8,7 @@ func main() {
|
||||
println(c)
|
||||
}
|
||||
bytes[0] = 113
|
||||
|
||||
|
||||
str = string(bytes)
|
||||
println(str)
|
||||
}
|
||||
|
||||
@@ -1,30 +1,33 @@
|
||||
// 版权 @2023 凹语言 作者。保留所有权利。
|
||||
|
||||
var Info: struct{
|
||||
var Info: struct {
|
||||
name: string
|
||||
age: i32
|
||||
age: i32
|
||||
}
|
||||
|
||||
func main() {
|
||||
i := gen_scref()
|
||||
println(*i.a) //13
|
||||
println(*i.a) //13
|
||||
println(i.b) //42
|
||||
|
||||
j := gen_sc()
|
||||
println(*j.a) //26
|
||||
println(*j.a) //26
|
||||
println(j.b) //58
|
||||
|
||||
//全局匿名结构体变量
|
||||
Info.name = "张三"
|
||||
Info.age = 88
|
||||
println(Info.name, " ", Info.age) //张三 88
|
||||
println(Info.name, " ", Info.age) //张三 88
|
||||
|
||||
//局部匿名结构体变量
|
||||
k := struct {name: string; age: i32}{"李四", 66}
|
||||
println(k.name, " ", k.age) //李四 66
|
||||
k := struct {
|
||||
name: string
|
||||
age: i32
|
||||
}{"李四", 66}
|
||||
println(k.name, " ", k.age) //李四 66
|
||||
|
||||
Info = k
|
||||
println(Info.name, " ", Info.age) //李四 66
|
||||
println(Info.name, " ", Info.age) //李四 66
|
||||
}
|
||||
|
||||
type sp struct {
|
||||
@@ -37,8 +40,8 @@ type sc struct {
|
||||
}
|
||||
|
||||
func gen_scref() => *sc {
|
||||
v: sc
|
||||
i: i32
|
||||
var v: sc
|
||||
var i: i32
|
||||
i = 13
|
||||
v.a = &i
|
||||
v.b = 42
|
||||
@@ -46,8 +49,8 @@ func gen_scref() => *sc {
|
||||
}
|
||||
|
||||
func gen_sc() => sc {
|
||||
i: i32 = 26
|
||||
v: sc
|
||||
var i: i32 = 26
|
||||
var v: sc
|
||||
v.a = &i
|
||||
v.b = 58
|
||||
return v
|
||||
|
||||
Reference in New Issue
Block a user