goscript 0.0.62 → 0.0.68
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +54 -47
- package/cmd/goscript/main.go +4 -0
- package/compiler/analysis.go +182 -101
- package/compiler/analysis_test.go +3 -3
- package/compiler/assignment.go +28 -0
- package/compiler/builtin_test.go +1 -1
- package/compiler/compiler.go +25 -18
- package/compiler/compiler_test.go +9 -9
- package/compiler/expr-call.go +10 -3
- package/compiler/expr.go +24 -0
- package/compiler/spec.go +4 -2
- package/compiler/stmt-assign.go +53 -0
- package/compiler/stmt.go +32 -14
- package/compiler/type-info.go +3 -5
- package/compiler/type.go +2 -2
- package/dist/gs/builtin/slice.js +43 -37
- package/dist/gs/builtin/slice.js.map +1 -1
- package/dist/gs/builtin/varRef.d.ts +3 -0
- package/dist/gs/builtin/varRef.js +6 -1
- package/dist/gs/builtin/varRef.js.map +1 -1
- package/dist/gs/reflect/type.d.ts +4 -1
- package/dist/gs/reflect/type.js +91 -9
- package/dist/gs/reflect/type.js.map +1 -1
- package/dist/gs/strconv/atoi.gs.js +20 -2
- package/dist/gs/strconv/atoi.gs.js.map +1 -1
- package/dist/gs/sync/atomic/type.gs.d.ts +3 -3
- package/dist/gs/sync/atomic/type.gs.js +5 -9
- package/dist/gs/sync/atomic/type.gs.js.map +1 -1
- package/go.mod +2 -2
- package/go.sum +4 -0
- package/gs/builtin/slice.ts +55 -48
- package/gs/builtin/varRef.ts +8 -2
- package/gs/reflect/type.ts +103 -9
- package/gs/strconv/atoi.gs.ts +18 -2
- package/gs/sync/atomic/type.gs.ts +8 -12
- package/package.json +13 -4
package/README.md
CHANGED
|
@@ -19,45 +19,42 @@ GoScript is an experimental **Go to TypeScript compiler** that translates Go cod
|
|
|
19
19
|
|
|
20
20
|
Write once, run everywhere. Share your Go algorithms, business logic, and data structures seamlessly between your backend and frontend without maintaining two codebases.
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
**Use cases:**
|
|
23
|
+
|
|
23
24
|
- Sharing business logic between Go services and web apps
|
|
24
25
|
- Porting Go algorithms to run in browsers
|
|
25
26
|
- Building TypeScript libraries from existing Go code
|
|
26
27
|
|
|
27
28
|
Go has powerful concurrency support and an excellent standard library. GoScript brings these capabilities to TypeScript with as simple and readable of a translation as possible.
|
|
28
29
|
|
|
29
|
-
|
|
30
|
-
GoScript is working on compiling a subset of Go:
|
|
31
|
-
- ✅ Basic structs, interfaces, methods, and functions
|
|
32
|
-
- ✅ Channels and goroutines (translating to async/await)
|
|
33
|
-
- ✅ Slice semantics, maps, and built-in types
|
|
34
|
-
- ✅ Standard control flow (if, for, switch, select, range, etc.)
|
|
35
|
-
- 🚧 Basic reflection support
|
|
36
|
-
- 🚧 Standard library support
|
|
30
|
+
**✅ What works:**
|
|
37
31
|
|
|
38
|
-
|
|
39
|
-
-
|
|
40
|
-
-
|
|
41
|
-
-
|
|
42
|
-
-
|
|
43
|
-
-
|
|
32
|
+
- Structs, interfaces, methods, and functions with full value semantics
|
|
33
|
+
- Channels and goroutines (translated to async/await with function coloring)
|
|
34
|
+
- Pointers and addressability (via VarRef system)
|
|
35
|
+
- Slices, maps, and built-in types
|
|
36
|
+
- Control flow (if, for, switch, select, range, defer, etc.)
|
|
37
|
+
- Type assertions and interface implementations
|
|
38
|
+
- Closures and anonymous functions
|
|
44
39
|
|
|
45
|
-
|
|
40
|
+
**🚧 In progress:**
|
|
46
41
|
|
|
47
|
-
|
|
42
|
+
- Reflection support
|
|
43
|
+
- Standard library coverage
|
|
44
|
+
- Generics
|
|
48
45
|
|
|
49
|
-
**
|
|
46
|
+
**Known limitations:**
|
|
50
47
|
|
|
51
|
-
|
|
48
|
+
- Uses JavaScript `number` type (64-bit float, not Go's int types)
|
|
49
|
+
- No pointer arithmetic (`uintptr`) or `unsafe` package
|
|
50
|
+
- No complex numbers
|
|
52
51
|
|
|
53
|
-
|
|
52
|
+
📖 **Learn more:** [Design document](./design/DESIGN.md) | [Architecture explainer](./docs/explainer.md) | [Compliance tests](./tests/README.md)
|
|
54
53
|
|
|
55
|
-
|
|
54
|
+
🐛 **Found an issue?** Please [open an issue](https://github.com/aperturerobotics/goscript/issues).
|
|
56
55
|
|
|
57
56
|
## 🚀 Try It
|
|
58
57
|
|
|
59
|
-
> **Warning:** This is experimental software. Features may be incomplete or broken. Please report any issues!
|
|
60
|
-
|
|
61
58
|
### Prerequisites
|
|
62
59
|
|
|
63
60
|
GoScript requires [Bun](https://bun.sh) to be installed for running compliance tests:
|
|
@@ -70,11 +67,13 @@ curl -fsSL https://bun.sh/install | bash
|
|
|
70
67
|
### Installation
|
|
71
68
|
|
|
72
69
|
**Option 1: Go Install**
|
|
70
|
+
|
|
73
71
|
```bash
|
|
74
72
|
go install github.com/aperturerobotics/goscript/cmd/goscript@latest
|
|
75
73
|
```
|
|
76
74
|
|
|
77
75
|
**Option 2: NPM** (if available)
|
|
76
|
+
|
|
78
77
|
```bash
|
|
79
78
|
npm install -g goscript
|
|
80
79
|
```
|
|
@@ -86,8 +85,6 @@ npm install -g goscript
|
|
|
86
85
|
goscript compile --package . --output ./dist
|
|
87
86
|
```
|
|
88
87
|
|
|
89
|
-
**Note:** Many Go packages may not compile successfully yet. Start with simple code and gradually test more complex features.
|
|
90
|
-
|
|
91
88
|
## 📦 Using Generated Code in Your Project
|
|
92
89
|
|
|
93
90
|
After compiling your Go code to TypeScript, you'll need to set up your project appropriately.
|
|
@@ -116,6 +113,7 @@ Create or update your `tsconfig.json` with these settings:
|
|
|
116
113
|
```
|
|
117
114
|
|
|
118
115
|
**Important requirements:**
|
|
116
|
+
|
|
119
117
|
- **`target: "ES2022"` or newer** - Required for `Disposable` and other features
|
|
120
118
|
- **`lib: ["esnext.disposable"]`** - Enables TypeScript's disposable types for resource management
|
|
121
119
|
- **`baseUrl` and `paths`** - Allows TypeScript to resolve `@goscript/*` imports
|
|
@@ -132,12 +130,14 @@ goscript compile --package ./my-go-code --output ./dist
|
|
|
132
130
|
```
|
|
133
131
|
|
|
134
132
|
**Options:**
|
|
133
|
+
|
|
135
134
|
- `--package <path>` - Go package to compile (default: ".")
|
|
136
135
|
- `--output <dir>` - Output directory for TypeScript files
|
|
137
136
|
|
|
138
137
|
### Programmatic API
|
|
139
138
|
|
|
140
139
|
**Go:**
|
|
140
|
+
|
|
141
141
|
```go
|
|
142
142
|
import "github.com/aperturerobotics/goscript/compiler"
|
|
143
143
|
|
|
@@ -147,24 +147,26 @@ _, err = comp.CompilePackages(ctx, "your/package/path")
|
|
|
147
147
|
```
|
|
148
148
|
|
|
149
149
|
**Node.js:**
|
|
150
|
+
|
|
150
151
|
```typescript
|
|
151
152
|
import { compile } from 'goscript'
|
|
152
153
|
|
|
153
154
|
await compile({
|
|
154
155
|
pkg: './my-go-package',
|
|
155
|
-
output: './dist'
|
|
156
|
+
output: './dist',
|
|
156
157
|
})
|
|
157
158
|
```
|
|
158
159
|
|
|
159
160
|
### Frontend Frameworks
|
|
160
161
|
|
|
161
162
|
**React + GoScript:**
|
|
163
|
+
|
|
162
164
|
```typescript
|
|
163
165
|
import { NewCalculator } from '@goscript/myapp/calculator'
|
|
164
166
|
|
|
165
167
|
function CalculatorApp() {
|
|
166
168
|
const [calc] = useState(() => NewCalculator())
|
|
167
|
-
|
|
169
|
+
|
|
168
170
|
const handleAdd = () => {
|
|
169
171
|
const result = calc.Add(5, 3)
|
|
170
172
|
setResult(result)
|
|
@@ -175,13 +177,12 @@ function CalculatorApp() {
|
|
|
175
177
|
```
|
|
176
178
|
|
|
177
179
|
**Vue + GoScript:**
|
|
180
|
+
|
|
178
181
|
```vue
|
|
179
182
|
<script setup lang="ts">
|
|
180
183
|
import { NewUser, FindUserByEmail } from '@goscript/myapp/user'
|
|
181
184
|
|
|
182
|
-
const users = ref([
|
|
183
|
-
NewUser(1, "Alice", "alice@example.com")
|
|
184
|
-
])
|
|
185
|
+
const users = ref([NewUser(1, 'Alice', 'alice@example.com')])
|
|
185
186
|
|
|
186
187
|
const searchUser = (email: string) => {
|
|
187
188
|
return FindUserByEmail(users.value, email)
|
|
@@ -189,14 +190,14 @@ const searchUser = (email: string) => {
|
|
|
189
190
|
</script>
|
|
190
191
|
```
|
|
191
192
|
|
|
192
|
-
|
|
193
193
|
## 💡 See It In Action
|
|
194
194
|
|
|
195
|
-
|
|
195
|
+
See the [example/app](./example/app) for a full todo list application using GoScript with tRPC, Drizzle ORM, and React, or [example/simple](./example/simple) for a comprehensive demo of language features.
|
|
196
196
|
|
|
197
197
|
### Example: User Management
|
|
198
198
|
|
|
199
199
|
**Go Code** (`user.go`):
|
|
200
|
+
|
|
200
201
|
```go
|
|
201
202
|
package main
|
|
202
203
|
|
|
@@ -225,20 +226,22 @@ func FindUserByEmail(users []*User, email string) *User {
|
|
|
225
226
|
```
|
|
226
227
|
|
|
227
228
|
**Compile it:**
|
|
229
|
+
|
|
228
230
|
```bash
|
|
229
231
|
goscript compile --package . --output ./dist
|
|
230
232
|
```
|
|
231
233
|
|
|
232
234
|
**Generated TypeScript** (`user.gs.ts`):
|
|
235
|
+
|
|
233
236
|
```typescript
|
|
234
237
|
export class User {
|
|
235
238
|
public ID: number = 0
|
|
236
|
-
public Name: string =
|
|
237
|
-
public Email: string =
|
|
239
|
+
public Name: string = ''
|
|
240
|
+
public Email: string = ''
|
|
238
241
|
|
|
239
242
|
public IsValid(): boolean {
|
|
240
243
|
const u = this
|
|
241
|
-
return u.Name !==
|
|
244
|
+
return u.Name !== '' && u.Email !== ''
|
|
242
245
|
}
|
|
243
246
|
|
|
244
247
|
constructor(init?: Partial<User>) {
|
|
@@ -261,26 +264,28 @@ export function FindUserByEmail(users: User[], email: string): User | null {
|
|
|
261
264
|
```
|
|
262
265
|
|
|
263
266
|
**Use in your frontend:**
|
|
267
|
+
|
|
264
268
|
```typescript
|
|
265
269
|
import { NewUser, FindUserByEmail } from '@goscript/myapp/user'
|
|
266
270
|
|
|
267
271
|
// Same logic, now in TypeScript!
|
|
268
272
|
const users = [
|
|
269
|
-
NewUser(1,
|
|
270
|
-
NewUser(2,
|
|
273
|
+
NewUser(1, 'Alice', 'alice@example.com'),
|
|
274
|
+
NewUser(2, 'Bob', 'bob@example.com'),
|
|
271
275
|
]
|
|
272
276
|
|
|
273
|
-
const alice = FindUserByEmail(users,
|
|
277
|
+
const alice = FindUserByEmail(users, 'alice@example.com')
|
|
274
278
|
console.log(alice?.IsValid()) // true
|
|
275
279
|
```
|
|
276
280
|
|
|
277
281
|
### Example: Async Processing with Channels
|
|
278
282
|
|
|
279
283
|
**Go Code:**
|
|
284
|
+
|
|
280
285
|
```go
|
|
281
286
|
func ProcessMessages(messages []string) chan string {
|
|
282
287
|
results := make(chan string, len(messages))
|
|
283
|
-
|
|
288
|
+
|
|
284
289
|
for _, msg := range messages {
|
|
285
290
|
go func(m string) {
|
|
286
291
|
// Simulate processing
|
|
@@ -288,34 +293,36 @@ func ProcessMessages(messages []string) chan string {
|
|
|
288
293
|
results <- processed
|
|
289
294
|
}(msg)
|
|
290
295
|
}
|
|
291
|
-
|
|
296
|
+
|
|
292
297
|
return results
|
|
293
298
|
}
|
|
294
299
|
```
|
|
295
300
|
|
|
296
301
|
**Generated TypeScript:**
|
|
302
|
+
|
|
297
303
|
```typescript
|
|
298
304
|
export function ProcessMessages(messages: string[]): $.Channel<string> {
|
|
299
|
-
let results = $.makeChannel<string>(messages.length,
|
|
300
|
-
|
|
305
|
+
let results = $.makeChannel<string>(messages.length, '')
|
|
306
|
+
|
|
301
307
|
for (let msg of messages) {
|
|
302
308
|
queueMicrotask(async (m: string) => {
|
|
303
|
-
let processed =
|
|
309
|
+
let processed = '✓ ' + m
|
|
304
310
|
await results.send(processed)
|
|
305
311
|
})(msg)
|
|
306
312
|
}
|
|
307
|
-
|
|
313
|
+
|
|
308
314
|
return results
|
|
309
315
|
}
|
|
310
316
|
```
|
|
311
317
|
|
|
312
318
|
**Use with async/await:**
|
|
319
|
+
|
|
313
320
|
```typescript
|
|
314
321
|
import { ProcessMessages } from '@goscript/myapp/processor'
|
|
315
322
|
|
|
316
323
|
async function handleMessages() {
|
|
317
|
-
const channel = ProcessMessages([
|
|
318
|
-
|
|
324
|
+
const channel = ProcessMessages(['hello', 'world', 'goscript'])
|
|
325
|
+
|
|
319
326
|
// Receive processed messages
|
|
320
327
|
for (let i = 0; i < 3; i++) {
|
|
321
328
|
const result = await channel.receive()
|
|
@@ -327,7 +334,7 @@ async function handleMessages() {
|
|
|
327
334
|
## 🤝 How You Can Help
|
|
328
335
|
|
|
329
336
|
- Try GoScript on your code and [report issues](https://github.com/aperturerobotics/goscript/issues)
|
|
330
|
-
- Check the [compliance tests](./
|
|
337
|
+
- Check the [compliance tests](./tests/README.md) for current progress
|
|
331
338
|
- Contribute test cases for edge cases you discover
|
|
332
339
|
|
|
333
340
|
## License
|
package/cmd/goscript/main.go
CHANGED
|
@@ -6,8 +6,12 @@ import (
|
|
|
6
6
|
"github.com/aperturerobotics/cli"
|
|
7
7
|
)
|
|
8
8
|
|
|
9
|
+
// version is set by goreleaser via ldflags
|
|
10
|
+
var version = "dev"
|
|
11
|
+
|
|
9
12
|
func main() {
|
|
10
13
|
app := cli.NewApp()
|
|
14
|
+
app.Version = version
|
|
11
15
|
|
|
12
16
|
app.Authors = []*cli.Author{
|
|
13
17
|
{Name: "Christian Stewart", Email: "christian@aperture.us"},
|