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.
- data/LICENSE +22 -0
- data/bin/style +5 -0
- data/examples/blocks.style +57 -0
- data/examples/code.style +173 -0
- data/examples/hello.style +1 -0
- data/examples/poignant.style +186 -0
- data/examples/potion.style +205 -0
- data/examples/underscore.style +603 -0
- data/lib/style-script.rb +21 -0
- data/lib/style_script/command_line.rb +235 -0
- data/lib/style_script/grammar.y +491 -0
- data/lib/style_script/lexer.js +363 -0
- data/lib/style_script/lexer.rb +272 -0
- data/lib/style_script/nodes.js +756 -0
- data/lib/style_script/nodes.rb +1079 -0
- data/lib/style_script/parse_error.rb +29 -0
- data/lib/style_script/parser.js +544 -0
- data/lib/style_script/parser.rb +2716 -0
- data/lib/style_script/repl.js +33 -0
- data/lib/style_script/rewriter.js +377 -0
- data/lib/style_script/rewriter.rb +289 -0
- data/lib/style_script/runner.js +11 -0
- data/lib/style_script/scope.js +129 -0
- data/lib/style_script/scope.rb +95 -0
- data/lib/style_script/std/style-script.js +96 -0
- data/lib/style_script/style-script.js +50 -0
- data/lib/style_script/value.rb +64 -0
- data/package.json +8 -0
- data/style-script.gemspec +21 -0
- metadata +93 -0
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) Danilo Lekovic, Jeremy Ashkenas
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person
|
4
|
+
obtaining a copy of this software and associated documentation
|
5
|
+
files (the "Software"), to deal in the Software without
|
6
|
+
restriction, including without limitation the rights to use,
|
7
|
+
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
+
copies of the Software, and to permit persons to whom the
|
9
|
+
Software is furnished to do so, subject to the following
|
10
|
+
conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be
|
13
|
+
included in all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
17
|
+
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
19
|
+
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
20
|
+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
21
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
22
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
data/bin/style
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
# After wycats' http://yehudakatz.com/2010/02/07/the-building-blocks-of-ruby/
|
2
|
+
|
3
|
+
# Sinatra.
|
4
|
+
get '/hello', ->
|
5
|
+
'Hello World'
|
6
|
+
|
7
|
+
|
8
|
+
# Append.
|
9
|
+
append: (location, data) ->
|
10
|
+
path: new Pathname location
|
11
|
+
throw "Location does not exist" unless path.exists()
|
12
|
+
|
13
|
+
File.open path, 'a', (file) ->
|
14
|
+
file.puts YAML.dump data
|
15
|
+
|
16
|
+
data
|
17
|
+
|
18
|
+
|
19
|
+
# Rubinius' File.open implementation.
|
20
|
+
File.open: (path, mode, block) ->
|
21
|
+
io: new File path, mode
|
22
|
+
|
23
|
+
return io unless block
|
24
|
+
|
25
|
+
try
|
26
|
+
block io
|
27
|
+
finally
|
28
|
+
try
|
29
|
+
io.close() unless io.closed()
|
30
|
+
catch error
|
31
|
+
# nothing, just swallow them.
|
32
|
+
|
33
|
+
|
34
|
+
# Write.
|
35
|
+
write: (location, data) ->
|
36
|
+
path = new Pathname location
|
37
|
+
raise "Location does not exist" unless path.exists()
|
38
|
+
|
39
|
+
File.open path, 'w', (file) ->
|
40
|
+
return false if Digest.MD5.hexdigest(file.read()) is data.hash()
|
41
|
+
file.puts YAML.dump data
|
42
|
+
true
|
43
|
+
|
44
|
+
|
45
|
+
# Rails' respond_to.
|
46
|
+
index: ->
|
47
|
+
people: Person.find 'all'
|
48
|
+
|
49
|
+
respond_to (format) ->
|
50
|
+
format.html()
|
51
|
+
format.xml -> render { xml: people.xml() }
|
52
|
+
|
53
|
+
|
54
|
+
# Synchronization.
|
55
|
+
synchronize: (block) ->
|
56
|
+
lock()
|
57
|
+
try block() finally unlock()
|
data/examples/code.style
ADDED
@@ -0,0 +1,173 @@
|
|
1
|
+
# Functions:
|
2
|
+
square: (x) -> x * x
|
3
|
+
|
4
|
+
sum: (x, y) -> x + y
|
5
|
+
|
6
|
+
odd: (x) -> x % 2 isnt 0
|
7
|
+
|
8
|
+
even: (x) -> x % 2 is 0
|
9
|
+
|
10
|
+
run_loop: ->
|
11
|
+
fire_events((e) -> e.stopPropagation())
|
12
|
+
listen()
|
13
|
+
wait()
|
14
|
+
|
15
|
+
# Objects:
|
16
|
+
dense_object_literal: {one: 1, two: 2, three: 3}
|
17
|
+
|
18
|
+
spaced_out_multiline_object: {
|
19
|
+
pi: 3.14159
|
20
|
+
list: [1, 2, 3, 4]
|
21
|
+
regex: /match[ing](every|thing|\/)/gi
|
22
|
+
three: new Idea()
|
23
|
+
|
24
|
+
inner_obj: {
|
25
|
+
freedom: -> _.freedom()
|
26
|
+
}
|
27
|
+
}
|
28
|
+
|
29
|
+
# Arrays:
|
30
|
+
stooges: [{moe: 45}, {curly: 43}, {larry: 46}]
|
31
|
+
|
32
|
+
exponents: [(x) -> x, (x) -> x * x, (x) -> x * x * x]
|
33
|
+
|
34
|
+
empty: []
|
35
|
+
|
36
|
+
multiline: [
|
37
|
+
'line one'
|
38
|
+
'line two'
|
39
|
+
]
|
40
|
+
|
41
|
+
# Conditionals and ternaries.
|
42
|
+
if submarine.shields_up
|
43
|
+
full_speed_ahead()
|
44
|
+
fire_torpedos()
|
45
|
+
else if submarine.sinking
|
46
|
+
abandon_ship()
|
47
|
+
else
|
48
|
+
run_away()
|
49
|
+
|
50
|
+
eldest: if 25 > 21 then liz else marge
|
51
|
+
|
52
|
+
decoration: medal_of_honor if war_hero
|
53
|
+
|
54
|
+
go_to_sleep() unless style
|
55
|
+
|
56
|
+
# Returning early:
|
57
|
+
race: ->
|
58
|
+
run()
|
59
|
+
walk()
|
60
|
+
crawl()
|
61
|
+
if tired then return sleep()
|
62
|
+
race()
|
63
|
+
|
64
|
+
# Conditional assignment:
|
65
|
+
good ||= evil
|
66
|
+
wine &&= cheese
|
67
|
+
|
68
|
+
# Nested property access and calls.
|
69
|
+
((moon.turn(360))).shapes[3].move({x: 45, y: 30}).position['top'].offset('x')
|
70
|
+
|
71
|
+
a: b: c: 5
|
72
|
+
|
73
|
+
# Embedded JavaScript.
|
74
|
+
callback(
|
75
|
+
`function(e) { e.stop(); }`
|
76
|
+
)
|
77
|
+
|
78
|
+
# Try/Catch/Finally/Throw.
|
79
|
+
try
|
80
|
+
all_hell_breaks_loose()
|
81
|
+
dogs_and_cats_living_together()
|
82
|
+
throw "up"
|
83
|
+
catch error
|
84
|
+
print(error)
|
85
|
+
finally
|
86
|
+
clean_up()
|
87
|
+
|
88
|
+
try all_hell_breaks_loose() catch error then print(error) finally clean_up()
|
89
|
+
|
90
|
+
# While loops, break and continue.
|
91
|
+
while demand > supply
|
92
|
+
sell()
|
93
|
+
restock()
|
94
|
+
|
95
|
+
while supply > demand then buy()
|
96
|
+
|
97
|
+
while true
|
98
|
+
break if broken
|
99
|
+
continue if continuing
|
100
|
+
|
101
|
+
# Unary operators.
|
102
|
+
!!true
|
103
|
+
|
104
|
+
# Lexical scoping.
|
105
|
+
v_1: 5
|
106
|
+
change_a_and_set_b: ->
|
107
|
+
v_1: 10
|
108
|
+
v_2: 15
|
109
|
+
v_2: 20
|
110
|
+
|
111
|
+
# Array comprehensions.
|
112
|
+
supper: food.capitalize() for food in ['toast', 'cheese', 'wine']
|
113
|
+
|
114
|
+
drink(bottle) for bottle, i in ['soda', 'wine', 'lemonade'] when even(i)
|
115
|
+
|
116
|
+
# Switch statements ("else" serves as a default).
|
117
|
+
activity: switch day
|
118
|
+
when "Tuesday" then eat_breakfast()
|
119
|
+
when "Sunday" then go_to_church()
|
120
|
+
when "Saturday" then go_to_the_park()
|
121
|
+
when "Wednesday"
|
122
|
+
if day is bingo_day
|
123
|
+
go_to_bingo()
|
124
|
+
else
|
125
|
+
eat_breakfast()
|
126
|
+
go_to_work()
|
127
|
+
eat_dinner()
|
128
|
+
else go_to_work()
|
129
|
+
|
130
|
+
# Semicolons can optionally be used instead of newlines.
|
131
|
+
wednesday: -> eat_breakfast(); go_to_work(); eat_dinner()
|
132
|
+
|
133
|
+
# Array slice literals.
|
134
|
+
zero_to_nine: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
135
|
+
three_to_six: zero_to_nine[3..6]
|
136
|
+
|
137
|
+
# Multiline strings with inner quotes.
|
138
|
+
story: "Lorem ipsum dolor \"sit\" amet, consectetuer adipiscing elit,
|
139
|
+
sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna
|
140
|
+
aliquam erat volutpat. Ut wisi enim ad."
|
141
|
+
|
142
|
+
# Inheritance and calling super.
|
143
|
+
Animal: ->
|
144
|
+
Animal::move: (meters) ->
|
145
|
+
alert(this.name + " moved " + meters + "m.")
|
146
|
+
|
147
|
+
Snake: (name) -> this.name: name
|
148
|
+
Snake extends Animal
|
149
|
+
Snake::move: ->
|
150
|
+
alert('Slithering...')
|
151
|
+
super(5)
|
152
|
+
|
153
|
+
Horse: (name) -> this.name: name
|
154
|
+
Horse extends Animal
|
155
|
+
Horse::move: ->
|
156
|
+
alert('Galloping...')
|
157
|
+
super(45)
|
158
|
+
|
159
|
+
sam: new Snake("Sammy the Snake")
|
160
|
+
tom: new Horse("Tommy the Horse")
|
161
|
+
|
162
|
+
sam.move()
|
163
|
+
tom.move()
|
164
|
+
|
165
|
+
# Numbers.
|
166
|
+
a_googol: 1e100
|
167
|
+
hex: 0xff0000
|
168
|
+
negative: -1.0
|
169
|
+
infinity: Infinity
|
170
|
+
nan: NaN
|
171
|
+
|
172
|
+
# Deleting.
|
173
|
+
delete secret.identity
|
@@ -0,0 +1 @@
|
|
1
|
+
console.log "Hey"
|
@@ -0,0 +1,186 @@
|
|
1
|
+
# Examples from the Poignant Guide.
|
2
|
+
|
3
|
+
# ['toast', 'cheese', 'wine'].each { |food| print food.capitalize }
|
4
|
+
|
5
|
+
['toast', 'wine', 'cheese'].each (food) -> print(food.capitalize())
|
6
|
+
|
7
|
+
|
8
|
+
|
9
|
+
# class LotteryTicket
|
10
|
+
# def picks; @picks; end
|
11
|
+
# def picks=(var); @picks = var; end
|
12
|
+
# def purchased; @purchased; end
|
13
|
+
# def purchased=(var); @purchased = var; end
|
14
|
+
# end
|
15
|
+
|
16
|
+
LotteryTicket: {
|
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
|
+
}
|
22
|
+
|
23
|
+
|
24
|
+
|
25
|
+
# class << LotteryDraw
|
26
|
+
# def play
|
27
|
+
# result = LotteryTicket.new_random
|
28
|
+
# winners = {}
|
29
|
+
# @@tickets.each do |buyer, ticket_list|
|
30
|
+
# ticket_list.each do |ticket|
|
31
|
+
# score = ticket.score( result )
|
32
|
+
# next if score.zero?
|
33
|
+
# winners[buyer] ||= []
|
34
|
+
# winners[buyer] << [ ticket, score ]
|
35
|
+
# end
|
36
|
+
# end
|
37
|
+
# @@tickets.clear
|
38
|
+
# winners
|
39
|
+
# end
|
40
|
+
# end
|
41
|
+
|
42
|
+
LotteryDraw: {
|
43
|
+
play: ->
|
44
|
+
result: LotteryTicket.new_random()
|
45
|
+
winners: {}
|
46
|
+
this.tickets.each (buyer, ticket_list) ->
|
47
|
+
ticket_list.each (ticket) ->
|
48
|
+
score: ticket.score(result)
|
49
|
+
return if score is 0
|
50
|
+
winners[buyer] ||= []
|
51
|
+
winners[buyer].push([ticket, score])
|
52
|
+
this.tickets: {}
|
53
|
+
winners
|
54
|
+
}
|
55
|
+
|
56
|
+
|
57
|
+
|
58
|
+
# module WishScanner
|
59
|
+
# def scan_for_a_wish
|
60
|
+
# wish = self.read.detect do |thought|
|
61
|
+
# thought.index( 'wish: ' ) == 0
|
62
|
+
# end
|
63
|
+
# wish.gsub( 'wish: ', '' )
|
64
|
+
# end
|
65
|
+
# end
|
66
|
+
|
67
|
+
WishScanner: {
|
68
|
+
scan_for_a_wish: ->
|
69
|
+
wish: this.read().detect((thought) -> thought.index('wish: ') is 0)
|
70
|
+
wish.replace('wish: ', '')
|
71
|
+
}
|
72
|
+
|
73
|
+
|
74
|
+
|
75
|
+
# class Creature
|
76
|
+
#
|
77
|
+
# # This method applies a hit taken during a fight.
|
78
|
+
# def hit( damage )
|
79
|
+
# p_up = rand( charisma )
|
80
|
+
# if p_up % 9 == 7
|
81
|
+
# @life += p_up / 4
|
82
|
+
# puts "[#{ self.class } magick powers up #{ p_up }!]"
|
83
|
+
# end
|
84
|
+
# @life -= damage
|
85
|
+
# puts "[#{ self.class } has died.]" if @life <= 0
|
86
|
+
# end
|
87
|
+
#
|
88
|
+
# # This method takes one turn in a fight.
|
89
|
+
# def fight( enemy, weapon )
|
90
|
+
# if life <= 0
|
91
|
+
# puts "[#{ self.class } is too dead to fight!]"
|
92
|
+
# return
|
93
|
+
# end
|
94
|
+
#
|
95
|
+
# # Attack the opponent
|
96
|
+
# your_hit = rand( strength + weapon )
|
97
|
+
# puts "[You hit with #{ your_hit } points of damage!]"
|
98
|
+
# enemy.hit( your_hit )
|
99
|
+
#
|
100
|
+
# # Retaliation
|
101
|
+
# p enemy
|
102
|
+
# if enemy.life > 0
|
103
|
+
# enemy_hit = rand( enemy.strength + enemy.weapon )
|
104
|
+
# puts "[Your enemy hit with #{ enemy_hit } points of damage!]"
|
105
|
+
# self.hit( enemy_hit )
|
106
|
+
# end
|
107
|
+
# end
|
108
|
+
#
|
109
|
+
# end
|
110
|
+
|
111
|
+
Creature : {
|
112
|
+
|
113
|
+
# This method applies a hit taken during a fight.
|
114
|
+
hit: (damage) ->
|
115
|
+
p_up: Math.rand(this.charisma)
|
116
|
+
if p_up % 9 is 7
|
117
|
+
this.life += p_up / 4
|
118
|
+
puts("[" + this.name + " magick powers up " + p_up + "!]")
|
119
|
+
this.life -= damage
|
120
|
+
if this.life <= 0 then puts("[" + this.name + " has died.]")
|
121
|
+
|
122
|
+
# This method takes one turn in a fight.
|
123
|
+
fight: (enemy, weapon) ->
|
124
|
+
if this.life <= 0 then return puts("[" + this.name + "is too dead to fight!]")
|
125
|
+
|
126
|
+
# Attack the opponent.
|
127
|
+
your_hit: Math.rand(this.strength + weapon)
|
128
|
+
puts("[You hit with " + your_hit + "points of damage!]")
|
129
|
+
enemy.hit(your_hit)
|
130
|
+
|
131
|
+
# Retaliation.
|
132
|
+
puts(enemy)
|
133
|
+
if enemy.life > 0
|
134
|
+
enemy_hit: Math.rand(enemy.strength + enemy.weapon)
|
135
|
+
puts("[Your enemy hit with " + enemy_hit + "points of damage!]")
|
136
|
+
this.hit(enemy_hit)
|
137
|
+
|
138
|
+
}
|
139
|
+
|
140
|
+
|
141
|
+
|
142
|
+
# # Get evil idea and swap in code words
|
143
|
+
# print "Enter your new idea: "
|
144
|
+
# idea = gets
|
145
|
+
# code_words.each do |real, code|
|
146
|
+
# idea.gsub!( real, code )
|
147
|
+
# end
|
148
|
+
#
|
149
|
+
# # Save the jibberish to a new file
|
150
|
+
# print "File encoded. Please enter a name for this idea: "
|
151
|
+
# idea_name = gets.strip
|
152
|
+
# File::open( "idea-" + idea_name + ".txt", "w" ) do |f|
|
153
|
+
# f << idea
|
154
|
+
# end
|
155
|
+
|
156
|
+
# Get evil idea and swap in code words
|
157
|
+
print("Enter your new idea: ")
|
158
|
+
idea: gets()
|
159
|
+
code_words.each((real, code) -> idea.replace(real, code))
|
160
|
+
|
161
|
+
# Save the jibberish to a new file
|
162
|
+
print("File encoded. Please enter a name for this idea: ")
|
163
|
+
idea_name: gets().strip()
|
164
|
+
File.open("idea-" + idea_name + '.txt', 'w', (file) -> file.write(idea))
|
165
|
+
|
166
|
+
|
167
|
+
|
168
|
+
# def wipe_mutterings_from( sentence )
|
169
|
+
# unless sentence.respond_to? :include?
|
170
|
+
# raise ArgumentError,
|
171
|
+
# "cannot wipe mutterings from a #{ sentence.class }"
|
172
|
+
# end
|
173
|
+
# while sentence.include? '('
|
174
|
+
# open = sentence.index( '(' )
|
175
|
+
# close = sentence.index( ')', open )
|
176
|
+
# sentence[open..close] = '' if close
|
177
|
+
# end
|
178
|
+
# end
|
179
|
+
|
180
|
+
wipe_mutterings_from: (sentence) ->
|
181
|
+
throw new Error("cannot wipe mutterings") unless sentence.indexOf
|
182
|
+
while sentence.indexOf('(') >= 0
|
183
|
+
open: sentence.indexOf('(') - 1
|
184
|
+
close: sentence.indexOf(')') + 1
|
185
|
+
sentence: sentence[0..open] + sentence[close..sentence.length]
|
186
|
+
sentence
|