├── std ├── syscall │ └── syscall.gos ├── runtime │ └── runtime.gos ├── sync │ ├── atomic │ │ └── value.gos │ ├── pool.gos │ ├── once.gos │ ├── sync.gos │ └── map.gos ├── math │ ├── cmplx │ │ ├── conj.go │ │ ├── rect.go │ │ ├── phase.go │ │ ├── polar.go │ │ ├── abs.go │ │ ├── isinf.go │ │ ├── isnan.go │ │ ├── exp.go │ │ ├── log.go │ │ └── pow.go │ ├── signbit.go │ ├── abs.go │ ├── copysign.go │ ├── log10.go │ ├── hypot.go │ ├── frexp.go │ ├── modf.go │ ├── mod.go │ ├── ldexp.go │ ├── asin.go │ ├── logb.go │ ├── nextafter.go │ ├── pow10.go │ ├── atan2.go │ ├── dim.go │ ├── sinh.go │ ├── acosh.go │ ├── sincos.go │ ├── asinh.go │ ├── bits.go │ ├── rand │ │ └── zipf.go │ ├── atanh.go │ ├── remainder.go │ ├── const.go │ ├── cbrt.go │ ├── tanh.go │ ├── unsafe.go │ └── trig_reduce.go ├── reflect │ ├── deepequal.go │ ├── makefunc.go │ └── swapper.go ├── fmt2 │ └── fmt2.gos ├── unicode │ ├── digit.go │ ├── casetables.go │ └── utf16 │ │ └── utf16.go ├── errors │ └── errors.gos ├── strconv │ ├── atob.go │ └── doc.go ├── strings │ ├── compare.go │ └── builder.go ├── sort │ └── slice.go ├── internal │ └── bytealg │ │ └── bytealg.gos ├── time │ └── tick.go ├── os │ └── file.gos └── io │ └── multi.go ├── parser ├── tests │ ├── common │ │ └── mod.rs │ ├── data │ │ └── case1.gos │ └── parser_test.rs ├── fuzz │ ├── .gitignore │ ├── Cargo.toml │ └── fuzz_targets │ │ └── parse_file.rs ├── .gitignore ├── src │ ├── map.rs │ └── lib.rs └── Cargo.toml ├── types ├── tests │ └── data │ │ ├── math │ │ ├── math.gos │ │ └── math2.gos │ │ ├── temp.gos │ │ ├── issue25008b.src │ │ ├── issue26390.src │ │ ├── importdecl1 │ │ ├── importdecl1b.src │ │ └── importdecl1a.src │ │ ├── issue25008a.src │ │ ├── issue23203a.src │ │ ├── issue23203b.src │ │ ├── decls5.src │ │ ├── importdecl0 │ │ ├── importdecl0a.src │ │ └── importdecl0b.src │ │ ├── cycles3.gos │ │ ├── time │ │ └── time.gos │ │ ├── cycles1.gos │ │ ├── importC.src │ │ ├── issue28251.src │ │ ├── LICENSE │ │ ├── cycles2.gos │ │ ├── init1.src │ │ ├── conversions.gos │ │ ├── errors.src │ │ ├── decls2 │ │ └── decls2b.src │ │ ├── cycles4.gos │ │ └── init0.src ├── src │ ├── check │ │ └── mod.rs │ └── lib.rs └── Cargo.toml ├── engine ├── tests │ ├── std.zip │ ├── group2 │ │ ├── local.gos │ │ ├── somelib │ │ │ └── some_lib.go │ │ ├── case1.gos │ │ ├── case3.gos │ │ ├── display.gos │ │ ├── unicode0.gos │ │ ├── nil.gos │ │ ├── sync_rwmutex.gos │ │ ├── case2.gos │ │ ├── sync_mutex.gos │ │ └── case0.gos │ ├── group1 │ │ ├── closure2.gos │ │ ├── declare.gos │ │ ├── closure1.gos │ │ ├── blankid.gos │ │ ├── closure3.gos │ │ ├── initorder.gos │ │ ├── array.gos │ │ ├── goto.gos │ │ ├── if.gos │ │ ├── init_func.gos │ │ ├── case1.gos │ │ ├── complex.gos │ │ ├── defer.gos │ │ ├── recover.gos │ │ ├── async.gos │ │ ├── closure4.gos │ │ ├── switch.gos │ │ ├── func1.gos │ │ ├── basictypes.gos │ │ ├── channel.gos │ │ ├── interface2.gos │ │ ├── select.gos │ │ ├── type1.gos │ │ ├── map1.gos │ │ ├── typeswitch.gos │ │ ├── composite.gos │ │ ├── pkg.gos │ │ ├── interface1.gos │ │ ├── conversion.gos │ │ ├── pointer.gos │ │ └── slice1.gos │ ├── issues │ │ ├── issue12.gos │ │ ├── issue16.gos │ │ └── issue8.gos │ ├── std │ │ ├── strconv.gos │ │ ├── strings.gos │ │ ├── bytes.gos │ │ ├── math.gos │ │ ├── fmt.gos │ │ ├── temp.gos │ │ ├── time.gos │ │ ├── sort.gos │ │ └── path.gos │ └── demo │ │ ├── fibonacci.gos │ │ ├── linked.gos │ │ └── leetcode5.gos ├── src │ ├── ffi.rs │ ├── std │ │ ├── io.rs │ │ ├── wasm.rs │ │ ├── bits.rs │ │ ├── mod.rs │ │ └── fmt2.rs │ ├── vfs │ │ ├── mod.rs │ │ ├── vfs_fs.rs │ │ ├── vfs_map.rs │ │ └── vfs_zip.rs │ └── lib.rs ├── benches │ └── leet5_benchmark.rs └── Cargo.toml ├── Cargo.toml ├── vm ├── .gitignore ├── Cargo.toml └── src │ └── lib.rs ├── pmacro ├── Cargo.toml └── src │ ├── async_fn.rs │ ├── unsafe_ptr.rs │ ├── lib.rs │ └── ffi.rs ├── .gitignore ├── codegen ├── src │ └── lib.rs └── Cargo.toml └── LICENSE /std/syscall/syscall.gos: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /parser/tests/common/mod.rs: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /parser/fuzz/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | target 3 | corpus 4 | artifacts 5 | -------------------------------------------------------------------------------- /std/runtime/runtime.gos: -------------------------------------------------------------------------------- 1 | package runtime 2 | 3 | var GOOS string -------------------------------------------------------------------------------- /types/tests/data/math/math.gos: -------------------------------------------------------------------------------- 1 | package math 2 | 3 | const Pi = 3.15 4 | -------------------------------------------------------------------------------- /engine/tests/std.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oxfeeefeee/goscript/HEAD/engine/tests/std.zip -------------------------------------------------------------------------------- /engine/tests/group2/local.gos: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import sl "./somelib" 4 | 5 | func main() { 6 | sl.SomeFunc() 7 | } -------------------------------------------------------------------------------- /types/tests/data/math/math2.gos: -------------------------------------------------------------------------------- 1 | package math 2 | 3 | const Pi2 = 6.28 4 | 5 | func Sin(x float64) float64 { 6 | return x 7 | } -------------------------------------------------------------------------------- /engine/tests/group2/somelib/some_lib.go: -------------------------------------------------------------------------------- 1 | package somelib 2 | 3 | import "fmt2" 4 | 5 | func SomeFunc() { 6 | fmt2.Println("someFunc from somelib") 7 | } 8 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | 3 | members = [ 4 | "./parser", 5 | "./types", 6 | "./vm", 7 | "./engine", 8 | "./codegen", 9 | "./pmacro", 10 | ] -------------------------------------------------------------------------------- /types/tests/data/temp.gos: -------------------------------------------------------------------------------- 1 | 2 | package importdecl1 3 | 4 | import _ "./math" 5 | 6 | func a() bool { 7 | return 0 == 1 8 | } 9 | 10 | func fff() { 11 | assert(a()) 12 | } -------------------------------------------------------------------------------- /engine/tests/group1/closure2.gos: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | func main() { 4 | a := 44 5 | b := func() int { 6 | a = 43 7 | return a + 10 8 | }() 9 | c := b + 10 10 | assert(c == 63) 11 | } -------------------------------------------------------------------------------- /engine/tests/group1/declare.gos: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | func main() { 4 | 5 | const i, j int = 1.0, 2 6 | var _,_,c int = 30,40, 50 7 | var l int 8 | k := i + j 9 | k = k + c + l 10 | assert(k == 53) 11 | } 12 | -------------------------------------------------------------------------------- /engine/tests/group1/closure1.gos: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | var a = 43 4 | 5 | func main() { 6 | //i := 0 7 | a := 44 8 | b := func() int { 9 | return a + 10 10 | } 11 | c := b() + 10 12 | assert(c == 64) 13 | } -------------------------------------------------------------------------------- /engine/tests/group2/case1.gos: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt2" 5 | ) 6 | 7 | func a() error { 8 | return nil 9 | } 10 | 11 | func main() { 12 | var v = a() 13 | assert(v == nil) 14 | fmt2.Println("Hello, playground", v) 15 | } 16 | -------------------------------------------------------------------------------- /engine/tests/group1/blankid.gos: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | func a() (int, int, int) { 4 | return 1, 2, 3 5 | } 6 | 7 | func main() { 8 | i, _, _ := a() 9 | _, j, _ := a() 10 | _, _, k := a() 11 | assert(i == 1) 12 | assert(j == 2) 13 | assert(k == 3) 14 | } -------------------------------------------------------------------------------- /engine/tests/group1/closure3.gos: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | func a(v int) func(int) int { 4 | i := 100 5 | i = i + v 6 | return func(j int) int { 7 | return i + j 8 | } 9 | } 10 | 11 | func main() { 12 | b := a(30) 13 | c := b(2) 14 | assert(c == 132) 15 | } -------------------------------------------------------------------------------- /engine/tests/issues/issue12.gos: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt2" 5 | ) 6 | 7 | 8 | 9 | func broken(elems ...int) { 10 | fmt2.Println(elems) 11 | } 12 | 13 | func main() { 14 | broken() 15 | 16 | broken(1) 17 | 18 | broken(2,3) 19 | } -------------------------------------------------------------------------------- /engine/tests/std/strconv.gos: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "strconv" 5 | "fmt2" 6 | ) 7 | 8 | 9 | func main() { 10 | r, err := strconv.ParseFloat("1.000000000000000111022302462515654042363166809082031251", 64) 11 | fmt2.Println(r, err) 12 | } -------------------------------------------------------------------------------- /engine/src/ffi.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Goscript Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | pub use go_pmacro::*; 6 | pub use go_vm::types::*; 7 | pub use go_vm::*; 8 | -------------------------------------------------------------------------------- /types/tests/data/issue25008b.src: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package p 6 | 7 | type B interface { 8 | A 9 | } 10 | -------------------------------------------------------------------------------- /parser/tests/data/case1.gos: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | //var i = a.b[1] 4 | 5 | var i = a + b 6 | 7 | /* 8 | func a(i int) int { 9 | fff := 4 10 | if fff < 3 { 11 | fff += 1 12 | } 13 | return fff 14 | } 15 | 16 | func init() { 17 | a(1) 18 | } 19 | */ -------------------------------------------------------------------------------- /engine/tests/group1/initorder.gos: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | 4 | //import "math" 5 | 6 | 7 | 8 | const k = i + 1 9 | 10 | const i = 7 11 | 12 | var b = a + k 13 | var a = 8 14 | 15 | 16 | 17 | func main() { 18 | //var pi = math.Pi 19 | //_ = pi 20 | //var i = 1 21 | assert(b == 16) 22 | } -------------------------------------------------------------------------------- /std/sync/atomic/value.gos: -------------------------------------------------------------------------------- 1 | package atomic 2 | 3 | // Load and Store are innately atomic in Goscript 4 | type Value struct { 5 | val interface{} 6 | } 7 | 8 | func (v *Value) Load() interface{} { 9 | return v.val 10 | } 11 | 12 | func (v *Value) Store(val interface{}) { 13 | v.val = val 14 | } 15 | -------------------------------------------------------------------------------- /types/tests/data/issue26390.src: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package issue26390 6 | 7 | type A = T 8 | 9 | func (t *T) m() *A { return t } 10 | 11 | type T struct{} 12 | -------------------------------------------------------------------------------- /engine/tests/group1/array.gos: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | //import "fmt2" 4 | 5 | 6 | type Node struct{ 7 | i int 8 | j string 9 | } 10 | 11 | func ttt() { 12 | 13 | 14 | var c [3]Node 15 | assert(c[2].i == 0) 16 | 17 | } 18 | 19 | func main() { 20 | //ttt() 21 | ttt() 22 | 23 | //testb() 24 | } -------------------------------------------------------------------------------- /std/math/cmplx/conj.go: -------------------------------------------------------------------------------- 1 | // Copyright 2010 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package cmplx 6 | 7 | // Conj returns the complex conjugate of x. 8 | func Conj(x complex128) complex128 { return complex(real(x), -imag(x)) } 9 | -------------------------------------------------------------------------------- /engine/tests/std/strings.gos: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt2" 5 | "strings" 6 | ) 7 | 8 | func main() { 9 | 10 | var b strings.Builder 11 | b.WriteString("3.......") 12 | b.WriteString("2.......") 13 | b.WriteString("1.......") 14 | b.WriteString("ignition") 15 | fmt2.Println("xxxx", b.String()) 16 | 17 | } 18 | -------------------------------------------------------------------------------- /std/reflect/deepequal.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Deep equality test via reflection 6 | 7 | package reflect 8 | 9 | func DeepEqual(x, y interface{}) bool { 10 | panic("not implemented") 11 | } 12 | -------------------------------------------------------------------------------- /types/tests/data/importdecl1/importdecl1b.src: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package importdecl1 6 | 7 | import . /* ERROR "imported but not used" */ "unsafe" 8 | 9 | type B interface { 10 | A 11 | } 12 | -------------------------------------------------------------------------------- /types/tests/data/issue25008a.src: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package p 6 | 7 | import "io" 8 | 9 | type A interface { 10 | io.Reader 11 | } 12 | 13 | func f(a A) { 14 | a.Read(nil) 15 | } 16 | -------------------------------------------------------------------------------- /std/math/signbit.go: -------------------------------------------------------------------------------- 1 | // Copyright 2010 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package math 6 | 7 | // Signbit reports whether x is negative or negative zero. 8 | func Signbit(x float64) bool { 9 | return Float64bits(x)&(1<<63) != 0 10 | } 11 | -------------------------------------------------------------------------------- /vm/.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | /target/ 4 | 5 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 6 | # More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock 7 | Cargo.lock 8 | 9 | # These are backup files generated by rustfmt 10 | **/*.rs.bk 11 | -------------------------------------------------------------------------------- /parser/.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | /target/ 4 | 5 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 6 | # More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock 7 | Cargo.lock 8 | 9 | # These are backup files generated by rustfmt 10 | **/*.rs.bk 11 | -------------------------------------------------------------------------------- /engine/tests/issues/issue16.gos: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt2" 4 | 5 | func get_input() interface{} { 6 | return map[string]interface{}{ 7 | "left": 2, 8 | "right": 3, 9 | } 10 | } 11 | 12 | func main() { 13 | m := get_input() 14 | fmt2.Println(m) 15 | data, ok := m.(map[string]interface{}) 16 | assert(ok) 17 | fmt2.Println(ok, data) 18 | } 19 | -------------------------------------------------------------------------------- /std/reflect/makefunc.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // MakeFunc implementation. 6 | 7 | package reflect 8 | 9 | func MakeFunc(typ Type, fn func(args []Value) (results []Value)) Value { 10 | panic("not implemented") 11 | } 12 | -------------------------------------------------------------------------------- /engine/src/std/io.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Goscript Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | extern crate self as go_engine; 6 | use crate::ffi::*; 7 | use go_vm::types::GosValue; 8 | 9 | #[derive(Ffi)] 10 | pub struct IoFfi; 11 | 12 | #[ffi_impl] 13 | impl IoFfi {} 14 | -------------------------------------------------------------------------------- /engine/tests/std/bytes.gos: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt2" 5 | "bytes" 6 | ) 7 | 8 | func main() { 9 | var s string = "Hello World" 10 | sb := []byte(s) 11 | 12 | fmt2.Println(bytes.Index(sb, []byte{111,114})) 13 | 14 | fmt2.Println(sb) // [72 101 108 108 111 32 87 111 114 108 100] 15 | 16 | fmt2.Println(string(sb)) // Hello World 17 | } -------------------------------------------------------------------------------- /engine/tests/std/math.gos: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "math" 5 | "fmt2" 6 | ) 7 | 8 | const k = i + 1 9 | 10 | const i = 7 11 | 12 | var b = a + k 13 | var a = 8 14 | 15 | 16 | func main() { 17 | p := math.Pi 18 | 19 | fmt2.Println(p, math.Log10(1000), math.Sin(p), math.Sin(p/2), math.Sin(1)) 20 | 21 | fmt2.Println(math.Pow(3,20.2), math.Pow(3,-20.2)) 22 | } -------------------------------------------------------------------------------- /std/fmt2/fmt2.gos: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Goscript Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package fmt2 6 | 7 | type ffiFmt2 interface { 8 | println(a ...interface{}) 9 | } 10 | 11 | func Println(a ...interface{}) { 12 | var f = ffi(ffiFmt2, "fmt2") 13 | f.println(a...) 14 | } -------------------------------------------------------------------------------- /types/tests/data/issue23203a.src: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package main 6 | 7 | import "unsafe" 8 | 9 | type T struct{} 10 | 11 | func (T) m1() {} 12 | func (T) m2([unsafe.Sizeof(T.m1)]int) {} 13 | 14 | func main() {} 15 | -------------------------------------------------------------------------------- /types/tests/data/issue23203b.src: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package main 6 | 7 | import "unsafe" 8 | 9 | type T struct{} 10 | 11 | func (T) m2([unsafe.Sizeof(T.m1)]int) {} 12 | func (T) m1() {} 13 | 14 | func main() {} 15 | -------------------------------------------------------------------------------- /engine/src/std/wasm.rs: -------------------------------------------------------------------------------- 1 | use wasm_bindgen::prelude::*; 2 | 3 | #[wasm_bindgen] 4 | extern "C" { 5 | // Use `js_namespace` here to bind `console.log(..)` instead of just 6 | // `log(..)` 7 | #[wasm_bindgen(js_namespace = console)] 8 | fn log(s: &str); 9 | } 10 | 11 | /// Logs a message to the console via wasm_bindgen. 12 | pub(crate) fn console_log(s: &str) { 13 | log(s); 14 | } 15 | -------------------------------------------------------------------------------- /engine/tests/std/fmt.gos: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "fmt2" 6 | ) 7 | 8 | func main() { 9 | fmt.Printf("%d %d %#[1]x %#x \n", 16, 17) 10 | const name, age = "Kim", 22 11 | s := fmt.Sprintf("%d/%d", 16, 1,1) 12 | fmt2.Println(s) 13 | fmt2.Println(name, "is", age, "years old.") 14 | fmt.Println(name, "is", age, "years old.") 15 | 16 | 17 | 18 | 19 | } -------------------------------------------------------------------------------- /pmacro/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "go-pmacro" 3 | version = "0.1.5" 4 | edition = "2021" 5 | license = "BSD-2-Clause " 6 | repository = "https://github.com/oxfeeefeee/goscript/" 7 | description = "Provides some proc-macros for the goscript project" 8 | 9 | [dependencies] 10 | proc-macro2 = "1.0" 11 | quote = "1.0" 12 | syn = { version = "1.0", features = ["full"] } 13 | 14 | [lib] 15 | proc-macro = true -------------------------------------------------------------------------------- /engine/tests/group2/case3.gos: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt2" 5 | ) 6 | 7 | 8 | 9 | func main() { 10 | var v = new(int) 11 | var vv = 2 12 | *v = 8 13 | var vvv = *v 14 | var s = []int{1,2,3} 15 | var s1 = s[0] 16 | var s3 = s[2] 17 | 18 | var sa = &A{} 19 | 20 | fmt2.Println("Hello, playground", v, vv, vvv, s, s1, s3, sa) 21 | } 22 | 23 | type A []int 24 | 25 | -------------------------------------------------------------------------------- /std/math/cmplx/rect.go: -------------------------------------------------------------------------------- 1 | // Copyright 2010 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package cmplx 6 | 7 | import "math" 8 | 9 | // Rect returns the complex number x with polar coordinates r, θ. 10 | func Rect(r, θ float64) complex128 { 11 | s, c := math.Sincos(θ) 12 | return complex(r*c, r*s) 13 | } 14 | -------------------------------------------------------------------------------- /std/unicode/digit.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package unicode 6 | 7 | // IsDigit reports whether the rune is a decimal digit. 8 | func IsDigit(r rune) bool { 9 | if r <= MaxLatin1 { 10 | return '0' <= r && r <= '9' 11 | } 12 | return isExcludingLatin(Digit, r) 13 | } 14 | -------------------------------------------------------------------------------- /engine/tests/group1/goto.gos: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt2" 4 | 5 | func main() { 6 | var a int = 0 7 | total := 0 8 | skip := 6 9 | 10 | LOOP: for a < 10 { 11 | if a == skip { 12 | a = a + 1 13 | goto LOOP 14 | } 15 | total += a 16 | fmt2.Println("value of a: ", a) 17 | a++ 18 | } 19 | 20 | fmt2.Println(total) 21 | assert(total == 45 - skip) 22 | } -------------------------------------------------------------------------------- /types/tests/data/decls5.src: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package main 6 | 7 | // declarations of main 8 | const _, main /* ERROR "cannot declare main" */ , _ = 0, 1, 2 9 | type main /* ERROR "cannot declare main" */ struct{} 10 | var _, main /* ERROR "cannot declare main" */ int 11 | -------------------------------------------------------------------------------- /std/math/abs.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package math 6 | 7 | // Abs returns the absolute value of x. 8 | // 9 | // Special cases are: 10 | // Abs(±Inf) = +Inf 11 | // Abs(NaN) = NaN 12 | func Abs(x float64) float64 { 13 | return Float64frombits(Float64bits(x) &^ (1 << 63)) 14 | } 15 | -------------------------------------------------------------------------------- /parser/src/map.rs: -------------------------------------------------------------------------------- 1 | #[cfg(feature = "btree_map")] 2 | pub type Map = std::collections::BTreeMap; 3 | #[cfg(not(feature = "btree_map"))] 4 | pub type Map = std::collections::HashMap; 5 | 6 | #[cfg(feature = "btree_map")] 7 | pub type MapIter<'a, K, V> = std::collections::btree_map::Iter<'a, K, V>; 8 | #[cfg(not(feature = "btree_map"))] 9 | pub type MapIter<'a, K, V> = std::collections::hash_map::Iter<'a, K, V>; 10 | -------------------------------------------------------------------------------- /std/math/cmplx/phase.go: -------------------------------------------------------------------------------- 1 | // Copyright 2010 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package cmplx 6 | 7 | import "math" 8 | 9 | // Phase returns the phase (also called the argument) of x. 10 | // The returned value is in the range [-Pi, Pi]. 11 | func Phase(x complex128) float64 { return math.Atan2(imag(x), real(x)) } 12 | -------------------------------------------------------------------------------- /std/math/cmplx/polar.go: -------------------------------------------------------------------------------- 1 | // Copyright 2010 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package cmplx 6 | 7 | // Polar returns the absolute value r and phase θ of x, 8 | // such that x = r * e**θi. 9 | // The phase is in the range [-Pi, Pi]. 10 | func Polar(x complex128) (r, θ float64) { 11 | return Abs(x), Phase(x) 12 | } 13 | -------------------------------------------------------------------------------- /engine/tests/group1/if.gos: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | func f(i int) int { 4 | var j int 5 | if k := 666; i == 0 { 6 | j = 888 7 | } else if i == 1 { 8 | j = 1 9 | } else if i == 2 { 10 | j = k 11 | } else { 12 | j = k + 4 13 | } 14 | return j 15 | } 16 | 17 | func main() { 18 | assert(f(0) == 888) 19 | assert(f(1) == 1) 20 | assert(f(2) == 666) 21 | assert(f(3) == 670) 22 | } -------------------------------------------------------------------------------- /std/math/copysign.go: -------------------------------------------------------------------------------- 1 | // Copyright 2010 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package math 6 | 7 | // Copysign returns a value with the magnitude 8 | // of x and the sign of y. 9 | func Copysign(x, y float64) float64 { 10 | const sign = 1 << 63 11 | return Float64frombits(Float64bits(x)&^sign | Float64bits(y)&sign) 12 | } 13 | -------------------------------------------------------------------------------- /engine/tests/group1/init_func.gos: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | 4 | import ( 5 | "fmt2" 6 | ) 7 | 8 | var i = 10 9 | 10 | func init() { 11 | i++ 12 | assert(i == 11) 13 | } 14 | 15 | 16 | func init() { 17 | i++ 18 | assert(i == 12) 19 | } 20 | 21 | func init() { 22 | i++ 23 | assert(i == 13) 24 | } 25 | 26 | 27 | 28 | func main() { 29 | m := []byte{1,3} 30 | n := []byte{2,4} 31 | t := append(m, n...) 32 | fmt2.Println(t, m, n, i) 33 | 34 | } -------------------------------------------------------------------------------- /std/math/cmplx/abs.go: -------------------------------------------------------------------------------- 1 | // Copyright 2010 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package cmplx provides basic constants and mathematical functions for 6 | // complex numbers. 7 | package cmplx 8 | 9 | import "math" 10 | 11 | // Abs returns the absolute value (also called the modulus) of x. 12 | func Abs(x complex128) float64 { return math.Hypot(real(x), imag(x)) } 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | /target/ 4 | 5 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 6 | # More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock 7 | Cargo.lock 8 | 9 | # These are backup files generated by rustfmt 10 | **/*.rs.bk 11 | 12 | .DS_Store 13 | *.code-workspace 14 | 15 | backend/.vscode/ 16 | 17 | backup/ 18 | 19 | .VSCodeCounter/ 20 | .vscode/settings.json 21 | -------------------------------------------------------------------------------- /engine/tests/demo/fibonacci.gos: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt2" 4 | 5 | func fibonacci(c, quit chan int) { 6 | x, y := 0, 1 7 | for { 8 | select { 9 | case c <- x: 10 | x, y = y, x+y 11 | case <-quit: 12 | fmt2.Println("quit 拉") 13 | return 14 | } 15 | } 16 | } 17 | 18 | func main() { 19 | c := make(chan int) 20 | quit := make(chan int) 21 | go func() { 22 | for i := 0; i < 12; i++ { 23 | fmt2.Println(<-c) 24 | } 25 | quit <- 0 26 | }() 27 | 28 | fibonacci(c, quit) 29 | } -------------------------------------------------------------------------------- /engine/tests/group1/case1.gos: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | 4 | import "fmt2" 5 | import "unsafe" 6 | 7 | 8 | 9 | type geometry interface { 10 | area() int 11 | perim() int 12 | } 13 | 14 | func a() []int { 15 | a1 := []int{3} 16 | a2 := a1[1:] 17 | return a2 18 | } 19 | 20 | 21 | 22 | func main() { 23 | 24 | //var n = ffi(geometry, "test", 1, 2, 3, "haha", 5) 25 | //var i = n.area() 26 | //assert(i == 666) 27 | var p unsafe.Pointer 28 | fmt2.Println(p, 666) 29 | 30 | } -------------------------------------------------------------------------------- /std/reflect/swapper.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package reflect 6 | 7 | // Swapper returns a function that swaps the elements in the provided 8 | // slice. 9 | // 10 | // Swapper panics if the provided interface is not a slice. 11 | func Swapper(slice interface{}) func(i, j int) { 12 | return func(i, j int) { 13 | native.swap(slice, i, j) 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /engine/tests/std/temp.gos: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt2" 4 | 5 | func shuffle(nums []int, n int) []int { 6 | for i := 0; i < n; i++ { 7 | nums[i*2] = (nums[i]&1023)<<10 | nums[i*2] 8 | } 9 | for j := n; j < len(nums); j++ { 10 | nums[2*(j-n)+1] = (nums[j]&1023)<<10 | nums[2*(j-n)+1] 11 | } 12 | 13 | for i, _ := range nums { 14 | nums[i] = nums[i] >> 10 15 | } 16 | return nums 17 | } 18 | 19 | func main() { 20 | var nums = []int{2, 5, 1, 3, 4, 7} 21 | var n = 3 22 | fmt2.Println(shuffle(nums, n)) 23 | } -------------------------------------------------------------------------------- /engine/tests/group2/display.gos: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt2" 5 | ) 6 | 7 | type III interface{} 8 | 9 | 10 | type A struct { 11 | i int 12 | j int 13 | } 14 | 15 | type B string 16 | 17 | func main() { 18 | i := 0 19 | var stru A 20 | var sli = []int{1,2,3} 21 | var m = map[A]interface{}{{1,2}:333, {1,3}:"fff", {2,2}:nil} 22 | m[A{1,3}] = "hahaxx" 23 | var b B 24 | b = "xxxx" 25 | var iii III 26 | iii = b 27 | fmt2.Println(&i, stru, &stru, b, &b, sli, &sli, m, &m, m[A{1,3}], iii) 28 | } -------------------------------------------------------------------------------- /parser/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "go-parser" 3 | version = "0.1.5" 4 | authors = ["oxfeeefeee "] 5 | edition = "2021" 6 | license = "BSD-3-Clause" 7 | repository = "https://github.com/oxfeeefeee/goscript/" 8 | keywords = ["golang", "parser", "goscript"] 9 | categories = ["compiler", "parser"] 10 | description = "The parser of the Goscript project." 11 | 12 | [features] 13 | default = [] 14 | btree_map = [] 15 | serde_borsh = ["dep:borsh"] 16 | 17 | [dependencies] 18 | borsh = { version ="0.10.3", optional = true } -------------------------------------------------------------------------------- /engine/tests/group1/complex.gos: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt2" 4 | 5 | func main() { 6 | c := complex(1,2) 7 | assert(real(c) == 1) 8 | assert(imag(c) == 2) 9 | fmt2.Println(c) 10 | 11 | 12 | var f float64 13 | f = 1.2345699999 14 | c2 := complex(8, f) 15 | 16 | var iface interface{} 17 | iface = real(c2) 18 | switch i := iface.(type) { 19 | case float32: 20 | j := 0 21 | assert(j == 1) 22 | case float64: 23 | assert(i == 8) 24 | fmt2.Println("float64", i) 25 | } 26 | } -------------------------------------------------------------------------------- /parser/fuzz/Cargo.toml: -------------------------------------------------------------------------------- 1 | 2 | [package] 3 | name = "go-parser-fuzz" 4 | version = "0.0.0" 5 | authors = ["Automatically generated"] 6 | publish = false 7 | edition = "2018" 8 | 9 | [package.metadata] 10 | cargo-fuzz = true 11 | 12 | [dependencies] 13 | libfuzzer-sys = "0.4" 14 | arbitrary = { version = "1.0", features = ["derive"] } 15 | 16 | [dependencies.go-parser] 17 | path = ".." 18 | 19 | # Prevent this from interfering with workspaces 20 | [workspace] 21 | members = ["."] 22 | 23 | [[bin]] 24 | name = "parse_file" 25 | path = "fuzz_targets/parse_file.rs" 26 | test = false 27 | doc = false 28 | -------------------------------------------------------------------------------- /std/math/cmplx/isinf.go: -------------------------------------------------------------------------------- 1 | // Copyright 2010 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package cmplx 6 | 7 | import "math" 8 | 9 | // IsInf reports whether either real(x) or imag(x) is an infinity. 10 | func IsInf(x complex128) bool { 11 | if math.IsInf(real(x), 0) || math.IsInf(imag(x), 0) { 12 | return true 13 | } 14 | return false 15 | } 16 | 17 | // Inf returns a complex infinity, complex(+Inf, +Inf). 18 | func Inf() complex128 { 19 | inf := math.Inf(1) 20 | return complex(inf, inf) 21 | } 22 | -------------------------------------------------------------------------------- /std/errors/errors.gos: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Goscript Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package errors 6 | 7 | // New returns an error that formats as the given text. 8 | // Each call to New returns a distinct error value even if the text is identical. 9 | func New(text string) error { 10 | return &errorString{text} 11 | } 12 | 13 | // errorString is a trivial implementation of error. 14 | type errorString struct { 15 | s string 16 | } 17 | 18 | func (e *errorString) Error() string { 19 | return e.s 20 | } -------------------------------------------------------------------------------- /types/src/check/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Goscript Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | #[macro_use] 6 | mod util; 7 | mod assignment; 8 | mod builtin; 9 | mod call; 10 | mod check; 11 | mod conversion; 12 | mod decl; 13 | mod expr; 14 | mod initorder; 15 | mod interface; 16 | mod label; 17 | mod resolver; 18 | mod returns; 19 | mod stmt; 20 | mod typexpr; 21 | 22 | pub(crate) use check::FilesContext; 23 | pub use check::{Checker, TypeInfo}; 24 | pub use interface::{IfaceInfo, MethodInfo}; 25 | pub use resolver::*; 26 | -------------------------------------------------------------------------------- /types/tests/data/importdecl1/importdecl1a.src: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Test case for issue 8969. 6 | 7 | package importdecl1 8 | 9 | import "../time" 10 | import . "unsafe" 11 | 12 | var _ Pointer // use dot-imported package unsafe 13 | 14 | // Test cases for issue 23914. 15 | 16 | type A interface { 17 | // Methods m1, m2 must be type-checked in this file scope 18 | // even when embedded in an interface in a different 19 | // file of the same package. 20 | m1() time.Time 21 | m2() Pointer 22 | } 23 | -------------------------------------------------------------------------------- /engine/tests/group2/unicode0.gos: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt2" 5 | "unicode/utf8" 6 | ) 7 | 8 | func ExampleDecodeLastRune() { 9 | b := []byte("Hello, 世界") 10 | utf8.DecodeLastRune(b) 11 | 12 | 13 | for len(b) > 0 { 14 | r, size := utf8.DecodeLastRune(b) 15 | fmt2.Println("%c %v\n", r, size) 16 | 17 | b = b[:len(b)-size] 18 | } 19 | 20 | // Output: 21 | // 界 3 22 | // 世 3 23 | // 1 24 | // , 1 25 | // o 1 26 | // l 1 27 | // l 1 28 | // e 1 29 | // H 1 30 | } 31 | 32 | 33 | func main() { 34 | ExampleDecodeLastRune() 35 | fmt2.Println(utf8.RuneError, "a \n b👌") 36 | s := "\\ \n \\" 37 | fmt2.Println(s[0], len(s), s) 38 | } -------------------------------------------------------------------------------- /codegen/src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Goscript Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | //! This crate is part of the Goscript project. Please refer to for more information. 6 | //! 7 | //! # Feature 8 | //! - `async`: Channel and goroutine support 9 | //! - `btree_map`: Make it use BTreeMap instead of HashMap 10 | 11 | mod branch; 12 | mod consts; 13 | mod context; 14 | //mod emit; 15 | mod package; 16 | //mod selector; 17 | mod codegen; 18 | mod entry; 19 | mod types; 20 | 21 | pub use entry::parse_check_gen; 22 | pub use go_types::{SourceRead, TraceConfig}; 23 | -------------------------------------------------------------------------------- /engine/tests/group1/defer.gos: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | 4 | import ( 5 | "fmt2" 6 | ) 7 | 8 | type Mutex struct { 9 | i int 10 | } 11 | 12 | 13 | func (m *Mutex) Lock() { 14 | m.i += 85 15 | assert(m.i == 85) 16 | } 17 | 18 | 19 | 20 | func test2() { 21 | var m Mutex 22 | 23 | defer m.Lock() 24 | } 25 | 26 | 27 | func f() (result int) { 28 | defer func() { 29 | // result is accessed after it was set to 6 by the return statement 30 | result *= 7 31 | }() 32 | return 6 33 | } 34 | 35 | func main() { 36 | assert(f() == 42) 37 | fmt2.Println(f()) 38 | 39 | for i := 0; i <= 3; i++ { 40 | defer fmt2.Println(i) 41 | } 42 | 43 | test2() 44 | } 45 | 46 | 47 | -------------------------------------------------------------------------------- /types/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "go-types" 3 | version = "0.1.5" 4 | authors = ["oxfeeefeee "] 5 | edition = "2021" 6 | license = "BSD-3-Clause" 7 | repository = "https://github.com/oxfeeefeee/goscript/" 8 | keywords = ["golang", "type-checker", "goscript"] 9 | categories = ["compiler", "type-checker"] 10 | description = "The type checker of the Goscript project." 11 | 12 | [features] 13 | default = [] 14 | btree_map = ["go-parser/btree_map"] 15 | 16 | [dependencies] 17 | num-bigint = "0.4" 18 | num-rational = "0.4" 19 | num-traits = "0.2" 20 | ordered-float = "3.0" 21 | 22 | go-parser = { version = "0.1.5", path = "../parser" } 23 | 24 | [dev-dependencies] 25 | regex = "1" 26 | 27 | -------------------------------------------------------------------------------- /engine/tests/group1/recover.gos: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | 4 | import "fmt2" 5 | 6 | func main() { 7 | f() 8 | fmt2.Println("Returned normally from f.") 9 | } 10 | 11 | func f() { 12 | defer func() { 13 | if r := recover(); r != nil { 14 | fmt2.Println("Recovered in f", r) 15 | } 16 | }() 17 | 18 | //panic("aaaaa") 19 | fmt2.Println("Calling g.") 20 | g(0) 21 | fmt2.Println("Returned normally from g.") 22 | } 23 | 24 | 25 | func g(i int) { 26 | if i > 3 { 27 | fmt2.Println("Panicking!") 28 | panic("xxxxx") 29 | } 30 | 31 | defer fmt2.Println("Defer in g", i) 32 | fmt2.Println("Printing in g", i) 33 | g(i + 1) 34 | } 35 | 36 | -------------------------------------------------------------------------------- /std/math/cmplx/isnan.go: -------------------------------------------------------------------------------- 1 | // Copyright 2010 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package cmplx 6 | 7 | import "math" 8 | 9 | // IsNaN reports whether either real(x) or imag(x) is NaN 10 | // and neither is an infinity. 11 | func IsNaN(x complex128) bool { 12 | switch { 13 | case math.IsInf(real(x), 0) || math.IsInf(imag(x), 0): 14 | return false 15 | case math.IsNaN(real(x)) || math.IsNaN(imag(x)): 16 | return true 17 | } 18 | return false 19 | } 20 | 21 | // NaN returns a complex ``not-a-number'' value. 22 | func NaN() complex128 { 23 | nan := math.NaN() 24 | return complex(nan, nan) 25 | } 26 | -------------------------------------------------------------------------------- /engine/tests/group1/async.gos: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt2" 5 | ) 6 | 7 | func add(a int, b int, c int) { 8 | assert(a + b == c) 9 | fmt2.Println(a, "+", b, "=", c) 10 | } 11 | 12 | func main() { 13 | go fmt2.Println("hello world?") 14 | i := 1 15 | j := 2 16 | n := 888 17 | go add(i, j, 3) 18 | 19 | go func() { 20 | n = 666 21 | assert(n == 666) 22 | fmt2.Println("----- n = ", n); 23 | }() 24 | 25 | assert(n == 888) 26 | fmt2.Println("before waiting... n = ", n); 27 | for i := 1; i <= 10000; i++ { 28 | } 29 | assert(n == 666) 30 | fmt2.Println("after waiting... n = ", n); 31 | 32 | k := i + j 33 | assert(k == 3) 34 | } -------------------------------------------------------------------------------- /pmacro/src/async_fn.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Goscript Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | use proc_macro2::Span; 6 | use proc_macro2::TokenStream; 7 | use quote::ToTokens; 8 | use syn::{ItemFn, Token}; 9 | 10 | pub fn async_fn_implement(input: proc_macro::TokenStream) -> proc_macro::TokenStream { 11 | let input: TokenStream = input.into(); 12 | let mut func = syn::parse2::(input.clone()).expect("async only applies to a function"); 13 | func.sig.asyncness = Some(Token![async](Span::call_site())); 14 | let mut output = TokenStream::new(); 15 | func.to_tokens(&mut output); 16 | output.into() 17 | } 18 | -------------------------------------------------------------------------------- /engine/tests/group1/closure4.gos: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | func tt() { 4 | a := 44 5 | b := func() func() int { 6 | c := 3 7 | return func()int { 8 | d := 2 9 | return a + 1 + c + d 10 | } 11 | } 12 | e := func() int { 13 | c := b()() + 10 14 | return c + a 15 | } 16 | f := e() 17 | assert(f == 104) 18 | } 19 | 20 | 21 | func main() { 22 | tt() 23 | 24 | a := 44 25 | b := func() func() int { 26 | c := 3 27 | return func()int { 28 | d := 2 29 | return a + 1 + c + d 30 | } 31 | } 32 | e := func() int { 33 | c := b()() + 10 34 | return c + a 35 | } 36 | f := e() 37 | assert(f == 104) 38 | } 39 | -------------------------------------------------------------------------------- /parser/fuzz/fuzz_targets/parse_file.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Goscript Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | #![no_main] 6 | use arbitrary::Arbitrary; 7 | use go_parser::errors::ErrorList; 8 | use go_parser::objects::Objects; 9 | use go_parser::{parse_file, FileSet}; 10 | use libfuzzer_sys::fuzz_target; 11 | 12 | #[derive(Arbitrary, Debug)] 13 | struct Input { 14 | src: String, 15 | trace: bool, 16 | } 17 | 18 | fuzz_target!(|input: Input| { 19 | let mut fs = FileSet::new(); 20 | let o = &mut Objects::new(); 21 | let el = &mut ErrorList::new(); 22 | let _ = parse_file(o, &mut fs, el, "/a", &input.src, input.trace); 23 | }); 24 | -------------------------------------------------------------------------------- /codegen/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "go-codegen" 3 | version = "0.1.5" 4 | authors = ["oxfeeefeee "] 5 | edition = "2021" 6 | license = "BSD-2-Clause" 7 | repository = "https://github.com/oxfeeefeee/goscript/" 8 | keywords = ["golang", "goscript", "codegen"] 9 | categories = ["scripting language", "programming language", "compiler"] 10 | description = "The codegen of the Goscript project." 11 | 12 | 13 | [features] 14 | default = [] 15 | async = ["go-vm/async"] 16 | btree_map = ["go-parser/btree_map"] 17 | 18 | [dependencies] 19 | go-parser = { version = "0.1.5", path = "../parser" } 20 | go-vm = { version = "0.1.5", path = "../vm" } 21 | go-types = { version = "0.1.5", path = "../types" } 22 | 23 | [dev-dependencies] 24 | time-test = "0.2.2" -------------------------------------------------------------------------------- /std/math/log10.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package math 6 | 7 | // Log10 returns the decimal logarithm of x. 8 | // The special cases are the same as for Log. 9 | func Log10(x float64) float64 { 10 | return Log(x) * (1 / Ln10) 11 | } 12 | 13 | // Log2 returns the binary logarithm of x. 14 | // The special cases are the same as for Log. 15 | func Log2(x float64) float64 { 16 | frac, exp := Frexp(x) 17 | // Make sure exact powers of two give an exact answer. 18 | // Don't depend on Log(0.5)*(1/Ln2)+exp being exactly exp-1. 19 | if frac == 0.5 { 20 | return float64(exp - 1) 21 | } 22 | return Log(frac)*(1/Ln2) + float64(exp) 23 | } 24 | -------------------------------------------------------------------------------- /engine/tests/group1/switch.gos: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | 4 | func test(v int) int { 5 | var a = 0 6 | switch v { 7 | default: 8 | a = 4 9 | case 100: 10 | a += 1 11 | case 200: 12 | a += 2 13 | } 14 | return a 15 | } 16 | 17 | func test2(v int) int { 18 | var a = 0 19 | switch v += 1; v { 20 | case 100, 101, 102: 21 | a += 1 22 | fallthrough 23 | case 200: 24 | a += 2 25 | default: 26 | a = 4 27 | } 28 | return a 29 | } 30 | 31 | func main() { 32 | assert(test(100) == 1) 33 | assert(test(200) == 2) 34 | assert(test(201) == 4) 35 | assert(test2(99) == 3) 36 | assert(test2(100) == 3) 37 | assert(test2(101) == 3) 38 | assert(test2(199) == 2) 39 | assert(test2(201) == 4) 40 | } -------------------------------------------------------------------------------- /engine/tests/group2/nil.gos: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt2" 5 | ) 6 | 7 | type III interface{} 8 | 9 | 10 | type A struct { 11 | i int 12 | } 13 | 14 | func main() { 15 | //var m []string 16 | 17 | var ia interface{} 18 | ia = 8 19 | 20 | var ib III 21 | ib = 9 22 | 23 | ib = ia 24 | 25 | var a A 26 | var b struct { 27 | i int 28 | } 29 | b.i = 99 30 | 31 | a = b 32 | b.i = 55 33 | 34 | fmt2.Println("Hello, playground", ia, ia == nil, ib, ib == nil, 10, a.i, b.i) 35 | 36 | c := &a 37 | d := &b 38 | c.i = 111 39 | d.i = 222 40 | fmt2.Println(a.i, b.i) 41 | *c = b 42 | fmt2.Println(a.i, b.i) 43 | 44 | var e *int 45 | fmt2.Println(e) 46 | i := 666 47 | e = &i 48 | fmt2.Println(e, *e) 49 | } 50 | -------------------------------------------------------------------------------- /engine/src/std/bits.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Goscript Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | extern crate self as go_engine; 6 | use crate::ffi::*; 7 | use go_vm::types::*; 8 | 9 | #[derive(Ffi)] 10 | pub struct BitsFfi; 11 | 12 | #[ffi_impl] 13 | impl BitsFfi { 14 | fn ffi_f32_to_bits(f: f32) -> u32 { 15 | u32::from_be_bytes(f.to_be_bytes()) 16 | } 17 | 18 | fn ffi_f32_from_bits(u: u32) -> f32 { 19 | f32::from_be_bytes(u.to_be_bytes()) 20 | } 21 | 22 | fn ffi_f64_to_bits(f: f64) -> u64 { 23 | u64::from_be_bytes(f.to_be_bytes()) 24 | } 25 | 26 | fn ffi_f64_from_bits(u: u64) -> f64 { 27 | f64::from_be_bytes(u.to_be_bytes()) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /std/sync/pool.gos: -------------------------------------------------------------------------------- 1 | package sync 2 | 3 | type Pool struct { 4 | shared []interface{} 5 | lock RWMutex 6 | // New optionally specifies a function to generate 7 | // a value when Get would otherwise return nil. 8 | // It may not be changed concurrently with calls to Get. 9 | New func() interface{} 10 | } 11 | 12 | func (p *Pool) Put(x interface{}) { 13 | p.lock.Lock() 14 | p.shared = append(p.shared, x) 15 | p.lock.Unlock() 16 | } 17 | 18 | 19 | func (p *Pool) Get() interface{} { 20 | p.lock.RLock() 21 | defer p.lock.RUnlock() 22 | l := len(p.shared) 23 | var x interface{} 24 | if l > 0 { 25 | x = p.shared[l-1] 26 | p.shared = p.shared[:l-1] 27 | } else if p.New != nil { 28 | x = p.New() 29 | } 30 | return x 31 | } 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /engine/src/std/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Goscript Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | /// Go 1.12 6 | /// 7 | mod bits; 8 | mod fmt2; 9 | mod io; 10 | pub(crate) mod os; 11 | mod reflect; 12 | #[cfg(feature = "async")] 13 | mod sync; 14 | #[cfg(target_arch = "wasm32")] 15 | mod wasm; 16 | 17 | pub(crate) fn register(factory: &mut go_vm::FfiFactory) { 18 | fmt2::Fmt2Ffi::register(factory); 19 | bits::BitsFfi::register(factory); 20 | #[cfg(feature = "async")] 21 | sync::MutexFfi::register(factory); 22 | #[cfg(feature = "async")] 23 | sync::RWMutexFfi::register(factory); 24 | reflect::ReflectFfi::register(factory); 25 | io::IoFfi::register(factory); 26 | os::FileFfi::register(factory); 27 | } 28 | -------------------------------------------------------------------------------- /std/unicode/casetables.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // TODO: This file contains the special casing rules for Turkish and Azeri only. 6 | // It should encompass all the languages with special casing rules 7 | // and be generated automatically, but that requires some API 8 | // development first. 9 | 10 | package unicode 11 | 12 | var TurkishCase SpecialCase = _TurkishCase 13 | var _TurkishCase = SpecialCase{ 14 | CaseRange{0x0049, 0x0049, d{0, 0x131 - 0x49, 0}}, 15 | CaseRange{0x0069, 0x0069, d{0x130 - 0x69, 0, 0x130 - 0x69}}, 16 | CaseRange{0x0130, 0x0130, d{0, 0x69 - 0x130, 0}}, 17 | CaseRange{0x0131, 0x0131, d{0x49 - 0x131, 0, 0x49 - 0x131}}, 18 | } 19 | 20 | var AzeriCase SpecialCase = _TurkishCase 21 | -------------------------------------------------------------------------------- /engine/tests/std/time.gos: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt2" 5 | "time" 6 | ) 7 | 8 | func main() { 9 | p := fmt2.Println 10 | 11 | now := time.Now() 12 | p(now) 13 | 14 | then := time.Date( 15 | 2009, 11, 17, 20, 34, 58, 651387237, time.UTC) 16 | p(then) 17 | 18 | p(then.Year()) 19 | p(then.Month()) 20 | p(then.Day()) 21 | p(then.Hour()) 22 | p(then.Minute()) 23 | p(then.Second()) 24 | p(then.Nanosecond()) 25 | p(then.Location()) 26 | 27 | p(then.Weekday()) 28 | 29 | p(then.Before(now)) 30 | 31 | p(then.After(now)) 32 | p(then.Equal(now)) 33 | 34 | diff := now.Sub(then) 35 | p(diff) 36 | 37 | p(diff.Hours()) 38 | p(diff.Minutes()) 39 | p(diff.Seconds()) 40 | p(diff.Nanoseconds()) 41 | 42 | p(then.Add(diff)) 43 | p(then.Add(-diff)) 44 | } -------------------------------------------------------------------------------- /engine/src/vfs/mod.rs: -------------------------------------------------------------------------------- 1 | use std::io; 2 | use std::path::{Path, PathBuf}; 3 | 4 | pub(crate) mod compound; 5 | pub(crate) mod vfs_map; 6 | 7 | #[cfg(feature = "read_fs")] 8 | pub(crate) mod vfs_fs; 9 | #[cfg(feature = "read_zip")] 10 | pub(crate) mod vfs_zip; 11 | 12 | pub trait VirtualFs { 13 | fn read_file(&self, path: &Path) -> io::Result; 14 | 15 | fn read_dir(&self, path: &Path) -> io::Result>; 16 | 17 | fn is_file(&self, path: &Path) -> bool; 18 | 19 | fn is_dir(&self, path: &Path) -> bool; 20 | 21 | fn canonicalize_path(&self, path: &PathBuf) -> io::Result; 22 | 23 | fn is_local(&self, path: &str) -> bool { 24 | path == "." || path == ".." || path.starts_with("./") || path.starts_with("../") 25 | } 26 | 27 | fn strip_prefix<'a>(&'a self, path: &'a Path) -> &'a Path { 28 | path 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /engine/tests/group1/func1.gos: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | func funca(i int) int { 4 | j := i + 1 5 | return j 6 | } 7 | 8 | 9 | func funcb(i int, iii int) (a int, b int) { 10 | fff := 4 11 | fff = 5 12 | fff = fff + 50 + i + funca(i) + iii 13 | b = fff 14 | return 15 | } 16 | 17 | 18 | func funcc(x ...int) (int, int, int) { 19 | i := []int{8} 20 | i = append(i, x...) 21 | m, n := funcb(i[0], i[1]) 22 | return m, n, i[2] 23 | } 24 | 25 | func named() (result int) { 26 | result = 6 27 | return 28 | } 29 | 30 | 31 | func main() { 32 | 33 | var v1, v2, v3 = funcc(100, 200, 300) 34 | var i1, i2, i3 = funcc([]int{1000, 2000, 3000}...) 35 | assert(v1 == 0) 36 | assert(v2 == 172) 37 | assert(v3 == 200) 38 | assert(i1 == 0) 39 | assert(i2 == 1072) 40 | assert(i3 == 2000) 41 | assert(named() == 6) 42 | } 43 | -------------------------------------------------------------------------------- /pmacro/src/unsafe_ptr.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Goscript Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | use quote::quote; 6 | use syn::{parse_macro_input, DeriveInput}; 7 | 8 | pub fn derive_unsafe_ptr_implement(input: proc_macro::TokenStream) -> proc_macro::TokenStream { 9 | // Parse the input tokens into a syntax tree. 10 | let input = parse_macro_input!(input as DeriveInput); 11 | let name = input.ident; 12 | let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl(); 13 | 14 | let expanded = quote! { 15 | impl #impl_generics UnsafePtr for #name #ty_generics #where_clause { 16 | fn as_any(&self) -> &dyn std::any::Any { 17 | self 18 | } 19 | } 20 | }; 21 | proc_macro::TokenStream::from(expanded) 22 | } 23 | -------------------------------------------------------------------------------- /std/math/hypot.go: -------------------------------------------------------------------------------- 1 | // Copyright 2010 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package math 6 | 7 | /* 8 | Hypot -- sqrt(p*p + q*q), but overflows only if the result does. 9 | */ 10 | 11 | // Hypot returns Sqrt(p*p + q*q), taking care to avoid 12 | // unnecessary overflow and underflow. 13 | // 14 | // Special cases are: 15 | // Hypot(±Inf, q) = +Inf 16 | // Hypot(p, ±Inf) = +Inf 17 | // Hypot(NaN, q) = NaN 18 | // Hypot(p, NaN) = NaN 19 | func Hypot(p, q float64) float64 { 20 | // special cases 21 | switch { 22 | case IsInf(p, 0) || IsInf(q, 0): 23 | return Inf(1) 24 | case IsNaN(p) || IsNaN(q): 25 | return NaN() 26 | } 27 | p, q = Abs(p), Abs(q) 28 | if p < q { 29 | p, q = q, p 30 | } 31 | if p == 0 { 32 | return 0 33 | } 34 | q = q / p 35 | return p * Sqrt(1+q*q) 36 | } 37 | -------------------------------------------------------------------------------- /engine/tests/group1/basictypes.gos: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt2" 4 | 5 | func main() { 6 | var i1 uint8 = 80 7 | j1 := i1 + 200 8 | assert(j1 == 24) 9 | fmt2.Println(j1) 10 | 11 | var i2 uint8 = 0b0011 12 | var i3 uint8 = 0b0101 13 | assert(i2 & i3 == 0b0001) 14 | assert(i2 | i3 == 0b0111) 15 | assert(^i3 == 0b11111010) 16 | 17 | var i4 = 0b00110101 18 | assert(i4 << 2 == 0b11010100) 19 | assert(i4 >> 2 == 0b00001101) 20 | assert(i4 << 100 == 0) 21 | 22 | var ir1 uint8 = 2 23 | var ir2 uint16 = 2 24 | var ir3 uint16 = 2 25 | assert(i4 << ir1 == 0b11010100) 26 | assert(i4 >> ir1 == 0b00001101) 27 | assert(i4 << ir2 == 0b11010100) 28 | assert(i4 >> ir2 == 0b00001101) 29 | assert(i4 << ir3 == 0b11010100) 30 | assert(i4 >> ir3 == 0b00001101) 31 | 32 | assert(i4 << -ir1 == 0) 33 | assert(-ir1 == 254) 34 | 35 | //todo 36 | 37 | } -------------------------------------------------------------------------------- /engine/tests/group2/sync_rwmutex.gos: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt2" 5 | "sync" 6 | ) 7 | 8 | type Container struct { 9 | counters map[string]int 10 | mu sync.RWMutex 11 | } 12 | 13 | 14 | func (c *Container) inc(name string) { 15 | 16 | c.mu.Lock() 17 | defer c.mu.Unlock() 18 | c.counters[name] +=1 19 | } 20 | 21 | func (c *Container) read(name string) { 22 | 23 | c.mu.RLock() 24 | defer c.mu.RUnlock() 25 | fmt2.Println(c.counters[name]) 26 | } 27 | 28 | 29 | func main() { 30 | 31 | c := Container{ 32 | 33 | counters: map[string]int{"a": 0, "b": 0}, 34 | } 35 | 36 | 37 | go func() { 38 | for i := 0; i < 3; i++ { 39 | c.inc("aaa") 40 | for i := 0; i < 100; i++ { 41 | } 42 | } 43 | }() 44 | 45 | go func() { 46 | for i := 0; i < 2; i++{ 47 | go c.read("aaa") 48 | } 49 | }() 50 | } -------------------------------------------------------------------------------- /std/math/frexp.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package math 6 | 7 | // Frexp breaks f into a normalized fraction 8 | // and an integral power of two. 9 | // It returns frac and exp satisfying f == frac × 2**exp, 10 | // with the absolute value of frac in the interval [½, 1). 11 | // 12 | // Special cases are: 13 | // Frexp(±0) = ±0, 0 14 | // Frexp(±Inf) = ±Inf, 0 15 | // Frexp(NaN) = NaN, 0 16 | func Frexp(f float64) (frac float64, exp int) { 17 | // special cases 18 | switch { 19 | case f == 0: 20 | return f, 0 // correctly return -0 21 | case IsInf(f, 0) || IsNaN(f): 22 | return f, 0 23 | } 24 | f, exp = normalize(f) 25 | x := Float64bits(f) 26 | exp += int((x>>shift)&mask) - bias + 1 27 | x &^= mask << shift 28 | x |= (-1 + bias) << shift 29 | frac = Float64frombits(x) 30 | return 31 | } 32 | -------------------------------------------------------------------------------- /std/math/modf.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package math 6 | 7 | // Modf returns integer and fractional floating-point numbers 8 | // that sum to f. Both values have the same sign as f. 9 | // 10 | // Special cases are: 11 | // Modf(±Inf) = ±Inf, NaN 12 | // Modf(NaN) = NaN, NaN 13 | func Modf(f float64) (int float64, frac float64) { 14 | if f < 1 { 15 | switch { 16 | case f < 0: 17 | int, frac = Modf(-f) 18 | return -int, -frac 19 | case f == 0: 20 | return f, f // Return -0, -0 when f == -0 21 | } 22 | return 0, f 23 | } 24 | 25 | x := Float64bits(f) 26 | e := uint(x>>shift)&mask - bias 27 | 28 | // Keep the top 12+e bits, the integer part; clear the rest. 29 | if e < 64-12 { 30 | x &^= 1<<(64-12-e) - 1 31 | } 32 | int = Float64frombits(x) 33 | frac = f - int 34 | return 35 | } 36 | -------------------------------------------------------------------------------- /types/tests/data/importdecl0/importdecl0a.src: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package importdecl0 6 | 7 | import () 8 | 9 | 10 | import "../math" /* ERROR "imported but not used" */ 11 | import m /* ERROR "imported but not used as m" */ "../math" 12 | import _ "../math" 13 | 14 | 15 | import "../time" 16 | import f1 "../time" 17 | import f2 "../time" 18 | 19 | // imported package name may conflict with local objects 20 | type time /* ERROR "time already declared" */ int 21 | 22 | // dot-imported exported objects may conflict with local objects 23 | type Time /* ERROR "Time already declared through dot-import of package" */ struct{} 24 | 25 | var _ = time.Time{} // use "fmt" 26 | 27 | func _() { 28 | _ = f1.Time{} // use "fmt" 29 | } 30 | 31 | func _() { 32 | _ = func() { 33 | _ = f2.Time{} // use "fmt" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /types/tests/data/cycles3.gos: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package p 6 | 7 | import "unsafe" 8 | 9 | var ( 10 | _ A = A(nil).a().b().c().d().e().f() 11 | _ A = A(nil).b().c().d().e().f() 12 | _ A = A(nil).c().d().e().f() 13 | _ A = A(nil).d().e().f() 14 | _ A = A(nil).e().f() 15 | _ A = A(nil).f() 16 | _ A = A(nil) 17 | ) 18 | 19 | type ( 20 | A interface { 21 | a() B 22 | B 23 | } 24 | 25 | B interface { 26 | b() C 27 | C 28 | } 29 | 30 | C interface { 31 | c() D 32 | D 33 | } 34 | 35 | D interface { 36 | d() E 37 | E 38 | } 39 | 40 | E interface { 41 | e() F 42 | F 43 | } 44 | 45 | F interface { 46 | f() A 47 | } 48 | ) 49 | 50 | type ( 51 | U /* ERROR cycle */ interface { 52 | V 53 | } 54 | 55 | V interface { 56 | v() [unsafe.Sizeof(u)]int 57 | } 58 | ) 59 | 60 | var u U 61 | -------------------------------------------------------------------------------- /std/math/mod.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009-2010 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package math 6 | 7 | /* 8 | Floating-point mod function. 9 | */ 10 | 11 | // Mod returns the floating-point remainder of x/y. 12 | // The magnitude of the result is less than y and its 13 | // sign agrees with that of x. 14 | // 15 | // Special cases are: 16 | // Mod(±Inf, y) = NaN 17 | // Mod(NaN, y) = NaN 18 | // Mod(x, 0) = NaN 19 | // Mod(x, ±Inf) = x 20 | // Mod(x, NaN) = NaN 21 | func Mod(x, y float64) float64 { 22 | if y == 0 || IsInf(x, 0) || IsNaN(x) || IsNaN(y) { 23 | return NaN() 24 | } 25 | y = Abs(y) 26 | 27 | yfr, yexp := Frexp(y) 28 | r := x 29 | if x < 0 { 30 | r = -x 31 | } 32 | 33 | for r >= y { 34 | rfr, rexp := Frexp(r) 35 | if rfr < yfr { 36 | rexp = rexp - 1 37 | } 38 | r = r - Ldexp(y, rexp-yexp) 39 | } 40 | if x < 0 { 41 | r = -r 42 | } 43 | return r 44 | } 45 | -------------------------------------------------------------------------------- /engine/tests/group1/channel.gos: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt2" 4 | 5 | func sum(s []int, c chan int) { 6 | sum := 0 7 | for _, v := range s { 8 | sum += v 9 | } 10 | c <- sum // send sum to c 11 | fmt2.Println("c len: ", len(c)) 12 | } 13 | 14 | func testWithCap(capacity int) { 15 | s := []int{7, 2, 8, -9, 4, 0} 16 | 17 | c := make(chan int, capacity) 18 | go sum(s[:len(s)/2], c) 19 | go sum(s[len(s)/2:], c) 20 | 21 | x, y := <-c, <-c // receive from c 22 | 23 | assert(x + y == 12) 24 | fmt2.Println(x, y, x+y) 25 | 26 | 27 | go func() {c <- 888}() 28 | nn, ok := <- c 29 | assert(nn == 888) 30 | assert(ok) 31 | 32 | close(c) 33 | assert(<-c == 0) 34 | fmt2.Println(<-c) 35 | m := <- c 36 | assert(m == 0) 37 | n, ok := <- c 38 | assert(n == 0) 39 | assert(!ok) 40 | 41 | fmt2.Println(m, n, nn) 42 | 43 | assert(cap(c) == capacity) 44 | } 45 | 46 | 47 | func main() { 48 | testWithCap(0) 49 | testWithCap(1) 50 | testWithCap(2) 51 | testWithCap(3) 52 | testWithCap(999) 53 | } 54 | -------------------------------------------------------------------------------- /engine/tests/std/sort.gos: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "sort" 5 | "fmt2" 6 | ) 7 | 8 | 9 | func main() { 10 | family := []struct { 11 | Name string 12 | Age int 13 | }{ 14 | {"Alice", 23}, 15 | {"David", 2}, 16 | {"Eve", 2}, 17 | {"Bob", 25}, 18 | } 19 | 20 | // Sort by age, keeping original order or equal elements. 21 | sort.SliceStable(family, func(i, j int) bool { 22 | return family[i].Age < family[j].Age 23 | }) 24 | assert(family[1].Name == "Eve") 25 | assert(family[3].Name == "Bob") 26 | fmt2.Println(family) 27 | 28 | sort.Slice(family, func(i, j int) bool { 29 | return family[i].Name < family[j].Name 30 | }) 31 | assert(family[0].Name == "Alice") 32 | assert(family[3].Name == "Eve") 33 | fmt2.Println(family) 34 | 35 | t := []string{"a", "b", "c","z", "y", "x"} 36 | sort.Strings(t) 37 | assert(t[0] == "a") 38 | assert(t[len(t)-1] == "z") 39 | fmt2.Println(t) 40 | 41 | } -------------------------------------------------------------------------------- /engine/tests/group1/interface2.gos: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt2" 4 | 5 | type geometry interface { 6 | area() float64 7 | perim() float64 8 | } 9 | 10 | type rect struct { 11 | width, height float64 12 | } 13 | 14 | func (r rect) perim() float64 { 15 | return 2*r.width + 2*r.height 16 | } 17 | 18 | func (r rect) area() float64 { 19 | return r.width * r.height 20 | } 21 | 22 | func test1() { 23 | 24 | a := geometry(nil) 25 | var b geometry = (geometry)(nil) 26 | assert(a == nil) 27 | assert(b == nil) 28 | 29 | var r *rect 30 | b = r 31 | assert(b != nil) 32 | } 33 | 34 | 35 | //////////////////////////////////// 36 | 37 | type I interface { 38 | printVal() 39 | } 40 | 41 | type S struct { 42 | i int 43 | } 44 | 45 | func (s S) printVal() { 46 | assert(s.i == 0) 47 | fmt2.Println(s.i) 48 | } 49 | 50 | func test2() { 51 | var i I 52 | 53 | var s S 54 | i = s 55 | s.i = 9 56 | i.printVal() 57 | } 58 | 59 | 60 | func main() { 61 | test1() 62 | test2() 63 | } 64 | -------------------------------------------------------------------------------- /types/src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Goscript Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | //! This crate is part of the Goscript project. Please refer to for more information. 6 | //! 7 | //! It's a port of the the parser from the Go standard library 8 | //! 9 | //! # Feature 10 | //! - `btree_map`: Make it use BTreeMap instead of HashMap 11 | //! 12 | 13 | mod constant; 14 | mod obj; 15 | mod package; 16 | mod scope; 17 | #[macro_use] 18 | mod objects; 19 | mod display; 20 | mod importer; 21 | mod lookup; 22 | mod operand; 23 | mod selection; 24 | mod universe; 25 | 26 | #[macro_use] 27 | pub mod typ; 28 | pub mod check; 29 | 30 | pub use constant::Value as ConstValue; 31 | pub use display::Displayer; 32 | pub use importer::*; 33 | pub use obj::*; 34 | pub use objects::*; 35 | pub use operand::OperandMode; 36 | pub use selection::*; 37 | pub use universe::*; 38 | -------------------------------------------------------------------------------- /engine/tests/group2/case2.gos: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "errors" 5 | "fmt2" 6 | ) 7 | 8 | func main() { 9 | 10 | err := errors.New("emit macho dwarf: elf header corrupted") 11 | if err != nil { 12 | fmt2.Println(err.Error(), 1, 2, 3, "tata") 13 | } 14 | 15 | 16 | var errNil error 17 | assert(errNil == nil) 18 | 19 | var sliceNil []int 20 | assert(sliceNil == nil) 21 | 22 | slice := make([]int, 1) 23 | assert(slice != nil) 24 | 25 | var mapNil map[int]string 26 | assert(mapNil == nil) 27 | mapNil[1] = "aa" 28 | 29 | m := make(map[int]string) 30 | assert(m != nil) 31 | m[1] = "aa" 32 | 33 | 34 | _, ok := err.(*errorString) 35 | assert(!ok) 36 | 37 | err2 := New("haha") 38 | _, ok2 := err2.(*errorString) 39 | assert(ok2) 40 | 41 | fmt2.Println(ok, ok2, m[1]) 42 | 43 | } 44 | 45 | 46 | 47 | func New(text string) error { 48 | return &errorString{text} 49 | } 50 | 51 | // errorString is a trivial implementation of error. 52 | type errorString struct { 53 | s string 54 | } 55 | 56 | func (e *errorString) Error() string { 57 | return e.s 58 | } 59 | -------------------------------------------------------------------------------- /types/tests/data/importdecl0/importdecl0b.src: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package importdecl0 6 | 7 | import "../math" 8 | import m "../math" 9 | 10 | 11 | import . /* ERROR "imported but not used" */ "unsafe" 12 | import . "../time" // declares Println in file scope 13 | 14 | import ( 15 | // TODO(gri) At the moment, 2 errors are reported because both go/parser 16 | // and the type checker report it. Eventually, this test should not be 17 | // done by the parser anymore. 18 | "" /*ERROR invalid import path */ /* ERROR invalid import path */ 19 | "a!b" /*ERROR invalid import path */ /* ERROR invalid import path */ 20 | "abc\xffdef" /*ERROR invalid import path */ /* ERROR invalid import path */ 21 | ) 22 | 23 | // using "math" in this file doesn't affect its use in other files 24 | const Pi0 = math.Pi 25 | const Pi1 = m.Pi 26 | 27 | func _() func() interface{} { 28 | return func() interface{} { 29 | return Time{} // use "../time" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /vm/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "go-vm" 3 | version = "0.1.5" 4 | authors = ["oxfeeefeee "] 5 | edition = "2021" 6 | license = "BSD-2-Clause" 7 | repository = "https://github.com/oxfeeefeee/goscript/" 8 | keywords = ["golang", "vm", "goscript"] 9 | categories = ["programming language", "vm"] 10 | description = "The vm of the Goscript project." 11 | 12 | [features] 13 | default = [] 14 | async = ["dep:async-channel", "dep:async-executor", "dep:futures-lite", "dep:fastrand"] 15 | btree_map = ["go-parser/btree_map"] 16 | instruction_pos = [] 17 | serde_borsh = ["dep:borsh", "go-parser/serde_borsh"] 18 | 19 | [dependencies] 20 | ordered-float = "3.0" 21 | async-channel = { version = "1.6.1", optional = true } 22 | async-executor = { version ="1.4.1", optional = true } 23 | futures-lite = { version ="1.12.0", optional = true } 24 | fastrand = { version ="1.9.0", optional = true } 25 | borsh = { version ="0.10.3", optional = true } 26 | 27 | go-parser = { version = "0.1.5", path = "../parser" } 28 | go-pmacro = { version = "0.1.5", path = "../pmacro" } 29 | 30 | [dev-dependencies] 31 | time-test = "0.2.2" -------------------------------------------------------------------------------- /types/tests/data/time/time.gos: -------------------------------------------------------------------------------- 1 | package time 2 | 3 | type Time struct { 4 | // wall and ext encode the wall time seconds, wall time nanoseconds, 5 | // and optional monotonic clock reading in nanoseconds. 6 | // 7 | // From high to low bit position, wall encodes a 1-bit flag (hasMonotonic), 8 | // a 33-bit seconds field, and a 30-bit wall time nanoseconds field. 9 | // The nanoseconds field is in the range [0, 999999999]. 10 | // If the hasMonotonic bit is 0, then the 33-bit field must be zero 11 | // and the full signed 64-bit wall seconds since Jan 1 year 1 is stored in ext. 12 | // If the hasMonotonic bit is 1, then the 33-bit field holds a 33-bit 13 | // unsigned wall seconds since Jan 1 year 1885, and ext holds a 14 | // signed 64-bit monotonic clock reading, nanoseconds since process start. 15 | wall uint64 16 | ext int64 17 | 18 | // loc specifies the Location that should be used to 19 | // determine the minute, hour, month, day, and year 20 | // that correspond to this Time. 21 | // The nil location means UTC. 22 | // All UTC times are represented with loc==nil, never loc==&utcLoc. 23 | loc *Time 24 | } 25 | -------------------------------------------------------------------------------- /std/strconv/atob.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package strconv 6 | 7 | // ParseBool returns the boolean value represented by the string. 8 | // It accepts 1, t, T, TRUE, true, True, 0, f, F, FALSE, false, False. 9 | // Any other value returns an error. 10 | func ParseBool(str string) (bool, error) { 11 | switch str { 12 | case "1", "t", "T", "true", "TRUE", "True": 13 | return true, nil 14 | case "0", "f", "F", "false", "FALSE", "False": 15 | return false, nil 16 | } 17 | return false, syntaxError("ParseBool", str) 18 | } 19 | 20 | // FormatBool returns "true" or "false" according to the value of b. 21 | func FormatBool(b bool) string { 22 | if b { 23 | return "true" 24 | } 25 | return "false" 26 | } 27 | 28 | // AppendBool appends "true" or "false", according to the value of b, 29 | // to dst and returns the extended buffer. 30 | func AppendBool(dst []byte, b bool) []byte { 31 | if b { 32 | return append(dst, "true"...) 33 | } 34 | return append(dst, "false"...) 35 | } 36 | -------------------------------------------------------------------------------- /std/math/ldexp.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package math 6 | 7 | // Ldexp is the inverse of Frexp. 8 | // It returns frac × 2**exp. 9 | // 10 | // Special cases are: 11 | // Ldexp(±0, exp) = ±0 12 | // Ldexp(±Inf, exp) = ±Inf 13 | // Ldexp(NaN, exp) = NaN 14 | func Ldexp(frac float64, exp int) float64 { 15 | // special cases 16 | switch { 17 | case frac == 0: 18 | return frac // correctly return -0 19 | case IsInf(frac, 0) || IsNaN(frac): 20 | return frac 21 | } 22 | frac, e := normalize(frac) 23 | exp += e 24 | x := Float64bits(frac) 25 | exp += int(x>>shift)&mask - bias 26 | if exp < -1075 { 27 | return Copysign(0, frac) // underflow 28 | } 29 | if exp > 1023 { // overflow 30 | if frac < 0 { 31 | return Inf(-1) 32 | } 33 | return Inf(1) 34 | } 35 | var m float64 = 1 36 | if exp < -1022 { // denormal 37 | exp += 53 38 | m = 1.0 / (1 << 53) // 2**-53 39 | } 40 | x &^= mask << shift 41 | x |= uint64(exp+bias) << shift 42 | return m * Float64frombits(x) 43 | } 44 | -------------------------------------------------------------------------------- /types/tests/data/cycles1.gos: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package p 6 | 7 | type ( 8 | A interface { 9 | a() interface { 10 | ABC1 11 | } 12 | } 13 | B interface { 14 | b() interface { 15 | ABC2 16 | } 17 | } 18 | C interface { 19 | c() interface { 20 | ABC3 21 | } 22 | } 23 | 24 | AB interface { 25 | A 26 | B 27 | } 28 | BC interface { 29 | B 30 | C 31 | } 32 | 33 | ABC1 interface { 34 | A 35 | B 36 | C 37 | } 38 | ABC2 interface { 39 | AB 40 | C 41 | } 42 | ABC3 interface { 43 | A 44 | BC 45 | } 46 | ) 47 | 48 | var ( 49 | x1 ABC1 50 | x2 ABC2 51 | x3 ABC3 52 | ) 53 | 54 | func _() { 55 | // all types have the same method set 56 | x1 = x2 57 | x2 = x1 58 | 59 | x1 = x3 60 | x3 = x1 61 | 62 | x2 = x3 63 | x3 = x2 64 | 65 | // all methods return the same type again 66 | x1 = x1.a() 67 | x1 = x1.b() 68 | x1 = x1.c() 69 | 70 | x2 = x2.a() 71 | x2 = x2.b() 72 | x2 = x2.c() 73 | 74 | x3 = x3.a() 75 | x3 = x3.b() 76 | x3 = x3.c() 77 | } 78 | -------------------------------------------------------------------------------- /engine/tests/group1/select.gos: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt2" 4 | 5 | func fibonacci(c, quit chan int) { 6 | x, y := 0, 1 7 | var s = make([]int, 2) 8 | for { 9 | select { 10 | case c <- x: 11 | x, y = y, x+y 12 | case s[0] = <-quit: 13 | assert(s[0] == 999) 14 | fmt2.Println("quit 拉", s) 15 | return 16 | } 17 | } 18 | } 19 | 20 | func main() { 21 | c := make(chan int) 22 | quit := make(chan int) 23 | go func() { 24 | for i := 0; i < 12; i++ { 25 | fmt2.Println(<-c) 26 | } 27 | quit <- 999 28 | }() 29 | 30 | fibonacci(c, quit) 31 | 32 | 33 | var f = false 34 | 35 | go func() { 36 | quit <- 888 37 | }() 38 | 39 | select { 40 | case v, ok := <- c: 41 | assert(f) 42 | fmt2.Println("c recv:", v, ok) 43 | case v, ok := <-quit: 44 | assert(v == 888) 45 | assert(ok) 46 | fmt2.Println("quit recv:", v, ok) 47 | } 48 | 49 | go func() { 50 | close(c) 51 | }() 52 | 53 | select { 54 | case v, ok := <- c: 55 | assert(v == 0) 56 | assert(!ok) 57 | fmt2.Println("c recv:", v, ok) 58 | break 59 | assert(f) 60 | case v, ok := <-quit: 61 | assert(f) 62 | fmt2.Println("222 quit recv:", v, ok) 63 | 64 | } 65 | } -------------------------------------------------------------------------------- /engine/tests/group2/sync_mutex.gos: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt2" 5 | "sync" 6 | ) 7 | 8 | type Container struct { 9 | counters map[string]int 10 | mu sync.Mutex 11 | } 12 | 13 | 14 | func (c *Container) inc(name string) { 15 | 16 | c.mu.Lock() 17 | defer c.mu.Unlock() 18 | c.counters[name] +=100 19 | } 20 | 21 | 22 | func sync_map() { 23 | var m sync.Map 24 | 25 | m.Store(2, "b") 26 | v, ok := m.LoadOrStore(1, "a") 27 | v2, ok2 := m.Load(1) 28 | assert(v == "a") 29 | assert(!ok) 30 | assert(v2 == "a") 31 | assert(ok2) 32 | fmt2.Println(v, ok, v2, ok2) 33 | fmt2.Println(m) 34 | m.Delete(2) 35 | v3, _ := m.Load(2) 36 | fmt2.Println(m, v3) 37 | assert(v3 == nil) 38 | 39 | 40 | } 41 | 42 | 43 | func main() { 44 | 45 | sync_map() 46 | 47 | /* 48 | c := Container{ 49 | 50 | counters: map[string]int{"a": 0, "b": 0}, 51 | } 52 | c.inc("aaa") 53 | 54 | go c.inc("aaa") 55 | 56 | 57 | fmt2.Println(c.counters) 58 | for i := 0; i < 10000; i++ { 59 | 60 | } 61 | fmt2.Println(c.counters) 62 | 63 | fmt2.Println() 64 | */ 65 | } -------------------------------------------------------------------------------- /std/math/asin.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package math 6 | 7 | /* 8 | Floating-point arcsine and arccosine. 9 | 10 | They are implemented by computing the arctangent 11 | after appropriate range reduction. 12 | */ 13 | 14 | // Asin returns the arcsine, in radians, of x. 15 | // 16 | // Special cases are: 17 | // Asin(±0) = ±0 18 | // Asin(x) = NaN if x < -1 or x > 1 19 | func Asin(x float64) float64 { 20 | if x == 0 { 21 | return x // special case 22 | } 23 | sign := false 24 | if x < 0 { 25 | x = -x 26 | sign = true 27 | } 28 | if x > 1 { 29 | return NaN() // special case 30 | } 31 | 32 | temp := Sqrt(1 - x*x) 33 | if x > 0.7 { 34 | temp = Pi/2 - satan(temp/x) 35 | } else { 36 | temp = satan(x / temp) 37 | } 38 | 39 | if sign { 40 | temp = -temp 41 | } 42 | return temp 43 | } 44 | 45 | // Acos returns the arccosine, in radians, of x. 46 | // 47 | // Special case is: 48 | // Acos(x) = NaN if x < -1 or x > 1 49 | func Acos(x float64) float64 50 | 51 | func acos(x float64) float64 { 52 | return Pi/2 - Asin(x) 53 | } 54 | -------------------------------------------------------------------------------- /std/strings/compare.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package strings 6 | 7 | // Compare returns an integer comparing two strings lexicographically. 8 | // The result will be 0 if a==b, -1 if a < b, and +1 if a > b. 9 | // 10 | // Compare is included only for symmetry with package bytes. 11 | // It is usually clearer and always faster to use the built-in 12 | // string comparison operators ==, <, >, and so on. 13 | func Compare(a, b string) int { 14 | // NOTE(rsc): This function does NOT call the runtime cmpstring function, 15 | // because we do not want to provide any performance justification for 16 | // using strings.Compare. Basically no one should use strings.Compare. 17 | // As the comment above says, it is here only for symmetry with package bytes. 18 | // If performance is important, the compiler should be changed to recognize 19 | // the pattern so that all code doing three-way comparisons, not just code 20 | // using strings.Compare, can benefit. 21 | if a == b { 22 | return 0 23 | } 24 | if a < b { 25 | return -1 26 | } 27 | return +1 28 | } 29 | -------------------------------------------------------------------------------- /engine/benches/leet5_benchmark.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Goscript Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | use criterion::{criterion_group, criterion_main, Criterion}; 6 | 7 | extern crate go_engine as engine; 8 | use std::path::{Path, PathBuf}; 9 | 10 | #[cfg(feature = "go_std")] 11 | fn run(path: &str, trace: bool) -> Result<(), engine::ErrorList> { 12 | let mut cfg = engine::Config::default(); 13 | cfg.trace_parser = trace; 14 | cfg.trace_checker = trace; 15 | let sr = engine::SourceReader::local_fs(PathBuf::from("../std/"), PathBuf::from("./")); 16 | engine::run(cfg, &sr, Path::new(path), None) 17 | } 18 | 19 | #[cfg(not(feature = "go_std"))] 20 | fn run(_path: &str, _trace: bool) -> Result<(), engine::ErrorList> { 21 | unimplemented!() 22 | } 23 | 24 | fn leetcode5() { 25 | let errs = run("./tests/demo/leetcode5.gos", false); 26 | assert!(errs.is_ok()); 27 | } 28 | 29 | pub fn criterion_benchmark(c: &mut Criterion) { 30 | c.bench_function("leet5", |b| b.iter(|| leetcode5())); 31 | } 32 | 33 | criterion_group!(benches, criterion_benchmark); 34 | criterion_main!(benches); 35 | -------------------------------------------------------------------------------- /engine/tests/group2/case0.gos: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt2" 4 | 5 | import sl "./somelib" 6 | 7 | type TestKey struct { 8 | i int 9 | s string 10 | } 11 | 12 | func ptr() (*int, *int) { 13 | i := 100 14 | return &i, &i 15 | } 16 | 17 | 18 | func main() { 19 | 20 | sl.SomeFunc() 21 | 22 | var errNil error 23 | var mapNil map[int]string 24 | //mapNil[1] = "aa" 25 | 26 | m := make(map[int]string) 27 | m[1] = "bb" 28 | 29 | assert(errNil == nil) 30 | assert(mapNil == nil) 31 | assert(m != nil) 32 | 33 | ms := make(map[string]int) 34 | ms["aa"] = 1 35 | assert(ms["aa"] == 1) 36 | 37 | mss := make(map[TestKey]int) 38 | mss[TestKey{1,"a"}] = 2 39 | assert(mss[TestKey{1,"a"}] == 2) 40 | assert(mss[TestKey{1,"b"}] == 0) 41 | 42 | mi := make(map[interface{}]int) 43 | mi[1] = 1 44 | mi["a"] = 2 45 | assert(mi[1] == 1) 46 | assert(mi["a"] == 2) 47 | mi["a"] = mi[1] 48 | assert(mi["a"] == 1) 49 | 50 | 51 | mp := make(map[*int]int) 52 | k, q := ptr() 53 | r,_ := ptr() 54 | mp[k] = 8 55 | assert(mp[q] == 8) 56 | assert(mp[r] == 0) 57 | assert(*k == *r) 58 | 59 | fmt2.Println(k, q, r, *k, *q, *r) 60 | } -------------------------------------------------------------------------------- /std/math/logb.go: -------------------------------------------------------------------------------- 1 | // Copyright 2010 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package math 6 | 7 | // Logb returns the binary exponent of x. 8 | // 9 | // Special cases are: 10 | // Logb(±Inf) = +Inf 11 | // Logb(0) = -Inf 12 | // Logb(NaN) = NaN 13 | func Logb(x float64) float64 { 14 | // special cases 15 | switch { 16 | case x == 0: 17 | return Inf(-1) 18 | case IsInf(x, 0): 19 | return Inf(1) 20 | case IsNaN(x): 21 | return x 22 | } 23 | return float64(ilogb(x)) 24 | } 25 | 26 | // Ilogb returns the binary exponent of x as an integer. 27 | // 28 | // Special cases are: 29 | // Ilogb(±Inf) = MaxInt32 30 | // Ilogb(0) = MinInt32 31 | // Ilogb(NaN) = MaxInt32 32 | func Ilogb(x float64) int { 33 | // special cases 34 | switch { 35 | case x == 0: 36 | return MinInt32 37 | case IsNaN(x): 38 | return MaxInt32 39 | case IsInf(x, 0): 40 | return MaxInt32 41 | } 42 | return ilogb(x) 43 | } 44 | 45 | // logb returns the binary exponent of x. It assumes x is finite and 46 | // non-zero. 47 | func ilogb(x float64) int { 48 | x, exp := normalize(x) 49 | return int((Float64bits(x)>>shift)&mask) - bias + exp 50 | } 51 | -------------------------------------------------------------------------------- /pmacro/src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Goscript Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | //! This crate is part of the Goscript project. Please refer to for more information. 6 | //! 7 | //! This crate provides some proc-macros for the project. 8 | //! 9 | 10 | mod async_fn; 11 | mod ffi; 12 | mod ffi_impl; 13 | mod unsafe_ptr; 14 | 15 | #[proc_macro_derive(Ffi)] 16 | pub fn derive_ffi(input: proc_macro::TokenStream) -> proc_macro::TokenStream { 17 | ffi::derive_ffi_implement(input) 18 | } 19 | 20 | #[proc_macro_attribute] 21 | pub fn ffi_impl( 22 | args: proc_macro::TokenStream, 23 | input: proc_macro::TokenStream, 24 | ) -> proc_macro::TokenStream { 25 | ffi_impl::ffi_impl_implement(args, input) 26 | } 27 | 28 | #[proc_macro_derive(UnsafePtr)] 29 | pub fn derive_unsafe_ptr(input: proc_macro::TokenStream) -> proc_macro::TokenStream { 30 | unsafe_ptr::derive_unsafe_ptr_implement(input) 31 | } 32 | 33 | #[proc_macro_attribute] 34 | pub fn async_fn( 35 | _: proc_macro::TokenStream, 36 | input: proc_macro::TokenStream, 37 | ) -> proc_macro::TokenStream { 38 | async_fn::async_fn_implement(input) 39 | } 40 | -------------------------------------------------------------------------------- /engine/src/vfs/vfs_fs.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Goscript Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | use crate::vfs::VirtualFs; 6 | use std::fs; 7 | use std::io; 8 | use std::path::{Path, PathBuf}; 9 | 10 | pub struct VfsFs {} 11 | 12 | impl VirtualFs for VfsFs { 13 | fn read_file(&self, path: &Path) -> io::Result { 14 | fs::read_to_string(path) 15 | } 16 | 17 | fn read_dir(&self, path: &Path) -> io::Result> { 18 | Ok(fs::read_dir(path)? 19 | .filter_map(|x| { 20 | x.map_or(None, |e| { 21 | let path = e.path(); 22 | (!path.is_dir()).then(|| path) 23 | }) 24 | }) 25 | .collect()) 26 | } 27 | 28 | fn is_file(&self, path: &Path) -> bool { 29 | path.is_file() 30 | } 31 | 32 | fn is_dir(&self, path: &Path) -> bool { 33 | path.is_dir() 34 | } 35 | 36 | fn canonicalize_path(&self, path: &PathBuf) -> io::Result { 37 | if !path.exists() { 38 | Err(io::Error::from(io::ErrorKind::NotFound)) 39 | } else { 40 | path.canonicalize() 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /engine/tests/issues/issue8.gos: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt2" 5 | ) 6 | 7 | type Base struct { 8 | i int 9 | name string 10 | } 11 | 12 | func (b Base) PrintField() { 13 | b.name = "not_go" 14 | fmt2.Println(b.name) 15 | } 16 | 17 | type Base2 struct { 18 | i int 19 | j int 20 | name2 string 21 | } 22 | 23 | func (b *Base2) PrintField2() { 24 | b.name2 = "not_go2" 25 | fmt2.Println(b.name2) 26 | } 27 | 28 | type Container struct { 29 | *Base 30 | Base2 31 | } 32 | 33 | type Container2 struct { 34 | Container 35 | } 36 | 37 | func main() { 38 | t := Container{&Base{1, "go"}, Base2{1, 1, "go2"}} 39 | t.PrintField() 40 | t.PrintField2() 41 | assert(t.name == "go") 42 | assert(t.name2 == "not_go2") 43 | t.Base.PrintField() 44 | t.Base2.PrintField2() 45 | 46 | fmt2.Println("-----") 47 | 48 | 49 | t2 := Container2{t} 50 | t2.PrintField() 51 | t2.PrintField2() 52 | assert(t.name == "go") 53 | assert(t.name2 == "not_go2") 54 | t2.Base.PrintField() 55 | t2.Base2.PrintField2() 56 | 57 | fmt2.Println("-----") 58 | 59 | p := &t 60 | p.PrintField() 61 | 62 | test2(); 63 | } 64 | 65 | func test2() { 66 | t := Container{&Base{1, "go"}, Base2{1, 1, "go2"}} 67 | t.j = 456 68 | assert(t.j == 456) 69 | } -------------------------------------------------------------------------------- /engine/tests/group1/type1.gos: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | type S1 struct {i int; j int} 4 | 5 | 6 | func (s *S1) Inc() int { 7 | t := s.i 8 | s.i += 66 9 | assert(s.i - t == 66) 10 | return s.i 11 | } 12 | 13 | func (s S1) Inc2() int { 14 | assert(s.j == 0) 15 | s.j += 1 16 | assert(s.j == 1) 17 | return s.j 18 | } 19 | 20 | func typeAssert() { 21 | var i interface{} = "hello" 22 | 23 | s, ok := i.(string) 24 | assert(ok) 25 | assert(s == "hello") 26 | 27 | s1 := i.(string) 28 | assert(s1 == "hello") 29 | 30 | var j interface{} = "h" 31 | s, ok = j.(string) 32 | assert(ok) 33 | assert(s == "h") 34 | 35 | var k interface{} 36 | _, ok = k.(string) 37 | assert(!ok) 38 | } 39 | 40 | type Add func(a int, b int) int 41 | 42 | 43 | func main() { 44 | type S2 struct {i int} 45 | var s1 S1 46 | //var s2 S2 47 | 48 | s1.Inc() 49 | s1.Inc2() 50 | assert(s1.i == 66) 51 | assert(s1.j == 0) 52 | 53 | p := &s1.i 54 | *p = 5 55 | assert(s1.i == 5) 56 | assert(s1.i == *p) 57 | 58 | f := s1.Inc 59 | f() 60 | assert(s1.i == 71) 61 | 62 | var afunc Add = func(i int, j int) int { return i + j + 1} 63 | d := afunc(s1.i, s1.j) 64 | assert(d == s1.i + s1.j + 1) 65 | 66 | 67 | typeAssert() 68 | typeAssert() 69 | typeAssert() 70 | 71 | } 72 | // 3, 8, 9 -------------------------------------------------------------------------------- /engine/src/std/fmt2.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Goscript Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | extern crate self as go_engine; 6 | use crate::ffi::*; 7 | use go_vm::types::{GosElem, GosValue}; 8 | 9 | #[derive(Ffi)] 10 | pub struct Fmt2Ffi; 11 | 12 | #[ffi_impl] 13 | impl Fmt2Ffi { 14 | fn ffi_println(args: GosValue) -> RuntimeResult<()> { 15 | let vec = FfiCtx::slice_as_rust_slice::(&args)?; 16 | let strs: Vec = vec 17 | .iter() 18 | .map(|x| { 19 | let val = x.borrow(); 20 | let s = if val.is_nil() { 21 | "".to_owned() 22 | } else { 23 | let underlying = val.iface_underlying()?; 24 | match underlying { 25 | Some(v) => v.to_string(), 26 | None => "".to_owned(), 27 | } 28 | }; 29 | Ok(s) 30 | }) 31 | .map(|x: RuntimeResult| x.unwrap()) 32 | .collect(); 33 | #[cfg(target_arch = "wasm32")] 34 | crate::std::wasm::console_log(&strs.join(", ")); 35 | #[cfg(not(target_arch = "wasm32"))] 36 | println!("{}", strs.join(", ")); 37 | Ok(()) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /pmacro/src/ffi.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Goscript Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | use quote::quote; 6 | use syn::{parse_macro_input, DeriveInput}; 7 | 8 | pub fn derive_ffi_implement(input: proc_macro::TokenStream) -> proc_macro::TokenStream { 9 | // Parse the input tokens into a syntax tree. 10 | let input = parse_macro_input!(input as DeriveInput); 11 | let name = input.ident; 12 | let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl(); 13 | 14 | let expanded = quote! { 15 | impl #impl_generics Ffi for #name #ty_generics #where_clause { 16 | fn call( 17 | &self, 18 | ctx: &mut FfiCtx, 19 | args: Vec, 20 | ) -> go_vm::types::RuntimeResult> { 21 | self.dispatch(ctx, args) 22 | } 23 | 24 | #[cfg(feature = "async")] 25 | fn async_call( 26 | &self, 27 | ctx: &mut FfiCtx, 28 | args: Vec, 29 | ) -> std::pin::Pin>> + '_>> { 30 | self.async_dispatch(ctx, args) 31 | } 32 | } 33 | }; 34 | 35 | proc_macro::TokenStream::from(expanded) 36 | } 37 | -------------------------------------------------------------------------------- /engine/tests/group1/map1.gos: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | 4 | func a () (int, int) { 5 | return 6,7 6 | } 7 | 8 | func b() int { 9 | return 8 10 | } 11 | 12 | func commaOk() { 13 | 14 | var i interface{} = "hello" 15 | 16 | 17 | s, ok := i.(string) 18 | assert(ok) 19 | assert(s == "hello") 20 | 21 | s1 := i.(string) 22 | assert(s1 == "hello") 23 | 24 | 25 | 26 | m := map[int]int{1:10, 2:20} 27 | int1, ok := m[1] 28 | assert(int1 == 10) 29 | assert(ok) 30 | int2 := m[2] 31 | assert(int2 == 20) 32 | 33 | t1, t2 := a() 34 | assert(t1 == 6) 35 | assert(t2 == 7) 36 | t3 := b() 37 | assert(t3 == 8) 38 | 39 | t01, t02 := 33, m[2] 40 | assert(t01 == 33) 41 | assert(t02 == 20) 42 | } 43 | 44 | func arrayKey() { 45 | m := make(map[[2]int]int) 46 | m[[2]int{1, 2}] = 1223 47 | m[[2]int{2, 2}] = 12233 48 | assert(m[[2]int{1, 2}] == 1223) 49 | 50 | m2 := make(map[[2]string]int) 51 | m2[[2]string{"1", "2"}] = 1223 52 | m2[[2]string{"2", "2"}] = 12233 53 | assert(m2[[2]string{"1", "2"}] == 1223) 54 | } 55 | 56 | func main() { 57 | var s1 = map[int]int{1:2, 3: 888} 58 | var v = s1[1] 59 | var v2 = s1[100] 60 | s1[0], v, v2 = 8, s1[100], s1[1] 61 | var v3 = s1[0] 62 | s1[2] = 3 63 | assert(v == 0) 64 | assert(v2 == 2) 65 | assert(v3 == 8) 66 | assert(s1[2] == 3) 67 | assert(s1[3] == 888) 68 | 69 | commaOk() 70 | 71 | arrayKey() 72 | } 73 | -------------------------------------------------------------------------------- /engine/tests/group1/typeswitch.gos: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | 8 | type S1 struct {i int; j int} 9 | 10 | func typeName(v interface{}) string { 11 | switch v.(type) { 12 | case int: 13 | return "int" 14 | case string: 15 | return "string" 16 | case *S1: 17 | return "S1" 18 | default: 19 | return "unknown" 20 | } 21 | } 22 | 23 | 24 | func typeName2(v interface{}) string { 25 | kk := 2 26 | switch i := v.(type) { 27 | case int: 28 | assert(i + kk == 890) 29 | return "int" 30 | case string: 31 | return "string" 32 | case *S1: 33 | _ = i 34 | return "S1" 35 | case []int: 36 | return "[]int" 37 | case map[string]int: 38 | assert(i["a"] == 666) 39 | return "map[string]int" 40 | case map[string][]int: 41 | return "map[string][]int" 42 | default: 43 | return "unknown" 44 | } 45 | return "int" 46 | } 47 | 48 | 49 | func test_ts_in_fmt() { 50 | var nums = []int{2, 5, 1, 3, 4, 7} 51 | fmt.Println(nums) 52 | } 53 | 54 | func main() { 55 | var s *S1; 56 | re := typeName(s) 57 | assert(re == "S1") 58 | re = typeName2(888) 59 | re2 := typeName2([]int{1}) 60 | re3 := typeName2(map[string]int{"a":666}) 61 | re4 := typeName2(map[string][]int{"a":{1}}) 62 | re5 := typeName2([]float32{1.2}) 63 | fmt.Println("typeswitch", re, re2, re3, re4, re5) 64 | assert(re == "int") 65 | assert(re5 == "unknown") 66 | 67 | test_ts_in_fmt() 68 | 69 | } -------------------------------------------------------------------------------- /std/math/nextafter.go: -------------------------------------------------------------------------------- 1 | // Copyright 2010 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package math 6 | 7 | // Nextafter32 returns the next representable float32 value after x towards y. 8 | // 9 | // Special cases are: 10 | // Nextafter32(x, x) = x 11 | // Nextafter32(NaN, y) = NaN 12 | // Nextafter32(x, NaN) = NaN 13 | func Nextafter32(x, y float32) (r float32) { 14 | switch { 15 | case IsNaN(float64(x)) || IsNaN(float64(y)): // special case 16 | r = float32(NaN()) 17 | case x == y: 18 | r = x 19 | case x == 0: 20 | r = float32(Copysign(float64(Float32frombits(1)), float64(y))) 21 | case (y > x) == (x > 0): 22 | r = Float32frombits(Float32bits(x) + 1) 23 | default: 24 | r = Float32frombits(Float32bits(x) - 1) 25 | } 26 | return 27 | } 28 | 29 | // Nextafter returns the next representable float64 value after x towards y. 30 | // 31 | // Special cases are: 32 | // Nextafter(x, x) = x 33 | // Nextafter(NaN, y) = NaN 34 | // Nextafter(x, NaN) = NaN 35 | func Nextafter(x, y float64) (r float64) { 36 | switch { 37 | case IsNaN(x) || IsNaN(y): // special case 38 | r = NaN() 39 | case x == y: 40 | r = x 41 | case x == 0: 42 | r = Copysign(Float64frombits(1), y) 43 | case (y > x) == (x > 0): 44 | r = Float64frombits(Float64bits(x) + 1) 45 | default: 46 | r = Float64frombits(Float64bits(x) - 1) 47 | } 48 | return 49 | } 50 | -------------------------------------------------------------------------------- /std/math/pow10.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package math 6 | 7 | // pow10tab stores the pre-computed values 10**i for i < 32. 8 | var pow10tab = [...]float64{ 9 | 1e00, 1e01, 1e02, 1e03, 1e04, 1e05, 1e06, 1e07, 1e08, 1e09, 10 | 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 11 | 1e20, 1e21, 1e22, 1e23, 1e24, 1e25, 1e26, 1e27, 1e28, 1e29, 12 | 1e30, 1e31, 13 | } 14 | 15 | // pow10postab32 stores the pre-computed value for 10**(i*32) at index i. 16 | var pow10postab32 = [...]float64{ 17 | 1e00, 1e32, 1e64, 1e96, 1e128, 1e160, 1e192, 1e224, 1e256, 1e288, 18 | } 19 | 20 | // pow10negtab32 stores the pre-computed value for 10**(-i*32) at index i. 21 | var pow10negtab32 = [...]float64{ 22 | 1e-00, 1e-32, 1e-64, 1e-96, 1e-128, 1e-160, 1e-192, 1e-224, 1e-256, 1e-288, 1e-320, 23 | } 24 | 25 | // Pow10 returns 10**n, the base-10 exponential of n. 26 | // 27 | // Special cases are: 28 | // Pow10(n) = 0 for n < -323 29 | // Pow10(n) = +Inf for n > 308 30 | func Pow10(n int) float64 { 31 | if 0 <= n && n <= 308 { 32 | return pow10postab32[uint(n)/32] * pow10tab[uint(n)%32] 33 | } 34 | 35 | if -323 <= n && n <= 0 { 36 | return pow10negtab32[uint(-n)/32] / pow10tab[uint(-n)%32] 37 | } 38 | 39 | // n < -323 || 308 < n 40 | if n > 0 { 41 | return Inf(1) 42 | } 43 | 44 | // n < -323 45 | return 0 46 | } 47 | -------------------------------------------------------------------------------- /types/tests/data/importC.src: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package importC 6 | 7 | import "C" 8 | import _ /* ERROR cannot rename import "C" */ "C" 9 | import foo /* ERROR cannot rename import "C" */ "C" 10 | import . /* ERROR cannot rename import "C" */ "C" 11 | 12 | // Test cases extracted from issue #22090. 13 | 14 | import "unsafe" 15 | 16 | const _ C.int = 0xff // no error due to invalid constant type 17 | 18 | type T struct { 19 | Name string 20 | Ordinal int 21 | } 22 | 23 | func _(args []T) { 24 | var s string 25 | for i, v := range args { 26 | cname := C.CString(v.Name) 27 | args[i].Ordinal = int(C.sqlite3_bind_parameter_index(s, cname)) // no error due to i not being "used" 28 | C.free(unsafe.Pointer(cname)) 29 | } 30 | } 31 | 32 | type CType C.Type 33 | 34 | const _ CType = C.X // no error due to invalid constant type 35 | const _ = C.X 36 | 37 | // Test cases extracted from issue #23712. 38 | 39 | func _() { 40 | var a [C.ArrayLength]byte 41 | _ = a[0] // no index out of bounds error here 42 | } 43 | 44 | // Additional tests to verify fix for #23712. 45 | 46 | func _() { 47 | var a [C.ArrayLength1]byte 48 | _ = 1 / len(a) // no division by zero error here and below 49 | _ = 1 / cap(a) 50 | _ = uint(unsafe.Sizeof(a)) // must not be negative 51 | 52 | var b [C.ArrayLength2]byte 53 | a = b // should be valid 54 | } 55 | -------------------------------------------------------------------------------- /std/sync/once.gos: -------------------------------------------------------------------------------- 1 | // Adapted from Go. 2 | 3 | // Copyright 2009 The Go Authors. All rights reserved. 4 | // Use of this source code is governed by a BSD-style 5 | // license that can be found in the LICENSE file. 6 | 7 | package sync 8 | 9 | // Once is an object that will perform exactly one action. 10 | type Once struct { 11 | m Mutex 12 | done bool 13 | } 14 | 15 | // Do calls the function f if and only if Do is being called for the 16 | // first time for this instance of Once. In other words, given 17 | // var once Once 18 | // if once.Do(f) is called multiple times, only the first call will invoke f, 19 | // even if f has a different value in each invocation. A new instance of 20 | // Once is required for each function to execute. 21 | // 22 | // Do is intended for initialization that must be run exactly once. Since f 23 | // is niladic, it may be necessary to use a function literal to capture the 24 | // arguments to a function to be invoked by Do: 25 | // config.once.Do(func() { config.init(filename) }) 26 | // 27 | // Because no call to Do returns until the one call to f returns, if f causes 28 | // Do to be called, it will deadlock. 29 | // 30 | // If f panics, Do considers it to have returned; future calls of Do return 31 | // without calling f. 32 | // 33 | func (o *Once) Do(f func()) { 34 | if o.done { 35 | return 36 | } 37 | // Slow-path. 38 | o.m.Lock() 39 | defer o.m.Unlock() 40 | if !o.done { 41 | defer func () { 42 | o.done = true 43 | }() 44 | f() 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /std/sort/slice.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build !compiler_bootstrap go1.8 6 | 7 | package sort 8 | 9 | import "reflect" 10 | 11 | // Slice sorts the provided slice given the provided less function. 12 | // 13 | // The sort is not guaranteed to be stable. For a stable sort, use 14 | // SliceStable. 15 | // 16 | // The function panics if the provided interface is not a slice. 17 | func Slice(slice interface{}, less func(i, j int) bool) { 18 | rv := reflect.ValueOf(slice) 19 | swap := reflect.Swapper(slice) 20 | length := rv.Len() 21 | quickSort_func(lessSwap{less, swap}, 0, length, maxDepth(length)) 22 | } 23 | 24 | // SliceStable sorts the provided slice given the provided less 25 | // function while keeping the original order of equal elements. 26 | // 27 | // The function panics if the provided interface is not a slice. 28 | func SliceStable(slice interface{}, less func(i, j int) bool) { 29 | rv := reflect.ValueOf(slice) 30 | swap := reflect.Swapper(slice) 31 | stable_func(lessSwap{less, swap}, rv.Len()) 32 | } 33 | 34 | // SliceIsSorted tests whether a slice is sorted. 35 | // 36 | // The function panics if the provided interface is not a slice. 37 | func SliceIsSorted(slice interface{}, less func(i, j int) bool) bool { 38 | rv := reflect.ValueOf(slice) 39 | n := rv.Len() 40 | for i := n - 1; i > 0; i-- { 41 | if less(i, i-1) { 42 | return false 43 | } 44 | } 45 | return true 46 | } 47 | -------------------------------------------------------------------------------- /types/tests/data/issue28251.src: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // This file contains test cases for various forms of 6 | // method receiver declarations, per the spec clarification 7 | // https://golang.org/cl/142757. 8 | 9 | package issue28251 10 | 11 | // test case from issue28251 12 | type T struct{} 13 | 14 | type T0 = *T 15 | 16 | func (T0) m() {} 17 | 18 | func _() { (&T{}).m() } 19 | 20 | // various alternative forms 21 | type ( 22 | T1 = (((T))) 23 | ) 24 | 25 | func ((*(T1))) m1() {} 26 | func _() { (T{}).m2() } 27 | func _() { (&T{}).m2() } 28 | 29 | type ( 30 | T2 = (((T3))) 31 | T3 = T 32 | ) 33 | 34 | func (T2) m2() {} 35 | func _() { (T{}).m2() } 36 | func _() { (&T{}).m2() } 37 | 38 | type ( 39 | T4 = ((*(T5))) 40 | T5 = T 41 | ) 42 | 43 | func (T4) m4() {} 44 | func _() { (T{}).m4 /* ERROR m4 is not in method set of T */ () } 45 | func _() { (&T{}).m4() } 46 | 47 | type ( 48 | T6 = (((T7))) 49 | T7 = (*(T8)) 50 | T8 = T 51 | ) 52 | 53 | func (T6) m6() {} 54 | func _() { (T{}).m6 /* ERROR m6 is not in method set of T */ () } 55 | func _() { (&T{}).m6() } 56 | 57 | type ( 58 | T9 = *T10 59 | T10 = *T11 60 | T11 = T 61 | ) 62 | 63 | func (T9 /* ERROR invalid receiver \*\*T */ ) m9() {} 64 | func _() { (T{}).m9 /* ERROR has no field or method m9 */ () } 65 | func _() { (&T{}).m9 /* ERROR has no field or method m9 */ () } 66 | -------------------------------------------------------------------------------- /types/tests/data/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009 The Go Authors. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Google Inc. nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /engine/src/vfs/vfs_map.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Goscript Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | use crate::vfs::VirtualFs; 6 | use go_parser::Map; 7 | use std::borrow::Cow; 8 | use std::io; 9 | use std::path::{Path, PathBuf}; 10 | 11 | pub struct VfsMap { 12 | map: Map>, 13 | } 14 | 15 | impl VfsMap { 16 | pub fn new(map: Map>) -> VfsMap { 17 | VfsMap { map } 18 | } 19 | } 20 | 21 | impl VirtualFs for VfsMap { 22 | fn read_file(&self, path: &Path) -> io::Result { 23 | self.map 24 | .get(path) 25 | .map(|x| x.to_string()) 26 | .ok_or(io::Error::from(io::ErrorKind::NotFound)) 27 | } 28 | 29 | fn read_dir(&self, path: &Path) -> io::Result> { 30 | let result: Vec = self 31 | .map 32 | .iter() 33 | .filter_map(|(p, _)| p.starts_with(path).then(|| p.to_path_buf())) 34 | .collect(); 35 | if result.is_empty() { 36 | Err(io::Error::from(io::ErrorKind::NotFound)) 37 | } else { 38 | Ok(result) 39 | } 40 | } 41 | 42 | fn is_file(&self, path: &Path) -> bool { 43 | path.extension().is_some() 44 | } 45 | 46 | fn is_dir(&self, path: &Path) -> bool { 47 | path.extension().is_none() 48 | } 49 | 50 | fn canonicalize_path(&self, path: &PathBuf) -> io::Result { 51 | Ok(path.clone()) 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /engine/tests/std/path.gos: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "path" 5 | ) 6 | 7 | type PathTest struct { 8 | path, result string 9 | } 10 | 11 | var cleantests = []PathTest{ 12 | // Already clean 13 | {"", "."}, 14 | {"abc", "abc"}, 15 | {"abc/def", "abc/def"}, 16 | {"a/b/c", "a/b/c"}, 17 | {".", "."}, 18 | {"..", ".."}, 19 | {"../..", "../.."}, 20 | {"../../abc", "../../abc"}, 21 | {"/abc", "/abc"}, 22 | {"/", "/"}, 23 | 24 | // Remove trailing slash 25 | {"abc/", "abc"}, 26 | {"abc/def/", "abc/def"}, 27 | {"a/b/c/", "a/b/c"}, 28 | {"./", "."}, 29 | {"../", ".."}, 30 | {"../../", "../.."}, 31 | {"/abc/", "/abc"}, 32 | 33 | // Remove doubled slash 34 | {"abc//def//ghi", "abc/def/ghi"}, 35 | {"//abc", "/abc"}, 36 | {"///abc", "/abc"}, 37 | {"//abc//", "/abc"}, 38 | {"abc//", "abc"}, 39 | 40 | // Remove . elements 41 | {"abc/./def", "abc/def"}, 42 | {"/./abc/def", "/abc/def"}, 43 | {"abc/.", "abc"}, 44 | 45 | // Remove .. elements 46 | {"abc/def/ghi/../jkl", "abc/def/jkl"}, 47 | {"abc/def/../ghi/../jkl", "abc/jkl"}, 48 | {"abc/def/..", "abc"}, 49 | {"abc/def/../..", "."}, 50 | {"/abc/def/../..", "/"}, 51 | {"abc/def/../../..", ".."}, 52 | {"/abc/def/../../..", "/"}, 53 | {"abc/def/../../../ghi/jkl/../../../mno", "../../mno"}, 54 | 55 | // Combinations 56 | {"abc/./../def", "def"}, 57 | {"abc//./../def", "def"}, 58 | {"abc/../../././../def", "../../def"}, 59 | } 60 | 61 | func main() { 62 | 63 | for _, test := range cleantests { 64 | assert(path.Clean(test.path) == test.result) 65 | assert(path.Clean(test.result) == test.result) 66 | } 67 | 68 | } -------------------------------------------------------------------------------- /std/internal/bytealg/bytealg.gos: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Goscript Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package bytealg 6 | 7 | // todo: implement these in native code 8 | 9 | 10 | func IndexByte(b []byte, c byte) int { 11 | for i, x := range b { 12 | if x == c { 13 | return i 14 | } 15 | } 16 | return -1 17 | } 18 | 19 | func IndexByteString(s string, c byte) int { 20 | for i := 0; i < len(s); i++ { 21 | if s[i] == c { 22 | return i 23 | } 24 | } 25 | return -1 26 | } 27 | 28 | func Count(b []byte, c byte) int { 29 | n := 0 30 | for _, x := range b { 31 | if x == c { 32 | n++ 33 | } 34 | } 35 | return n 36 | } 37 | 38 | func CountString(s string, c byte) int { 39 | n := 0 40 | for i := 0; i < len(s); i++ { 41 | if s[i] == c { 42 | n++ 43 | } 44 | } 45 | return n 46 | } 47 | 48 | 49 | func Compare(a, b []byte) int { 50 | l := len(a) 51 | if len(b) < l { 52 | l = len(b) 53 | } 54 | if l == 0 || &a[0] == &b[0] { 55 | goto samebytes 56 | } 57 | for i := 0; i < l; i++ { 58 | c1, c2 := a[i], b[i] 59 | if c1 < c2 { 60 | return -1 61 | } 62 | if c1 > c2 { 63 | return +1 64 | } 65 | } 66 | samebytes: 67 | if len(a) < len(b) { 68 | return -1 69 | } 70 | if len(a) > len(b) { 71 | return +1 72 | } 73 | return 0 74 | } 75 | 76 | func Equal(a, b []byte) bool { 77 | l := len(a) 78 | if len(b) != l { 79 | return false 80 | } 81 | for i := 0; i < l; i++ { 82 | if a[i] != b[i] { 83 | return false 84 | } 85 | } 86 | return true 87 | } 88 | -------------------------------------------------------------------------------- /engine/tests/group1/composite.gos: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt2" 5 | ) 6 | 7 | 8 | type Point3D struct { x, y, z int } 9 | type Point3Df struct { x, y, z float32 } 10 | 11 | type acceptRange struct { 12 | lo uint8 13 | hi uint8 14 | } 15 | 16 | var t = [16]Point3D{{1,2,3},{y:4}} 17 | 18 | 19 | var acceptRanges = [16]acceptRange{ 20 | 0: {1, 2}, 21 | 1: {1, 2}, 22 | 2: {1, 0x9F}, 23 | 3: {0x90, 1}, 24 | 4: {1, 0x8F}, 25 | } 26 | 27 | 28 | func withInterface() { 29 | m := []interface{}{"a string", 1, 2.04, []int{1, 2, 3, 4}} 30 | get_string := m[0] 31 | fmt2.Println(get_string) 32 | get_num := m[1] 33 | fmt2.Println(get_num) 34 | get_float := m[2] 35 | fmt2.Println(get_float) 36 | 37 | get_array := m[3] 38 | fmt2.Println(get_array) 39 | } 40 | 41 | 42 | func main() { 43 | 44 | var p = Point3D{8,9,10} 45 | assert(p.x == 8) 46 | 47 | var p2 = Point3D{y:88} 48 | assert(p2.y == 88) 49 | 50 | var s = []Point3D{{1,2,3},{y:4}} 51 | fmt2.Println(s[0].x, s[0].y, s[0].z, s[1].x, s[1].y, s[1].z) 52 | 53 | assert(s[0].z == 3) 54 | assert(s[1].y == 4) 55 | 56 | var pf = Point3Df{1.1,20000000000000000000,3} 57 | assert(pf.x == 1.1) 58 | 59 | var t2 = []acceptRange{10:{1,1}, {2,2}, 1:{3,3}} 60 | fmt2.Println(t2) 61 | assert(t2[0].lo == 0) 62 | assert(t2[1].lo == 3) 63 | assert(t2[11].lo == 2) 64 | assert(len(t2) == 12) 65 | 66 | var t3 = []acceptRange{1:{1,1}, {2,2}, 10:{3,3}} 67 | fmt2.Println(t3) 68 | assert(t3[0].lo == 0) 69 | assert(t3[1].lo == 1) 70 | assert(t3[2].lo == 2) 71 | assert(len(t3) == 11) 72 | 73 | 74 | withInterface() 75 | } 76 | -------------------------------------------------------------------------------- /types/tests/data/cycles2.gos: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package p 6 | 7 | import "unsafe" 8 | 9 | // Test case for issue 5090 10 | 11 | type t interface { 12 | f(u) 13 | } 14 | 15 | type u interface { 16 | t 17 | } 18 | 19 | func _() { 20 | var t t 21 | var u u 22 | 23 | t.f(t) 24 | t.f(u) 25 | 26 | u.f(t) 27 | u.f(u) 28 | } 29 | 30 | 31 | // Test case for issue 6589. 32 | 33 | type A interface { 34 | a() interface { 35 | AB 36 | } 37 | } 38 | 39 | type B interface { 40 | a() interface { 41 | AB 42 | } 43 | } 44 | 45 | type AB interface { 46 | a() interface { 47 | A 48 | B /* ERROR a redeclared */ 49 | } 50 | b() interface { 51 | A 52 | B /* ERROR a redeclared */ 53 | } 54 | } 55 | 56 | var x AB 57 | var y interface { 58 | A 59 | B /* ERROR a redeclared */ 60 | } 61 | var _ = x /* ERROR cannot compare */ == y 62 | 63 | 64 | // Test case for issue 6638. 65 | 66 | type T interface { 67 | //m() [T /*ERROR no value */ (nil).m()[0]]int 68 | } 69 | 70 | // Variations of this test case. 71 | 72 | type T1 /* ERROR cycle */ interface { 73 | m() [x1.m()[0]]int 74 | } 75 | 76 | var x1 T1 77 | 78 | type T2 /* ERROR cycle */ interface { 79 | m() [len(x2.m())]int 80 | } 81 | 82 | var x2 T2 83 | 84 | type T3 /* ERROR cycle */ interface { 85 | m() [unsafe.Sizeof(x3.m)]int 86 | } 87 | 88 | var x3 T3 89 | 90 | type T4 /* ERROR cycle */ interface { 91 | m() [unsafe.Sizeof(cast4(x4.m))]int // cast is invalid but we have a cycle, so all bets are off 92 | } 93 | 94 | var x4 T4 95 | var _ = cast4(x4.m) 96 | 97 | type cast4 func() 98 | -------------------------------------------------------------------------------- /parser/src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Goscript Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | //! This crate is part of the Goscript project. Please refer to for more information. 6 | //! 7 | //! It's a port of the the parser from the Go standard library 8 | //! 9 | //! # Usage: 10 | //! ``` 11 | //! fn parse_file() { 12 | //! let source = "package main ..."; 13 | //! let mut fs = go_parser::FileSet::new(); 14 | //! let o = &mut go_parser::AstObjects::new(); 15 | //! let el = &mut go_parser::ErrorList::new(); 16 | //! let (p, _) = go_parser::parse_file(o, &mut fs, el, "./main.go", source, false); 17 | //! print!("{}", p.get_errors()); 18 | //! } 19 | //! ``` 20 | //! 21 | //! # Feature 22 | //! - `btree_map`: Make it use BTreeMap instead of HashMap 23 | //! 24 | 25 | mod errors; 26 | mod map; 27 | mod objects; 28 | mod parser; 29 | mod position; 30 | mod scanner; 31 | mod token; 32 | 33 | pub mod ast; 34 | pub mod scope; 35 | pub mod visitor; 36 | 37 | pub use errors::*; 38 | pub use map::{Map, MapIter}; 39 | pub use objects::*; 40 | pub use parser::Parser; 41 | pub use position::*; 42 | pub use token::*; 43 | 44 | pub fn parse_file<'a>( 45 | o: &'a mut AstObjects, 46 | fs: &'a mut FileSet, 47 | el: &'a ErrorList, 48 | name: &str, 49 | src: &'a str, 50 | trace: bool, 51 | ) -> (parser::Parser<'a>, Option) { 52 | let f = fs.add_file(name.to_string(), None, src.chars().count()); 53 | let mut p = parser::Parser::new(o, f, el, src, trace); 54 | let file = p.parse_file(); 55 | (p, file) 56 | } 57 | -------------------------------------------------------------------------------- /engine/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "go-engine" 3 | version = "0.1.5" 4 | authors = ["oxfeeefeee "] 5 | edition = "2021" 6 | license = "BSD-2-Clause" 7 | repository = "https://github.com/oxfeeefeee/goscript/" 8 | keywords = ["golang", "goscript"] 9 | categories = ["scripting language", "programming language", "compiler"] 10 | description = "The wrapper of the Goscript project." 11 | 12 | [features] 13 | default = ["read_fs", "async", "go_std", "codegen", "instruction_pos"] 14 | read_fs = [] 15 | read_zip = ["dep:zip"] 16 | async = ["go-codegen/async", "go-vm/async"] 17 | go_std = [] 18 | btree_map = ["go-parser/btree_map", "go-codegen/btree_map", "go-vm/btree_map"] 19 | codegen = [] 20 | instruction_pos = ["go-vm/instruction_pos"] 21 | serde_borsh = ["dep:borsh", "go-vm/serde_borsh"] 22 | wasm = ["dep:wasm-bindgen", "dep:instant", "dep:getrandom"] 23 | 24 | [dependencies] 25 | futures-lite = "1.12.0" 26 | lazy_static = "1.4.0" 27 | zip = { version = "0.6.2", features = ["deflate"], default-features = false, optional = true } 28 | borsh = { version ="0.10.3", optional = true } 29 | 30 | wasm-bindgen = { version = "0.2.84", optional = true } 31 | instant = { version = "0.1", features = ["wasm-bindgen"], optional = true } 32 | getrandom = { version = "0.2", features = ["js"], optional = true } 33 | 34 | go-parser = { version = "0.1.5", path = "../parser" } 35 | go-vm = { version = "0.1.5", path = "../vm" } 36 | go-types = { version = "0.1.5", path = "../types" } 37 | go-codegen = { version = "0.1.5", path = "../codegen" } 38 | go-pmacro = { version = "0.1.5", path = "../pmacro" } 39 | 40 | [dev-dependencies] 41 | time-test = "0.2.2" 42 | criterion = "0.3" 43 | 44 | [[bench]] 45 | name = "leet5_benchmark" 46 | harness = false 47 | 48 | -------------------------------------------------------------------------------- /std/math/atan2.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package math 6 | 7 | // Atan2 returns the arc tangent of y/x, using 8 | // the signs of the two to determine the quadrant 9 | // of the return value. 10 | // 11 | // Special cases are (in order): 12 | // Atan2(y, NaN) = NaN 13 | // Atan2(NaN, x) = NaN 14 | // Atan2(+0, x>=0) = +0 15 | // Atan2(-0, x>=0) = -0 16 | // Atan2(+0, x<=-0) = +Pi 17 | // Atan2(-0, x<=-0) = -Pi 18 | // Atan2(y>0, 0) = +Pi/2 19 | // Atan2(y<0, 0) = -Pi/2 20 | // Atan2(+Inf, +Inf) = +Pi/4 21 | // Atan2(-Inf, +Inf) = -Pi/4 22 | // Atan2(+Inf, -Inf) = 3Pi/4 23 | // Atan2(-Inf, -Inf) = -3Pi/4 24 | // Atan2(y, +Inf) = 0 25 | // Atan2(y>0, -Inf) = +Pi 26 | // Atan2(y<0, -Inf) = -Pi 27 | // Atan2(+Inf, x) = +Pi/2 28 | // Atan2(-Inf, x) = -Pi/2 29 | func Atan2(y, x float64) float64 { 30 | // special cases 31 | switch { 32 | case IsNaN(y) || IsNaN(x): 33 | return NaN() 34 | case y == 0: 35 | if x >= 0 && !Signbit(x) { 36 | return Copysign(0, y) 37 | } 38 | return Copysign(Pi, y) 39 | case x == 0: 40 | return Copysign(Pi/2, y) 41 | case IsInf(x, 0): 42 | if IsInf(x, 1) { 43 | switch { 44 | case IsInf(y, 0): 45 | return Copysign(Pi/4, y) 46 | default: 47 | return Copysign(0, y) 48 | } 49 | } 50 | switch { 51 | case IsInf(y, 0): 52 | return Copysign(3*Pi/4, y) 53 | default: 54 | return Copysign(Pi, y) 55 | } 56 | case IsInf(y, 0): 57 | return Copysign(Pi/2, y) 58 | } 59 | 60 | // Call atan and determine the quadrant. 61 | q := Atan(y / x) 62 | if x < 0 { 63 | if q <= 0 { 64 | return q + Pi 65 | } 66 | return q - Pi 67 | } 68 | return q 69 | } 70 | -------------------------------------------------------------------------------- /parser/tests/parser_test.rs: -------------------------------------------------------------------------------- 1 | extern crate go_parser as fe; 2 | use std::fs; 3 | 4 | fn load_parse(path: &str, trace: bool) -> usize { 5 | let mut fs = fe::FileSet::new(); 6 | let src = fs::read_to_string(path).expect("read file err: "); 7 | let o = &mut fe::AstObjects::new(); 8 | let el = &mut fe::ErrorList::new(); 9 | let (p, _) = fe::parse_file(o, &mut fs, el, path, &src, trace); 10 | 11 | print!("{}", p.get_errors()); 12 | 13 | let l = p.get_errors().len(); 14 | l 15 | } 16 | 17 | #[test] 18 | fn test_parser_case0() { 19 | load_parse("./../../go/src/archive/tar/strconv_test.go", true); 20 | } 21 | 22 | #[test] 23 | fn test_parser_case1() { 24 | let err_cnt = load_parse("./tests/data/case1.gos", true); 25 | dbg!(err_cnt); 26 | } 27 | 28 | // fn parse_dir(s: &str, trace: bool) -> usize { 29 | // let mut total = 0; 30 | // let paths = fs::read_dir(s).unwrap(); 31 | // for path in paths { 32 | // let p0 = path.unwrap().path(); 33 | // if p0.is_dir() { 34 | // total += parse_dir(p0.to_str().unwrap(), trace); 35 | // } 36 | // let p = p0.to_str().unwrap(); 37 | // if p.ends_with(".go") { 38 | // println!("Name: {}", p); 39 | // total += load_parse(p, trace); 40 | // } 41 | // } 42 | // total 43 | // } 44 | 45 | // #[test] 46 | // fn test_parser_dir() { 47 | // let t = parse_dir("./../../go/src", false); 48 | // //let t = parse_dir("./../../../../go/src/github.com/ethereum", false); 49 | // println!("hohohoh{}", t); 50 | // } 51 | 52 | #[test] 53 | fn test_issue3() { 54 | let mut fs = fe::FileSet::new(); 55 | let o = &mut fe::AstObjects::new(); 56 | let el = &mut fe::ErrorList::new(); 57 | let (p, _) = fe::parse_file(o, &mut fs, el, "/a", "`", false); 58 | print!("{}", p.get_errors()); 59 | } 60 | -------------------------------------------------------------------------------- /std/math/dim.go: -------------------------------------------------------------------------------- 1 | // Copyright 2010 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package math 6 | 7 | // Dim returns the maximum of x-y or 0. 8 | // 9 | // Special cases are: 10 | // Dim(+Inf, +Inf) = NaN 11 | // Dim(-Inf, -Inf) = NaN 12 | // Dim(x, NaN) = Dim(NaN, x) = NaN 13 | func Dim(x, y float64) float64 { 14 | // The special cases result in NaN after the subtraction: 15 | // +Inf - +Inf = NaN 16 | // -Inf - -Inf = NaN 17 | // NaN - y = NaN 18 | // x - NaN = NaN 19 | v := x - y 20 | if v <= 0 { 21 | // v is negative or 0 22 | return 0 23 | } 24 | // v is positive or NaN 25 | return v 26 | } 27 | 28 | // Max returns the larger of x or y. 29 | // 30 | // Special cases are: 31 | // Max(x, +Inf) = Max(+Inf, x) = +Inf 32 | // Max(x, NaN) = Max(NaN, x) = NaN 33 | // Max(+0, ±0) = Max(±0, +0) = +0 34 | // Max(-0, -0) = -0 35 | func Max(x, y float64) float64 { 36 | // special cases 37 | switch { 38 | case IsInf(x, 1) || IsInf(y, 1): 39 | return Inf(1) 40 | case IsNaN(x) || IsNaN(y): 41 | return NaN() 42 | case x == 0 && x == y: 43 | if Signbit(x) { 44 | return y 45 | } 46 | return x 47 | } 48 | if x > y { 49 | return x 50 | } 51 | return y 52 | } 53 | 54 | // Min returns the smaller of x or y. 55 | // 56 | // Special cases are: 57 | // Min(x, -Inf) = Min(-Inf, x) = -Inf 58 | // Min(x, NaN) = Min(NaN, x) = NaN 59 | // Min(-0, ±0) = Min(±0, -0) = -0 60 | func Min(x, y float64) float64 61 | 62 | func min(x, y float64) float64 { 63 | // special cases 64 | switch { 65 | case IsInf(x, -1) || IsInf(y, -1): 66 | return Inf(-1) 67 | case IsNaN(x) || IsNaN(y): 68 | return NaN() 69 | case x == 0 && x == y: 70 | if Signbit(x) { 71 | return x 72 | } 73 | return y 74 | } 75 | if x < y { 76 | return x 77 | } 78 | return y 79 | } 80 | -------------------------------------------------------------------------------- /std/math/sinh.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package math 6 | 7 | /* 8 | Floating-point hyperbolic sine and cosine. 9 | 10 | The exponential func is called for arguments 11 | greater in magnitude than 0.5. 12 | 13 | A series is used for arguments smaller in magnitude than 0.5. 14 | 15 | Cosh(x) is computed from the exponential func for 16 | all arguments. 17 | */ 18 | 19 | // Sinh returns the hyperbolic sine of x. 20 | // 21 | // Special cases are: 22 | // Sinh(±0) = ±0 23 | // Sinh(±Inf) = ±Inf 24 | // Sinh(NaN) = NaN 25 | func Sinh(x float64) float64 { 26 | // The coefficients are #2029 from Hart & Cheney. (20.36D) 27 | const ( 28 | P0 = -0.6307673640497716991184787251e+6 29 | P1 = -0.8991272022039509355398013511e+5 30 | P2 = -0.2894211355989563807284660366e+4 31 | P3 = -0.2630563213397497062819489e+2 32 | Q0 = -0.6307673640497716991212077277e+6 33 | Q1 = 0.1521517378790019070696485176e+5 34 | Q2 = -0.173678953558233699533450911e+3 35 | ) 36 | 37 | sign := false 38 | if x < 0 { 39 | x = -x 40 | sign = true 41 | } 42 | 43 | var temp float64 44 | switch { 45 | case x > 21: 46 | temp = Exp(x) * 0.5 47 | 48 | case x > 0.5: 49 | ex := Exp(x) 50 | temp = (ex - 1/ex) * 0.5 51 | 52 | default: 53 | sq := x * x 54 | temp = (((P3*sq+P2)*sq+P1)*sq + P0) * x 55 | temp = temp / (((sq+Q2)*sq+Q1)*sq + Q0) 56 | } 57 | 58 | if sign { 59 | temp = -temp 60 | } 61 | return temp 62 | } 63 | 64 | // Cosh returns the hyperbolic cosine of x. 65 | // 66 | // Special cases are: 67 | // Cosh(±0) = 1 68 | // Cosh(±Inf) = +Inf 69 | // Cosh(NaN) = NaN 70 | func Cosh(x float64) float64 71 | 72 | func cosh(x float64) float64 { 73 | x = Abs(x) 74 | if x > 21 { 75 | return Exp(x) * 0.5 76 | } 77 | ex := Exp(x) 78 | return (ex + 1/ex) * 0.5 79 | } 80 | -------------------------------------------------------------------------------- /engine/tests/group1/pkg.gos: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | 4 | import ( 5 | . "fmt2" 6 | ) 7 | 8 | 9 | const k = i + 1 10 | 11 | const i = 7 12 | 13 | var b = a + k 14 | var a = 8 15 | 16 | 17 | 18 | type Kind uint 19 | 20 | const ( 21 | Invalid Kind = iota 22 | Bool 23 | Int 24 | Int8 25 | Int16 26 | Int32 27 | Int64 28 | Uint 29 | Uint8 30 | Uint16 31 | Uint32 32 | Uint64 33 | Uintptr 34 | Float32 35 | Float64 36 | Complex64 37 | Complex128 38 | Array 39 | Chan 40 | Func 41 | Interface 42 | Map 43 | Ptr 44 | Slice 45 | String 46 | Struct 47 | UnsafePointer 48 | ) 49 | 50 | var kindNames = []string{ 51 | Invalid: "invalid", 52 | Bool: "bool", 53 | Int: "int", 54 | Int8: "int8", 55 | Int16: "int16", 56 | Int32: "int32", 57 | Int64: "int64", 58 | Uint: "uint", 59 | Uint8: "uint8", 60 | Uint16: "uint16", 61 | Uint32: "uint32", 62 | Uint64: "uint64", 63 | Uintptr: "uintptr", 64 | Float32: "float32", 65 | Float64: "float64", 66 | Complex64: "complex64", 67 | Complex128: "complex128", 68 | Array: "array", 69 | Chan: "chan", 70 | Func: "func", 71 | Interface: "interface", 72 | Map: "map", 73 | Ptr: "ptr", 74 | Slice: "slice", 75 | String: "string", 76 | Struct: "struct", 77 | UnsafePointer: "unsafe.Pointer", 78 | } 79 | 80 | func test1() { 81 | _, j := fa() 82 | assert(j == 7) 83 | 84 | assert(kindNames[2] == "int") 85 | } 86 | 87 | func fa () (int, int) { 88 | assert(8 == fb()) 89 | return 6,7 90 | } 91 | 92 | func fb() int { 93 | return 8 94 | } 95 | 96 | func test2() { 97 | Println("Hello, World!") 98 | } 99 | 100 | func main() { 101 | test1() 102 | test2() 103 | } 104 | -------------------------------------------------------------------------------- /types/tests/data/init1.src: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // initialization cycles 6 | 7 | package init1 8 | 9 | // issue 6683 (marked as WorkingAsIntended) 10 | 11 | type T0 struct{} 12 | 13 | func (T0) m() int { return y0 } 14 | 15 | var x0 = T0{} 16 | 17 | var y0 /* ERROR initialization cycle */ = x0.m() 18 | 19 | type T1 struct{} 20 | 21 | func (T1) m() int { return y1 } 22 | 23 | var x1 interface { 24 | m() int 25 | } = T1{} 26 | 27 | var y1 = x1.m() // no cycle reported, x1 is of interface type 28 | 29 | // issue 6703 (modified) 30 | 31 | var x2 /* ERROR initialization cycle */ = T2.m 32 | 33 | var y2 = x2 34 | 35 | type T2 struct{} 36 | 37 | func (T2) m() int { 38 | _ = y2 39 | return 0 40 | } 41 | 42 | var x3 /* ERROR initialization cycle */ = T3.m(T3{}) // <<<< added (T3{}) 43 | 44 | var y3 = x3 45 | 46 | type T3 struct{} 47 | 48 | func (T3) m() int { 49 | _ = y3 50 | return 0 51 | } 52 | 53 | var x4 /* ERROR initialization cycle */ = T4{}.m // <<<< added {} 54 | 55 | var y4 = x4 56 | 57 | type T4 struct{} 58 | 59 | func (T4) m() int { 60 | _ = y4 61 | return 0 62 | } 63 | 64 | var x5 /* ERROR initialization cycle */ = T5{}.m() // <<<< added () 65 | 66 | var y5 = x5 67 | 68 | type T5 struct{} 69 | 70 | func (T5) m() int { 71 | _ = y5 72 | return 0 73 | } 74 | 75 | // issue 4847 76 | // simplified test case 77 | 78 | var x6 = f6 79 | var y6 /* ERROR initialization cycle */ = f6 80 | func f6() { _ = y6 } 81 | 82 | // full test case 83 | 84 | type ( 85 | E int 86 | S int 87 | ) 88 | 89 | type matcher func(s *S) E 90 | 91 | func matchList(s *S) E { return matcher(matchAnyFn)(s) } 92 | 93 | var foo = matcher(matchList) 94 | 95 | var matchAny /* ERROR initialization cycle */ = matcher(matchList) 96 | 97 | func matchAnyFn(s *S) (err E) { return matchAny(s) } -------------------------------------------------------------------------------- /std/math/cmplx/exp.go: -------------------------------------------------------------------------------- 1 | // Copyright 2010 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package cmplx 6 | 7 | import "math" 8 | 9 | // The original C code, the long comment, and the constants 10 | // below are from http://netlib.sandia.gov/cephes/c9x-complex/clog.c. 11 | // The go code is a simplified version of the original C. 12 | // 13 | // Cephes Math Library Release 2.8: June, 2000 14 | // Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier 15 | // 16 | // The readme file at http://netlib.sandia.gov/cephes/ says: 17 | // Some software in this archive may be from the book _Methods and 18 | // Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster 19 | // International, 1989) or from the Cephes Mathematical Library, a 20 | // commercial product. In either event, it is copyrighted by the author. 21 | // What you see here may be used freely but it comes with no support or 22 | // guarantee. 23 | // 24 | // The two known misprints in the book are repaired here in the 25 | // source listings for the gamma function and the incomplete beta 26 | // integral. 27 | // 28 | // Stephen L. Moshier 29 | // moshier@na-net.ornl.gov 30 | 31 | // Complex exponential function 32 | // 33 | // DESCRIPTION: 34 | // 35 | // Returns the complex exponential of the complex argument z. 36 | // 37 | // If 38 | // z = x + iy, 39 | // r = exp(x), 40 | // then 41 | // w = r cos y + i r sin y. 42 | // 43 | // ACCURACY: 44 | // 45 | // Relative error: 46 | // arithmetic domain # trials peak rms 47 | // DEC -10,+10 8700 3.7e-17 1.1e-17 48 | // IEEE -10,+10 30000 3.0e-16 8.7e-17 49 | 50 | // Exp returns e**x, the base-e exponential of x. 51 | func Exp(x complex128) complex128 { 52 | r := math.Exp(real(x)) 53 | s, c := math.Sincos(imag(x)) 54 | return complex(r*c, r*s) 55 | } 56 | -------------------------------------------------------------------------------- /std/math/acosh.go: -------------------------------------------------------------------------------- 1 | // Copyright 2010 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package math 6 | 7 | // The original C code, the long comment, and the constants 8 | // below are from FreeBSD's /usr/src/lib/msun/src/e_acosh.c 9 | // and came with this notice. The go code is a simplified 10 | // version of the original C. 11 | // 12 | // ==================================================== 13 | // Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. 14 | // 15 | // Developed at SunPro, a Sun Microsystems, Inc. business. 16 | // Permission to use, copy, modify, and distribute this 17 | // software is freely granted, provided that this notice 18 | // is preserved. 19 | // ==================================================== 20 | // 21 | // 22 | // __ieee754_acosh(x) 23 | // Method : 24 | // Based on 25 | // acosh(x) = log [ x + sqrt(x*x-1) ] 26 | // we have 27 | // acosh(x) := log(x)+ln2, if x is large; else 28 | // acosh(x) := log(2x-1/(sqrt(x*x-1)+x)) if x>2; else 29 | // acosh(x) := log1p(t+sqrt(2.0*t+t*t)); where t=x-1. 30 | // 31 | // Special cases: 32 | // acosh(x) is NaN with signal if x<1. 33 | // acosh(NaN) is NaN without signal. 34 | // 35 | 36 | // Acosh returns the inverse hyperbolic cosine of x. 37 | // 38 | // Special cases are: 39 | // Acosh(+Inf) = +Inf 40 | // Acosh(x) = NaN if x < 1 41 | // Acosh(NaN) = NaN 42 | func Acosh(x float64) float64 { 43 | const ( 44 | Ln2 = 6.93147180559945286227e-01 // 0x3FE62E42FEFA39EF 45 | Large = 1 << 28 // 2**28 46 | ) 47 | // first case is special case 48 | switch { 49 | case x < 1 || IsNaN(x): 50 | return NaN() 51 | case x == 1: 52 | return 0 53 | case x >= Large: 54 | return Log(x) + Ln2 // x > 2**28 55 | case x > 2: 56 | return Log(2*x - 1/(x+Sqrt(x*x-1))) // 2**28 > x > 2 57 | } 58 | t := x - 1 59 | return Log1p(t + Sqrt(2*t+t*t)) // 2 >= x > 1 60 | } 61 | -------------------------------------------------------------------------------- /std/time/tick.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package time 6 | 7 | import "errors" 8 | 9 | // A Ticker holds a channel that delivers `ticks' of a clock 10 | // at intervals. 11 | type Ticker struct { 12 | C <-chan Time // The channel on which the ticks are delivered. 13 | r runtimeTimer 14 | } 15 | 16 | // NewTicker returns a new Ticker containing a channel that will send the 17 | // time with a period specified by the duration argument. 18 | // It adjusts the intervals or drops ticks to make up for slow receivers. 19 | // The duration d must be greater than zero; if not, NewTicker will panic. 20 | // Stop the ticker to release associated resources. 21 | func NewTicker(d Duration) *Ticker { 22 | if d <= 0 { 23 | panic(errors.New("non-positive interval for NewTicker")) 24 | } 25 | // Give the channel a 1-element time buffer. 26 | // If the client falls behind while reading, we drop ticks 27 | // on the floor until the client catches up. 28 | c := make(chan Time, 1) 29 | t := &Ticker{ 30 | C: c, 31 | r: runtimeTimer{ 32 | when: when(d), 33 | period: int64(d), 34 | f: sendTime, 35 | arg: c, 36 | }, 37 | } 38 | startTimer(&t.r) 39 | return t 40 | } 41 | 42 | // Stop turns off a ticker. After Stop, no more ticks will be sent. 43 | // Stop does not close the channel, to prevent a concurrent goroutine 44 | // reading from the channel from seeing an erroneous "tick". 45 | func (t *Ticker) Stop() { 46 | stopTimer(&t.r) 47 | } 48 | 49 | // Tick is a convenience wrapper for NewTicker providing access to the ticking 50 | // channel only. While Tick is useful for clients that have no need to shut down 51 | // the Ticker, be aware that without a way to shut it down the underlying 52 | // Ticker cannot be recovered by the garbage collector; it "leaks". 53 | // Unlike NewTicker, Tick will return nil if d <= 0. 54 | func Tick(d Duration) <-chan Time { 55 | if d <= 0 { 56 | return nil 57 | } 58 | return NewTicker(d).C 59 | } 60 | -------------------------------------------------------------------------------- /std/math/sincos.go: -------------------------------------------------------------------------------- 1 | // Copyright 2010 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package math 6 | 7 | // Coefficients _sin[] and _cos[] are found in pkg/math/sin.go. 8 | 9 | // Sincos returns Sin(x), Cos(x). 10 | // 11 | // Special cases are: 12 | // Sincos(±0) = ±0, 1 13 | // Sincos(±Inf) = NaN, NaN 14 | // Sincos(NaN) = NaN, NaN 15 | func Sincos(x float64) (sin, cos float64) { 16 | const ( 17 | PI4A = 7.85398125648498535156E-1 // 0x3fe921fb40000000, Pi/4 split into three parts 18 | PI4B = 3.77489470793079817668E-8 // 0x3e64442d00000000, 19 | PI4C = 2.69515142907905952645E-15 // 0x3ce8469898cc5170, 20 | ) 21 | // special cases 22 | switch { 23 | case x == 0: 24 | return x, 1 // return ±0.0, 1.0 25 | case IsNaN(x) || IsInf(x, 0): 26 | return NaN(), NaN() 27 | } 28 | 29 | // make argument positive 30 | sinSign, cosSign := false, false 31 | if x < 0 { 32 | x = -x 33 | sinSign = true 34 | } 35 | 36 | var j uint64 37 | var y, z float64 38 | if x >= reduceThreshold { 39 | j, z = trigReduce(x) 40 | } else { 41 | j = uint64(x * (4 / Pi)) // integer part of x/(Pi/4), as integer for tests on the phase angle 42 | y = float64(j) // integer part of x/(Pi/4), as float 43 | 44 | if j&1 == 1 { // map zeros to origin 45 | j++ 46 | y++ 47 | } 48 | j &= 7 // octant modulo 2Pi radians (360 degrees) 49 | z = ((x - y*PI4A) - y*PI4B) - y*PI4C // Extended precision modular arithmetic 50 | } 51 | if j > 3 { // reflect in x axis 52 | j -= 4 53 | sinSign, cosSign = !sinSign, !cosSign 54 | } 55 | if j > 1 { 56 | cosSign = !cosSign 57 | } 58 | 59 | zz := z * z 60 | cos = 1.0 - 0.5*zz + zz*zz*((((((_cos[0]*zz)+_cos[1])*zz+_cos[2])*zz+_cos[3])*zz+_cos[4])*zz+_cos[5]) 61 | sin = z + z*zz*((((((_sin[0]*zz)+_sin[1])*zz+_sin[2])*zz+_sin[3])*zz+_sin[4])*zz+_sin[5]) 62 | if j == 1 || j == 2 { 63 | sin, cos = cos, sin 64 | } 65 | if cosSign { 66 | cos = -cos 67 | } 68 | if sinSign { 69 | sin = -sin 70 | } 71 | return 72 | } 73 | -------------------------------------------------------------------------------- /std/strconv/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package strconv implements conversions to and from string representations 6 | // of basic data types. 7 | // 8 | // Numeric Conversions 9 | // 10 | // The most common numeric conversions are Atoi (string to int) and Itoa (int to string). 11 | // 12 | // i, err := strconv.Atoi("-42") 13 | // s := strconv.Itoa(-42) 14 | // 15 | // These assume decimal and the Go int type. 16 | // 17 | // ParseBool, ParseFloat, ParseInt, and ParseUint convert strings to values: 18 | // 19 | // b, err := strconv.ParseBool("true") 20 | // f, err := strconv.ParseFloat("3.1415", 64) 21 | // i, err := strconv.ParseInt("-42", 10, 64) 22 | // u, err := strconv.ParseUint("42", 10, 64) 23 | // 24 | // The parse functions return the widest type (float64, int64, and uint64), 25 | // but if the size argument specifies a narrower width the result can be 26 | // converted to that narrower type without data loss: 27 | // 28 | // s := "2147483647" // biggest int32 29 | // i64, err := strconv.ParseInt(s, 10, 32) 30 | // ... 31 | // i := int32(i64) 32 | // 33 | // FormatBool, FormatFloat, FormatInt, and FormatUint convert values to strings: 34 | // 35 | // s := strconv.FormatBool(true) 36 | // s := strconv.FormatFloat(3.1415, 'E', -1, 64) 37 | // s := strconv.FormatInt(-42, 16) 38 | // s := strconv.FormatUint(42, 16) 39 | // 40 | // AppendBool, AppendFloat, AppendInt, and AppendUint are similar but 41 | // append the formatted value to a destination slice. 42 | // 43 | // String Conversions 44 | // 45 | // Quote and QuoteToASCII convert strings to quoted Go string literals. 46 | // The latter guarantees that the result is an ASCII string, by escaping 47 | // any non-ASCII Unicode with \u: 48 | // 49 | // q := strconv.Quote("Hello, 世界") 50 | // q := strconv.QuoteToASCII("Hello, 世界") 51 | // 52 | // QuoteRune and QuoteRuneToASCII are similar but accept runes and 53 | // return quoted Go rune literals. 54 | // 55 | // Unquote and UnquoteChar unquote Go string and rune literals. 56 | // 57 | package strconv 58 | -------------------------------------------------------------------------------- /std/math/asinh.go: -------------------------------------------------------------------------------- 1 | // Copyright 2010 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package math 6 | 7 | // The original C code, the long comment, and the constants 8 | // below are from FreeBSD's /usr/src/lib/msun/src/s_asinh.c 9 | // and came with this notice. The go code is a simplified 10 | // version of the original C. 11 | // 12 | // ==================================================== 13 | // Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. 14 | // 15 | // Developed at SunPro, a Sun Microsystems, Inc. business. 16 | // Permission to use, copy, modify, and distribute this 17 | // software is freely granted, provided that this notice 18 | // is preserved. 19 | // ==================================================== 20 | // 21 | // 22 | // asinh(x) 23 | // Method : 24 | // Based on 25 | // asinh(x) = sign(x) * log [ |x| + sqrt(x*x+1) ] 26 | // we have 27 | // asinh(x) := x if 1+x*x=1, 28 | // := sign(x)*(log(x)+ln2)) for large |x|, else 29 | // := sign(x)*log(2|x|+1/(|x|+sqrt(x*x+1))) if|x|>2, else 30 | // := sign(x)*log1p(|x| + x**2/(1 + sqrt(1+x**2))) 31 | // 32 | 33 | // Asinh returns the inverse hyperbolic sine of x. 34 | // 35 | // Special cases are: 36 | // Asinh(±0) = ±0 37 | // Asinh(±Inf) = ±Inf 38 | // Asinh(NaN) = NaN 39 | func Asinh(x float64) float64 { 40 | const ( 41 | Ln2 = 6.93147180559945286227e-01 // 0x3FE62E42FEFA39EF 42 | NearZero = 1.0 / (1 << 28) // 2**-28 43 | Large = 1 << 28 // 2**28 44 | ) 45 | // special cases 46 | if IsNaN(x) || IsInf(x, 0) { 47 | return x 48 | } 49 | sign := false 50 | if x < 0 { 51 | x = -x 52 | sign = true 53 | } 54 | var temp float64 55 | switch { 56 | case x > Large: 57 | temp = Log(x) + Ln2 // |x| > 2**28 58 | case x > 2: 59 | temp = Log(2*x + 1/(Sqrt(x*x+1)+x)) // 2**28 > |x| > 2.0 60 | case x < NearZero: 61 | temp = x // |x| < 2**-28 62 | default: 63 | temp = Log1p(x + x*x/(1+Sqrt(1+x*x))) // 2.0 > |x| > 2**-28 64 | } 65 | if sign { 66 | temp = -temp 67 | } 68 | return temp 69 | } 70 | -------------------------------------------------------------------------------- /std/math/bits.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package math 6 | 7 | const ( 8 | uvnan = 0x7FF8000000000001 9 | uvinf = 0x7FF0000000000000 10 | uvneginf = 0xFFF0000000000000 11 | uvone = 0x3FF0000000000000 12 | mask = 0x7FF 13 | shift = 64 - 11 - 1 14 | bias = 1023 15 | signMask = 1 << 63 16 | fracMask = 1<= 0, negative infinity if sign < 0. 20 | func Inf(sign int) float64 { 21 | var v uint64 22 | if sign >= 0 { 23 | v = uvinf 24 | } else { 25 | v = uvneginf 26 | } 27 | return Float64frombits(v) 28 | } 29 | 30 | // NaN returns an IEEE 754 ``not-a-number'' value. 31 | func NaN() float64 { return Float64frombits(uvnan) } 32 | 33 | // IsNaN reports whether f is an IEEE 754 ``not-a-number'' value. 34 | func IsNaN(f float64) (is bool) { 35 | // IEEE 754 says that only NaNs satisfy f != f. 36 | // To avoid the floating-point hardware, could use: 37 | // x := Float64bits(f); 38 | // return uint32(x>>shift)&mask == mask && x != uvinf && x != uvneginf 39 | return f != f 40 | } 41 | 42 | // IsInf reports whether f is an infinity, according to sign. 43 | // If sign > 0, IsInf reports whether f is positive infinity. 44 | // If sign < 0, IsInf reports whether f is negative infinity. 45 | // If sign == 0, IsInf reports whether f is either infinity. 46 | func IsInf(f float64, sign int) bool { 47 | // Test for infinity by comparing against maximum float. 48 | // To avoid the floating-point hardware, could use: 49 | // x := Float64bits(f); 50 | // return sign >= 0 && x == uvinf || sign <= 0 && x == uvneginf; 51 | return sign >= 0 && f > MaxFloat64 || sign <= 0 && f < -MaxFloat64 52 | } 53 | 54 | // normalize returns a normal number y and exponent exp 55 | // satisfying x == y × 2**exp. It assumes x is finite and non-zero. 56 | func normalize(x float64) (y float64, exp int) { 57 | const SmallestNormal = 2.2250738585072014e-308 // 2**-1022 58 | if Abs(x) < SmallestNormal { 59 | return x * (1 << 52), -52 60 | } 61 | return x, 0 62 | } 63 | -------------------------------------------------------------------------------- /std/math/rand/zipf.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // W.Hormann, G.Derflinger: 6 | // "Rejection-Inversion to Generate Variates 7 | // from Monotone Discrete Distributions" 8 | // http://eeyore.wu-wien.ac.at/papers/96-04-04.wh-der.ps.gz 9 | 10 | package rand 11 | 12 | import "math" 13 | 14 | // A Zipf generates Zipf distributed variates. 15 | type Zipf struct { 16 | r *Rand 17 | imax float64 18 | v float64 19 | q float64 20 | s float64 21 | oneminusQ float64 22 | oneminusQinv float64 23 | hxm float64 24 | hx0minusHxm float64 25 | } 26 | 27 | func (z *Zipf) h(x float64) float64 { 28 | return math.Exp(z.oneminusQ*math.Log(z.v+x)) * z.oneminusQinv 29 | } 30 | 31 | func (z *Zipf) hinv(x float64) float64 { 32 | return math.Exp(z.oneminusQinv*math.Log(z.oneminusQ*x)) - z.v 33 | } 34 | 35 | // NewZipf returns a Zipf variate generator. 36 | // The generator generates values k ∈ [0, imax] 37 | // such that P(k) is proportional to (v + k) ** (-s). 38 | // Requirements: s > 1 and v >= 1. 39 | func NewZipf(r *Rand, s float64, v float64, imax uint64) *Zipf { 40 | z := new(Zipf) 41 | if s <= 1.0 || v < 1 { 42 | return nil 43 | } 44 | z.r = r 45 | z.imax = float64(imax) 46 | z.v = v 47 | z.q = s 48 | z.oneminusQ = 1.0 - z.q 49 | z.oneminusQinv = 1.0 / z.oneminusQ 50 | z.hxm = z.h(z.imax + 0.5) 51 | z.hx0minusHxm = z.h(0.5) - math.Exp(math.Log(z.v)*(-z.q)) - z.hxm 52 | z.s = 1 - z.hinv(z.h(1.5)-math.Exp(-z.q*math.Log(z.v+1.0))) 53 | return z 54 | } 55 | 56 | // Uint64 returns a value drawn from the Zipf distribution described 57 | // by the Zipf object. 58 | func (z *Zipf) Uint64() uint64 { 59 | if z == nil { 60 | panic("rand: nil Zipf") 61 | } 62 | k := 0.0 63 | 64 | for { 65 | r := z.r.Float64() // r on [0,1] 66 | ur := z.hxm + r*z.hx0minusHxm 67 | x := z.hinv(ur) 68 | k = math.Floor(x + 0.5) 69 | if k-x <= z.s { 70 | break 71 | } 72 | if ur >= z.h(k+0.5)-math.Exp(-math.Log(k+z.v)*z.q) { 73 | break 74 | } 75 | } 76 | return uint64(k) 77 | } 78 | -------------------------------------------------------------------------------- /types/tests/data/conversions.gos: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // conversions 6 | 7 | package conversions 8 | 9 | import "unsafe" 10 | 11 | // argument count 12 | var ( 13 | _ = int() /* ERROR "missing argument" */ 14 | _ = int(1, 2 /* ERROR "too many arguments" */ ) 15 | ) 16 | 17 | // numeric constant conversions are in const1.src. 18 | 19 | func string_conversions() { 20 | const A = string(65) 21 | assert(A == "A") 22 | const E = string(-1) 23 | assert(E == "\uFFFD") 24 | assert(E == string(1234567890)) 25 | 26 | type myint int 27 | assert(A == string(myint(65))) 28 | 29 | type mystring string 30 | const _ mystring = mystring("foo") 31 | 32 | const _ = string(true /* ERROR "cannot convert" */ ) 33 | const _ = string(1.2 /* ERROR "cannot convert" */ ) 34 | const _ = string(nil /* ERROR "cannot convert" */ ) 35 | 36 | // issues 11357, 11353: argument must be of integer type 37 | _ = string(0.0 /* ERROR "cannot convert" */ ) 38 | _ = string(0i /* ERROR "cannot convert" */ ) 39 | _ = string(1 /* ERROR "cannot convert" */ + 2i) 40 | } 41 | 42 | func interface_conversions() { 43 | type E interface{} 44 | 45 | type I1 interface{ 46 | m1() 47 | } 48 | 49 | type I2 interface{ 50 | m1() 51 | m2(x int) 52 | } 53 | 54 | type I3 interface{ 55 | m1() 56 | m2() int 57 | } 58 | 59 | var e E 60 | var i1 I1 61 | var i2 I2 62 | var i3 I3 63 | 64 | _ = E(0) 65 | _ = E(nil) 66 | _ = E(e) 67 | _ = E(i1) 68 | _ = E(i2) 69 | 70 | _ = I1(0 /* ERROR "cannot convert" */ ) 71 | _ = I1(nil) 72 | _ = I1(i1) 73 | _ = I1(e /* ERROR "cannot convert" */ ) 74 | _ = I1(i2) 75 | 76 | _ = I2(nil) 77 | _ = I2(i1 /* ERROR "cannot convert" */ ) 78 | _ = I2(i2) 79 | _ = I2(i3 /* ERROR "cannot convert" */ ) 80 | 81 | _ = I3(nil) 82 | _ = I3(i1 /* ERROR "cannot convert" */ ) 83 | _ = I3(i2 /* ERROR "cannot convert" */ ) 84 | _ = I3(i3) 85 | 86 | // TODO(gri) add more tests, improve error message 87 | } 88 | 89 | func issue6326() { 90 | type T unsafe.Pointer 91 | var x T 92 | _ = uintptr(x) // see issue 6326 93 | } 94 | -------------------------------------------------------------------------------- /types/tests/data/errors.src: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package errors 6 | 7 | // Testing precise operand formatting in error messages 8 | // (matching messages are regular expressions, hence the \'s). 9 | func f(x int, m map[string]int) { 10 | // no values 11 | _ = f /* ERROR "f\(0, m\) \(no value\) used as value" */ (0, m) 12 | 13 | // built-ins 14 | _ = println /* ERROR "println \(built-in\) must be called" */ 15 | 16 | // types 17 | _ = complex128 /* ERROR "complex128 \(type\) is not an expression" */ 18 | 19 | // constants 20 | const c1 = 991 21 | const c2 float32 = 0.5 22 | 0 /* ERROR "0 \(untyped int constant 0\) is not used" */ 23 | c1 /* ERROR "c1 \(untyped int constant 991\) is not used" */ 24 | c2 /* ERROR "c2 \(constant 0.5 of type float32\) is not used" */ 25 | c1 /* ERROR "c1 \+ c2 \(constant 991.5 of type float32\) is not used" */ + c2 26 | 27 | // variables 28 | x /* ERROR "x \(variable of type int\) is not used" */ 29 | 30 | // values 31 | x /* ERROR "x != x \(untyped bool value\) is not used" */ != x 32 | x /* ERROR "x \+ x \(value of type int\) is not used" */ + x 33 | 34 | // value, ok's 35 | const s = "foo" 36 | m /* ERROR "m\[s\] \(map index expression of type int\) is not used" */ [s] 37 | } 38 | 39 | // Valid ERROR comments can have a variety of forms. 40 | func _() { 41 | 0 /* ERROR "0 .* is not used" */ 42 | 0 /* ERROR 0 .* is not used */ 43 | 0 // ERROR "0 .* is not used" 44 | 0 // ERROR 0 .* is not used 45 | } 46 | 47 | // Don't report spurious errors as a consequence of earlier errors. 48 | // Add more tests as needed. 49 | func _() { 50 | if err := foo /* ERROR undeclared */ (); err != nil /* no error here */ {} 51 | } 52 | 53 | // Use unqualified names for package-local objects. 54 | type T struct{} 55 | var _ int = T /* ERROR value of type */ {} // use T in error message rather then errors.T 56 | 57 | // Don't report errors containing "invalid type" (issue #24182). 58 | func _(x *missing /* ERROR undeclared name: missing */ ) { 59 | //x.m() // there shouldn't be an error here referring to *invalid type 60 | } 61 | -------------------------------------------------------------------------------- /std/sync/sync.gos: -------------------------------------------------------------------------------- 1 | package sync 2 | 3 | import "unsafe" 4 | 5 | var nativeMutex ffiMutex 6 | var nativeRWMutex ffiRWMutex 7 | 8 | func init() { 9 | nativeMutex = ffi(ffiMutex, "sync.mutex") 10 | nativeRWMutex = ffi(ffiRWMutex, "sync.rw_mutex") 11 | } 12 | 13 | type ffiMutex interface { 14 | async_lock(*unsafe.Pointer) 15 | async_unlock(unsafe.Pointer) 16 | } 17 | 18 | type ffiRWMutex interface { 19 | async_r_lock(*unsafe.Pointer) 20 | async_r_unlock(unsafe.Pointer) 21 | async_w_lock(*unsafe.Pointer) 22 | async_w_unlock(unsafe.Pointer) 23 | } 24 | 25 | // A Locker represents an object that can be locked and unlocked. 26 | type Locker interface { 27 | Lock() 28 | Unlock() 29 | } 30 | 31 | // A Mutex is a mutual exclusion lock. 32 | // The zero value for a Mutex is an unlocked mutex. 33 | // 34 | // A Mutex must not be copied after first use. 35 | type Mutex struct { 36 | handle unsafe.Pointer 37 | } 38 | 39 | // Lock locks m. 40 | // If the lock is already in use, the calling goroutine 41 | // blocks until the mutex is available. 42 | func (m *Mutex) Lock() { 43 | nativeMutex.async_lock(&m.handle) 44 | } 45 | 46 | 47 | // Unlock unlocks m. 48 | // It is a run-time error if m is not locked on entry to Unlock. 49 | // 50 | // A locked Mutex is not associated with a particular goroutine. 51 | // It is allowed for one goroutine to lock a Mutex and then 52 | // arrange for another goroutine to unlock it. 53 | func (m *Mutex) Unlock() { 54 | nativeMutex.async_unlock(m.handle) 55 | } 56 | 57 | 58 | // A RWMutex is a reader/writer mutual exclusion lock. 59 | // The lock can be held by an arbitrary number of readers or a single writer. 60 | // The zero value for a RWMutex is an unlocked mutex. 61 | // 62 | // A RWMutex must not be copied after first use. 63 | type RWMutex struct { 64 | handle unsafe.Pointer 65 | } 66 | 67 | func (rw *RWMutex) RLock() { 68 | nativeRWMutex.async_r_lock(&rw.handle) 69 | } 70 | 71 | func (rw *RWMutex) RUnlock() { 72 | nativeRWMutex.async_r_unlock(rw.handle) 73 | } 74 | 75 | func (rw *RWMutex) Lock() { 76 | nativeRWMutex.async_w_lock(&rw.handle) 77 | } 78 | 79 | func (rw *RWMutex) Unlock() { 80 | nativeRWMutex.async_w_unlock(rw.handle) 81 | } -------------------------------------------------------------------------------- /types/tests/data/decls2/decls2b.src: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // method declarations 6 | 7 | package decls2 8 | 9 | //import "io" 10 | 11 | const pi = 3.1415 12 | 13 | func (T1) m /* ERROR "already declared" */ () {} 14 | //func (T2) m(io.Writer) {} 15 | 16 | type T3 struct { 17 | f *T3 18 | } 19 | 20 | type T6 struct { 21 | x int 22 | } 23 | 24 | func (t *T6) m1() int { 25 | return t.x 26 | } 27 | 28 | func f() { 29 | var t *T6 30 | t.m1() 31 | } 32 | 33 | // Double declarations across package files 34 | const c_double /* ERROR "redeclared" */ = 0 35 | type t_double /* ERROR "redeclared" */ int 36 | var v_double /* ERROR "redeclared" */ int 37 | func f_double /* ERROR "redeclared" */ () {} 38 | 39 | // Blank methods need to be type-checked. 40 | // Verify by checking that errors are reported. 41 | func (T /* ERROR "undeclared" */ ) _() {} 42 | func (T1) _(undeclared /* ERROR "undeclared" */ ) {} 43 | func (T1) _() int { return "foo" /* ERROR "cannot convert" */ } 44 | 45 | // Methods with undeclared receiver type can still be checked. 46 | // Verify by checking that errors are reported. 47 | func (Foo /* ERROR "undeclared" */ ) m() {} 48 | func (Foo /* ERROR "undeclared" */ ) m(undeclared /* ERROR "undeclared" */ ) {} 49 | func (Foo /* ERROR "undeclared" */ ) m() int { return "foo" /* ERROR "cannot convert" */ } 50 | 51 | func (Foo /* ERROR "undeclared" */ ) _() {} 52 | func (Foo /* ERROR "undeclared" */ ) _(undeclared /* ERROR "undeclared" */ ) {} 53 | func (Foo /* ERROR "undeclared" */ ) _() int { return "foo" /* ERROR "cannot convert" */ } 54 | 55 | // Receiver declarations are regular parameter lists; 56 | // receiver types may use parentheses, and the list 57 | // may have a trailing comma. 58 | type T7 struct {} 59 | 60 | func (T7) m1() {} 61 | func ((T7)) m2() {} 62 | func ((*T7)) m3() {} 63 | func (x *(T7),) m4() {} 64 | func (x (*(T7)),) m5() {} 65 | func (x ((*((T7)))),) m6() {} 66 | 67 | // Check that methods with parenthesized receiver are actually present (issue #23130). 68 | var ( 69 | _ = T7.m1 70 | _ = T7.m2 71 | _ = (*T7).m3 72 | _ = (*T7).m4 73 | _ = (*T7).m5 74 | _ = (*T7).m6 75 | ) -------------------------------------------------------------------------------- /std/sync/map.gos: -------------------------------------------------------------------------------- 1 | package sync 2 | 3 | // Map operations in Goscript are innately atomic 4 | 5 | type Map struct { 6 | data map[interface{}]interface{} 7 | } 8 | 9 | // Load returns the value stored in the map for a key, or nil if no 10 | // value is present. 11 | // The ok result indicates whether value was found in the map. 12 | func (m *Map) Load(key interface{}) (value interface{}, ok bool) { 13 | v, ok := m.getData()[key] 14 | return v, ok 15 | } 16 | 17 | // Store sets the value for a key. 18 | func (m *Map) Store(key, value interface{}) { 19 | m.getData()[key] = value 20 | } 21 | 22 | // LoadOrStore returns the existing value for the key if present. 23 | // Otherwise, it stores and returns the given value. 24 | // The loaded result is true if the value was loaded, false if stored. 25 | func (m *Map) LoadOrStore(key, value interface{}) (actual interface{}, loaded bool) { 26 | if e, ok := m.getData()[key]; ok { 27 | return e, true 28 | } 29 | 30 | var mu Mutex 31 | mu.Lock() 32 | defer mu.Unlock() 33 | if e, ok := m.data[key]; ok { 34 | return e, true 35 | } else { 36 | m.data[key] = value 37 | return value, false 38 | } 39 | } 40 | 41 | // Delete deletes the value for a key. 42 | func (m *Map) Delete(key interface{}) { 43 | delete(m.getData(), key) 44 | } 45 | 46 | // Range calls f sequentially for each key and value present in the map. 47 | // If f returns false, range stops the iteration. 48 | // 49 | // Range does not necessarily correspond to any consistent snapshot of the Map's 50 | // contents: no key will be visited more than once, but if the value for any key 51 | // is stored or deleted concurrently, Range may reflect any mapping for that key 52 | // from any point during the Range call. 53 | // 54 | // Range may be O(N) with the number of elements in the map even if f returns 55 | // false after a constant number of calls. 56 | func (m *Map) Range(f func(key, value interface{}) bool) { 57 | panic("not implemented") 58 | } 59 | 60 | func (m *Map) getData() map[interface{}]interface{} { 61 | var l Mutex 62 | l.Lock() 63 | defer l.Unlock() 64 | if m.data == nil { 65 | m.data = make(map[interface{}]interface{}) 66 | } 67 | return m.data 68 | } -------------------------------------------------------------------------------- /std/math/atanh.go: -------------------------------------------------------------------------------- 1 | // Copyright 2010 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package math 6 | 7 | // The original C code, the long comment, and the constants 8 | // below are from FreeBSD's /usr/src/lib/msun/src/e_atanh.c 9 | // and came with this notice. The go code is a simplified 10 | // version of the original C. 11 | // 12 | // ==================================================== 13 | // Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. 14 | // 15 | // Developed at SunPro, a Sun Microsystems, Inc. business. 16 | // Permission to use, copy, modify, and distribute this 17 | // software is freely granted, provided that this notice 18 | // is preserved. 19 | // ==================================================== 20 | // 21 | // 22 | // __ieee754_atanh(x) 23 | // Method : 24 | // 1. Reduce x to positive by atanh(-x) = -atanh(x) 25 | // 2. For x>=0.5 26 | // 1 2x x 27 | // atanh(x) = --- * log(1 + -------) = 0.5 * log1p(2 * --------) 28 | // 2 1 - x 1 - x 29 | // 30 | // For x<0.5 31 | // atanh(x) = 0.5*log1p(2x+2x*x/(1-x)) 32 | // 33 | // Special cases: 34 | // atanh(x) is NaN if |x| > 1 with signal; 35 | // atanh(NaN) is that NaN with no signal; 36 | // atanh(+-1) is +-INF with signal. 37 | // 38 | 39 | // Atanh returns the inverse hyperbolic tangent of x. 40 | // 41 | // Special cases are: 42 | // Atanh(1) = +Inf 43 | // Atanh(±0) = ±0 44 | // Atanh(-1) = -Inf 45 | // Atanh(x) = NaN if x < -1 or x > 1 46 | // Atanh(NaN) = NaN 47 | func Atanh(x float64) float64 { 48 | const NearZero = 1.0 / (1 << 28) // 2**-28 49 | // special cases 50 | switch { 51 | case x < -1 || x > 1 || IsNaN(x): 52 | return NaN() 53 | case x == 1: 54 | return Inf(1) 55 | case x == -1: 56 | return Inf(-1) 57 | } 58 | sign := false 59 | if x < 0 { 60 | x = -x 61 | sign = true 62 | } 63 | var temp float64 64 | switch { 65 | case x < NearZero: 66 | temp = x 67 | case x < 0.5: 68 | temp = x + x 69 | temp = 0.5 * Log1p(temp+temp*x/(1-x)) 70 | default: 71 | temp = 0.5 * Log1p((x+x)/(1-x)) 72 | } 73 | if sign { 74 | temp = -temp 75 | } 76 | return temp 77 | } 78 | -------------------------------------------------------------------------------- /std/math/remainder.go: -------------------------------------------------------------------------------- 1 | // Copyright 2010 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package math 6 | 7 | // The original C code and the comment below are from 8 | // FreeBSD's /usr/src/lib/msun/src/e_remainder.c and came 9 | // with this notice. The go code is a simplified version of 10 | // the original C. 11 | // 12 | // ==================================================== 13 | // Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. 14 | // 15 | // Developed at SunPro, a Sun Microsystems, Inc. business. 16 | // Permission to use, copy, modify, and distribute this 17 | // software is freely granted, provided that this notice 18 | // is preserved. 19 | // ==================================================== 20 | // 21 | // __ieee754_remainder(x,y) 22 | // Return : 23 | // returns x REM y = x - [x/y]*y as if in infinite 24 | // precision arithmetic, where [x/y] is the (infinite bit) 25 | // integer nearest x/y (in half way cases, choose the even one). 26 | // Method : 27 | // Based on Mod() returning x - [x/y]chopped * y exactly. 28 | 29 | // Remainder returns the IEEE 754 floating-point remainder of x/y. 30 | // 31 | // Special cases are: 32 | // Remainder(±Inf, y) = NaN 33 | // Remainder(NaN, y) = NaN 34 | // Remainder(x, 0) = NaN 35 | // Remainder(x, ±Inf) = x 36 | // Remainder(x, NaN) = NaN 37 | func Remainder(x, y float64) float64 { 38 | const ( 39 | Tiny = 4.45014771701440276618e-308 // 0x0020000000000000 40 | HalfMax = MaxFloat64 / 2 41 | ) 42 | // special cases 43 | switch { 44 | case IsNaN(x) || IsNaN(y) || IsInf(x, 0) || y == 0: 45 | return NaN() 46 | case IsInf(y, 0): 47 | return x 48 | } 49 | sign := false 50 | if x < 0 { 51 | x = -x 52 | sign = true 53 | } 54 | if y < 0 { 55 | y = -y 56 | } 57 | if x == y { 58 | return 0 59 | } 60 | if y <= HalfMax { 61 | x = Mod(x, y+y) // now x < 2y 62 | } 63 | if y < Tiny { 64 | if x+x > y { 65 | x -= y 66 | if x+x >= y { 67 | x -= y 68 | } 69 | } 70 | } else { 71 | yHalf := 0.5 * y 72 | if x > yHalf { 73 | x -= y 74 | if x >= yHalf { 75 | x -= y 76 | } 77 | } 78 | } 79 | if sign { 80 | x = -x 81 | } 82 | return x 83 | } 84 | -------------------------------------------------------------------------------- /std/math/cmplx/log.go: -------------------------------------------------------------------------------- 1 | // Copyright 2010 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package cmplx 6 | 7 | import "math" 8 | 9 | // The original C code, the long comment, and the constants 10 | // below are from http://netlib.sandia.gov/cephes/c9x-complex/clog.c. 11 | // The go code is a simplified version of the original C. 12 | // 13 | // Cephes Math Library Release 2.8: June, 2000 14 | // Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier 15 | // 16 | // The readme file at http://netlib.sandia.gov/cephes/ says: 17 | // Some software in this archive may be from the book _Methods and 18 | // Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster 19 | // International, 1989) or from the Cephes Mathematical Library, a 20 | // commercial product. In either event, it is copyrighted by the author. 21 | // What you see here may be used freely but it comes with no support or 22 | // guarantee. 23 | // 24 | // The two known misprints in the book are repaired here in the 25 | // source listings for the gamma function and the incomplete beta 26 | // integral. 27 | // 28 | // Stephen L. Moshier 29 | // moshier@na-net.ornl.gov 30 | 31 | // Complex natural logarithm 32 | // 33 | // DESCRIPTION: 34 | // 35 | // Returns complex logarithm to the base e (2.718...) of 36 | // the complex argument z. 37 | // 38 | // If 39 | // z = x + iy, r = sqrt( x**2 + y**2 ), 40 | // then 41 | // w = log(r) + i arctan(y/x). 42 | // 43 | // The arctangent ranges from -PI to +PI. 44 | // 45 | // ACCURACY: 46 | // 47 | // Relative error: 48 | // arithmetic domain # trials peak rms 49 | // DEC -10,+10 7000 8.5e-17 1.9e-17 50 | // IEEE -10,+10 30000 5.0e-15 1.1e-16 51 | // 52 | // Larger relative error can be observed for z near 1 +i0. 53 | // In IEEE arithmetic the peak absolute error is 5.2e-16, rms 54 | // absolute error 1.0e-16. 55 | 56 | // Log returns the natural logarithm of x. 57 | func Log(x complex128) complex128 { 58 | return complex(math.Log(Abs(x)), Phase(x)) 59 | } 60 | 61 | // Log10 returns the decimal logarithm of x. 62 | func Log10(x complex128) complex128 { 63 | return math.Log10E * Log(x) 64 | } 65 | -------------------------------------------------------------------------------- /engine/tests/group1/interface1.gos: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | 4 | type geometry interface { 5 | area() float64 6 | perim() float64 7 | } 8 | 9 | 10 | type rect struct { 11 | width, height float64 12 | } 13 | 14 | func (r rect) perim() float64 { 15 | return 2*r.width + 2*r.height 16 | } 17 | 18 | func (r rect) area() float64 { 19 | return r.width * r.height 20 | } 21 | 22 | func measure(x geometry) float64 { 23 | return x.perim() 24 | } 25 | 26 | func measure2(x geometry, f float64, y geometry) float64 { 27 | return x.perim() + f + y.perim() 28 | } 29 | 30 | func measure3(x geometry, c float64, v... geometry) float64 { 31 | total := x.perim() + c 32 | for _, g := range v { 33 | total += g.perim() 34 | } 35 | return total 36 | } 37 | 38 | func measure4(x geometry, v... float64) float64 { 39 | total := x.perim() 40 | for _, g := range v { 41 | total += g 42 | } 43 | return total 44 | } 45 | 46 | /* 47 | type circle struct { 48 | radius float64 49 | } 50 | 51 | func (r rect) area() float64 { 52 | return r.width * r.height 53 | } 54 | func (r rect) perim() float64 { 55 | return 2*r.width + 2*r.height 56 | } 57 | 58 | func (c circle) area() float64 { 59 | return c.radius * c.radius 60 | } 61 | func (c circle) perim() float64 { 62 | return 1 * c.radius 63 | } 64 | 65 | func measure(g geometry) { 66 | assert(g.area() == 1) 67 | } 68 | */ 69 | 70 | func aaa() (int, *rect) { 71 | var r rect 72 | r2 := &r 73 | r.height = 2 74 | assert(2 == r2.height) 75 | return 1, r2 76 | } 77 | 78 | 79 | func main() { 80 | 81 | var r rect 82 | r.height = 8 83 | assert(8 == r.height) 84 | 85 | var g geometry 86 | f, g := -6, &r 87 | assert(f == -6) 88 | assert(16 == measure(g)) 89 | 90 | f, g = aaa() 91 | assert(f == 1) 92 | assert(4 == measure(g)) 93 | 94 | assert(37 == measure2(r, 5, r)) 95 | 96 | assert(16 * 3 + 5 == 53) 97 | 98 | //measure3(r, 2, r, r, r) 99 | assert(53 == measure3(r, 5, r, r)) 100 | 101 | assert(30 == measure4(r, 2, 3,4,5)) 102 | 103 | /* 104 | r := rect{width: 1, height: 1} 105 | c := circle{radius: 1} 106 | 107 | measure(r) 108 | measure(c) 109 | */ 110 | } -------------------------------------------------------------------------------- /engine/src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Goscript Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | //! This crate is part of the Goscript project. Please refer to for more information. 6 | //! 7 | //! It's a wapper of all the parts of the Goscript project. It also implements the standard library, 8 | //! the standard library part is still under development, only a few parts are implemented. 9 | //! 10 | //! # Example: 11 | //! ``` 12 | //! use std::path::{Path, PathBuf}; 13 | //! use go_engine::{Config, ErrorList, SourceReader, run}; 14 | //! 15 | //!fn run_file(path: &str, trace: bool) -> Result<(), ErrorList> { 16 | //! let mut cfg = Config::default(); 17 | //! cfg.trace_parser = trace; 18 | //! cfg.trace_checker = trace; 19 | //! let sr = SourceReader::local_fs(PathBuf::from("../std/"), PathBuf::from("./")); 20 | //! let result = run(cfg, &sr, Path::new(path), None); 21 | //! if let Err(el) = &result { 22 | //! el.sort(); 23 | //! eprint!("{}", el); 24 | //! } 25 | //! result 26 | //!} 27 | //! ``` 28 | //! 29 | //! # Feature 30 | //! The project is entended to be enbedded, so it has a lot of feature flags to turn on/off different parts. 31 | //! - `read_fs`: Read source code from local file system 32 | //! - `read_zip`: Read source code from zip file 33 | //! - `async`: Channel and goroutine support 34 | //! - `go_std`: Enable the Go standard library 35 | //! - `btree_map`: Make it use BTreeMap instead of HashMap 36 | //! - `codegen`: Enable codegen 37 | //! - `instruction_pos`: Add instruction position to bytecode for debugging 38 | //! - `serde_borsh`: Serde support for bytecode using Borsh 39 | //! - `wasm`: Enable wasm support 40 | //! 41 | 42 | mod engine; 43 | 44 | #[cfg(feature = "go_std")] 45 | mod std; 46 | 47 | mod vfs; 48 | 49 | mod source; 50 | 51 | #[macro_use] 52 | pub mod ffi; 53 | 54 | #[cfg(feature = "go_std")] 55 | #[macro_use] 56 | extern crate lazy_static; 57 | 58 | pub use engine::*; 59 | pub use go_parser::{ErrorList, FileSet}; 60 | pub use source::*; 61 | 62 | pub use crate::vfs::{compound::CompoundFs, vfs_map::VfsMap, VirtualFs}; 63 | 64 | #[cfg(feature = "read_fs")] 65 | pub use crate::vfs::vfs_fs::VfsFs; 66 | #[cfg(feature = "read_zip")] 67 | pub use crate::vfs::vfs_zip::VfsZip; 68 | -------------------------------------------------------------------------------- /vm/src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Goscript Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | //! This crate is part of the Goscript project. Please refer to for more information. 6 | //! 7 | //! # Feature 8 | //! - `async`: Channel and goroutine support 9 | //! - `btree_map`: Make it use BTreeMap instead of HashMap 10 | //! - `instruction_pos`: Add instruction position to bytecode for debugging 11 | //! - `serde_borsh`: Serde support for bytecode using Borsh 12 | 13 | mod instruction; 14 | #[macro_use] 15 | mod metadata; 16 | #[cfg(feature = "async")] 17 | mod channel; 18 | mod objects; 19 | #[macro_use] 20 | mod dispatcher; 21 | mod bytecode; 22 | mod ffi; 23 | mod stack; 24 | mod value; 25 | mod vm; 26 | 27 | pub mod gc; 28 | pub mod types { 29 | pub use crate::value::*; 30 | } 31 | 32 | pub mod parser { 33 | pub use go_parser::*; 34 | } 35 | 36 | pub use { 37 | ffi::*, 38 | go_parser::{Map, MapIter}, 39 | go_pmacro::{ffi_impl, Ffi, UnsafePtr}, 40 | value::Bytecode, 41 | vm::run, 42 | vm::PanicData, 43 | }; 44 | 45 | pub struct CallStackDisplay<'a> { 46 | panic_data: &'a PanicData, 47 | bc: &'a Bytecode, 48 | } 49 | 50 | impl<'a> CallStackDisplay<'a> { 51 | pub fn new(panic_data: &'a PanicData, bc: &'a Bytecode) -> CallStackDisplay<'a> { 52 | Self { panic_data, bc } 53 | } 54 | } 55 | 56 | impl<'a> std::fmt::Display for CallStackDisplay<'a> { 57 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 58 | for (fkey, pc) in self.panic_data.call_stack.iter() { 59 | let func = &self.bc.objects.functions[*fkey]; 60 | if let Some(p) = func.pos[*pc as usize] { 61 | if let Some(fs) = &self.bc.file_set { 62 | writeln!( 63 | f, 64 | "{}", 65 | fs.position(p as usize) 66 | .unwrap_or(go_parser::FilePos::null()) 67 | )?; 68 | } else { 69 | writeln!(f, "fileset not available, pos:{}", p)?; 70 | } 71 | } else { 72 | f.write_str("\n")?; 73 | }; 74 | } 75 | Ok(()) 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /types/tests/data/cycles4.gos: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package p 6 | 7 | // Check that all methods of T are collected before 8 | // determining the result type of m (which embeds 9 | // all methods of T). 10 | 11 | type T interface { 12 | m() interface {T} 13 | E 14 | } 15 | 16 | var _ = T.m(nil).m().e() 17 | 18 | type E interface { 19 | e() int 20 | } 21 | 22 | // Check that unresolved forward chains are followed 23 | // (see also comment in resolver.go, checker.typeDecl). 24 | 25 | var _ = C.m(nil).m().e() 26 | 27 | type A B 28 | 29 | type B interface { 30 | m() interface{C} 31 | E 32 | } 33 | 34 | type C A 35 | 36 | // Check that interface type comparison for identity 37 | // does not recur endlessly. 38 | 39 | type T1 interface { 40 | m() interface{T1} 41 | } 42 | 43 | type T2 interface { 44 | m() interface{T2} 45 | } 46 | 47 | func _(x T1, y T2) { 48 | // Checking for assignability of interfaces must check 49 | // if all methods of x are present in y, and that they 50 | // have identical signatures. The signatures recur via 51 | // the result type, which is an interface that embeds 52 | // a single method m that refers to the very interface 53 | // that contains it. This requires cycle detection in 54 | // identity checks for interface types. 55 | x = y 56 | } 57 | 58 | type T3 interface { 59 | m() interface{T4} 60 | } 61 | 62 | type T4 interface { 63 | m() interface{T3} 64 | } 65 | 66 | func _(x T1, y T3) { 67 | x = y 68 | } 69 | 70 | // Check that interfaces are type-checked in order of 71 | // (embedded interface) dependencies (was issue 7158). 72 | 73 | var x1 T5 = T7(nil) 74 | 75 | type T5 interface { 76 | T6 77 | } 78 | 79 | type T6 interface { 80 | m() T7 81 | } 82 | type T7 interface { 83 | T5 84 | } 85 | 86 | // Actual test case from issue 7158. 87 | 88 | func wrapNode() Node { 89 | return wrapElement() 90 | } 91 | 92 | func wrapElement() Element { 93 | return nil 94 | } 95 | 96 | type EventTarget interface { 97 | AddEventListener(Event) 98 | } 99 | 100 | type Node interface { 101 | EventTarget 102 | } 103 | 104 | type Element interface { 105 | Node 106 | } 107 | 108 | type Event interface { 109 | Target() Element 110 | } 111 | -------------------------------------------------------------------------------- /std/math/const.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package math provides basic constants and mathematical functions. 6 | // 7 | // This package does not guarantee bit-identical results across architectures. 8 | package math 9 | 10 | // Mathematical constants. 11 | const ( 12 | E = 2.71828182845904523536028747135266249775724709369995957496696763 // https://oeis.org/A001113 13 | Pi = 3.14159265358979323846264338327950288419716939937510582097494459 // https://oeis.org/A000796 14 | Phi = 1.61803398874989484820458683436563811772030917980576286213544862 // https://oeis.org/A001622 15 | 16 | Sqrt2 = 1.41421356237309504880168872420969807856967187537694807317667974 // https://oeis.org/A002193 17 | SqrtE = 1.64872127070012814684865078781416357165377610071014801157507931 // https://oeis.org/A019774 18 | SqrtPi = 1.77245385090551602729816748334114518279754945612238712821380779 // https://oeis.org/A002161 19 | SqrtPhi = 1.27201964951406896425242246173749149171560804184009624861664038 // https://oeis.org/A139339 20 | 21 | Ln2 = 0.693147180559945309417232121458176568075500134360255254120680009 // https://oeis.org/A002162 22 | Log2E = 1 / Ln2 23 | Ln10 = 2.30258509299404568401799145468436420760110148862877297603332790 // https://oeis.org/A002392 24 | Log10E = 1 / Ln10 25 | ) 26 | 27 | // Floating-point limit values. 28 | // Max is the largest finite value representable by the type. 29 | // SmallestNonzero is the smallest positive, non-zero value representable by the type. 30 | const ( 31 | MaxFloat32 = 3.40282346638528859811704183484516925440e+38 // 2**127 * (2**24 - 1) / 2**23 32 | SmallestNonzeroFloat32 = 1.401298464324817070923729583289916131280e-45 // 1 / 2**(127 - 1 + 23) 33 | 34 | MaxFloat64 = 1.797693134862315708145274237317043567981e+308 // 2**1023 * (2**53 - 1) / 2**52 35 | SmallestNonzeroFloat64 = 4.940656458412465441765687928682213723651e-324 // 1 / 2**(1023 - 1 + 52) 36 | ) 37 | 38 | // Integer limit values. 39 | const ( 40 | MaxInt8 = 1<<7 - 1 41 | MinInt8 = -1 << 7 42 | MaxInt16 = 1<<15 - 1 43 | MinInt16 = -1 << 15 44 | MaxInt32 = 1<<31 - 1 45 | MinInt32 = -1 << 31 46 | MaxInt64 = 1<<63 - 1 47 | MinInt64 = -1 << 63 48 | MaxUint8 = 1<<8 - 1 49 | MaxUint16 = 1<<16 - 1 50 | MaxUint32 = 1<<32 - 1 51 | MaxUint64 = 1<<64 - 1 52 | ) 53 | -------------------------------------------------------------------------------- /engine/tests/demo/linked.gos: -------------------------------------------------------------------------------- 1 | // for testing GC; taken from internet 2 | package main 3 | 4 | import "fmt2" 5 | 6 | type Node struct { 7 | prev *Node 8 | next *Node 9 | key interface{} 10 | } 11 | 12 | type List struct { 13 | head *Node 14 | tail *Node 15 | t1 *Node 16 | t2 *Node 17 | } 18 | 19 | var glist = List{} 20 | 21 | func (L *List) Insert(key interface{}) { 22 | list := &Node{ 23 | next: L.head, 24 | key: key, 25 | } 26 | if L.head != nil { 27 | L.head.prev = list 28 | } 29 | L.head = list 30 | 31 | l := L.head 32 | for l.next != nil { 33 | l = l.next 34 | } 35 | L.tail = l 36 | } 37 | 38 | func (l *List) Display() { 39 | list := l.head 40 | for list != nil { 41 | fmt2.Println("%+v ->", list.key) 42 | list = list.next 43 | } 44 | //fmt2.Println() 45 | } 46 | 47 | func Display(list *Node) { 48 | for list != nil { 49 | fmt2.Println("%v ->", list.key) 50 | list = list.next 51 | } 52 | //fmt2.Println() 53 | } 54 | 55 | func ShowBackwards(list *Node) { 56 | for list != nil { 57 | fmt2.Println("%v <-", list.key) 58 | list = list.prev 59 | } 60 | //fmt2.Println() 61 | } 62 | 63 | func (l *List) Reverse() { 64 | curr := l.head 65 | var prev *Node 66 | l.tail = l.head 67 | 68 | for curr != nil { 69 | next := curr.next 70 | curr.next = prev 71 | prev = curr 72 | curr = next 73 | } 74 | l.head = prev 75 | Display(l.head) 76 | } 77 | 78 | func main() { 79 | 80 | link := List{} 81 | link.Insert(1) 82 | link.Insert(3) 83 | link.Insert(5) 84 | link.Insert(7) 85 | link.Insert(9) 86 | 87 | fmt2.Println("\n==============================\n") 88 | fmt2.Println("Head: %v\n", link.head.key) 89 | fmt2.Println("Tail: %v\n", link.tail.key) 90 | //fmt2.Println("ttt: %v\n", link.ttt.key) 91 | link.Display() 92 | fmt2.Println("\n==============================\n") 93 | fmt2.Println("head: %v\n", link.head.key) 94 | fmt2.Println("tail: %v\n", link.tail.key) 95 | link.Reverse() 96 | fmt2.Println("\n==============================\n") 97 | 98 | 99 | // for testing GC 100 | link2 := List{} 101 | link2.Insert(10) 102 | link2.Insert(30) 103 | link2.Insert(50) 104 | link2.Insert(70) 105 | link2.Insert(90) 106 | link2.head.prev = link2.tail 107 | link2.tail.next = link2.head 108 | glist.Insert(2) 109 | glist.Insert(4) 110 | glist.Insert(6) 111 | glist.Insert(8) 112 | glist.Insert(10) 113 | glist.t1 = glist.head 114 | glist.t2 = glist.head 115 | 116 | } 117 | -------------------------------------------------------------------------------- /engine/tests/demo/leetcode5.gos: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt2" 4 | 5 | func longestPalindrome(s string) string { 6 | if len(s) <= 1 { 7 | return s 8 | } 9 | table := make([][]bool, len(s)) 10 | for i := 0; i < len(table); i++ { 11 | table[i] = make([]bool, len(s)) 12 | } 13 | 14 | b := 0 15 | e := 1 16 | for l := 0; l < len(s); l++ { 17 | for i := 0; i < len(s) - l; i++ { 18 | j := i + l 19 | if l == 0 { 20 | table[i][j] = true 21 | } else if l == 1 { 22 | table[i][j] = s[i] == s[j] 23 | } else { 24 | table[i][j] = table[i+1][j-1] && (s[i] == s[j]) 25 | } 26 | if table[i][j] { 27 | b, e = i, j 28 | } 29 | } 30 | } 31 | return s[b:e+1] 32 | } 33 | 34 | 35 | func longestPalindrome2(s string) string { 36 | if len(s) <= 1 { 37 | return s 38 | } 39 | table := make([][]int, len(s)) 40 | for i := 0; i < len(table); i++ { 41 | table[i] = make([]int, len(s)) 42 | } 43 | var res string 44 | max := 0 45 | for i, _ := range s{ 46 | for j := i; j > -1; j-- { 47 | if s[i] == s[j] && (i - j < 2 || table[i - 1][j + 1] != 0) { 48 | table[i][j] = 1 49 | } 50 | 51 | if table[i][j] != 0 && (i - j + 1) > max { 52 | max = i - j + 1 53 | res = s[j:i + 1] 54 | } 55 | } 56 | } 57 | return res 58 | } 59 | 60 | func t(size int) { 61 | table := make([][]int, size) 62 | for i := 0; i < len(table); i++ { 63 | table[i] = make([]int, size) 64 | } 65 | //total := 0 66 | for i := 0; i < size; i++ { 67 | for j :=0; j < size; j++ { 68 | table[i][j] = i + j 69 | //total += (i + j) 70 | } 71 | } 72 | } 73 | 74 | 75 | func main() { 76 | //j := 10 77 | s := "ZnVuYyBsb25nZXN0UGFsaW5kcm9tZShzIHN0cmaabbaabbaabbluZykgc3RyaW5nIHsKICAgIGlmIGxlbihzKSA8PSAxIHsKICAgICAgICByZXR1cm4gcwogICAgfQogICAgCiAgICB0YWJsZSA6PaaabbbaaabbbaaaSBtYWtlKFtdW11ib29" 78 | for i := 0; i < 0; i++ { 79 | s = s + s 80 | 81 | //j += j 82 | //j -= j/2 83 | 84 | //t(1000) 85 | } 86 | //assert(j == 10) 87 | 88 | fmt2.Println(len(s)) 89 | result := longestPalindrome2(s) 90 | assert(result == "aaabbbaaabbbaaa") 91 | 92 | 93 | //assert(longestPalindrome("aa") == "aa") 94 | } 95 | -------------------------------------------------------------------------------- /types/tests/data/init0.src: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // initialization cycles 6 | 7 | package init0 8 | 9 | // initialization cycles (we don't know the types) 10 | const ( 11 | s0 /* ERROR initialization cycle */ = s0 12 | 13 | x0 /* ERROR initialization cycle */ = y0 14 | y0 = x0 15 | 16 | a0 = b0 17 | b0 /* ERROR initialization cycle */ = c0 18 | c0 = d0 19 | d0 = b0 20 | ) 21 | 22 | var ( 23 | s1 /* ERROR initialization cycle */ = s1 24 | 25 | x1 /* ERROR initialization cycle */ = y1 26 | y1 = x1 27 | 28 | a1 = b1 29 | b1 /* ERROR initialization cycle */ = c1 30 | c1 = d1 31 | d1 = b1 32 | ) 33 | 34 | // initialization cycles (we know the types) 35 | const ( 36 | s2 /* ERROR initialization cycle */ int = s2 37 | 38 | x2 /* ERROR initialization cycle */ int = y2 39 | y2 = x2 40 | 41 | a2 = b2 42 | b2 /* ERROR initialization cycle */ int = c2 43 | c2 = d2 44 | d2 = b2 45 | ) 46 | 47 | var ( 48 | s3 /* ERROR initialization cycle */ int = s3 49 | 50 | x3 /* ERROR initialization cycle */ int = y3 51 | y3 = x3 52 | 53 | a3 = b3 54 | b3 /* ERROR initialization cycle */ int = c3 55 | c3 = d3 56 | d3 = b3 57 | ) 58 | 59 | // cycles via struct fields 60 | 61 | type S1 struct { 62 | f int 63 | } 64 | const cx3 S1 /* ERROR invalid constant type */ = S1{cx3.f} 65 | var vx3 /* ERROR initialization cycle */ S1 = S1{vx3.f} 66 | 67 | // cycles via functions 68 | 69 | var x4 = x5 70 | var x5 /* ERROR initialization cycle */ = f1() 71 | func f1() int { return x5*10 } 72 | 73 | var x6, x7 /* ERROR initialization cycle */ = f2() 74 | var x8 = x7 75 | func f2() (int, int) { return f3() + f3(), 0 } 76 | func f3() int { return x8 } 77 | 78 | // cycles via function literals 79 | 80 | var x9 /* ERROR initialization cycle */ = func() int { return x9 }() 81 | 82 | var x10 /* ERROR initialization cycle */ = f4() 83 | 84 | func f4() int { 85 | _ = func() { 86 | _ = x10 87 | } 88 | return 0 89 | } 90 | 91 | // cycles via method expressions 92 | 93 | type T1 struct{} 94 | 95 | func (T1) m() bool { _ = x11; return false } 96 | 97 | var x11 /* ERROR initialization cycle */ = T1.m(T1{}) 98 | 99 | // cycles via method values 100 | 101 | type T2 struct{} 102 | 103 | func (T2) m() bool { _ = x12; return false } 104 | 105 | var t1 T2 106 | var x12 /* ERROR initialization cycle */ = t1.m 107 | -------------------------------------------------------------------------------- /engine/tests/group1/conversion.gos: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt2" 4 | 5 | type type1 []struct { 6 | Field1 string 7 | Field2 int 8 | } 9 | type type2 []struct { 10 | Field1 string 11 | Field2 int 12 | } 13 | 14 | 15 | func main() { 16 | 17 | i := uint(42.0) 18 | f := float64(i) 19 | u := uint(f) 20 | assert(u == 42) 21 | 22 | { 23 | f2 := float64(-3.25) 24 | assert(f2 == -3.25) 25 | f3 := float32(f2) 26 | assert(f3 == -3.25) 27 | i := int(f3) 28 | assert(i == -3) 29 | } 30 | 31 | t1 := type1{{"A", 1}, {"B", 2}} 32 | t2 := type2(t1) 33 | assert(t2[1].Field2 == 2) 34 | 35 | 36 | s1 := string(100) 37 | assert(s1 == "d") 38 | fmt2.Println(s1) 39 | 40 | s2 := string([]rune{100, 101}) 41 | assert(s2 == "de") 42 | fmt2.Println(s2) 43 | 44 | data := []byte{'t','e','s','t'} 45 | s3 := string(data) 46 | assert(s3 == "test") 47 | fmt2.Println(s3) 48 | 49 | b4 := []byte("dHello, 世界") 50 | r4 := []rune("dHello, 世界") 51 | assert(b4[0] == 100) 52 | assert(r4[0] == 100) 53 | s51 := string(b4) 54 | s52 := string(r4) 55 | assert(s51[0] == 'd') 56 | assert(s52[0] == 'd') 57 | shijie := "世界" 58 | assert(s51[8] == shijie[0]) 59 | assert(s52[9] == shijie[1]) 60 | fmt2.Println(b4, r4, s51, s52) 61 | 62 | 63 | 64 | testNamed() 65 | testStruct() 66 | testChan() 67 | } 68 | 69 | 70 | type Duration int64 71 | 72 | func testNamed() { 73 | var minDuration Duration 74 | var i int32 = 4 75 | d := Duration(i) + minDuration 76 | j := Duration(i) 77 | assert(j==d) 78 | } 79 | 80 | type Person struct { 81 | Name string 82 | Address *struct { 83 | Street string 84 | City string 85 | } 86 | } 87 | 88 | var data struct { 89 | Name string `json:"name"` 90 | Address *struct { 91 | Street string `json:"street"` 92 | City string `json:"city"` 93 | } `json:"address"` 94 | } 95 | 96 | 97 | func testStruct() { 98 | var p Person = Person(data) 99 | 100 | var person = (*Person)(&data) // ignoring tags, the underlying types are identical 101 | assert(person != nil) 102 | person.Name = "aaaa" 103 | assert(data.Name == "aaaa") 104 | 105 | assert(p.Name == "") 106 | fmt2.Println(p) 107 | } 108 | 109 | type C chan string 110 | 111 | func testChan() { 112 | var c C = make(C) 113 | d := (chan <- string)(c) 114 | fmt2.Println(d) 115 | } -------------------------------------------------------------------------------- /std/math/cbrt.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package math 6 | 7 | // The go code is a modified version of the original C code from 8 | // http://www.netlib.org/fdlibm/s_cbrt.c and came with this notice. 9 | // 10 | // ==================================================== 11 | // Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. 12 | // 13 | // Developed at SunSoft, a Sun Microsystems, Inc. business. 14 | // Permission to use, copy, modify, and distribute this 15 | // software is freely granted, provided that this notice 16 | // is preserved. 17 | // ==================================================== 18 | 19 | // Cbrt returns the cube root of x. 20 | // 21 | // Special cases are: 22 | // Cbrt(±0) = ±0 23 | // Cbrt(±Inf) = ±Inf 24 | // Cbrt(NaN) = NaN 25 | func Cbrt(x float64) float64 { 26 | const ( 27 | B1 = 715094163 // (682-0.03306235651)*2**20 28 | B2 = 696219795 // (664-0.03306235651)*2**20 29 | C = 5.42857142857142815906e-01 // 19/35 = 0x3FE15F15F15F15F1 30 | D = -7.05306122448979611050e-01 // -864/1225 = 0xBFE691DE2532C834 31 | E = 1.41428571428571436819e+00 // 99/70 = 0x3FF6A0EA0EA0EA0F 32 | F = 1.60714285714285720630e+00 // 45/28 = 0x3FF9B6DB6DB6DB6E 33 | G = 3.57142857142857150787e-01 // 5/14 = 0x3FD6DB6DB6DB6DB7 34 | SmallestNormal = 2.22507385850720138309e-308 // 2**-1022 = 0x0010000000000000 35 | ) 36 | // special cases 37 | switch { 38 | case x == 0 || IsNaN(x) || IsInf(x, 0): 39 | return x 40 | } 41 | 42 | sign := false 43 | if x < 0 { 44 | x = -x 45 | sign = true 46 | } 47 | 48 | // rough cbrt to 5 bits 49 | t := Float64frombits(Float64bits(x)/3 + B1<<32) 50 | if x < SmallestNormal { 51 | // subnormal number 52 | t = float64(1 << 54) // set t= 2**54 53 | t *= x 54 | t = Float64frombits(Float64bits(t)/3 + B2<<32) 55 | } 56 | 57 | // new cbrt to 23 bits 58 | r := t * t / x 59 | s := C + r*t 60 | t *= G + F/(s+E+D/s) 61 | 62 | // chop to 22 bits, make larger than cbrt(x) 63 | t = Float64frombits(Float64bits(t)&(0xFFFFFFFFC<<28) + 1<<30) 64 | 65 | // one step newton iteration to 53 bits with error less than 0.667ulps 66 | s = t * t // t*t is exact 67 | r = x / s 68 | w := t + t 69 | r = (r - t) / (w + r) // r-s is exact 70 | t = t + t*r 71 | 72 | // restore the sign bit 73 | if sign { 74 | t = -t 75 | } 76 | return t 77 | } 78 | -------------------------------------------------------------------------------- /engine/tests/group1/pointer.gos: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | //import "math" 4 | 5 | type Node struct{ 6 | i int 7 | j string 8 | } 9 | 10 | var pkgVarA = 1 11 | 12 | func test() { 13 | a := 1 14 | b := &a 15 | *b = 2 16 | assert(2 == a) 17 | 18 | f := func() *int { 19 | return &a 20 | } 21 | 22 | d := f() 23 | e := *d 24 | assert(a == e) 25 | 26 | var n, n2 Node 27 | n.i = 1 28 | n2.i = 222 29 | m := &n 30 | *m = n2 31 | assert(n.i == 222) 32 | assert(m.i == 222) 33 | m.i = 333 34 | m.j = "abc" 35 | assert(n.i == 333) 36 | assert(n.j == "abc") 37 | 38 | pfield := &n.i 39 | *pfield += 1 40 | assert(n.i == 334) 41 | 42 | sl1 := []int{1,2} 43 | sl2 := sl1 44 | assert(sl2[0] == 1) 45 | i := 3 46 | psl := &sl2[i-3] 47 | *psl = 3 48 | assert(sl1[0] == 3) 49 | 50 | *psl += 2 51 | assert(sl1[0] == 5) 52 | 53 | sl1p := &sl1 54 | (*sl1p)[0] = 8 55 | assert(sl1[0] == 8) 56 | 57 | *sl1p = []int{111,222} 58 | assert(sl1[0] == 111) 59 | assert(sl1[1] == 222) 60 | 61 | { 62 | sl1 := [2]int{1,2} 63 | sl2 := sl1 64 | assert(sl2[0] == 1) 65 | i := 3 66 | psl := &sl2[i-3] 67 | *psl = 3 68 | assert(sl1[0] == 1) 69 | assert(sl2[0] == 3) 70 | 71 | *psl += 2 72 | assert(sl2[0] == 5) 73 | 74 | sl1p := &sl1 75 | (*sl1p)[0] = 8 76 | assert(sl1[0] == 8) 77 | 78 | *sl1p = [2]int{111,222} 79 | assert(sl1[0] == 111) 80 | assert(sl1[1] == 222) 81 | 82 | } 83 | 84 | var m1 = map[int]int{1:2, 3: 888} 85 | m1p := &m1 86 | (*m1p)[3] = 88 87 | assert(m1[3] == 88) 88 | 89 | { 90 | var d = &pkgVarA 91 | *d = 2 92 | assert(pkgVarA == 2) 93 | 94 | /* 95 | var e = &math.PI 96 | assert(math.V1 == 1) 97 | *e = 2 98 | assert(math.V1 == 2) 99 | */ 100 | } 101 | } 102 | 103 | 104 | func ret() *int { 105 | i := 666 106 | return &i 107 | } 108 | 109 | 110 | func ret2() (*int, *int) { 111 | i := 666 112 | return &i, &i 113 | } 114 | 115 | 116 | func test_ret2() { 117 | i, j := ret2() 118 | *i = 888 119 | assert(*j == 888) 120 | } 121 | 122 | 123 | func main() { 124 | a := 1 125 | b := &a 126 | assert(*b + 1 == 2) 127 | 128 | assert(*ret() + 1 == 667) 129 | 130 | test() 131 | 132 | test_ret2() 133 | } -------------------------------------------------------------------------------- /std/math/cmplx/pow.go: -------------------------------------------------------------------------------- 1 | // Copyright 2010 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package cmplx 6 | 7 | import "math" 8 | 9 | // The original C code, the long comment, and the constants 10 | // below are from http://netlib.sandia.gov/cephes/c9x-complex/clog.c. 11 | // The go code is a simplified version of the original C. 12 | // 13 | // Cephes Math Library Release 2.8: June, 2000 14 | // Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier 15 | // 16 | // The readme file at http://netlib.sandia.gov/cephes/ says: 17 | // Some software in this archive may be from the book _Methods and 18 | // Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster 19 | // International, 1989) or from the Cephes Mathematical Library, a 20 | // commercial product. In either event, it is copyrighted by the author. 21 | // What you see here may be used freely but it comes with no support or 22 | // guarantee. 23 | // 24 | // The two known misprints in the book are repaired here in the 25 | // source listings for the gamma function and the incomplete beta 26 | // integral. 27 | // 28 | // Stephen L. Moshier 29 | // moshier@na-net.ornl.gov 30 | 31 | // Complex power function 32 | // 33 | // DESCRIPTION: 34 | // 35 | // Raises complex A to the complex Zth power. 36 | // Definition is per AMS55 # 4.2.8, 37 | // analytically equivalent to cpow(a,z) = cexp(z clog(a)). 38 | // 39 | // ACCURACY: 40 | // 41 | // Relative error: 42 | // arithmetic domain # trials peak rms 43 | // IEEE -10,+10 30000 9.4e-15 1.5e-15 44 | 45 | // Pow returns x**y, the base-x exponential of y. 46 | // For generalized compatibility with math.Pow: 47 | // Pow(0, ±0) returns 1+0i 48 | // Pow(0, c) for real(c)<0 returns Inf+0i if imag(c) is zero, otherwise Inf+Inf i. 49 | func Pow(x, y complex128) complex128 { 50 | if x == 0 { // Guaranteed also true for x == -0. 51 | r, i := real(y), imag(y) 52 | switch { 53 | case r == 0: 54 | return 1 55 | case r < 0: 56 | if i == 0 { 57 | return complex(math.Inf(1), 0) 58 | } 59 | return Inf() 60 | case r > 0: 61 | return 0 62 | } 63 | panic("not reached") 64 | } 65 | modulus := Abs(x) 66 | if modulus == 0 { 67 | return complex(0, 0) 68 | } 69 | r := math.Pow(modulus, real(y)) 70 | arg := Phase(x) 71 | theta := real(y) * arg 72 | if imag(y) != 0 { 73 | r *= math.Exp(-imag(y) * arg) 74 | theta += imag(y) * math.Log(modulus) 75 | } 76 | s, c := math.Sincos(theta) 77 | return complex(r*c, r*s) 78 | } 79 | -------------------------------------------------------------------------------- /engine/src/vfs/vfs_zip.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Goscript Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | use crate::vfs::VirtualFs; 6 | use std::borrow::Cow; 7 | use std::cell::RefCell; 8 | use std::io; 9 | use std::io::Read; 10 | use std::path::Path; 11 | use std::path::PathBuf; 12 | use std::vec; 13 | use zip::read::ZipArchive; 14 | use zip::result::{ZipError, ZipResult}; 15 | 16 | pub struct VfsZip { 17 | archive: RefCell>>>, 18 | } 19 | 20 | impl VfsZip { 21 | pub fn new(archive: Cow<'static, [u8]>) -> ZipResult { 22 | let c = io::Cursor::new(archive); 23 | let archive = RefCell::new(ZipArchive::new(c)?); 24 | Ok(VfsZip { archive }) 25 | } 26 | 27 | fn convert_err(err: ZipResult) -> io::Result { 28 | match err { 29 | Ok(v) => Ok(v), 30 | Err(e) => match e { 31 | ZipError::Io(ioe) => Err(ioe), 32 | _ => Err(io::Error::new(io::ErrorKind::Other, format!("{}", e))), 33 | }, 34 | } 35 | } 36 | } 37 | 38 | impl VirtualFs for VfsZip { 39 | fn read_file(&self, path: &Path) -> io::Result { 40 | let mut borrow = self.archive.borrow_mut(); 41 | let re = borrow.by_name(path.to_str().unwrap()); 42 | let mut file = VfsZip::convert_err(re)?; 43 | let mut buf = String::new(); 44 | file.read_to_string(&mut buf)?; 45 | Ok(buf) 46 | } 47 | 48 | fn read_dir(&self, path: &Path) -> io::Result> { 49 | let mut result = vec![]; 50 | let len = self.archive.borrow().len(); 51 | for i in 0..len { 52 | let mut borrow = self.archive.borrow_mut(); 53 | let file = borrow.by_index(i)?; 54 | let fp = Path::new(file.name()); 55 | if fp.starts_with(path) 56 | && !fp 57 | .strip_prefix(path) 58 | .unwrap() 59 | .to_string_lossy() 60 | .contains("/") 61 | { 62 | result.push(fp.to_path_buf()) 63 | } 64 | } 65 | if result.is_empty() { 66 | Err(io::Error::from(io::ErrorKind::NotFound)) 67 | } else { 68 | Ok(result) 69 | } 70 | } 71 | 72 | fn is_file(&self, path: &Path) -> bool { 73 | path.extension().is_some() 74 | } 75 | 76 | fn is_dir(&self, path: &Path) -> bool { 77 | path.extension().is_none() 78 | } 79 | 80 | fn canonicalize_path(&self, path: &PathBuf) -> io::Result { 81 | Ok(path.clone()) 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /std/os/file.gos: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Goscript Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | 6 | package os 7 | 8 | import "unsafe" 9 | import "errors" 10 | 11 | var fileIface ffiFile 12 | 13 | type ffiFile interface { 14 | get_std_io(which int) unsafe.Pointer 15 | open(name string, flags int) (p unsafe.Pointer, errKind int, err string) 16 | read(f unsafe.Pointer, b []byte) (n int, errKind int, err string) 17 | write(f unsafe.Pointer, b []byte) (n int, errKind int, err string) 18 | seek(f unsafe.Pointer, offset int64, whence int) (ret int64, errKind int, err string) 19 | } 20 | 21 | var Stdin *File 22 | var Stdout *File 23 | var Stderr *File 24 | 25 | func init() { 26 | fileIface = ffi(ffiFile, "os.file") 27 | 28 | Stdin = &File{fileIface.get_std_io(0), "Stdin"} 29 | Stdout = &File{fileIface.get_std_io(1), "Stdout"} 30 | Stderr = &File{fileIface.get_std_io(2), "Stderr"} 31 | } 32 | 33 | // Flags to OpenFile 34 | const ( 35 | // Exactly one of O_RDONLY, O_WRONLY, or O_RDWR must be specified. 36 | O_RDONLY int = 0x00000 // open the file read-only. 37 | O_WRONLY int = 0x00001 // open the file write-only. 38 | O_RDWR int = 0x00002 // open the file read-write. 39 | // The remaining values may be or'ed in to control behavior. 40 | O_APPEND int = 0x00400 // append data to the file when writing. 41 | O_CREATE int = 0x00040 // create a new file if none exists. 42 | O_EXCL int = 0x00080 // used with O_CREATE, file must not exist. 43 | //O_SYNC int = syscall.O_SYNC // open for synchronous I/O. 44 | O_TRUNC int = 0x00200 // truncate regular writable file when opened. 45 | ) 46 | 47 | type File struct{ 48 | ptr unsafe.Pointer 49 | name string 50 | } 51 | 52 | func Open(name string) (*File, error) { 53 | p, _, msg := fileIface.open(name, O_RDONLY) 54 | if msg != "" { 55 | return nil, errors.New(msg) 56 | } else { 57 | return &File{ptr: p, name: name}, nil 58 | } 59 | } 60 | 61 | func (f *File) Read(b []byte) (n int, err error) { 62 | n, _, msg := fileIface.read(f.ptr, b) 63 | if msg != "" { 64 | return n, errors.New(msg) 65 | } else { 66 | return n, nil 67 | } 68 | } 69 | 70 | func (f *File) Write(b []byte) (n int, err error) { 71 | n, _, msg := fileIface.write(f.ptr, b) 72 | if msg != "" { 73 | return n, errors.New(msg) 74 | } else { 75 | return n, nil 76 | } 77 | } 78 | 79 | func (f *File) Seek(offset int64, whence int) (ret int64, err error) { 80 | n, _, msg := fileIface.seek(f.ptr, offset, whence) 81 | if msg != "" { 82 | return n, errors.New(msg) 83 | } else { 84 | return n, nil 85 | } 86 | } -------------------------------------------------------------------------------- /engine/tests/group1/slice1.gos: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | 4 | func a() bool { 5 | s := []int{8,8} 6 | s[1] -= 9 7 | k := s[1] == -1 8 | return k 9 | } 10 | 11 | func f2() { 12 | var j int 13 | var s = []int{10, 20} 14 | var s2 = []int{100, 200} 15 | for _, v := range s { 16 | j += v 17 | for _, v2 := range s2{ 18 | j += v2 19 | for _, v := range s { 20 | j += v 21 | } 22 | } 23 | } 24 | assert(j == 750) 25 | } 26 | 27 | 28 | func slice_slice() { 29 | s := []int{1,2,3,4} 30 | s1 := s[:1] 31 | assert(len(s1) == 1) 32 | assert(cap(s1) == 4) 33 | 34 | s2 := s[1:] 35 | assert(len(s2) == 3) 36 | assert(cap(s2) == 3) 37 | 38 | s3 := s[1:2:2] 39 | assert(s3[0] == 2) 40 | assert(len(s3) == 1) 41 | assert(cap(s3) == 1) 42 | 43 | s4 := s[1:2:3] 44 | assert(cap(s4) == 2) 45 | 46 | // index out of range 47 | //s4 = s[1:2:11] 48 | //assert(cap(s4) == 10) 49 | } 50 | 51 | func append_slice() { 52 | m := []byte{1,3} 53 | n := []byte{2,4} 54 | t := append(m, n...) 55 | assert(t[0] == 1) 56 | assert(t[2] == 2) 57 | 58 | s := "what" 59 | s1 := append(m, s...) 60 | assert(s1[2] == 'w') 61 | assert(s1[3] == 'h') 62 | assert(s1[4] == 'a') 63 | assert(s1[5] == 't') 64 | } 65 | 66 | func copy_slice() { 67 | m := []byte{1,2,3,4} 68 | n := []byte{66,77} 69 | t := m[1:4] 70 | count := copy(t, n) 71 | assert(count == 2) 72 | assert(t[0] == 66) 73 | assert(t[1] == 77) 74 | assert(t[2] == 4) 75 | 76 | t2 := m[:1] 77 | count = copy(t2, n) 78 | assert(count == 1) 79 | assert(t2[0] == 66) 80 | assert(t2[1] == 66) 81 | assert(t2[2] == 77) 82 | 83 | count = copy(t2, "what") 84 | assert(count == 1) 85 | assert(t2[0] == 'w') 86 | assert(t2[1] == 66) 87 | } 88 | 89 | 90 | 91 | func copy_no_return() { 92 | s := "/a" 93 | buf := make([]byte, 3) 94 | copy(buf, s[:1]) 95 | assert(buf[0] == '/') 96 | } 97 | 98 | 99 | func appendToNil() { 100 | var a []int 101 | b := []int{6,6,6} 102 | a = append(a, b...) 103 | a[0] = 123 104 | assert(a[0] == 123) 105 | assert(b[0] == 6) 106 | } 107 | 108 | 109 | 110 | func main() { 111 | var s1 = [][]int{{0},{99},{2}} 112 | var s2 = []int{0,100,2} 113 | i := s1[1][0] + s2[1] - 1 114 | s2[0] = 8 115 | j := s2[0] 116 | assert(i == 198) 117 | assert(j == 8) 118 | assert(a()) 119 | 120 | f2() 121 | 122 | slice_slice() 123 | 124 | append_slice() 125 | 126 | copy_slice() 127 | 128 | copy_no_return() 129 | 130 | appendToNil() 131 | } -------------------------------------------------------------------------------- /std/math/tanh.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package math 6 | 7 | // The original C code, the long comment, and the constants 8 | // below were from http://netlib.sandia.gov/cephes/cmath/sin.c, 9 | // available from http://www.netlib.org/cephes/cmath.tgz. 10 | // The go code is a simplified version of the original C. 11 | // tanh.c 12 | // 13 | // Hyperbolic tangent 14 | // 15 | // SYNOPSIS: 16 | // 17 | // double x, y, tanh(); 18 | // 19 | // y = tanh( x ); 20 | // 21 | // DESCRIPTION: 22 | // 23 | // Returns hyperbolic tangent of argument in the range MINLOG to MAXLOG. 24 | // MAXLOG = 8.8029691931113054295988e+01 = log(2**127) 25 | // MINLOG = -8.872283911167299960540e+01 = log(2**-128) 26 | // 27 | // A rational function is used for |x| < 0.625. The form 28 | // x + x**3 P(x)/Q(x) of Cody & Waite is employed. 29 | // Otherwise, 30 | // tanh(x) = sinh(x)/cosh(x) = 1 - 2/(exp(2x) + 1). 31 | // 32 | // ACCURACY: 33 | // 34 | // Relative error: 35 | // arithmetic domain # trials peak rms 36 | // IEEE -2,2 30000 2.5e-16 5.8e-17 37 | // 38 | // Cephes Math Library Release 2.8: June, 2000 39 | // Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier 40 | // 41 | // The readme file at http://netlib.sandia.gov/cephes/ says: 42 | // Some software in this archive may be from the book _Methods and 43 | // Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster 44 | // International, 1989) or from the Cephes Mathematical Library, a 45 | // commercial product. In either event, it is copyrighted by the author. 46 | // What you see here may be used freely but it comes with no support or 47 | // guarantee. 48 | // 49 | // The two known misprints in the book are repaired here in the 50 | // source listings for the gamma function and the incomplete beta 51 | // integral. 52 | // 53 | // Stephen L. Moshier 54 | // moshier@na-net.ornl.gov 55 | // 56 | 57 | var tanhP = [...]float64{ 58 | -9.64399179425052238628e-1, 59 | -9.92877231001918586564e1, 60 | -1.61468768441708447952e3, 61 | } 62 | var tanhQ = [...]float64{ 63 | 1.12811678491632931402e2, 64 | 2.23548839060100448583e3, 65 | 4.84406305325125486048e3, 66 | } 67 | 68 | // Tanh returns the hyperbolic tangent of x. 69 | // 70 | // Special cases are: 71 | // Tanh(±0) = ±0 72 | // Tanh(±Inf) = ±1 73 | // Tanh(NaN) = NaN 74 | func Tanh(x float64) float64 { 75 | const MAXLOG = 8.8029691931113054295988e+01 // log(2**127) 76 | z := Abs(x) 77 | switch { 78 | case z > 0.5*MAXLOG: 79 | if x < 0 { 80 | return -1 81 | } 82 | return 1 83 | case z >= 0.625: 84 | s := Exp(2 * z) 85 | z = 1 - 2/(s+1) 86 | if x < 0 { 87 | z = -z 88 | } 89 | default: 90 | if x == 0 { 91 | return x 92 | } 93 | s := x * x 94 | z = x + x*s*((tanhP[0]*s+tanhP[1])*s+tanhP[2])/(((s+tanhQ[0])*s+tanhQ[1])*s+tanhQ[2]) 95 | } 96 | return z 97 | } 98 | -------------------------------------------------------------------------------- /std/math/unsafe.go: -------------------------------------------------------------------------------- 1 | // This code is adapted from the offical Go code written in Go 2 | // with license as follows: 3 | // 4 | // Copyright 2009 The Go Authors. All rights reserved. 5 | // Use of this source code is governed by a BSD-style 6 | // license that can be found in the LICENSE file. 7 | 8 | package math 9 | 10 | /* This is the offical version: 11 | import "unsafe" 12 | 13 | // Float32bits returns the IEEE 754 binary representation of f, 14 | // with the sign bit of f and the result in the same bit position. 15 | // Float32bits(Float32frombits(x)) == x. 16 | func Float32bits(f float32) uint32 { return *(*uint32)(unsafe.Pointer(&f)) } 17 | 18 | // Float32frombits returns the floating-point number corresponding 19 | // to the IEEE 754 binary representation b, with the sign bit of b 20 | // and the result in the same bit position. 21 | // Float32frombits(Float32bits(x)) == x. 22 | func Float32frombits(b uint32) float32 { return *(*float32)(unsafe.Pointer(&b)) } 23 | 24 | // Float64bits returns the IEEE 754 binary representation of f, 25 | // with the sign bit of f and the result in the same bit position, 26 | // and Float64bits(Float64frombits(x)) == x. 27 | func Float64bits(f float64) uint64 { return *(*uint64)(unsafe.Pointer(&f)) } 28 | 29 | // Float64frombits returns the floating-point number corresponding 30 | // to the IEEE 754 binary representation b, with the sign bit of b 31 | // and the result in the same bit position. 32 | // Float64frombits(Float64bits(x)) == x. 33 | func Float64frombits(b uint64) float64 { return *(*float64)(unsafe.Pointer(&b)) } 34 | */ 35 | 36 | var native ffiBits 37 | 38 | func init() { 39 | native = ffi(ffiBits, "bits") 40 | } 41 | 42 | type ffiBits interface { 43 | f32_to_bits(f float32) uint32 44 | f32_from_bits(b uint32) float32 45 | f64_to_bits(f float64) uint64 46 | f64_from_bits(b uint64) float64 47 | } 48 | 49 | // Float32bits returns the IEEE 754 binary representation of f, 50 | // with the sign bit of f and the result in the same bit position. 51 | // Float32bits(Float32frombits(x)) == x. 52 | func Float32bits(f float32) uint32 { 53 | return native.f32_to_bits(f) 54 | } 55 | 56 | // Float32frombits returns the floating-point number corresponding 57 | // to the IEEE 754 binary representation b, with the sign bit of b 58 | // and the result in the same bit position. 59 | // Float32frombits(Float32bits(x)) == x. 60 | func Float32frombits(b uint32) float32 { 61 | return native.f32_from_bits(b) 62 | } 63 | 64 | // Float64bits returns the IEEE 754 binary representation of f, 65 | // with the sign bit of f and the result in the same bit position, 66 | // and Float64bits(Float64frombits(x)) == x. 67 | func Float64bits(f float64) uint64 { 68 | return native.f64_to_bits(f) 69 | } 70 | 71 | // Float64frombits returns the floating-point number corresponding 72 | // to the IEEE 754 binary representation b, with the sign bit of b 73 | // and the result in the same bit position. 74 | // Float64frombits(Float64bits(x)) == x. 75 | func Float64frombits(b uint64) float64 { 76 | return native.f64_from_bits(b) 77 | } 78 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD License 2 | 3 | Copyright (c) 2022 Goscript authors 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 18 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 21 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | 25 | 26 | 27 | 28 | 29 | ////////////////////////////////////////////////////////////////////////////// 30 | BSD license of the original Go source code: 31 | ////////////////////////////////////////////////////////////////////////////// 32 | 33 | Copyright (c) 2009 The Go Authors. All rights reserved. 34 | 35 | Redistribution and use in source and binary forms, with or without 36 | modification, are permitted provided that the following conditions are 37 | met: 38 | 39 | * Redistributions of source code must retain the above copyright 40 | notice, this list of conditions and the following disclaimer. 41 | * Redistributions in binary form must reproduce the above 42 | copyright notice, this list of conditions and the following disclaimer 43 | in the documentation and/or other materials provided with the 44 | distribution. 45 | * Neither the name of Google Inc. nor the names of its 46 | contributors may be used to endorse or promote products derived from 47 | this software without specific prior written permission. 48 | 49 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 50 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 51 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 52 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 53 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 54 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 55 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 56 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 57 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 58 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 59 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 60 | -------------------------------------------------------------------------------- /std/io/multi.go: -------------------------------------------------------------------------------- 1 | // Copyright 2010 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package io 6 | 7 | type eofReader struct{} 8 | 9 | func (eofReader) Read([]byte) (int, error) { 10 | return 0, EOF 11 | } 12 | 13 | type multiReader struct { 14 | readers []Reader 15 | } 16 | 17 | func (mr *multiReader) Read(p []byte) (n int, err error) { 18 | for len(mr.readers) > 0 { 19 | // Optimization to flatten nested multiReaders (Issue 13558). 20 | if len(mr.readers) == 1 { 21 | if r, ok := mr.readers[0].(*multiReader); ok { 22 | mr.readers = r.readers 23 | continue 24 | } 25 | } 26 | n, err = mr.readers[0].Read(p) 27 | if err == EOF { 28 | // Use eofReader instead of nil to avoid nil panic 29 | // after performing flatten (Issue 18232). 30 | mr.readers[0] = eofReader{} // permit earlier GC 31 | mr.readers = mr.readers[1:] 32 | } 33 | if n > 0 || err != EOF { 34 | if err == EOF && len(mr.readers) > 0 { 35 | // Don't return EOF yet. More readers remain. 36 | err = nil 37 | } 38 | return 39 | } 40 | } 41 | return 0, EOF 42 | } 43 | 44 | // MultiReader returns a Reader that's the logical concatenation of 45 | // the provided input readers. They're read sequentially. Once all 46 | // inputs have returned EOF, Read will return EOF. If any of the readers 47 | // return a non-nil, non-EOF error, Read will return that error. 48 | func MultiReader(readers ...Reader) Reader { 49 | r := make([]Reader, len(readers)) 50 | copy(r, readers) 51 | return &multiReader{r} 52 | } 53 | 54 | type multiWriter struct { 55 | writers []Writer 56 | } 57 | 58 | func (t *multiWriter) Write(p []byte) (n int, err error) { 59 | for _, w := range t.writers { 60 | n, err = w.Write(p) 61 | if err != nil { 62 | return 63 | } 64 | if n != len(p) { 65 | err = ErrShortWrite 66 | return 67 | } 68 | } 69 | return len(p), nil 70 | } 71 | 72 | var _ StringWriter = (*multiWriter)(nil) 73 | 74 | func (t *multiWriter) WriteString(s string) (n int, err error) { 75 | var p []byte // lazily initialized if/when needed 76 | for _, w := range t.writers { 77 | if sw, ok := w.(StringWriter); ok { 78 | n, err = sw.WriteString(s) 79 | } else { 80 | if p == nil { 81 | p = []byte(s) 82 | } 83 | n, err = w.Write(p) 84 | } 85 | if err != nil { 86 | return 87 | } 88 | if n != len(s) { 89 | err = ErrShortWrite 90 | return 91 | } 92 | } 93 | return len(s), nil 94 | } 95 | 96 | // MultiWriter creates a writer that duplicates its writes to all the 97 | // provided writers, similar to the Unix tee(1) command. 98 | // 99 | // Each write is written to each listed writer, one at a time. 100 | // If a listed writer returns an error, that overall write operation 101 | // stops and returns the error; it does not continue down the list. 102 | func MultiWriter(writers ...Writer) Writer { 103 | allWriters := make([]Writer, 0, len(writers)) 104 | for _, w := range writers { 105 | if mw, ok := w.(*multiWriter); ok { 106 | allWriters = append(allWriters, mw.writers...) 107 | } else { 108 | allWriters = append(allWriters, w) 109 | } 110 | } 111 | return &multiWriter{allWriters} 112 | } 113 | -------------------------------------------------------------------------------- /std/math/trig_reduce.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package math 6 | 7 | import ( 8 | "math/bits" 9 | ) 10 | 11 | // reduceThreshold is the maximum value where the reduction using Pi/4 12 | // in 3 float64 parts still gives accurate results. Above this 13 | // threshold Payne-Hanek range reduction must be used. 14 | const reduceThreshold = (1 << 52) / (4 / Pi) 15 | 16 | // trigReduce implements Payne-Hanek range reduction by Pi/4 17 | // for x > 0. It returns the integer part mod 8 (j) and 18 | // the fractional part (z) of x / (Pi/4). 19 | // The implementation is based on: 20 | // "ARGUMENT REDUCTION FOR HUGE ARGUMENTS: Good to the Last Bit" 21 | // K. C. Ng et al, March 24, 1992 22 | // The simulated multi-precision calculation of x*B uses 64-bit integer arithmetic. 23 | func trigReduce(x float64) (j uint64, z float64) { 24 | const PI4 = Pi / 4 25 | if x < PI4 { 26 | return 0, x 27 | } 28 | // Extract out the integer and exponent such that, 29 | // x = ix * 2 ** exp. 30 | ix := Float64bits(x) 31 | exp := int(ix>>shift&mask) - bias - shift 32 | ix &^= mask << shift 33 | ix |= 1 << shift 34 | // Use the exponent to extract the 3 appropriate uint64 digits from mPi4, 35 | // B ~ (z0, z1, z2), such that the product leading digit has the exponent -61. 36 | // Note, exp >= -53 since x >= PI4 and exp < 971 for maximum float64. 37 | digit, bitshift := uint(exp+61)/64, uint(exp+61)%64 38 | z0 := (mPi4[digit] << bitshift) | (mPi4[digit+1] >> (64 - bitshift)) 39 | z1 := (mPi4[digit+1] << bitshift) | (mPi4[digit+2] >> (64 - bitshift)) 40 | z2 := (mPi4[digit+2] << bitshift) | (mPi4[digit+3] >> (64 - bitshift)) 41 | // Multiply mantissa by the digits and extract the upper two digits (hi, lo). 42 | z2hi, _ := bits.Mul64(z2, ix) 43 | z1hi, z1lo := bits.Mul64(z1, ix) 44 | z0lo := z0 * ix 45 | lo, c := bits.Add64(z1lo, z2hi, 0) 46 | hi, _ := bits.Add64(z0lo, z1hi, c) 47 | // The top 3 bits are j. 48 | j = hi >> 61 49 | // Extract the fraction and find its magnitude. 50 | hi = hi<<3 | lo>>61 51 | lz := uint(bits.LeadingZeros64(hi)) 52 | e := uint64(bias - (lz + 1)) 53 | // Clear implicit mantissa bit and shift into place. 54 | hi = (hi << (lz + 1)) | (lo >> (64 - (lz + 1))) 55 | hi >>= 64 - shift 56 | // Include the exponent and convert to a float. 57 | hi |= e << shift 58 | z = Float64frombits(hi) 59 | // Map zeros to origin. 60 | if j&1 == 1 { 61 | j++ 62 | j &= 7 63 | z-- 64 | } 65 | // Multiply the fractional part by pi/4. 66 | return j, z * PI4 67 | } 68 | 69 | // mPi4 is the binary digits of 4/pi as a uint64 array, 70 | // that is, 4/pi = Sum mPi4[i]*2^(-64*i) 71 | // 19 64-bit digits and the leading one bit give 1217 bits 72 | // of precision to handle the largest possible float64 exponent. 73 | var mPi4 = [...]uint64{ 74 | 0x0000000000000001, 75 | 0x45f306dc9c882a53, 76 | 0xf84eafa3ea69bb81, 77 | 0xb6c52b3278872083, 78 | 0xfca2c757bd778ac3, 79 | 0x6e48dc74849ba5c0, 80 | 0x0c925dd413a32439, 81 | 0xfc3bd63962534e7d, 82 | 0xd1046bea5d768909, 83 | 0xd338e04d68befc82, 84 | 0x7323ac7306a673e9, 85 | 0x3908bf177bf25076, 86 | 0x3ff12fffbc0b301f, 87 | 0xde5e2316b414da3e, 88 | 0xda6cfd9e4f96136e, 89 | 0x9e8c7ecd3cbfd45a, 90 | 0xea4f758fd7cbe2f6, 91 | 0x7a0e73ef14a525d4, 92 | 0xd7f6bf623f1aba10, 93 | 0xac06608df8f6d757, 94 | } 95 | -------------------------------------------------------------------------------- /std/unicode/utf16/utf16.go: -------------------------------------------------------------------------------- 1 | // Copyright 2010 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package utf16 implements encoding and decoding of UTF-16 sequences. 6 | package utf16 7 | 8 | // The conditions replacementChar==unicode.ReplacementChar and 9 | // maxRune==unicode.MaxRune are verified in the tests. 10 | // Defining them locally avoids this package depending on package unicode. 11 | 12 | const ( 13 | replacementChar = '\uFFFD' // Unicode replacement character 14 | maxRune = '\U0010FFFF' // Maximum valid Unicode code point. 15 | ) 16 | 17 | const ( 18 | // 0xd800-0xdc00 encodes the high 10 bits of a pair. 19 | // 0xdc00-0xe000 encodes the low 10 bits of a pair. 20 | // the value is those 20 bits plus 0x10000. 21 | surr1 = 0xd800 22 | surr2 = 0xdc00 23 | surr3 = 0xe000 24 | 25 | surrSelf = 0x10000 26 | ) 27 | 28 | // IsSurrogate reports whether the specified Unicode code point 29 | // can appear in a surrogate pair. 30 | func IsSurrogate(r rune) bool { 31 | return surr1 <= r && r < surr3 32 | } 33 | 34 | // DecodeRune returns the UTF-16 decoding of a surrogate pair. 35 | // If the pair is not a valid UTF-16 surrogate pair, DecodeRune returns 36 | // the Unicode replacement code point U+FFFD. 37 | func DecodeRune(r1, r2 rune) rune { 38 | if surr1 <= r1 && r1 < surr2 && surr2 <= r2 && r2 < surr3 { 39 | return (r1-surr1)<<10 | (r2 - surr2) + surrSelf 40 | } 41 | return replacementChar 42 | } 43 | 44 | // EncodeRune returns the UTF-16 surrogate pair r1, r2 for the given rune. 45 | // If the rune is not a valid Unicode code point or does not need encoding, 46 | // EncodeRune returns U+FFFD, U+FFFD. 47 | func EncodeRune(r rune) (r1, r2 rune) { 48 | if r < surrSelf || r > maxRune { 49 | return replacementChar, replacementChar 50 | } 51 | r -= surrSelf 52 | return surr1 + (r>>10)&0x3ff, surr2 + r&0x3ff 53 | } 54 | 55 | // Encode returns the UTF-16 encoding of the Unicode code point sequence s. 56 | func Encode(s []rune) []uint16 { 57 | n := len(s) 58 | for _, v := range s { 59 | if v >= surrSelf { 60 | n++ 61 | } 62 | } 63 | 64 | a := make([]uint16, n) 65 | n = 0 66 | for _, v := range s { 67 | switch { 68 | case 0 <= v && v < surr1, surr3 <= v && v < surrSelf: 69 | // normal rune 70 | a[n] = uint16(v) 71 | n++ 72 | case surrSelf <= v && v <= maxRune: 73 | // needs surrogate sequence 74 | r1, r2 := EncodeRune(v) 75 | a[n] = uint16(r1) 76 | a[n+1] = uint16(r2) 77 | n += 2 78 | default: 79 | a[n] = uint16(replacementChar) 80 | n++ 81 | } 82 | } 83 | return a[:n] 84 | } 85 | 86 | // Decode returns the Unicode code point sequence represented 87 | // by the UTF-16 encoding s. 88 | func Decode(s []uint16) []rune { 89 | a := make([]rune, len(s)) 90 | n := 0 91 | for i := 0; i < len(s); i++ { 92 | switch r := s[i]; { 93 | case r < surr1, surr3 <= r: 94 | // normal rune 95 | a[n] = rune(r) 96 | case surr1 <= r && r < surr2 && i+1 < len(s) && 97 | surr2 <= s[i+1] && s[i+1] < surr3: 98 | // valid surrogate sequence 99 | a[n] = DecodeRune(rune(r), rune(s[i+1])) 100 | i++ 101 | default: 102 | // invalid surrogate sequence 103 | a[n] = replacementChar 104 | } 105 | n++ 106 | } 107 | return a[:n] 108 | } 109 | -------------------------------------------------------------------------------- /std/strings/builder.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package strings 6 | 7 | import ( 8 | "unicode/utf8" 9 | "unsafe" 10 | ) 11 | 12 | // A Builder is used to efficiently build a string using Write methods. 13 | // It minimizes memory copying. The zero value is ready to use. 14 | // Do not copy a non-zero Builder. 15 | type Builder struct { 16 | addr *Builder // of receiver, to detect copies by value 17 | buf []byte 18 | } 19 | 20 | func (b *Builder) copyCheck() { 21 | if b.addr == nil { 22 | b.addr = b 23 | } else if b.addr != b { 24 | panic("strings: illegal use of non-zero Builder copied by value") 25 | } 26 | } 27 | 28 | // String returns the accumulated string. 29 | func (b *Builder) String() string { 30 | return *(*string)(unsafe.Pointer(&b.buf)) 31 | } 32 | 33 | // Len returns the number of accumulated bytes; b.Len() == len(b.String()). 34 | func (b *Builder) Len() int { return len(b.buf) } 35 | 36 | // Cap returns the capacity of the builder's underlying byte slice. It is the 37 | // total space allocated for the string being built and includes any bytes 38 | // already written. 39 | func (b *Builder) Cap() int { return cap(b.buf) } 40 | 41 | // Reset resets the Builder to be empty. 42 | func (b *Builder) Reset() { 43 | b.addr = nil 44 | b.buf = nil 45 | } 46 | 47 | // grow copies the buffer to a new, larger buffer so that there are at least n 48 | // bytes of capacity beyond len(b.buf). 49 | func (b *Builder) grow(n int) { 50 | buf := make([]byte, len(b.buf), 2*cap(b.buf)+n) 51 | copy(buf, b.buf) 52 | b.buf = buf 53 | } 54 | 55 | // Grow grows b's capacity, if necessary, to guarantee space for 56 | // another n bytes. After Grow(n), at least n bytes can be written to b 57 | // without another allocation. If n is negative, Grow panics. 58 | func (b *Builder) Grow(n int) { 59 | b.copyCheck() 60 | if n < 0 { 61 | panic("strings.Builder.Grow: negative count") 62 | } 63 | if cap(b.buf)-len(b.buf) < n { 64 | b.grow(n) 65 | } 66 | } 67 | 68 | // Write appends the contents of p to b's buffer. 69 | // Write always returns len(p), nil. 70 | func (b *Builder) Write(p []byte) (int, error) { 71 | b.copyCheck() 72 | b.buf = append(b.buf, p...) 73 | return len(p), nil 74 | } 75 | 76 | // WriteByte appends the byte c to b's buffer. 77 | // The returned error is always nil. 78 | func (b *Builder) WriteByte(c byte) error { 79 | b.copyCheck() 80 | b.buf = append(b.buf, c) 81 | return nil 82 | } 83 | 84 | // WriteRune appends the UTF-8 encoding of Unicode code point r to b's buffer. 85 | // It returns the length of r and a nil error. 86 | func (b *Builder) WriteRune(r rune) (int, error) { 87 | b.copyCheck() 88 | if r < utf8.RuneSelf { 89 | b.buf = append(b.buf, byte(r)) 90 | return 1, nil 91 | } 92 | l := len(b.buf) 93 | if cap(b.buf)-l < utf8.UTFMax { 94 | b.grow(utf8.UTFMax) 95 | } 96 | n := utf8.EncodeRune(b.buf[l:l+utf8.UTFMax], r) 97 | b.buf = b.buf[:l+n] 98 | return n, nil 99 | } 100 | 101 | // WriteString appends the contents of s to b's buffer. 102 | // It returns the length of s and a nil error. 103 | func (b *Builder) WriteString(s string) (int, error) { 104 | b.copyCheck() 105 | b.buf = append(b.buf, s...) 106 | return len(s), nil 107 | } 108 | --------------------------------------------------------------------------------