style-script 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,11 @@
1
+ (function(){
2
+ var style, paths;
3
+ // Quickie script to compile and run all the files given as arguments.
4
+ process.mixin(require('sys'));
5
+ style = require('./style-script');
6
+ paths = process.ARGV;
7
+ paths = paths.slice(2, paths.length);
8
+ paths.length ? style.compile_files(paths, function(js) {
9
+ return eval(js);
10
+ }) : require('./repl');
11
+ })();
@@ -0,0 +1,129 @@
1
+ (function(){
2
+ var Scope, succ;
3
+ var __hasProp = Object.prototype.hasOwnProperty;
4
+ // Scope objects form a tree corresponding to the shape of the function
5
+ // definitions present in the script. They provide lexical scope, to determine
6
+ // whether a variable has been seen before or if it needs to be declared.
7
+ //
8
+ // Initialize a scope with its parent, for lookups up the chain,
9
+ // as well as the Expressions body where it should declare its variables,
10
+ // and the function that it wraps.
11
+ Scope = (exports.Scope = function Scope(parent, expressions, method) {
12
+ var __a;
13
+ this.parent = parent;
14
+ this.expressions = expressions;
15
+ this.method = method;
16
+ this.variables = {
17
+ };
18
+ this.temp_variable = this.parent ? this.parent.temp_variable : '__a';
19
+ __a = this;
20
+ return Scope === this.constructor ? this : __a;
21
+ });
22
+ // Look up a variable in lexical scope, or declare it if not found.
23
+ Scope.prototype.find = function find(name, remote) {
24
+ var found;
25
+ found = this.check(name);
26
+ if (found || remote) {
27
+ return found;
28
+ }
29
+ this.variables[name] = 'var';
30
+ return found;
31
+ };
32
+ // Define a local variable as originating from a parameter in current scope
33
+ // -- no var required.
34
+ Scope.prototype.parameter = function parameter(name) {
35
+ return this.variables[name] = 'param';
36
+ };
37
+ // Just check to see if a variable has already been declared.
38
+ Scope.prototype.check = function check(name) {
39
+ if (this.variables[name]) {
40
+ return true;
41
+ }
42
+ return !!(this.parent && this.parent.check(name));
43
+ };
44
+ // You can reset a found variable on the immediate scope.
45
+ Scope.prototype.reset = function reset(name) {
46
+ return delete this.variables[name];
47
+ };
48
+ // Find an available, short, name for a compiler-generated variable.
49
+ Scope.prototype.free_variable = function free_variable() {
50
+ while (this.check(this.temp_variable)) {
51
+ ((this.temp_variable = succ(this.temp_variable)));
52
+ }
53
+ this.variables[this.temp_variable] = 'var';
54
+ return this.temp_variable;
55
+ };
56
+ // Ensure that an assignment is made at the top of scope (or top-level
57
+ // scope, if requested).
58
+ Scope.prototype.assign = function assign(name, value, top_level) {
59
+ if (top_level && this.parent) {
60
+ return this.parent.assign(name, value, top_level);
61
+ }
62
+ return this.variables[name] = {
63
+ value: value,
64
+ assigned: true
65
+ };
66
+ };
67
+ // Does this scope reference any variables that need to be declared in the
68
+ // given function body?
69
+ Scope.prototype.has_declarations = function has_declarations(body) {
70
+ return body === this.expressions && this.declared_variables().length;
71
+ };
72
+ // Does this scope reference any assignments that need to be declared at the
73
+ // top of the given function body?
74
+ Scope.prototype.has_assignments = function has_assignments(body) {
75
+ return body === this.expressions && this.assigned_variables().length;
76
+ };
77
+ // Return the list of variables first declared in current scope.
78
+ Scope.prototype.declared_variables = function declared_variables() {
79
+ var __a, __b, key, val;
80
+ return ((function() {
81
+ __a = []; __b = this.variables;
82
+ for (key in __b) {
83
+ val = __b[key];
84
+ if (__hasProp.call(__b, key)) {
85
+ if (val === 'var') {
86
+ __a.push(key);
87
+ }
88
+ }
89
+ }
90
+ return __a;
91
+ }).call(this)).sort();
92
+ };
93
+ // Return the list of variables that are supposed to be assigned at the top
94
+ // of scope.
95
+ Scope.prototype.assigned_variables = function assigned_variables() {
96
+ var __a, __b, key, val;
97
+ return ((function() {
98
+ __a = []; __b = this.variables;
99
+ for (key in __b) {
100
+ val = __b[key];
101
+ if (__hasProp.call(__b, key)) {
102
+ if (val.assigned) {
103
+ __a.push([key, val.value]);
104
+ }
105
+ }
106
+ }
107
+ return __a;
108
+ }).call(this)).sort();
109
+ };
110
+ Scope.prototype.compiled_declarations = function compiled_declarations() {
111
+ return this.declared_variables().join(', ');
112
+ };
113
+ Scope.prototype.compiled_assignments = function compiled_assignments() {
114
+ var __a, __b, __c, t;
115
+ return ((function() {
116
+ __a = []; __b = this.assigned_variables();
117
+ for (__c = 0; __c < __b.length; __c++) {
118
+ t = __b[__c];
119
+ __a.push(t[0] + ' = ' + t[1]);
120
+ }
121
+ return __a;
122
+ }).call(this)).join(', ');
123
+ };
124
+ // Helper functions:
125
+ // The next character alphabetically, to produce the following string.
126
+ succ = function succ(str) {
127
+ return str.slice(0, str.length - 1) + String.fromCharCode(str.charCodeAt(str.length - 1) + 1);
128
+ };
129
+ })();
@@ -0,0 +1,95 @@
1
+ module StyleScript
2
+
3
+ # Scope objects form a tree corresponding to the shape of the function
4
+ # definitions present in the script. They provide lexical scope, to determine
5
+ # whether a variable has been seen before or if it needs to be declared.
6
+ class Scope
7
+
8
+ attr_reader :parent, :expressions, :function, :variables, :temp_variable
9
+
10
+ # Initialize a scope with its parent, for lookups up the chain,
11
+ # as well as the Expressions body where it should declare its variables,
12
+ # and the function that it wraps.
13
+ def initialize(parent, expressions, function)
14
+ @parent, @expressions, @function = parent, expressions, function
15
+ @variables = {}
16
+ @temp_variable = @parent ? @parent.temp_variable.dup : '__a'
17
+ end
18
+
19
+ # Look up a variable in lexical scope, or declare it if not found.
20
+ def find(name, remote=false)
21
+ found = check(name)
22
+ return found if found || remote
23
+ @variables[name.to_sym] = :var
24
+ found
25
+ end
26
+
27
+ # Define a local variable as originating from a parameter in current scope
28
+ # -- no var required.
29
+ def parameter(name)
30
+ @variables[name.to_sym] = :param
31
+ end
32
+
33
+ # Just check to see if a variable has already been declared.
34
+ def check(name)
35
+ return true if @variables[name.to_sym]
36
+ !!(@parent && @parent.check(name))
37
+ end
38
+
39
+ # You can reset a found variable on the immediate scope.
40
+ def reset(name)
41
+ @variables[name.to_sym] = false
42
+ end
43
+
44
+ # Find an available, short, name for a compiler-generated variable.
45
+ def free_variable
46
+ @temp_variable.succ! while check(@temp_variable)
47
+ @variables[@temp_variable.to_sym] = :var
48
+ Value.new(@temp_variable.dup)
49
+ end
50
+
51
+ # Ensure that an assignment is made at the top of scope (or top-level
52
+ # scope, if requested).
53
+ def assign(name, value, top=false)
54
+ return @parent.assign(name, value, top) if top && @parent
55
+ @variables[name.to_sym] = Value.new(value)
56
+ end
57
+
58
+ # Does this scope reference any variables that need to be declared in the
59
+ # given function body?
60
+ def declarations?(body)
61
+ !declared_variables.empty? && body == @expressions
62
+ end
63
+
64
+ # Does this scope reference any assignments that need to be declared at the
65
+ # top of the given function body?
66
+ def assignments?(body)
67
+ !assigned_variables.empty? && body == @expressions
68
+ end
69
+
70
+ # Return the list of variables first declared in current scope.
71
+ def declared_variables
72
+ @variables.select {|k, v| v == :var }.map {|pair| pair[0].to_s }.sort
73
+ end
74
+
75
+ # Return the list of variables that are supposed to be assigned at the top
76
+ # of scope.
77
+ def assigned_variables
78
+ @variables.select {|k, v| v.is_a?(Value) }.sort_by {|pair| pair[0].to_s }
79
+ end
80
+
81
+ def compiled_declarations
82
+ declared_variables.join(', ')
83
+ end
84
+
85
+ def compiled_assignments
86
+ assigned_variables.map {|name, val| "#{name} = #{val}"}.join(', ')
87
+ end
88
+
89
+ def inspect
90
+ "<Scope:#{__id__} #{@variables.inspect}>"
91
+ end
92
+
93
+ end
94
+
95
+ end
@@ -0,0 +1,96 @@
1
+ (function(){
2
+ var File, OS, Readline, checkForErrors, stylePath, factories, loader, puts;
3
+ // The Narwhal-compatibility wrapper for StyleScript.
4
+ // Require external dependencies.
5
+ OS = require('os');
6
+ File = require('file');
7
+ Readline = require('readline');
8
+ // The path to the StyleScript Compiler.
9
+ stylePath = File.path(module.path).dirname().dirname().dirname().dirname().join('bin', 'style');
10
+ // Our general-purpose error handler.
11
+ checkForErrors = function checkForErrors(styleProcess) {
12
+ if (styleProcess.wait() === 0) {
13
+ return true;
14
+ }
15
+ system.stderr.print(styleProcess.stderr.read());
16
+ throw new Error("StyleScript compile error");
17
+ };
18
+ // Alias print to "puts", for Node.js compatibility:
19
+ puts = print;
20
+ // Run a simple REPL, round-tripping to the StyleScript compiler for every
21
+ // command.
22
+ exports.run = function run(args) {
23
+ var __a, __b, i, path, result;
24
+ if (args.length) {
25
+ __a = args;
26
+ for (i = 0; i < __a.length; i++) {
27
+ path = __a[i];
28
+ exports.evalCS(File.read(path));
29
+ delete args[i];
30
+ }
31
+ return true;
32
+ }
33
+ __b = [];
34
+ while (true) {
35
+ __b.push((function() {
36
+ try {
37
+ system.stdout.write('style> ').flush();
38
+ result = exports.evalCS(Readline.readline(), ['--globals']);
39
+ if (result !== undefined) {
40
+ return print(result);
41
+ }
42
+ } catch (e) {
43
+ return print(e);
44
+ }
45
+ }).call(this));
46
+ }
47
+ return __b;
48
+ };
49
+ // Compile a given StyleScript file into JavaScript.
50
+ exports.compileFile = function compileFile(path) {
51
+ var style;
52
+ style = OS.popen([stylePath, "--print", "--no-wrap", path]);
53
+ checkForErrors(style);
54
+ return style.stdout.read();
55
+ };
56
+ // Compile a string of StyleScript into JavaScript.
57
+ exports.compile = function compile(source, flags) {
58
+ var style;
59
+ style = OS.popen([stylePath, "--eval", "--no-wrap"].concat(flags || []));
60
+ style.stdin.write(source).flush().close();
61
+ checkForErrors(style);
62
+ return style.stdout.read();
63
+ };
64
+ // Evaluating a string of StyleScript first compiles it externally.
65
+ exports.evalCS = function evalCS(source, flags) {
66
+ return eval(exports.compile(source, flags));
67
+ };
68
+ // Make a factory for the StyleScript environment.
69
+ exports.makeNarwhalFactory = function makeNarwhalFactory(path) {
70
+ var code, factoryText;
71
+ code = exports.compileFile(path);
72
+ factoryText = "function(require,exports,module,system,print){" + code + "/**/\n}";
73
+ if (system.engine === "rhino") {
74
+ return Packages.org.mozilla.javascript.Context.getCurrentContext().compileFunction(global, factoryText, path, 0, null);
75
+ } else {
76
+ // eval requires parentheses, but parentheses break compileFunction.
77
+ return eval("(" + factoryText + ")");
78
+ }
79
+ };
80
+ // The Narwhal loader for '.style' files.
81
+ factories = {
82
+ };
83
+ loader = {
84
+ };
85
+ // Reload the style-script environment from source.
86
+ loader.reload = function reload(topId, path) {
87
+ return factories[topId] = function() {
88
+ return exports.makeNarwhalFactory(path);
89
+ };
90
+ };
91
+ // Ensure that the style-script environment is loaded.
92
+ loader.load = function load(topId, path) {
93
+ return factories[topId] = factories[topId] || this.reload(topId, path);
94
+ };
95
+ require.loader.loaders.unshift([".style", loader]);
96
+ })();
@@ -0,0 +1,50 @@
1
+ (function(){
2
+ var compiler, path;
3
+ // Executes the `style` Ruby program to convert from StyleScript to JavaScript.
4
+ path = require('path');
5
+ // The path to the StyleScript executable.
6
+ compiler = path.normalize(path.dirname(__filename) + '/../../bin/style');
7
+ // Compile a string over stdin, with global variables, for the REPL.
8
+ exports.compile = function compile(code, callback) {
9
+ var style, js;
10
+ js = '';
11
+ style = process.createChildProcess(compiler, ['--eval', '--no-wrap', '--globals']);
12
+ style.addListener('output', function(results) {
13
+ if ((typeof results !== "undefined" && results !== null)) {
14
+ return js += results;
15
+ }
16
+ });
17
+ style.addListener('exit', function() {
18
+ return callback(js);
19
+ });
20
+ style.write(code);
21
+ return style.close();
22
+ };
23
+ // Compile a list of StyleScript files on disk.
24
+ exports.compile_files = function compile_files(paths, callback) {
25
+ var style, exit_ran, js;
26
+ js = '';
27
+ style = process.createChildProcess(compiler, ['--print'].concat(paths));
28
+ style.addListener('output', function(results) {
29
+ if ((typeof results !== "undefined" && results !== null)) {
30
+ return js += results;
31
+ }
32
+ });
33
+ // NB: we have to add a mutex to make sure it doesn't get called twice.
34
+ exit_ran = false;
35
+ style.addListener('exit', function() {
36
+ if (exit_ran) {
37
+ return null;
38
+ }
39
+ exit_ran = true;
40
+ return callback(js);
41
+ });
42
+ return style.addListener('error', function(message) {
43
+ if (!(message)) {
44
+ return null;
45
+ }
46
+ puts(message);
47
+ throw new Error("StyleScript compile error");
48
+ });
49
+ };
50
+ })();
@@ -0,0 +1,64 @@
1
+ module StyleScript
2
+
3
+ # Instead of producing raw Ruby objects, the Lexer produces values of this
4
+ # class, wrapping native objects tagged with line number information.
5
+ # Values masquerade as both strings and nodes -- being used both as nodes in
6
+ # the AST, and as literally-interpolated values in the generated code.
7
+ class Value
8
+ attr_reader :value, :line
9
+
10
+ def initialize(value, line=nil)
11
+ @value, @line = value, line
12
+ end
13
+
14
+ def to_str
15
+ @value.to_s
16
+ end
17
+ alias_method :to_s, :to_str
18
+
19
+ def to_sym
20
+ to_str.to_sym
21
+ end
22
+
23
+ def compile(o={})
24
+ to_s
25
+ end
26
+
27
+ def inspect
28
+ @value.inspect
29
+ end
30
+
31
+ def ==(other)
32
+ @value == other
33
+ end
34
+
35
+ def [](index)
36
+ @value[index]
37
+ end
38
+
39
+ def eql?(other)
40
+ @value.eql?(other)
41
+ end
42
+
43
+ def hash
44
+ @value.hash
45
+ end
46
+
47
+ def match(regex)
48
+ @value.match(regex)
49
+ end
50
+
51
+ def children
52
+ []
53
+ end
54
+
55
+ def statement_only?
56
+ false
57
+ end
58
+
59
+ def contains?
60
+ false
61
+ end
62
+ end
63
+
64
+ end