mt-lang 0.3.17 → 0.3.22

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 (57) hide show
  1. checksums.yaml +4 -4
  2. data/lib/milk_tea/base.rb +1 -1
  3. data/lib/milk_tea/core/c_backend/expressions.rb +34 -23
  4. data/lib/milk_tea/core/c_backend/feature_detection.rb +25 -45
  5. data/lib/milk_tea/core/c_backend/type_collectors.rb +18 -30
  6. data/lib/milk_tea/core/c_backend/type_declaration.rb +0 -6
  7. data/lib/milk_tea/core/c_backend.rb +49 -39
  8. data/lib/milk_tea/core/compile_time.rb +98 -72
  9. data/lib/milk_tea/core/control_flow/builder.rb +2 -1
  10. data/lib/milk_tea/core/intrinsics.rb +7 -0
  11. data/lib/milk_tea/core/lexer.rb +46 -35
  12. data/lib/milk_tea/core/lowering/block.rb +9 -0
  13. data/lib/milk_tea/core/lowering/calls.rb +2 -0
  14. data/lib/milk_tea/core/lowering/declarations.rb +1 -1
  15. data/lib/milk_tea/core/lowering/functions.rb +11 -8
  16. data/lib/milk_tea/core/lowering/resolve.rb +11 -4
  17. data/lib/milk_tea/core/lowering/scans.rb +13 -18
  18. data/lib/milk_tea/core/module_binder.rb +19 -15
  19. data/lib/milk_tea/core/module_loader.rb +212 -59
  20. data/lib/milk_tea/core/module_path_resolver.rb +8 -7
  21. data/lib/milk_tea/core/parser/declarations.rb +43 -19
  22. data/lib/milk_tea/core/parser/expressions.rb +5 -8
  23. data/lib/milk_tea/core/parser/statements.rb +5 -5
  24. data/lib/milk_tea/core/parser.rb +26 -0
  25. data/lib/milk_tea/core/semantic_analyzer/calls.rb +24 -31
  26. data/lib/milk_tea/core/semantic_analyzer/expressions.rb +20 -23
  27. data/lib/milk_tea/core/semantic_analyzer/name_resolution.rb +146 -92
  28. data/lib/milk_tea/core/semantic_analyzer/statements.rb +19 -41
  29. data/lib/milk_tea/core/semantic_analyzer.rb +56 -37
  30. data/lib/milk_tea/core/types.rb +12 -17
  31. data/lib/milk_tea/lsp/diagnostics.rb +13 -0
  32. data/lib/milk_tea/lsp/server/semantic_tokens.rb +6 -0
  33. data/lib/milk_tea/tooling/cli/commands/bindgen.rb +11 -0
  34. data/lib/milk_tea/tooling/cli/commands/build.rb +37 -0
  35. data/lib/milk_tea/tooling/cli/commands/cache.rb +46 -0
  36. data/lib/milk_tea/tooling/cli/commands/check.rb +106 -0
  37. data/lib/milk_tea/tooling/cli/commands/command_base.rb +8 -0
  38. data/lib/milk_tea/tooling/cli/commands/completions.rb +48 -0
  39. data/lib/milk_tea/tooling/cli/commands/dap.rb +58 -0
  40. data/lib/milk_tea/tooling/cli/commands/debug.rb +77 -0
  41. data/lib/milk_tea/tooling/cli/commands/deps.rb +17 -0
  42. data/lib/milk_tea/tooling/cli/commands/docs.rb +58 -0
  43. data/lib/milk_tea/tooling/cli/commands/emit_c.rb +64 -0
  44. data/lib/milk_tea/tooling/cli/commands/format.rb +199 -0
  45. data/lib/milk_tea/tooling/cli/commands/lex.rb +46 -0
  46. data/lib/milk_tea/tooling/cli/commands/lint.rb +248 -0
  47. data/lib/milk_tea/tooling/cli/commands/lower.rb +50 -0
  48. data/lib/milk_tea/tooling/cli/commands/lsp.rb +43 -0
  49. data/lib/milk_tea/tooling/cli/commands/new.rb +26 -0
  50. data/lib/milk_tea/tooling/cli/commands/parse.rb +51 -0
  51. data/lib/milk_tea/tooling/cli/commands/run.rb +99 -0
  52. data/lib/milk_tea/tooling/cli/commands/snapshot.rb +117 -0
  53. data/lib/milk_tea/tooling/cli/commands/test.rb +557 -0
  54. data/lib/milk_tea/tooling/cli/commands/toolchain.rb +16 -0
  55. data/lib/milk_tea/tooling/cli.rb +101 -1893
  56. data/lib/milk_tea/tooling/sexpr_dumper.rb +7 -7
  57. metadata +24 -2
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MilkTea
4
+ class CLI
5
+ module CommandParse
6
+ def parse_command
7
+ sexpr = false
8
+ args = @argv.dup
9
+ @argv = []
10
+ until args.empty?
11
+ arg = args.shift
12
+ if arg == "--sexpr"
13
+ sexpr = true
14
+ next
15
+ end
16
+ @argv << arg
17
+ end
18
+
19
+ unless @argv.any?
20
+ @err.puts("missing source file path")
21
+ print_usage(@err)
22
+ return 1
23
+ end
24
+
25
+ resolution = extract_resolution_flags!
26
+ input_paths = @argv.dup
27
+ return 1 unless ensure_known_source_operands!("parse", input_paths)
28
+
29
+ paths = expand_source_paths(input_paths)
30
+ return 0 if print_no_source_files_if_empty(paths, input_paths)
31
+
32
+ ensure_current_lockfiles!(paths) if resolution[:frozen]
33
+
34
+ multiple = paths.length > 1
35
+ paths.each_with_index do |path, index|
36
+ ast = make_module_loader(path, locked: resolution[:locked], platform: ModuleLoader.default_host_platform).load_file(path)
37
+ if multiple
38
+ @out.puts("# --- #{path} ---") unless sexpr
39
+ end
40
+ if sexpr
41
+ @out.puts(SexprDumper.dump_ast(ast))
42
+ else
43
+ @out.write(PrettyPrinter.format_ast(ast))
44
+ end
45
+ @out.puts if multiple && index < paths.length - 1
46
+ end
47
+ 0
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,99 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MilkTea
4
+ class CLI
5
+ module CommandRun
6
+ def run_command
7
+ path, options = extract_path_and_options
8
+ return 1 unless path
9
+
10
+ run_and_print_result(path, options)
11
+ end
12
+
13
+ def app_command
14
+ options = parse_build_options
15
+ return 1 unless options
16
+
17
+ module_name = @argv.shift
18
+ unless module_name
19
+ @err.puts("missing module name")
20
+ print_usage(@err)
21
+ return 1
22
+ end
23
+
24
+ path = resolve_app_module(module_name)
25
+ unless path
26
+ @err.puts("run-module module not found: #{module_name}")
27
+ return 1
28
+ end
29
+
30
+ frozen = options.delete(:frozen)
31
+ ensure_current_lockfile!(path) if frozen
32
+
33
+ run_and_print_result(path, options)
34
+ end
35
+
36
+ def extract_path_and_options(allow_clean: false)
37
+ options = parse_build_options(allow_clean:)
38
+ return nil unless options
39
+
40
+ path = @argv.shift
41
+ unless path
42
+ if File.file?(File.join(Dir.pwd, "package.toml"))
43
+ path = Dir.pwd
44
+ else
45
+ @err.puts("missing source file path")
46
+ print_usage(@err)
47
+ return nil
48
+ end
49
+ end
50
+
51
+ [path, options]
52
+ end
53
+
54
+ def run_and_print_result(path, options)
55
+ frozen = options.delete(:frozen)
56
+ ensure_current_lockfile!(path) if frozen
57
+ locked = options.delete(:locked)
58
+ package_graph = package_graph_for(path, locked:)
59
+ preview_notice_emitted = false
60
+ preview_started = lambda do |message|
61
+ preview_notice_emitted = true
62
+ @out.write(message)
63
+ @out.flush if @out.respond_to?(:flush)
64
+ end
65
+
66
+ result = Run.run(
67
+ path,
68
+ module_roots: module_roots_for(path, locked:),
69
+ package_graph:,
70
+ frontend: @build_frontend,
71
+ preview_started:,
72
+ argv: @argv.dup,
73
+ **options.except(:timings)
74
+ )
75
+ unless @out.equal?($stdout) || preview_notice_emitted
76
+ @out.write(result.stdout)
77
+ end
78
+ @out.flush if @out.respond_to?(:flush)
79
+ @err.write(result.stderr) unless @err.equal?($stderr)
80
+ info("[cached]") if result.cached
81
+ result.exit_status
82
+ end
83
+
84
+ def resolve_app_module(name)
85
+ relative = name.tr(".", "/").sub(%r{^/}, "") + ".mt"
86
+
87
+ module_roots_for(Dir.pwd).each do |root|
88
+ candidate = File.join(root, "std", relative)
89
+ return File.expand_path(candidate) if File.file?(candidate)
90
+
91
+ candidate = File.join(root, relative)
92
+ return File.expand_path(candidate) if File.file?(candidate)
93
+ end
94
+
95
+ nil
96
+ end
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,117 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MilkTea
4
+ class CLI
5
+ module CommandSnapshot
6
+ def snapshot_command
7
+ input_path = nil
8
+ theme_path = nil
9
+ output_path = nil
10
+ textmate_only = false
11
+
12
+ until @argv.empty?
13
+ arg = @argv.first
14
+ case arg
15
+ when "--theme", "-t"
16
+ @argv.shift
17
+ theme_path = @argv.shift
18
+ unless theme_path
19
+ @err.puts("snapshot: missing value for --theme")
20
+ return 1
21
+ end
22
+ when "--output", "-o"
23
+ @argv.shift
24
+ output_path = @argv.shift
25
+ unless output_path
26
+ @err.puts("snapshot: missing value for --output")
27
+ return 1
28
+ end
29
+ when "--textmate-only"
30
+ @argv.shift
31
+ textmate_only = true
32
+ else
33
+ if arg.start_with?("-")
34
+ @err.puts("snapshot: unknown option #{arg}")
35
+ return 1
36
+ end
37
+ unless input_path
38
+ input_path = @argv.shift
39
+ else
40
+ @err.puts("snapshot: unexpected argument #{@argv.shift}")
41
+ return 1
42
+ end
43
+ end
44
+ end
45
+
46
+ unless input_path
47
+ @err.puts("snapshot: missing source file path")
48
+ print_usage(@err)
49
+ return 1
50
+ end
51
+
52
+ unless File.file?(input_path)
53
+ @err.puts("snapshot: source file not found: #{input_path}")
54
+ return 1
55
+ end
56
+
57
+ input_path = File.expand_path(input_path)
58
+ theme_path = File.expand_path(theme_path) if theme_path
59
+ output_path = File.expand_path(output_path) if output_path
60
+
61
+ if theme_path && !File.file?(theme_path)
62
+ @err.puts("snapshot: theme file not found: #{theme_path}")
63
+ return 1
64
+ end
65
+
66
+ snapshot_script = MilkTea.root.join("bindings/vscode/scripts/snapshot.js").to_s
67
+ unless File.file?(snapshot_script)
68
+ @err.puts("snapshot: internal script not found at #{snapshot_script}")
69
+ return 1
70
+ end
71
+
72
+ args = ["node", snapshot_script, input_path]
73
+ args.push("-t", theme_path) if theme_path
74
+ args.push("-o", output_path) if output_path
75
+
76
+ semantic_result = nil
77
+ unless textmate_only
78
+ begin
79
+ semantic_result = MilkTea::LSP::Server.semantic_tokens_for_path(input_path)
80
+ rescue => e
81
+ @err.puts("snapshot: semantic analysis skipped: #{e.message}")
82
+ end
83
+ end
84
+
85
+ if semantic_result && semantic_result[:entries] && !semantic_result[:entries].empty?
86
+ source = File.read(input_path)
87
+ lines = source.split("\n", -1)
88
+ semantic_result[:entries].each do |entry|
89
+ byte_start = entry[:startChar]
90
+ byte_len = entry[:length]
91
+ line_text = lines[entry[:line]]
92
+ unless line_text && byte_start && byte_len
93
+ entry[:startChar] = 0
94
+ entry[:length] = 0
95
+ next
96
+ end
97
+ char_start = line_text.byteslice(0, byte_start).length
98
+ char_length = line_text.byteslice(byte_start, byte_len).length
99
+ char_length = line_text.length - char_start if char_start + char_length > line_text.length
100
+ entry[:startChar] = char_start
101
+ entry[:length] = char_length
102
+ end
103
+
104
+ temp = Tempfile.new(["mt_semantic", ".json"])
105
+ temp.write(JSON.generate(semantic_result[:entries]))
106
+ temp.close
107
+ args.push("-s", temp.path)
108
+ system(*args)
109
+ temp.unlink
110
+ else
111
+ system(*args)
112
+ end
113
+ $?.success? ? 0 : 1
114
+ end
115
+ end
116
+ end
117
+ end