CI 添加 fmt 并包含更多测试

This commit is contained in:
chai2010
2023-06-28 19:28:16 +08:00
parent 86a784e019
commit 0a5a671f5d
51 changed files with 661 additions and 5759 deletions

View File

@@ -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)

View File

@@ -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)
}
}
}
}

View File

@@ -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)
}
}
}

View File

@@ -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

View File

@@ -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")
}
}

View File

@@ -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)
}
}

View File

@@ -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)
}

View File

@@ -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

View File

@@ -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

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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)
}
}
}

View File

@@ -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
}

View File

@@ -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")
}
}

View File

@@ -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 {

View File

@@ -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
}

View File

@@ -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)
}
}

View File

@@ -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

View File

@@ -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)
}

View File

@@ -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}

View File

@@ -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}

View File

@@ -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], "}")

View File

@@ -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) {

View File

@@ -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

View File

@@ -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) {

View File

@@ -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) {

View File

@@ -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

View File

@@ -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)

View 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:

View File

@@ -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)

View File

@@ -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])
}

View File

@@ -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))
}

View File

@@ -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

View File

@@ -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
}
}

View File

@@ -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()))
}

View 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()))
}

View File

@@ -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

View File

@@ -8,7 +8,7 @@ func main() {
}
func new_int() => *i32 {
i: i32
var i: i32
i = 42
return &i
}

View File

@@ -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
}
}

View File

@@ -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)
}

View File

@@ -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

View File

@@ -24,7 +24,7 @@ func main {
Do()
println(G.A)
println(G.B)
println(mypkg.G.A)
println(mypkg.G.B)
}

View File

@@ -1,5 +1,5 @@
// 版权 @2022 _examples/hello 作者。保留所有权利。
func Println(x int) {
func Println(x: int) {
println(x)
}

View File

@@ -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)

View File

@@ -1,8 +1,8 @@
// 版权 @2023 凹语言 作者。保留所有权利。
func main {
L0: bool
L: int = 123
var L0: bool
var L: int = 123
Loop:
for 1 > 0 {

View File

@@ -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

View File

@@ -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 {

View File

@@ -8,7 +8,7 @@ func main() {
println(c)
}
bytes[0] = 113
str = string(bytes)
println(str)
}

View File

@@ -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