lat 0.1.1 → 0.1.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 051514055bc30ad3baf609b932c2b252f842ca9d864f929a6f8115ad72847de7
4
- data.tar.gz: 6352e1091aab7ba991cec765bd77941eba6d92ff998684b2958fd92ccce1e17a
3
+ metadata.gz: 79c0178cf5e3b3e1168af97aec3a318b082b25c43a2835464682f6bdcdf545f7
4
+ data.tar.gz: ef5b003a8c15b86ffd3575844232bfe909b084844587a114312b35d5d76e113b
5
5
  SHA512:
6
- metadata.gz: d5c337be6a2c2d6525638fbcc0c3e57b2fcacc021501af218c2e5a452a4fb526356df6c5a5210cef99262f91f7c26c1d6cffdb0857caccc29f875547e15c5fa2
7
- data.tar.gz: adbc284ef685eb4ceac54abe6dfe7a4337e29ea99f5784050ac28a47aff13194c6f61a4a26089231ed100f2a4fcc49839a1fcc39b5b4efbc6b257c365aeed51f
6
+ metadata.gz: a8377175fe6c7cb97521c4a51c6a7a5b2ebe0aa1a9bb9c3a0f19299fdd2e7d9f08fc9c5efe86098b716063ea656293d4612fc5575cfb39481d81fadd2282210b
7
+ data.tar.gz: 50e003a2f76a40427759f032ce0da3355422c481d6089f99d2deb1f1d384ca137478ffc0b14dd64c74ab3c856edc09c19ac99dc8b3665214d608e6b847ab39b7
data/bin/lat CHANGED
@@ -1,3 +1,3 @@
1
- #!/usr/bin/env ruby
2
- $LOAD_PATH.unshift File.join(__dir__, "../compiler")
1
+ #!/usr/bin/env ruby
2
+ $LOAD_PATH.unshift File.join(__dir__, "../compiler")
3
3
  require_relative "../compiler/compile"
data/compiler/codegen.rb CHANGED
@@ -7,9 +7,8 @@ class Generator
7
7
  case node
8
8
 
9
9
  when ImportNode
10
- "require %s" % [
11
- node.location
12
- ]
10
+ "require(\"#{node.location}\")"
11
+
13
12
  when ClassNode
14
13
  out = []
15
14
  out << "local #{node.name} = {}"
@@ -90,6 +89,50 @@ class Generator
90
89
  body_code
91
90
  ]
92
91
 
92
+ when ForNode
93
+ body_code =
94
+ if node.body.is_a?(Array)
95
+ node.body.map{ |n| generate (n) }.join("\n")
96
+ else
97
+ generate(node.body)
98
+ end
99
+ increment = ", #{node.step.nil? ? "" : generate(node.step)}"
100
+ "for %s = %s, %s%s do\n %s \nend" % [
101
+ generate(node.var),
102
+ generate(node.start),
103
+ generate(node.stop),
104
+ increment,
105
+ body_code
106
+ ]
107
+
108
+ when ForPairNode
109
+ body_code =
110
+ if node.body.is_a?(Array)
111
+ node.body.map{ |n| generate (n) }.join("\n")
112
+ else
113
+ generate(node.body)
114
+ end
115
+ "for %s, %s in pairs(%s) do\n %s \nend" % [
116
+ node.key,
117
+ node.val,
118
+ generate(node.t),
119
+ body_code
120
+ ]
121
+
122
+ when ForPairNode
123
+ body_code =
124
+ if node.body.is_a?(Array)
125
+ node.body.map{ |n| generate (n) }.join("\n")
126
+ else
127
+ generate(node.body)
128
+ end
129
+ "for %s, %s in ipairs(%s) do\n %s \nend" % [
130
+ generate(node.index),
131
+ generate(node.val),
132
+ generate(node.t),
133
+ body_code
134
+ ]
135
+
93
136
  when SwitchNode
94
137
  compiled = ""
95
138
  node.cases.each_with_index do |c, i|
@@ -169,6 +212,9 @@ class Generator
169
212
  when IntegerNode
170
213
  node.value.to_s
171
214
 
215
+ when FloatNode
216
+ node.value.to_s
217
+
172
218
  when StringNode
173
219
  "\"%s\"" % [
174
220
  node.value
data/compiler/compile.rb CHANGED
@@ -19,8 +19,10 @@ def detect_os
19
19
  :linux
20
20
  end
21
21
 
22
+ OS = detect_os
23
+
22
24
  def love_installed?
23
- if detect_os == :windows
25
+ if OS == :windows
24
26
  common_paths = [
25
27
  "C:/Program Files/LOVE/love.exe",
26
28
  "C:/Program Files (x86)/LOVE/love.exe",
@@ -33,15 +35,14 @@ def love_installed?
33
35
  end
34
36
 
35
37
  def install_love
36
- os = detect_os
37
38
  puts "[lat] Love2D not found, attempting to install"
38
- print "Do you want to install Love2d? (y/n)"
39
+ print "Do you want to install LOVE2D? (y/n)"
39
40
  answer = $stdin.gets.chomp.downcase
40
41
 
41
42
  if %w[y yes].include?(answer.downcase)
42
43
  puts "installing love..."
43
44
 
44
- case os
45
+ case OS
45
46
  when :arch
46
47
  system("sudo pacman -S --noconfirm love")
47
48
  when :debian
@@ -52,11 +53,11 @@ def install_love
52
53
  if system("which brew > /dev/null 2>&1")
53
54
  system("brew install love")
54
55
  else
55
- puts "[lat] Homebrew not found. Install Love2D from https://love2d.org"
56
+ puts "[lat] Homebrew not found. Install LOVE2D from https://love2d.org"
56
57
  exit 1
57
58
  end
58
59
  when :windows
59
- puts "[lat] Please install Love2D from https://love2d.org"
60
+ puts "[lat] Please install LOVE2D from https://love2d.org"
60
61
  puts "[lat] Set LOVE_PATH to the love.exe location:"
61
62
  puts '[lat] setx LOVE_PATH "C:\\Program Files\\LOVE\\love.exe"'
62
63
  else
@@ -74,22 +75,19 @@ end
74
75
  def find_love
75
76
  install_love unless love_installed?
76
77
 
77
- candidates = [
78
- "love",
79
- "C:/Program Files/LOVE/love.exe",
80
- "C:/Program Files (x86)/LOVE/love.exe",
81
- ENV["LOVE_PATH"]
82
- ].compact
83
-
84
- candidates.each do |path|
85
- return path if system("where #{path} >nul 2>&1") || File.exist?(path.to_s)
78
+ if OS == :windows
79
+ candidates = [ENV["LOVE_PATH"], "C:/Program Files/LOVE/love.exe", "C:/Program Files (x86)/LOVE/love.exe"].compact
80
+ candidates.each { |p| return p if File.exist?(p) }
81
+ else
82
+ ["love", "love2d"].each do |cmd|
83
+ return cmd if system("which #{cmd} > /dev/null 2>&1")
84
+ end
86
85
  end
87
86
 
88
87
  puts "Error: LOVE2D not found. Install it from https://love2d.org or set LOVE_PATH env variable."
89
88
  exit 1
90
89
  end
91
90
  skip_run = false
92
- love = find_love()
93
91
 
94
92
  if ARGV[0] == "run"
95
93
  latcDir = File.join(Dir.pwd, ".latc")
@@ -102,6 +100,7 @@ if ARGV[0] == "run"
102
100
  puts "Error: .latc exists but no main.lua found"
103
101
  exit 1
104
102
  end
103
+ love = find_love()
105
104
  exec(love, latcDir)
106
105
  elsif ARGV[0] == "build"
107
106
  ARGV.shift
@@ -110,7 +109,7 @@ end
110
109
  inputFile = ARGV[0] || "main.lat"
111
110
 
112
111
  unless File.exist?(inputFile)
113
- puts "Error: fil `#{inputFile}` not found"
112
+ puts "Error: file `#{inputFile}` not found"
114
113
  exit 1
115
114
  end
116
115
 
@@ -139,6 +138,7 @@ generated = Generator.new.generate(tree)
139
138
  # puts generated
140
139
  File.open(outputFile, 'w') { |file| file.write(generated)}
141
140
 
142
- exec(love, latcDir) unless skip_run
141
+
142
+ exec(find_love(), latcDir) unless skip_run
143
143
 
144
144
  # ln -s "$(pwd)/compiler/compile.rb" /usr/local/bin/lat
data/compiler/parser.rb CHANGED
@@ -6,9 +6,16 @@ IfNode = Struct.new(:condition, :body, :elif_blocks, :else_body)
6
6
  ElifBlock = Struct.new(:condition, :body)
7
7
 
8
8
  ImportNode = Struct.new(:location)
9
+
9
10
  WhileNode = Struct.new(:statement, :body)
11
+ ForNode = Struct.new(:var, :start, :stop, :step, :body)
12
+ ForPairNode = Struct.new(:key, :val, :t, :body)
13
+ ForIPairNode = Struct.new(:index, :val, :t, :body)
14
+
10
15
  IntegerNode = Struct.new(:value)
16
+ FloatNode = Struct.new(:value)
11
17
  StringNode = Struct.new(:value)
18
+
12
19
  CallNode = Struct.new(:name, :arg_expr)
13
20
  VarRefNode = Struct.new(:value)
14
21
  VarAssignNode = Struct.new(:name, :value)
@@ -89,6 +96,12 @@ class Parser
89
96
  parse_if
90
97
  elsif peek(:while)
91
98
  parse_while
99
+ elsif peek(:for)
100
+ parse_for
101
+ elsif peek(:forpairs)
102
+ parse_forpairs
103
+ elsif peek(:foripairs)
104
+ parse_foripairs
92
105
  elsif peek(:switch)
93
106
  parse_switch
94
107
  elsif peek(:print)
@@ -142,14 +155,8 @@ class Parser
142
155
  consume(:def)
143
156
  name = "#{name}:#{consume(:identifier).value}"
144
157
  args = parse_args
145
- skip_newlines
146
-
147
- body = []
158
+ body = parse_block
148
159
 
149
- until peek(:end)
150
- body << parse_statement
151
- skip_newlines
152
- end
153
160
  consume(:end)
154
161
  ClassDefNode.new(name, args, body)
155
162
  end
@@ -165,13 +172,7 @@ class Parser
165
172
  name = consume(:identifier).value
166
173
  args = parse_args
167
174
 
168
- skip_newlines
169
- body = []
170
-
171
- until peek(:end)
172
- body << parse_statement
173
- skip_newlines
174
- end
175
+ body = parse_block
175
176
  consume(:end)
176
177
  DefNode.new(type, name, args, body)
177
178
  end
@@ -207,11 +208,8 @@ class Parser
207
208
  consume(:else)
208
209
  skip_newlines
209
210
 
210
- else_body = []
211
- while !peek(:end)
212
- else_body << parse_statement
213
- skip_newlines
214
- end
211
+ else_body = parse_block
212
+
215
213
  end
216
214
 
217
215
  consume(:end)
@@ -230,16 +228,57 @@ class Parser
230
228
  statement = parse_expr
231
229
  end
232
230
 
233
- skip_newlines
234
- body = []
231
+ body = parse_block
235
232
 
236
- until peek(:end)
237
- body << parse_statement
238
- skip_newlines
233
+ consume(:end)
234
+ WhileNode.new(statement, body)
235
+ end
236
+
237
+ def parse_for
238
+ consume(:for)
239
+ var = parse_expr
240
+ consume(:equal)
241
+ start = parse_expr
242
+ consume(:comma)
243
+ stop = parse_expr
244
+
245
+ step = nil
246
+ if peek(:comma)
247
+ consume(:comma)
248
+ step = parse_expr
239
249
  end
250
+ body = parse_block
240
251
 
241
252
  consume(:end)
242
- WhileNode.new(statement, body)
253
+ ForNode.new(var, start, stop, step, body)
254
+
255
+ end
256
+
257
+ def parse_forpairs
258
+ consume(:forpairs)
259
+ key = consume(:identifier).value
260
+ consume(:comma)
261
+ val = consume(:identifier).value
262
+ consume(:in)
263
+ t = parse_expr
264
+ body = parse_block
265
+ consume(:end)
266
+
267
+ ForPairNode.new(key, val, t, body)
268
+ end
269
+
270
+
271
+ def parse_foripairs
272
+ consume(:foripairs)
273
+ index = consume(:identifier).value
274
+ consume(:comma)
275
+ val = consume(:identifier).value
276
+ consume(:in)
277
+ t = parse_expr
278
+ body = parse_block
279
+ consume(:end)
280
+
281
+ ForIPairNode.new(index, val, t, body)
243
282
  end
244
283
 
245
284
  def parse_switch
@@ -306,24 +345,6 @@ class Parser
306
345
 
307
346
  left
308
347
  end
309
- # consume(:if)
310
-
311
- # if peek(:oparen)
312
- # consume(:oparen)
313
- # statement = parse_expr
314
- # consume(:cparen)
315
- # else
316
- # statement = parse_expr
317
- # end
318
- # skip_newlines
319
- # body = []
320
-
321
- # until peek(:elif) peek(:end)
322
- # body << parse_statement
323
- # skip_newlines
324
- # end
325
- # consume(:end)
326
- # IfNode.new(statement, body)
327
348
 
328
349
  def parse_args
329
350
  consume(:oparen)
@@ -339,6 +360,17 @@ class Parser
339
360
  args
340
361
  end
341
362
 
363
+ def parse_block
364
+ skip_newlines
365
+ body = []
366
+
367
+ until peek(:end)
368
+ body << parse_statement
369
+ skip_newlines
370
+ end
371
+ body
372
+ end
373
+
342
374
 
343
375
 
344
376
  def parse_additive
@@ -362,41 +394,31 @@ class Parser
362
394
  end
363
395
  left
364
396
  end
365
- # def parse_operators
366
- # left = parse_term
367
-
368
- # left = parse_op(left, :divide)
369
- # left = parse_op(left, :multiply)
370
- # left = parse_op(left, :plus)
371
- # left = parse_op(left, :minus)
372
-
373
- # left
374
- # end
375
397
 
376
- # def parse_op(left, operator)
377
-
378
- # while peek(operator)
379
- # consume(operator)
380
- # right = parse_term
381
- # left = BinOpNode.new(left, operator, right)
382
- # end
383
- # left
384
-
385
- # end
386
398
 
387
399
  def parse_term
400
+ skip_newlines
388
401
  if peek(:integer)
389
402
  IntegerNode.new(consume(:integer).value.to_i)
390
403
 
404
+ elsif peek(:float)
405
+ FloatNode.new(consume(:float).value.to_f)
406
+
391
407
  elsif peek(:identifier) && peek(:oparen, 1)
392
408
  parse_call
393
409
 
410
+ elsif peek(:identifier) && peek(:lbracket, 1)
411
+ parse_array_access
412
+
413
+ elsif peek(:lbrace)
414
+ parse_array
415
+
394
416
  elsif peek(:identifier)
395
417
  VarRefNode.new(consume(:identifier).value)
396
418
 
397
419
  elsif peek(:string)
398
420
  strVal = consume(:string).value
399
- StringNode.new(strVal[1..-2])
421
+ StringNode.new(strVal[1..-2])
400
422
 
401
423
  elsif peek(:oparen)
402
424
  # consume(:oparen)
@@ -407,15 +429,19 @@ class Parser
407
429
 
408
430
  first = parse_expr
409
431
  items = [first]
410
- until peek(:identifier) && peek(:or) && peek(:dequal) && peek(:cparen) && peek(:plus)
432
+ until peek(:identifier) || peek(:dequal)
411
433
  break
412
434
  end
413
435
 
414
- if !peek(:identifier) && peek(:or)
436
+ if !peek(:identifier) && peek(:or) || peek(:and)
415
437
  while peek(:or)
416
438
  consume(:or)
417
439
  items << parse_expr
418
440
  end
441
+ while peek(:and)
442
+ consume(:and)
443
+ items << parse_expr
444
+ end
419
445
  consume(:cparen)
420
446
  return AndOrListNode.new(items)
421
447
  end
@@ -426,8 +452,7 @@ class Parser
426
452
  elsif peek(:self)
427
453
  parse_self_node
428
454
 
429
- elsif peek(:coparen)
430
- parse_array
455
+
431
456
 
432
457
 
433
458
  elsif LOVE_NAMESPACES.keys.include?(peek_type)
@@ -444,7 +469,8 @@ class Parser
444
469
  prefix = @tokens.shift.type
445
470
  namespace = LOVE_NAMESPACES[prefix]
446
471
 
447
- name = consume(:identifier).value
472
+ name = @tokens.shift.value
473
+
448
474
  args = parse_arg_expr
449
475
 
450
476
  LoveCallNode.new(namespace, name, args)
@@ -499,25 +525,30 @@ class Parser
499
525
  end
500
526
 
501
527
  def parse_array
502
- consume(:coparen)
528
+ consume(:lbrace)
529
+ skip_newlines
503
530
  elements = []
504
- unless peek(:ccparen)
531
+ unless peek(:rbrace)
505
532
  elements << parse_expr
533
+ skip_newlines
506
534
  while peek(:comma)
507
535
  consume(:comma)
536
+ skip_newlines
508
537
  elements << parse_expr
538
+ skip_newlines
509
539
  end
510
540
  end
511
- consume(:ccparen)
541
+ skip_newlines
542
+ consume(:rbrace)
512
543
  ArrayNode.new(elements)
513
544
  end
514
545
 
515
546
 
516
547
  def parse_array_access
517
548
  name = consume(:identifier).value
518
- consume(:soparen)
549
+ consume(:lbracket)
519
550
  index = parse_expr
520
- consume(:scparen)
551
+ consume(:rbracket)
521
552
  ArrayAccessNode.new(name, index)
522
553
  end
523
554
 
@@ -534,4 +565,4 @@ class Parser
534
565
  def peek_type(offset = 0)
535
566
  @tokens[offset]&.type
536
567
  end
537
- end
568
+ end
@@ -3,56 +3,66 @@ Token = Struct.new(:type, :value)
3
3
  class Tokenizer
4
4
 
5
5
  TOKEN_TYPES = [
6
+
7
+ #love
8
+ [:lgraphics, /-G:/],
9
+ [:laudio, /-A:/],
10
+ [:ldata, /-D:/],
11
+ [:levent, /-E:/],
12
+ [:lfilesystem, /-FS:/],
13
+ [:lfont, /-F:/],
14
+ [:limage, /-I:/],
15
+ [:ljoystick, /-J:/],
16
+ [:lmouse, /-M:/],
17
+ [:lkeyboard, /-K:/],
18
+ [:love, /\blove\b/],
19
+
6
20
  [:local, /\bnat\b/],
7
21
  [:def, /\bcall\b/],
8
22
  [:end, /\bdone\b/],
9
23
  [:if, /\bif\b/],
10
24
  [:elif, /\belif\b/],
11
25
  [:else, /\belse\b/],
26
+
12
27
  [:while, /\bwhen\b/],
28
+ [:for, /\bfor\b/],
29
+ [:forpairs, /\beach\b/],
30
+ [:foripairs, /\bseq\b/],
31
+
13
32
  [:print, /\bprint\b/],
14
33
  [:return, /\breturn\b/],
15
34
  [:or, /\bor\b/],
16
35
  [:and, /\band\b/],
36
+ [:in, /\bas\b/],
17
37
  [:switch, /\bswitch\b/],
18
38
  [:to, /\bto\b/],
19
39
  [:class, /\bclass\b/],
20
40
  [:self, /\bself\b/],
21
41
  [:import, /\bbring\b/],
22
42
 
23
- #love
24
- [:lgraphics, /-G:/],
25
- [:laudio, /-A:/],
26
- [:ldata, /-D:/],
27
- [:levent, /-E:/],
28
- [:lfilesystem, /-FS:/],
29
- [:lfont, /-F:/],
30
- [:limage, /-I:/],
31
- [:ljoystick, /-J:/],
32
- [:lmouse, /-M:/],
33
- [:lkeyboard, /-K:/],
34
- [:love, /\blove\b/],
43
+
35
44
 
36
45
  # thingies
37
- [:identifier, /\b[a-zA-Z]+\b/],
46
+ [:identifier, /\b[a-zA-Z_][a-zA-Z0-9_]*\b/],
38
47
  [:string, /"([^"]*)"/],
39
- [:integer, /\b[0-9]+\b/],
48
+ [:float, /(?:\d+\.\d*|\.\d+)/],
49
+ [:integer, /\b\d+\b/],
40
50
  [:oparen, /\(/],
41
51
  [:cparen, /\)/],
42
- [:soparen, /\[/],
43
- [:scparen, /\]/],
44
- [:coparen, /\{/],
45
- [:ccparen, /\}/],
52
+ [:lbracket, /\[/],
53
+ [:rbracket, /\]/],
54
+ [:lbrace, /\{/],
55
+ [:rbrace, /\}/],
46
56
  [:comma, /,/],
47
57
  [:dot, /\./],
48
58
  [:colon, /:/],
49
59
 
50
60
  # operators
51
61
  [:dequal, /==/],
52
- [:greater, />/],
53
- [:lesser, /</],
54
62
  [:grequal, />=/],
55
63
  [:lequal, /<=/],
64
+ [:greater, />/],
65
+ [:lesser, /</],
56
66
  [:equal, /=/],
57
67
  [:divide, /\//],
58
68
  [:multiply, /\*/],
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lat
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - JakeOJeff