mt-lang 0.2.14 → 0.2.16

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: 684d2aada4af1e2b5fc1c0685e26004ed9442931692cb25007777b09df77dbe5
4
- data.tar.gz: 5f16c0ce02404a51f4ac8dd8c12b8047fb4ae5ab442b1269ba7ce8c58809a065
3
+ metadata.gz: 63970cb18bb8d90aee1270f838e8a6520c0f4bce08871f36ffc53f9cbf11c8a0
4
+ data.tar.gz: f0faadd64e77babdde7b98fa2866681d7d8de8749dfb9d5e312a856be795b68d
5
5
  SHA512:
6
- metadata.gz: 9e129d1a7a428094755af01cb5bb98c29fb78ee9003b6938cb4335eb0e58763804a9e1c902f5d1563111a20c7b70ca69f4497f11c4cf476ed5b9ef8696ccc9ed
7
- data.tar.gz: ffc46a4a1658c84a2fa6d2d7d6331b98164487c488112055adc9a2f20367074f26a02002d0a36ec493f9f9738ac2123f80a2e1e04fbaa5b364a54509898a2644
6
+ metadata.gz: 03fb4af02f332e10f66abe76fd5e79a701f9a29ef91bfd0670e0988e0fd6e82e1424432f3d163b4d8f80330269c0484cc8f54cd20a521d1889e44fa9ecc138ed
7
+ data.tar.gz: a40c9ba93dfeb52a6752f33cba2365e4f941f1f7bee992ddb80eb6702f051b3830acbf79cce8c0c1bc6f3fe2a99d15d21ca827e1f3d9ef0e03c446dca8ead2d8
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.14"
6
+ VERSION = "0.2.16"
7
7
 
8
8
  def self.root
9
9
  @root ||= Pathname.new(File.expand_path("../..", __dir__))
@@ -302,6 +302,161 @@ module MilkTea
302
302
  end
303
303
  end
304
304
 
305
+ # Names recognised as builtin callable / type-constructor identifiers by
306
+ # resolve_callable and the compile-time evaluation path. We allow these
307
+ # so the generic-name check does not flag them as unknown before the full
308
+ # type checker has a chance to handle the surrounding Specialization /
309
+ # Call context.
310
+ BUILTIN_CALLABLE_NAMES = %w[
311
+ fatal ref_of const_ptr_of read ptr_of
312
+ field_of fields_of callable_of attribute_of has_attribute
313
+ members_of attributes_of get
314
+ reinterpret array span zero default hash equal order
315
+ adapt attribute_arg
316
+ Task Option Result SoA str_buffer atomic
317
+ ].to_set.freeze
318
+
319
+ # Verifies that every bare identifier used as a value expression inside
320
+ # a generic method body resolves to a known name (parameter, local,
321
+ # top-level value, function, type, import, or type parameter). This
322
+ # catches misspelled variables and undeclared names without touching any
323
+ # type-dependent logic, so it is safe to run during structural analysis
324
+ # before concrete types are substituted.
325
+ def check_generic_method_names(binding, scopes)
326
+ names = Set.new
327
+ binding.ast.body&.each do |statement|
328
+ check_stmt_names(statement, scopes, binding, names)
329
+ end
330
+ end
331
+
332
+ def check_stmt_names(stmt, scopes, binding, names)
333
+ case stmt
334
+ when AST::LocalDecl
335
+ check_expr_names(stmt.value, scopes, binding, names) if stmt.value
336
+ names.add(stmt.name) if stmt.name
337
+ when AST::Assignment
338
+ check_expr_names(stmt.target, scopes, binding, names)
339
+ check_expr_names(stmt.value, scopes, binding, names)
340
+ when AST::ExpressionStmt
341
+ check_expr_names(stmt.expression, scopes, binding, names)
342
+ when AST::ReturnStmt
343
+ check_expr_names(stmt.value, scopes, binding, names) if stmt.value
344
+ when AST::IfStmt
345
+ stmt.branches.each do |b|
346
+ check_expr_names(b.condition, scopes, binding, names)
347
+ branch_names = names.dup
348
+ b.body&.each { |s| check_stmt_names(s, scopes, binding, branch_names) }
349
+ end
350
+ else_names = names.dup
351
+ stmt.else_body&.each { |s| check_stmt_names(s, scopes, binding, else_names) }
352
+ when AST::WhileStmt
353
+ check_expr_names(stmt.condition, scopes, binding, names)
354
+ body_names = names.dup
355
+ stmt.body&.each { |s| check_stmt_names(s, scopes, binding, body_names) }
356
+ when AST::ForStmt
357
+ Array(stmt.iterables).each { |i| check_expr_names(i, scopes, binding, names) }
358
+ body_names = names.dup
359
+ Array(stmt.bindings).each { |b| body_names.add(b.respond_to?(:name) ? b.name : b) }
360
+ stmt.body&.each { |s| check_stmt_names(s, scopes, binding, body_names) }
361
+ when AST::MatchStmt
362
+ check_expr_names(stmt.expression, scopes, binding, names)
363
+ stmt.arms.each do |arm|
364
+ arm_names = names.dup
365
+ arm_names.add(arm.binding_name) if arm.binding_name
366
+ arm.body&.each { |s| check_stmt_names(s, scopes, binding, arm_names) }
367
+ end
368
+ when AST::UnsafeStmt, AST::ParallelBlockStmt
369
+ body_names = names.dup
370
+ stmt.body&.each { |s| check_stmt_names(s, scopes, binding, body_names) }
371
+ when AST::DeferStmt
372
+ check_expr_names(stmt.expression, scopes, binding, names) if stmt.expression
373
+ body_names = names.dup
374
+ stmt.body&.each { |s| check_stmt_names(s, scopes, binding, body_names) }
375
+ when AST::WhenStmt
376
+ check_expr_names(stmt.discriminant, scopes, binding, names)
377
+ stmt.branches.each do |b|
378
+ branch_names = names.dup
379
+ b.body&.each { |s| check_stmt_names(s, scopes, binding, branch_names) }
380
+ end
381
+ else_names = names.dup
382
+ stmt.else_body&.each { |s| check_stmt_names(s, scopes, binding, else_names) }
383
+ when AST::ErrorBlockStmt
384
+ body_names = names.dup
385
+ stmt.body&.each { |s| check_stmt_names(s, scopes, binding, body_names) }
386
+ when AST::BreakStmt, AST::ContinueStmt, AST::PassStmt, AST::StaticAssert, AST::EmitStmt
387
+ nil
388
+ end
389
+ end
390
+
391
+ def check_expr_names(expr, scopes, binding, names)
392
+ case expr
393
+ when AST::Identifier
394
+ check_generic_name(expr.name, scopes, binding, expr, names)
395
+ when AST::MemberAccess
396
+ check_expr_names(expr.receiver, scopes, binding, names)
397
+ when AST::Call
398
+ check_expr_names(expr.callee, scopes, binding, names)
399
+ expr.arguments.each { |arg| check_expr_names(arg.value, scopes, binding, names) }
400
+ when AST::BinaryOp
401
+ check_expr_names(expr.left, scopes, binding, names)
402
+ check_expr_names(expr.right, scopes, binding, names)
403
+ when AST::UnaryOp
404
+ check_expr_names(expr.operand, scopes, binding, names)
405
+ when AST::IfExpr
406
+ check_expr_names(expr.condition, scopes, binding, names)
407
+ check_expr_names(expr.then_expression, scopes, binding, names)
408
+ check_expr_names(expr.else_expression, scopes, binding, names)
409
+ when AST::MatchExpr
410
+ check_expr_names(expr.expression, scopes, binding, names)
411
+ expr.arms.each do |arm|
412
+ arm_names = names.dup
413
+ arm_names.add(arm.binding_name) if arm.binding_name
414
+ check_expr_names(arm.value, scopes, binding, arm_names)
415
+ end
416
+ when AST::IndexAccess
417
+ check_expr_names(expr.receiver, scopes, binding, names)
418
+ check_expr_names(expr.index, scopes, binding, names)
419
+ when AST::Specialization
420
+ check_expr_names(expr.callee, scopes, binding, names)
421
+ when AST::PrefixCast
422
+ check_expr_names(expr.expression, scopes, binding, names)
423
+ when AST::AwaitExpr
424
+ check_expr_names(expr.expression, scopes, binding, names)
425
+ when AST::UnsafeExpr
426
+ check_expr_names(expr.expression, scopes, binding, names)
427
+ when AST::RangeExpr
428
+ check_expr_names(expr.start_expr, scopes, binding, names) if expr.start_expr
429
+ check_expr_names(expr.end_expr, scopes, binding, names) if expr.end_expr
430
+ when AST::ExpressionList
431
+ expr.elements.each { |elem| check_expr_names(elem, scopes, binding, names) }
432
+ when AST::ProcExpr
433
+ body_names = names.dup
434
+ Array(expr.params).each { |p| body_names.add(p.name) if p.respond_to?(:name) }
435
+ expr.body&.each { |s| check_stmt_names(s, scopes, binding, body_names) }
436
+ when AST::DetachExpr
437
+ check_expr_names(expr.body, scopes, binding, names)
438
+ when AST::FormatExprPart
439
+ check_expr_names(expr.expression, scopes, binding, names)
440
+ when AST::IntegerLiteral, AST::FloatLiteral, AST::StringLiteral,
441
+ AST::BooleanLiteral, AST::NullLiteral, AST::CharLiteral,
442
+ AST::FormatString, AST::FormatTextPart
443
+ nil
444
+ end
445
+ end
446
+
447
+ def check_generic_name(name, scopes, binding, node, names)
448
+ return if name == "_" || name == "this"
449
+ return if names.include?(name)
450
+ return if BUILTIN_CALLABLE_NAMES.include?(name)
451
+ return if lookup_value(name, scopes)
452
+ return if @ctx.top_level_functions.key?(name)
453
+ return if @ctx.types.key?(name)
454
+ return if @ctx.imports.key?(name)
455
+ return if binding.type_params.include?(name)
456
+
457
+ raise_sema_error("unknown name #{name}", node)
458
+ end
459
+
305
460
  # Scans generic method bodies for assignments to this through a
306
461
  # non-editable receiver. Full body checking is deferred to call-site
307
462
  # specialization, but immutable-this violations are type-independent.
@@ -337,6 +492,7 @@ module MilkTea
337
492
  start_local_completion_frame(binding, scopes)
338
493
  if binding.type_params.any?
339
494
  check_generic_method_immutable_this(binding, scopes)
495
+ check_generic_method_names(binding, scopes)
340
496
  return
341
497
  end
342
498
 
@@ -314,6 +314,7 @@ module MilkTea
314
314
  token = context&.fetch(:token, nil)
315
315
  token_kind = token&.type || :none
316
316
  unless token&.type == :identifier
317
+ return nil if token.nil?
317
318
  unless member_access_token?(context)
318
319
  info = builtin_keyword_hover_info(token) ||
319
320
  BUILTIN_CALL_HOVER_INFO[token.lexeme]&.slice(:signature, :docs)
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.14
4
+ version: 0.2.16
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.14 installed!
586
+ Milk Tea 0.2.16 installed!
587
587
 
588
588
  System requirements:
589
589
  - A C compiler (gcc or clang) must be available on PATH