Skip to content

Commit 68bb223

Browse files
authored
Fix anon containers (#159)
* Update compiler-structures.js: Remove special container inlining code * Update compiler-conditional.js: fix switch cases not inheriting scope * Update compiler-structures.js * update handling for switch getField * lint
1 parent 73479a0 commit 68bb223

File tree

3 files changed

+27
-68
lines changed

3 files changed

+27
-68
lines changed

src/compiler.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ class Compiler {
195195
return code.split('\n').map((line) => indent + line).join('\n')
196196
}
197197

198-
getField (name) {
198+
getField (name, noAssign) {
199199
const path = name.split('/')
200200
let i = this.scopeStack.length - 1
201201
const reserved = ['value', 'enum', 'default', 'size', 'offset']
@@ -217,7 +217,11 @@ class Compiler {
217217
for (let j = 0; j < i; j++) {
218218
if (this.scopeStack[j][field]) count++
219219
}
220-
scope[field] = field + (count || '') // If the name is already used, add a number
220+
if (noAssign) { // referencing a variable, inherit from parent scope
221+
scope[field] = field
222+
} else { // creating a new variable in this scope
223+
scope[field] = field + (count || '') // If the name is already used, add a number
224+
}
221225
return scope[field]
222226
}
223227
throw new Error('Unknown field ' + path)

src/datatypes/compiler-conditional.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ module.exports = {
55
const args = []
66
if (compare.startsWith('$')) args.push(compare)
77
else if (struct.compareTo) {
8-
compare = compiler.getField(compare)
8+
compare = compiler.getField(compare, true)
99
}
1010
let code = `switch (${compare}) {\n`
1111
for (const key in struct.fields) {
@@ -35,7 +35,7 @@ module.exports = {
3535
const args = []
3636
if (compare.startsWith('$')) args.push(compare)
3737
else if (struct.compareTo) {
38-
compare = compiler.getField(compare)
38+
compare = compiler.getField(compare, true)
3939
}
4040
let code = `switch (${compare}) {\n`
4141
for (const key in struct.fields) {
@@ -66,7 +66,7 @@ module.exports = {
6666
const args = []
6767
if (compare.startsWith('$')) args.push(compare)
6868
else if (struct.compareTo) {
69-
compare = compiler.getField(compare)
69+
compare = compiler.getField(compare, true)
7070
}
7171
let code = `switch (${compare}) {\n`
7272
for (const key in struct.fields) {

src/datatypes/compiler-structures.js

Lines changed: 18 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ module.exports = {
3232
let offsetExpr = 'offset'
3333
const names = []
3434
for (const i in values) {
35-
const { type, name, anon } = values[i]
35+
const { type, name, anon, _shouldBeInlined } = values[i]
3636
let trueName
3737
let sizeName
3838
if (type instanceof Array && type[0] === 'bitfield' && anon) {
@@ -52,7 +52,8 @@ module.exports = {
5252
} else {
5353
trueName = compiler.getField(name)
5454
sizeName = `${trueName}Size`
55-
if (name === trueName) names.push(name)
55+
if (_shouldBeInlined) names.push('...' + name)
56+
else if (name === trueName) names.push(name)
5657
else names.push(`${name}: ${trueName}`)
5758
}
5859
code += `let { value: ${trueName}, size: ${sizeName} } = ` + compiler.callType(type, offsetExpr) + '\n'
@@ -88,7 +89,7 @@ module.exports = {
8889
values = containerInlining(values)
8990
let code = ''
9091
for (const i in values) {
91-
const { type, name, anon } = values[i]
92+
const { type, name, anon, _shouldBeInlined } = values[i]
9293
let trueName
9394
if (type instanceof Array && type[0] === 'bitfield' && anon) {
9495
const names = []
@@ -101,7 +102,8 @@ module.exports = {
101102
trueName = '{' + names.join(', ') + '}'
102103
} else {
103104
trueName = compiler.getField(name)
104-
code += `let ${trueName} = value.${name}\n`
105+
if (_shouldBeInlined) code += `let ${name} = value\n`
106+
else code += `let ${trueName} = value.${name}\n`
105107
}
106108
code += 'offset = ' + compiler.callType(trueName, type) + '\n'
107109
}
@@ -138,7 +140,7 @@ module.exports = {
138140
values = containerInlining(values)
139141
let code = 'let size = 0\n'
140142
for (const i in values) {
141-
const { type, name, anon } = values[i]
143+
const { type, name, anon, _shouldBeInlined } = values[i]
142144
let trueName
143145
if (type instanceof Array && type[0] === 'bitfield' && anon) {
144146
const names = []
@@ -151,7 +153,8 @@ module.exports = {
151153
trueName = '{' + names.join(', ') + '}'
152154
} else {
153155
trueName = compiler.getField(name)
154-
code += `let ${trueName} = value.${name}\n`
156+
if (_shouldBeInlined) code += `let ${name} = value\n`
157+
else code += `let ${trueName} = value.${name}\n`
155158
}
156159
code += 'size += ' + compiler.callType(trueName, type) + '\n'
157160
}
@@ -161,6 +164,10 @@ module.exports = {
161164
}
162165
}
163166

167+
function uniqueId () {
168+
return '_' + Math.random().toString(36).substr(2, 9)
169+
}
170+
164171
function containerInlining (values) {
165172
// Inlining (support only 1 level)
166173
const newValues = []
@@ -170,63 +177,11 @@ function containerInlining (values) {
170177
if (type instanceof Array && type[0] === 'container') {
171178
for (const j in type[1]) newValues.push(type[1][j])
172179
} else if (type instanceof Array && type[0] === 'switch') {
173-
const theSwitch = type[1]
174-
const valueSet = new Set()
175-
// search for containers and build a set of possible values
176-
for (const field in theSwitch.fields) {
177-
if (theSwitch.fields[field] instanceof Array && theSwitch.fields[field][0] === 'container') {
178-
for (const j in theSwitch.fields[field][1]) {
179-
const item = theSwitch.fields[field][1][j]
180-
valueSet.add(item.name)
181-
}
182-
}
183-
}
184-
if (theSwitch.default instanceof Array && theSwitch.default[0] === 'container') {
185-
for (const j in theSwitch.default[1]) {
186-
const item = theSwitch.default[1][j]
187-
valueSet.add(item.name)
188-
}
189-
}
190-
// For each value create a switch
191-
for (const name of valueSet.keys()) {
192-
const fields = {}
193-
let theDefault = theSwitch.default
194-
195-
if (theDefault instanceof Array && theDefault[0] === 'container') {
196-
for (const j in theDefault[1]) {
197-
const item = theDefault[1][j]
198-
if (item.name === name) {
199-
theDefault = item.type
200-
break
201-
}
202-
}
203-
}
204-
for (const field in theSwitch.fields) {
205-
if (theSwitch.fields[field] instanceof Array && theSwitch.fields[field][0] === 'container') {
206-
for (const j in theSwitch.fields[field][1]) {
207-
const item = theSwitch.fields[field][1][j]
208-
if (item.name === name) {
209-
fields[field] = theSwitch.fields[field][1][j].type
210-
break
211-
}
212-
}
213-
} else {
214-
fields[field] = theSwitch.fields[field]
215-
}
216-
}
217-
if (!theDefault) {
218-
theDefault = 'void'
219-
}
220-
newValues.push({
221-
name,
222-
type: ['switch', {
223-
compareTo: theSwitch.compareTo,
224-
compareToValue: theSwitch.compareToValue,
225-
default: theDefault,
226-
fields
227-
}]
228-
})
229-
}
180+
newValues.push({
181+
name: uniqueId(),
182+
_shouldBeInlined: true,
183+
type
184+
})
230185
} else {
231186
throw new Error('Cannot inline anonymous type: ' + type)
232187
}

0 commit comments

Comments
 (0)