Skip to content

Macros #2

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
May 21, 2016
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
291 changes: 284 additions & 7 deletions LANGUAGE.md

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -12,9 +12,9 @@ JSONScript is created to manage scripted execution in remote systems to avoid th

JSONScript:

- uses JSON as its representaion format for both data and control structures, being similar to lisp (homoiconic)
- uses JSON as its representaion format for both data and control structures, being similar to lisp (homoiconic).
- defines simple control structures.
- is asynchronous and concurrent without the need to use any special keywords
- is asynchronous and concurrent without the need to use any special keywords.
- actual processing in the remote system is done synchronously or asynchronously by the functions and objects supplied to JSONScript interpreter by the host environment.


14 changes: 9 additions & 5 deletions SCHEMA.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
# JSONScript Schema

JSONScript uses JSON-Schema standard both for the validation schemas and for the schema that defines evaluation process.
JSONScript uses JSON-Schema standard both for the validation schemas and for the schemas that define macro expansion and evaluation process.

[JSONScript schema](http://www.json-script.com/schema/schema.json#) the schema that does not validate scalar keywords in instructions (keyword values can be scripts and have to be validated when the script is evaluated).
[JSONScript schema](http://www.json-script.com/schema/schema.json#) - the schema for JSONScript that does not validate scalar keywords in instructions (keyword values can be scripts and have to be validated when the script is evaluated).

[JSONScript strict schema](http://www.json-script.com/schema/schema_strict.json#) the schema that validates scalar keywords in instructions.
[JSONScript strict schema](http://www.json-script.com/schema/schema_strict.json#) - the schema for JSONScript that validates scalar keywords in instructions.

[JSONScript evaluation schema](http://www.json-script.com/schema/evaluate.json#) this schema defines evalution process. It can be used by implementations to evaluate scripts. It contains non-standard keywords.
[Macro expansion schema](http://www.json-script.com/schema/expand_macros.json#) - this schema defines macro expansion process. It can be used by implementations to expand macros in the scripts before their evaluation. It contains non-standard keyword `expandJsMacro`.

[Instruction definition schema](http://www.json-script.com/schema/instruction.json#) the schema for instruction defnitions. The definitions of both standard and user-defined instructions should be valid according to this schema.
[Evaluation schema](http://www.json-script.com/schema/evaluate.json#) - this schema defines evalution process. It can be used by implementations to evaluate scripts. It contains non-standard keywords.

[Instruction definition schema](http://www.json-script.com/schema/instruction.json#) - the schema for instruction defnitions. The definitions of both standard and user-defined instructions should be valid according to this schema.

[Macro definition schema](http://www.json-script.com/schema/macro.json#) - the schema for macro definition. The definitions of both standard and user-defined macros should be valid according to this schema.
32 changes: 32 additions & 0 deletions macros/calc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"name": "calc",
"description": "short calculations syntax",
"rules": [
{
"description": "calculation",
"pattern": {
"\\$([+\\-*/=!<>&\\|^]{1,2})": 1
},
"script": {
"$exec": "calc",
"$method": { "$1": {
"+": "add",
"-": "subtract",
"*": "multiply",
"/": "divide",
"==": "equal",
"!=": "notEqual",
">": "greater",
">=": "greaterEqual",
"<": "lesser",
"<=": "lesserEqual",
"&&": "and",
"||": "or",
"^^": "xor",
"!": "not"
} },
"$args": 1
}
}
]
}
16 changes: 16 additions & 0 deletions macros/call.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"name": "call",
"description": "short syntax for function call",
"rules": [
{
"description": "call named function with arguments",
"pattern": {
"^\\$\\#(.+)$": 1
},
"script": {
"$call": "$1",
"$args": 1
}
}
]
}
27 changes: 27 additions & 0 deletions macros/exec.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"name": "exec",
"description": "short syntax for executor call",
"rules": [
{
"description": "executor call with method",
"pattern": {
"^\\$\\$([^\\.]+)\\.([^\\.]+)$": 1
},
"script": {
"$exec": "$1",
"$method": "$2",
"$args": 1
}
},
{
"description": "executor call without method",
"pattern": {
"^\\$\\$([^\\.]+)$": 1
},
"script": {
"$exec": "$1",
"$args": 1
}
}
]
}
7 changes: 7 additions & 0 deletions macros/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
'use strict';

module.exports = [
require('./exec.json'),
require('./call.json'),
require('./calc.json')
];
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "jsonscript",
"version": "0.3.0",
"version": "0.4.0",
"description": "Platform independent asynchronous and concurrent scripting language using JSON format",
"main": "index.js",
"scripts": {
108 changes: 108 additions & 0 deletions schema/expand_macros.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
{
"id": "http://www.json-script.com/schema/expand_macros.json#",
"$schema": "https://raw.githubusercontent.com/epoberezkin/ajv/master/lib/refs/json-schema-v5.json#",
"title": "JSONScript macro expansion schema",
"description": "Schema with custom keywords that expands macros in JSON script.",
"switch": [
{
"if": {
"type": "object"
},
"then": {
"allOf": [
{
"anyOf": [
{
"expandJsMacro": {
"description": "executor call with method",
"pattern": {
"^\\$\\$([^\\.]+)\\.([^\\.]+)$": 1
},
"script": {
"$exec": "$1",
"$method": "$2",
"$args": 1
}
}
},
{
"expandJsMacro": {
"description": "executor call without method",
"pattern": {
"^\\$\\$([^\\.]+)$": 1
},
"script": {
"$exec": "$1",
"$args": 1
}
}
},
{
"expandJsMacro": {
"description": "call named function with arguments",
"pattern": {
"^\\$\\#(.+)$": 1
},
"script": {
"$call": "$1",
"$args": 1
}
}
},
{
"expandJsMacro": {
"description": "calculation",
"pattern": {
"\\$([+\\-*/=!<>&\\|^]{1,2})": 1
},
"script": {
"$exec": "calc",
"$method": {
"$1": {
"+": "add",
"-": "subtract",
"*": "multiply",
"/": "divide",
"==": "equal",
"!=": "notEqual",
">": "greater",
">=": "greaterEqual",
"<": "lesser",
"<=": "lesserEqual",
"&&": "and",
"||": "or",
"^^": "xor",
"!": "not"
}
},
"$args": 1
}
}
},
{
"additionalProperties": {
"$ref": "#"
}
}
]
},
{
"additionalProperties": {
"$ref": "#"
}
}
]
}
},
{
"if": {
"type": "array"
},
"then": {
"items": {
"$ref": "#"
}
}
}
]
}
30 changes: 30 additions & 0 deletions schema/expand_macros.json.dot
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"id": "http://www.json-script.com/schema/expand_macros.json#",
"$schema": "https://raw.githubusercontent.com/epoberezkin/ajv/master/lib/refs/json-schema-v5.json#",
"title": "JSONScript macro expansion schema",
"description": "Schema with custom keywords that expands macros in JSON script.",
"switch": [
{
"if": { "type": "object" },
"then": {
"allOf": [
{
"anyOf": [
{{~ it.macros:macro }}
{{~ macro.rules:rule }}
{ "expandJsMacro": {{= JSON.stringify(rule) }} },
{{~}}
{{~}}
{ "additionalProperties": { "$ref": "#" } }
]
},
{ "additionalProperties": { "$ref": "#" } }
]
}
},
{
"if": { "type": "array" },
"then": { "items": { "$ref": "#" } }
}
]
}
83 changes: 83 additions & 0 deletions schema/macro.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
{
"id": "http://www.json-script.com/schema/macro.json#",
"$schema": "https://raw.githubusercontent.com/epoberezkin/ajv/master/lib/refs/json-schema-v5.json#",
"description": "schema for macro definition",
"type": "object",
"required": [ "name", "description", "rules" ],
"additionalProperties": false,
"properties": {
"name": {
"decription": "macro name",
"$ref": "#nonEmptyString"
},
"description": {
"$ref": "#nonEmptyString"
},
"rules": {
"description": "macro rules",
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"required": [ "description", "pattern", "script" ],
"additionalProperties": false,
"properties": {
"description": { "$ref": "#nonEmptyString" },
"pattern": {
"type": "object",
"minProperties": 1,
"maxProperties": 1,
"additionalProperties": {
"description": "property itself should be a valid regular expression",
"type": "integer"
}
},
"script": {
"type": "object",
"additionalProperties": false,
"patternProperties": {
"^\\$[a-z]+$": {
"anyOf": [
{
"description": "this string referes to the partial match in macro pattern",
"type": "string",
"pattern": "^\\$[1-9]$"
},
{
"description": "object with a single property that refers to the match; the value of the property is a substitution map",
"type": "object",
"minProperties": 1,
"maxProperties": 1,
"additionalProperties": false,
"patternProperties": {
"^\\$[1-9]$": {
"type": "object",
"additionalProperties": {
"type": "string"
}
}
}
},
{
"description": "this number referes to the value in the macro",
"type": "integer"
},
{
"description": "any valid JSONScript"
}
]
}
}
}
}
}
}
},
"definitions": {
"nonEmptyString": {
"id": "#nonEmptyString",
"type": "string",
"minLength": 1
}
}
}
78 changes: 77 additions & 1 deletion schema/schema.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"id": "http://www.json-script.com/schema/schema.json#",
"$schema": "http://json-schema.org/draft-04/schema#",
"$schema": "https://raw.githubusercontent.com/epoberezkin/ajv/master/lib/refs/json-schema-v5.json#",
"title": "JSONScript schema",
"description": "JSONScript script with instructions (generated from template)",
"anyOf": [
@@ -28,6 +28,18 @@
{
"$ref": "#$quote"
},
{
"$ref": "#macro_exec_0"
},
{
"$ref": "#macro_exec_1"
},
{
"$ref": "#macro_call_0"
},
{
"$ref": "#macro_calc_0"
},
{
"$ref": "#parallel"
},
@@ -184,6 +196,70 @@
"$quote"
]
},
"_macro_exec_0": {
"id": "#macro_exec_0",
"description": "short syntax for executor call",
"type": "object",
"patternProperties": {
"^\\$\\$([^\\.]+)\\.([^\\.]+)$": {
"$ref": "#"
}
},
"maxProperties": 1,
"minProperties": 1,
"additionalProperties": false,
"patternRequired": [
"^\\$\\$([^\\.]+)\\.([^\\.]+)$"
]
},
"_macro_exec_1": {
"id": "#macro_exec_1",
"description": "short syntax for executor call",
"type": "object",
"patternProperties": {
"^\\$\\$([^\\.]+)$": {
"$ref": "#"
}
},
"maxProperties": 1,
"minProperties": 1,
"additionalProperties": false,
"patternRequired": [
"^\\$\\$([^\\.]+)$"
]
},
"_macro_call_0": {
"id": "#macro_call_0",
"description": "short syntax for function call",
"type": "object",
"patternProperties": {
"^\\$\\#(.+)$": {
"$ref": "#"
}
},
"maxProperties": 1,
"minProperties": 1,
"additionalProperties": false,
"patternRequired": [
"^\\$\\#(.+)$"
]
},
"_macro_calc_0": {
"id": "#macro_calc_0",
"description": "short calculations syntax",
"type": "object",
"patternProperties": {
"\\$([+\\-*/=!<>&\\|^]{1,2})": {
"$ref": "#"
}
},
"maxProperties": 1,
"minProperties": 1,
"additionalProperties": false,
"patternRequired": [
"\\$([+\\-*/=!<>&\\|^]{1,2})"
]
},
"parallel": {
"id": "#parallel",
"description": "scripts in the object are executed in parallel, property names should not start with $",
26 changes: 24 additions & 2 deletions schema/schema.json.dot
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
{
"id": "http://www.json-script.com/schema/schema{{?it.strictSchema}}_strict{{?}}.json#",
"$schema": "http://json-schema.org/draft-04/schema#",
"$schema": "https://raw.githubusercontent.com/epoberezkin/ajv/master/lib/refs/json-schema-v5.json#",
"title": "JSONScript schema",
"description": "JSONScript script with instructions (generated from template)",
"anyOf": [
{{~ it.instructions:inst }}
{ "$ref": "#{{=inst.name}}" },
{ "$ref": "#{{=inst.name}}" },
{{~}}
{{~ it.macros:macro }}
{{~ macro.rules:rule:i }}
{ "$ref": "#macro_{{=macro.name}}_{{=i}}" },
{{~}}
{{~}}
{ "$ref": "#parallel" },
{ "$ref": "#sequential" },
@@ -47,6 +52,23 @@
"required": {{= JSON.stringify(inst.required) }}
},
{{~}}
{{~ it.macros:macro }}
{{~ macro.rules:rule:i }}
{{ var patternKey = Object.keys(rule.pattern)[0].replace(/\\/g, '\\\\'); }}
"_macro_{{=macro.name}}_{{=i}}": {
"id": "#macro_{{=macro.name}}_{{=i}}",
"description": "{{=macro.description}}",
"type": "object",
"patternProperties": {
"{{= patternKey }}": { "$ref": "#" }
},
"maxProperties": 1,
"minProperties": 1,
"additionalProperties": false,
"patternRequired": [ "{{= patternKey }}" ]
},
{{~}}
{{~}}
"parallel": {
"id": "#parallel",
"description": "scripts in the object are executed in parallel, property names should not start with $",
78 changes: 77 additions & 1 deletion schema/schema_strict.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"id": "http://www.json-script.com/schema/schema_strict.json#",
"$schema": "http://json-schema.org/draft-04/schema#",
"$schema": "https://raw.githubusercontent.com/epoberezkin/ajv/master/lib/refs/json-schema-v5.json#",
"title": "JSONScript schema",
"description": "JSONScript script with instructions (generated from template)",
"anyOf": [
@@ -28,6 +28,18 @@
{
"$ref": "#$quote"
},
{
"$ref": "#macro_exec_0"
},
{
"$ref": "#macro_exec_1"
},
{
"$ref": "#macro_call_0"
},
{
"$ref": "#macro_calc_0"
},
{
"$ref": "#parallel"
},
@@ -330,6 +342,70 @@
"$quote"
]
},
"_macro_exec_0": {
"id": "#macro_exec_0",
"description": "short syntax for executor call",
"type": "object",
"patternProperties": {
"^\\$\\$([^\\.]+)\\.([^\\.]+)$": {
"$ref": "#"
}
},
"maxProperties": 1,
"minProperties": 1,
"additionalProperties": false,
"patternRequired": [
"^\\$\\$([^\\.]+)\\.([^\\.]+)$"
]
},
"_macro_exec_1": {
"id": "#macro_exec_1",
"description": "short syntax for executor call",
"type": "object",
"patternProperties": {
"^\\$\\$([^\\.]+)$": {
"$ref": "#"
}
},
"maxProperties": 1,
"minProperties": 1,
"additionalProperties": false,
"patternRequired": [
"^\\$\\$([^\\.]+)$"
]
},
"_macro_call_0": {
"id": "#macro_call_0",
"description": "short syntax for function call",
"type": "object",
"patternProperties": {
"^\\$\\#(.+)$": {
"$ref": "#"
}
},
"maxProperties": 1,
"minProperties": 1,
"additionalProperties": false,
"patternRequired": [
"^\\$\\#(.+)$"
]
},
"_macro_calc_0": {
"id": "#macro_calc_0",
"description": "short calculations syntax",
"type": "object",
"patternProperties": {
"\\$([+\\-*/=!<>&\\|^]{1,2})": {
"$ref": "#"
}
},
"maxProperties": 1,
"minProperties": 1,
"additionalProperties": false,
"patternRequired": [
"\\$([+\\-*/=!<>&\\|^]{1,2})"
]
},
"parallel": {
"id": "#parallel",
"description": "scripts in the object are executed in parallel, property names should not start with $",
8 changes: 7 additions & 1 deletion scripts/generate.js
Original file line number Diff line number Diff line change
@@ -3,15 +3,21 @@
var fs = require('fs');
var doT = require('dot');
var instructions = require('../instructions');
var macros = require('../macros');

generateSchema('schema');
generateSchema('schema', true);
generateSchema('expand_macros');
generateSchema('evaluate');


function generateSchema(schemaName, strictSchema) {
var template = getSchemaTemplate(schemaName);
var schemaStr = template({ instructions: instructions, strictSchema: strictSchema });
var schemaStr = template({
instructions: instructions,
macros: macros,
strictSchema: strictSchema
});
schemaStr = JSON.stringify(JSON.parse(schemaStr), null, ' ');
var schemaFile = getFileName(schemaName);
if (strictSchema) schemaFile = schemaFile.replace('.json', '_strict.json');
12 changes: 12 additions & 0 deletions spec/expand_macro.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
'use strict';

var Ajv = require('ajv');

var ajv = Ajv({ allErrors: true, v5: true });


describe('expand_macros schema', function() {
it('should be valid and should compile', function() {
ajv.compile(require('../schema/expand_macros'));
});
});
18 changes: 18 additions & 0 deletions spec/macro.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
'use strict';

var macros = require('../macros');
var Ajv = require('ajv');
var ajv = Ajv({ v5: true });
ajv.addSchema(require('../schema/schema.json'));
var validate = ajv.compile(require('../schema/macro.json'));
var assert = require('assert');


describe('macro definition validation', function() {
macros.forEach(function (macro) {
it(macro.name + ' should be valid according to schema', function() {
validate(macro);
assert.strictEqual(validate.errors, null);
});
});
});