shift-lang 0.1.1

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.
Files changed (42) hide show
  1. data/.gitignore +17 -0
  2. data/Gemfile +4 -0
  3. data/LICENSE +22 -0
  4. data/README.md +29 -0
  5. data/Rakefile +2 -0
  6. data/bin/sft +5 -0
  7. data/bin/shift +5 -0
  8. data/lib/app_engine_templates/app.yaml +13 -0
  9. data/lib/app_engine_templates/pystache/__init__.py +8 -0
  10. data/lib/app_engine_templates/pystache/__init__.pyc +0 -0
  11. data/lib/app_engine_templates/pystache/loader.py +47 -0
  12. data/lib/app_engine_templates/pystache/loader.pyc +0 -0
  13. data/lib/app_engine_templates/pystache/template.py +177 -0
  14. data/lib/app_engine_templates/pystache/template.pyc +0 -0
  15. data/lib/app_engine_templates/pystache/view.py +94 -0
  16. data/lib/app_engine_templates/pystache/view.pyc +0 -0
  17. data/lib/heroku_templates/Gemfile +6 -0
  18. data/lib/heroku_templates/Procfile +1 -0
  19. data/lib/shift-lang/builder/db_model.rb +20 -0
  20. data/lib/shift-lang/builder/url_handler.rb +17 -0
  21. data/lib/shift-lang/builder.rb +103 -0
  22. data/lib/shift-lang/generator/javascript_generator.rb +410 -0
  23. data/lib/shift-lang/generator/javascript_templates.rb +37 -0
  24. data/lib/shift-lang/generator/python_generator.rb +330 -0
  25. data/lib/shift-lang/generator/python_templates.rb +44 -0
  26. data/lib/shift-lang/generator/ruby_generator.rb +334 -0
  27. data/lib/shift-lang/generator/ruby_templates.rb +50 -0
  28. data/lib/shift-lang/generator.rb +41 -0
  29. data/lib/shift-lang/parser/control_statement_parser.rb +17 -0
  30. data/lib/shift-lang/parser/db_query_parser.rb +20 -0
  31. data/lib/shift-lang/parser/keyword_parser.rb +52 -0
  32. data/lib/shift-lang/parser/operator_parser.rb +35 -0
  33. data/lib/shift-lang/parser/routing_expression_parser.rb +33 -0
  34. data/lib/shift-lang/parser/simple_expression_parser.rb +87 -0
  35. data/lib/shift-lang/parser/token_parser.rb +69 -0
  36. data/lib/shift-lang/parser/value_returning_expression_parser.rb +18 -0
  37. data/lib/shift-lang/parser/void_statement_parser.rb +12 -0
  38. data/lib/shift-lang/parser.rb +120 -0
  39. data/lib/shift-lang/version.rb +3 -0
  40. data/lib/shift-lang.rb +224 -0
  41. data/shift-lang.gemspec +19 -0
  42. metadata +106 -0
@@ -0,0 +1,410 @@
1
+ require 'erb'
2
+
3
+ require_relative '../builder'
4
+ require_relative './javascript_templates'
5
+
6
+ module Shift
7
+ module Generator
8
+
9
+ class JavaScriptGenerator
10
+ attr_accessor :blocks, :functions, :builder, :url_variables, :has_models, :defined_hashes
11
+
12
+ def initialize()
13
+ @blocks = []
14
+ @defined_hashes = []
15
+ @functions = []
16
+ @has_models = false
17
+ @builder = Shift::ShiftBuilder.new
18
+ end
19
+
20
+ def get_data(builder)
21
+ @builder = builder
22
+ end
23
+
24
+ def get_data_from_file(file_name)
25
+ @builder.get_data_from_file file_name
26
+ end
27
+
28
+ def get_import_statements()
29
+ Shift::Generator::JavaScriptTemplates::IMPORT_JQNODE_STATEMENT +
30
+ Shift::Generator::JavaScriptTemplates::IMPORT_UTIL_STATEMENT +
31
+ Shift::Generator::JavaScriptTemplates::IMPORT_MU_STATEMENT +
32
+ (@has_models ? Shift::Generator::JavaScriptTemplates::IMPORT_DB_STATEMENT : "") +
33
+ Shift::Generator::JavaScriptTemplates::UTILITY_FUNCTIONS + "\n"
34
+ end
35
+
36
+ def get_model_data()
37
+ result = ""
38
+
39
+ model_name_template = ERB.new(Shift::Generator::JavaScriptTemplates::MODEL_NAME_TEMPLATE)
40
+
41
+ @builder.models.each do | model |
42
+ model_name = model.name
43
+ result += model_name_template.result(binding) + "\n"
44
+
45
+ first = true
46
+
47
+ # TODO: Test if comma syntax is valid
48
+
49
+ model.attributes.each do | attribute |
50
+ if (attribute[:type] == "string")
51
+ if (first == true)
52
+ first = false
53
+ else
54
+ result += ","
55
+ end
56
+ result += ("\t" + attribute[:name] + " : " + "String" + "\n")
57
+ else
58
+ if (attribute[:type] == "integer")
59
+ if (first == true)
60
+ first = false
61
+ else
62
+ result += ","
63
+ end
64
+ result += ("\t" + attribute[:name] + " : " + "Number" + "\n")
65
+ end
66
+ end
67
+ end
68
+
69
+ result += "});\n\n"
70
+ end
71
+
72
+ result
73
+ end
74
+
75
+ def url_transform(url)
76
+ if(url.is_a?(Array))
77
+ result_url = ""
78
+
79
+ url.each do | token |
80
+ case token.keys[0]
81
+ when :url_token
82
+ result_url += "/" + token[:url_token].to_s
83
+ when :url_variable
84
+ result_url += "/:" + token[:url_variable].to_s
85
+ end
86
+ end
87
+ result_url
88
+ else
89
+ url.to_s
90
+ end
91
+ end
92
+
93
+ def expression_transform(statement, num_tabs)
94
+ tabs = ""
95
+ num_tabs.times { tabs += "\t" }
96
+ key = statement.keys[0]
97
+ case key
98
+ when :assignment_statement
99
+ extra = ""
100
+ if(statement[:assignment_statement][:left].keys[0] == :hash_value)
101
+ val = statement[:assignment_statement][:left][:hash_value].to_s
102
+ hash_var = val[0..(val.index('[') - 1)]
103
+ if !@defined_hashes.include?(hash_var)
104
+ @defined_hashes.push hash_var
105
+ extra += (tabs + "if (typeof " + hash_var + " == 'undefined')\n")
106
+ extra += (tabs + "\t" + hash_var + " = {}\n")
107
+ end
108
+ end
109
+
110
+ left = apply_transforms(statement[:assignment_statement][:left], 0)
111
+ right = apply_transforms(statement[:assignment_statement][:right], 0)
112
+
113
+ if(statement[:assignment_statement][:left].keys[0] == :object_value)
114
+ value_name = statement[:assignment_statement][:left][:object_value].to_s
115
+ value_name = value_name[(value_name.index('.') + 1)..(value_name.length - 1)]
116
+ end
117
+
118
+ if(statement[:assignment_statement][:right].is_a?(Hash) && statement[:assignment_statement][:right].keys[0] == :query)
119
+ case statement[:assignment_statement][:right][:query][:operation]
120
+ when "all"
121
+ @functions.push (tabs + "});")
122
+ tabs + right.to_s + left.to_s + ") {"
123
+ when "new"
124
+ tabs + "var " + left.to_s + " = " + right.to_s
125
+ when "find"
126
+ @functions.push (tabs + "});")
127
+ tabs + right.to_s + left.to_s + ") {"
128
+ when "find_by_id"
129
+ @functions.push (tabs + "});")
130
+ tabs + right.to_s + left.to_s + ") {"
131
+ end
132
+ else
133
+ extra + tabs + left.to_s + " = " + right.to_s + ";"
134
+ end
135
+ else
136
+ ""
137
+ end
138
+ end
139
+
140
+ def token_transform(statement, num_tabs)
141
+ tabs = ""
142
+ num_tabs.times { tabs += "\t" }
143
+
144
+ key = statement.keys[0]
145
+
146
+ case key
147
+ when :identifier
148
+ result = statement[:identifier].to_s
149
+ @url_variables.include?(result) ? "urlData['" + result + "']" : result
150
+ when :object_value
151
+ if (statement[:object_value].to_s.split(".")[1] == "save")
152
+ tabs + statement[:object_value].to_s.split(".")[0] + ".save();" + "\n"
153
+ else
154
+ tabs + statement[:object_value].to_s
155
+ end
156
+ when :hash_value
157
+ statement[:hash_value].to_s
158
+ when :string
159
+ statement[:string].to_s
160
+ else
161
+ ""
162
+ end
163
+
164
+ end
165
+
166
+ def write_function_transform(statement, num_tabs)
167
+ tabs = ""
168
+ num_tabs.times { tabs += "\t" }
169
+
170
+ write_data_template = ERB.new(Shift::Generator::JavaScriptTemplates::WRITE_DATA_TEMPLATE)
171
+
172
+ write_data = apply_transforms(statement[:write_statement][:write_statement_param], 0)
173
+
174
+ tabs + write_data_template.result(binding)
175
+ end
176
+
177
+ def write_file_function_transform(statement, num_tabs)
178
+ tabs = ""
179
+ num_tabs.times { tabs += "\t" }
180
+
181
+ write_file_template = ERB.new(Shift::Generator::JavaScriptTemplates::WRITE_FILE_TEMPLATE)
182
+
183
+ if(statement[:write_file_statement].is_a?(Array))
184
+ file_name = apply_transforms(statement[:write_file_statement][0][:file_name], 0)
185
+ template_values = apply_transforms(statement[:write_file_statement][1][:template_values], 0)
186
+ args = file_name + ', ' + template_values + ", response"
187
+ else
188
+ file_name = apply_transforms(statement[:write_file_statement][:file_name], 0)
189
+ args = file_name + ', false'
190
+ end
191
+
192
+ tabs + write_file_template.result(binding)
193
+ end
194
+
195
+
196
+ def query_transform(statement, num_tabs)
197
+ tabs = ""
198
+ num_tabs.times { tabs += "\t" }
199
+ statement = statement[:query]
200
+ case statement[:operation].to_s
201
+ when "all"
202
+ statement[:model_name].to_s + ".all(function (err, "
203
+ when "new"
204
+ (statement[:model_name].to_s + "()")
205
+ when "find"
206
+ result = statement[:model_name].to_s + ".all({ where : "
207
+ condition = statement[:condition]
208
+
209
+ condition_attribute = apply_transforms(condition[:value], 0)
210
+
211
+ condition_expression = ""
212
+
213
+ case statement[:condition][:operator].to_s.gsub!(" ", "")
214
+ when "<="
215
+ condition_expression = "{lte : " + condition_attribute + "}"
216
+ else
217
+ puts statement[:operator].to_s.gsub!(" ", "")
218
+ end
219
+
220
+ result += "{ " + condition[:attribute] + " : " + condition_expression + " }"
221
+ result += " }, function (err, "
222
+ when "find_by_id"
223
+ result = statement[:model_name].to_s + ".find("
224
+ result += apply_transforms(statement[:item_id], 0)
225
+ result += ", function(err, "
226
+ when "update"
227
+ @functions.push (tabs + "});")
228
+ result = tabs + statement[:model_name].to_s + ".updateAttributes({}, function() {"
229
+ when "delete"
230
+ @functions.push (tabs + "});")
231
+ result = tabs + statement[:model_name].to_s + ".destroy(function() {"
232
+ end
233
+ end
234
+
235
+ def read_statement_transform(statement, num_tabs)
236
+ param = apply_transforms(statement[:read_statement][:read_statement_param], 0)
237
+ "data[" + param + "]"
238
+ end
239
+
240
+ def redirect_statement_transform(statement, num_tabs)
241
+ tabs = ""
242
+ num_tabs.times { tabs += "\t" }
243
+
244
+ redirect_statement_template = ERB.new(Shift::Generator::JavaScriptTemplates::REDIRECT_STATEMENT_TEMPLATE)
245
+ url = apply_transforms(statement[:redirect_statement][:redirect_statement_param], 0)
246
+ "\n" + tabs + redirect_statement_template.result(binding)
247
+ end
248
+
249
+ def value_transform(statement, num_tabs)
250
+ tabs = ""
251
+ num_tabs.times { tabs += "\t" }
252
+
253
+ key = statement.keys[0]
254
+
255
+ statement[key].to_s
256
+ end
257
+
258
+ def control_statement_transform(statement, num_tabs)
259
+ tabs = ""
260
+ num_tabs.times { tabs += "\t" }
261
+
262
+ key = statement.keys[0]
263
+
264
+ result = ""
265
+
266
+ @blocks.push (num_tabs)
267
+
268
+ case key
269
+ when :if_statement
270
+ result = tabs + "if " + apply_transforms(statement[:if_statement][:condition], 0) + " {"
271
+ when :while_statement
272
+ result = tabs + "while " + apply_transforms(statement[:while_statement][:condition], 0) + " {"
273
+ end
274
+
275
+ result
276
+ end
277
+
278
+ def concatenated_string_expression_transform(statement, num_tabs)
279
+ statement = statement.map do | token |
280
+ apply_transforms(token, 0)
281
+ end
282
+
283
+ statement.join(" + ")
284
+ end
285
+
286
+ def integer_casted_expression_transform(statement, num_tabs)
287
+ statement.delete(:int)
288
+ "Number(" + apply_transforms(statement, 0) + ")"
289
+ end
290
+
291
+ def apply_transforms(statement, num_tabs)
292
+ tabs = ""
293
+ if (num_tabs > 0)
294
+ num_tabs = num_tabs - 1
295
+ end
296
+
297
+ result = ""
298
+
299
+ if(@blocks.length > 0)
300
+ if(@blocks[@blocks.length - 1] == num_tabs)
301
+ t = ""
302
+ @blocks.pop.times { t += "\t" }
303
+ result += t + "}\n"
304
+ end
305
+ end
306
+
307
+ num_tabs.times { tabs += "\t" }
308
+
309
+ if(statement.is_a?(Hash))
310
+ key = statement.keys[0]
311
+ case key
312
+ when :assignment_statement
313
+ result += expression_transform(statement, num_tabs) + "\n"
314
+ when :write_statement
315
+ result += write_function_transform(statement, num_tabs) + "\n"
316
+ when :write_file_statement
317
+ result += write_file_function_transform(statement, num_tabs) + "\n"
318
+ when :read_statement
319
+ result += read_statement_transform(statement, num_tabs)
320
+ when :redirect_statement
321
+ result += redirect_statement_transform(statement, num_tabs) + "\n"
322
+ when :arithmetic_expression
323
+ result += value_transform(statement, num_tabs)
324
+ when :boolean_expression
325
+ result += value_transform(statement, num_tabs)
326
+ when :if_statement
327
+ result += control_statement_transform(statement, num_tabs) + "\n"
328
+ when :else_statement
329
+ @blocks.push (num_tabs)
330
+ result += tabs + value_transform(statement, num_tabs) + " {\n"
331
+ when :for_statement
332
+ statement = statement[:for_statement]
333
+ tokens = statement.to_s.split(" ")
334
+ @blocks.push (num_tabs)
335
+ result += tabs + "for(var k in " + tokens[3] + ") {\n"
336
+ result += tabs + "\t" + tokens[1] + " = " + tokens[3] + "[k];\n"
337
+ when :while_statement
338
+ result += control_statement_transform(statement, num_tabs) + "\n"
339
+ when :query
340
+ result += query_transform(statement, num_tabs)
341
+ when :int
342
+ integer_casted_expression_transform(statement, num_tabs)
343
+ else
344
+ result += token_transform(statement, num_tabs)
345
+ end
346
+ else
347
+ if statement.is_a?(Array)
348
+ concatenated_string_expression_transform(statement, num_tabs)
349
+ else
350
+ result += statement.to_s
351
+ end
352
+ end
353
+ end
354
+
355
+ def write_data()
356
+ if(@builder.models.length != 0)
357
+ @has_models = true
358
+ end
359
+
360
+ result = get_import_statements + get_model_data
361
+
362
+ @builder.handlers.each do | handlers |
363
+ url = url_transform(handlers.url)
364
+ method = handlers.method
365
+
366
+ @url_variables = []
367
+ current_url = handlers.url
368
+ if(current_url.is_a?(Array))
369
+ current_url.each do | token |
370
+ case token.keys[0]
371
+ when :url_variable
372
+ @url_variables.push token[:url_variable]
373
+ end
374
+ end
375
+ end
376
+
377
+ url_handler_template = ERB.new(Shift::Generator::JavaScriptTemplates::URL_HANDLER_DEFINITION)
378
+ result += "\n" + url_handler_template.result(binding) + "\n"
379
+
380
+ defined_hashes = []
381
+
382
+ handlers.handler.each do | statement |
383
+ result += apply_transforms(statement[:statement], statement[:num_tabs] + functions.length)
384
+ end
385
+
386
+ i = @functions.length - 2
387
+
388
+ blocks.each do | t |
389
+ tabs = ""
390
+ t.times { tabs += "\t" }
391
+ result += tabs + "}" + "\n"
392
+ end
393
+
394
+ functions.reverse.each do | closing_block |
395
+ tabs = ""
396
+ i.times { tabs += "\t" }
397
+ result += tabs + closing_block + "\n"
398
+ end
399
+
400
+ @functions = []
401
+ @blocks = []
402
+
403
+ result += "});\n"
404
+ end
405
+
406
+ result += "\n\n" + Shift::Generator::JavaScriptTemplates::APP_START_STATEMENT
407
+ end
408
+ end
409
+ end
410
+ end
@@ -0,0 +1,37 @@
1
+ module Shift
2
+ module Generator
3
+ module JavaScriptTemplates
4
+
5
+ IMPORT_JQNODE_STATEMENT = "var $ = require('jqNode').$;\n"
6
+
7
+ IMPORT_UTIL_STATEMENT = "var util = require('util');\n"
8
+
9
+ IMPORT_MU_STATEMENT = "var mu = require('mu2');\nmu.root = __dirname + '/views';\n"
10
+
11
+ IMPORT_DB_STATEMENT = "_Schema = require('jugglingdb').Schema;\nvar schema = new _Schema('mongodb', {port : 27017});\n"
12
+
13
+ UTILITY_FUNCTIONS = "
14
+ function writeTemplate(fileName, templateValues, response) {
15
+ if(!templateValues) {
16
+ $.writeFile('views/' + fileName);
17
+ } else {
18
+ var templateStream = mu.compileAndRender(fileName, templateValues);
19
+ util.pump(templateStream, response);
20
+ }
21
+ }"
22
+
23
+ MODEL_NAME_TEMPLATE = "var <%= model_name %> = schema.define('<%= model_name %>', {"
24
+
25
+ URL_HANDLER_DEFINITION = '$("<%= url %>").<%= method %>(function(request, response, data, urlData) {'
26
+
27
+ REDIRECT_STATEMENT_TEMPLATE = "$.redirect(<%= url %>);"
28
+
29
+ WRITE_DATA_TEMPLATE = "$.write(<%= write_data %>);"
30
+
31
+ WRITE_FILE_TEMPLATE = "writeTemplate(<%= args %>);"
32
+
33
+ APP_START_STATEMENT = "$.start({port : 8080});"
34
+
35
+ end
36
+ end
37
+ end