Skip to content

Commit

Permalink
feat: codegen forRange loop
Browse files Browse the repository at this point in the history
  • Loading branch information
epoberezkin committed Sep 9, 2020
1 parent 4a0311d commit 49d2d3e
Show file tree
Hide file tree
Showing 5 changed files with 31 additions and 29 deletions.
47 changes: 26 additions & 21 deletions lib/compile/codegen/index.ts
Expand Up @@ -110,7 +110,7 @@ export class CodeGen {
} else if (thenBody) {
this.code(thenBody).endIf()
} else if (elseBody) {
throw new Error('CodeGen: "else" body wit_out "then" body')
throw new Error('CodeGen: "else" body without "then" body')
}
return this
}
Expand All @@ -121,13 +121,13 @@ export class CodeGen {
}

elseIf(condition: Code): CodeGen {
if (this._lastBlock !== BlockKind.If) throw new Error('CodeGen: "else if" wit_out "if"')
if (this._lastBlock !== BlockKind.If) throw new Error('CodeGen: "else if" without "if"')
this._out += `}else if(${condition}){` + this._n
return this
}

else(): CodeGen {
if (this._lastBlock !== BlockKind.If) throw new Error('CodeGen: "else" wit_out "if"')
if (this._lastBlock !== BlockKind.If) throw new Error('CodeGen: "else" without "if"')
this._lastBlock = BlockKind.Else
this._out += "}else{" + this._n
return this
Expand All @@ -136,7 +136,7 @@ export class CodeGen {
endIf(): CodeGen {
// TODO possibly remove empty branches here
const b = this._lastBlock
if (b !== BlockKind.If && b !== BlockKind.Else) throw new Error('CodeGen: "endIf" wit_out "if"')
if (b !== BlockKind.If && b !== BlockKind.Else) throw new Error('CodeGen: "endIf" without "if"')
this._blocks.pop()
this._out += "}" + this._n
return this
Expand All @@ -149,6 +149,18 @@ export class CodeGen {
return this
}

forRange(
nameOrPrefix: Name | string,
from: SafeExpr,
to: SafeExpr,
forBody: (n: Name) => void,
varKind: Code = varKinds.let
): CodeGen {
const i = this.toName(nameOrPrefix)
if (this.opts.es5) varKind = varKinds.var
return _loop.call(this, _`for(${varKind} ${i}=${from}; ${i}<${to}; ${i}++){`, i, forBody)
}

forOf(
nameOrPrefix: Name | string,
iterable: SafeExpr,
Expand All @@ -157,19 +169,13 @@ export class CodeGen {
): CodeGen {
const name = this.toName(nameOrPrefix)
if (this.opts.es5) {
const i = this.name("_i")
return _loop.call(
this,
new _Code(`for(${varKinds.let} ${i}=0; ${i}<${iterable}.length; ${i}++){`),
i,
() => {
const item = new _Code(`${iterable}[${i}]`)
_def.call(this, varKind, name, item)
forBody(name)
}
)
const arr = iterable instanceof Name ? iterable : this.var("arr", iterable)
return this.forRange("_i", 0, new _Code(`${arr}.length`), (i) => {
this.var(name, new _Code(`${arr}[${i}]`))
forBody(name)
})
}
return _loop.call(this, new _Code(`for(${varKind} ${name} of ${iterable}){`), name, forBody)
return _loop.call(this, _`for(${varKind} ${name} of ${iterable}){`, name, forBody)
}

forIn(
Expand All @@ -178,17 +184,16 @@ export class CodeGen {
forBody: (n: Name) => void,
varKind: Code = varKinds.const
): CodeGen {
// TODO define enum for var kinds
if (this.opts.forInOwn) {
return this.forOf(nameOrPrefix, new _Code(`Object.keys(${obj})`), forBody)
}
const name = this.toName(nameOrPrefix)
return _loop.call(this, new _Code(`for(${varKind} ${name} in ${obj}){`), name, forBody)
return _loop.call(this, _`for(${varKind} ${name} in ${obj}){`, name, forBody)
}

endFor(): CodeGen {
const b = this._lastBlock
if (b !== BlockKind.For) throw new Error('CodeGen: "endFor" wit_out "for"')
if (b !== BlockKind.For) throw new Error('CodeGen: "endFor" without "for"')
this._blocks.pop()
this._out += "}" + this._n
return this
Expand All @@ -212,7 +217,7 @@ export class CodeGen {
}

try(tryBody: Block, catchCode?: (e: Name) => void, finallyCode?: Block): CodeGen {
if (!catchCode && !finallyCode) throw new Error('CodeGen: "try" wit_out "catch" and "finally"')
if (!catchCode && !finallyCode) throw new Error('CodeGen: "try" without "catch" and "finally"')
this._out += "try{" + this._n
this.code(tryBody)
if (catchCode) {
Expand Down Expand Up @@ -261,7 +266,7 @@ export class CodeGen {

endFunc(): CodeGen {
const b = this._lastBlock
if (b !== BlockKind.Func) throw new Error('CodeGen: "endFunc" wit_out "func"')
if (b !== BlockKind.Func) throw new Error('CodeGen: "endFunc" without "func"')
this._blocks.pop()
this._out += "}" + this._n
return this
Expand Down
4 changes: 2 additions & 2 deletions lib/compile/errors.ts
Expand Up @@ -55,8 +55,8 @@ export function extendErrors({
}: KeywordErrorCtx): void {
if (errsCount === undefined) throw new Error("ajv implementation error")
const err = gen.name("err")
gen.for(_`let i=${errsCount}; i<${N.errors}; i++`, () => {
gen.const(err, _`${N.vErrors}[i]`)
gen.forRange("i", errsCount, N.errors, (i) => {
gen.const(err, _`${N.vErrors}[${i}]`)
gen.if(
_`${err}.dataPath === undefined`,
_`${err}.dataPath = (${N.dataPath} || '') + ${it.errorPath}`
Expand Down
3 changes: 1 addition & 2 deletions lib/vocabularies/applicator/additionalItems.ts
Expand Up @@ -27,8 +27,7 @@ const def: CodeKeywordDefinition = {
}

function validateItems(valid: Name): void {
const i = gen.name("i")
gen.for(_`let ${i}=${items.length}; ${i}<${len}; ${i}++`, () => {
gen.forRange("i", items.length, len, (i) => {
applySubschema(it, {keyword: "additionalItems", dataProp: i, dataPropType: Type.Num}, valid)
if (!it.allErrors) gen.ifNot(valid, _`break`)
})
Expand Down
3 changes: 1 addition & 2 deletions lib/vocabularies/applicator/contains.ts
Expand Up @@ -19,8 +19,7 @@ const def: CodeKeywordDefinition = {
}

const valid = gen.name("valid")
const i = gen.name("i")
gen.for(_`let ${i}=0; ${i}<${data}.length; ${i}++`, () => {
gen.forRange("i", 0, _`${data}.length`, (i) => {
applySubschema(
it,
{
Expand Down
3 changes: 1 addition & 2 deletions lib/vocabularies/applicator/items.ts
Expand Up @@ -39,8 +39,7 @@ const def: CodeKeywordDefinition = {

function validateItems(): void {
const valid = gen.name("valid")
const i = gen.name("i")
gen.for(_`let ${i}=0; ${i}<${len}; ${i}++`, () => {
gen.forRange("i", 0, len, (i) => {
applySubschema(it, {keyword: "items", dataProp: i, dataPropType: Type.Num}, valid)
if (!it.allErrors) gen.ifNot(valid, _`break`)
})
Expand Down

0 comments on commit 49d2d3e

Please sign in to comment.