Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
wa-lang
wa
提交
9f848656
wa
项目概览
wa-lang
/
wa
大约 1 年 前同步成功
通知
68
Star
655
Fork
45
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
wa
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
9f848656
编写于
8月 08, 2023
作者:
3
3dgen
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'master' of
https://gitee.com/wa-lang/wa
上级
3693430e
66113f0f
变更
17
隐藏空白更改
内联
并排
Showing
17 changed file
with
1000 addition
and
275 deletion
+1000
-275
README-zh.md
README-zh.md
+1
-0
README.md
README.md
+1
-0
internal/app/apptest/apptest.go
internal/app/apptest/apptest.go
+92
-4
internal/loader/api.go
internal/loader/api.go
+4
-3
internal/loader/loader.go
internal/loader/loader.go
+32
-18
waroot/src/apple/apple_test.wa
waroot/src/apple/apple_test.wa
+8
-1
waroot/src/builtin/builtin.wa
waroot/src/builtin/builtin.wa
+8
-45
waroot/src/math/bits/bits.wa
waroot/src/math/bits/bits.wa
+68
-60
waroot/src/math/bits/bits_errors_bootstrap.wa
waroot/src/math/bits/bits_errors_bootstrap.wa
+0
-23
waroot/src/math/bits/bits_panic_test.wa
waroot/src/math/bits/bits_panic_test.wa
+77
-0
waroot/src/math/bits/bits_test.wa
waroot/src/math/bits/bits_test.wa
+560
-0
waroot/src/math/bits/example_test.wa
waroot/src/math/bits/example_test.wa
+141
-0
waroot/src/math/bits/make_examples.go
waroot/src/math/bits/make_examples.go
+0
-113
waroot/src/runtime/runtime_arduino.wa
waroot/src/runtime/runtime_arduino.wa
+3
-3
waroot/src/runtime/runtime_chrome.wa
waroot/src/runtime/runtime_chrome.wa
+3
-3
waroot/src/runtime/runtime_mvp.wa
waroot/src/runtime/runtime_mvp.wa
+1
-1
waroot/src/runtime/runtime_wasi.wa
waroot/src/runtime/runtime_wasi.wa
+1
-1
未找到文件。
README-zh.md
浏览文件 @
9f848656
...
...
@@ -10,6 +10,7 @@
![](
docs/images/logo/logo-animate1.svg
)
-
主页:
[
https://wa-lang.org
](
https://wa-lang.org
)
-
参考手册:
[
https://wa-lang.org/man/
](
https://wa-lang.org/man/
)
-
仓库(Gitee):
[
https://gitee.com/wa-lang/wa
](
https://gitee.com/wa-lang/wa
)
-
仓库(Github):
[
https://github.com/wa-lang/wa
](
https://github.com/wa-lang/wa
)
-
Playground:
[
https://wa-lang.org/playground
](
https://wa-lang.org/playground
)
...
...
README.md
浏览文件 @
9f848656
...
...
@@ -22,6 +22,7 @@ Instead of requiring complex toolchains to set up, you can simply go install it
![](
docs/images/logo/logo-animate1.svg
)
-
Home:
[
https://wa-lang.org
](
https://wa-lang.org
)
-
Manual(Chinese):
[
https://wa-lang.org/man/
](
https://wa-lang.org/man/
)
-
Github:
[
https://github.com/wa-lang/wa
](
https://github.com/wa-lang/wa
)
-
Playground:
[
https://wa-lang.org/playground
](
https://wa-lang.org/playground
)
...
...
internal/app/apptest/apptest.go
浏览文件 @
9f848656
...
...
@@ -98,8 +98,49 @@ func runTest(cfg *config.Config, pkgpath string, appArgs ...string) {
// 执行测试函数
var
firstError
error
for
_
,
t
:=
range
mainPkg
.
TestInfo
.
Tests
{
_
,
stdout
,
stderr
,
err
:=
m
.
RunFunc
(
mainPkg
.
Pkg
.
Path
()
+
"."
+
t
.
Name
)
for
i
:=
0
;
i
<
len
(
mainPkg
.
TestInfo
.
Tests
);
i
++
{
t
:=
mainPkg
.
TestInfo
.
Tests
[
i
]
tFuncName
:=
mainPkg
.
Pkg
.
Path
()
+
"."
+
t
.
Name
tFuncName
=
strings
.
ReplaceAll
(
tFuncName
,
"/"
,
"$"
)
_
,
stdout
,
stderr
,
err
:=
m
.
RunFunc
(
tFuncName
)
if
t
.
OutputPanic
{
stdout
=
bytes
.
TrimSpace
(
stdout
)
expect
,
got
:=
t
.
Output
,
string
(
stdout
)
if
exitCode
,
_
:=
wazero
.
AsExitError
(
err
);
exitCode
==
0
{
fmt
.
Printf
(
"---- %s.%s
\n
"
,
prog
.
Manifest
.
MainPkg
,
t
.
Name
)
fmt
.
Printf
(
" expect panic, got = nil
\n
"
)
if
firstError
==
nil
{
firstError
=
fmt
.
Errorf
(
"expect(panic) = %q, got = %q"
,
expect
,
"nil"
)
}
continue
}
if
!
strings
.
HasPrefix
(
got
,
"panic: "
+
expect
)
{
// panic: ${expect} (pos)
fmt
.
Printf
(
"---- %s.%s
\n
"
,
prog
.
Manifest
.
MainPkg
,
t
.
Name
)
fmt
.
Printf
(
" expect(panic) = %q, got = %q
\n
"
,
expect
,
got
)
if
firstError
==
nil
{
firstError
=
fmt
.
Errorf
(
"expect(panic) = %q, got = %q"
,
expect
,
got
)
}
}
// 重新加载
{
m
,
err
=
wazero
.
BuildModule
(
cfg
,
wasmName
,
wasmBytes
,
wasmArgs
...
)
if
err
!=
nil
{
fmt
.
Println
(
err
)
os
.
Exit
(
1
)
}
// 临时方案: defer 太多
defer
m
.
Close
()
}
continue
}
if
err
!=
nil
{
if
len
(
stdout
)
>
0
{
if
s
:=
sWithPrefix
(
string
(
stdout
),
" "
);
s
!=
""
{
...
...
@@ -110,7 +151,12 @@ func runTest(cfg *config.Config, pkgpath string, appArgs ...string) {
if
s
:=
sWithPrefix
(
string
(
stderr
),
" "
);
s
!=
""
{
fmt
.
Println
(
s
)
}
}
else
{
if
s
:=
sWithPrefix
(
err
.
Error
(),
" "
);
s
!=
""
{
fmt
.
Println
(
s
)
}
}
os
.
Exit
(
1
)
}
...
...
@@ -146,8 +192,50 @@ func runTest(cfg *config.Config, pkgpath string, appArgs ...string) {
}
}
}
for
_
,
t
:=
range
mainPkg
.
TestInfo
.
Examples
{
_
,
stdout
,
stderr
,
err
:=
m
.
RunFunc
(
mainPkg
.
Pkg
.
Path
()
+
"."
+
t
.
Name
)
for
i
:=
0
;
i
<
len
(
mainPkg
.
TestInfo
.
Examples
);
i
++
{
t
:=
mainPkg
.
TestInfo
.
Examples
[
i
]
tFuncName
:=
mainPkg
.
Pkg
.
Path
()
+
"."
+
t
.
Name
tFuncName
=
strings
.
ReplaceAll
(
tFuncName
,
"/"
,
"$"
)
_
,
stdout
,
stderr
,
err
:=
m
.
RunFunc
(
tFuncName
)
if
t
.
OutputPanic
{
stdout
=
bytes
.
TrimSpace
(
stdout
)
expect
,
got
:=
t
.
Output
,
string
(
stdout
)
if
exitCode
,
_
:=
wazero
.
AsExitError
(
err
);
exitCode
==
0
{
fmt
.
Printf
(
"---- %s.%s
\n
"
,
prog
.
Manifest
.
MainPkg
,
t
.
Name
)
fmt
.
Printf
(
" expect panic, got = nil
\n
"
)
if
firstError
==
nil
{
firstError
=
fmt
.
Errorf
(
"expect panic, got = nil"
)
}
continue
}
if
!
strings
.
HasPrefix
(
got
,
"panic: "
+
expect
)
{
// panic: ${expect} (pos)
fmt
.
Printf
(
"---- %s.%s
\n
"
,
prog
.
Manifest
.
MainPkg
,
t
.
Name
)
fmt
.
Printf
(
" expect(panic) = %q, got = %q
\n
"
,
expect
,
got
)
if
firstError
==
nil
{
firstError
=
fmt
.
Errorf
(
"expect(panic) = %q, got = %q"
,
expect
,
got
)
}
}
// 重新加载
{
m
,
err
=
wazero
.
BuildModule
(
cfg
,
wasmName
,
wasmBytes
,
wasmArgs
...
)
if
err
!=
nil
{
fmt
.
Println
(
err
)
os
.
Exit
(
1
)
}
// 临时方案: defer 太多
defer
m
.
Close
()
}
continue
}
if
err
!=
nil
{
if
len
(
stdout
)
>
0
{
if
s
:=
sWithPrefix
(
string
(
stdout
),
" "
);
s
!=
""
{
...
...
internal/loader/api.go
浏览文件 @
9f848656
...
...
@@ -44,9 +44,10 @@ type TestInfo struct {
// 测试函数信息
type
TestFuncInfo
struct
{
FuncPos
token
.
Pos
// 函数位置
Name
string
// 函数名, 不含包路径
Output
string
// 期望输出, 为空表示不验证
FuncPos
token
.
Pos
// 函数位置
Name
string
// 函数名, 不含包路径
Output
string
// 期望输出, 为空表示不验证
OutputPanic
bool
// 异常信息
}
// 汇编代码文件
...
...
internal/loader/loader.go
浏览文件 @
9f848656
...
...
@@ -300,10 +300,12 @@ func (p *_Loader) parseTestInfo(pkg *Package, filenames []string) (*TestInfo, er
switch
{
case
strings
.
HasPrefix
(
name
,
"Test"
)
:
output
,
isPanic
:=
p
.
parseExampleOutputComment
(
file
,
fn
)
tInfo
.
Tests
=
append
(
tInfo
.
Tests
,
TestFuncInfo
{
FuncPos
:
obj
.
Pos
(),
Name
:
name
,
Output
:
p
.
parseExampleOutputComment
(
file
,
fn
),
FuncPos
:
obj
.
Pos
(),
Name
:
name
,
Output
:
output
,
OutputPanic
:
isPanic
,
})
case
strings
.
HasPrefix
(
name
,
"Bench"
)
:
tInfo
.
Benchs
=
append
(
tInfo
.
Benchs
,
TestFuncInfo
{
...
...
@@ -311,10 +313,12 @@ func (p *_Loader) parseTestInfo(pkg *Package, filenames []string) (*TestInfo, er
Name
:
name
,
})
case
strings
.
HasPrefix
(
name
,
"Example"
)
:
output
,
isPanic
:=
p
.
parseExampleOutputComment
(
file
,
fn
)
tInfo
.
Examples
=
append
(
tInfo
.
Examples
,
TestFuncInfo
{
FuncPos
:
obj
.
Pos
(),
Name
:
name
,
Output
:
p
.
parseExampleOutputComment
(
file
,
fn
),
FuncPos
:
obj
.
Pos
(),
Name
:
name
,
Output
:
output
,
OutputPanic
:
isPanic
,
})
}
}
...
...
@@ -324,7 +328,7 @@ func (p *_Loader) parseTestInfo(pkg *Package, filenames []string) (*TestInfo, er
return
tInfo
,
nil
}
func
(
p
*
_Loader
)
parseExampleOutputComment
(
f
*
ast
.
File
,
fn
*
ast
.
FuncDecl
)
string
{
func
(
p
*
_Loader
)
parseExampleOutputComment
(
f
*
ast
.
File
,
fn
*
ast
.
FuncDecl
)
(
output
string
,
isPanic
bool
)
{
for
_
,
commentGroup
:=
range
f
.
Comments
{
if
commentGroup
.
Pos
()
<=
fn
.
Body
.
Pos
()
{
continue
...
...
@@ -334,23 +338,33 @@ func (p *_Loader) parseExampleOutputComment(f *ast.File, fn *ast.FuncDecl) strin
}
for
j
,
comment
:=
range
commentGroup
.
List
{
if
comment
.
Text
!=
"// Output:"
{
continue
}
switch
comment
.
Text
{
case
"// Output:"
:
var
lineTexts
[]
string
for
_
,
x
:=
range
commentGroup
.
List
[
j
+
1
:
]
{
if
!
strings
.
HasPrefix
(
x
.
Text
,
"//"
)
{
break
}
lineTexts
=
append
(
lineTexts
,
strings
.
TrimSpace
(
x
.
Text
[
2
:
]))
}
var
lineTexts
[]
string
for
_
,
x
:=
range
commentGroup
.
List
[
j
+
1
:
]
{
if
!
strings
.
HasPrefix
(
x
.
Text
,
"//"
)
{
break
return
strings
.
Join
(
lineTexts
,
"
\n
"
),
false
case
"// Output(panic):"
:
var
lineTexts
[]
string
for
_
,
x
:=
range
commentGroup
.
List
[
j
+
1
:
]
{
if
!
strings
.
HasPrefix
(
x
.
Text
,
"//"
)
{
break
}
lineTexts
=
append
(
lineTexts
,
strings
.
TrimSpace
(
x
.
Text
[
2
:
]))
}
lineTexts
=
append
(
lineTexts
,
strings
.
TrimSpace
(
x
.
Text
[
2
:
]))
}
return
strings
.
Join
(
lineTexts
,
"
\n
"
)
return
strings
.
Join
(
lineTexts
,
"
\n
"
),
true
}
}
}
return
""
return
""
,
false
}
func
(
p
*
_Loader
)
ParseDir_wsFiles
(
pkgpath
string
)
(
files
[]
*
WsFile
,
err
error
)
{
...
...
waroot/src/apple/apple_test.wa
浏览文件 @
9f848656
...
...
@@ -23,4 +23,11 @@ func ExampleApple {
// Output:
// apple-mvp
}
\ No newline at end of file
}
func ExamplePanic {
panic("fuck panic")
// Output(panic):
// fuck panic
}
waroot/src/builtin/builtin.wa
浏览文件 @
9f848656
...
...
@@ -12,40 +12,32 @@ const (
// u8 is the set of all unsigned 8-bit integers.
// Range: 0 through 255.
type u8: u8
type uint8: u8
// u16 is the set of all unsigned 16-bit integers.
// Range: 0 through 65535.
type u16: u16
type uint16: u16
// u32 is the set of all unsigned 32-bit integers.
// Range: 0 through 4294967295.
type u32: u32
type uint32: u32
// u64 is the set of all unsigned 64-bit integers.
// Range: 0 through 18446744073709551615.
type u64: u64
type uint64: u64
// int32 is the set of all signed 32-bit integers.
// Range: -2147483648 through 2147483647.
type i32: i32
type int32: i32
// int64 is the set of all signed 64-bit integers.
// Range: -9223372036854775808 through 9223372036854775807.
type i64: i64
type int64: i64
// float32 is the set of all IEEE-754 32-bit floating-point numbers.
type f32: f32
type float32: f32
// float64 is the set of all IEEE-754 64-bit floating-point numbers.
type f64: f64
type float64: f64
// string is the set of all strings of 8-bit bytes, conventionally but not
// necessarily representing UTF-8-encoded text. A string may be empty, but
...
...
@@ -60,10 +52,6 @@ type int: int
// distinct type, however, and not an alias for, say, u32.
type uint: uint
// uintptr is an integer type that is large enough to hold the bit pattern of
// any pointer.
type uintptr uintptr
// byte is an alias for u8 and is equivalent to u8 in all ways. It is
// used, by convention, to distinguish byte values from 8-bit unsigned
// integer values.
...
...
@@ -73,24 +61,14 @@ type byte = u8
// used, by convention, to distinguish character values from integer values.
type rune = i32
// iota is a predeclared identifier representing the untyped integer ordinal
// number of the current const specification in a (usually parenthesized)
// const declaration. It is zero-indexed.
const iota = 0 // Untyped int.
// nil is a predeclared identifier representing the zero value for a
// pointer, channel, func, interface, map, or slice type.
global nil: Type // Type must be a pointer, channel, func, interface, map, or slice type
// Type is here for the purposes of documentation only. It is a stand-in
// for any
Go
type, but represents the same type for any given function
// for any
Wa
type, but represents the same type for any given function
// invocation.
type Type: int
// Type1 is here for the purposes of documentation only. It is a stand-in
// for any Go type, but represents the same type for any given function
// invocation.
type Type1: int
// nil is a predeclared identifier representing the zero value for a
// pointer, func, interface, map, or slice type.
global nil: Type // Type must be a pointer, func, interface, map, or slice type
// IntegerType is here for the purposes of documentation only. It is a stand-in
// for any integer type: int, uint, int8 etc.
...
...
@@ -123,10 +101,8 @@ func copy(dst, src: []Type) => int
// Pointer to array: the number of elements in *v (even if v is nil).
// Slice, or map: the number of elements in v; if v is nil, len(v) is zero.
// String: the number of bytes in v.
// Channel: the number of elements queued (unread) in the channel buffer;
// if v is nil, len(v) is zero.
// For some arguments, such as a string literal or a simple array expression, the
// result can be a constant. See the
Go
language specification's "Length and
// result can be a constant. See the
Wa
language specification's "Length and
// capacity" section for details.
func len(v: Type) => int
...
...
@@ -135,15 +111,13 @@ func len(v: Type) => int
// Pointer to array: the number of elements in *v (same as len(v)).
// Slice: the maximum length the slice can reach when resliced;
// if v is nil, cap(v) is zero.
// Channel: the channel buffer capacity, in units of elements;
// if v is nil, cap(v) is zero.
// For some arguments, such as a simple array expression, the result can be a
// constant. See the
Go
language specification's "Length and capacity" section for
// constant. See the
Wa
language specification's "Length and capacity" section for
// details.
func cap(v: Type) => int
// The make built-in function allocates and initializes an object of type
// slice,
map, or chan (only)
. Like new, the first argument is a type, not a
// slice,
or map
. Like new, the first argument is a type, not a
// value. Unlike new, make's return type is the same as the type of its
// argument, not a pointer to it. The specification of the result depends on
// the type:
...
...
@@ -156,9 +130,6 @@ func cap(v: Type) => int
// Map: An empty map is allocated with enough space to hold the
// specified number of elements. The size may be omitted, in which case
// a small starting size is allocated.
// Channel: The channel's buffer is initialized with the specified
// buffer capacity. If zero, or the size is omitted, the channel is
// unbuffered.
func make(t: Type, size: ...IntegerType) => Type
// The new built-in function allocates memory. The first argument is a type,
...
...
@@ -167,15 +138,7 @@ func make(t: Type, size: ...IntegerType) => Type
func new(Type) => *Type
// The panic built-in function stops normal execution of the current
// goroutine. When a function F calls panic, normal execution of F stops
// immediately. Any functions whose execution was deferred by F are run in
// the usual way, and then F returns to its caller. To the caller G, the
// invocation of F then behaves like a call to panic, terminating G's
// execution and running any deferred functions. This continues until all
// functions in the executing goroutine have stopped, in reverse order. At
// that point, the program is terminated with a non-zero exit code. This
// termination sequence is called panicking and can be controlled by the
// built-in function recover.
// application.
func panic(msg: string)
// The print built-in function formats its arguments in an
...
...
waroot/src/math/bits/bits.wa
浏览文件 @
9f848656
...
...
@@ -4,6 +4,11 @@
//go:generate go run make_tables.go
const (
overflowError = "integer overflow"
divideError = "integer divide by zero"
)
const uintSize = 32 << (^uint(0) >> 63) // 32 or 64
// UintSize is the size of a uint in bits.
...
...
@@ -21,24 +26,24 @@ func LeadingZeros8(x: uint8) => int { return 8 - Len8(x) }
func LeadingZeros16(x: uint16) => int { return 16 - Len16(x) }
// LeadingZeros32 returns the number of leading zero bits in x; the result is 32 for x == 0.
func LeadingZeros32(x: u
int
32) => int { return 32 - Len32(x) }
func LeadingZeros32(x: u32) => int { return 32 - Len32(x) }
// LeadingZeros64 returns the number of leading zero bits in x; the result is 64 for x == 0.
func LeadingZeros64(x: u
int
64) => int { return 64 - Len64(x) }
func LeadingZeros64(x: u64) => int { return 64 - Len64(x) }
// --- TrailingZeros ---
// See http://supertech.csail.mit.edu/papers/debruijn.pdf
const deBruijn32 = 0x077CB531
var
deBruijn32tab = [32]byte{
global
deBruijn32tab = [32]byte{
0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9,
}
const deBruijn64 = 0x03f79d71b4ca8b09
var
deBruijn64tab = [64]byte{
global
deBruijn64tab = [64]byte{
0, 1, 56, 2, 57, 49, 28, 3, 61, 58, 42, 50, 38, 29, 17, 4,
62, 47, 59, 36, 45, 43, 51, 22, 53, 39, 33, 30, 24, 18, 12, 5,
63, 55, 48, 27, 60, 41, 37, 16, 46, 35, 44, 21, 52, 32, 23, 11,
...
...
@@ -48,9 +53,9 @@ var deBruijn64tab = [64]byte{
// TrailingZeros returns the number of trailing zero bits in x; the result is UintSize for x == 0.
func TrailingZeros(x: uint) => int {
if UintSize == 32 {
return TrailingZeros32(u
int
32(x))
return TrailingZeros32(u32(x))
}
return TrailingZeros64(u
int
64(x))
return TrailingZeros64(u64(x))
}
// TrailingZeros8 returns the number of trailing zero bits in x; the result is 8 for x == 0.
...
...
@@ -64,11 +69,11 @@ func TrailingZeros16(x: uint16) => int {
return 16
}
// see comment in TrailingZeros64
return int(deBruijn32tab[u
int
32(x&-x)*deBruijn32>>(32-5)])
return int(deBruijn32tab[u32(x&-x)*deBruijn32>>(32-5)])
}
// TrailingZeros32 returns the number of trailing zero bits in x; the result is 32 for x == 0.
func TrailingZeros32(x: u
int
32) => int {
func TrailingZeros32(x: u32) => int {
if x == 0 {
return 32
}
...
...
@@ -77,7 +82,7 @@ func TrailingZeros32(x: uint32) => int {
}
// TrailingZeros64 returns the number of trailing zero bits in x; the result is 64 for x == 0.
func TrailingZeros64(x: u
int
64) => int {
func TrailingZeros64(x: u64) => int {
if x == 0 {
return 64
}
...
...
@@ -106,9 +111,9 @@ const m4 = 0x0000ffff0000ffff
// OnesCount returns the number of one bits ("population count") in x.
func OnesCount(x: uint) => int {
if UintSize == 32 {
return OnesCount32(u
int
32(x))
return OnesCount32(u32(x))
}
return OnesCount64(u
int
64(x))
return OnesCount64(u64(x))
}
// OnesCount8 returns the number of one bits ("population count") in x.
...
...
@@ -122,12 +127,12 @@ func OnesCount16(x: uint16) => int {
}
// OnesCount32 returns the number of one bits ("population count") in x.
func OnesCount32(x: u
int
32) => int {
func OnesCount32(x: u32) => int {
return int(pop8tab[x>>24] + pop8tab[x>>16&0xff] + pop8tab[x>>8&0xff] + pop8tab[x&0xff])
}
// OnesCount64 returns the number of one bits ("population count") in x.
func OnesCount64(x: u
int
64) => int {
func OnesCount64(x: u64) => int {
// Implementation: Parallel summing of adjacent bits.
// See "Hacker's Delight", Chap. 5: Counting Bits.
// The following pattern shows the general approach:
...
...
@@ -165,9 +170,9 @@ func OnesCount64(x: uint64) => int {
// This function's execution time does not depend on the inputs.
func RotateLeft(x: uint, k: int) => uint {
if UintSize == 32 {
return uint(RotateLeft32(u
int
32(x), k))
return uint(RotateLeft32(u32(x), k))
}
return uint(RotateLeft64(u
int
64(x), k))
return uint(RotateLeft64(u64(x), k))
}
// RotateLeft8 returns the value of x rotated left by (k mod 8) bits.
...
...
@@ -194,7 +199,7 @@ func RotateLeft16(x: uint16, k: int) => uint16 {
// To rotate x right by k bits, call RotateLeft32(x, -k).
//
// This function's execution time does not depend on the inputs.
func RotateLeft32(x: u
int32, k: int) => uint
32 {
func RotateLeft32(x: u
32, k: int) => u
32 {
const n = 32
s := uint(k) & (n - 1)
return x<<s | x>>(n-s)
...
...
@@ -204,7 +209,7 @@ func RotateLeft32(x: uint32, k: int) => uint32 {
// To rotate x right by k bits, call RotateLeft64(x, -k).
//
// This function's execution time does not depend on the inputs.
func RotateLeft64(x: u
int64, k: int) => uint
64 {
func RotateLeft64(x: u
64, k: int) => u
64 {
const n = 64
s := uint(k) & (n - 1)
return x<<s | x>>(n-s)
...
...
@@ -215,9 +220,9 @@ func RotateLeft64(x: uint64, k: int) => uint64 {
// Reverse returns the value of x with its bits in reversed order.
func Reverse(x: uint) => uint {
if UintSize == 32 {
return uint(Reverse32(u
int
32(x)))
return uint(Reverse32(u32(x)))
}
return uint(Reverse64(u
int
64(x)))
return uint(Reverse64(u64(x)))
}
// Reverse8 returns the value of x with its bits in reversed order.
...
...
@@ -231,7 +236,7 @@ func Reverse16(x: uint16) => uint16 {
}
// Reverse32 returns the value of x with its bits in reversed order.
func Reverse32(x: u
int32) => uint
32 {
func Reverse32(x: u
32) => u
32 {
const m = 1<<32 - 1
x = x>>1&(m0&m) | x&(m0&m)<<1
x = x>>2&(m1&m) | x&(m1&m)<<2
...
...
@@ -240,7 +245,7 @@ func Reverse32(x: uint32) => uint32 {
}
// Reverse64 returns the value of x with its bits in reversed order.
func Reverse64(x: u
int64) => uint
64 {
func Reverse64(x: u
64) => u
64 {
const m = 1<<64 - 1
x = x>>1&(m0&m) | x&(m0&m)<<1
x = x>>2&(m1&m) | x&(m1&m)<<2
...
...
@@ -255,9 +260,9 @@ func Reverse64(x: uint64) => uint64 {
// This function's execution time does not depend on the inputs.
func ReverseBytes(x: uint) => uint {
if UintSize == 32 {
return uint(ReverseBytes32(u
int
32(x)))
return uint(ReverseBytes32(u32(x)))
}
return uint(ReverseBytes64(u
int
64(x)))
return uint(ReverseBytes64(u64(x)))
}
// ReverseBytes16 returns the value of x with its bytes in reversed order.
...
...
@@ -270,7 +275,7 @@ func ReverseBytes16(x: uint16) => uint16 {
// ReverseBytes32 returns the value of x with its bytes in reversed order.
//
// This function's execution time does not depend on the inputs.
func ReverseBytes32(x: u
int32) => uint
32 {
func ReverseBytes32(x: u
32) => u
32 {
const m = 1<<32 - 1
x = x>>8&(m3&m) | x&(m3&m)<<8
return x>>16 | x<<16
...
...
@@ -279,7 +284,7 @@ func ReverseBytes32(x: uint32) => uint32 {
// ReverseBytes64 returns the value of x with its bytes in reversed order.
//
// This function's execution time does not depend on the inputs.
func ReverseBytes64(x: u
int64) => uint
64 {
func ReverseBytes64(x: u
64) => u
64 {
const m = 1<<64 - 1
x = x>>8&(m3&m) | x&(m3&m)<<8
x = x>>16&(m4&m) | x&(m4&m)<<16
...
...
@@ -291,9 +296,9 @@ func ReverseBytes64(x: uint64) => uint64 {
// Len returns the minimum number of bits required to represent x; the result is 0 for x == 0.
func Len(x: uint) => int {
if UintSize == 32 {
return Len32(u
int
32(x))
return Len32(u32(x))
}
return Len64(u
int
64(x))
return Len64(u64(x))
}
// Len8 returns the minimum number of bits required to represent x; the result is 0 for x == 0.
...
...
@@ -311,7 +316,7 @@ func Len16(x: uint16) => (n: int) {
}
// Len32 returns the minimum number of bits required to represent x; the result is 0 for x == 0.
func Len32(x: u
int
32) => (n: int) {
func Len32(x: u32) => (n: int) {
if x >= 1<<16 {
x >>= 16
n = 16
...
...
@@ -324,7 +329,7 @@ func Len32(x: uint32) => (n: int) {
}
// Len64 returns the minimum number of bits required to represent x; the result is 0 for x == 0.
func Len64(x: u
int
64) => (n: int) {
func Len64(x: u64) => (n: int) {
if x >= 1<<32 {
x >>= 32
n = 32
...
...
@@ -349,10 +354,10 @@ func Len64(x: uint64) => (n: int) {
// This function's execution time does not depend on the inputs.
func Add(x, y, carry: uint) => (sum, carryOut: uint) {
if UintSize == 32 {
s32, c32 := Add32(u
int32(x), uint32(y), uint
32(carry))
s32, c32 := Add32(u
32(x), u32(y), u
32(carry))
return uint(s32), uint(c32)
}
s64, c64 := Add64(u
int64(x), uint64(y), uint
64(carry))
s64, c64 := Add64(u
64(x), u64(y), u
64(carry))
return uint(s64), uint(c64)
}
...
...
@@ -361,10 +366,10 @@ func Add(x, y, carry: uint) => (sum, carryOut: uint) {
// The carryOut output is guaranteed to be 0 or 1.
//
// This function's execution time does not depend on the inputs.
func Add32(x, y, carry: u
int32) => (sum, carryOut: uint
32) {
sum64 := u
int64(x) + uint64(y) + uint
64(carry)
sum = u
int
32(sum64)
carryOut = u
int
32(sum64 >> 32)
func Add32(x, y, carry: u
32) => (sum, carryOut: u
32) {
sum64 := u
64(x) + u64(y) + u
64(carry)
sum = u32(sum64)
carryOut = u32(sum64 >> 32)
return
}
...
...
@@ -373,7 +378,7 @@ func Add32(x, y, carry: uint32) => (sum, carryOut: uint32) {
// The carryOut output is guaranteed to be 0 or 1.
//
// This function's execution time does not depend on the inputs.
func Add64(x, y, carry: u
int64) => (sum, carryOut: uint
64) {
func Add64(x, y, carry: u
64) => (sum, carryOut: u
64) {
sum = x + y + carry
// The sum will overflow if both top bits are set (x & y) or if one of them
// is (x | y), and a carry from the lower place happened. If such a carry
...
...
@@ -391,10 +396,10 @@ func Add64(x, y, carry: uint64) => (sum, carryOut: uint64) {
// This function's execution time does not depend on the inputs.
func Sub(x, y, borrow: uint) => (diff, borrowOut: uint) {
if UintSize == 32 {
d32, b32 := Sub32(u
int32(x), uint32(y), uint
32(borrow))
d32, b32 := Sub32(u
32(x), u32(y), u
32(borrow))
return uint(d32), uint(b32)
}
d64, b64 := Sub64(u
int64(x), uint64(y), uint
64(borrow))
d64, b64 := Sub64(u
64(x), u64(y), u
64(borrow))
return uint(d64), uint(b64)
}
...
...
@@ -403,7 +408,7 @@ func Sub(x, y, borrow: uint) => (diff, borrowOut: uint) {
// The borrowOut output is guaranteed to be 0 or 1.
//
// This function's execution time does not depend on the inputs.
func Sub32(x, y, borrow: u
int32) => (diff, borrowOut: uint
32) {
func Sub32(x, y, borrow: u
32) => (diff, borrowOut: u
32) {
diff = x - y - borrow
// The difference will underflow if the top bit of x is not set and the top
// bit of y is set (^x & y) or if they are the same (^(x ^ y)) and a borrow
...
...
@@ -418,7 +423,7 @@ func Sub32(x, y, borrow: uint32) => (diff, borrowOut: uint32) {
// The borrowOut output is guaranteed to be 0 or 1.
//
// This function's execution time does not depend on the inputs.
func Sub64(x, y, borrow: u
int64) => (diff, borrowOut: uint
64) {
func Sub64(x, y, borrow: u
64) => (diff, borrowOut: u
64) {
diff = x - y - borrow
// See Sub32 for the bit logic.
borrowOut = ((^x & y) | (^(x ^ y) & diff)) >> 63
...
...
@@ -434,10 +439,10 @@ func Sub64(x, y, borrow: uint64) => (diff, borrowOut: uint64) {
// This function's execution time does not depend on the inputs.
func Mul(x, y: uint) => (hi, lo: uint) {
if UintSize == 32 {
h, l := Mul32(u
int32(x), uint
32(y))
h, l := Mul32(u
32(x), u
32(y))
return uint(h), uint(l)
}
h, l := Mul64(u
int64(x), uint
64(y))
h, l := Mul64(u
64(x), u
64(y))
return uint(h), uint(l)
}
...
...
@@ -446,9 +451,9 @@ func Mul(x, y: uint) => (hi, lo: uint) {
// half returned in lo.
//
// This function's execution time does not depend on the inputs.
func Mul32(x, y: u
int32) => (hi, lo: uint
32) {
tmp := u
int64(x) * uint
64(y)
hi, lo = u
int32(tmp>>32), uint
32(tmp)
func Mul32(x, y: u
32) => (hi, lo: u
32) {
tmp := u
64(x) * u
64(y)
hi, lo = u
32(tmp>>32), u
32(tmp)
return
}
...
...
@@ -457,7 +462,7 @@ func Mul32(x, y: uint32) => (hi, lo: uint32) {
// half returned in lo.
//
// This function's execution time does not depend on the inputs.
func Mul64(x, y: u
int64) => (hi, lo: uint
64) {
func Mul64(x, y: u
64) => (hi, lo: u
64) {
const mask32 = 1<<32 - 1
x0 := x & mask32
x1 := x >> 32
...
...
@@ -481,10 +486,10 @@ func Mul64(x, y: uint64) => (hi, lo: uint64) {
// Div panics for y == 0 (division by zero) or y <= hi (quotient overflow).
func Div(hi, lo, y: uint) => (quo, rem: uint) {
if UintSize == 32 {
q, r := Div32(u
int32(hi), uint32(lo), uint
32(y))
q, r := Div32(u
32(hi), u32(lo), u
32(y))
return uint(q), uint(r)
}
q, r := Div64(u
int64(hi), uint64(lo), uint
64(y))
q, r := Div64(u
64(hi), u64(lo), u
64(y))
return uint(q), uint(r)
}
...
...
@@ -492,12 +497,15 @@ func Div(hi, lo, y: uint) => (quo, rem: uint) {
// quo = (hi, lo)/y, rem = (hi, lo)%y with the dividend bits' upper
// half in parameter hi and the lower half in parameter lo.
// Div32 panics for y == 0 (division by zero) or y <= hi (quotient overflow).
func Div32(hi, lo, y: u
int32) => (quo, rem: uint
32) {
func Div32(hi, lo, y: u
32) => (quo, rem: u
32) {
if y != 0 && y <= hi {
// panic(overflowError)
panic(overflowError)
}
if y == 0 {
panic(divideError)
}
z := u
int64(hi)<<32 | uint
64(lo)
quo, rem = u
int32(z/uint64(y)), uint32(z%uint
64(y))
z := u
64(hi)<<32 | u
64(lo)
quo, rem = u
32(z/u64(y)), u32(z%u
64(y))
return
}
...
...
@@ -505,16 +513,16 @@ func Div32(hi, lo, y: uint32) => (quo, rem: uint32) {
// quo = (hi, lo)/y, rem = (hi, lo)%y with the dividend bits' upper
// half in parameter hi and the lower half in parameter lo.
// Div64 panics for y == 0 (division by zero) or y <= hi (quotient overflow).
func Div64(hi, lo, y: u
int64) => (quo, rem: uint
64) {
func Div64(hi, lo, y: u
64) => (quo, rem: u
64) {
const (
two32 = 1 << 32
mask32 = two32 - 1
)
if y == 0 {
//
panic(divideError)
panic(divideError)
}
if y <= hi {
//
panic(overflowError)
panic(overflowError)
}
s := uint(LeadingZeros64(y))
...
...
@@ -557,22 +565,22 @@ func Div64(hi, lo, y: uint64) => (quo, rem: uint64) {
// quotient overflow.
func Rem(hi, lo, y: uint) => uint {
if UintSize == 32 {
return uint(Rem32(u
int32(hi), uint32(lo), uint
32(y)))
return uint(Rem32(u
32(hi), u32(lo), u
32(y)))
}
return uint(Rem64(u
int64(hi), uint64(lo), uint
64(y)))
return uint(Rem64(u
64(hi), u64(lo), u
64(y)))
}
// Rem32 returns the remainder of (hi, lo) divided by y. Rem32 panics
// for y == 0 (division by zero) but, unlike Div32, it doesn't panic
// on a quotient overflow.
func Rem32(hi, lo, y: u
int32) => uint
32 {
return u
int32((uint64(hi)<<32 | uint64(lo)) % uint
64(y))
func Rem32(hi, lo, y: u
32) => u
32 {
return u
32((u64(hi)<<32 | u64(lo)) % u
64(y))
}
// Rem64 returns the remainder of (hi, lo) divided by y. Rem64 panics
// for y == 0 (division by zero) but, unlike Div64, it doesn't panic
// on a quotient overflow.
func Rem64(hi, lo, y: u
int64) => uint
64 {
func Rem64(hi, lo, y: u
64) => u
64 {
// We scale down hi so that hi < y, then use Div64 to compute the
// rem with the guarantee that it won't panic on quotient overflow.
// Given that
...
...
waroot/src/math/bits/bits_errors_bootstrap.wa
已删除
100644 → 0
浏览文件 @
3693430e
// Copyright 2019 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.
//go:build compiler_bootstrap
// +build compiler_bootstrap
// This version used only for bootstrap (on this path we want
// to avoid use of go:linkname as applied to variables).
type errorString struct {
msg string
}
func (e: errorString) RuntimeError {}
func (e: errorString) Error => string {
return "runtime error: " + string(e.msg)
}
var overflowError = error(&errorString{"integer overflow"})
var divideError = error(&errorString{"integer divide by zero"})
waroot/src/math/bits/bits_panic_test.wa
0 → 100644
浏览文件 @
9f848656
// 版权 @2023 凹语言 作者。保留所有权利。
const (
divZeroError = "runtime error: integer divide by zero"
)
func TestDivPanicOverflow {
// Output(panic):
// integer overflow
assert(overflowError == "integer overflow")
q, r := Div(1, 0, 1)
_, _= q, r
assert(false, "should panic")
}
func TestDiv32PanicOverflow {
// Output(panic):
// integer overflow
assert(overflowError == "integer overflow")
q, r := Div32(1, 0, 1)
_, _= q, r
assert(false, "should panic")
}
func TestDiv64PanicOverflow {
// Output(panic):
// integer overflow
assert(overflowError == "integer overflow")
q, r := Div64(1, 0, 1)
_, _= q, r
assert(false, "should panic")
}
func TestDivPanicZero {
// Output(panic):
// integer divide by zero
assert(divideError == "integer divide by zero")
q, r := Div(1, 1, 0)
_, _= q, r
assert(false, "should panic")
}
func TestDiv32PanicZero {
// Output(panic):
// integer divide by zero
assert(divideError == "integer divide by zero")
q, r := Div32(1, 1, 0)
_, _= q, r
assert(false, "should panic")
}
func TestDiv64PanicZero {
// Output(panic):
// integer divide by zero
assert(divideError == "integer divide by zero")
q, r := Div64(1, 1, 0)
_, _= q, r
assert(false, "should panic")
}
waroot/src/math/bits/bits_test.wa
0 → 100644
浏览文件 @
9f848656
// 版权 @2023 凹语言 作者。保留所有权利。
// ----------------------------------------------------------------------------
// Testing support
const DeBruijn64 = deBruijn64
type entry = struct {
nlz, ntz, pop: int
}
// tab contains results for all uint8 values
global tab: [256]entry
func init() {
tab[0] = entry{8, 8, 0}
for i := 1; i < len(tab); i++ {
// nlz
x := i // x != 0
n := 0
for x&0x80 == 0 {
n++
x <<= 1
}
tab[i].nlz = n
// ntz
x = i // x != 0
n = 0
for x&1 == 0 {
n++
x >>= 1
}
tab[i].ntz = n
// pop
x = i // x != 0
n = 0
for x != 0 {
n += int(x & 1)
x >>= 1
}
tab[i].pop = n
}
}
// ----------------------------------------------------------------------------
func TestUintSize {
assert(UintSize == 32)
}
func TestLeadingZeros {
for i := 0; i < 256; i++ {
nlz := tab[i].nlz
for k := 0; k < 64-8; k++ {
x := u64(i) << uint(k)
if x <= 1<<8-1 {
got := LeadingZeros8(uint8(x))
want := nlz - k + (8 - 8)
if x == 0 {
want = 8
}
assert(got == want, "LeadingZeros8 got != want")
}
if x <= 1<<16-1 {
got := LeadingZeros16(uint16(x))
want := nlz - k + (16 - 8)
if x == 0 {
want = 16
}
assert(got == want, "LeadingZeros16 got != want")
}
if x <= 1<<32-1 {
got := LeadingZeros32(uint32(x))
want := nlz - k + (32 - 8)
if x == 0 {
want = 32
}
assert(got == want, "LeadingZeros32 got != want")
if UintSize == 32 {
got = LeadingZeros(uint(x))
if got != want {
assert(got == want, "LeadingZeros got != want")
}
}
}
if x <= 1<<64-1 {
got := LeadingZeros64(u64(x))
want := nlz - k + (64 - 8)
if x == 0 {
want = 64
}
assert(got == want, "LeadingZeros64 got != want")
if UintSize == 64 {
got = LeadingZeros(uint(x))
if got != want {
assert(got == want, "LeadingZeros got != want")
}
}
}
}
}
}
func TestTrailingZeros {
for i := 0; i < 256; i++ {
ntz := tab[i].ntz
for k := 0; k < 64-8; k++ {
x := u64(i) << uint(k)
want := ntz + k
if x <= 1<<8-1 {
got := TrailingZeros8(u8(x))
if x == 0 {
want = 8
}
if got != want {
assert(got == want, "TrailingZeros8 got != want")
}
}
if x <= 1<<16-1 {
got := TrailingZeros16(u16(x))
if x == 0 {
want = 16
}
if got != want {
assert(got == want, "TrailingZeros16 got != want")
}
}
if x <= 1<<32-1 {
got := TrailingZeros32(u32(x))
if x == 0 {
want = 32
}
if got != want {
assert(got == want, "TrailingZeros32 got != want")
}
if UintSize == 32 {
got = TrailingZeros(uint(x))
if got != want {
assert(got == want, "TrailingZeros got != want")
}
}
}
if x <= 1<<64-1 {
got := TrailingZeros64(u64(x))
if x == 0 {
want = 64
}
if got != want {
assert(got == want, "TrailingZeros64 got != want")
}
if UintSize == 64 {
got = TrailingZeros(uint(x))
if got != want {
assert(got == want, "TrailingZeros got != want")
}
}
}
}
}
}
func TestOnesCount {
x: u64
for i := 0; i <= 64; i++ {
testOnesCount(x, i)
x = x<<1 | 1
}
for i := 64; i >= 0; i-- {
testOnesCount(x, i)
x = x << 1
}
for i := 0; i < 256; i++ {
for k := 0; k < 64-8; k++ {
testOnesCount(u64(i)<<uint(k), tab[i].pop)
}
}
}
func testOnesCount(x: u64, want: int) {
if x <= 1<<8-1 {
got := OnesCount8(u8(x))
if got != want {
assert(got == want, "OnesCount8 got != want")
}
}
if x <= 1<<16-1 {
got := OnesCount16(u16(x))
if got != want {
assert(got == want, "OnesCount16 got != want")
}
}
if x <= 1<<32-1 {
got := OnesCount32(u32(x))
if got != want {
assert(got == want, "OnesCount32 got != want")
}
if UintSize == 32 {
got = OnesCount(uint(x))
if got != want {
assert(got == want, "OnesCount got != want")
}
}
}
if x <= 1<<64-1 {
got := OnesCount64(u64(x))
if got != want {
assert(got == want, "OnesCount64 got != want")
}
if UintSize == 64 {
got = OnesCount(uint(x))
if got != want {
assert(got == want, "OnesCount got != want")
}
}
}
}
func TestRotateLeft {
m: u64 = DeBruijn64
for k := uint(0); k < 128; k++ {
x8 := u8(m)
got8 := RotateLeft8(x8, int(k))
want8 := x8<<(k&0x7) | x8>>(8-k&0x7)
if got8 != want8 {
assert(got8 == want8, "RotateLeft8 got != want")
}
got8 = RotateLeft8(want8, -int(k))
if got8 != x8 {
assert(got8 == x8, "RotateLeft8 got != want")
}
x16 := u16(m)
got16 := RotateLeft16(x16, int(k))
want16 := x16<<(k&0xf) | x16>>(16-k&0xf)
if got16 != want16 {
assert(got16 == want16, "RotateLeft16 got != want")
}
got16 = RotateLeft16(want16, -int(k))
if got16 != x16 {
assert(got16 == x16, "RotateLeft16 got != want")
}
x32 := uint32(m)
got32 := RotateLeft32(x32, int(k))
want32 := x32<<(k&0x1f) | x32>>(32-k&0x1f)
if got32 != want32 {
assert(got32 == want32, "RotateLeft32 got != want")
}
got32 = RotateLeft32(want32, -int(k))
if got32 != x32 {
assert(got32 == x32, "RotateLeft32 got != want")
}
if UintSize == 32 {
x := uint(m)
got := RotateLeft(x, int(k))
want := x<<(k&0x1f) | x>>(32-k&0x1f)
if got != want {
assert(got == want, "RotateLeft got != want")
}
got = RotateLeft(want, -int(k))
if got != x {
assert(got == x, "RotateLeft got != want")
}
}
x64 := u64(m)
got64 := RotateLeft64(x64, int(k))
want64 := x64<<(k&0x3f) | x64>>(64-k&0x3f)
if got64 != want64 {
assert(got64 == want64, "RotateLeft64 got != want")
}
got64 = RotateLeft64(want64, -int(k))
if got64 != x64 {
assert(got64 == x64, "RotateLeft64 got != want")
}
if UintSize == 64 {
x := uint(m)
got := RotateLeft(x, int(k))
want := x<<(k&0x3f) | x>>(64-k&0x3f)
if got != want {
assert(got == want, "RotateLeft got != want")
}
got = RotateLeft(want, -int(k))
if got != x {
assert(got == x, "RotateLeft got != want")
}
}
}
}
func TestReverse {
// test each bit
for i := uint(0); i < 64; i++ {
testReverse(u64(1)<<i, u64(1)<<(63-i))
}
// test a few patterns
for _, test := range []struct {
x, r: u64
}{
{0, 0},
{0x1, 0x8 << 60},
{0x2, 0x4 << 60},
{0x3, 0xc << 60},
{0x4, 0x2 << 60},
{0x5, 0xa << 60},
{0x6, 0x6 << 60},
{0x7, 0xe << 60},
{0x8, 0x1 << 60},
{0x9, 0x9 << 60},
{0xa, 0x5 << 60},
{0xb, 0xd << 60},
{0xc, 0x3 << 60},
{0xd, 0xb << 60},
{0xe, 0x7 << 60},
{0xf, 0xf << 60},
{0x5686487, 0xe12616a000000000},
{0x0123456789abcdef, 0xf7b3d591e6a2c480},
} {
testReverse(test.x, test.r)
testReverse(test.r, test.x)
}
}
func testReverse(x64, want64: u64) {
x8 := u8(x64)
got8 := Reverse8(x8)
want8 := u8(want64 >> (64 - 8))
if got8 != want8 {
assert(got8 == want8, "Reverse8 got != want")
}
x16 := u16(x64)
got16 := Reverse16(x16)
want16 := u16(want64 >> (64 - 16))
if got16 != want16 {
assert(got16 == want16, "Reverse16 got != want")
}
x32 := u32(x64)
got32 := Reverse32(x32)
want32 := u32(want64 >> (64 - 32))
if got32 != want32 {
assert(got32 == want32, "Reverse32 got != want")
}
if UintSize == 32 {
x := uint(x32)
got := Reverse(x)
want := uint(want32)
if got != want {
assert(got == want, "Reverse got != want")
}
}
got64 := Reverse64(x64)
if got64 != want64 {
assert(got64 == want64, "Reverse64 got != want")
}
if UintSize == 64 {
x := uint(x64)
got := Reverse(x)
want := uint(want64)
if got != want {
assert(got == want, "Reverse got != want")
}
}
}
func TestReverseBytes {
for _, test := range []struct {
x, r uint64
}{
{0, 0},
{0x01, 0x01 << 56},
{0x0123, 0x2301 << 48},
{0x012345, 0x452301 << 40},
{0x01234567, 0x67452301 << 32},
{0x0123456789, 0x8967452301 << 24},
{0x0123456789ab, 0xab8967452301 << 16},
{0x0123456789abcd, 0xcdab8967452301 << 8},
{0x0123456789abcdef, 0xefcdab8967452301 << 0},
} {
testReverseBytes(test.x, test.r)
testReverseBytes(test.r, test.x)
}
}
func testReverseBytes(x64, want64: u64) {
x16 := u16(x64)
got16 := ReverseBytes16(x16)
want16 := u16(want64 >> (64 - 16))
if got16 != want16 {
assert(got16 == want16, "ReverseBytes16 got != want")
}
x32 := u32(x64)
got32 := ReverseBytes32(x32)
want32 := u32(want64 >> (64 - 32))
if got32 != want32 {
assert(got32 == want32, "ReverseBytes32 got != want")
}
if UintSize == 32 {
x := uint(x32)
got := ReverseBytes(x)
want := uint(want32)
if got != want {
assert(got == want, "ReverseBytes got != want")
}
}
got64 := ReverseBytes64(x64)
if got64 != want64 {
assert(got64 == want64, "ReverseBytes64 got != want")
}
if UintSize == 64 {
x := uint(x64)
got := ReverseBytes(x)
want := uint(want64)
if got != want {
assert(got == want, "ReverseBytes got != want")
}
}
}
func TestLen {
for i := 0; i < 256; i++ {
len := 8 - tab[i].nlz
for k := 0; k < 64-8; k++ {
x := u64(i) << uint(k)
want := 0
if x != 0 {
want = len + k
}
if x <= 1<<8-1 {
got := Len8(u8(x))
if got != want {
assert(got == want, "Len8 got != want")
}
}
if x <= 1<<16-1 {
got := Len16(u16(x))
if got != want {
assert(got == want, "Len16 got != want")
}
}
if x <= 1<<32-1 {
got := Len32(u32(x))
if got != want {
assert(got == want, "Len32 got != want")
}
if UintSize == 32 {
got := Len(uint(x))
if got != want {
assert(got == want, "Len got != want")
}
}
}
if x <= 1<<64-1 {
got := Len64(u64(x))
if got != want {
assert(got == want, "Len64 got != want")
}
if UintSize == 64 {
got := Len(uint(x))
if got != want {
assert(got == want, "Len got != want")
}
}
}
}
}
}
func TestRem32 {
// Sanity check: for non-oveflowing dividends, the result is the
// same as the rem returned by Div32
hi, lo, y := u32(510510), u32(9699690), u32(510510+1) // ensure hi < y
for i := 0; i < 1000; i++ {
r := Rem32(hi, lo, y)
_, r2 := Div32(hi, lo, y)
if r != r2 {
assert(false, "Rem32 failed")
}
y += 13
}
}
func TestRem32Overflow {
// To trigger a quotient overflow, we need y <= hi
hi, lo, y := u32(510510), u32(9699690), u32(7)
for i := 0; i < 1000; i++ {
r := Rem32(hi, lo, y)
_, r2 := Div64(0, u64(hi)<<32|u64(lo), u64(y))
if r != u32(r2) {
assert(false, "Rem32 failed")
}
y += 13
}
}
func TestRem64 {
// Sanity check: for non-oveflowing dividends, the result is the
// same as the rem returned by Div64
hi, lo, y := u64(510510), u64(9699690), u64(510510+1) // ensure hi < y
for i := 0; i < 1000; i++ {
r := Rem64(hi, lo, y)
_, r2 := Div64(hi, lo, y)
if r != r2 {
assert(false, "Rem64 failed")
}
y += 13
}
}
func TestRem64Overflow {
Rem64Tests := []struct {
hi, lo, y: u64
rem: u64
}{
// Testcases computed using Python 3, as:
// >>> hi = 42; lo = 1119; y = 42
// >>> ((hi<<64)+lo) % y
{42, 1119, 42, 27},
{42, 1119, 38, 9},
{42, 1119, 26, 23},
{469, 0, 467, 271},
{469, 0, 113, 58},
{111111, 111111, 1171, 803},
{3968194946088682615, 3192705705065114702, 1000037, 56067},
}
for _, rt := range Rem64Tests {
if rt.hi < rt.y {
assert(false, "Rem64 is not a test with quo overflow")
}
rem := Rem64(rt.hi, rt.lo, rt.y)
if rem != rt.rem {
assert(false, "Rem64 failed")
}
}
}
waroot/src/math/bits/example_test.wa
0 → 100644
浏览文件 @
9f848656
// 版权 @2023 凹语言 作者。保留所有权利。
func TestLeadingZeros8 {
assert(0b00000001 == 1)
assert(7 == LeadingZeros8(1))
}
func TestLeadingZeros16 {
assert(0b0000000000000001 == 1)
assert(15 == LeadingZeros16(1))
}
func TestLeadingZeros32 {
assert(0b00000000000000000000000000000001 == 1)
assert(31 == LeadingZeros32(1))
}
func TestLeadingZeros64 {
assert(0b0000000000000000000000000000000000000000000000000000000000000001 == 1)
assert(63 == LeadingZeros64(1))
}
func TestTrailingZeros8 {
assert(0b00001110 == 14)
assert(1 == TrailingZeros8(14))
}
func TestTrailingZeros16 {
assert(0b0000000000001110 == 14)
assert(1 == TrailingZeros16(14))
}
func TestTrailingZeros32 {
assert(0b00000000000000000000000000001110 == 14)
assert(1 == TrailingZeros32(14))
}
func TestTrailingZeros64 {
assert(0b0000000000000000000000000000000000000000000000000000000000001110 == 14)
assert(1 == TrailingZeros64(14))
}
func TestOnesCount8 {
assert(0b00001110 == 14)
assert(3 == OnesCount8(14))
}
func TestOnesCount16 {
assert(0b0000000000001110 == 14)
assert(3 == OnesCount16(14))
}
func TestOnesCount32 {
assert(0b00000000000000000000000000001110 == 14)
assert(3 == OnesCount32(14))
}
func TestOnesCount64 {
assert(0b0000000000000000000000000000000000000000000000000000000000001110 == 14)
assert(3 == OnesCount64(14))
}
func TestRotateLeft8 {
assert(0b00001111 == 15)
assert(0b00111100 == RotateLeft8(15, 2))
assert(0b11000011 == RotateLeft8(15, -2))
}
func TestRotateLeft16 {
assert(0b0000000000001111 == 15)
assert(0b0000000000111100 == RotateLeft16(15, 2))
assert(0b1100000000000011 == RotateLeft16(15, -2))
}
func TestRotateLeft32 {
assert(0b00000000000000000000000000001111 == 15)
assert(0b00000000000000000000000000111100 == RotateLeft32(15, 2))
assert(0b11000000000000000000000000000011 == RotateLeft32(15, -2))
}
func TestRotateLeft64 {
assert(0b0000000000000000000000000000000000000000000000000000000000001111 == 15)
assert(0b0000000000000000000000000000000000000000000000000000000000111100 == RotateLeft64(15, 2))
assert(0b1100000000000000000000000000000000000000000000000000000000000011 == RotateLeft64(15, -2))
}
func TestReverse8 {
assert(0b00010011 == 19)
assert(0b11001000 == Reverse8(19))
}
func TestReverse16 {
assert(0b0000000000010011 == 19)
assert(0b1100100000000000 == Reverse16(19))
}
func TestReverse32 {
assert(0b00000000000000000000000000010011 == 19)
assert(0b11001000000000000000000000000000 == Reverse32(19))
}
func TestReverse64 {
assert(0b0000000000000000000000000000000000000000000000000000000000010011 == 19)
assert(0b1100100000000000000000000000000000000000000000000000000000000000 == Reverse64(19))
}
func TestReverseBytes16 {
assert(0b0000000000001111 == 15)
assert(0b0000111100000000 == ReverseBytes16(15))
}
func TestReverseBytes32 {
assert(0b00000000000000000000000000001111 == 15)
assert(0b00001111000000000000000000000000 == ReverseBytes32(15))
}
func TestReverseBytes64 {
assert(0b0000000000000000000000000000000000000000000000000000000000001111 == 15)
assert(0b0000111100000000000000000000000000000000000000000000000000000000 == ReverseBytes64(15))
}
func TestLen8 {
assert(0b00001000 == 8)
assert(4 == Len8(8))
}
func TestLen16 {
assert(0b0000000000001000 == 8)
assert(4 == Len16(8))
}
func TestLen32 {
assert(0b00000000000000000000000000001000 == 8)
assert(4 == Len32(8))
}
func TestLen64 {
assert(0b0000000000000000000000000000000000000000000000000000000000001000 == 8)
assert(4 == Len64(8))
}
waroot/src/math/bits/make_examples.go
已删除
100644 → 0
浏览文件 @
3693430e
// Copyright 2017 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.
//go:build ignore
// +build ignore
// This program generates example_test.go.
package
main
import
(
"bytes"
"fmt"
"log"
"math/bits"
"os"
)
const
header
=
`// Copyright 2017 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.
// Code generated by go run make_examples.go. DO NOT EDIT.
package bits_test
import (
"fmt"
"math/bits"
)
`
func
main
()
{
w
:=
bytes
.
NewBuffer
([]
byte
(
header
))
for
_
,
e
:=
range
[]
struct
{
name
string
in
int
out
[
4
]
interface
{}
out2
[
4
]
interface
{}
}{
{
name
:
"LeadingZeros"
,
in
:
1
,
out
:
[
4
]
interface
{}{
bits
.
LeadingZeros8
(
1
),
bits
.
LeadingZeros16
(
1
),
bits
.
LeadingZeros32
(
1
),
bits
.
LeadingZeros64
(
1
)},
},
{
name
:
"TrailingZeros"
,
in
:
14
,
out
:
[
4
]
interface
{}{
bits
.
TrailingZeros8
(
14
),
bits
.
TrailingZeros16
(
14
),
bits
.
TrailingZeros32
(
14
),
bits
.
TrailingZeros64
(
14
)},
},
{
name
:
"OnesCount"
,
in
:
14
,
out
:
[
4
]
interface
{}{
bits
.
OnesCount8
(
14
),
bits
.
OnesCount16
(
14
),
bits
.
OnesCount32
(
14
),
bits
.
OnesCount64
(
14
)},
},
{
name
:
"RotateLeft"
,
in
:
15
,
out
:
[
4
]
interface
{}{
bits
.
RotateLeft8
(
15
,
2
),
bits
.
RotateLeft16
(
15
,
2
),
bits
.
RotateLeft32
(
15
,
2
),
bits
.
RotateLeft64
(
15
,
2
)},
out2
:
[
4
]
interface
{}{
bits
.
RotateLeft8
(
15
,
-
2
),
bits
.
RotateLeft16
(
15
,
-
2
),
bits
.
RotateLeft32
(
15
,
-
2
),
bits
.
RotateLeft64
(
15
,
-
2
)},
},
{
name
:
"Reverse"
,
in
:
19
,
out
:
[
4
]
interface
{}{
bits
.
Reverse8
(
19
),
bits
.
Reverse16
(
19
),
bits
.
Reverse32
(
19
),
bits
.
Reverse64
(
19
)},
},
{
name
:
"ReverseBytes"
,
in
:
15
,
out
:
[
4
]
interface
{}{
nil
,
bits
.
ReverseBytes16
(
15
),
bits
.
ReverseBytes32
(
15
),
bits
.
ReverseBytes64
(
15
)},
},
{
name
:
"Len"
,
in
:
8
,
out
:
[
4
]
interface
{}{
bits
.
Len8
(
8
),
bits
.
Len16
(
8
),
bits
.
Len32
(
8
),
bits
.
Len64
(
8
)},
},
}
{
for
i
,
size
:=
range
[]
int
{
8
,
16
,
32
,
64
}
{
if
e
.
out
[
i
]
==
nil
{
continue
// function doesn't exist
}
f
:=
fmt
.
Sprintf
(
"%s%d"
,
e
.
name
,
size
)
fmt
.
Fprintf
(
w
,
"
\n
func Example%s() {
\n
"
,
f
)
switch
e
.
name
{
case
"RotateLeft"
,
"Reverse"
,
"ReverseBytes"
:
fmt
.
Fprintf
(
w
,
"
\t
fmt.Printf(
\"
%%0%db
\\
n
\"
, %d)
\n
"
,
size
,
e
.
in
)
if
e
.
name
==
"RotateLeft"
{
fmt
.
Fprintf
(
w
,
"
\t
fmt.Printf(
\"
%%0%db
\\
n
\"
, bits.%s(%d, 2))
\n
"
,
size
,
f
,
e
.
in
)
fmt
.
Fprintf
(
w
,
"
\t
fmt.Printf(
\"
%%0%db
\\
n
\"
, bits.%s(%d, -2))
\n
"
,
size
,
f
,
e
.
in
)
}
else
{
fmt
.
Fprintf
(
w
,
"
\t
fmt.Printf(
\"
%%0%db
\\
n
\"
, bits.%s(%d))
\n
"
,
size
,
f
,
e
.
in
)
}
fmt
.
Fprintf
(
w
,
"
\t
// Output:
\n
"
)
fmt
.
Fprintf
(
w
,
"
\t
// %0*b
\n
"
,
size
,
e
.
in
)
fmt
.
Fprintf
(
w
,
"
\t
// %0*b
\n
"
,
size
,
e
.
out
[
i
])
if
e
.
name
==
"RotateLeft"
&&
e
.
out2
[
i
]
!=
nil
{
fmt
.
Fprintf
(
w
,
"
\t
// %0*b
\n
"
,
size
,
e
.
out2
[
i
])
}
default
:
fmt
.
Fprintf
(
w
,
"
\t
fmt.Printf(
\"
%s(%%0%db) = %%d
\\
n
\"
, %d, bits.%s(%d))
\n
"
,
f
,
size
,
e
.
in
,
f
,
e
.
in
)
fmt
.
Fprintf
(
w
,
"
\t
// Output:
\n
"
)
fmt
.
Fprintf
(
w
,
"
\t
// %s(%0*b) = %d
\n
"
,
f
,
size
,
e
.
in
,
e
.
out
[
i
])
}
fmt
.
Fprintf
(
w
,
"}
\n
"
)
}
}
if
err
:=
os
.
WriteFile
(
"example_test.go"
,
w
.
Bytes
(),
0666
);
err
!=
nil
{
log
.
Fatal
(
err
)
}
}
waroot/src/runtime/runtime_arduino.wa
浏览文件 @
9f848656
...
...
@@ -2,7 +2,7 @@
import "syscall/arduino"
var
WAOS = "arduino"
const
WAOS = "arduino"
#wa:linkname $runtime.argsSizesGet
func argsSizesGet(result_argc: i32, result_argv_len: i32) => (errno: i32) {
...
...
@@ -70,8 +70,8 @@ func waPrintI64(i: i32) {
}
#wa:linkname $runtime.waPrintU64
func waPrintU64(i:
i32
) {
printU64(
u64(i)
)
func waPrintU64(i:
u64
) {
printU64(
i
)
}
#wa:linkname $runtime.waPrintF32
...
...
waroot/src/runtime/runtime_chrome.wa
浏览文件 @
9f848656
...
...
@@ -2,7 +2,7 @@
import "syscall/chrome"
var
WAOS = "chrome"
const
WAOS = "chrome"
#wa:linkname $runtime.argsSizesGet
func argsSizesGet(result_argc: i32, result_argv_len: i32) => (errno: i32) {
...
...
@@ -70,8 +70,8 @@ func waPrintI64(i: i32) {
}
#wa:linkname $runtime.waPrintU64
func waPrintU64(i:
i32
) {
printU64(
u64(i)
)
func waPrintU64(i:
u64
) {
printU64(
i
)
}
#wa:linkname $runtime.waPrintF32
...
...
waroot/src/runtime/runtime_mvp.wa
浏览文件 @
9f848656
...
...
@@ -2,7 +2,7 @@
import "syscall/mvp"
var
WAOS = "mvp"
const
WAOS = "mvp"
#wa:linkname $runtime.argsSizesGet
func argsSizesGet(result_argc: i32, result_argv_len: i32) => (errno: i32) {
...
...
waroot/src/runtime/runtime_wasi.wa
浏览文件 @
9f848656
...
...
@@ -2,7 +2,7 @@
import "syscall/wasi"
var
WAOS = "wasi"
const
WAOS = "wasi"
#wa:linkname $runtime.argsSizesGet
func argsSizesGet(result_argc: i32, result_argv_len: i32) => (errno: i32) {
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录