Skip to content

Commit

Permalink
refactor(codegen): allow passing string as block body
Browse files Browse the repository at this point in the history
  • Loading branch information
epoberezkin committed Aug 21, 2020
1 parent da74871 commit b1da85f
Show file tree
Hide file tree
Showing 6 changed files with 29 additions and 38 deletions.
43 changes: 19 additions & 24 deletions lib/compile/codegen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ enum Block {
For,
}

type Code = string | (() => void)

export default class CodeGen {
#names: {[key: string]: number} = {}
// TODO make private. Possibly stack?
Expand All @@ -17,23 +19,20 @@ export default class CodeGen {
return `${prefix}_${num}`
}

code(str?: string): CodeGen {
code(c?: Code): CodeGen {
// TODO optionally strip whitespace
if (str) this._out += str + "\n"
if (typeof c == "function") c()
else if (c) this._out += c + "\n"
return this
}

if(condition: string, thenBody?: () => void, elseBody?: () => void): CodeGen {
if(condition: string, thenBody?: Code, elseBody?: Code): CodeGen {
this.#blocks.push(Block.If)
this.code(`if(${condition}){`)
if (thenBody && elseBody) {
thenBody()
this.else()
elseBody()
this.endIf()
this.code(thenBody).else().code(elseBody).endIf()
} else if (thenBody) {
thenBody()
this.endIf()
this.code(thenBody).endIf()
} else if (elseBody) {
throw new Error("CodeGen: else body without then body")
}
Expand Down Expand Up @@ -62,13 +61,10 @@ export default class CodeGen {
return this
}

for(iteration: string, forBody?: () => void): CodeGen {
for(iteration: string, forBody?: Code): CodeGen {
this.#blocks.push(Block.For)
this.code(`for(${iteration}){`)
if (forBody) {
forBody()
this.endFor()
}
if (forBody) this.code(forBody).endFor()
return this
}

Expand All @@ -80,12 +76,9 @@ export default class CodeGen {
return this
}

block(body?: () => void, expectedToClose?: number): CodeGen {
block(body?: Code, expectedToClose?: number): CodeGen {
this.#blockStarts.push(this.#blocks.length)
if (body) {
body()
this.endBlock(expectedToClose)
}
if (body) this.code(body).endBlock(expectedToClose)
return this
}

Expand All @@ -103,14 +96,16 @@ export default class CodeGen {
}

get _lastBlock(): Block {
const len = this.#blocks.length
if (len === 0) throw new Error("CodeGen: not in block")
return this.#blocks[len - 1]
return this.#blocks[this._last()]
}

set _lastBlock(b: Block) {
this.#blocks[this._last()] = b
}

_last() {
const len = this.#blocks.length
if (len === 0) throw new Error('CodeGen: not in "if" block')
this.#blocks[len - 1] = b
if (len === 0) throw new Error("CodeGen: not in block")
return len - 1
}
}
2 changes: 1 addition & 1 deletion lib/vocabularies/applicator/contains.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ const def: KeywordDefinition = {
},
valid
)
gen.code(`if (${valid}) break;`)
gen.if(valid, "break")
})

// TODO refactor failCompoundOrReset? It is different from anyOf though
Expand Down
2 changes: 1 addition & 1 deletion lib/vocabularies/applicator/dependencies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ const def: KeywordDefinition = {
gen.if(
propertyInData(data, prop, Expr.Const, it.opts.ownProperties),
() => applySubschema(it, {keyword: "dependencies", schemaProp: prop}, valid),
() => gen.code(`var ${valid} = true;`) // TODO refactor var
`var ${valid} = true;` // TODO refactor var
)
if (!it.allErrors) gen.if(valid)
}
Expand Down
2 changes: 1 addition & 1 deletion lib/vocabularies/applicator/patternProperties.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ const def: KeywordDefinition = {
},
valid
)
if (!it.allErrors) gen.if(`!${valid}`, () => gen.code("break;"))
if (!it.allErrors) gen.if(`!${valid}`, "break")
})
})
}
Expand Down
11 changes: 4 additions & 7 deletions lib/vocabularies/validation/enum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,10 @@ const def: KeywordDefinition = {
if ($data) {
const valid = gen.name("valid")
gen.code(`let ${valid};`)
gen.if(
`${schemaCode} === undefined`,
() => gen.code(`${valid} = true;`),
() =>
gen
.code(`${valid} = false;`)
.if(`Array.isArray(${schemaCode})`, () => loopEnum(<string>schemaCode, valid))
gen.if(`${schemaCode} === undefined`, `${valid} = true;`, () =>
gen
.code(`${valid} = false;`)
.if(`Array.isArray(${schemaCode})`, () => loopEnum(<string>schemaCode, valid))
)
fail(`!${valid}`)
} else {
Expand Down
7 changes: 3 additions & 4 deletions lib/vocabularies/validation/required.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,10 +94,9 @@ const def: KeywordDefinition = {

function loopUntilMissing(missing: string, valid: string): void {
gen.for(`${missing} of ${schemaCode}`, () =>
gen.code(
`${valid} = ${propertyInData(data, missing, Expr.Str, it.opts.ownProperties)};
if (!${valid}) break;`
)
gen
.code(`${valid} = ${propertyInData(data, missing, Expr.Str, it.opts.ownProperties)};`)
.if(`!${valid}`, "break")
)
}
},
Expand Down

0 comments on commit b1da85f

Please sign in to comment.