style-script 1.0.1 → 1.0.2
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.
- data/examples/blocks.style +10 -10
- data/examples/code.style +17 -17
- data/examples/poignant.style +15 -15
- data/examples/potion.style +11 -11
- data/examples/underscore.style +93 -93
- data/lib/style-script.rb +1 -1
- data/lib/style_script/grammar.y +2 -2
- data/lib/style_script/nodes.js +2 -2
- data/lib/style_script/parser.js +48 -48
- data/lib/style_script/parser.rb +2 -2
- data/lib/style_script/rewriter.js +3 -3
- data/lib/style_script/rewriter.rb +3 -3
- data/lib/style_script/runner.js +2 -2
- data/package.json +1 -1
- data/style-script.gemspec +1 -1
- metadata +3 -3
data/examples/blocks.style
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
# After wycats' http://yehudakatz.com/2010/02/07/the-building-blocks-of-ruby/
|
|
2
2
|
|
|
3
3
|
# Sinatra.
|
|
4
|
-
get '/hello',
|
|
4
|
+
get '/hello', :>
|
|
5
5
|
'Hello World'
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
# Append.
|
|
9
|
-
append: (location, data)
|
|
9
|
+
append: (location, data) :>
|
|
10
10
|
path: new Pathname location
|
|
11
11
|
throw "Location does not exist" unless path.exists()
|
|
12
12
|
|
|
13
|
-
File.open path, 'a', (file)
|
|
13
|
+
File.open path, 'a', (file) :>
|
|
14
14
|
file.puts YAML.dump data
|
|
15
15
|
|
|
16
16
|
data
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
# Rubinius' File.open implementation.
|
|
20
|
-
File.open: (path, mode, block)
|
|
20
|
+
File.open: (path, mode, block) :>
|
|
21
21
|
io: new File path, mode
|
|
22
22
|
|
|
23
23
|
return io unless block
|
|
@@ -32,26 +32,26 @@ File.open: (path, mode, block) ->
|
|
|
32
32
|
|
|
33
33
|
|
|
34
34
|
# Write.
|
|
35
|
-
write: (location, data)
|
|
35
|
+
write: (location, data) :>
|
|
36
36
|
path = new Pathname location
|
|
37
37
|
raise "Location does not exist" unless path.exists()
|
|
38
38
|
|
|
39
|
-
File.open path, 'w', (file)
|
|
39
|
+
File.open path, 'w', (file) :>
|
|
40
40
|
return false if Digest.MD5.hexdigest(file.read()) is data.hash()
|
|
41
41
|
file.puts YAML.dump data
|
|
42
42
|
true
|
|
43
43
|
|
|
44
44
|
|
|
45
45
|
# Rails' respond_to.
|
|
46
|
-
index:
|
|
46
|
+
index: :>
|
|
47
47
|
people: Person.find 'all'
|
|
48
48
|
|
|
49
|
-
respond_to (format)
|
|
49
|
+
respond_to (format) :>
|
|
50
50
|
format.html()
|
|
51
|
-
format.xml
|
|
51
|
+
format.xml :> render { xml: people.xml() }
|
|
52
52
|
|
|
53
53
|
|
|
54
54
|
# Synchronization.
|
|
55
|
-
synchronize: (block)
|
|
55
|
+
synchronize: (block) :>
|
|
56
56
|
lock()
|
|
57
57
|
try block() finally unlock()
|
data/examples/code.style
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
# Functions:
|
|
2
|
-
square: (x)
|
|
2
|
+
square: (x) :> x * x
|
|
3
3
|
|
|
4
|
-
sum: (x, y)
|
|
4
|
+
sum: (x, y) :> x + y
|
|
5
5
|
|
|
6
|
-
odd: (x)
|
|
6
|
+
odd: (x) :> x % 2 isnt 0
|
|
7
7
|
|
|
8
|
-
even: (x)
|
|
8
|
+
even: (x) :> x % 2 is 0
|
|
9
9
|
|
|
10
|
-
run_loop:
|
|
11
|
-
fire_events((e)
|
|
10
|
+
run_loop: :>
|
|
11
|
+
fire_events((e) :> e.stopPropagation())
|
|
12
12
|
listen()
|
|
13
13
|
wait()
|
|
14
14
|
|
|
@@ -22,14 +22,14 @@ spaced_out_multiline_object: {
|
|
|
22
22
|
three: new Idea()
|
|
23
23
|
|
|
24
24
|
inner_obj: {
|
|
25
|
-
freedom:
|
|
25
|
+
freedom: :> _.freedom()
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
# Arrays:
|
|
30
30
|
stooges: [{moe: 45}, {curly: 43}, {larry: 46}]
|
|
31
31
|
|
|
32
|
-
exponents: [(x)
|
|
32
|
+
exponents: [(x) :> x, (x) :> x * x, (x) :> x * x * x]
|
|
33
33
|
|
|
34
34
|
empty: []
|
|
35
35
|
|
|
@@ -54,7 +54,7 @@ decoration: medal_of_honor if war_hero
|
|
|
54
54
|
go_to_sleep() unless style
|
|
55
55
|
|
|
56
56
|
# Returning early:
|
|
57
|
-
race:
|
|
57
|
+
race: :>
|
|
58
58
|
run()
|
|
59
59
|
walk()
|
|
60
60
|
crawl()
|
|
@@ -103,7 +103,7 @@ while true
|
|
|
103
103
|
|
|
104
104
|
# Lexical scoping.
|
|
105
105
|
v_1: 5
|
|
106
|
-
change_a_and_set_b:
|
|
106
|
+
change_a_and_set_b: :>
|
|
107
107
|
v_1: 10
|
|
108
108
|
v_2: 15
|
|
109
109
|
v_2: 20
|
|
@@ -128,7 +128,7 @@ activity: switch day
|
|
|
128
128
|
else go_to_work()
|
|
129
129
|
|
|
130
130
|
# Semicolons can optionally be used instead of newlines.
|
|
131
|
-
wednesday:
|
|
131
|
+
wednesday: :> eat_breakfast(); go_to_work(); eat_dinner()
|
|
132
132
|
|
|
133
133
|
# Array slice literals.
|
|
134
134
|
zero_to_nine: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
|
@@ -140,19 +140,19 @@ sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna
|
|
|
140
140
|
aliquam erat volutpat. Ut wisi enim ad."
|
|
141
141
|
|
|
142
142
|
# Inheritance and calling super.
|
|
143
|
-
Animal:
|
|
144
|
-
Animal::move: (meters)
|
|
143
|
+
Animal: :>
|
|
144
|
+
Animal::move: (meters) :>
|
|
145
145
|
alert(this.name + " moved " + meters + "m.")
|
|
146
146
|
|
|
147
|
-
Snake: (name)
|
|
147
|
+
Snake: (name) :> this.name: name
|
|
148
148
|
Snake extends Animal
|
|
149
|
-
Snake::move:
|
|
149
|
+
Snake::move: :>
|
|
150
150
|
alert('Slithering...')
|
|
151
151
|
super(5)
|
|
152
152
|
|
|
153
|
-
Horse: (name)
|
|
153
|
+
Horse: (name) :> this.name: name
|
|
154
154
|
Horse extends Animal
|
|
155
|
-
Horse::move:
|
|
155
|
+
Horse::move: :>
|
|
156
156
|
alert('Galloping...')
|
|
157
157
|
super(45)
|
|
158
158
|
|
data/examples/poignant.style
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
# ['toast', 'cheese', 'wine'].each { |food| print food.capitalize }
|
|
4
4
|
|
|
5
|
-
['toast', 'wine', 'cheese'].each (food)
|
|
5
|
+
['toast', 'wine', 'cheese'].each (food) :> print(food.capitalize())
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
|
|
@@ -14,10 +14,10 @@
|
|
|
14
14
|
# end
|
|
15
15
|
|
|
16
16
|
LotteryTicket: {
|
|
17
|
-
get_picks:
|
|
18
|
-
set_picks: (nums)
|
|
19
|
-
get_purchase:
|
|
20
|
-
set_purchase: (amount)
|
|
17
|
+
get_picks: :> this.picks
|
|
18
|
+
set_picks: (nums) :> this.picks: nums
|
|
19
|
+
get_purchase: :> this.purchase
|
|
20
|
+
set_purchase: (amount) :> this.purchase: amount
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
|
|
@@ -40,11 +40,11 @@ LotteryTicket: {
|
|
|
40
40
|
# end
|
|
41
41
|
|
|
42
42
|
LotteryDraw: {
|
|
43
|
-
play:
|
|
43
|
+
play: :>
|
|
44
44
|
result: LotteryTicket.new_random()
|
|
45
45
|
winners: {}
|
|
46
|
-
this.tickets.each (buyer, ticket_list)
|
|
47
|
-
ticket_list.each (ticket)
|
|
46
|
+
this.tickets.each (buyer, ticket_list) :>
|
|
47
|
+
ticket_list.each (ticket) :>
|
|
48
48
|
score: ticket.score(result)
|
|
49
49
|
return if score is 0
|
|
50
50
|
winners[buyer] ||= []
|
|
@@ -65,8 +65,8 @@ LotteryDraw: {
|
|
|
65
65
|
# end
|
|
66
66
|
|
|
67
67
|
WishScanner: {
|
|
68
|
-
scan_for_a_wish:
|
|
69
|
-
wish: this.read().detect((thought)
|
|
68
|
+
scan_for_a_wish: :>
|
|
69
|
+
wish: this.read().detect((thought) :> thought.index('wish: ') is 0)
|
|
70
70
|
wish.replace('wish: ', '')
|
|
71
71
|
}
|
|
72
72
|
|
|
@@ -111,7 +111,7 @@ WishScanner: {
|
|
|
111
111
|
Creature : {
|
|
112
112
|
|
|
113
113
|
# This method applies a hit taken during a fight.
|
|
114
|
-
hit: (damage)
|
|
114
|
+
hit: (damage) :>
|
|
115
115
|
p_up: Math.rand(this.charisma)
|
|
116
116
|
if p_up % 9 is 7
|
|
117
117
|
this.life += p_up / 4
|
|
@@ -120,7 +120,7 @@ Creature : {
|
|
|
120
120
|
if this.life <= 0 then puts("[" + this.name + " has died.]")
|
|
121
121
|
|
|
122
122
|
# This method takes one turn in a fight.
|
|
123
|
-
fight: (enemy, weapon)
|
|
123
|
+
fight: (enemy, weapon) :>
|
|
124
124
|
if this.life <= 0 then return puts("[" + this.name + "is too dead to fight!]")
|
|
125
125
|
|
|
126
126
|
# Attack the opponent.
|
|
@@ -156,12 +156,12 @@ Creature : {
|
|
|
156
156
|
# Get evil idea and swap in code words
|
|
157
157
|
print("Enter your new idea: ")
|
|
158
158
|
idea: gets()
|
|
159
|
-
code_words.each((real, code)
|
|
159
|
+
code_words.each((real, code) :> idea.replace(real, code))
|
|
160
160
|
|
|
161
161
|
# Save the jibberish to a new file
|
|
162
162
|
print("File encoded. Please enter a name for this idea: ")
|
|
163
163
|
idea_name: gets().strip()
|
|
164
|
-
File.open("idea-" + idea_name + '.txt', 'w', (file)
|
|
164
|
+
File.open("idea-" + idea_name + '.txt', 'w', (file) :> file.write(idea))
|
|
165
165
|
|
|
166
166
|
|
|
167
167
|
|
|
@@ -177,7 +177,7 @@ File.open("idea-" + idea_name + '.txt', 'w', (file) -> file.write(idea))
|
|
|
177
177
|
# end
|
|
178
178
|
# end
|
|
179
179
|
|
|
180
|
-
wipe_mutterings_from: (sentence)
|
|
180
|
+
wipe_mutterings_from: (sentence) :>
|
|
181
181
|
throw new Error("cannot wipe mutterings") unless sentence.indexOf
|
|
182
182
|
while sentence.indexOf('(') >= 0
|
|
183
183
|
open: sentence.indexOf('(') - 1
|
data/examples/potion.style
CHANGED
|
@@ -8,7 +8,7 @@ print("Odelay!") for i in [1..5]
|
|
|
8
8
|
# add = (x, y): x + y.
|
|
9
9
|
# add(2, 4) string print
|
|
10
10
|
|
|
11
|
-
add: (x, y)
|
|
11
|
+
add: (x, y) :> x + y
|
|
12
12
|
print(add(2, 4))
|
|
13
13
|
|
|
14
14
|
|
|
@@ -31,7 +31,7 @@ print({language: 'Potion', pointless: true}['language'])
|
|
|
31
31
|
# minus = (x, y): x - y.
|
|
32
32
|
# minus (y=10, x=6)
|
|
33
33
|
|
|
34
|
-
minus: (x, y)
|
|
34
|
+
minus: (x, y) :> x - y
|
|
35
35
|
minus(6, 10)
|
|
36
36
|
|
|
37
37
|
|
|
@@ -53,8 +53,8 @@ for key, val of {dog: 'canine', cat: 'feline', fox: 'vulpine'}
|
|
|
53
53
|
# Person print = ():
|
|
54
54
|
# ('My name is ', /name, '.') join print.
|
|
55
55
|
|
|
56
|
-
Person:
|
|
57
|
-
Person::print:
|
|
56
|
+
Person: :>
|
|
57
|
+
Person::print: :>
|
|
58
58
|
print('My name is ' + this.name + '.')
|
|
59
59
|
|
|
60
60
|
|
|
@@ -71,9 +71,9 @@ print(p.name)
|
|
|
71
71
|
#
|
|
72
72
|
# Policeman ('Constable') print
|
|
73
73
|
|
|
74
|
-
Policeman: (rank)
|
|
74
|
+
Policeman: (rank) :> this.rank: rank
|
|
75
75
|
Policeman extends Person
|
|
76
|
-
Policeman::print:
|
|
76
|
+
Policeman::print: :>
|
|
77
77
|
print('My name is ' + this.name + " and I'm a " + this.rank + '.')
|
|
78
78
|
|
|
79
79
|
print(new Policeman('Constable'))
|
|
@@ -115,13 +115,13 @@ table: {
|
|
|
115
115
|
# String length = (): 10.
|
|
116
116
|
|
|
117
117
|
# this foul business...
|
|
118
|
-
String::length:
|
|
118
|
+
String::length: :> 10
|
|
119
119
|
|
|
120
120
|
|
|
121
121
|
# block = :
|
|
122
122
|
# 'potion' print.
|
|
123
123
|
|
|
124
|
-
block:
|
|
124
|
+
block: :>
|
|
125
125
|
print('potion')
|
|
126
126
|
|
|
127
127
|
|
|
@@ -178,7 +178,7 @@ if (3).gender?
|
|
|
178
178
|
# HomePage get = (url):
|
|
179
179
|
# session = url query ? at ('session').
|
|
180
180
|
|
|
181
|
-
HomePage::get: (url)
|
|
181
|
+
HomePage::get: (url) :>
|
|
182
182
|
session: url.query.session if url.query?
|
|
183
183
|
|
|
184
184
|
|
|
@@ -187,7 +187,7 @@ HomePage::get: (url) ->
|
|
|
187
187
|
# b /left = BTree ()
|
|
188
188
|
# b /right = BTree ()
|
|
189
189
|
|
|
190
|
-
BTree:
|
|
190
|
+
BTree: :>
|
|
191
191
|
b: new BTree()
|
|
192
192
|
b.left: new BTree()
|
|
193
193
|
b.right: new BTree()
|
|
@@ -199,7 +199,7 @@ b.right: new BTree()
|
|
|
199
199
|
# if (b ? /left):
|
|
200
200
|
# 'left path found!' print.
|
|
201
201
|
|
|
202
|
-
BTree:
|
|
202
|
+
BTree: :>
|
|
203
203
|
b: new BTree()
|
|
204
204
|
|
|
205
205
|
print('left path found!') if b.left?
|
data/examples/underscore.style
CHANGED
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
# If Underscore is called as a function, it returns a wrapped object that
|
|
22
22
|
# can be used OO-style. This wrapper holds altered versions of all the
|
|
23
23
|
# underscore functions. Wrapped objects may be chained.
|
|
24
|
-
wrapper: (obj)
|
|
24
|
+
wrapper: (obj) :>
|
|
25
25
|
this._wrapped: obj
|
|
26
26
|
this
|
|
27
27
|
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
|
|
32
32
|
|
|
33
33
|
# Create a safe reference to the Underscore object forreference below.
|
|
34
|
-
_: root._: (obj)
|
|
34
|
+
_: root._: (obj) :> new wrapper(obj)
|
|
35
35
|
|
|
36
36
|
|
|
37
37
|
# Export the Underscore object for CommonJS.
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
|
|
55
55
|
# The cornerstone, an each implementation.
|
|
56
56
|
# Handles objects implementing forEach, arrays, and raw objects.
|
|
57
|
-
_.each: (obj, iterator, context)
|
|
57
|
+
_.each: (obj, iterator, context) :>
|
|
58
58
|
index: 0
|
|
59
59
|
try
|
|
60
60
|
return obj.forEach(iterator, context) if obj.forEach
|
|
@@ -68,36 +68,36 @@
|
|
|
68
68
|
|
|
69
69
|
# Return the results of applying the iterator to each element. Use JavaScript
|
|
70
70
|
# 1.6's version of map, if possible.
|
|
71
|
-
_.map: (obj, iterator, context)
|
|
71
|
+
_.map: (obj, iterator, context) :>
|
|
72
72
|
return obj.map(iterator, context) if (obj and _.isFunction(obj.map))
|
|
73
73
|
results: []
|
|
74
|
-
_.each obj, (value, index, list)
|
|
74
|
+
_.each obj, (value, index, list) :>
|
|
75
75
|
results.push(iterator.call(context, value, index, list))
|
|
76
76
|
results
|
|
77
77
|
|
|
78
78
|
|
|
79
79
|
# Reduce builds up a single result from a list of values. Also known as
|
|
80
80
|
# inject, or foldl. Uses JavaScript 1.8's version of reduce, if possible.
|
|
81
|
-
_.reduce: (obj, memo, iterator, context)
|
|
81
|
+
_.reduce: (obj, memo, iterator, context) :>
|
|
82
82
|
return obj.reduce(_.bind(iterator, context), memo) if (obj and _.isFunction(obj.reduce))
|
|
83
|
-
_.each obj, (value, index, list)
|
|
83
|
+
_.each obj, (value, index, list) :>
|
|
84
84
|
memo: iterator.call(context, memo, value, index, list)
|
|
85
85
|
memo
|
|
86
86
|
|
|
87
87
|
|
|
88
88
|
# The right-associative version of reduce, also known as foldr. Uses
|
|
89
89
|
# JavaScript 1.8's version of reduceRight, if available.
|
|
90
|
-
_.reduceRight: (obj, memo, iterator, context)
|
|
90
|
+
_.reduceRight: (obj, memo, iterator, context) :>
|
|
91
91
|
return obj.reduceRight(_.bind(iterator, context), memo) if (obj and _.isFunction(obj.reduceRight))
|
|
92
|
-
_.each _.clone(_.toArray(obj)).reverse(), (value, index)
|
|
92
|
+
_.each _.clone(_.toArray(obj)).reverse(), (value, index) :>
|
|
93
93
|
memo: iterator.call(context, memo, value, index, obj)
|
|
94
94
|
memo
|
|
95
95
|
|
|
96
96
|
|
|
97
97
|
# Return the first value which passes a truth test.
|
|
98
|
-
_.detect: (obj, iterator, context)
|
|
98
|
+
_.detect: (obj, iterator, context) :>
|
|
99
99
|
result: null
|
|
100
|
-
_.each obj, (value, index, list)
|
|
100
|
+
_.each obj, (value, index, list) :>
|
|
101
101
|
if iterator.call(context, value, index, list)
|
|
102
102
|
result: value
|
|
103
103
|
_.breakLoop()
|
|
@@ -106,47 +106,47 @@
|
|
|
106
106
|
|
|
107
107
|
# Return all the elements that pass a truth test. Use JavaScript 1.6's
|
|
108
108
|
# filter(), if it exists.
|
|
109
|
-
_.select: (obj, iterator, context)
|
|
109
|
+
_.select: (obj, iterator, context) :>
|
|
110
110
|
if obj and _.isFunction(obj.filter) then return obj.filter(iterator, context)
|
|
111
111
|
results: []
|
|
112
|
-
_.each obj, (value, index, list)
|
|
112
|
+
_.each obj, (value, index, list) :>
|
|
113
113
|
results.push(value) if iterator.call(context, value, index, list)
|
|
114
114
|
results
|
|
115
115
|
|
|
116
116
|
|
|
117
117
|
# Return all the elements for which a truth test fails.
|
|
118
|
-
_.reject: (obj, iterator, context)
|
|
118
|
+
_.reject: (obj, iterator, context) :>
|
|
119
119
|
results: []
|
|
120
|
-
_.each obj, (value, index, list)
|
|
120
|
+
_.each obj, (value, index, list) :>
|
|
121
121
|
results.push(value) if not iterator.call(context, value, index, list)
|
|
122
122
|
results
|
|
123
123
|
|
|
124
124
|
|
|
125
125
|
# Determine whether all of the elements match a truth test. Delegate to
|
|
126
126
|
# JavaScript 1.6's every(), if it is present.
|
|
127
|
-
_.all: (obj, iterator, context)
|
|
127
|
+
_.all: (obj, iterator, context) :>
|
|
128
128
|
iterator ||= _.identity
|
|
129
129
|
return obj.every(iterator, context) if obj and _.isFunction(obj.every)
|
|
130
130
|
result: true
|
|
131
|
-
_.each obj, (value, index, list)
|
|
131
|
+
_.each obj, (value, index, list) :>
|
|
132
132
|
_.breakLoop() unless (result: result and iterator.call(context, value, index, list))
|
|
133
133
|
result
|
|
134
134
|
|
|
135
135
|
|
|
136
136
|
# Determine if at least one element in the object matches a truth test. Use
|
|
137
137
|
# JavaScript 1.6's some(), if it exists.
|
|
138
|
-
_.any: (obj, iterator, context)
|
|
138
|
+
_.any: (obj, iterator, context) :>
|
|
139
139
|
iterator ||= _.identity
|
|
140
140
|
return obj.some(iterator, context) if obj and _.isFunction(obj.some)
|
|
141
141
|
result: false
|
|
142
|
-
_.each obj, (value, index, list)
|
|
142
|
+
_.each obj, (value, index, list) :>
|
|
143
143
|
_.breakLoop() if (result: iterator.call(context, value, index, list))
|
|
144
144
|
result
|
|
145
145
|
|
|
146
146
|
|
|
147
147
|
# Determine if a given value is included in the array or object,
|
|
148
148
|
# based on '==='.
|
|
149
|
-
_.include: (obj, target)
|
|
149
|
+
_.include: (obj, target) :>
|
|
150
150
|
return _.indexOf(obj, target) isnt -1 if _.isArray(obj)
|
|
151
151
|
for key, val of obj
|
|
152
152
|
return true if val is target
|
|
@@ -154,41 +154,41 @@
|
|
|
154
154
|
|
|
155
155
|
|
|
156
156
|
# Invoke a method with arguments on every item in a collection.
|
|
157
|
-
_.invoke: (obj, method)
|
|
157
|
+
_.invoke: (obj, method) :>
|
|
158
158
|
args: _.rest(arguments, 2)
|
|
159
159
|
(if method then val[method] else val).apply(val, args) for val in obj
|
|
160
160
|
|
|
161
161
|
|
|
162
162
|
# Convenience version of a common use case of map: fetching a property.
|
|
163
|
-
_.pluck: (obj, key)
|
|
164
|
-
_.map(obj, ((val)
|
|
163
|
+
_.pluck: (obj, key) :>
|
|
164
|
+
_.map(obj, ((val) :> val[key]))
|
|
165
165
|
|
|
166
166
|
|
|
167
167
|
# Return the maximum item or (item-based computation).
|
|
168
|
-
_.max: (obj, iterator, context)
|
|
168
|
+
_.max: (obj, iterator, context) :>
|
|
169
169
|
return Math.max.apply(Math, obj) if not iterator and _.isArray(obj)
|
|
170
170
|
result: {computed: -Infinity}
|
|
171
|
-
_.each obj, (value, index, list)
|
|
171
|
+
_.each obj, (value, index, list) :>
|
|
172
172
|
computed: if iterator then iterator.call(context, value, index, list) else value
|
|
173
173
|
computed >= result.computed and (result: {value: value, computed: computed})
|
|
174
174
|
result.value
|
|
175
175
|
|
|
176
176
|
|
|
177
177
|
# Return the minimum element (or element-based computation).
|
|
178
|
-
_.min: (obj, iterator, context)
|
|
178
|
+
_.min: (obj, iterator, context) :>
|
|
179
179
|
return Math.min.apply(Math, obj) if not iterator and _.isArray(obj)
|
|
180
180
|
result: {computed: Infinity}
|
|
181
|
-
_.each obj, (value, index, list)
|
|
181
|
+
_.each obj, (value, index, list) :>
|
|
182
182
|
computed: if iterator then iterator.call(context, value, index, list) else value
|
|
183
183
|
computed < result.computed and (result: {value: value, computed: computed})
|
|
184
184
|
result.value
|
|
185
185
|
|
|
186
186
|
|
|
187
187
|
# Sort the object's values by a criteria produced by an iterator.
|
|
188
|
-
_.sortBy: (obj, iterator, context)
|
|
189
|
-
_.pluck(((_.map obj, (value, index, list)
|
|
188
|
+
_.sortBy: (obj, iterator, context) :>
|
|
189
|
+
_.pluck(((_.map obj, (value, index, list) :>
|
|
190
190
|
{value: value, criteria: iterator.call(context, value, index, list)}
|
|
191
|
-
).sort((left, right)
|
|
191
|
+
).sort((left, right) :>
|
|
192
192
|
a: left.criteria; b: right.criteria
|
|
193
193
|
if a < b then -1 else if a > b then 1 else 0
|
|
194
194
|
)), 'value')
|
|
@@ -196,7 +196,7 @@
|
|
|
196
196
|
|
|
197
197
|
# Use a comparator function to figure out at what index an object should
|
|
198
198
|
# be inserted so as to maintain order. Uses binary search.
|
|
199
|
-
_.sortedIndex: (array, obj, iterator)
|
|
199
|
+
_.sortedIndex: (array, obj, iterator) :>
|
|
200
200
|
iterator ||= _.identity
|
|
201
201
|
low: 0; high: array.length
|
|
202
202
|
while low < high
|
|
@@ -206,7 +206,7 @@
|
|
|
206
206
|
|
|
207
207
|
|
|
208
208
|
# Convert anything iterable into a real, live array.
|
|
209
|
-
_.toArray: (iterable)
|
|
209
|
+
_.toArray: (iterable) :>
|
|
210
210
|
return [] if (!iterable)
|
|
211
211
|
return iterable.toArray() if (iterable.toArray)
|
|
212
212
|
return iterable if (_.isArray(iterable))
|
|
@@ -215,7 +215,7 @@
|
|
|
215
215
|
|
|
216
216
|
|
|
217
217
|
# Return the number of elements in an object.
|
|
218
|
-
_.size: (obj)
|
|
218
|
+
_.size: (obj) :> _.toArray(obj).length
|
|
219
219
|
|
|
220
220
|
|
|
221
221
|
# -------------------------- Array Functions: ------------------------------
|
|
@@ -223,7 +223,7 @@
|
|
|
223
223
|
# Get the first element of an array. Passing "n" will return the first N
|
|
224
224
|
# values in the array. Aliased as "head". The "guard" check allows it to work
|
|
225
225
|
# with _.map.
|
|
226
|
-
_.first: (array, n, guard)
|
|
226
|
+
_.first: (array, n, guard) :>
|
|
227
227
|
if n and not guard then slice.call(array, 0, n) else array[0]
|
|
228
228
|
|
|
229
229
|
|
|
@@ -231,35 +231,35 @@
|
|
|
231
231
|
# Especially useful on the arguments object. Passing an "index" will return
|
|
232
232
|
# the rest of the values in the array from that index onward. The "guard"
|
|
233
233
|
# check allows it to work with _.map.
|
|
234
|
-
_.rest: (array, index, guard)
|
|
234
|
+
_.rest: (array, index, guard) :>
|
|
235
235
|
slice.call(array, if _.isUndefined(index) or guard then 1 else index)
|
|
236
236
|
|
|
237
237
|
|
|
238
238
|
# Get the last element of an array.
|
|
239
|
-
_.last: (array)
|
|
239
|
+
_.last: (array) :> array[array.length - 1]
|
|
240
240
|
|
|
241
241
|
|
|
242
242
|
# Trim out all falsy values from an array.
|
|
243
|
-
_.compact: (array)
|
|
243
|
+
_.compact: (array) :> array[i] for i in [0...array.length] when array[i]
|
|
244
244
|
|
|
245
245
|
|
|
246
246
|
# Return a completely flattened version of an array.
|
|
247
|
-
_.flatten: (array)
|
|
248
|
-
_.reduce array, [], (memo, value)
|
|
247
|
+
_.flatten: (array) :>
|
|
248
|
+
_.reduce array, [], (memo, value) :>
|
|
249
249
|
return memo.concat(_.flatten(value)) if _.isArray(value)
|
|
250
250
|
memo.push(value)
|
|
251
251
|
memo
|
|
252
252
|
|
|
253
253
|
|
|
254
254
|
# Return a version of the array that does not contain the specified value(s).
|
|
255
|
-
_.without: (array)
|
|
255
|
+
_.without: (array) :>
|
|
256
256
|
values: _.rest(arguments)
|
|
257
257
|
val for val in _.toArray(array) when not _.include(values, val)
|
|
258
258
|
|
|
259
259
|
|
|
260
260
|
# Produce a duplicate-free version of the array. If the array has already
|
|
261
261
|
# been sorted, you have the option of using a faster algorithm.
|
|
262
|
-
_.uniq: (array, isSorted)
|
|
262
|
+
_.uniq: (array, isSorted) :>
|
|
263
263
|
memo: []
|
|
264
264
|
for el, i in _.toArray(array)
|
|
265
265
|
memo.push(el) if i is 0 || (if isSorted is true then _.last(memo) isnt el else not _.include(memo, el))
|
|
@@ -268,16 +268,16 @@
|
|
|
268
268
|
|
|
269
269
|
# Produce an array that contains every item shared between all the
|
|
270
270
|
# passed-in arrays.
|
|
271
|
-
_.intersect: (array)
|
|
271
|
+
_.intersect: (array) :>
|
|
272
272
|
rest: _.rest(arguments)
|
|
273
|
-
_.select _.uniq(array), (item)
|
|
274
|
-
_.all rest, (other)
|
|
273
|
+
_.select _.uniq(array), (item) :>
|
|
274
|
+
_.all rest, (other) :>
|
|
275
275
|
_.indexOf(other, item) >= 0
|
|
276
276
|
|
|
277
277
|
|
|
278
278
|
# Zip together multiple lists into a single array -- elements that share
|
|
279
279
|
# an index go together.
|
|
280
|
-
_.zip:
|
|
280
|
+
_.zip: :>
|
|
281
281
|
length: _.max(_.pluck(arguments, 'length'))
|
|
282
282
|
results: new Array(length)
|
|
283
283
|
for i in [0...length]
|
|
@@ -288,7 +288,7 @@
|
|
|
288
288
|
# If the browser doesn't supply us with indexOf (I'm looking at you, MSIE),
|
|
289
289
|
# we need this function. Return the position of the first occurence of an
|
|
290
290
|
# item in an array, or -1 if the item is not included in the array.
|
|
291
|
-
_.indexOf: (array, item)
|
|
291
|
+
_.indexOf: (array, item) :>
|
|
292
292
|
return array.indexOf(item) if array.indexOf
|
|
293
293
|
i: 0; l: array.length
|
|
294
294
|
while l - i
|
|
@@ -298,7 +298,7 @@
|
|
|
298
298
|
|
|
299
299
|
# Provide JavaScript 1.6's lastIndexOf, delegating to the native function,
|
|
300
300
|
# if possible.
|
|
301
|
-
_.lastIndexOf: (array, item)
|
|
301
|
+
_.lastIndexOf: (array, item) :>
|
|
302
302
|
return array.lastIndexOf(item) if array.lastIndexOf
|
|
303
303
|
i: array.length
|
|
304
304
|
while i
|
|
@@ -309,7 +309,7 @@
|
|
|
309
309
|
# Generate an integer Array containing an arithmetic progression. A port of
|
|
310
310
|
# the native Python range() function. See:
|
|
311
311
|
# http://docs.python.org/library/functions.html#range
|
|
312
|
-
_.range: (start, stop, step)
|
|
312
|
+
_.range: (start, stop, step) :>
|
|
313
313
|
a: arguments
|
|
314
314
|
solo: a.length <= 1
|
|
315
315
|
i: start: if solo then 0 else a[0];
|
|
@@ -330,44 +330,44 @@
|
|
|
330
330
|
|
|
331
331
|
# Create a function bound to a given object (assigning 'this', and arguments,
|
|
332
332
|
# optionally). Binding with arguments is also known as 'curry'.
|
|
333
|
-
_.bind: (func, obj)
|
|
333
|
+
_.bind: (func, obj) :>
|
|
334
334
|
args: _.rest(arguments, 2)
|
|
335
|
-
|
|
335
|
+
:> func.apply(obj or root, args.concat(arguments))
|
|
336
336
|
|
|
337
337
|
|
|
338
338
|
# Bind all of an object's methods to that object. Useful for ensuring that
|
|
339
339
|
# all callbacks defined on an object belong to it.
|
|
340
|
-
_.bindAll: (obj)
|
|
340
|
+
_.bindAll: (obj) :>
|
|
341
341
|
funcs: if arguments.length > 1 then _.rest(arguments) else _.functions(obj)
|
|
342
|
-
_.each(funcs, (f)
|
|
342
|
+
_.each(funcs, (f) :> obj[f]: _.bind(obj[f], obj))
|
|
343
343
|
obj
|
|
344
344
|
|
|
345
345
|
|
|
346
346
|
# Delays a function for the given number of milliseconds, and then calls
|
|
347
347
|
# it with the arguments supplied.
|
|
348
|
-
_.delay: (func, wait)
|
|
348
|
+
_.delay: (func, wait) :>
|
|
349
349
|
args: _.rest(arguments, 2)
|
|
350
|
-
setTimeout((
|
|
350
|
+
setTimeout((:> func.apply(func, args)), wait)
|
|
351
351
|
|
|
352
352
|
|
|
353
353
|
# Defers a function, scheduling it to run after the current call stack has
|
|
354
354
|
# cleared.
|
|
355
|
-
_.defer: (func)
|
|
355
|
+
_.defer: (func) :>
|
|
356
356
|
_.delay.apply(_, [func, 1].concat(_.rest(arguments)))
|
|
357
357
|
|
|
358
358
|
|
|
359
359
|
# Returns the first function passed as an argument to the second,
|
|
360
360
|
# allowing you to adjust arguments, run code before and after, and
|
|
361
361
|
# conditionally execute the original function.
|
|
362
|
-
_.wrap: (func, wrapper)
|
|
363
|
-
|
|
362
|
+
_.wrap: (func, wrapper) :>
|
|
363
|
+
:> wrapper.apply(wrapper, [func].concat(arguments))
|
|
364
364
|
|
|
365
365
|
|
|
366
366
|
# Returns a function that is the composition of a list of functions, each
|
|
367
367
|
# consuming the return value of the function that follows.
|
|
368
|
-
_.compose:
|
|
368
|
+
_.compose: :>
|
|
369
369
|
funcs: arguments
|
|
370
|
-
|
|
370
|
+
:>
|
|
371
371
|
args: arguments
|
|
372
372
|
for i in [(funcs.length - 1)..0]
|
|
373
373
|
args: [funcs[i].apply(this, args)]
|
|
@@ -377,43 +377,43 @@
|
|
|
377
377
|
# ------------------------- Object Functions: ----------------------------
|
|
378
378
|
|
|
379
379
|
# Retrieve the names of an object's properties.
|
|
380
|
-
_.keys: (obj)
|
|
380
|
+
_.keys: (obj) :>
|
|
381
381
|
return _.range(0, obj.length) if _.isArray(obj)
|
|
382
382
|
key for key, val of obj
|
|
383
383
|
|
|
384
384
|
|
|
385
385
|
# Retrieve the values of an object's properties.
|
|
386
|
-
_.values: (obj)
|
|
386
|
+
_.values: (obj) :>
|
|
387
387
|
_.map(obj, _.identity)
|
|
388
388
|
|
|
389
389
|
|
|
390
390
|
# Return a sorted list of the function names available in Underscore.
|
|
391
|
-
_.functions: (obj)
|
|
392
|
-
_.select(_.keys(obj), (key)
|
|
391
|
+
_.functions: (obj) :>
|
|
392
|
+
_.select(_.keys(obj), (key) :> _.isFunction(obj[key])).sort()
|
|
393
393
|
|
|
394
394
|
|
|
395
395
|
# Extend a given object with all of the properties in a source object.
|
|
396
|
-
_.extend: (destination, source)
|
|
396
|
+
_.extend: (destination, source) :>
|
|
397
397
|
for key, val of source
|
|
398
398
|
destination[key]: val
|
|
399
399
|
destination
|
|
400
400
|
|
|
401
401
|
|
|
402
402
|
# Create a (shallow-cloned) duplicate of an object.
|
|
403
|
-
_.clone: (obj)
|
|
403
|
+
_.clone: (obj) :>
|
|
404
404
|
return obj.slice(0) if _.isArray(obj)
|
|
405
405
|
_.extend({}, obj)
|
|
406
406
|
|
|
407
407
|
|
|
408
408
|
# Invokes interceptor with the obj, and then returns obj.
|
|
409
409
|
# The primary purpose of this method is to "tap into" a method chain, in order to perform operations on intermediate results within the chain.
|
|
410
|
-
_.tap: (obj, interceptor)
|
|
410
|
+
_.tap: (obj, interceptor) :>
|
|
411
411
|
interceptor(obj)
|
|
412
412
|
obj
|
|
413
413
|
|
|
414
414
|
|
|
415
415
|
# Perform a deep comparison to check if two objects are equal.
|
|
416
|
-
_.isEqual: (a, b)
|
|
416
|
+
_.isEqual: (a, b) :>
|
|
417
417
|
# Check object identity.
|
|
418
418
|
return true if a is b
|
|
419
419
|
# Different types?
|
|
@@ -449,76 +449,76 @@
|
|
|
449
449
|
|
|
450
450
|
|
|
451
451
|
# Is a given array or object empty?
|
|
452
|
-
_.isEmpty: (obj)
|
|
452
|
+
_.isEmpty: (obj) :> _.keys(obj).length is 0
|
|
453
453
|
|
|
454
454
|
|
|
455
455
|
# Is a given value a DOM element?
|
|
456
|
-
_.isElement: (obj)
|
|
456
|
+
_.isElement: (obj) :> obj and obj.nodeType is 1
|
|
457
457
|
|
|
458
458
|
|
|
459
459
|
# Is a given value an array?
|
|
460
|
-
_.isArray: (obj)
|
|
460
|
+
_.isArray: (obj) :> !!(obj and obj.concat and obj.unshift)
|
|
461
461
|
|
|
462
462
|
|
|
463
463
|
# Is a given variable an arguments object?
|
|
464
|
-
_.isArguments: (obj)
|
|
464
|
+
_.isArguments: (obj) :> obj and _.isNumber(obj.length) and not obj.concat and
|
|
465
465
|
not obj.substr and not obj.apply and not propertyIsEnumerable.call(obj, 'length')
|
|
466
466
|
|
|
467
467
|
|
|
468
468
|
# Is the given value a function?
|
|
469
|
-
_.isFunction: (obj)
|
|
469
|
+
_.isFunction: (obj) :> !!(obj and obj.constructor and obj.call and obj.apply)
|
|
470
470
|
|
|
471
471
|
|
|
472
472
|
# Is the given value a string?
|
|
473
|
-
_.isString: (obj)
|
|
473
|
+
_.isString: (obj) :> !!(obj is '' or (obj and obj.charCodeAt and obj.substr))
|
|
474
474
|
|
|
475
475
|
|
|
476
476
|
# Is a given value a number?
|
|
477
|
-
_.isNumber: (obj)
|
|
477
|
+
_.isNumber: (obj) :> (obj is +obj) or toString.call(obj) is '[object Number]'
|
|
478
478
|
|
|
479
479
|
|
|
480
480
|
# Is a given value a Date?
|
|
481
|
-
_.isDate: (obj)
|
|
481
|
+
_.isDate: (obj) :> !!(obj and obj.getTimezoneOffset and obj.setUTCFullYear)
|
|
482
482
|
|
|
483
483
|
|
|
484
484
|
# Is the given value a regular expression?
|
|
485
|
-
_.isRegExp: (obj)
|
|
485
|
+
_.isRegExp: (obj) :> !!(obj and obj.exec and (obj.ignoreCase or obj.ignoreCase is false))
|
|
486
486
|
|
|
487
487
|
|
|
488
488
|
# Is the given value NaN -- this one is interesting. NaN != NaN, and
|
|
489
489
|
# isNaN(undefined) == true, so we make sure it's a number first.
|
|
490
|
-
_.isNaN: (obj)
|
|
490
|
+
_.isNaN: (obj) :> _.isNumber(obj) and window.isNaN(obj)
|
|
491
491
|
|
|
492
492
|
|
|
493
493
|
# Is a given value equal to null?
|
|
494
|
-
_.isNull: (obj)
|
|
494
|
+
_.isNull: (obj) :> obj is null
|
|
495
495
|
|
|
496
496
|
|
|
497
497
|
# Is a given variable undefined?
|
|
498
|
-
_.isUndefined: (obj)
|
|
498
|
+
_.isUndefined: (obj) :> typeof obj is 'undefined'
|
|
499
499
|
|
|
500
500
|
|
|
501
501
|
# -------------------------- Utility Functions: --------------------------
|
|
502
502
|
|
|
503
503
|
# Run Underscore.js in noConflict mode, returning the '_' variable to its
|
|
504
504
|
# previous owner. Returns a reference to the Underscore object.
|
|
505
|
-
_.noConflict:
|
|
505
|
+
_.noConflict: :>
|
|
506
506
|
root._: previousUnderscore
|
|
507
507
|
this
|
|
508
508
|
|
|
509
509
|
|
|
510
510
|
# Keep the identity function around for default iterators.
|
|
511
|
-
_.identity: (value)
|
|
511
|
+
_.identity: (value) :> value
|
|
512
512
|
|
|
513
513
|
|
|
514
514
|
# Break out of the middle of an iteration.
|
|
515
|
-
_.breakLoop:
|
|
515
|
+
_.breakLoop: :> throw breaker
|
|
516
516
|
|
|
517
517
|
|
|
518
518
|
# Generate a unique integer id (unique within the entire client session).
|
|
519
519
|
# Useful for temporary DOM ids.
|
|
520
520
|
idCounter: 0
|
|
521
|
-
_.uniqueId: (prefix)
|
|
521
|
+
_.uniqueId: (prefix) :>
|
|
522
522
|
(prefix or '') + idCounter++
|
|
523
523
|
|
|
524
524
|
|
|
@@ -534,7 +534,7 @@
|
|
|
534
534
|
# JavaScript templating a-la ERB, pilfered from John Resig's
|
|
535
535
|
# "Secrets of the JavaScript Ninja", page 83.
|
|
536
536
|
# Single-quotea fix from Rick Strahl's version.
|
|
537
|
-
_.template: (str, data)
|
|
537
|
+
_.template: (str, data) :>
|
|
538
538
|
c: _.templateSettings
|
|
539
539
|
fn: new Function 'obj',
|
|
540
540
|
'var p=[],print=function(){p.push.apply(p,arguments);};' +
|
|
@@ -566,38 +566,38 @@
|
|
|
566
566
|
# /*------------------------ Setup the OOP Wrapper: --------------------------*/
|
|
567
567
|
|
|
568
568
|
# Helper function to continue chaining intermediate results.
|
|
569
|
-
result: (obj, chain)
|
|
569
|
+
result: (obj, chain) :>
|
|
570
570
|
if chain then _(obj).chain() else obj
|
|
571
571
|
|
|
572
572
|
|
|
573
573
|
# Add all of the Underscore functions to the wrapper object.
|
|
574
|
-
_.each _.functions(_), (name)
|
|
574
|
+
_.each _.functions(_), (name) :>
|
|
575
575
|
method: _[name]
|
|
576
|
-
wrapper.prototype[name]:
|
|
576
|
+
wrapper.prototype[name]: :>
|
|
577
577
|
unshift.call(arguments, this._wrapped)
|
|
578
578
|
result(method.apply(_, arguments), this._chain)
|
|
579
579
|
|
|
580
580
|
|
|
581
581
|
# Add all mutator Array functions to the wrapper.
|
|
582
|
-
_.each ['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], (name)
|
|
582
|
+
_.each ['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], (name) :>
|
|
583
583
|
method: Array.prototype[name]
|
|
584
|
-
wrapper.prototype[name]:
|
|
584
|
+
wrapper.prototype[name]: :>
|
|
585
585
|
method.apply(this._wrapped, arguments)
|
|
586
586
|
result(this._wrapped, this._chain)
|
|
587
587
|
|
|
588
588
|
|
|
589
589
|
# Add all accessor Array functions to the wrapper.
|
|
590
|
-
_.each ['concat', 'join', 'slice'], (name)
|
|
590
|
+
_.each ['concat', 'join', 'slice'], (name) :>
|
|
591
591
|
method: Array.prototype[name]
|
|
592
|
-
wrapper.prototype[name]:
|
|
592
|
+
wrapper.prototype[name]: :>
|
|
593
593
|
result(method.apply(this._wrapped, arguments), this._chain)
|
|
594
594
|
|
|
595
595
|
|
|
596
596
|
# Start chaining a wrapped Underscore object.
|
|
597
|
-
wrapper::chain:
|
|
597
|
+
wrapper::chain: :>
|
|
598
598
|
this._chain: true
|
|
599
599
|
this
|
|
600
600
|
|
|
601
601
|
|
|
602
602
|
# Extracts the result from a wrapped and chained object.
|
|
603
|
-
wrapper::value:
|
|
603
|
+
wrapper::value: :> this._wrapped
|
data/lib/style-script.rb
CHANGED
|
@@ -10,7 +10,7 @@ require "style_script/parse_error"
|
|
|
10
10
|
# Namespace for all StyleScript internal classes.
|
|
11
11
|
module StyleScript
|
|
12
12
|
|
|
13
|
-
VERSION = '1.0.
|
|
13
|
+
VERSION = '1.0.2' # Keep in sync with the gemspec.
|
|
14
14
|
|
|
15
15
|
# Compile a script (String or IO) to JavaScript.
|
|
16
16
|
def self.compile(script, options={})
|
data/lib/style_script/grammar.y
CHANGED
|
@@ -37,7 +37,7 @@ prechigh
|
|
|
37
37
|
right THROW FOR NEW SUPER
|
|
38
38
|
left EXTENDS
|
|
39
39
|
right ASSIGN RETURN
|
|
40
|
-
right '
|
|
40
|
+
right ':>' '=>' UNLESS IF ELSE WHILE UNTIL
|
|
41
41
|
preclow
|
|
42
42
|
|
|
43
43
|
rule
|
|
@@ -207,7 +207,7 @@ rule
|
|
|
207
207
|
|
|
208
208
|
# The symbols to signify functions, and bound functions.
|
|
209
209
|
FuncGlyph:
|
|
210
|
-
'
|
|
210
|
+
':>' { result = :func }
|
|
211
211
|
| '=>' { result = :boundfunc }
|
|
212
212
|
;
|
|
213
213
|
|
data/lib/style_script/nodes.js
CHANGED
|
@@ -308,8 +308,8 @@
|
|
|
308
308
|
return klass;
|
|
309
309
|
};
|
|
310
310
|
// # Provide a quick implementation of a children method.
|
|
311
|
-
// children: (klass, attrs...)
|
|
312
|
-
// klass::children:
|
|
311
|
+
// children: (klass, attrs...) :>
|
|
312
|
+
// klass::children: :>
|
|
313
313
|
// nodes: this[attr] for attr in attrs
|
|
314
314
|
// compact flatten nodes
|
|
315
315
|
// Mark a node as a statement, or a statement only.
|
data/lib/style_script/parser.js
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
}
|
|
18
18
|
};
|
|
19
19
|
// Precedence ===========================================================
|
|
20
|
-
operators = [["left", '?'], ["right", 'NOT', '!', '!!', '~', '++', '--'], ["left", '*', '/', '%'], ["left", '+', '-'], ["left", '<<', '>>', '>>>'], ["left", '&', '|', '^'], ["left", '<=', '<', '>', '>='], ["right", '==', '!=', 'IS', 'ISNT'], ["left", '&&', '||', 'AND', 'OR'], ["right", '-=', '+=', '/=', '*=', '%='], ["right", 'DELETE', 'INSTANCEOF', 'TYPEOF'], ["left", '.'], ["right", 'INDENT'], ["left", 'OUTDENT'], ["right", 'WHEN', 'LEADING_WHEN', 'IN', 'OF', 'BY'], ["right", 'THROW', 'FOR', 'NEW', 'SUPER'], ["left", 'EXTENDS'], ["left", '||=', '&&=', '?='], ["right", 'ASSIGN', 'RETURN'], ["right", '
|
|
20
|
+
operators = [["left", '?'], ["right", 'NOT', '!', '!!', '~', '++', '--'], ["left", '*', '/', '%'], ["left", '+', '-'], ["left", '<<', '>>', '>>>'], ["left", '&', '|', '^'], ["left", '<=', '<', '>', '>='], ["right", '==', '!=', 'IS', 'ISNT'], ["left", '&&', '||', 'AND', 'OR'], ["right", '-=', '+=', '/=', '*=', '%='], ["right", 'DELETE', 'INSTANCEOF', 'TYPEOF'], ["left", '.'], ["right", 'INDENT'], ["left", 'OUTDENT'], ["right", 'WHEN', 'LEADING_WHEN', 'IN', 'OF', 'BY'], ["right", 'THROW', 'FOR', 'NEW', 'SUPER'], ["left", 'EXTENDS'], ["left", '||=', '&&=', '?='], ["right", 'ASSIGN', 'RETURN'], ["right", ':>', '=>', 'UNLESS', 'IF', 'ELSE', 'WHILE']];
|
|
21
21
|
// Grammar ==============================================================
|
|
22
22
|
grammar = {
|
|
23
23
|
// All parsing will end in this rule, being the trunk of the AST.
|
|
@@ -105,61 +105,61 @@
|
|
|
105
105
|
// # For Ruby's Operator precedence, see: [
|
|
106
106
|
// # https://www.cs.auckland.ac.nz/references/ruby/ProgrammingRuby/language.html
|
|
107
107
|
// Operation: [
|
|
108
|
-
// o "! Expression",
|
|
109
|
-
// o "!! Expression",
|
|
110
|
-
// o "- Expression",
|
|
111
|
-
// o "+ Expression",
|
|
112
|
-
// o "NOT Expression",
|
|
113
|
-
// o "~ Expression",
|
|
114
|
-
// o "-- Expression",
|
|
115
|
-
// o "++ Expression",
|
|
116
|
-
// o "DELETE Expression",
|
|
117
|
-
// o "TYPEOF Expression",
|
|
118
|
-
// o "Expression --",
|
|
119
|
-
// o "Expression ++",
|
|
108
|
+
// o "! Expression", :> new OpNode($1, $2)
|
|
109
|
+
// o "!! Expression", :> new OpNode($1, $2)
|
|
110
|
+
// o "- Expression", :> new OpNode($1, $2)
|
|
111
|
+
// o "+ Expression", :> new OpNode($1, $2)
|
|
112
|
+
// o "NOT Expression", :> new OpNode($1, $2)
|
|
113
|
+
// o "~ Expression", :> new OpNode($1, $2)
|
|
114
|
+
// o "-- Expression", :> new OpNode($1, $2)
|
|
115
|
+
// o "++ Expression", :> new OpNode($1, $2)
|
|
116
|
+
// o "DELETE Expression", :> new OpNode($1, $2)
|
|
117
|
+
// o "TYPEOF Expression", :> new OpNode($1, $2)
|
|
118
|
+
// o "Expression --", :> new OpNode($2, $1, null, true)
|
|
119
|
+
// o "Expression ++", :> new OpNode($2, $1, null, true)
|
|
120
120
|
//
|
|
121
|
-
// o "Expression * Expression",
|
|
122
|
-
// o "Expression / Expression",
|
|
123
|
-
// o "Expression % Expression",
|
|
121
|
+
// o "Expression * Expression", :> new OpNode($2, $1, $3)
|
|
122
|
+
// o "Expression / Expression", :> new OpNode($2, $1, $3)
|
|
123
|
+
// o "Expression % Expression", :> new OpNode($2, $1, $3)
|
|
124
124
|
//
|
|
125
|
-
// o "Expression + Expression",
|
|
126
|
-
// o "Expression - Expression",
|
|
125
|
+
// o "Expression + Expression", :> new OpNode($2, $1, $3)
|
|
126
|
+
// o "Expression - Expression", :> new OpNode($2, $1, $3)
|
|
127
127
|
//
|
|
128
|
-
// o "Expression << Expression",
|
|
129
|
-
// o "Expression >> Expression",
|
|
130
|
-
// o "Expression >>> Expression",
|
|
128
|
+
// o "Expression << Expression", :> new OpNode($2, $1, $3)
|
|
129
|
+
// o "Expression >> Expression", :> new OpNode($2, $1, $3)
|
|
130
|
+
// o "Expression >>> Expression", :> new OpNode($2, $1, $3)
|
|
131
131
|
//
|
|
132
|
-
// o "Expression & Expression",
|
|
133
|
-
// o "Expression | Expression",
|
|
134
|
-
// o "Expression ^ Expression",
|
|
132
|
+
// o "Expression & Expression", :> new OpNode($2, $1, $3)
|
|
133
|
+
// o "Expression | Expression", :> new OpNode($2, $1, $3)
|
|
134
|
+
// o "Expression ^ Expression", :> new OpNode($2, $1, $3)
|
|
135
135
|
//
|
|
136
|
-
// o "Expression <= Expression",
|
|
137
|
-
// o "Expression < Expression",
|
|
138
|
-
// o "Expression > Expression",
|
|
139
|
-
// o "Expression >= Expression",
|
|
136
|
+
// o "Expression <= Expression", :> new OpNode($2, $1, $3)
|
|
137
|
+
// o "Expression < Expression", :> new OpNode($2, $1, $3)
|
|
138
|
+
// o "Expression > Expression", :> new OpNode($2, $1, $3)
|
|
139
|
+
// o "Expression >= Expression", :> new OpNode($2, $1, $3)
|
|
140
140
|
//
|
|
141
|
-
// o "Expression == Expression",
|
|
142
|
-
// o "Expression != Expression",
|
|
143
|
-
// o "Expression IS Expression",
|
|
144
|
-
// o "Expression ISNT Expression",
|
|
141
|
+
// o "Expression == Expression", :> new OpNode($2, $1, $3)
|
|
142
|
+
// o "Expression != Expression", :> new OpNode($2, $1, $3)
|
|
143
|
+
// o "Expression IS Expression", :> new OpNode($2, $1, $3)
|
|
144
|
+
// o "Expression ISNT Expression", :> new OpNode($2, $1, $3)
|
|
145
145
|
//
|
|
146
|
-
// o "Expression && Expression",
|
|
147
|
-
// o "Expression || Expression",
|
|
148
|
-
// o "Expression AND Expression",
|
|
149
|
-
// o "Expression OR Expression",
|
|
150
|
-
// o "Expression ? Expression",
|
|
146
|
+
// o "Expression && Expression", :> new OpNode($2, $1, $3)
|
|
147
|
+
// o "Expression || Expression", :> new OpNode($2, $1, $3)
|
|
148
|
+
// o "Expression AND Expression", :> new OpNode($2, $1, $3)
|
|
149
|
+
// o "Expression OR Expression", :> new OpNode($2, $1, $3)
|
|
150
|
+
// o "Expression ? Expression", :> new OpNode($2, $1, $3)
|
|
151
151
|
//
|
|
152
|
-
// o "Expression -= Expression",
|
|
153
|
-
// o "Expression += Expression",
|
|
154
|
-
// o "Expression /= Expression",
|
|
155
|
-
// o "Expression *= Expression",
|
|
156
|
-
// o "Expression %= Expression",
|
|
157
|
-
// o "Expression ||= Expression",
|
|
158
|
-
// o "Expression &&= Expression",
|
|
159
|
-
// o "Expression ?= Expression",
|
|
152
|
+
// o "Expression -= Expression", :> new OpNode($2, $1, $3)
|
|
153
|
+
// o "Expression += Expression", :> new OpNode($2, $1, $3)
|
|
154
|
+
// o "Expression /= Expression", :> new OpNode($2, $1, $3)
|
|
155
|
+
// o "Expression *= Expression", :> new OpNode($2, $1, $3)
|
|
156
|
+
// o "Expression %= Expression", :> new OpNode($2, $1, $3)
|
|
157
|
+
// o "Expression ||= Expression", :> new OpNode($2, $1, $3)
|
|
158
|
+
// o "Expression &&= Expression", :> new OpNode($2, $1, $3)
|
|
159
|
+
// o "Expression ?= Expression", :> new OpNode($2, $1, $3)
|
|
160
160
|
//
|
|
161
|
-
// o "Expression INSTANCEOF Expression",
|
|
162
|
-
// o "Expression IN Expression",
|
|
161
|
+
// o "Expression INSTANCEOF Expression", :> new OpNode($2, $1, $3)
|
|
162
|
+
// o "Expression IN Expression", :> new OpNode($2, $1, $3)
|
|
163
163
|
// ]
|
|
164
164
|
// The existence operator.
|
|
165
165
|
Existence: [o("Expression ?", function() {
|
|
@@ -174,7 +174,7 @@
|
|
|
174
174
|
})
|
|
175
175
|
],
|
|
176
176
|
// The symbols to signify functions, and bound functions.
|
|
177
|
-
FuncGlyph: [o("
|
|
177
|
+
FuncGlyph: [o(":>", function() {
|
|
178
178
|
return 'func';
|
|
179
179
|
}), o("=>", function() {
|
|
180
180
|
return 'boundfunc';
|
data/lib/style_script/parser.rb
CHANGED
|
@@ -1284,7 +1284,7 @@ racc_token_table = {
|
|
|
1284
1284
|
"||=" => 92,
|
|
1285
1285
|
"&&=" => 93,
|
|
1286
1286
|
"?=" => 94,
|
|
1287
|
-
"
|
|
1287
|
+
":>" => 95,
|
|
1288
1288
|
"=>" => 96,
|
|
1289
1289
|
"\n" => 97,
|
|
1290
1290
|
";" => 98,
|
|
@@ -1413,7 +1413,7 @@ Racc_token_to_s_table = [
|
|
|
1413
1413
|
"\"||=\"",
|
|
1414
1414
|
"\"&&=\"",
|
|
1415
1415
|
"\"?=\"",
|
|
1416
|
-
"\"
|
|
1416
|
+
"\":>\"",
|
|
1417
1417
|
"\"=>\"",
|
|
1418
1418
|
"\"\\n\"",
|
|
1419
1419
|
"\";\"",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
// Tokens pairs that, in immediate succession, indicate an implicit call.
|
|
31
31
|
IMPLICIT_FUNC = ['IDENTIFIER', 'SUPER', ')', 'CALL_END', ']', 'INDEX_END'];
|
|
32
32
|
IMPLICIT_END = ['IF', 'UNLESS', 'FOR', 'WHILE', 'TERMINATOR', 'OUTDENT'];
|
|
33
|
-
IMPLICIT_CALL = ['IDENTIFIER', 'NUMBER', 'STRING', 'JS', 'REGEX', 'NEW', 'PARAM_START', 'TRY', 'DELETE', 'TYPEOF', 'SWITCH', 'ARGUMENTS', 'TRUE', 'FALSE', 'YES', 'NO', 'ON', 'OFF', '!', '!!', 'NOT', '
|
|
33
|
+
IMPLICIT_CALL = ['IDENTIFIER', 'NUMBER', 'STRING', 'JS', 'REGEX', 'NEW', 'PARAM_START', 'TRY', 'DELETE', 'TYPEOF', 'SWITCH', 'ARGUMENTS', 'TRUE', 'FALSE', 'YES', 'NO', 'ON', 'OFF', '!', '!!', 'NOT', ':>', '=>', '[', '(', '{'];
|
|
34
34
|
// The inverse mappings of token pairs we're trying to fix up.
|
|
35
35
|
INVERSES = {
|
|
36
36
|
};
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
}
|
|
43
43
|
// Single-line flavors of block expressions that have unclosed endings.
|
|
44
44
|
// The grammar can't disambiguate them, so we insert the implicit indentation.
|
|
45
|
-
SINGLE_LINERS = ['ELSE', "
|
|
45
|
+
SINGLE_LINERS = ['ELSE', ":>", "=>", 'TRY', 'FINALLY', 'THEN'];
|
|
46
46
|
SINGLE_CLOSERS = ['TERMINATOR', 'CATCH', 'FINALLY', 'ELSE', 'OUTDENT', 'LEADING_WHEN', 'PARAM_START'];
|
|
47
47
|
// Rewrite the token stream in multiple passes, one logical filter at
|
|
48
48
|
// a time. This could certainly be changed into a single pass through the
|
|
@@ -311,7 +311,7 @@
|
|
|
311
311
|
}
|
|
312
312
|
};
|
|
313
313
|
// We'd like to support syntax like this:
|
|
314
|
-
// el.click((event)
|
|
314
|
+
// el.click((event) :>
|
|
315
315
|
// el.hide())
|
|
316
316
|
// In order to accomplish this, move outdents that follow closing parens
|
|
317
317
|
// inwards, safely. The steps to accomplish this are:
|
|
@@ -24,7 +24,7 @@ module StyleScript
|
|
|
24
24
|
IMPLICIT_CALL = [:IDENTIFIER, :NUMBER, :STRING, :JS, :REGEX, :NEW, :PARAM_START,
|
|
25
25
|
:TRY, :DELETE, :TYPEOF, :SWITCH,
|
|
26
26
|
:TRUE, :FALSE, :YES, :NO, :ON, :OFF, '!', '!!', :NOT,
|
|
27
|
-
'@', '
|
|
27
|
+
'@', ':>', '=>', '[', '(', '{']
|
|
28
28
|
|
|
29
29
|
# The inverse mappings of token pairs we're trying to fix up.
|
|
30
30
|
INVERSES = BALANCED_PAIRS.inject({}) do |memo, pair|
|
|
@@ -35,7 +35,7 @@ module StyleScript
|
|
|
35
35
|
|
|
36
36
|
# Single-line flavors of block expressions that have unclosed endings.
|
|
37
37
|
# The grammar can't disambiguate them, so we insert the implicit indentation.
|
|
38
|
-
SINGLE_LINERS = [:ELSE, "
|
|
38
|
+
SINGLE_LINERS = [:ELSE, ":>", "=>", :TRY, :FINALLY, :THEN]
|
|
39
39
|
SINGLE_CLOSERS = ["\n", :CATCH, :FINALLY, :ELSE, :OUTDENT, :LEADING_WHEN, :PARAM_START]
|
|
40
40
|
|
|
41
41
|
# Rewrite the token stream in multiple passes, one logical filter at
|
|
@@ -228,7 +228,7 @@ module StyleScript
|
|
|
228
228
|
end
|
|
229
229
|
|
|
230
230
|
# We'd like to support syntax like this:
|
|
231
|
-
# el.click((event)
|
|
231
|
+
# el.click((event) :>
|
|
232
232
|
# el.hide())
|
|
233
233
|
# In order to accomplish this, move outdents that follow closing parens
|
|
234
234
|
# inwards, safely. The steps to accomplish this are:
|
data/lib/style_script/runner.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
(function(){
|
|
2
2
|
var style, paths;
|
|
3
3
|
// Quickie script to compile and run all the files given as arguments.
|
|
4
|
-
|
|
4
|
+
require('sys');
|
|
5
5
|
style = require('./style-script');
|
|
6
6
|
paths = process.ARGV;
|
|
7
7
|
paths = paths.slice(2, paths.length);
|
|
8
8
|
paths.length ? style.compile_files(paths, function(js) {
|
|
9
9
|
return eval(js);
|
|
10
10
|
}) : require('./repl');
|
|
11
|
-
})();
|
|
11
|
+
})();
|
data/package.json
CHANGED
data/style-script.gemspec
CHANGED
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: style-script
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
hash:
|
|
4
|
+
hash: 19
|
|
5
5
|
prerelease:
|
|
6
6
|
segments:
|
|
7
7
|
- 1
|
|
8
8
|
- 0
|
|
9
|
-
-
|
|
10
|
-
version: 1.0.
|
|
9
|
+
- 2
|
|
10
|
+
version: 1.0.2
|
|
11
11
|
platform: ruby
|
|
12
12
|
authors:
|
|
13
13
|
- Danilo Lekovic
|