perf: introduce AST to avoid reparse

This commit is contained in:
harttle
2020-03-15 02:51:25 +08:00
committed by Jun Yang
parent 3b58f1c3f6
commit d2d6a38235
96 changed files with 1553 additions and 1168 deletions
+3 -3
View File
@@ -1,8 +1,8 @@
import { AssertionError } from './error'
export function assert <T> (predicate: T | null | undefined, message?: string) {
export function assert <T> (predicate: T | null | undefined, message?: () => string) {
if (!predicate) {
message = message || `expect ${predicate} to be true`
throw new AssertionError(message)
const msg = message ? message() : `expect ${predicate} to be true`
throw new AssertionError(msg)
}
}
+1 -1
View File
@@ -1,6 +1,6 @@
import { isFunction } from './underscore'
type resolver = (x?: any) => Thenable
type resolver = (x?: any) => any
interface Thenable {
then (resolve: resolver, reject?: resolver): Thenable;
+10
View File
@@ -0,0 +1,10 @@
// bitmask character types to boost performance
// generated by bin/char-types.js
export const TYPES = [0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 4, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 2, 8, 0, 0, 0, 0, 8, 0, 0, 0, 64, 0, 65, 0, 0, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 0, 0, 2, 2, 2, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0]
export const VARIABLE = 1
export const OPERATOR = 2
export const BLANK = 4
export const QUOTE = 8
export const INLINE_BLANK = 16
export const NUMBER = 32
export const SIGN = 64
+7 -5
View File
@@ -1,5 +1,5 @@
import * as _ from './underscore'
import { Token } from '../parser/token'
import { Token } from '../tokens/token'
import { Template } from '../template/template'
abstract class LiquidError extends Error {
@@ -57,14 +57,15 @@ export class AssertionError extends Error {
}
function mkContext (token: Token) {
const [line] = token.getPosition()
const lines = token.input.split('\n')
const begin = Math.max(token.line - 2, 1)
const end = Math.min(token.line + 3, lines.length)
const begin = Math.max(line - 2, 1)
const end = Math.min(line + 3, lines.length)
const context = _
.range(begin, end + 1)
.map(lineNumber => {
const indicator = (lineNumber === token.line) ? '>> ' : ' '
const indicator = (lineNumber === line) ? '>> ' : ' '
const num = _.padStart(String(lineNumber), String(end).length)
const text = lines[lineNumber - 1]
return `${indicator}${num}| ${text}`
@@ -76,6 +77,7 @@ function mkContext (token: Token) {
function mkMessage (msg: string, token: Token) {
if (token.file) msg += `, file:${token.file}`
msg += `, line:${token.line}, col:${token.col}`
const [line, col] = token.getPosition()
msg += `, line:${line}, col:${col}`
return msg
}
+12
View File
@@ -0,0 +1,12 @@
import { NullDrop } from '../drop/null-drop'
import { EmptyDrop } from '../drop/empty-drop'
import { BlankDrop } from '../drop/blank-drop'
export const literalValues = {
'true': true,
'false': false,
'nil': new NullDrop(),
'null': new NullDrop(),
'empty': new EmptyDrop(),
'blank': new BlankDrop()
}
+55
View File
@@ -0,0 +1,55 @@
import { OperatorToken } from '../tokens/operator-token'
import { WordToken } from '../tokens/word-token'
import { TagToken } from '../tokens/tag-token'
import { HTMLToken } from '../tokens/html-token'
import { OutputToken } from '../tokens/output-token'
import { PropertyAccessToken } from '../tokens/property-access-token'
import { LiteralToken } from '../tokens/literal-token'
import { QuotedToken } from '../tokens/quoted-token'
import { NumberToken } from '../tokens/number-token'
import { RangeToken } from '../tokens/range-token'
import { TokenKind } from '../parser/token-kind'
export function isOperatorToken (val: any): val is OperatorToken {
return getKind(val) === TokenKind.Operator
}
export function isHTMLToken (val: any): val is HTMLToken {
return getKind(val) === TokenKind.HTML
}
export function isOutputToken (val: any): val is OutputToken {
return getKind(val) === TokenKind.Output
}
export function isTagToken (val: any): val is TagToken {
return getKind(val) === TokenKind.Tag
}
export function isQuotedToken (val: any): val is QuotedToken {
return getKind(val) === TokenKind.Quoted
}
export function isLiteralToken (val: any): val is LiteralToken {
return getKind(val) === TokenKind.Literal
}
export function isNumberToken (val: any): val is NumberToken {
return getKind(val) === TokenKind.Number
}
export function isPropertyAccessToken (val: any): val is PropertyAccessToken {
return getKind(val) === TokenKind.PropertyAccess
}
export function isWordToken (val: any): val is WordToken {
return getKind(val) === TokenKind.Word
}
export function isRangeToken (val: any): val is RangeToken {
return getKind(val) === TokenKind.Range
}
function getKind (val: any) {
return val ? val.kind : -1
}