mt-lang 0.3.2 → 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: ed7c9f0e80bb1fcfc3b458b277a0a2eda3b55ca295950af89c99a769b74e4be2
4
- data.tar.gz: 4eb3fdfcbdb1557b3ed87a1f60ce8704f1f1de943e58e2c096318fc802da55a2
3
+ metadata.gz: 7cd20acdc903389647adc4c6c7e552fdbbf35694f69328b0427134109782b21f
4
+ data.tar.gz: 5cc1498f88f6ddb87eaa2d7a7da9f54c76a6ee9a38fe3e33f68ddc6120160057
5
5
  SHA512:
6
- metadata.gz: f900ebf361a8f2c8acec00fb63ccae9d6b23cd6059ba2edc27b4a3c89fe288453498d9aca753cba2b1139db6b69a82e52038e976c5d4b692d052845735afd754
7
- data.tar.gz: 0a2bffc30d6485314ef351fb3917696298978798494e8eb655b27ed045c2d0c74674ab53d2c8b8764241b1e07fef092c3bbd6b35b73451d0237ac250a4d7a21c
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.2"
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
@@ -18,7 +18,6 @@ module MilkTea
18
18
  local_name = import.alias_name || import.path.parts.last
19
19
  next if ignored_binding_name?(local_name)
20
20
  next if used.include?(local_name)
21
- next if import_provides_extending_methods?(import)
22
21
 
23
22
  @warnings << Warning.new(
24
23
  path: @path,
@@ -32,15 +31,6 @@ module MilkTea
32
31
  end
33
32
  end
34
33
 
35
- def import_provides_extending_methods?(import)
36
- return false unless @sema_facts.respond_to?(:imports)
37
-
38
- module_binding = @sema_facts.imports[import.alias_name || import.path.parts.last]
39
- return false unless module_binding&.respond_to?(:methods)
40
-
41
- module_binding.methods.any?
42
- end
43
-
44
34
  def check_platform_api_drift(source_file)
45
35
  resolved_path = self.class.resolve_lint_path(@path)
46
36
  return unless resolved_path&.end_with?(".mt")
@@ -615,10 +605,13 @@ module MilkTea
615
605
  end
616
606
 
617
607
  def collect_method_provider_import_uses(receiver, member_name, used, binding_resolution)
618
- return unless receiver.is_a?(AST::Identifier)
619
608
  return unless @sema_facts.respond_to?(:imports)
620
609
 
621
- 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
622
615
  return unless receiver_type
623
616
 
624
617
  @sema_facts.imports.each do |local_name, module_binding|
@@ -629,6 +622,14 @@ module MilkTea
629
622
  end
630
623
  end
631
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
+
632
633
  def identifier_binding_type(identifier, binding_resolution)
633
634
  binding_id = binding_resolution.identifier_binding_ids[identifier.object_id]
634
635
  return nil unless binding_id
@@ -663,7 +664,7 @@ module MilkTea
663
664
  Types::Registry.generic_instance(
664
665
  receiver_type.name,
665
666
  receiver_type.arguments.each_with_index.map do |argument, index|
666
- 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}")
667
668
  end,
668
669
  )
669
670
  when Types::StructInstance
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)