mt-lang 0.3.16 → 0.3.20

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 (69) hide show
  1. checksums.yaml +4 -4
  2. data/docs/language-design.md +3 -4
  3. data/docs/language-manual.md +3 -3
  4. data/lib/milk_tea/base.rb +1 -1
  5. data/lib/milk_tea/core/{binding_types.rb → bindings.rb} +1 -1
  6. data/lib/milk_tea/core/c_backend/expressions.rb +34 -23
  7. data/lib/milk_tea/core/c_backend/feature_detection.rb +25 -45
  8. data/lib/milk_tea/core/c_backend/type_collectors.rb +18 -30
  9. data/lib/milk_tea/core/c_backend/type_declaration.rb +0 -6
  10. data/lib/milk_tea/core/c_backend.rb +63 -54
  11. data/lib/milk_tea/core/compile_time.rb +279 -74
  12. data/lib/milk_tea/core/control_flow/constant_propagation.rb +1 -1
  13. data/lib/milk_tea/core/{compatibility_helpers.rb → intrinsics.rb} +9 -2
  14. data/lib/milk_tea/core/lexer.rb +55 -48
  15. data/lib/milk_tea/core/lowering/block.rb +9 -0
  16. data/lib/milk_tea/core/lowering/calls.rb +2 -0
  17. data/lib/milk_tea/core/lowering/declarations.rb +1 -1
  18. data/lib/milk_tea/core/lowering/functions.rb +11 -8
  19. data/lib/milk_tea/core/lowering/resolve.rb +10 -3
  20. data/lib/milk_tea/core/lowering/scans.rb +13 -18
  21. data/lib/milk_tea/core/lowering.rb +18 -18
  22. data/lib/milk_tea/core/module_binder.rb +9 -10
  23. data/lib/milk_tea/core/module_loader.rb +64 -57
  24. data/lib/milk_tea/core/module_path_resolver.rb +1 -4
  25. data/lib/milk_tea/core/parser/declarations.rb +43 -19
  26. data/lib/milk_tea/core/parser/expressions.rb +4 -7
  27. data/lib/milk_tea/core/parser/statements.rb +5 -5
  28. data/lib/milk_tea/core/parser.rb +43 -17
  29. data/lib/milk_tea/core/semantic_analyzer/calls.rb +24 -31
  30. data/lib/milk_tea/core/semantic_analyzer/expressions.rb +20 -23
  31. data/lib/milk_tea/core/semantic_analyzer/name_resolution.rb +117 -85
  32. data/lib/milk_tea/core/semantic_analyzer/statements.rb +19 -41
  33. data/lib/milk_tea/core/semantic_analyzer.rb +57 -38
  34. data/lib/milk_tea/core.rb +6 -2
  35. data/lib/milk_tea/dap/lldb_dap_backend.rb +153 -0
  36. data/lib/milk_tea/dap/server/lldb_backend.rb +1 -1
  37. data/lib/milk_tea/dap.rb +1 -1
  38. data/lib/milk_tea/lsp/server/semantic_tokens.rb +6 -0
  39. data/lib/milk_tea/lsp.rb +1 -7
  40. data/lib/milk_tea/{bindings/cli.rb → tooling/bindgen_cli.rb} +1 -1
  41. data/lib/milk_tea/tooling/cli/commands/bindgen.rb +11 -0
  42. data/lib/milk_tea/tooling/cli/commands/build.rb +37 -0
  43. data/lib/milk_tea/tooling/cli/commands/cache.rb +46 -0
  44. data/lib/milk_tea/tooling/cli/commands/check.rb +116 -0
  45. data/lib/milk_tea/tooling/cli/commands/command_base.rb +8 -0
  46. data/lib/milk_tea/tooling/cli/commands/completions.rb +48 -0
  47. data/lib/milk_tea/tooling/cli/commands/dap.rb +58 -0
  48. data/lib/milk_tea/tooling/cli/commands/debug.rb +77 -0
  49. data/lib/milk_tea/tooling/cli/commands/deps.rb +17 -0
  50. data/lib/milk_tea/tooling/cli/commands/docs.rb +58 -0
  51. data/lib/milk_tea/tooling/cli/commands/emit_c.rb +64 -0
  52. data/lib/milk_tea/tooling/cli/commands/format.rb +199 -0
  53. data/lib/milk_tea/tooling/cli/commands/lex.rb +46 -0
  54. data/lib/milk_tea/tooling/cli/commands/lint.rb +248 -0
  55. data/lib/milk_tea/tooling/cli/commands/lower.rb +50 -0
  56. data/lib/milk_tea/tooling/cli/commands/lsp.rb +43 -0
  57. data/lib/milk_tea/tooling/cli/commands/new.rb +26 -0
  58. data/lib/milk_tea/tooling/cli/commands/parse.rb +51 -0
  59. data/lib/milk_tea/tooling/cli/commands/run.rb +99 -0
  60. data/lib/milk_tea/tooling/cli/commands/snapshot.rb +117 -0
  61. data/lib/milk_tea/tooling/cli/commands/test.rb +557 -0
  62. data/lib/milk_tea/tooling/cli/commands/toolchain.rb +16 -0
  63. data/lib/milk_tea/tooling/cli.rb +101 -1893
  64. data/lib/milk_tea/tooling.rb +1 -1
  65. metadata +29 -9
  66. data/lib/milk_tea/core/compile_time/const_eval.rb +0 -182
  67. data/lib/milk_tea/core/module_loader/errors.rb +0 -23
  68. data/lib/milk_tea/dap/backends/lldb_dap.rb +0 -156
  69. /data/lib/milk_tea/core/lowering/{async.rb → async/frame_builder.rb} +0 -0
@@ -18,5 +18,5 @@ require_relative "tooling/linter"
18
18
  require_relative "tooling/docs_app"
19
19
  require_relative "tooling/project_scaffold"
20
20
  require_relative "tooling/toolchain_cli"
21
- require_relative "bindings/cli"
21
+ require_relative "tooling/bindgen_cli"
22
22
  require_relative "tooling/cli"
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.16
4
+ version: 0.3.20
5
5
  platform: ruby
6
6
  authors:
7
7
  - Long (Teefan) Tran
@@ -158,7 +158,6 @@ files:
158
158
  - lib/milk_tea/bindings/bindgen/emitter.rb
159
159
  - lib/milk_tea/bindings/bindgen/overrides.rb
160
160
  - lib/milk_tea/bindings/bindgen/type_mapper.rb
161
- - lib/milk_tea/bindings/cli.rb
162
161
  - lib/milk_tea/bindings/imported_bindings.rb
163
162
  - lib/milk_tea/bindings/imported_bindings/defaults.rb
164
163
  - lib/milk_tea/bindings/imported_bindings/generator.rb
@@ -185,7 +184,7 @@ files:
185
184
  - lib/milk_tea/core.rb
186
185
  - lib/milk_tea/core/ast.rb
187
186
  - lib/milk_tea/core/async_runtime_installer.rb
188
- - lib/milk_tea/core/binding_types.rb
187
+ - lib/milk_tea/core/bindings.rb
189
188
  - lib/milk_tea/core/bindings/attribute_binding.rb
190
189
  - lib/milk_tea/core/bindings/function_binding.rb
191
190
  - lib/milk_tea/core/bindings/module_binding.rb
@@ -203,9 +202,7 @@ files:
203
202
  - lib/milk_tea/core/c_backend/type_collectors.rb
204
203
  - lib/milk_tea/core/c_backend/type_declaration.rb
205
204
  - lib/milk_tea/core/c_backend/type_system.rb
206
- - lib/milk_tea/core/compatibility_helpers.rb
207
205
  - lib/milk_tea/core/compile_time.rb
208
- - lib/milk_tea/core/compile_time/const_eval.rb
209
206
  - lib/milk_tea/core/control_flow.rb
210
207
  - lib/milk_tea/core/control_flow/builder.rb
211
208
  - lib/milk_tea/core/control_flow/constant_propagation.rb
@@ -218,6 +215,7 @@ files:
218
215
  - lib/milk_tea/core/control_flow/termination.rb
219
216
  - lib/milk_tea/core/cst.rb
220
217
  - lib/milk_tea/core/cst_builder.rb
218
+ - lib/milk_tea/core/intrinsics.rb
221
219
  - lib/milk_tea/core/ir.rb
222
220
  - lib/milk_tea/core/keywords.rb
223
221
  - lib/milk_tea/core/lexer.rb
@@ -232,8 +230,8 @@ files:
232
230
  - lib/milk_tea/core/lexer/trivia.rb
233
231
  - lib/milk_tea/core/lowering.rb
234
232
  - lib/milk_tea/core/lowering/artifacts.rb
235
- - lib/milk_tea/core/lowering/async.rb
236
233
  - lib/milk_tea/core/lowering/async/analysis.rb
234
+ - lib/milk_tea/core/lowering/async/frame_builder.rb
237
235
  - lib/milk_tea/core/lowering/async/lowering.rb
238
236
  - lib/milk_tea/core/lowering/async/normalization.rb
239
237
  - lib/milk_tea/core/lowering/block.rb
@@ -253,7 +251,6 @@ files:
253
251
  - lib/milk_tea/core/lowering/utils.rb
254
252
  - lib/milk_tea/core/module_binder.rb
255
253
  - lib/milk_tea/core/module_loader.rb
256
- - lib/milk_tea/core/module_loader/errors.rb
257
254
  - lib/milk_tea/core/module_path_resolver.rb
258
255
  - lib/milk_tea/core/module_roots.rb
259
256
  - lib/milk_tea/core/parser.rb
@@ -294,7 +291,7 @@ files:
294
291
  - lib/milk_tea/core/types/registry.rb
295
292
  - lib/milk_tea/core/types/visitor.rb
296
293
  - lib/milk_tea/dap.rb
297
- - lib/milk_tea/dap/backends/lldb_dap.rb
294
+ - lib/milk_tea/dap/lldb_dap_backend.rb
298
295
  - lib/milk_tea/dap/protocol.rb
299
296
  - lib/milk_tea/dap/server.rb
300
297
  - lib/milk_tea/dap/server/breakpoints.rb
@@ -361,9 +358,32 @@ files:
361
358
  - lib/milk_tea/packages/version.rb
362
359
  - lib/milk_tea/tooling.rb
363
360
  - lib/milk_tea/tooling/asset_pack.rb
361
+ - lib/milk_tea/tooling/bindgen_cli.rb
364
362
  - lib/milk_tea/tooling/build.rb
365
363
  - lib/milk_tea/tooling/build_cache.rb
366
364
  - lib/milk_tea/tooling/cli.rb
365
+ - lib/milk_tea/tooling/cli/commands/bindgen.rb
366
+ - lib/milk_tea/tooling/cli/commands/build.rb
367
+ - lib/milk_tea/tooling/cli/commands/cache.rb
368
+ - lib/milk_tea/tooling/cli/commands/check.rb
369
+ - lib/milk_tea/tooling/cli/commands/command_base.rb
370
+ - lib/milk_tea/tooling/cli/commands/completions.rb
371
+ - lib/milk_tea/tooling/cli/commands/dap.rb
372
+ - lib/milk_tea/tooling/cli/commands/debug.rb
373
+ - lib/milk_tea/tooling/cli/commands/deps.rb
374
+ - lib/milk_tea/tooling/cli/commands/docs.rb
375
+ - lib/milk_tea/tooling/cli/commands/emit_c.rb
376
+ - lib/milk_tea/tooling/cli/commands/format.rb
377
+ - lib/milk_tea/tooling/cli/commands/lex.rb
378
+ - lib/milk_tea/tooling/cli/commands/lint.rb
379
+ - lib/milk_tea/tooling/cli/commands/lower.rb
380
+ - lib/milk_tea/tooling/cli/commands/lsp.rb
381
+ - lib/milk_tea/tooling/cli/commands/new.rb
382
+ - lib/milk_tea/tooling/cli/commands/parse.rb
383
+ - lib/milk_tea/tooling/cli/commands/run.rb
384
+ - lib/milk_tea/tooling/cli/commands/snapshot.rb
385
+ - lib/milk_tea/tooling/cli/commands/test.rb
386
+ - lib/milk_tea/tooling/cli/commands/toolchain.rb
367
387
  - lib/milk_tea/tooling/cst_formatter.rb
368
388
  - lib/milk_tea/tooling/debug_info_formatter.rb
369
389
  - lib/milk_tea/tooling/debug_map.rb
@@ -605,7 +625,7 @@ metadata:
605
625
  homepage_uri: https://teefan.github.io/mt-lang/
606
626
  source_code_uri: https://github.com/teefan/mt-lang
607
627
  post_install_message: |
608
- Milk Tea 0.3.16 installed!
628
+ Milk Tea 0.3.20 installed!
609
629
 
610
630
  System requirements:
611
631
  - A C compiler (gcc or clang) must be available on PATH
@@ -1,182 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "../types/layout"
4
-
5
- module MilkTea
6
- module ConstEval
7
-
8
- def self.evaluate(expression, resolve_identifier:, resolve_member_access:, resolve_type_ref: nil, resolve_call: nil)
9
- Evaluator.new(
10
- resolve_identifier:,
11
- resolve_member_access:,
12
- resolve_type_ref:,
13
- resolve_call:,
14
- ).evaluate(expression)
15
- end
16
-
17
- def self.equality_result(left, right)
18
- return left == right if left.is_a?(Numeric) && right.is_a?(Numeric)
19
- return left == right if left.is_a?(String) && right.is_a?(String)
20
- return left == right if boolean_value?(left) && boolean_value?(right)
21
- return left == right if left.is_a?(Types::Base) && right.is_a?(Types::Base)
22
-
23
- nil
24
- end
25
-
26
- def self.boolean_value?(value)
27
- value == true || value == false
28
- end
29
-
30
- class Evaluator
31
- def initialize(resolve_identifier:, resolve_member_access:, resolve_type_ref: nil, resolve_call: nil)
32
- @resolve_identifier = resolve_identifier
33
- @resolve_member_access = resolve_member_access
34
- @resolve_type_ref = resolve_type_ref
35
- @resolve_call = resolve_call
36
- end
37
-
38
- def evaluate(expression)
39
- case expression
40
- when AST::ErrorExpr
41
- nil
42
- when AST::ExpressionList
43
- expression.elements.filter_map { |element| evaluate(element) }
44
- when AST::IntegerLiteral, AST::FloatLiteral, AST::BooleanLiteral
45
- expression.value
46
- when AST::StringLiteral
47
- expression.value
48
- when AST::Identifier
49
- @resolve_identifier&.call(expression)
50
- when AST::MemberAccess
51
- @resolve_member_access&.call(expression)
52
- when AST::Call
53
- @resolve_call&.call(expression)
54
- when AST::Specialization
55
- @resolve_call&.call(expression)
56
- when AST::SizeofExpr
57
- type = resolve_layout_type(expression.type)
58
- type && Layout.size_of(type)
59
- when AST::AlignofExpr
60
- type = resolve_layout_type(expression.type)
61
- type && Layout.alignment_of(type)
62
- when AST::OffsetofExpr
63
- type = resolve_layout_type(expression.type)
64
- if type
65
- result = Layout.offset_of(type, expression.field)
66
- return result if result
67
-
68
- id_expr = AST::Identifier.new(name: expression.field)
69
- value = @resolve_identifier&.call(id_expr)
70
- if value.is_a?(Types::FieldHandle)
71
- return Layout.offset_of(type, value.field_name)
72
- end
73
- end
74
- nil
75
- when AST::UnaryOp
76
- evaluate_unary(expression)
77
- when AST::BinaryOp
78
- evaluate_binary(expression)
79
- when AST::IfExpr
80
- condition = evaluate(expression.condition)
81
- return unless ConstEval.boolean_value?(condition)
82
-
83
- evaluate(condition ? expression.then_expression : expression.else_expression)
84
- else
85
- nil
86
- end
87
- end
88
-
89
- def resolve_layout_type(type_ref)
90
- return unless @resolve_type_ref
91
-
92
- @resolve_type_ref.call(type_ref)
93
- end
94
-
95
- def evaluate_unary(expression)
96
- operand = evaluate(expression.operand)
97
-
98
- case expression.operator
99
- when "+"
100
- operand.is_a?(Numeric) ? operand : nil
101
- when "-"
102
- operand.is_a?(Numeric) ? -operand : nil
103
- when "~"
104
- operand.is_a?(Integer) ? ~operand : nil
105
- when "not"
106
- ConstEval.boolean_value?(operand) ? !operand : nil
107
- end
108
- end
109
-
110
- def evaluate_binary(expression)
111
- left = evaluate(expression.left)
112
-
113
- case expression.operator
114
- when "and"
115
- return unless ConstEval.boolean_value?(left)
116
- return false if left == false
117
-
118
- right = evaluate(expression.right)
119
- return right if ConstEval.boolean_value?(right)
120
-
121
- return nil
122
- when "or"
123
- return unless ConstEval.boolean_value?(left)
124
- return true if left == true
125
-
126
- right = evaluate(expression.right)
127
- return right if ConstEval.boolean_value?(right)
128
-
129
- return nil
130
- end
131
-
132
- right = evaluate(expression.right)
133
-
134
- case expression.operator
135
- when "=="
136
- ConstEval.equality_result(left, right)
137
- when "!="
138
- result = ConstEval.equality_result(left, right)
139
- result.nil? ? nil : !result
140
- when "+"
141
- left.is_a?(Numeric) && right.is_a?(Numeric) ? left + right : nil
142
- when "-"
143
- left.is_a?(Numeric) && right.is_a?(Numeric) ? left - right : nil
144
- when "*"
145
- left.is_a?(Numeric) && right.is_a?(Numeric) ? left * right : nil
146
- when "/"
147
- return unless left.is_a?(Numeric) && right.is_a?(Numeric)
148
- raise CompileTime::Error, "division by zero" if zero_numeric?(right)
149
-
150
- left / right
151
- when "%"
152
- return unless left.is_a?(Integer) && right.is_a?(Integer)
153
- raise CompileTime::Error, "modulo by zero" if right.zero?
154
-
155
- left % right
156
- when "<<"
157
- left.is_a?(Integer) && right.is_a?(Integer) ? left << right : nil
158
- when ">>"
159
- left.is_a?(Integer) && right.is_a?(Integer) ? left >> right : nil
160
- when "&"
161
- left.is_a?(Integer) && right.is_a?(Integer) ? left & right : nil
162
- when "|"
163
- left.is_a?(Integer) && right.is_a?(Integer) ? left | right : nil
164
- when "^"
165
- left.is_a?(Integer) && right.is_a?(Integer) ? left ^ right : nil
166
- when "<"
167
- left.is_a?(Numeric) && right.is_a?(Numeric) ? left < right : nil
168
- when "<="
169
- left.is_a?(Numeric) && right.is_a?(Numeric) ? left <= right : nil
170
- when ">"
171
- left.is_a?(Numeric) && right.is_a?(Numeric) ? left > right : nil
172
- when ">="
173
- left.is_a?(Numeric) && right.is_a?(Numeric) ? left >= right : nil
174
- end
175
- end
176
-
177
- def zero_numeric?(value)
178
- (value.is_a?(Integer) && value.zero?) || (value.is_a?(Float) && value.zero?)
179
- end
180
- end
181
- end
182
- end
@@ -1,23 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module MilkTea
4
- class ModuleLoadError < StandardError
5
- attr_reader :path, :line, :column
6
-
7
- def initialize(message, path:, line: nil, column: nil)
8
- @path = path
9
- @line = line
10
- @column = column
11
- super("#{message}: #{path}")
12
- end
13
-
14
- def code
15
- "module/error"
16
- end
17
- end
18
-
19
- class ModuleLoader
20
- ImportResolution = Data.define(:modules, :errors)
21
- ImportResolutionError = Data.define(:import, :error)
22
- end
23
- end
@@ -1,156 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "open3"
4
- require "thread"
5
- require "timeout"
6
-
7
- module MilkTea
8
- module DAP
9
- module Backends
10
- # Thin bridge to an lldb-dap compatible adapter process.
11
- class LLDBDAP
12
- def initialize(adapter_command: ["lldb-dap"], on_event: nil, on_request: nil)
13
- @adapter_command = adapter_command
14
- @on_event = on_event
15
- @on_request = on_request
16
- @protocol = nil
17
- @stdin = nil
18
- @stdout = nil
19
- @stderr = nil
20
- @wait_thread = nil
21
- @reader_thread = nil
22
- @stderr_thread = nil
23
- @write_mutex = Mutex.new
24
- @pending_mutex = Mutex.new
25
- @pending = {}
26
- @next_seq = 1
27
- end
28
-
29
- def start!
30
- return if running?
31
-
32
- @stdin, @stdout, @stderr, @wait_thread = Open3.popen3(*@adapter_command)
33
- @protocol = Protocol.new(input: @stdout, output: @stdin)
34
-
35
- @reader_thread = Thread.new { read_loop }
36
- @stderr_thread = Thread.new { drain_stderr }
37
- end
38
-
39
- def running?
40
- !@wait_thread.nil? && @wait_thread.alive?
41
- end
42
-
43
- def request(command, arguments = {}, timeout: 5)
44
- start! unless running?
45
-
46
- seq = next_seq
47
- queue = Queue.new
48
- @pending_mutex.synchronize do
49
- @pending[seq] = queue
50
- end
51
-
52
- @write_mutex.synchronize do
53
- @protocol.write_message({
54
- seq: seq,
55
- type: "request",
56
- command: command,
57
- arguments: arguments
58
- })
59
- end
60
-
61
- Timeout.timeout(timeout) { queue.pop }
62
- rescue Timeout::Error
63
- {
64
- "type" => "response",
65
- "request_seq" => seq,
66
- "success" => false,
67
- "message" => "backend request timed out: #{command}"
68
- }
69
- ensure
70
- @pending_mutex.synchronize { @pending.delete(seq) }
71
- end
72
-
73
- def stop!
74
- @stdin&.close
75
- @stdout&.close
76
- @stderr&.close
77
- if @wait_thread&.alive?
78
- Process.kill("TERM", @wait_thread.pid)
79
- end
80
- rescue StandardError
81
- nil
82
- ensure
83
- @wait_thread&.join(0.2)
84
- @reader_thread&.join(0.2)
85
- @stderr_thread&.join(0.2)
86
- @stdin = nil
87
- @stdout = nil
88
- @stderr = nil
89
- @wait_thread = nil
90
- @reader_thread = nil
91
- @stderr_thread = nil
92
- end
93
-
94
- def next_seq
95
- seq = @next_seq
96
- @next_seq += 1
97
- seq
98
- end
99
-
100
- def read_loop
101
- loop do
102
- message = @protocol.read_message
103
- break if message.nil?
104
-
105
- if message["type"] == "response"
106
- queue = @pending_mutex.synchronize { @pending[message["request_seq"]] }
107
- queue&.push(message)
108
- elsif message["type"] == "event"
109
- @on_event&.call(message)
110
- elsif message["type"] == "request"
111
- handle_adapter_request(message)
112
- end
113
- end
114
- rescue StandardError
115
- nil
116
- ensure
117
- @pending_mutex.synchronize do
118
- @pending.each_value do |queue|
119
- queue.push({
120
- "type" => "response",
121
- "success" => false,
122
- "message" => "backend closed"
123
- })
124
- end
125
- @pending.clear
126
- end
127
- end
128
-
129
- def drain_stderr
130
- return unless @stderr
131
-
132
- @stderr.each_line do |_line|
133
- # Intentionally ignored in this bridge layer.
134
- end
135
- rescue StandardError
136
- nil
137
- end
138
-
139
- def handle_adapter_request(message)
140
- response = @on_request&.call(message)
141
- response ||= {
142
- "type" => "response",
143
- "request_seq" => message["seq"],
144
- "success" => false,
145
- "command" => message["command"],
146
- "message" => "unsupported reverse request: #{message['command']}"
147
- }
148
-
149
- @write_mutex.synchronize do
150
- @protocol.write_message(response)
151
- end
152
- end
153
- end
154
- end
155
- end
156
- end