Skip to content

Commit

Permalink
added constants #38
Browse files Browse the repository at this point in the history
  • Loading branch information
cshaa committed Sep 21, 2021
1 parent c383e46 commit abfa2a2
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 14 deletions.
10 changes: 10 additions & 0 deletions src/filtrex.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,16 @@ export interface Options
[T: string]: Function
}

/**
* Pass constants like `pi` or `true` to the expression without having to modify data.
* These constants will shadow identically named properties on the data object. In order
* to access `data.pi` instead of `constants.pi`, for example, use a single-quoted
* symbol in your expression, ie. `'pi'` instead of just `pi`.
*/
constants?: {
[T: string]: any
}

/**
* If you want to do some more magic with your expression, you can supply a custom function
* that will resolve the identifiers used in the expression and assign them a value yourself.
Expand Down
31 changes: 20 additions & 11 deletions src/filtrex.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ const std =
}
}

return JSON.stringify(built)
return built
},

reduceRelation(arr) {
Expand Down Expand Up @@ -100,12 +100,12 @@ export function compileExpression(expression, options) {
if (arguments.length > 2) throw new TypeError('Too many arguments.')

options = typeof options === "object" ? options : {}
let {extraFunctions, customProp, operators} = options

const knownOptions = ['extraFunctions', 'constants', 'customProp', 'operators']
let {extraFunctions, constants, customProp, operators} = options

for (const key of Object.keys(options))
{
if (!(["extraFunctions", "customProp", "operators"].includes(key)))
throw new UnknownOptionError(key)
}
if (!knownOptions.includes(key)) throw new UnknownOptionError(key)



Expand Down Expand Up @@ -160,6 +160,8 @@ export function compileExpression(expression, options) {

operators = defaultOperators

constants = constants ?? {}



// Compile the expression
Expand All @@ -171,35 +173,42 @@ export function compileExpression(expression, options) {

// Metaprogramming functions

function prop(name, obj) {
if (hasOwnProperty(obj||{}, name))
function nakedProp(name, obj) {
if (hasOwnProperty(obj ?? {}, name))
return obj[name]

throw new UnknownPropertyError(name)
}

function safeGetter(obj) {
return function get(name) {
if (hasOwnProperty(obj||{}, name))
if (hasOwnProperty(obj ?? {}, name))
return obj[name]

throw new UnknownPropertyError(name)
}
}

if (typeof customProp === 'function') {
prop = (name, obj) => customProp(name, safeGetter(obj), obj)
nakedProp = (name, obj) => customProp(name, safeGetter(obj), obj)
}

function createCall(fns) {
return function call(name, ...args) {
return function call({ name }, ...args) {
if (hasOwnProperty(fns, name) && typeof fns[name] === "function")
return fns[name](...args)

throw new UnknownFunctionError(name)
}
}

function prop({ name, type }, obj) {
if (type === 'unescaped' && hasOwnProperty(constants, name))
return constants[name]

return nakedProp(name, obj)
}



// Patch together and return
Expand Down
12 changes: 9 additions & 3 deletions src/generateParser.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -40,17 +40,23 @@ const grammar = {
[_`[0-9]+(?:\.[0-9]+)?(?![0-9\.])`, `return "Number";`], // 212.321

[_`[a-zA-Z$_][\.a-zA-Z0-9$_]*`,
`yytext = JSON.stringify(yytext);
`yytext = JSON.stringify({
name: yytext,
type: 'unescaped'
});
return "Symbol";`
], // some.Symbol22

[_`'(?:\\'|\\\\|[^'\\])*'`,
`yytext = yy.buildString("'", yytext);
`yytext = JSON.stringify({
name: yy.buildString("'", yytext),
type: 'single-quoted'
});
return "Symbol";`
], // 'any \'escaped\' symbol'

[_`"(?:\\"|\\\\|[^"\\])*"`,
`yytext = yy.buildString('"', yytext);
`yytext = JSON.stringify(yy.buildString('"', yytext));
return "String";`
], // "any \"escaped\" string"

Expand Down
28 changes: 28 additions & 0 deletions test/misc.js
Original file line number Diff line number Diff line change
Expand Up @@ -160,4 +160,32 @@ describe('Various other things', () => {
expect( eval('4 + 3 not in (6, 8)') ).equals(true);
})

it('constants basics', () => {
const options = { constants: { pi: Math.PI, true: true, false: false }}

expect(
compileExpression('2 * pi * radius', options)({ radius: 6 })
).equals(2 * Math.PI * 6)

expect(
compileExpression('not true == false and not false == true', options)()
).equals(true)

expect(
compileExpression('pi', options)({ pi: 3 })
).equals(Math.PI)

expect(
compileExpression(`'pi'`, options)({ pi: 3 })
).equals(3)


const options2 = { constants: { a: "a_const " } }
const data = { a: "a_data ", b: "b_data " }
const expr = `'a' + a + 'b' + b`

expect( compileExpression(expr, options2)(data) ).equals("a_data a_const b_data b_data ")

})

});

0 comments on commit abfa2a2

Please sign in to comment.