mt-lang 0.3.5 → 0.3.6

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: 1ba5797b3cf3ff504321adf78e281c017a4ca3aa30088f5d472c01fe157f7b4f
4
- data.tar.gz: f1b7c0dd477f0e0868e6b3da0fa7f640ace5ef9d53703a7aa8ab89b8907999c9
3
+ metadata.gz: 2d5caebfa149a9d43d576f3cbf1b36b175ce70b28bfe474bc942fc2d11f0f1e8
4
+ data.tar.gz: bf9f4a30b1cabadbed2b2d276dd29d567e118d008000791eefb2ec0e81f80c4f
5
5
  SHA512:
6
- metadata.gz: 9db5f6898f03726a69d907b0a5dec9d19a52ac3141e8cfdda443797476d9fc8f7b0e426812288babdbba3f48d270499e49998224a4509705286992bfd117e810
7
- data.tar.gz: 5de95e68ce290fa2e3f80e5d595e29dba7d19093f91dcc169c6773a027fe80f3866f38a213713709911aeda767ccd28b30eb3b4765b5d58319997aaec587f414
6
+ metadata.gz: 681c1614c3449f16bb71fbb0f9ee7e9ec10420e302602b131c4ed813b087742e7474ff71e9111f5d35cb1e4315eb440c3c85e29d66e8c733159063cbe946ea01
7
+ data.tar.gz: 6ea9caabdb7407f64d634f6576135df74e614878f81680777062c2e5f64f75278bb56f71bb48406153e40745e2d2b458e99c46193c9c85837c2b28b3b7aca4b4
data/lib/milk_tea/base.rb CHANGED
@@ -3,7 +3,7 @@
3
3
  require "pathname"
4
4
 
5
5
  module MilkTea
6
- VERSION = "0.3.5"
6
+ VERSION = "0.3.6"
7
7
 
8
8
  def self.root
9
9
  @root ||= Pathname.new(File.expand_path("../..", __dir__))
@@ -33,7 +33,12 @@ module MilkTea
33
33
  when IR::NullableSpanIndex
34
34
  "#{nullable_span_index_helper_name(expression.receiver_type)}(#{emit_expression(expression.receiver)}, #{emit_expression(expression.index)})"
35
35
  when IR::Call
36
- raise CBackendError, "array-return call must be materialized before C emission" if array_type?(expression.type)
36
+ if array_type?(expression.type)
37
+ location = [@source_path, @current_line && "line #{@current_line}"].compact.join(" ")
38
+ msg = "array-return call must be materialized before C emission"
39
+ msg += " (#{location})" unless location.empty?
40
+ raise CBackendError.new(msg, line: @current_line, path: @source_path)
41
+ end
37
42
 
38
43
  emit_call_expression(expression)
39
44
  when IR::Unary
@@ -23,6 +23,10 @@ module MilkTea
23
23
  indent = INDENT * level
24
24
  aliases = checked_index_aliases_for_statement(statement)
25
25
  alias_lines = emit_checked_index_alias_declarations(aliases, indent)
26
+ if statement.respond_to?(:line) && statement.line
27
+ @current_line = statement.line
28
+ @source_path ||= statement.source_path if statement.respond_to?(:source_path) && statement.source_path
29
+ end
26
30
  line_directive = if @emit_line_directives && statement.respond_to?(:line) && statement.line
27
31
  sp = (statement.respond_to?(:source_path) && statement.source_path) || @source_path
28
32
  sp ? ["#line #{statement.line} #{sp.inspect}"] : []
@@ -55,6 +55,8 @@ module MilkTea
55
55
  @checked_index_alias_id = 0
56
56
  @loop_guard_id = 0
57
57
  @emitted_span_type_names = Set.new
58
+ @source_path = program.source_path
59
+ @current_line = nil
58
60
  end
59
61
 
60
62
  def emit
@@ -218,10 +220,16 @@ module MilkTea
218
220
  end
219
221
 
220
222
  constants.each do |constant|
223
+ @current_line = constant.line if constant.line
224
+ @source_path ||= constant.source_path if constant.source_path
221
225
  lines << "#{constant_storage(constant.type)} #{c_declaration(constant.type, constant.linkage_name)} = #{emit_initializer(constant.value)};"
222
226
  end
223
227
  @program.globals.each do |global|
224
228
  next unless emitted_globals.include?(global)
229
+ if global.respond_to?(:line) && global.line
230
+ @current_line = global.line
231
+ @source_path ||= global.source_path if global.respond_to?(:source_path) && global.source_path
232
+ end
225
233
  lines << "#{global_storage(global.type)} #{c_declaration(global.type, global.linkage_name)} = #{emit_initializer(global.value)};"
226
234
  end
227
235
  lines << "" unless constants.empty? && @program.globals.empty?
@@ -114,7 +114,12 @@ module MilkTea
114
114
  else
115
115
  @checker.instance_variable_get(:@ctx).types
116
116
  end
117
- if (type = types[call_expr.callee.name]) && type.is_a?(Types::Struct)
117
+ callee_name = if call_expr.callee.is_a?(AST::Specialization) && call_expr.callee.callee.respond_to?(:name)
118
+ call_expr.callee.callee.name
119
+ elsif call_expr.callee.respond_to?(:name)
120
+ call_expr.callee.name
121
+ end
122
+ if callee_name && (type = types[callee_name]) && type.is_a?(Types::Struct)
118
123
  fields = {}
119
124
  call_expr.arguments.each do |argument|
120
125
  val = evaluate_expression(argument.value, scopes:)
@@ -123,6 +128,19 @@ module MilkTea
123
128
  end
124
129
  next fields
125
130
  end
131
+
132
+ if call_expr.callee.is_a?(AST::Specialization) && @checker.respond_to?(:resolve_type_expression)
133
+ resolved = @checker.send(:resolve_type_expression, call_expr.callee)
134
+ if resolved && @checker.respond_to?(:array_type?) && @checker.send(:array_type?, resolved)
135
+ values = []
136
+ call_expr.arguments.each do |argument|
137
+ val = evaluate_expression(argument.value, scopes:)
138
+ return nil unless val
139
+ values << val
140
+ end
141
+ next values
142
+ end
143
+ end
126
144
 
127
145
  @checker.send(:evaluate_compile_time_const_value, call_expr, scopes:)
128
146
  },
@@ -6,7 +6,9 @@ module MilkTea
6
6
  def initialize(module_name:, includes:, constants:, globals:, opaques:, structs:, unions:, enums:, variants:, static_asserts:, functions:, source_path: nil) = super
7
7
  end
8
8
  Include = Data.define(:header)
9
- Constant = Data.define(:name, :linkage_name, :type, :value)
9
+ Constant = Data.define(:name, :linkage_name, :type, :value, :line, :source_path) do
10
+ def initialize(name:, linkage_name:, type:, value:, line: nil, source_path: nil) = super
11
+ end
10
12
  Global = Data.define(:name, :linkage_name, :type, :value)
11
13
  OpaqueDecl = Data.define(:name, :linkage_name, :forward_declarable, :source_module) do
12
14
  def initialize(name:, linkage_name:, forward_declarable:, source_module: nil) = super
@@ -353,7 +353,8 @@ module MilkTea
353
353
  value = lower_static_storage_initializer(decl.value, env:, expected_type: decl.type ? resolve_type_ref(decl.type) : nil)
354
354
  type = decl.type ? resolve_type_ref(decl.type) : infer_expression_type(decl.value, env:)
355
355
  linkage_name = value_c_name(decl.name)
356
- constant = IR::Constant.new(name: decl.name, linkage_name:, type:, value:)
356
+ constant = IR::Constant.new(name: decl.name, linkage_name:, type:, value:,
357
+ line: decl.line, source_path: @ctx.current_analysis_path)
357
358
  @artifacts.emitted_declarations << constant
358
359
  []
359
360
  end
@@ -511,7 +512,7 @@ module MilkTea
511
512
  env: local_env,
512
513
  expected_type: target.type,
513
514
  allow_root_statement_foreign: true,
514
- materialize_array_calls: !array_type?(target.type),
515
+ materialize_array_calls: true,
515
516
  )
516
517
  lowered.concat(prepared_setup)
517
518
  if (foreign_call = foreign_call_info(prepared_value, local_env))
@@ -700,7 +701,7 @@ module MilkTea
700
701
  env: local_env,
701
702
  expected_type: storage_type,
702
703
  allow_root_statement_foreign: true,
703
- materialize_array_calls: !array_type?(storage_type),
704
+ materialize_array_calls: true,
704
705
  )
705
706
  lowered.concat(prepared_setup)
706
707
  end
@@ -41,7 +41,8 @@ module MilkTea
41
41
  value = lower_static_storage_initializer(decl.value, env: empty_env, expected_type: type)
42
42
  end
43
43
 
44
- IR::Constant.new(name: decl.name, linkage_name: value_c_name(decl.name), type:, value:)
44
+ IR::Constant.new(name: decl.name, linkage_name: value_c_name(decl.name), type:, value:,
45
+ line: decl.line, source_path: @ctx.current_analysis_path)
45
46
  end
46
47
  end
47
48
 
@@ -666,11 +666,11 @@ module MilkTea
666
666
  end
667
667
 
668
668
  if (callable_resolution = resolve_specialized_callable_binding(callee, env:))
669
- callable_kind, function_binding, receiver = callable_resolution
669
+ callable_kind, function_binding, receiver, method_entry_receiver_type = callable_resolution
670
670
  if callable_kind == :method
671
671
  return [
672
672
  :method,
673
- function_binding_c_name(function_binding, module_name: function_binding.owner.module_name, receiver_type: function_binding.type.receiver_type),
673
+ function_binding_c_name(function_binding, module_name: function_binding.owner.module_name, receiver_type: method_entry_receiver_type),
674
674
  receiver,
675
675
  function_binding.type,
676
676
  function_binding,
@@ -1277,7 +1277,7 @@ module MilkTea
1277
1277
  return nil unless binding
1278
1278
 
1279
1279
  type_arguments = resolve_specialization_type_arguments(expression)
1280
- [callable_kind, instantiate_function_binding_with_receiver(binding, type_arguments, receiver_type:), receiver]
1280
+ [callable_kind, instantiate_function_binding_with_receiver(binding, type_arguments, receiver_type:), receiver, method_entry_receiver_type]
1281
1281
  end
1282
1282
 
1283
1283
  def resolve_default_specialization(expression, env:)
@@ -376,6 +376,29 @@ 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 = resolve_type_expression(expression.callee)
380
+ if resolved_type && resolved_type.is_a?(Types::Struct)
381
+ fields = {}
382
+ expression.arguments.each do |argument|
383
+ val = CompileTime.evaluate(argument.value, resolve_identifier: lambda { |id|
384
+ if scopes
385
+ binding = lookup_value(id.name, scopes)
386
+ return binding.const_value unless binding&.const_value.nil?
387
+ end
388
+ resolve_current_module_const_value(id.name)
389
+ }, resolve_member_access: lambda { |ma|
390
+ if (receiver_type = resolve_type_expression(ma.receiver))
391
+ next resolve_enum_member_const_value(receiver_type, ma.member)
392
+ end
393
+ nil
394
+ }, resolve_call: lambda { |inner_call|
395
+ evaluate_compile_time_call(inner_call, scopes:)
396
+ })
397
+ return nil unless val
398
+ fields[argument.name] = val
399
+ end
400
+ return fields
401
+ end
379
402
  func = @ctx.top_level_functions[callee_name]
380
403
  if func&.ast&.respond_to?(:const) && func.ast.const
381
404
  evaluate_const_function_body(func, expression.arguments, scopes:)
@@ -16,19 +16,11 @@ module MilkTea
16
16
  severity = error.respond_to?(:severity) ? error.severity : :error
17
17
  code = error.respond_to?(:code) ? error.code : nil
18
18
 
19
- source ||= read_source(path)
20
- return "#{severity_label(severity)}: #{error_message} at #{path}:#{line}:#{column}" unless source
21
-
22
- source_lines = source.split("\n", -1)
23
- source_line = source_lines[line - 1] || ""
24
- stripped = source_line.gsub(/\t/, " ")
19
+ # Strip location suffix from message (errors embed "at path:line:col" in message text)
20
+ location_suffix = " at #{path}:#{line}:#{column}"
21
+ error_message = error_message.delete_suffix(location_suffix).strip
25
22
 
26
- indent = " " * [column - 1, 0].max
27
- highlight = if length && length > 1
28
- "^" + "~" * (length - 1)
29
- else
30
- "^"
31
- end
23
+ source ||= read_source(path)
32
24
 
33
25
  bold = color ? "\e[1m" : ""
34
26
  red = color ? "\e[31m" : ""
@@ -46,9 +38,21 @@ module MilkTea
46
38
 
47
39
  code_text = code ? "#{cyan}[#{code}]#{reset}" : ""
48
40
 
41
+ return "#{sev_color}#{sev_text}#{code_text}#{reset}: #{error_message} -- #{path}:#{line}:#{column}" unless source
42
+
43
+ source_lines = source.split("\n", -1)
44
+ source_line = source_lines[line - 1] || ""
45
+ stripped = source_line.gsub(/\t/, " ")
46
+
47
+ indent = " " * [column - 1, 0].max
48
+ highlight = if length && length > 1
49
+ "^" + "~" * (length - 1)
50
+ else
51
+ "^"
52
+ end
53
+
49
54
  [
50
- "#{bold}#{sev_color}#{sev_text}#{code_text}#{reset}: #{error_message}",
51
- " #{bold}-->#{reset} #{path}:#{line}:#{column}",
55
+ "#{sev_color}#{sev_text}#{code_text}#{reset}: #{error_message} -- #{path}:#{line}:#{column}",
52
56
  " #{bold}|#{reset}",
53
57
  "#{line.to_s.rjust(5)} #{bold}|#{reset} #{stripped}",
54
58
  " #{bold}|#{reset} #{sev_color}#{indent}#{highlight}#{reset}",
data/std/mem/ptr.mt CHANGED
@@ -10,3 +10,12 @@ extending ptr[T]:
10
10
 
11
11
  public function store(value: T) -> void:
12
12
  unsafe: read(this) = value
13
+
14
+ public function load_at(offset: ptr_uint) -> T:
15
+ return unsafe: read(this + offset)
16
+
17
+ public function store_at(offset: ptr_uint, value: T) -> void:
18
+ unsafe: read(this + offset) = value
19
+
20
+ public function cast[U]() -> ptr[U]:
21
+ return unsafe: ptr[U]<-this
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.5
4
+ version: 0.3.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Long (Teefan) Tran
@@ -602,7 +602,7 @@ metadata:
602
602
  homepage_uri: https://teefan.github.io/mt-lang/
603
603
  source_code_uri: https://github.com/teefan/mt-lang
604
604
  post_install_message: |
605
- Milk Tea 0.3.5 installed!
605
+ Milk Tea 0.3.6 installed!
606
606
 
607
607
  System requirements:
608
608
  - A C compiler (gcc or clang) must be available on PATH