style-script 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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