aboutsummaryrefslogtreecommitdiff
path: root/node_modules/montage/core/selector/abstract-semantics.js
blob: 9a55ecca0b561a07b852a940e5363cd191c21515 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
/* <copyright>
 This file contains proprietary software owned by Motorola Mobility, Inc.<br/>
 No rights, expressed or implied, whatsoever to this software are provided by Motorola Mobility, Inc. hereunder.<br/>
 (c) Copyright 2011 Motorola Mobility, Inc.  All Rights Reserved.
 </copyright> */

var Montage = require("montage").Montage;

var AbstractSemantics = exports.AbstractSemantics = Montage.create(Montage, {

    create: {
        value: function (prototype, descriptor) {
            var self = Montage.create(prototype, descriptor);

            var operators = self.operators;
            self.evaluatorArgumentLengths = {};

            // convert the declared operators into evaluators
            Object.keys(operators).forEach(function (name) {
                var operate = operators[name];
                self.evaluators[name] = function () { // ...args
                    var args = Array.prototype.slice.call(
                        arguments,
                        0,
                        operate.length
                    );
                    return function (value, parameters, visitor) {
                        return operate.apply(
                            operators,
                            args.map(function (argument) {
                                return argument(value, parameters, visitor);
                            })
                        );
                    };
                };
                self.evaluatorArgumentLengths[name] = operate.length;
            });

            return self;
        }
    },

    evaluatorArgumentLengths: {
        value: null
    },

    compile: {
        value: function (syntax, parents) {
            var self = this;
            parents = {
                syntax: syntax,
                parents: parents
            };
            if (syntax.type === 'value') {
                return function (value) {
                    return value;
                };
            } else if (syntax.type === 'parameters') {
                return function (value, parameters) {
                    return parameters;
                };
            } else if (syntax.type === 'literal') {
                return function () {
                    return syntax.value;
                };
            } else if (self.evaluators[syntax.type]) {
                var evaluator = self.evaluators[syntax.type];
                var length =
                    self.evaluatorArgumentLengths[syntax.type] ||
                        evaluator.length;
                var args = syntax.args.map(function (child) {
                    return self.compile(child, parents);
                });
                if (syntax.insensitive) {
                    args = args.map(function (evaluate) {
                        return function (value, parameters, visitor) {
                            return evaluate.call(
                                self,
                                value,
                                parameters,
                                visitor
                            ).toLowerCase();
                        };
                    })
                }
                return evaluator.apply(self, args.concat([parents]));
            } else {
                throw new Error("Unknown evaluator " + syntax.type);
            }
        }
    },

    evaluate: {
        value: function (syntax, value, parameters, visitor) {
            return this.compile(syntax)(value, parameters, visitor);
        }
    }

});