Skip to content

Commit 1e537aa

Browse files
authored
Merge pull request #46 from moeshin/fix-constant-value
Fix constant value
2 parents 342962e + 5f49821 commit 1e537aa

File tree

4 files changed

+107
-27
lines changed

4 files changed

+107
-27
lines changed

examples/abstract/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ export const FourString: string = "four";
1313
export const AlsoFourString: string = "four";
1414
export const Five = 5;
1515
export const FiveAgain = 5;
16-
export const Sixteen = 16;
17-
export const Seventeen = 17;
16+
export const Sixteen = 10 + 6;
17+
export const Seventeen = 11 + 6;
1818

1919
//////////
2020
// source: misc.go

tygo/iota.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import (
99
var iotaRegexp = regexp.MustCompile(`\biota\b`)
1010

1111
func isProbablyIotaType(valueString string) bool {
12-
return !strings.ContainsAny(valueString, "\"'`") && iotaRegexp.MatchString(valueString)
12+
return !strings.ContainsAny(valueString, "\"`") && iotaRegexp.MatchString(valueString)
1313
}
1414

1515
func replaceIotaValue(valueString string, iotaValue int) string {

tygo/write.go

Lines changed: 100 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,36 @@
11
package tygo
22

33
import (
4+
"encoding/json"
45
"fmt"
56
"go/ast"
67
"go/token"
78
"regexp"
9+
"strconv"
810
"strings"
911

1012
"github.com/fatih/structtag"
1113
)
1214

1315
var validJSNameRegexp = regexp.MustCompile(`(?m)^[\pL_][\pL\pN_]*$`)
1416
var backquoteEscapeRegexp = regexp.MustCompile(`([$\\])`)
17+
var octalPrefixRegexp = regexp.MustCompile(`^0[0-7]`)
18+
var unicode8Regexp = regexp.MustCompile(`\\\\|\\U[\da-fA-F]{8}`)
19+
20+
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_precedence#table
21+
var jsNumberOperatorPrecedence = map[token.Token]int{
22+
token.MUL: 6,
23+
token.QUO: 6,
24+
token.REM: 6,
25+
token.ADD: 5,
26+
token.SUB: 5,
27+
token.SHL: 4,
28+
token.SHR: 4,
29+
token.AND: 3,
30+
token.AND_NOT: 3,
31+
token.OR: 2,
32+
token.XOR: 1,
33+
}
1534

1635
func validJSName(n string) bool {
1736
return validJSNameRegexp.MatchString(n)
@@ -39,15 +58,17 @@ func (g *PackageGenerator) writeIndent(s *strings.Builder, depth int) {
3958
func (g *PackageGenerator) writeType(
4059
s *strings.Builder,
4160
t ast.Expr,
61+
p ast.Expr,
4262
depth int,
4363
optionalParens bool,
4464
) {
65+
// log.Println("writeType:", reflect.TypeOf(t), t)
4566
switch t := t.(type) {
4667
case *ast.StarExpr:
4768
if optionalParens {
4869
s.WriteByte('(')
4970
}
50-
g.writeType(s, t.X, depth, false)
71+
g.writeType(s, t.X, t, depth, false)
5172
s.WriteString(" | undefined")
5273
if optionalParens {
5374
s.WriteByte(')')
@@ -57,7 +78,7 @@ func (g *PackageGenerator) writeType(
5778
s.WriteString("string")
5879
break
5980
}
60-
g.writeType(s, t.Elt, depth, true)
81+
g.writeType(s, t.Elt, t, depth, true)
6182
s.WriteString("[]")
6283
case *ast.StructType:
6384
s.WriteString("{\n")
@@ -84,25 +105,83 @@ func (g *PackageGenerator) writeType(
84105
}
85106
case *ast.MapType:
86107
s.WriteString("{ [key: ")
87-
g.writeType(s, t.Key, depth, false)
108+
g.writeType(s, t.Key, t, depth, false)
88109
s.WriteString("]: ")
89-
g.writeType(s, t.Value, depth, false)
110+
g.writeType(s, t.Value, t, depth, false)
90111
s.WriteByte('}')
91112
case *ast.BasicLit:
92-
if strings.HasPrefix(t.Value, "`") {
93-
t.Value = backquoteEscapeRegexp.ReplaceAllString(t.Value, `\$1`)
113+
switch t.Kind {
114+
case token.INT:
115+
if octalPrefixRegexp.MatchString(t.Value) {
116+
t.Value = "0o" + t.Value[1:]
117+
}
118+
case token.CHAR:
119+
var char rune
120+
if strings.HasPrefix(t.Value, `'\x`) ||
121+
strings.HasPrefix(t.Value, `'\u`) ||
122+
strings.HasPrefix(t.Value, `'\U`) {
123+
i32, err := strconv.ParseInt(t.Value[3:len(t.Value)-1], 16, 32)
124+
if err != nil {
125+
panic(err)
126+
}
127+
char = rune(i32)
128+
} else {
129+
var data []byte
130+
data = append(data, '"')
131+
data = append(data, []byte(t.Value[1:len(t.Value)-1])...)
132+
data = append(data, '"')
133+
var s string
134+
err := json.Unmarshal(data, &s)
135+
if err != nil {
136+
panic(err)
137+
}
138+
char = []rune(s)[0]
139+
}
140+
if char > 0xFFFF {
141+
t.Value = fmt.Sprintf("0x%08X /* %s */", char, t.Value)
142+
} else {
143+
t.Value = fmt.Sprintf("0x%04X /* %s */", char, t.Value)
144+
}
145+
case token.STRING:
146+
if strings.HasPrefix(t.Value, "`") {
147+
t.Value = backquoteEscapeRegexp.ReplaceAllString(t.Value, `\$1`)
148+
} else {
149+
t.Value = unicode8Regexp.ReplaceAllStringFunc(t.Value, func(s string) string {
150+
if len(s) == 10 {
151+
s = fmt.Sprintf("\\u{%s}", strings.ToUpper(s[2:]))
152+
}
153+
return s
154+
})
155+
}
94156
}
95157
s.WriteString(t.Value)
96158
case *ast.ParenExpr:
97159
s.WriteByte('(')
98-
g.writeType(s, t.X, depth, false)
160+
g.writeType(s, t.X, t, depth, false)
99161
s.WriteByte(')')
100162
case *ast.BinaryExpr:
101-
g.writeType(s, t.X, depth, false)
102-
s.WriteByte(' ')
103-
s.WriteString(t.Op.String())
163+
inParen := false
164+
switch p := p.(type) {
165+
case *ast.BinaryExpr:
166+
if jsNumberOperatorPrecedence[t.Op] < jsNumberOperatorPrecedence[p.Op] {
167+
inParen = true
168+
}
169+
}
170+
if inParen {
171+
s.WriteByte('(')
172+
}
173+
g.writeType(s, t.X, t, depth, false)
104174
s.WriteByte(' ')
105-
g.writeType(s, t.Y, depth, false)
175+
if t.Op == token.AND_NOT {
176+
s.WriteString("& ~")
177+
} else {
178+
s.WriteString(t.Op.String())
179+
s.WriteByte(' ')
180+
}
181+
g.writeType(s, t.Y, t, depth, false)
182+
if inParen {
183+
s.WriteByte(')')
184+
}
106185
case *ast.InterfaceType:
107186
g.writeInterfaceFields(s, t.Methods.List, depth+1)
108187
case *ast.CallExpr, *ast.FuncType, *ast.ChanType:
@@ -112,32 +191,32 @@ func (g *PackageGenerator) writeType(
112191
case token.TILDE:
113192
// We just ignore the tilde token, in Typescript extended types are
114193
// put into the generic typing itself, which we can't support yet.
115-
g.writeType(s, t.X, depth, false)
194+
g.writeType(s, t.X, t, depth, false)
116195
case token.XOR:
117196
s.WriteString("~")
118-
g.writeType(s, t.X, depth, false)
197+
g.writeType(s, t.X, t, depth, false)
119198
case token.ADD, token.SUB, token.NOT:
120199
s.WriteString(t.Op.String())
121-
g.writeType(s, t.X, depth, false)
200+
g.writeType(s, t.X, t, depth, false)
122201
default:
123202
err := fmt.Errorf("unhandled unary expr: %v\n %T", t, t)
124203
fmt.Println(err)
125204
panic(err)
126205
}
127206
case *ast.IndexListExpr:
128-
g.writeType(s, t.X, depth, false)
207+
g.writeType(s, t.X, t, depth, false)
129208
s.WriteByte('<')
130209
for i, index := range t.Indices {
131-
g.writeType(s, index, depth, false)
210+
g.writeType(s, index, t, depth, false)
132211
if i != len(t.Indices)-1 {
133212
s.WriteString(", ")
134213
}
135214
}
136215
s.WriteByte('>')
137216
case *ast.IndexExpr:
138-
g.writeType(s, t.X, depth, false)
217+
g.writeType(s, t.X, t, depth, false)
139218
s.WriteByte('<')
140-
g.writeType(s, t.Index, depth, false)
219+
g.writeType(s, t.Index, t, depth, false)
141220
s.WriteByte('>')
142221
default:
143222
err := fmt.Errorf("unhandled: %s\n %T", t, t)
@@ -152,7 +231,7 @@ func (g *PackageGenerator) writeTypeParamsFields(s *strings.Builder, fields []*a
152231
for j, ident := range f.Names {
153232
s.WriteString(ident.Name)
154233
s.WriteString(" extends ")
155-
g.writeType(s, f.Type, 0, true)
234+
g.writeType(s, f.Type, nil, 0, true)
156235

157236
if i != len(fields)-1 || j != len(f.Names)-1 {
158237
s.WriteString(", ")
@@ -192,7 +271,7 @@ func (g *PackageGenerator) writeInterfaceFields(
192271
g.writeCommentGroupIfNotNil(s, f.Doc, depth+1)
193272
}
194273
g.writeIndent(s, depth+1)
195-
g.writeType(s, f.Type, depth, false)
274+
g.writeType(s, f.Type, nil, depth, false)
196275

197276
if f.Comment != nil && g.PreserveTypeComments() {
198277
s.WriteString(" // ")
@@ -301,7 +380,7 @@ func (g *PackageGenerator) writeStructFields(s *strings.Builder, fields []*ast.F
301380
s.WriteString(": ")
302381

303382
if tstype == "" {
304-
g.writeType(s, f.Type, depth, false)
383+
g.writeType(s, f.Type, nil, depth, false)
305384
} else {
306385
s.WriteString(tstype)
307386
}

tygo/write_toplevel.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ func (g *PackageGenerator) writeTypeSpec(
109109
s.WriteString("export type ")
110110
s.WriteString(ts.Name.Name)
111111
s.WriteString(" = ")
112-
g.writeType(s, ts.Type, 0, true)
112+
g.writeType(s, ts.Type, nil, 0, true)
113113
s.WriteString(";")
114114

115115
}
@@ -185,7 +185,7 @@ func (g *PackageGenerator) writeValueSpec(
185185
s.WriteString(": ")
186186

187187
tempSB := &strings.Builder{}
188-
g.writeType(tempSB, vs.Type, 0, true)
188+
g.writeType(tempSB, vs.Type, nil, 0, true)
189189
typeString := tempSB.String()
190190

191191
s.WriteString(typeString)
@@ -200,7 +200,8 @@ func (g *PackageGenerator) writeValueSpec(
200200
if hasExplicitValue {
201201
val := vs.Values[i]
202202
tempSB := &strings.Builder{}
203-
g.writeType(tempSB, val, 0, true)
203+
// log.Println("const:", name.Name, reflect.TypeOf(val), val)
204+
g.writeType(tempSB, val, nil, 0, false)
204205
group.groupValue = tempSB.String()
205206
}
206207

0 commit comments

Comments
 (0)