mt-lang 0.3.7 → 0.3.9
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 +4 -4
- data/lib/milk_tea/base.rb +1 -1
- data/lib/milk_tea/core/control_flow/builder.rb +6 -1
- data/lib/milk_tea/core/parser/expressions.rb +23 -5
- data/lib/milk_tea/core/parser.rb +1 -1
- data/lib/milk_tea/core/semantic_analyzer/flow_refinement.rb +12 -2
- data/lib/milk_tea/core/semantic_analyzer/top_level.rb +5 -1
- data/lib/milk_tea/tooling/linter/visitors.rb +54 -0
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 61a19112e2810978ecf1ce56b1d1d1290a26bcb933b9e89857ffca77d1323392
|
|
4
|
+
data.tar.gz: f68d1016a49c1cf195b5d24c430e4bbccde2c1ad9c7b82523b9e51d9f899d2b6
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d7ffd6ea3d812428f451bbf304662a36a05986eb7ff2ec9a207364be7f37f81d84379e40325a155fd9565885d648503c73ab34fb1e851adbb1d5e53b193d696c
|
|
7
|
+
data.tar.gz: caa0c4acb4264740d58d857214ff68c3b726bf9a08d5f894ddc25466066e898567fd45c3b1c0e0634902be9a993acec7f1006b146af811ec0b918c778f60b234
|
data/lib/milk_tea/base.rb
CHANGED
|
@@ -137,7 +137,12 @@ module MilkTea
|
|
|
137
137
|
@graph.add_edge(match_id, next_id)
|
|
138
138
|
else
|
|
139
139
|
stmt.arms.each do |arm|
|
|
140
|
-
|
|
140
|
+
arm_body = if arm.respond_to?(:body)
|
|
141
|
+
arm.body
|
|
142
|
+
else
|
|
143
|
+
[MilkTea::AST::ExpressionStmt.new(expression: arm.value, line: arm.value.respond_to?(:line) ? arm.value.line : nil)]
|
|
144
|
+
end
|
|
145
|
+
arm_entry = build_block(arm_body, next_id, break_target:, continue_target:)
|
|
141
146
|
if arm.binding_name
|
|
142
147
|
binding_key = declaration_binding_key(arm, arm.binding_name)
|
|
143
148
|
if binding_key
|
|
@@ -25,11 +25,29 @@ module MilkTea
|
|
|
25
25
|
|
|
26
26
|
def parse_if_expression
|
|
27
27
|
condition = parse_or
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
28
|
+
|
|
29
|
+
if inline_block_body?
|
|
30
|
+
consume(:colon, "expected ':' after condition in if expression")
|
|
31
|
+
then_expression = parse_expression
|
|
32
|
+
consume(:else, "expected 'else' in if expression")
|
|
33
|
+
consume(:colon, "expected ':' after 'else' in if expression")
|
|
34
|
+
else_expression = parse_expression
|
|
35
|
+
else
|
|
36
|
+
consume(:colon, "expected ':' after condition in if expression")
|
|
37
|
+
consume(:newline, "expected newline after 'if condition:' in if expression")
|
|
38
|
+
consume(:indent, "expected indented body in if expression")
|
|
39
|
+
then_expression = parse_expression
|
|
40
|
+
consume_end_of_statement unless block_expression?(then_expression)
|
|
41
|
+
consume(:dedent, "expected end of if expression body")
|
|
42
|
+
consume(:else, "expected 'else' in if expression")
|
|
43
|
+
consume(:colon, "expected ':' after 'else' in if expression")
|
|
44
|
+
consume(:newline, "expected newline after 'else:' in if expression")
|
|
45
|
+
consume(:indent, "expected indented else body in if expression")
|
|
46
|
+
else_expression = parse_expression
|
|
47
|
+
consume_end_of_statement unless block_expression?(else_expression)
|
|
48
|
+
consume(:dedent, "expected end of else expression body")
|
|
49
|
+
end
|
|
50
|
+
|
|
33
51
|
AST::IfExpr.new(condition:, then_expression:, else_expression:)
|
|
34
52
|
end
|
|
35
53
|
|
data/lib/milk_tea/core/parser.rb
CHANGED
|
@@ -253,7 +253,7 @@ module MilkTea
|
|
|
253
253
|
end
|
|
254
254
|
|
|
255
255
|
def block_expression?(expression)
|
|
256
|
-
expression.is_a?(AST::ProcExpr) || expression.is_a?(AST::MatchExpr)
|
|
256
|
+
expression.is_a?(AST::ProcExpr) || expression.is_a?(AST::MatchExpr) || expression.is_a?(AST::IfExpr)
|
|
257
257
|
end
|
|
258
258
|
|
|
259
259
|
def parse_qualified_name
|
|
@@ -204,7 +204,11 @@ module MilkTea
|
|
|
204
204
|
lines.concat(statement_list_lines(statement.body))
|
|
205
205
|
when AST::MatchStmt
|
|
206
206
|
statement.arms.each do |arm|
|
|
207
|
-
|
|
207
|
+
if arm.respond_to?(:body)
|
|
208
|
+
lines.concat(statement_list_lines(arm.body))
|
|
209
|
+
else
|
|
210
|
+
lines << expression_end_line(arm.value)
|
|
211
|
+
end
|
|
208
212
|
end
|
|
209
213
|
when AST::DeferStmt
|
|
210
214
|
lines.concat(statement_list_lines(statement.body)) if statement.body
|
|
@@ -374,7 +378,13 @@ module MilkTea
|
|
|
374
378
|
when AST::WhileStmt, AST::ForStmt, AST::UnsafeStmt, AST::ErrorBlockStmt
|
|
375
379
|
[stmt.respond_to?(:line) ? stmt.line : nil, last_ast_line(stmt.body)].compact.max
|
|
376
380
|
when AST::MatchStmt
|
|
377
|
-
arm_lines = stmt.arms.filter_map
|
|
381
|
+
arm_lines = stmt.arms.filter_map do |arm|
|
|
382
|
+
if arm.respond_to?(:body)
|
|
383
|
+
last_ast_line(arm.body)
|
|
384
|
+
elsif arm.respond_to?(:value)
|
|
385
|
+
arm.value.respond_to?(:line) ? arm.value.line : nil
|
|
386
|
+
end
|
|
387
|
+
end
|
|
378
388
|
[stmt.line, *arm_lines].compact.max
|
|
379
389
|
when AST::DeferStmt
|
|
380
390
|
[stmt.respond_to?(:line) ? stmt.line : nil, last_ast_line(stmt.body)].compact.max
|
|
@@ -376,7 +376,11 @@ module MilkTea
|
|
|
376
376
|
else
|
|
377
377
|
callee_name = expression.callee.callee.is_a?(AST::Identifier) ? expression.callee.callee.name : nil
|
|
378
378
|
if callee_name
|
|
379
|
-
resolved_type =
|
|
379
|
+
resolved_type = begin
|
|
380
|
+
resolve_type_expression(expression.callee)
|
|
381
|
+
rescue SemanticError
|
|
382
|
+
nil
|
|
383
|
+
end
|
|
380
384
|
if resolved_type && resolved_type.is_a?(Types::Struct)
|
|
381
385
|
fields = {}
|
|
382
386
|
expression.arguments.each do |argument|
|
|
@@ -197,14 +197,20 @@ module MilkTea
|
|
|
197
197
|
with_scope { visit_statement_list(statement.body) }
|
|
198
198
|
@unsafe_depth -= 1
|
|
199
199
|
when AST::ForStmt
|
|
200
|
+
@loop_depth ||= 0
|
|
201
|
+
@loop_depth += 1
|
|
200
202
|
visit_expression(statement.iterable)
|
|
201
203
|
with_scope do
|
|
202
204
|
declare_local(statement.name, statement.line, column: statement.column, var: false) if statement.name
|
|
203
205
|
visit_statement_list(statement.body)
|
|
204
206
|
end
|
|
207
|
+
@loop_depth -= 1
|
|
205
208
|
when AST::WhileStmt
|
|
209
|
+
@loop_depth ||= 0
|
|
210
|
+
@loop_depth += 1
|
|
206
211
|
visit_expression(statement.condition)
|
|
207
212
|
with_scope { visit_statement_list(statement.body) }
|
|
213
|
+
@loop_depth -= 1
|
|
208
214
|
when AST::ReturnStmt
|
|
209
215
|
visit_expression(statement.value) if statement.value
|
|
210
216
|
flag_redundant_widening_cast(statement.value) if statement.value
|
|
@@ -776,6 +782,7 @@ module MilkTea
|
|
|
776
782
|
return unless stmts.all? { |s| inline_simple_statement?(s) }
|
|
777
783
|
|
|
778
784
|
return if visually_inline_if?(statement, stmts)
|
|
785
|
+
return if inline_if_too_wide?(statement, stmts)
|
|
779
786
|
|
|
780
787
|
emit_conciseness_hint(
|
|
781
788
|
"prefer-inline-if",
|
|
@@ -785,6 +792,51 @@ module MilkTea
|
|
|
785
792
|
)
|
|
786
793
|
end
|
|
787
794
|
|
|
795
|
+
def inline_if_too_wide?(statement, stmts)
|
|
796
|
+
return false if statement.branches.empty?
|
|
797
|
+
|
|
798
|
+
text = +""
|
|
799
|
+
|
|
800
|
+
statement.branches.each_with_index do |b, i|
|
|
801
|
+
cond_src = source_line_from(b.line, b.column)
|
|
802
|
+
return false unless cond_src
|
|
803
|
+
|
|
804
|
+
stmt_col = stmts[i].respond_to?(:column) ? stmts[i].column : nil
|
|
805
|
+
stmt_line = stmts[i].respond_to?(:line) ? stmts[i].line : nil
|
|
806
|
+
body_src = source_line_from(stmt_line, stmt_col)
|
|
807
|
+
return false unless body_src
|
|
808
|
+
|
|
809
|
+
text << cond_src
|
|
810
|
+
text << " "
|
|
811
|
+
text << body_src
|
|
812
|
+
text << " "
|
|
813
|
+
end
|
|
814
|
+
|
|
815
|
+
if statement.else_line
|
|
816
|
+
else_src = source_line_from(statement.else_line, statement.else_column)
|
|
817
|
+
return false unless else_src
|
|
818
|
+
text << else_src
|
|
819
|
+
text << " "
|
|
820
|
+
end
|
|
821
|
+
|
|
822
|
+
stmt_col = stmts.last.respond_to?(:column) ? stmts.last.column : nil
|
|
823
|
+
stmt_line = stmts.last.respond_to?(:line) ? stmts.last.line : nil
|
|
824
|
+
else_body = source_line_from(stmt_line, stmt_col)
|
|
825
|
+
return false unless else_body
|
|
826
|
+
text << else_body
|
|
827
|
+
|
|
828
|
+
text.strip.length > 120
|
|
829
|
+
end
|
|
830
|
+
|
|
831
|
+
def source_line_from(line, column)
|
|
832
|
+
return nil unless line
|
|
833
|
+
line_idx = Integer(line) - 1
|
|
834
|
+
return nil if line_idx < 0 || line_idx >= @source_lines.length
|
|
835
|
+
raw = @source_lines[line_idx].to_s
|
|
836
|
+
return raw.strip if column.nil?
|
|
837
|
+
raw[Integer(column) - 1..]&.strip
|
|
838
|
+
end
|
|
839
|
+
|
|
788
840
|
def visually_inline_if?(statement, stmts)
|
|
789
841
|
n = statement.branches.length
|
|
790
842
|
statement.branches.each_with_index.all? { |b, i|
|
|
@@ -801,6 +853,7 @@ module MilkTea
|
|
|
801
853
|
return unless statement.else_body
|
|
802
854
|
|
|
803
855
|
stmts = (statement.branches.map(&:body) + [statement.else_body]).map { |b| single_statement_body(b) }
|
|
856
|
+
return if inline_if_too_wide?(statement, stmts)
|
|
804
857
|
report_conditional_expression(stmts, line: statement.line, column: statement.branches.first&.column, kind: "if")
|
|
805
858
|
end
|
|
806
859
|
|
|
@@ -814,6 +867,7 @@ module MilkTea
|
|
|
814
867
|
|
|
815
868
|
def report_conditional_expression(stmts, line:, column:, kind:)
|
|
816
869
|
return if stmts.empty? || stmts.any?(&:nil?)
|
|
870
|
+
return if @loop_depth && @loop_depth > 0
|
|
817
871
|
|
|
818
872
|
if stmts.all? { |s| s.is_a?(AST::ReturnStmt) && s.value }
|
|
819
873
|
emit_conciseness_hint(
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: mt-lang
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.3.
|
|
4
|
+
version: 0.3.9
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Long (Teefan) Tran
|
|
@@ -603,7 +603,7 @@ metadata:
|
|
|
603
603
|
homepage_uri: https://teefan.github.io/mt-lang/
|
|
604
604
|
source_code_uri: https://github.com/teefan/mt-lang
|
|
605
605
|
post_install_message: |
|
|
606
|
-
Milk Tea 0.3.
|
|
606
|
+
Milk Tea 0.3.9 installed!
|
|
607
607
|
|
|
608
608
|
System requirements:
|
|
609
609
|
- A C compiler (gcc or clang) must be available on PATH
|