mt-lang 0.2.10 → 0.2.12

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: 9047d861f94f1e5b66f531712466e32779a0a86bd02db452e36cd8990980ee5c
4
- data.tar.gz: 3e9d1c7f06e70e2a9e3b84b8df4e8ee64b92be6e34f6bc970ca0b2ef69683c8e
3
+ metadata.gz: 28dc7f8c8824f11189bdd3cf704d10eefa2e144d466b218b5b34b1693531fe94
4
+ data.tar.gz: 73dcea75aeb6fb9c460e6b574e0bb64dc118ca9cd0a028586bd526d7b00acb49
5
5
  SHA512:
6
- metadata.gz: 4144e09654664b0dd4eaf7d697fe077381c965902564297d32002807be4b9100861ca8c7c7e065b983e90b91dba4b86f22f52eaa4eae47fa1d68dee1cb1acc36
7
- data.tar.gz: a712ee592463d961523bd2c8481be6993843f277c51bd3947f34bd8d3e32ae8d245ead8985f31d2621cefd8cc1ec705eba1749aca99324cdd3061adb5ef13ce2
6
+ metadata.gz: c3286442bbca94bd51b9c7aa4166f2b854d9f6bd48da3f6860648f303c30c90e39f2ac531315a5f13a148f3591eab1a5a02dabfd935f6ea136dfe0018012db9d
7
+ data.tar.gz: 53cc3240a7b226d152f831775e508a1db5c030f533d4fb6a88084f6564fcffa86954614e86b37f2c0b7650ae5ef27486e9aea05a6eaffe14b2aa5b2be9be0c8a
data/lib/milk_tea/base.rb CHANGED
@@ -3,7 +3,7 @@
3
3
  require "pathname"
4
4
 
5
5
  module MilkTea
6
- VERSION = "0.2.10"
6
+ VERSION = "0.2.12"
7
7
 
8
8
  def self.root
9
9
  @root ||= Pathname.new(File.expand_path("../..", __dir__))
@@ -87,6 +87,7 @@ module MilkTea
87
87
 
88
88
  def parse_local_decl(kind)
89
89
  line = previous.line
90
+ column = previous.column
90
91
  name_token = nil
91
92
  name = nil
92
93
  var_type = nil
@@ -145,7 +146,7 @@ module MilkTea
145
146
  consume_end_of_statement
146
147
  end
147
148
 
148
- AST::LocalDecl.new(kind:, name:, type: var_type, value:, else_binding:, else_body:, line:, column: name_token&.column || line, destructure_bindings:, destructure_type_name:)
149
+ AST::LocalDecl.new(kind:, name:, type: var_type, value:, else_binding:, else_body:, line:, column: name_token&.column || column, destructure_bindings:, destructure_type_name:)
149
150
  rescue ParseError => e
150
151
  raise unless @recovery_errors && name
151
152
 
@@ -224,6 +224,76 @@ module MilkTea
224
224
  },
225
225
  }.freeze
226
226
 
227
+ BUILTIN_TYPE_DOCS = {
228
+ 'bool' => '1-byte boolean: `true` or `false`.',
229
+ 'byte' => '8-bit signed integer. Range: -128 to 127.',
230
+ 'ubyte' => '8-bit unsigned integer. Range: 0 to 255. Also used for `char` literals like `\'A\'`.',
231
+ 'char' => '8-bit character type (alias for `ubyte`).',
232
+ 'short' => '16-bit signed integer. Range: -32,768 to 32,767.',
233
+ 'ushort' => '16-bit unsigned integer. Range: 0 to 65,535.',
234
+ 'int' => '32-bit signed integer. Range: -2,147,483,648 to 2,147,483,647. Default enum backing type.',
235
+ 'uint' => '32-bit unsigned integer. Range: 0 to 4,294,967,295.',
236
+ 'long' => '64-bit signed integer.',
237
+ 'ulong' => '64-bit unsigned integer.',
238
+ 'ptr_int' => 'Pointer-sized signed integer. Width matches the target platform pointer size.',
239
+ 'ptr_uint' => 'Pointer-sized unsigned integer. Return type for `size_of`, `align_of`, `offset_of`.',
240
+ 'float' => '32-bit IEEE 754 single-precision float.',
241
+ 'double' => '64-bit IEEE 754 double-precision float.',
242
+ 'void' => 'Empty type for functions with no return value. Not a storable type.',
243
+ 'str' => 'Non-owning UTF-8 string view (pointer + length). Not null-terminated.',
244
+ 'cstr' => 'Null-terminated C string. Used at FFI boundaries.',
245
+ 'vec2' => '2-component float vector. Fields: `.x`, `.y`. Supports component-wise arithmetic.',
246
+ 'vec3' => '3-component float vector. Fields: `.x`, `.y`, `.z`. Supports component-wise arithmetic and `dot`/`cross`/`length` via `std.linear_algebra`.',
247
+ 'vec4' => '4-component float vector. Fields: `.x`, `.y`, `.z`, `.w`. Supports component-wise arithmetic.',
248
+ 'ivec2' => '2-component integer vector. Fields: `.x`, `.y`. Supports component-wise arithmetic.',
249
+ 'ivec3' => '3-component integer vector. Fields: `.x`, `.y`, `.z`. Supports component-wise arithmetic.',
250
+ 'ivec4' => '4-component integer vector. Fields: `.x`, `.y`, `.z`, `.w`. Supports component-wise arithmetic.',
251
+ 'mat3' => '3×3 column-major float matrix. Columns: `.col0`–`.col2` (each `vec3`). Supports `identity`, `transpose` via `std.linear_algebra`.',
252
+ 'mat4' => '4×4 column-major float matrix. Columns: `.col0`–`.col3` (each `vec4`). Supports `identity`, `transpose` via `std.linear_algebra`.',
253
+ 'quat' => 'Quaternion. Fields: `.x`, `.y`, `.z`, `.w`. Layout-compatible with `vec4`. Supports `identity`, `conjugate` via `std.linear_algebra`.',
254
+ 'ptr' => 'Generic pointer type: `ptr[T]`. Raw mutable pointer. Requires `unsafe` for indexing, dereference, and arithmetic.',
255
+ 'const_ptr' => 'Read-only pointer type: `const_ptr[T]`. Immutable pointer, does not require `unsafe` for dereference.',
256
+ 'own' => 'Owning heap pointer: `own[T]`. Auto-dereferences like `ref`. Storable, returnable, and nullable. Allocated via `heap.must_alloc[T](count)`.',
257
+ 'ref' => 'Non-null borrow reference: `ref[T]`. Auto-dereferences for member access and method calls. Cannot be stored in module variables or constants.',
258
+ 'span' => 'Borrowed pointer-plus-length view: `span[T]`. Constructed via `span[T](data = ..., len = ...)`. Arrays coerce implicitly.',
259
+ 'array' => 'Fixed-length array: `array[T, N]`. Constructed via `array[T, N](elements...)`. Omitted trailing elements default to zero.',
260
+ 'str_buffer' => 'Fixed-capacity mutable UTF-8 text buffer: `str_buffer[N]`. Methods: `assign`, `append`, `assign_format`, `append_format`, `clear`, `as_str`, `as_cstr`.',
261
+ 'atomic' => 'Atomic value for lock-free concurrent access: `atomic[T]`. `T` must be a primitive integer or `bool`. Methods: `load`, `store`, `add`, `sub`, `exchange`. Uses C11 `_Atomic`.',
262
+ 'Task' => 'Async task future: `Task[T]`. Returned by `async function`. Use `await` to unwrap, or `aio.wait`/`aio.run` to drive.',
263
+ 'Option' => 'Built-in optional type: `Option[T]`. Arms: `some(value: T)` and `none`. Use `let ... else:` or `?` for safe unwrapping.',
264
+ 'Result' => 'Built-in result type: `Result[T, E]`. Arms: `success(value: T)` and `failure(error: E)`. Use `let ... else:` or `?` for error propagation.',
265
+ 'SoA' => 'Struct-of-Arrays: `SoA[T, N]`. Each struct field becomes a separate array of length `N`. Access `soa[i].field` reads from column `field` at row `i`.',
266
+ 'struct_handle' => 'Compile-time handle for a struct type. Obtained via reflection builtins like `fields_of`.',
267
+ 'field_handle' => 'Compile-time handle for a struct field. Exposes `.name` and `.type`. Obtained via `field_of` and `fields_of`.',
268
+ 'callable_handle' => 'Compile-time handle for a callable declaration. Obtained via `callable_of`. Used with `has_attribute`, `attribute_of`.',
269
+ 'attribute_handle' => 'Compile-time handle for an applied attribute. Obtained via `attribute_of` and `attributes_of`. Use `attribute_arg[T]` to read arguments.',
270
+ 'member_handle' => 'Compile-time handle for an enum or flags member. Exposes `.name` and `.value`. Obtained via `members_of`.',
271
+ 'EventError' => 'Built-in enum returned when event listener capacity is exhausted. Single member: `full`.',
272
+ 'Subscription' => 'Opaque handle returned by `event.subscribe`. Pass to `event.unsubscribe` to remove a listener.',
273
+ }.freeze
274
+
275
+ BUILTIN_TYPE_METHOD_SIGNATURES = {
276
+ 'atomic' => {
277
+ 'load' => 'function load() -> T',
278
+ 'store' => 'static function store(value: T) -> void',
279
+ 'add' => 'static function add(value: T) -> T',
280
+ 'sub' => 'static function sub(value: T) -> T',
281
+ 'exchange' => 'static function exchange(value: T) -> T',
282
+ 'compare_exchange' => 'static function compare_exchange(expected: T, desired: T) -> bool',
283
+ },
284
+ 'str_buffer' => {
285
+ 'assign' => 'static function assign(value: str) -> void',
286
+ 'append' => 'static function append(value: str) -> void',
287
+ 'assign_format' => 'static function assign_format(fmt: str) -> void',
288
+ 'append_format' => 'static function append_format(fmt: str) -> void',
289
+ 'clear' => 'static function clear() -> void',
290
+ 'len' => 'static function len() -> ptr_uint',
291
+ 'capacity' => 'static function capacity() -> ptr_uint',
292
+ 'as_str' => 'static function as_str() -> str',
293
+ 'as_cstr' => 'static function as_cstr() -> cstr',
294
+ },
295
+ }.freeze
296
+
227
297
  def handle_hover(params)
228
298
  stages = new_perf_stages
229
299
  total_start = stages ? monotonic_time : nil
@@ -238,7 +308,16 @@ module MilkTea
238
308
  token_kind = token&.type || :none
239
309
  unless token&.type == :identifier
240
310
  info = builtin_keyword_hover_info(token)
241
- return info if info
311
+ if info
312
+ result_state = 'hit'
313
+ return {
314
+ contents: {
315
+ kind: 'markdown',
316
+ value: render_hover_markdown(info)
317
+ },
318
+ range: token_to_range(token)
319
+ }
320
+ end
242
321
 
243
322
  result_state = 'not-identifier'
244
323
  return nil
@@ -369,6 +448,7 @@ module MilkTea
369
448
  elsif facts.types.key?(name)
370
449
  type = facts.types[name]
371
450
  signature = type_hover_signature(name, type)
451
+ docs ||= BUILTIN_TYPE_DOCS[name]
372
452
  elsif (binding = facts.values[name])
373
453
  signature = value_hover_signature(binding)
374
454
  elsif (import_binding = facts.imports[name])
@@ -386,6 +466,7 @@ module MilkTea
386
466
  signature = value_hover_signature(val)
387
467
  elsif module_binding.types.key?(name)
388
468
  signature = "type #{name}"
469
+ docs ||= BUILTIN_TYPE_DOCS[name]
389
470
  elsif (binding = module_binding.interfaces[name])
390
471
  signature = interface_signature(binding)
391
472
  source_location = module_member_definition_location(uri, module_binding.name, name)
@@ -406,6 +487,27 @@ module MilkTea
406
487
  end
407
488
  end
408
489
 
490
+ unless signature
491
+ if dot_receiver
492
+ receiver_name = dot_receiver
493
+ receiver_binding = resolve_local_hover_binding(facts, receiver_name, lsp_line + 1, lsp_char + 1) ||
494
+ facts.values[receiver_name] ||
495
+ facts.functions[receiver_name]
496
+ if receiver_binding && receiver_binding.type
497
+ receiver_type = receiver_binding.respond_to?(:storage_type) ? receiver_binding.storage_type : receiver_binding.type
498
+ methods = methods_for_receiver_type(facts, receiver_type)
499
+ if (method_binding = methods[name])
500
+ signature = method_signature(method_binding)
501
+ else
502
+ type_base = receiver_type.to_s[/^([a-z_]+)/, 1]
503
+ if type_base && (method_sigs = BUILTIN_TYPE_METHOD_SIGNATURES[type_base])
504
+ signature = method_sigs[name]
505
+ end
506
+ end
507
+ end
508
+ end
509
+ end
510
+
409
511
  unless signature
410
512
  if token_index && (builtin_info = builtin_hover_info(name, tokens, token_index))
411
513
  signature = builtin_info[:signature]
@@ -414,14 +516,16 @@ module MilkTea
414
516
  end
415
517
 
416
518
  unless signature
417
- local_def = @workspace.find_definition_token_global(
418
- name,
419
- preferred_uri: uri,
420
- before_line: lsp_line + 1,
421
- before_char: lsp_char + 1,
422
- )
423
- if local_def
424
- signature = resolve_lexical_local_hover_signature(local_def[:uri], name, local_def[:token])
519
+ unless token_index && tokens && tokens[previous_non_trivia_token_index(tokens, token_index)]&.type == :dot
520
+ local_def = @workspace.find_definition_token_global(
521
+ name,
522
+ preferred_uri: uri,
523
+ before_line: lsp_line + 1,
524
+ before_char: lsp_char + 1,
525
+ )
526
+ if local_def
527
+ signature = resolve_lexical_local_hover_signature(local_def[:uri], name, local_def[:token])
528
+ end
425
529
  end
426
530
  end
427
531
  end
@@ -1335,7 +1439,7 @@ module MilkTea
1335
1439
  end
1336
1440
 
1337
1441
  def builtin_type_constructor_hover_info(name, tokens, token_index)
1338
- return nil unless %w[array span Option Result SoA].include?(name)
1442
+ return nil unless %w[array span Option Result SoA str_buffer].include?(name)
1339
1443
 
1340
1444
  lbracket_index = next_non_trivia_token_index(tokens, token_index + 1)
1341
1445
  return nil unless lbracket_index && tokens[lbracket_index].type == :lbracket
@@ -1387,8 +1491,10 @@ module MilkTea
1387
1491
  when 'Option'
1388
1492
  '`Option[T]` is the built-in optional value type with `some(value = ...)` and `none` arms.'
1389
1493
  when 'Result'
1390
- '`Result[T, E]` is the built-in success/failure type with `success(value = ...)` and `failure(error = ...)` arms.'
1391
- end
1494
+ '`Result[T, E]` is the built-in success/failure type with `success(value = ...)` and `failure(error = ...)` arms.'
1495
+ when 'str_buffer'
1496
+ '`str_buffer[N]` is a fixed-capacity mutable UTF-8 text buffer. Methods: `assign`, `append`, `assign_format`, `append_format`, `clear`, `len`, `as_str`, `as_cstr`.'
1497
+ end
1392
1498
 
1393
1499
  {
1394
1500
  signature: "builtin type #{specialization}",
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.2.10
4
+ version: 0.2.12
5
5
  platform: ruby
6
6
  authors:
7
7
  - Long (Teefan) Tran
@@ -583,7 +583,7 @@ metadata:
583
583
  homepage_uri: https://teefan.github.io/mt-lang/
584
584
  source_code_uri: https://github.com/teefan/mt-lang
585
585
  post_install_message: |
586
- Milk Tea 0.2.10 installed!
586
+ Milk Tea 0.2.12 installed!
587
587
 
588
588
  System requirements:
589
589
  - A C compiler (gcc or clang) must be available on PATH