In order to do so, we need:
A pure functional programming language. Its power is controlled by us.
(n, a) => reduce(
map(range(1, a), () => n),
(r, c) => multiply(r, c),
1
)A set of pure functions we supply as the basic functions for the dynamic calculations mechanism.
{
now: {
exec: () => Date.now(),
accepts: [],
returns: 'date'
},
eq: {
exec: _.eq,
accepts: ['any', 'any'],
returns: 'boolean'
},
filter: {
exec: (arr = [], cb) => arr.filter(cb),
accepts: ['array', 'any, number => boolean'],
returns: 'array'
},
map: {
exec: (arr = [], cb) => arr.map(cb),
accepts: ['array', 'any, number => any'],
returns: 'array'
},
reduce: {
exec: (arr = [], cb, acc) => arr.reduce(cb, acc),
accepts: ['array', 'any, any, number => any', 'any'],
returns: 'any'
},
// ...
}We will tell the dynamic calculations mechanism which variables are supported, what's their type, and how to evaluate them.
$patient
$patient.visit[0]
$config
$lookups.GENDER
// ...{
"nodeType": "CallNode",
"identifier": {
"nodeType": "IdentifierNode",
"name": "eq"
},
"arguments": [
{
"nodeType": "CallNode",
"identifier": {
"nodeType": "IdentifierNode",
"name": "add"
},
"arguments": [
{
"nodeType": "LiteralNode",
"type": "number",
"value": 1
},
{
"nodeType": "LiteralNode",
"type": "number",
"value": 2
}
]
},
{
"nodeType": "LiteralNode",
"type": "number",
"value": 3
}
]
}eq(add(1, 2), 3)basic
calculations
GetEnvironmentVariableType
(varName: string, path: Array<string>) => string
GetEnvironmentVariable
(varName: string, path: Array<string>) => any
Compiler
Runner
Parser
SemanticAnalyzer
Code (text)
AST
Calculation Result
{
"nodeType": "CallNode",
"identifier": {
"nodeType": "IdentifierNode",
"name": "eq"
},
"arguments": [
{
"nodeType": "CallNode",
"identifier": {
"nodeType": "IdentifierNode",
"name": "add"
},
"arguments": [
{
"nodeType": "LiteralNode",
"type": "number",
"value": 1
},
{
"nodeType": "LiteralNode",
"type": "number",
"value": 2
}
]
},
{
"nodeType": "LiteralNode",
"type": "number",
"value": 3
}
]
}eq(add(1, 2), 3)How can I evaluate this?
{
"nodeType": "LambdaNode",
"parameters": [
{
"nodeType": "IdentifierNode",
"name": "n"
}
],
"body": {
"nodeType": "CallNode",
"identifier": {
"nodeType": "IdentifierNode",
"name": "add"
},
"arguments": [
{
"nodeType": "IdentifierNode",
"name": "n"
},
{
"nodeType": "LiteralNode",
"type": "number",
"value": 1
}
]
}
}n => add(n, 1)And this?
map(range(1,10), n => add(n, 1))