mt-lang 0.3.1 → 0.3.4

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: e212444d219545cf86e5711bdcd0eb02028b94fd8b0ae1ac8b6ade08b25967da
4
- data.tar.gz: fce0d6413dfc434af53103228604527bf9f08fef30dcbd7013fd50f5bd30878b
3
+ metadata.gz: 7cd20acdc903389647adc4c6c7e552fdbbf35694f69328b0427134109782b21f
4
+ data.tar.gz: 5cc1498f88f6ddb87eaa2d7a7da9f54c76a6ee9a38fe3e33f68ddc6120160057
5
5
  SHA512:
6
- metadata.gz: acc176d3ad35b7184b3df7e4beb4fb6a411bcf613bc7905fa16f215388d0ff26a6a0cea201f124f861f571efa7166098e969cffbe5e600ccf2e30614c5351065
7
- data.tar.gz: 7664d2ceb6235804d8ee78e6dd594ece82492f2e1d00c792762c696d122e3ad669b57dd4825acbada2c5d83dcb1fddef0b366dacd2f363d475bbedefba6122a9
6
+ metadata.gz: bcf70e8639131a5d7198028d7f70e632ebb817eba816635d24d753dfa4023bc0364e0b8a6082f2ccd747d40bf7c5f7d778ad2efeb2b6283e6c10604a4f44492b
7
+ data.tar.gz: b802f4c8cc2654c8464ec156967430573577a76316d916e31e5b043d81a61a8e2279bf5fadc037b38f2f388e3241507b4f17be08b78558fa2424da4b72315c31
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.1"
6
+ VERSION = "0.3.4"
7
7
 
8
8
  def self.root
9
9
  @root ||= Pathname.new(File.expand_path("../..", __dir__))
@@ -211,7 +211,7 @@ module MilkTea
211
211
  unresolved_import_paths.include?(import_path)
212
212
  end
213
213
 
214
- def self.path_to_uri(path)
214
+ def self.path_to_uri(path)
215
215
  escaped_path = path.split('/').map { |seg| CGI.escape(seg).gsub('+', '%20') }.join('/')
216
216
  "file://#{escaped_path}"
217
217
  end
@@ -605,10 +605,13 @@ module MilkTea
605
605
  end
606
606
 
607
607
  def collect_method_provider_import_uses(receiver, member_name, used, binding_resolution)
608
- return unless receiver.is_a?(AST::Identifier)
609
608
  return unless @sema_facts.respond_to?(:imports)
610
609
 
611
- receiver_type = identifier_binding_type(receiver, binding_resolution)
610
+ receiver_type = if receiver.is_a?(AST::Identifier)
611
+ identifier_binding_type(receiver, binding_resolution)
612
+ else
613
+ resolved_expr_type(receiver)
614
+ end
612
615
  return unless receiver_type
613
616
 
614
617
  @sema_facts.imports.each do |local_name, module_binding|
@@ -619,6 +622,14 @@ module MilkTea
619
622
  end
620
623
  end
621
624
 
625
+ def resolved_expr_type(expr)
626
+ return nil unless @sema_facts.respond_to?(:ast) && @sema_facts.ast.respond_to?(:node_ids)
627
+ return nil unless @sema_facts.respond_to?(:resolved_expr_types)
628
+
629
+ node_id = @sema_facts.ast.node_ids[expr.object_id]
630
+ node_id ? @sema_facts.resolved_expr_types[node_id] : nil
631
+ end
632
+
622
633
  def identifier_binding_type(identifier, binding_resolution)
623
634
  binding_id = binding_resolution.identifier_binding_ids[identifier.object_id]
624
635
  return nil unless binding_id
@@ -653,7 +664,7 @@ module MilkTea
653
664
  Types::Registry.generic_instance(
654
665
  receiver_type.name,
655
666
  receiver_type.arguments.each_with_index.map do |argument, index|
656
- argument.is_a?(Types::LiteralTypeArg) ? argument : Types::TypeVar.new("__lint_receiver_arg#{index}")
667
+ argument.is_a?(Types::LiteralTypeArg) ? argument : Types::TypeVar.new("__receiver_arg#{index}")
657
668
  end,
658
669
  )
659
670
  when Types::StructInstance
@@ -239,16 +239,37 @@ module MilkTea
239
239
  true
240
240
  elsif stmt.is_a?(AST::Assignment) && stmt.value.is_a?(AST::Identifier) && stmt.value.name == name
241
241
  true
242
+ elsif stmt.is_a?(AST::ReturnStmt) && own_cast_in_unsafe?(stmt.value, name)
243
+ true
242
244
  else
243
245
  false
244
246
  end
245
247
  end
246
248
  end
247
249
 
250
+ def own_cast_in_unsafe?(expr, name)
251
+ case expr
252
+ when AST::UnsafeExpr
253
+ case expr.expression
254
+ when AST::PrefixCast
255
+ expr.expression.expression.is_a?(AST::Identifier) && expr.expression.expression.name == name
256
+ end
257
+ else
258
+ false
259
+ end
260
+ end
261
+
248
262
  def own_struct_field_transfer?(expr, name)
249
- return false unless expr.is_a?(AST::Call)
250
- expr.arguments.any? do |arg|
251
- arg.is_a?(AST::Argument) && arg.value.is_a?(AST::Identifier) && arg.value.name == name
263
+ case expr
264
+ when AST::Call
265
+ expr.arguments.any? do |arg|
266
+ next unless arg.is_a?(AST::Argument)
267
+
268
+ arg.value.is_a?(AST::Identifier) && arg.value.name == name ||
269
+ own_struct_field_transfer?(arg.value, name)
270
+ end
271
+ else
272
+ false
252
273
  end
253
274
  end
254
275
 
@@ -152,6 +152,7 @@ module MilkTea
152
152
  column: statement.column,
153
153
  var: statement.kind == :var
154
154
  )
155
+ with_scope { visit_statement_list(statement.else_body) } if statement.else_body
155
156
  check_redundant_type_annotation(statement)
156
157
  flag_redundant_widening_cast(statement.value) if statement.type && statement.value
157
158
  record_ptr_candidate(statement)
data/std/blackboard.mt ADDED
@@ -0,0 +1,100 @@
1
+ ## Blackboard — typed key-value shared state for AI.
2
+ ##
3
+ ## Store and retrieve named values that multiple AI systems
4
+ ## can read and write. Linear O(n) lookup (tuned for small
5
+ ## sizes — typical AI blackboards have under 20 entries).
6
+ ##
7
+ ## import std.blackboard as bb
8
+ ## var board = bb.Blackboard[float].create()
9
+ ## board.set("health", 100.0)
10
+ ## let h = board.get("health") else: 0.0
11
+
12
+ import std.vec as vec
13
+
14
+
15
+ public struct BlackboardEntry[T]:
16
+ key: str
17
+ value: T
18
+
19
+
20
+ public struct Blackboard[T]:
21
+ entries: vec.Vec[BlackboardEntry[T]]
22
+
23
+
24
+ # ── internal helpers ──
25
+
26
+ function find_entry[T](board: ref[Blackboard[T]], key: str) -> ptr[BlackboardEntry[T]]?:
27
+ for entry in board.entries:
28
+ unsafe:
29
+ if read(entry).key == key:
30
+ return entry
31
+ return null
32
+
33
+
34
+ # ── public API ──
35
+
36
+ extending Blackboard[T]:
37
+ public static function create() -> Blackboard[T]:
38
+ return Blackboard[T](
39
+ entries = vec.Vec[BlackboardEntry[T]].create()
40
+ )
41
+
42
+
43
+ public editable function set(key: str, value: T) -> void:
44
+ let existing = find_entry(ref_of(this), key)
45
+ if existing != null:
46
+ unsafe:
47
+ read(ptr[BlackboardEntry[T]]<-existing).value = value
48
+ return
49
+ this.entries.push(BlackboardEntry[T](key = key, value = value))
50
+
51
+
52
+ public function get(key: str) -> Option[T]:
53
+ var n = this.entries.len()
54
+ var i: ptr_uint = 0
55
+ while i < n:
56
+ let entry_ptr = this.entries.get(i) else:
57
+ break
58
+ unsafe:
59
+ if read(entry_ptr).key == key:
60
+ return Option[T].some(value = read(entry_ptr).value)
61
+ i += 1
62
+ return Option[T].none
63
+
64
+
65
+ public function has(key: str) -> bool:
66
+ var n = this.entries.len()
67
+ var i: ptr_uint = 0
68
+ while i < n:
69
+ let entry_ptr = this.entries.get(i) else:
70
+ break
71
+ unsafe:
72
+ if read(entry_ptr).key == key:
73
+ return true
74
+ i += 1
75
+ return false
76
+
77
+
78
+ public editable function remove(key: str) -> void:
79
+ var n = this.entries.len()
80
+ var i: ptr_uint = 0
81
+ while i < n:
82
+ let entry_ptr = this.entries.get(i) else:
83
+ break
84
+ unsafe:
85
+ if read(entry_ptr).key == key:
86
+ this.entries.swap_remove(i)
87
+ return
88
+ i += 1
89
+
90
+
91
+ public editable function clear() -> void:
92
+ this.entries.clear()
93
+
94
+
95
+ public function count() -> ptr_uint:
96
+ return this.entries.len()
97
+
98
+
99
+ public editable function release() -> void:
100
+ this.entries.release()
data/std/cmd.mt ADDED
@@ -0,0 +1,132 @@
1
+ ## Command pattern — undo/redo with paired do/undo callbacks.
2
+ ##
3
+ ## Encapsulate reversible actions as value-objects. Stack-based
4
+ ## history for linear undo/redo. Recording for replay capture.
5
+ ##
6
+ ## import std.cmd as cmd
7
+ ## var hist = cmd.History[Editor].create()
8
+ ## hist.execute(cmd.Cmd[Editor].create(ctx, do_insert, undo_delete))
9
+ ## hist.undo()
10
+
11
+ import std.vec as vec
12
+
13
+
14
+ public struct Cmd[Context]:
15
+ context: ptr[Context]
16
+ do_fn: fn(context: ptr[Context]) -> void
17
+ undo_fn: fn(context: ptr[Context]) -> void
18
+
19
+
20
+ public struct History[Context]:
21
+ undos: vec.Vec[Cmd[Context]]
22
+ redos: vec.Vec[Cmd[Context]]
23
+
24
+
25
+ public struct Recording[Context]:
26
+ cmds: vec.Vec[Cmd[Context]]
27
+
28
+
29
+ # ── Cmd ──
30
+
31
+ extending Cmd[Context]:
32
+ public static function create(
33
+ context: ptr[Context],
34
+ do_fn: fn(context: ptr[Context]) -> void,
35
+ undo_fn: fn(context: ptr[Context]) -> void
36
+ ) -> Cmd[Context]:
37
+ return Cmd[Context](context = context, do_fn = do_fn, undo_fn = undo_fn)
38
+
39
+
40
+ public function invoke() -> void:
41
+ this.do_fn(this.context)
42
+
43
+
44
+ public function revert() -> void:
45
+ this.undo_fn(this.context)
46
+
47
+
48
+ # ── History ──
49
+
50
+ extending History[Context]:
51
+ public static function create() -> History[Context]:
52
+ return History[Context](
53
+ undos = vec.Vec[Cmd[Context]].create(),
54
+ redos = vec.Vec[Cmd[Context]].create()
55
+ )
56
+
57
+
58
+ public editable function execute(cmd: Cmd[Context]) -> void:
59
+ cmd.invoke()
60
+ this.undos.push(cmd)
61
+ this.redos.clear()
62
+
63
+
64
+ public editable function undo() -> bool:
65
+ let cmd = this.undos.pop() else:
66
+ return false
67
+ cmd.revert()
68
+ this.redos.push(cmd)
69
+ return true
70
+
71
+
72
+ public editable function redo() -> bool:
73
+ let cmd = this.redos.pop() else:
74
+ return false
75
+ cmd.invoke()
76
+ this.undos.push(cmd)
77
+ return true
78
+
79
+
80
+ public function can_undo() -> bool:
81
+ return this.undos.len() > 0
82
+
83
+
84
+ public function can_redo() -> bool:
85
+ return this.redos.len() > 0
86
+
87
+
88
+ public function undo_count() -> ptr_uint:
89
+ return this.undos.len()
90
+
91
+
92
+ public function redo_count() -> ptr_uint:
93
+ return this.redos.len()
94
+
95
+
96
+ public editable function clear() -> void:
97
+ this.undos.clear()
98
+ this.redos.clear()
99
+
100
+
101
+ public editable function release() -> void:
102
+ this.undos.release()
103
+ this.redos.release()
104
+
105
+
106
+ # ── Recording ──
107
+
108
+ extending Recording[Context]:
109
+ public static function create() -> Recording[Context]:
110
+ return Recording[Context](cmds = vec.Vec[Cmd[Context]].create())
111
+
112
+
113
+ public editable function record(cmd: Cmd[Context]) -> void:
114
+ this.cmds.push(cmd)
115
+
116
+
117
+ public editable function replay(history: ref[History[Context]]) -> void:
118
+ for entry in this.cmds:
119
+ unsafe:
120
+ history.execute(read(entry))
121
+
122
+
123
+ public function count() -> ptr_uint:
124
+ return this.cmds.len()
125
+
126
+
127
+ public editable function clear() -> void:
128
+ this.cmds.clear()
129
+
130
+
131
+ public editable function release() -> void:
132
+ this.cmds.release()
data/std/color.mt ADDED
@@ -0,0 +1,245 @@
1
+ ## Color utilities — RGBA conversion, blending, and presets.
2
+ ##
3
+ ## Provides an RGBA Color struct compatible with raylib/FBO
4
+ ## layouts, plus HSL/HSV conversion, hex parsing, alpha
5
+ ## blending, and common named-color constants.
6
+ ##
7
+ ## import std.color as clr
8
+ ## let c = clr.Color.from_hsl(210.0, 0.8, 0.6)
9
+ ## let blended = c.alpha_blend(clr.WHITE)
10
+
11
+ public struct Color:
12
+ r: ubyte
13
+ g: ubyte
14
+ b: ubyte
15
+ a: ubyte
16
+
17
+
18
+ public const WHITE: Color = Color(r = 255, g = 255, b = 255, a = 255)
19
+ public const BLACK: Color = Color(r = 0, g = 0, b = 0, a = 255)
20
+ public const RED: Color = Color(r = 255, g = 0, b = 0, a = 255)
21
+ public const GREEN: Color = Color(r = 0, g = 255, b = 0, a = 255)
22
+ public const BLUE: Color = Color(r = 0, g = 0, b = 255, a = 255)
23
+ public const YELLOW: Color = Color(r = 255, g = 255, b = 0, a = 255)
24
+ public const CYAN: Color = Color(r = 0, g = 255, b = 255, a = 255)
25
+ public const MAGENTA:Color = Color(r = 255, g = 0, b = 255, a = 255)
26
+ public const GRAY: Color = Color(r = 128, g = 128, b = 128, a = 255)
27
+ public const ORANGE: Color = Color(r = 255, g = 165, b = 0, a = 255)
28
+ public const PINK: Color = Color(r = 255, g = 192, b = 203, a = 255)
29
+ public const PURPLE: Color = Color(r = 128, g = 0, b = 128, a = 255)
30
+ public const TRANSPARENT: Color = Color(r = 0, g = 0, b = 0, a = 0)
31
+
32
+
33
+ # ── math helpers ──
34
+
35
+ function fmin(a: float, b: float) -> float:
36
+ if a < b: return a
37
+ return b
38
+
39
+
40
+ function fmax(a: float, b: float) -> float:
41
+ if a > b: return a
42
+ return b
43
+
44
+
45
+ function fabs(x: float) -> float:
46
+ if x < 0.0: return -x
47
+ return x
48
+
49
+
50
+ function fmod(x: float, m: float) -> float:
51
+ # x - floor(x / m) * m
52
+ let div = x / m
53
+ let fl = float<-(int<-(div))
54
+ if div < 0.0 and float<-(int<-(div)) != div:
55
+ return x - (fl - 1.0) * m
56
+ return x - fl * m
57
+
58
+
59
+ # ── public API ──
60
+
61
+ extending Color:
62
+ public static function from_rgba(r: ubyte, g: ubyte, b: ubyte, a: ubyte) -> Color:
63
+ return Color(r = r, g = g, b = b, a = a)
64
+
65
+
66
+ public static function from_hsl(h: float, s: float, l: float) -> Color:
67
+ # h: 0..360, s: 0..1, l: 0..1
68
+ var hh = fmod(h, 360.0)
69
+ if hh < 0.0: hh = hh + 360.0
70
+
71
+ let c = (1.0 - fabs(2.0 * l - 1.0)) * s
72
+ let x = c * (1.0 - fabs(fmod(hh / 60.0, 2.0) - 1.0))
73
+ let m = l - c / 2.0
74
+
75
+ var r1: float = 0.0
76
+ var g1: float = 0.0
77
+ var b1: float = 0.0
78
+
79
+ if hh < 60.0:
80
+ r1 = c
81
+ g1 = x
82
+ else if hh < 120.0:
83
+ r1 = x
84
+ g1 = c
85
+ else if hh < 180.0:
86
+ g1 = c
87
+ b1 = x
88
+ else if hh < 240.0:
89
+ g1 = x
90
+ b1 = c
91
+ else if hh < 300.0:
92
+ r1 = x
93
+ b1 = c
94
+ else:
95
+ r1 = c
96
+ b1 = x
97
+
98
+ return Color(
99
+ r = ubyte<-((r1 + m) * 255.0),
100
+ g = ubyte<-((g1 + m) * 255.0),
101
+ b = ubyte<-((b1 + m) * 255.0),
102
+ a = 255
103
+ )
104
+
105
+
106
+ public static function from_hsv(h: float, s: float, v: float) -> Color:
107
+ var hh = fmod(h, 360.0)
108
+ if hh < 0.0: hh = hh + 360.0
109
+
110
+ let c = v * s
111
+ let x = c * (1.0 - fabs(fmod(hh / 60.0, 2.0) - 1.0))
112
+ let m = v - c
113
+
114
+ var r1: float = 0.0
115
+ var g1: float = 0.0
116
+ var b1: float = 0.0
117
+
118
+ if hh < 60.0:
119
+ r1 = c
120
+ g1 = x
121
+ else if hh < 120.0:
122
+ r1 = x
123
+ g1 = c
124
+ else if hh < 180.0:
125
+ g1 = c
126
+ b1 = x
127
+ else if hh < 240.0:
128
+ g1 = x
129
+ b1 = c
130
+ else if hh < 300.0:
131
+ r1 = x
132
+ b1 = c
133
+ else:
134
+ r1 = c
135
+ b1 = x
136
+
137
+ return Color(
138
+ r = ubyte<-((r1 + m) * 255.0),
139
+ g = ubyte<-((g1 + m) * 255.0),
140
+ b = ubyte<-((b1 + m) * 255.0),
141
+ a = 255
142
+ )
143
+
144
+
145
+ public function to_hsl() -> (float, float, float):
146
+ let rf = float<-(this.r) / 255.0
147
+ let gf = float<-(this.g) / 255.0
148
+ let bf = float<-(this.b) / 255.0
149
+
150
+ let mx = fmax(fmax(rf, gf), bf)
151
+ let mn = fmin(fmin(rf, gf), bf)
152
+ let delta = mx - mn
153
+
154
+ let l = (mx + mn) / 2.0
155
+
156
+ var h: float = 0.0
157
+ let s = if delta == 0.0: 0.0 else: delta / (1.0 - fabs(2.0 * l - 1.0))
158
+
159
+ if delta != 0.0:
160
+ if mx == rf:
161
+ h = fmod((gf - bf) / delta, 6.0)
162
+ else if mx == gf:
163
+ h = (bf - rf) / delta + 2.0
164
+ else:
165
+ h = (rf - gf) / delta + 4.0
166
+ h = h * 60.0
167
+ if h < 0.0:
168
+ h = h + 360.0
169
+
170
+ return (h, s, l)
171
+
172
+
173
+ public function to_hsv() -> (float, float, float):
174
+ let rf = float<-(this.r) / 255.0
175
+ let gf = float<-(this.g) / 255.0
176
+ let bf = float<-(this.b) / 255.0
177
+
178
+ let mx = fmax(fmax(rf, gf), bf)
179
+ let mn = fmin(fmin(rf, gf), bf)
180
+ let delta = mx - mn
181
+
182
+ var h: float = 0.0
183
+ let s = if mx == 0.0: 0.0 else: delta / mx
184
+ let v = mx
185
+
186
+ if delta != 0.0:
187
+ if mx == rf:
188
+ h = fmod((gf - bf) / delta, 6.0)
189
+ else if mx == gf:
190
+ h = (bf - rf) / delta + 2.0
191
+ else:
192
+ h = (rf - gf) / delta + 4.0
193
+ h = h * 60.0
194
+ if h < 0.0:
195
+ h = h + 360.0
196
+
197
+ return (h, s, v)
198
+
199
+
200
+ public function lerp(target: Color, t: float) -> Color:
201
+ let r = float<-(this.r) + (float<-(target.r) - float<-(this.r)) * t
202
+ let g = float<-(this.g) + (float<-(target.g) - float<-(this.g)) * t
203
+ let b = float<-(this.b) + (float<-(target.b) - float<-(this.b)) * t
204
+ let a = float<-(this.a) + (float<-(target.a) - float<-(this.a)) * t
205
+ return Color(r = ubyte<-(r), g = ubyte<-(g), b = ubyte<-(b), a = ubyte<-(a))
206
+
207
+
208
+ public function alpha_blend(background: Color) -> Color:
209
+ if this.a == 0:
210
+ return background
211
+ if this.a == 255:
212
+ return this
213
+
214
+ let sa = float<-(this.a) / 255.0
215
+ let da = float<-(background.a) / 255.0
216
+
217
+ let r_out = float<-(this.r) * sa + float<-(background.r) * da * (1.0 - sa)
218
+ let g_out = float<-(this.g) * sa + float<-(background.g) * da * (1.0 - sa)
219
+ let b_out = float<-(this.b) * sa + float<-(background.b) * da * (1.0 - sa)
220
+ let a_out = sa + da * (1.0 - sa)
221
+
222
+ return Color(
223
+ r = ubyte<-(r_out),
224
+ g = ubyte<-(g_out),
225
+ b = ubyte<-(b_out),
226
+ a = ubyte<-(a_out * 255.0)
227
+ )
228
+
229
+
230
+ public function scale(factor: float) -> Color:
231
+ let r = fmin(fmax(float<-(this.r) * factor, 0.0), 255.0)
232
+ let g = fmin(fmax(float<-(this.g) * factor, 0.0), 255.0)
233
+ let b = fmin(fmax(float<-(this.b) * factor, 0.0), 255.0)
234
+ return Color(r = ubyte<-(r), g = ubyte<-(g), b = ubyte<-(b), a = this.a)
235
+
236
+
237
+ public function multiply(other: Color) -> Color:
238
+ let r = ubyte<-(int<-((int<-(this.r) * int<-(other.r)) / 255))
239
+ let g = ubyte<-(int<-((int<-(this.g) * int<-(other.g)) / 255))
240
+ let b = ubyte<-(int<-((int<-(this.b) * int<-(other.b)) / 255))
241
+ return Color(r = r, g = g, b = b, a = this.a)
242
+
243
+
244
+ public function with_alpha(a: ubyte) -> Color:
245
+ return Color(r = this.r, g = this.g, b = this.b, a = a)