Skip to main content

tl_compiler/
chunk.rs

1// ThinkingLanguage — Bytecode chunk (compiled function)
2
3use std::sync::Arc;
4use tl_ast::Expr as AstExpr;
5
6/// A compiled function / top-level script.
7#[derive(Debug, Clone)]
8pub struct Prototype {
9    /// Bytecode instructions
10    pub code: Vec<u32>,
11    /// Constant pool
12    pub constants: Vec<Constant>,
13    /// Source line for each instruction (for error reporting)
14    pub lines: Vec<u32>,
15    /// Number of parameters
16    pub arity: u8,
17    /// Number of local variable slots needed
18    pub num_locals: u8,
19    /// Number of registers needed
20    pub num_registers: u8,
21    /// Upvalue definitions (how to capture from enclosing scope)
22    pub upvalue_defs: Vec<UpvalueDef>,
23    /// Function name (for debugging)
24    pub name: String,
25    /// Whether this function contains yield (is a generator)
26    pub is_generator: bool,
27    /// Top-level local bindings: (name, register_index) — used for module exports
28    pub top_level_locals: Vec<(String, u8)>,
29}
30
31impl Prototype {
32    pub fn new(name: String) -> Self {
33        Prototype {
34            code: Vec::new(),
35            constants: Vec::new(),
36            lines: Vec::new(),
37            arity: 0,
38            num_locals: 0,
39            num_registers: 0,
40            upvalue_defs: Vec::new(),
41            name,
42            is_generator: false,
43            top_level_locals: Vec::new(),
44        }
45    }
46
47    /// Disassemble this prototype into a human-readable string.
48    pub fn disassemble(&self) -> String {
49        use crate::opcode::*;
50
51        let mut out = String::new();
52        let label = if self.name.is_empty() {
53            "<script>"
54        } else {
55            &self.name
56        };
57        out.push_str(&format!("=== {label} ===\n"));
58        out.push_str(&format!(
59            "  arity={} locals={} registers={}{}\n",
60            self.arity,
61            self.num_locals,
62            self.num_registers,
63            if self.is_generator {
64                " [generator]"
65            } else {
66                ""
67            }
68        ));
69
70        let mut offset = 0usize;
71        while offset < self.code.len() {
72            let inst_offset = offset; // save for display
73            let inst = self.code[offset];
74            let op = decode_op(inst);
75            let a = decode_a(inst);
76            let b = decode_b(inst);
77            let c = decode_c(inst);
78            let bx = decode_bx(inst);
79            let sbx = decode_sbx(inst);
80
81            // Line number
82            let line_num = if inst_offset < self.lines.len() {
83                let ln = self.lines[inst_offset];
84                if ln == 0 {
85                    "----".to_string()
86                } else {
87                    format!("{ln:04}")
88                }
89            } else {
90                "----".to_string()
91            };
92
93            let args = match op {
94                // ABx format: constant load
95                Op::LoadConst => {
96                    let val = self.format_constant(bx as usize);
97                    format!("R{a} = K{bx} ({val})")
98                }
99                // A-only: no args
100                Op::LoadNone => format!("R{a}"),
101                Op::LoadTrue => format!("R{a}"),
102                Op::LoadFalse => format!("R{a}"),
103
104                // AB: register copy
105                Op::Move => format!("R{a} = R{b}"),
106
107                // AB: locals
108                Op::GetLocal => format!("R{a} = L{b}"),
109                Op::SetLocal => format!("L{b} = R{a}"),
110
111                // ABx: globals (constant index for name)
112                Op::GetGlobal => {
113                    let name = self.format_constant(bx as usize);
114                    format!("R{a} = G[{name}]")
115                }
116                Op::SetGlobal => {
117                    let name = self.format_constant(bx as usize);
118                    format!("G[{name}] = R{a}")
119                }
120
121                // AB: upvalues
122                Op::GetUpvalue => format!("R{a} = U{b}"),
123                Op::SetUpvalue => format!("U{b} = R{a}"),
124
125                // ABC: arithmetic/comparison/logic
126                Op::Add
127                | Op::Sub
128                | Op::Mul
129                | Op::Div
130                | Op::Mod
131                | Op::Pow
132                | Op::Eq
133                | Op::Neq
134                | Op::Lt
135                | Op::Gt
136                | Op::Lte
137                | Op::Gte
138                | Op::And
139                | Op::Or
140                | Op::Concat => {
141                    let sym = match op {
142                        Op::Add => "+",
143                        Op::Sub => "-",
144                        Op::Mul => "*",
145                        Op::Div => "/",
146                        Op::Mod => "%",
147                        Op::Pow => "**",
148                        Op::Eq => "==",
149                        Op::Neq => "!=",
150                        Op::Lt => "<",
151                        Op::Gt => ">",
152                        Op::Lte => "<=",
153                        Op::Gte => ">=",
154                        Op::And => "and",
155                        Op::Or => "or",
156                        Op::Concat => "..",
157                        _ => "?",
158                    };
159                    format!("R{a} = R{b} {sym} R{c}")
160                }
161
162                // AB: unary
163                Op::Neg => format!("R{a} = -R{b}"),
164                Op::Not => format!("R{a} = not R{b}"),
165
166                // ABx: jumps (signed offset)
167                Op::Jump => {
168                    let target = offset as i32 + 1 + sbx as i32;
169                    format!("-> {target:04}")
170                }
171                Op::JumpIfFalse => {
172                    let target = offset as i32 + 1 + sbx as i32;
173                    format!("R{a} ? -> {target:04}")
174                }
175                Op::JumpIfTrue => {
176                    let target = offset as i32 + 1 + sbx as i32;
177                    format!("R{a} ? -> {target:04}")
178                }
179
180                // ABC: call
181                Op::Call => {
182                    if c == 0 {
183                        format!("R{a} = call R{b}()")
184                    } else {
185                        format!("R{a} = call R{b}(R{}..R{})", b + 1, b + c)
186                    }
187                }
188
189                // A: return
190                Op::Return => format!("R{a}"),
191
192                // ABx: closure
193                Op::Closure => {
194                    let val = self.format_constant(bx as usize);
195                    format!("R{a} = closure K{bx} ({val})")
196                }
197
198                // ABC: data structures
199                Op::NewList => format!("R{a} = list(R{}..R{})", b, b + c),
200                Op::GetIndex => format!("R{a} = R{b}[R{c}]"),
201                Op::SetIndex => format!("R{b}[R{c}] = R{a}"),
202                Op::NewMap => format!("R{a} = map(R{b}, {c} pairs)"),
203
204                // ABC: table ops
205                Op::TablePipe => format!("R{a} = table_pipe(K{b}, R{c})"),
206
207                // ABx: builtin call (Bx=builtin_id, followed by extra word for arg count + first arg)
208                Op::CallBuiltin => {
209                    let builtin_id = decode_bx(inst);
210                    let builtin_name = BuiltinId::try_from(builtin_id)
211                        .map(|b| b.name())
212                        .unwrap_or("<unknown>");
213                    // Next instruction: A=arg_count, B=first_arg_reg
214                    let (argc, first_arg) = if offset + 1 < self.code.len() {
215                        let next = self.code[offset + 1];
216                        (decode_a(next), decode_b(next))
217                    } else {
218                        (0, 0)
219                    };
220                    offset += 1; // skip the extra word
221                    format!("R{a} = {builtin_name}(R{first_arg}, argc={argc})")
222                }
223
224                // AB: iteration
225                Op::ForIter => {
226                    // Next instruction has jump offset in Bx
227                    let jump_word = if offset + 1 < self.code.len() {
228                        self.code[offset + 1]
229                    } else {
230                        0
231                    };
232                    let jump_sbx = decode_sbx(jump_word);
233                    let target = (offset + 2) as i32 + jump_sbx as i32;
234                    offset += 1;
235                    format!("R{b} = next(R{a}), done -> {target:04}")
236                }
237                Op::ForPrep => format!("R{a} = iter(R{b})"),
238
239                // ABC: pattern matching
240                Op::TestMatch => format!("R{c} = (R{a} matches R{b})"),
241
242                // AB: null coalesce
243                Op::NullCoalesce => format!("R{a} = R{a} ?? R{b}"),
244
245                // ABC: member access
246                Op::GetMember => {
247                    let field = self.format_constant(c as usize);
248                    format!("R{a} = R{b}.{field}")
249                }
250
251                // Interpolate: A=dest, B=template const, C=values start
252                Op::Interpolate => {
253                    let argc = if offset + 1 < self.code.len() {
254                        decode_a(self.code[offset + 1])
255                    } else {
256                        0
257                    };
258                    offset += 1;
259                    format!("R{a} = interpolate(K{b}, R{c}, argc={argc})")
260                }
261
262                // Special domain ops
263                Op::Train => format!("R{a} = train(K{b}, K{c})"),
264                Op::PipelineExec => format!("R{a} = pipeline(K{b}, K{c})"),
265                Op::StreamExec => format!("R{a} = stream(K{b}, R{c})"),
266                Op::ConnectorDecl => format!("R{a} = connector(K{b}, K{c})"),
267
268                // Phase 5: structs, enums, methods, exceptions, imports
269                Op::NewStruct => {
270                    let type_name = self.format_constant(b as usize);
271                    if c & 0x80 != 0 {
272                        format!("R{a} = struct_decl({type_name})")
273                    } else {
274                        format!("R{a} = new {type_name}({c} fields)")
275                    }
276                }
277                Op::SetMember => {
278                    let field = self.format_constant(b as usize);
279                    format!("R{a}.{field} = R{c}")
280                }
281                Op::NewEnum => {
282                    let variant = self.format_constant(b as usize);
283                    let argc = if offset + 1 < self.code.len() {
284                        decode_a(self.code[offset + 1])
285                    } else {
286                        0
287                    };
288                    offset += 1;
289                    format!("R{a} = enum {variant}(R{c}, argc={argc})")
290                }
291                Op::MatchEnum => {
292                    let variant = self.format_constant(b as usize);
293                    format!("R{c} = (R{a} is {variant})")
294                }
295                Op::MethodCall => {
296                    let method = self.format_constant(c as usize);
297                    let extra = if offset + 1 < self.code.len() {
298                        let w = self.code[offset + 1];
299                        let args_start = decode_a(w);
300                        let arg_count = decode_b(w);
301                        offset += 1;
302                        format!("(R{args_start}, argc={arg_count})")
303                    } else {
304                        String::new()
305                    };
306                    format!("R{a} = R{b}.{method}{extra}")
307                }
308                Op::Throw => format!("throw R{a}"),
309                Op::TryBegin => {
310                    let target = offset as i32 + 1 + sbx as i32;
311                    format!("catch -> {target:04}")
312                }
313                Op::TryEnd => "end_try".to_string(),
314                Op::Import => {
315                    let path = self.format_constant(bx as usize);
316                    format!("R{a} = import({path})")
317                }
318
319                // Phase 7: concurrency
320                Op::Await => format!("R{a} = await R{b}"),
321
322                // Phase 8: generators
323                Op::Yield => format!("yield R{a}"),
324
325                // Phase 10: type system
326                Op::TryPropagate => format!("R{a} = try R{b}"),
327
328                // Phase 17: pattern matching
329                Op::ExtractField => format!("R{a} = R{b}[{c}]"),
330                Op::ExtractNamedField => {
331                    let field_name = self.format_constant(c as usize);
332                    format!("R{a} = R{b}.{field_name}")
333                }
334
335                // Phase 28: ownership & move semantics
336                Op::LoadMoved => format!("R{a} = <moved>"),
337                Op::MakeRef => format!("R{a} = &R{b}"),
338                Op::ParallelFor => {
339                    let body = self.format_constant(b as usize);
340                    format!("parallel_for R{a}, {body}")
341                }
342                // Phase 34: AI Agent Framework
343                Op::AgentExec => format!("R{a} = agent(K{b}, K{c})"),
344            };
345
346            out.push_str(&format!(
347                "{line_num}  {inst_offset:04}    {:<16}{args}\n",
348                op.name()
349            ));
350
351            offset += 1;
352        }
353
354        // Disassemble child prototypes
355        for (i, constant) in self.constants.iter().enumerate() {
356            if let Constant::Prototype(child) = constant {
357                out.push_str(&format!("\n--- K{i} ---\n"));
358                out.push_str(&child.disassemble());
359            }
360        }
361
362        out
363    }
364
365    /// Format a constant value for display, truncating strings to 20 chars.
366    fn format_constant(&self, index: usize) -> String {
367        if index >= self.constants.len() {
368            return format!("K{index}?");
369        }
370        match &self.constants[index] {
371            Constant::Int(n) => format!("{n}"),
372            Constant::Float(f) => format!("{f}"),
373            Constant::String(s) => {
374                if s.len() > 20 {
375                    format!("\"{}...\"", &s[..20])
376                } else {
377                    format!("\"{s}\"")
378                }
379            }
380            Constant::Prototype(p) => {
381                let name = if p.name.is_empty() { "<anon>" } else { &p.name };
382                format!("fn {name}")
383            }
384            Constant::Decimal(s) => format!("{s}d"),
385            Constant::AstExpr(_) => "<ast_expr>".to_string(),
386            Constant::AstExprList(_) => "<ast_expr_list>".to_string(),
387        }
388    }
389}
390
391/// Constant pool entry.
392#[derive(Debug, Clone)]
393pub enum Constant {
394    Int(i64),
395    Float(f64),
396    String(Arc<str>),
397    /// Decimal literal string — parsed to rust_decimal::Decimal at runtime
398    Decimal(Arc<str>),
399    /// A nested function prototype
400    Prototype(Arc<Prototype>),
401    /// Raw AST expression — used for table pipe operations
402    /// so the VM can pass it to translate_expr at runtime
403    AstExpr(Box<AstExpr>),
404    /// A list of AST expressions (for table op args)
405    AstExprList(Vec<AstExpr>),
406}
407
408/// How to capture an upvalue from the enclosing function.
409#[derive(Debug, Clone, Copy)]
410pub struct UpvalueDef {
411    /// If true, capture from enclosing function's locals.
412    /// If false, capture from enclosing function's upvalues.
413    pub is_local: bool,
414    /// Index into enclosing function's locals or upvalues.
415    pub index: u8,
416}
417
418/// Builtin function identifiers — avoids string comparisons in the VM hot loop.
419#[derive(Debug, Clone, Copy, PartialEq, Eq)]
420#[repr(u16)]
421pub enum BuiltinId {
422    Print = 0,
423    Println = 1,
424    Len = 2,
425    Str = 3,
426    Int = 4,
427    Float = 5,
428    Abs = 6,
429    Min = 7,
430    Max = 8,
431    Range = 9,
432    Push = 10,
433    TypeOf = 11,
434    Map = 12,
435    Filter = 13,
436    Reduce = 14,
437    Sum = 15,
438    Any = 16,
439    All = 17,
440    ReadCsv = 18,
441    ReadParquet = 19,
442    WriteCsv = 20,
443    WriteParquet = 21,
444    Collect = 22,
445    Show = 23,
446    Describe = 24,
447    Head = 25,
448    Postgres = 26,
449    // AI builtins
450    Tensor = 27,
451    TensorZeros = 28,
452    TensorOnes = 29,
453    TensorShape = 30,
454    TensorReshape = 31,
455    TensorTranspose = 32,
456    TensorSum = 33,
457    TensorMean = 34,
458    TensorDot = 35,
459    Predict = 36,
460    Similarity = 37,
461    AiComplete = 38,
462    AiChat = 39,
463    ModelSave = 40,
464    ModelLoad = 41,
465    ModelRegister = 42,
466    ModelList = 43,
467    ModelGet = 44,
468    // Streaming builtins
469    AlertSlack = 45,
470    AlertWebhook = 46,
471    Emit = 47,
472    Lineage = 48,
473    RunPipeline = 49,
474    // Phase 5: Math builtins
475    Sqrt = 50,
476    Pow = 51,
477    Floor = 52,
478    Ceil = 53,
479    Round = 54,
480    Sin = 55,
481    Cos = 56,
482    Tan = 57,
483    Log = 58,
484    Log2 = 59,
485    Log10 = 60,
486    Join = 61,
487    // Phase 5: HTTP builtins
488    HttpGet = 62,
489    HttpPost = 63,
490    // Phase 5: Assert builtins
491    Assert = 64,
492    AssertEq = 65,
493    // Phase 6: Stdlib & Ecosystem
494    JsonParse = 66,
495    JsonStringify = 67,
496    MapFrom = 68,
497    ReadFile = 69,
498    WriteFile = 70,
499    AppendFile = 71,
500    FileExists = 72,
501    ListDir = 73,
502    EnvGet = 74,
503    EnvSet = 75,
504    RegexMatch = 76,
505    RegexFind = 77,
506    RegexReplace = 78,
507    Now = 79,
508    DateFormat = 80,
509    DateParse = 81,
510    Zip = 82,
511    Enumerate = 83,
512    Bool = 84,
513    // Phase 7: Concurrency
514    Spawn = 85,
515    Sleep = 86,
516    Channel = 87,
517    Send = 88,
518    Recv = 89,
519    TryRecv = 90,
520    AwaitAll = 91,
521    Pmap = 92,
522    Timeout = 93,
523    // Phase 8: Iterators & Generators
524    Next = 94,
525    IsGenerator = 95,
526    Iter = 96,
527    Take = 97,
528    Skip_ = 98,
529    GenCollect = 99,
530    GenMap = 100,
531    GenFilter = 101,
532    Chain = 102,
533    GenZip = 103,
534    GenEnumerate = 104,
535    // Phase 10: Type system
536    Ok = 105,
537    Err_ = 106,
538    IsOk = 107,
539    IsErr = 108,
540    Unwrap = 109,
541    SetFrom = 110,
542    SetAdd = 111,
543    SetRemove = 112,
544    SetContains = 113,
545    SetUnion = 114,
546    SetIntersection = 115,
547    SetDifference = 116,
548    // Phase 15: Data Quality & Connectors
549    FillNull = 117,
550    DropNull = 118,
551    Dedup = 119,
552    Clamp = 120,
553    DataProfile = 121,
554    RowCount = 122,
555    NullRate = 123,
556    IsUnique = 124,
557    IsEmail = 125,
558    IsUrl = 126,
559    IsPhone = 127,
560    IsBetween = 128,
561    Levenshtein = 129,
562    Soundex = 130,
563    ReadMysql = 131,
564    RedisConnect = 132,
565    RedisGet = 133,
566    RedisSet = 134,
567    RedisDel = 135,
568    GraphqlQuery = 136,
569    RegisterS3 = 137,
570    // Phase 20: Python FFI
571    PyImport = 138,
572    PyCall = 139,
573    PyEval = 140,
574    PyGetAttr = 141,
575    PySetAttr = 142,
576    PyToTl = 143,
577    // Phase 21: Schema Evolution
578    SchemaRegister = 144,
579    SchemaGet = 145,
580    SchemaLatest = 146,
581    SchemaHistory = 147,
582    SchemaCheck = 148,
583    SchemaDiff = 149,
584    SchemaApplyMigration = 150,
585    SchemaVersions = 151,
586    SchemaFields = 152,
587    // Phase 22: Advanced Types
588    Decimal = 153,
589    // Phase 23: Security & Access Control
590    SecretGet = 154,
591    SecretSet = 155,
592    SecretDelete = 156,
593    SecretList = 157,
594    CheckPermission = 158,
595    MaskEmail = 159,
596    MaskPhone = 160,
597    MaskCreditCard = 161,
598    Redact = 162,
599    Hash = 163,
600    // Phase 24: Async/Await
601    AsyncReadFile = 164,
602    AsyncWriteFile = 165,
603    AsyncHttpGet = 166,
604    AsyncHttpPost = 167,
605    AsyncSleep = 168,
606    Select = 169,
607    AsyncMap = 170,
608    AsyncFilter = 171,
609    RaceAll = 172,
610    // Phase 27: Data Error Hierarchy
611    IsError = 173,
612    ErrorType = 174,
613    // Phase 32: GPU Tensor Support
614    GpuAvailable = 175,
615    ToGpu = 176,
616    ToCpu = 177,
617    GpuMatmul = 178,
618    GpuBatchPredict = 179,
619    // Phase 33: SQLite
620    ReadSqlite = 180,
621    WriteSqlite = 181,
622    // Phase 34: AI Agent Framework
623    Embed = 182,
624    HttpRequest = 183,
625    RunAgent = 184,
626    // Phase E5: Random & Sampling
627    Random = 185,
628    RandomInt = 186,
629    Sample = 187,
630    // Phase E6: Math builtins
631    Exp = 188,
632    IsNan = 189,
633    IsInfinite = 190,
634    Sign = 191,
635    // Phase E8: Table assertion
636    AssertTableEq = 192,
637    // Phase F1: Date/Time builtins
638    Today = 193,
639    DateAdd = 194,
640    DateDiff = 195,
641    DateTrunc = 196,
642    DateExtract = 197,
643    StreamAgent = 198,
644    // Aliases & new builtins
645    PostgresQuery = 199,
646    Fold = 200,
647    TlConfigResolve = 201,
648    // Phase 35: New connectors
649    ReadDuckDb = 202,
650    WriteDuckDb = 203,
651    ReadRedshift = 204,
652    ReadMssql = 205,
653    ReadSnowflake = 206,
654    ReadBigQuery = 207,
655    ReadDatabricks = 208,
656    ReadClickHouse = 209,
657    ReadMongo = 210,
658    // Phase 35: SFTP/SCP
659    SftpDownload = 211,
660    SftpUpload = 212,
661    SftpList = 213,
662    SftpReadCsv = 214,
663    SftpReadParquet = 215,
664    // MCP builtins (Phase 3)
665    McpConnect = 216,
666    McpListTools = 217,
667    McpCallTool = 218,
668    McpDisconnect = 219,
669    McpServe = 220,
670    McpServerInfo = 221,
671    McpPing = 222,
672    McpListResources = 223,
673    McpReadResource = 224,
674    McpListPrompts = 225,
675    McpGetPrompt = 226,
676}
677
678impl TryFrom<u16> for BuiltinId {
679    type Error = u16;
680
681    fn try_from(value: u16) -> Result<Self, Self::Error> {
682        match value {
683            0 => Ok(BuiltinId::Print),
684            1 => Ok(BuiltinId::Println),
685            2 => Ok(BuiltinId::Len),
686            3 => Ok(BuiltinId::Str),
687            4 => Ok(BuiltinId::Int),
688            5 => Ok(BuiltinId::Float),
689            6 => Ok(BuiltinId::Abs),
690            7 => Ok(BuiltinId::Min),
691            8 => Ok(BuiltinId::Max),
692            9 => Ok(BuiltinId::Range),
693            10 => Ok(BuiltinId::Push),
694            11 => Ok(BuiltinId::TypeOf),
695            12 => Ok(BuiltinId::Map),
696            13 => Ok(BuiltinId::Filter),
697            14 => Ok(BuiltinId::Reduce),
698            15 => Ok(BuiltinId::Sum),
699            16 => Ok(BuiltinId::Any),
700            17 => Ok(BuiltinId::All),
701            18 => Ok(BuiltinId::ReadCsv),
702            19 => Ok(BuiltinId::ReadParquet),
703            20 => Ok(BuiltinId::WriteCsv),
704            21 => Ok(BuiltinId::WriteParquet),
705            22 => Ok(BuiltinId::Collect),
706            23 => Ok(BuiltinId::Show),
707            24 => Ok(BuiltinId::Describe),
708            25 => Ok(BuiltinId::Head),
709            26 => Ok(BuiltinId::Postgres),
710            27 => Ok(BuiltinId::Tensor),
711            28 => Ok(BuiltinId::TensorZeros),
712            29 => Ok(BuiltinId::TensorOnes),
713            30 => Ok(BuiltinId::TensorShape),
714            31 => Ok(BuiltinId::TensorReshape),
715            32 => Ok(BuiltinId::TensorTranspose),
716            33 => Ok(BuiltinId::TensorSum),
717            34 => Ok(BuiltinId::TensorMean),
718            35 => Ok(BuiltinId::TensorDot),
719            36 => Ok(BuiltinId::Predict),
720            37 => Ok(BuiltinId::Similarity),
721            38 => Ok(BuiltinId::AiComplete),
722            39 => Ok(BuiltinId::AiChat),
723            40 => Ok(BuiltinId::ModelSave),
724            41 => Ok(BuiltinId::ModelLoad),
725            42 => Ok(BuiltinId::ModelRegister),
726            43 => Ok(BuiltinId::ModelList),
727            44 => Ok(BuiltinId::ModelGet),
728            45 => Ok(BuiltinId::AlertSlack),
729            46 => Ok(BuiltinId::AlertWebhook),
730            47 => Ok(BuiltinId::Emit),
731            48 => Ok(BuiltinId::Lineage),
732            49 => Ok(BuiltinId::RunPipeline),
733            50 => Ok(BuiltinId::Sqrt),
734            51 => Ok(BuiltinId::Pow),
735            52 => Ok(BuiltinId::Floor),
736            53 => Ok(BuiltinId::Ceil),
737            54 => Ok(BuiltinId::Round),
738            55 => Ok(BuiltinId::Sin),
739            56 => Ok(BuiltinId::Cos),
740            57 => Ok(BuiltinId::Tan),
741            58 => Ok(BuiltinId::Log),
742            59 => Ok(BuiltinId::Log2),
743            60 => Ok(BuiltinId::Log10),
744            61 => Ok(BuiltinId::Join),
745            62 => Ok(BuiltinId::HttpGet),
746            63 => Ok(BuiltinId::HttpPost),
747            64 => Ok(BuiltinId::Assert),
748            65 => Ok(BuiltinId::AssertEq),
749            66 => Ok(BuiltinId::JsonParse),
750            67 => Ok(BuiltinId::JsonStringify),
751            68 => Ok(BuiltinId::MapFrom),
752            69 => Ok(BuiltinId::ReadFile),
753            70 => Ok(BuiltinId::WriteFile),
754            71 => Ok(BuiltinId::AppendFile),
755            72 => Ok(BuiltinId::FileExists),
756            73 => Ok(BuiltinId::ListDir),
757            74 => Ok(BuiltinId::EnvGet),
758            75 => Ok(BuiltinId::EnvSet),
759            76 => Ok(BuiltinId::RegexMatch),
760            77 => Ok(BuiltinId::RegexFind),
761            78 => Ok(BuiltinId::RegexReplace),
762            79 => Ok(BuiltinId::Now),
763            80 => Ok(BuiltinId::DateFormat),
764            81 => Ok(BuiltinId::DateParse),
765            82 => Ok(BuiltinId::Zip),
766            83 => Ok(BuiltinId::Enumerate),
767            84 => Ok(BuiltinId::Bool),
768            85 => Ok(BuiltinId::Spawn),
769            86 => Ok(BuiltinId::Sleep),
770            87 => Ok(BuiltinId::Channel),
771            88 => Ok(BuiltinId::Send),
772            89 => Ok(BuiltinId::Recv),
773            90 => Ok(BuiltinId::TryRecv),
774            91 => Ok(BuiltinId::AwaitAll),
775            92 => Ok(BuiltinId::Pmap),
776            93 => Ok(BuiltinId::Timeout),
777            94 => Ok(BuiltinId::Next),
778            95 => Ok(BuiltinId::IsGenerator),
779            96 => Ok(BuiltinId::Iter),
780            97 => Ok(BuiltinId::Take),
781            98 => Ok(BuiltinId::Skip_),
782            99 => Ok(BuiltinId::GenCollect),
783            100 => Ok(BuiltinId::GenMap),
784            101 => Ok(BuiltinId::GenFilter),
785            102 => Ok(BuiltinId::Chain),
786            103 => Ok(BuiltinId::GenZip),
787            104 => Ok(BuiltinId::GenEnumerate),
788            105 => Ok(BuiltinId::Ok),
789            106 => Ok(BuiltinId::Err_),
790            107 => Ok(BuiltinId::IsOk),
791            108 => Ok(BuiltinId::IsErr),
792            109 => Ok(BuiltinId::Unwrap),
793            110 => Ok(BuiltinId::SetFrom),
794            111 => Ok(BuiltinId::SetAdd),
795            112 => Ok(BuiltinId::SetRemove),
796            113 => Ok(BuiltinId::SetContains),
797            114 => Ok(BuiltinId::SetUnion),
798            115 => Ok(BuiltinId::SetIntersection),
799            116 => Ok(BuiltinId::SetDifference),
800            117 => Ok(BuiltinId::FillNull),
801            118 => Ok(BuiltinId::DropNull),
802            119 => Ok(BuiltinId::Dedup),
803            120 => Ok(BuiltinId::Clamp),
804            121 => Ok(BuiltinId::DataProfile),
805            122 => Ok(BuiltinId::RowCount),
806            123 => Ok(BuiltinId::NullRate),
807            124 => Ok(BuiltinId::IsUnique),
808            125 => Ok(BuiltinId::IsEmail),
809            126 => Ok(BuiltinId::IsUrl),
810            127 => Ok(BuiltinId::IsPhone),
811            128 => Ok(BuiltinId::IsBetween),
812            129 => Ok(BuiltinId::Levenshtein),
813            130 => Ok(BuiltinId::Soundex),
814            131 => Ok(BuiltinId::ReadMysql),
815            132 => Ok(BuiltinId::RedisConnect),
816            133 => Ok(BuiltinId::RedisGet),
817            134 => Ok(BuiltinId::RedisSet),
818            135 => Ok(BuiltinId::RedisDel),
819            136 => Ok(BuiltinId::GraphqlQuery),
820            137 => Ok(BuiltinId::RegisterS3),
821            138 => Ok(BuiltinId::PyImport),
822            139 => Ok(BuiltinId::PyCall),
823            140 => Ok(BuiltinId::PyEval),
824            141 => Ok(BuiltinId::PyGetAttr),
825            142 => Ok(BuiltinId::PySetAttr),
826            143 => Ok(BuiltinId::PyToTl),
827            144 => Ok(BuiltinId::SchemaRegister),
828            145 => Ok(BuiltinId::SchemaGet),
829            146 => Ok(BuiltinId::SchemaLatest),
830            147 => Ok(BuiltinId::SchemaHistory),
831            148 => Ok(BuiltinId::SchemaCheck),
832            149 => Ok(BuiltinId::SchemaDiff),
833            150 => Ok(BuiltinId::SchemaApplyMigration),
834            151 => Ok(BuiltinId::SchemaVersions),
835            152 => Ok(BuiltinId::SchemaFields),
836            153 => Ok(BuiltinId::Decimal),
837            154 => Ok(BuiltinId::SecretGet),
838            155 => Ok(BuiltinId::SecretSet),
839            156 => Ok(BuiltinId::SecretDelete),
840            157 => Ok(BuiltinId::SecretList),
841            158 => Ok(BuiltinId::CheckPermission),
842            159 => Ok(BuiltinId::MaskEmail),
843            160 => Ok(BuiltinId::MaskPhone),
844            161 => Ok(BuiltinId::MaskCreditCard),
845            162 => Ok(BuiltinId::Redact),
846            163 => Ok(BuiltinId::Hash),
847            164 => Ok(BuiltinId::AsyncReadFile),
848            165 => Ok(BuiltinId::AsyncWriteFile),
849            166 => Ok(BuiltinId::AsyncHttpGet),
850            167 => Ok(BuiltinId::AsyncHttpPost),
851            168 => Ok(BuiltinId::AsyncSleep),
852            169 => Ok(BuiltinId::Select),
853            170 => Ok(BuiltinId::AsyncMap),
854            171 => Ok(BuiltinId::AsyncFilter),
855            172 => Ok(BuiltinId::RaceAll),
856            173 => Ok(BuiltinId::IsError),
857            174 => Ok(BuiltinId::ErrorType),
858            175 => Ok(BuiltinId::GpuAvailable),
859            176 => Ok(BuiltinId::ToGpu),
860            177 => Ok(BuiltinId::ToCpu),
861            178 => Ok(BuiltinId::GpuMatmul),
862            179 => Ok(BuiltinId::GpuBatchPredict),
863            180 => Ok(BuiltinId::ReadSqlite),
864            181 => Ok(BuiltinId::WriteSqlite),
865            182 => Ok(BuiltinId::Embed),
866            183 => Ok(BuiltinId::HttpRequest),
867            184 => Ok(BuiltinId::RunAgent),
868            185 => Ok(BuiltinId::Random),
869            186 => Ok(BuiltinId::RandomInt),
870            187 => Ok(BuiltinId::Sample),
871            188 => Ok(BuiltinId::Exp),
872            189 => Ok(BuiltinId::IsNan),
873            190 => Ok(BuiltinId::IsInfinite),
874            191 => Ok(BuiltinId::Sign),
875            192 => Ok(BuiltinId::AssertTableEq),
876            193 => Ok(BuiltinId::Today),
877            194 => Ok(BuiltinId::DateAdd),
878            195 => Ok(BuiltinId::DateDiff),
879            196 => Ok(BuiltinId::DateTrunc),
880            197 => Ok(BuiltinId::DateExtract),
881            198 => Ok(BuiltinId::StreamAgent),
882            199 => Ok(BuiltinId::PostgresQuery),
883            200 => Ok(BuiltinId::Fold),
884            201 => Ok(BuiltinId::TlConfigResolve),
885            202 => Ok(BuiltinId::ReadDuckDb),
886            203 => Ok(BuiltinId::WriteDuckDb),
887            204 => Ok(BuiltinId::ReadRedshift),
888            205 => Ok(BuiltinId::ReadMssql),
889            206 => Ok(BuiltinId::ReadSnowflake),
890            207 => Ok(BuiltinId::ReadBigQuery),
891            208 => Ok(BuiltinId::ReadDatabricks),
892            209 => Ok(BuiltinId::ReadClickHouse),
893            210 => Ok(BuiltinId::ReadMongo),
894            211 => Ok(BuiltinId::SftpDownload),
895            212 => Ok(BuiltinId::SftpUpload),
896            213 => Ok(BuiltinId::SftpList),
897            214 => Ok(BuiltinId::SftpReadCsv),
898            215 => Ok(BuiltinId::SftpReadParquet),
899            216 => Ok(BuiltinId::McpConnect),
900            217 => Ok(BuiltinId::McpListTools),
901            218 => Ok(BuiltinId::McpCallTool),
902            219 => Ok(BuiltinId::McpDisconnect),
903            220 => Ok(BuiltinId::McpServe),
904            221 => Ok(BuiltinId::McpServerInfo),
905            222 => Ok(BuiltinId::McpPing),
906            223 => Ok(BuiltinId::McpListResources),
907            224 => Ok(BuiltinId::McpReadResource),
908            225 => Ok(BuiltinId::McpListPrompts),
909            226 => Ok(BuiltinId::McpGetPrompt),
910            _ => Err(value),
911        }
912    }
913}
914
915impl BuiltinId {
916    pub fn from_name(name: &str) -> Option<BuiltinId> {
917        match name {
918            "print" => Some(BuiltinId::Print),
919            "println" => Some(BuiltinId::Println),
920            "len" => Some(BuiltinId::Len),
921            "str" => Some(BuiltinId::Str),
922            "int" => Some(BuiltinId::Int),
923            "float" => Some(BuiltinId::Float),
924            "abs" => Some(BuiltinId::Abs),
925            "min" => Some(BuiltinId::Min),
926            "max" => Some(BuiltinId::Max),
927            "range" => Some(BuiltinId::Range),
928            "push" => Some(BuiltinId::Push),
929            "type_of" => Some(BuiltinId::TypeOf),
930            "map" => Some(BuiltinId::Map),
931            "filter" => Some(BuiltinId::Filter),
932            "reduce" => Some(BuiltinId::Reduce),
933            "sum" => Some(BuiltinId::Sum),
934            "any" => Some(BuiltinId::Any),
935            "all" => Some(BuiltinId::All),
936            "read_csv" => Some(BuiltinId::ReadCsv),
937            "read_parquet" => Some(BuiltinId::ReadParquet),
938            "write_csv" => Some(BuiltinId::WriteCsv),
939            "write_parquet" => Some(BuiltinId::WriteParquet),
940            "collect" => Some(BuiltinId::Collect),
941            "show" => Some(BuiltinId::Show),
942            "describe" => Some(BuiltinId::Describe),
943            "head" => Some(BuiltinId::Head),
944            "postgres" | "read_postgres" => Some(BuiltinId::Postgres),
945            "tensor" => Some(BuiltinId::Tensor),
946            "tensor_zeros" => Some(BuiltinId::TensorZeros),
947            "tensor_ones" => Some(BuiltinId::TensorOnes),
948            "tensor_shape" => Some(BuiltinId::TensorShape),
949            "tensor_reshape" => Some(BuiltinId::TensorReshape),
950            "tensor_transpose" => Some(BuiltinId::TensorTranspose),
951            "tensor_sum" => Some(BuiltinId::TensorSum),
952            "tensor_mean" => Some(BuiltinId::TensorMean),
953            "tensor_dot" => Some(BuiltinId::TensorDot),
954            "predict" => Some(BuiltinId::Predict),
955            "similarity" => Some(BuiltinId::Similarity),
956            "ai_complete" => Some(BuiltinId::AiComplete),
957            "ai_chat" => Some(BuiltinId::AiChat),
958            "model_save" => Some(BuiltinId::ModelSave),
959            "model_load" => Some(BuiltinId::ModelLoad),
960            "model_register" => Some(BuiltinId::ModelRegister),
961            "model_list" => Some(BuiltinId::ModelList),
962            "model_get" => Some(BuiltinId::ModelGet),
963            "alert_slack" => Some(BuiltinId::AlertSlack),
964            "alert_webhook" => Some(BuiltinId::AlertWebhook),
965            "emit" => Some(BuiltinId::Emit),
966            "lineage" => Some(BuiltinId::Lineage),
967            "run_pipeline" => Some(BuiltinId::RunPipeline),
968            "sqrt" => Some(BuiltinId::Sqrt),
969            "pow" => Some(BuiltinId::Pow),
970            "floor" => Some(BuiltinId::Floor),
971            "ceil" => Some(BuiltinId::Ceil),
972            "round" => Some(BuiltinId::Round),
973            "sin" => Some(BuiltinId::Sin),
974            "cos" => Some(BuiltinId::Cos),
975            "tan" => Some(BuiltinId::Tan),
976            "log" => Some(BuiltinId::Log),
977            "log2" => Some(BuiltinId::Log2),
978            "log10" => Some(BuiltinId::Log10),
979            "join" => Some(BuiltinId::Join),
980            "http_get" => Some(BuiltinId::HttpGet),
981            "http_post" => Some(BuiltinId::HttpPost),
982            "assert" => Some(BuiltinId::Assert),
983            "assert_eq" => Some(BuiltinId::AssertEq),
984            "json_parse" => Some(BuiltinId::JsonParse),
985            "json_stringify" => Some(BuiltinId::JsonStringify),
986            "map_from" => Some(BuiltinId::MapFrom),
987            "read_file" => Some(BuiltinId::ReadFile),
988            "write_file" => Some(BuiltinId::WriteFile),
989            "append_file" => Some(BuiltinId::AppendFile),
990            "file_exists" => Some(BuiltinId::FileExists),
991            "list_dir" => Some(BuiltinId::ListDir),
992            "env_get" => Some(BuiltinId::EnvGet),
993            "env_set" => Some(BuiltinId::EnvSet),
994            "regex_match" => Some(BuiltinId::RegexMatch),
995            "regex_find" => Some(BuiltinId::RegexFind),
996            "regex_replace" => Some(BuiltinId::RegexReplace),
997            "now" => Some(BuiltinId::Now),
998            "date_format" => Some(BuiltinId::DateFormat),
999            "date_parse" => Some(BuiltinId::DateParse),
1000            "zip" => Some(BuiltinId::Zip),
1001            "enumerate" => Some(BuiltinId::Enumerate),
1002            "bool" => Some(BuiltinId::Bool),
1003            "spawn" => Some(BuiltinId::Spawn),
1004            "sleep" => Some(BuiltinId::Sleep),
1005            "channel" => Some(BuiltinId::Channel),
1006            "send" => Some(BuiltinId::Send),
1007            "recv" => Some(BuiltinId::Recv),
1008            "try_recv" => Some(BuiltinId::TryRecv),
1009            "await_all" => Some(BuiltinId::AwaitAll),
1010            "pmap" => Some(BuiltinId::Pmap),
1011            "timeout" => Some(BuiltinId::Timeout),
1012            "next" => Some(BuiltinId::Next),
1013            "is_generator" => Some(BuiltinId::IsGenerator),
1014            "iter" => Some(BuiltinId::Iter),
1015            "take" => Some(BuiltinId::Take),
1016            "skip" => Some(BuiltinId::Skip_),
1017            "gen_collect" => Some(BuiltinId::GenCollect),
1018            "gen_map" => Some(BuiltinId::GenMap),
1019            "gen_filter" => Some(BuiltinId::GenFilter),
1020            "chain" => Some(BuiltinId::Chain),
1021            "gen_zip" => Some(BuiltinId::GenZip),
1022            "gen_enumerate" => Some(BuiltinId::GenEnumerate),
1023            "Ok" => Some(BuiltinId::Ok),
1024            "Err" => Some(BuiltinId::Err_),
1025            "is_ok" => Some(BuiltinId::IsOk),
1026            "is_err" => Some(BuiltinId::IsErr),
1027            "unwrap" => Some(BuiltinId::Unwrap),
1028            "set_from" => Some(BuiltinId::SetFrom),
1029            "set_add" => Some(BuiltinId::SetAdd),
1030            "set_remove" => Some(BuiltinId::SetRemove),
1031            "set_contains" => Some(BuiltinId::SetContains),
1032            "set_union" => Some(BuiltinId::SetUnion),
1033            "set_intersection" => Some(BuiltinId::SetIntersection),
1034            "set_difference" => Some(BuiltinId::SetDifference),
1035            // Phase 15: Data Quality & Connectors
1036            "fill_null" => Some(BuiltinId::FillNull),
1037            "drop_null" => Some(BuiltinId::DropNull),
1038            "dedup" => Some(BuiltinId::Dedup),
1039            "clamp" => Some(BuiltinId::Clamp),
1040            "data_profile" => Some(BuiltinId::DataProfile),
1041            "row_count" => Some(BuiltinId::RowCount),
1042            "null_rate" => Some(BuiltinId::NullRate),
1043            "is_unique" => Some(BuiltinId::IsUnique),
1044            "is_email" => Some(BuiltinId::IsEmail),
1045            "is_url" => Some(BuiltinId::IsUrl),
1046            "is_phone" => Some(BuiltinId::IsPhone),
1047            "is_between" => Some(BuiltinId::IsBetween),
1048            "levenshtein" => Some(BuiltinId::Levenshtein),
1049            "soundex" => Some(BuiltinId::Soundex),
1050            "read_mysql" => Some(BuiltinId::ReadMysql),
1051            "redis_connect" => Some(BuiltinId::RedisConnect),
1052            "redis_get" => Some(BuiltinId::RedisGet),
1053            "redis_set" => Some(BuiltinId::RedisSet),
1054            "redis_del" => Some(BuiltinId::RedisDel),
1055            "graphql_query" => Some(BuiltinId::GraphqlQuery),
1056            "register_s3" => Some(BuiltinId::RegisterS3),
1057            // Phase 20: Python FFI
1058            "py_import" => Some(BuiltinId::PyImport),
1059            "py_call" => Some(BuiltinId::PyCall),
1060            "py_eval" => Some(BuiltinId::PyEval),
1061            "py_getattr" => Some(BuiltinId::PyGetAttr),
1062            "py_setattr" => Some(BuiltinId::PySetAttr),
1063            "py_to_tl" => Some(BuiltinId::PyToTl),
1064            // Phase 21: Schema Evolution
1065            "schema_register" => Some(BuiltinId::SchemaRegister),
1066            "schema_get" => Some(BuiltinId::SchemaGet),
1067            "schema_latest" => Some(BuiltinId::SchemaLatest),
1068            "schema_history" => Some(BuiltinId::SchemaHistory),
1069            "schema_check" => Some(BuiltinId::SchemaCheck),
1070            "schema_diff" => Some(BuiltinId::SchemaDiff),
1071            "schema_apply_migration" => Some(BuiltinId::SchemaApplyMigration),
1072            "schema_versions" => Some(BuiltinId::SchemaVersions),
1073            "schema_fields" => Some(BuiltinId::SchemaFields),
1074            // Phase 22: Advanced Types
1075            "decimal" => Some(BuiltinId::Decimal),
1076            // Phase 23: Security
1077            "secret_get" => Some(BuiltinId::SecretGet),
1078            "secret_set" => Some(BuiltinId::SecretSet),
1079            "secret_delete" => Some(BuiltinId::SecretDelete),
1080            "secret_list" => Some(BuiltinId::SecretList),
1081            "check_permission" => Some(BuiltinId::CheckPermission),
1082            "mask_email" => Some(BuiltinId::MaskEmail),
1083            "mask_phone" => Some(BuiltinId::MaskPhone),
1084            "mask_cc" => Some(BuiltinId::MaskCreditCard),
1085            "redact" => Some(BuiltinId::Redact),
1086            "hash" => Some(BuiltinId::Hash),
1087            // Phase 24: Async
1088            "async_read_file" => Some(BuiltinId::AsyncReadFile),
1089            "async_write_file" => Some(BuiltinId::AsyncWriteFile),
1090            "async_http_get" => Some(BuiltinId::AsyncHttpGet),
1091            "async_http_post" => Some(BuiltinId::AsyncHttpPost),
1092            "async_sleep" => Some(BuiltinId::AsyncSleep),
1093            "select" => Some(BuiltinId::Select),
1094            "async_map" => Some(BuiltinId::AsyncMap),
1095            "async_filter" => Some(BuiltinId::AsyncFilter),
1096            "race_all" => Some(BuiltinId::RaceAll),
1097            // Phase 27: Data Error Hierarchy
1098            "is_error" => Some(BuiltinId::IsError),
1099            "error_type" => Some(BuiltinId::ErrorType),
1100            // Phase 32: GPU Tensor Support
1101            "gpu_available" => Some(BuiltinId::GpuAvailable),
1102            "to_gpu" => Some(BuiltinId::ToGpu),
1103            "to_cpu" => Some(BuiltinId::ToCpu),
1104            "gpu_matmul" => Some(BuiltinId::GpuMatmul),
1105            "gpu_batch_predict" => Some(BuiltinId::GpuBatchPredict),
1106            // Phase 33: SQLite
1107            "read_sqlite" => Some(BuiltinId::ReadSqlite),
1108            "write_sqlite" => Some(BuiltinId::WriteSqlite),
1109            // Phase 34: AI Agent Framework
1110            "embed" => Some(BuiltinId::Embed),
1111            "http_request" => Some(BuiltinId::HttpRequest),
1112            "run_agent" => Some(BuiltinId::RunAgent),
1113            "random" => Some(BuiltinId::Random),
1114            "random_int" => Some(BuiltinId::RandomInt),
1115            "sample" => Some(BuiltinId::Sample),
1116            "exp" => Some(BuiltinId::Exp),
1117            "is_nan" => Some(BuiltinId::IsNan),
1118            "is_infinite" => Some(BuiltinId::IsInfinite),
1119            "sign" => Some(BuiltinId::Sign),
1120            "assert_table_eq" => Some(BuiltinId::AssertTableEq),
1121            "today" => Some(BuiltinId::Today),
1122            "date_add" => Some(BuiltinId::DateAdd),
1123            "date_diff" => Some(BuiltinId::DateDiff),
1124            "date_trunc" => Some(BuiltinId::DateTrunc),
1125            "date_extract" | "extract" => Some(BuiltinId::DateExtract),
1126            "stream_agent" => Some(BuiltinId::StreamAgent),
1127            "postgres_query" => Some(BuiltinId::PostgresQuery),
1128            "fold" => Some(BuiltinId::Fold),
1129            "tl_config_resolve" => Some(BuiltinId::TlConfigResolve),
1130            "duckdb" | "read_duckdb" => Some(BuiltinId::ReadDuckDb),
1131            "write_duckdb" => Some(BuiltinId::WriteDuckDb),
1132            "redshift" | "read_redshift" => Some(BuiltinId::ReadRedshift),
1133            "mssql" | "read_mssql" => Some(BuiltinId::ReadMssql),
1134            "snowflake" | "read_snowflake" => Some(BuiltinId::ReadSnowflake),
1135            "bigquery" | "read_bigquery" => Some(BuiltinId::ReadBigQuery),
1136            "databricks" | "read_databricks" => Some(BuiltinId::ReadDatabricks),
1137            "clickhouse" | "read_clickhouse" => Some(BuiltinId::ReadClickHouse),
1138            "mongo" | "read_mongo" | "read_mongodb" => Some(BuiltinId::ReadMongo),
1139            "sftp_download" => Some(BuiltinId::SftpDownload),
1140            "sftp_upload" => Some(BuiltinId::SftpUpload),
1141            "sftp_list" | "sftp_ls" => Some(BuiltinId::SftpList),
1142            "sftp_read_csv" => Some(BuiltinId::SftpReadCsv),
1143            "sftp_read_parquet" => Some(BuiltinId::SftpReadParquet),
1144            "mcp_connect" => Some(BuiltinId::McpConnect),
1145            "mcp_list_tools" => Some(BuiltinId::McpListTools),
1146            "mcp_call_tool" => Some(BuiltinId::McpCallTool),
1147            "mcp_disconnect" => Some(BuiltinId::McpDisconnect),
1148            "mcp_serve" => Some(BuiltinId::McpServe),
1149            "mcp_server_info" => Some(BuiltinId::McpServerInfo),
1150            "mcp_ping" => Some(BuiltinId::McpPing),
1151            "mcp_list_resources" => Some(BuiltinId::McpListResources),
1152            "mcp_read_resource" => Some(BuiltinId::McpReadResource),
1153            "mcp_list_prompts" => Some(BuiltinId::McpListPrompts),
1154            "mcp_get_prompt" => Some(BuiltinId::McpGetPrompt),
1155            _ => None,
1156        }
1157    }
1158
1159    pub fn name(&self) -> &'static str {
1160        match self {
1161            BuiltinId::Print => "print",
1162            BuiltinId::Println => "println",
1163            BuiltinId::Len => "len",
1164            BuiltinId::Str => "str",
1165            BuiltinId::Int => "int",
1166            BuiltinId::Float => "float",
1167            BuiltinId::Abs => "abs",
1168            BuiltinId::Min => "min",
1169            BuiltinId::Max => "max",
1170            BuiltinId::Range => "range",
1171            BuiltinId::Push => "push",
1172            BuiltinId::TypeOf => "type_of",
1173            BuiltinId::Map => "map",
1174            BuiltinId::Filter => "filter",
1175            BuiltinId::Reduce => "reduce",
1176            BuiltinId::Sum => "sum",
1177            BuiltinId::Any => "any",
1178            BuiltinId::All => "all",
1179            BuiltinId::ReadCsv => "read_csv",
1180            BuiltinId::ReadParquet => "read_parquet",
1181            BuiltinId::WriteCsv => "write_csv",
1182            BuiltinId::WriteParquet => "write_parquet",
1183            BuiltinId::Collect => "collect",
1184            BuiltinId::Show => "show",
1185            BuiltinId::Describe => "describe",
1186            BuiltinId::Head => "head",
1187            BuiltinId::Postgres => "postgres",
1188            BuiltinId::Tensor => "tensor",
1189            BuiltinId::TensorZeros => "tensor_zeros",
1190            BuiltinId::TensorOnes => "tensor_ones",
1191            BuiltinId::TensorShape => "tensor_shape",
1192            BuiltinId::TensorReshape => "tensor_reshape",
1193            BuiltinId::TensorTranspose => "tensor_transpose",
1194            BuiltinId::TensorSum => "tensor_sum",
1195            BuiltinId::TensorMean => "tensor_mean",
1196            BuiltinId::TensorDot => "tensor_dot",
1197            BuiltinId::Predict => "predict",
1198            BuiltinId::Similarity => "similarity",
1199            BuiltinId::AiComplete => "ai_complete",
1200            BuiltinId::AiChat => "ai_chat",
1201            BuiltinId::ModelSave => "model_save",
1202            BuiltinId::ModelLoad => "model_load",
1203            BuiltinId::ModelRegister => "model_register",
1204            BuiltinId::ModelList => "model_list",
1205            BuiltinId::ModelGet => "model_get",
1206            BuiltinId::AlertSlack => "alert_slack",
1207            BuiltinId::AlertWebhook => "alert_webhook",
1208            BuiltinId::Emit => "emit",
1209            BuiltinId::Lineage => "lineage",
1210            BuiltinId::RunPipeline => "run_pipeline",
1211            BuiltinId::Sqrt => "sqrt",
1212            BuiltinId::Pow => "pow",
1213            BuiltinId::Floor => "floor",
1214            BuiltinId::Ceil => "ceil",
1215            BuiltinId::Round => "round",
1216            BuiltinId::Sin => "sin",
1217            BuiltinId::Cos => "cos",
1218            BuiltinId::Tan => "tan",
1219            BuiltinId::Log => "log",
1220            BuiltinId::Log2 => "log2",
1221            BuiltinId::Log10 => "log10",
1222            BuiltinId::Join => "join",
1223            BuiltinId::HttpGet => "http_get",
1224            BuiltinId::HttpPost => "http_post",
1225            BuiltinId::Assert => "assert",
1226            BuiltinId::AssertEq => "assert_eq",
1227            BuiltinId::JsonParse => "json_parse",
1228            BuiltinId::JsonStringify => "json_stringify",
1229            BuiltinId::MapFrom => "map_from",
1230            BuiltinId::ReadFile => "read_file",
1231            BuiltinId::WriteFile => "write_file",
1232            BuiltinId::AppendFile => "append_file",
1233            BuiltinId::FileExists => "file_exists",
1234            BuiltinId::ListDir => "list_dir",
1235            BuiltinId::EnvGet => "env_get",
1236            BuiltinId::EnvSet => "env_set",
1237            BuiltinId::RegexMatch => "regex_match",
1238            BuiltinId::RegexFind => "regex_find",
1239            BuiltinId::RegexReplace => "regex_replace",
1240            BuiltinId::Now => "now",
1241            BuiltinId::DateFormat => "date_format",
1242            BuiltinId::DateParse => "date_parse",
1243            BuiltinId::Zip => "zip",
1244            BuiltinId::Enumerate => "enumerate",
1245            BuiltinId::Bool => "bool",
1246            BuiltinId::Spawn => "spawn",
1247            BuiltinId::Sleep => "sleep",
1248            BuiltinId::Channel => "channel",
1249            BuiltinId::Send => "send",
1250            BuiltinId::Recv => "recv",
1251            BuiltinId::TryRecv => "try_recv",
1252            BuiltinId::AwaitAll => "await_all",
1253            BuiltinId::Pmap => "pmap",
1254            BuiltinId::Timeout => "timeout",
1255            BuiltinId::Next => "next",
1256            BuiltinId::IsGenerator => "is_generator",
1257            BuiltinId::Iter => "iter",
1258            BuiltinId::Take => "take",
1259            BuiltinId::Skip_ => "skip",
1260            BuiltinId::GenCollect => "gen_collect",
1261            BuiltinId::GenMap => "gen_map",
1262            BuiltinId::GenFilter => "gen_filter",
1263            BuiltinId::Chain => "chain",
1264            BuiltinId::GenZip => "gen_zip",
1265            BuiltinId::GenEnumerate => "gen_enumerate",
1266            BuiltinId::Ok => "Ok",
1267            BuiltinId::Err_ => "Err",
1268            BuiltinId::IsOk => "is_ok",
1269            BuiltinId::IsErr => "is_err",
1270            BuiltinId::Unwrap => "unwrap",
1271            BuiltinId::SetFrom => "set_from",
1272            BuiltinId::SetAdd => "set_add",
1273            BuiltinId::SetRemove => "set_remove",
1274            BuiltinId::SetContains => "set_contains",
1275            BuiltinId::SetUnion => "set_union",
1276            BuiltinId::SetIntersection => "set_intersection",
1277            BuiltinId::SetDifference => "set_difference",
1278            // Phase 15: Data Quality & Connectors
1279            BuiltinId::FillNull => "fill_null",
1280            BuiltinId::DropNull => "drop_null",
1281            BuiltinId::Dedup => "dedup",
1282            BuiltinId::Clamp => "clamp",
1283            BuiltinId::DataProfile => "data_profile",
1284            BuiltinId::RowCount => "row_count",
1285            BuiltinId::NullRate => "null_rate",
1286            BuiltinId::IsUnique => "is_unique",
1287            BuiltinId::IsEmail => "is_email",
1288            BuiltinId::IsUrl => "is_url",
1289            BuiltinId::IsPhone => "is_phone",
1290            BuiltinId::IsBetween => "is_between",
1291            BuiltinId::Levenshtein => "levenshtein",
1292            BuiltinId::Soundex => "soundex",
1293            BuiltinId::ReadMysql => "read_mysql",
1294            BuiltinId::RedisConnect => "redis_connect",
1295            BuiltinId::RedisGet => "redis_get",
1296            BuiltinId::RedisSet => "redis_set",
1297            BuiltinId::RedisDel => "redis_del",
1298            BuiltinId::GraphqlQuery => "graphql_query",
1299            BuiltinId::RegisterS3 => "register_s3",
1300            // Phase 20: Python FFI
1301            BuiltinId::PyImport => "py_import",
1302            BuiltinId::PyCall => "py_call",
1303            BuiltinId::PyEval => "py_eval",
1304            BuiltinId::PyGetAttr => "py_getattr",
1305            BuiltinId::PySetAttr => "py_setattr",
1306            BuiltinId::PyToTl => "py_to_tl",
1307            // Phase 21: Schema Evolution
1308            BuiltinId::SchemaRegister => "schema_register",
1309            BuiltinId::SchemaGet => "schema_get",
1310            BuiltinId::SchemaLatest => "schema_latest",
1311            BuiltinId::SchemaHistory => "schema_history",
1312            BuiltinId::SchemaCheck => "schema_check",
1313            BuiltinId::SchemaDiff => "schema_diff",
1314            BuiltinId::SchemaApplyMigration => "schema_apply_migration",
1315            BuiltinId::SchemaVersions => "schema_versions",
1316            BuiltinId::SchemaFields => "schema_fields",
1317            // Phase 22
1318            BuiltinId::Decimal => "decimal",
1319            // Phase 23
1320            BuiltinId::SecretGet => "secret_get",
1321            BuiltinId::SecretSet => "secret_set",
1322            BuiltinId::SecretDelete => "secret_delete",
1323            BuiltinId::SecretList => "secret_list",
1324            BuiltinId::CheckPermission => "check_permission",
1325            BuiltinId::MaskEmail => "mask_email",
1326            BuiltinId::MaskPhone => "mask_phone",
1327            BuiltinId::MaskCreditCard => "mask_cc",
1328            BuiltinId::Redact => "redact",
1329            BuiltinId::Hash => "hash",
1330            // Phase 24
1331            BuiltinId::AsyncReadFile => "async_read_file",
1332            BuiltinId::AsyncWriteFile => "async_write_file",
1333            BuiltinId::AsyncHttpGet => "async_http_get",
1334            BuiltinId::AsyncHttpPost => "async_http_post",
1335            BuiltinId::AsyncSleep => "async_sleep",
1336            BuiltinId::Select => "select",
1337            BuiltinId::AsyncMap => "async_map",
1338            BuiltinId::AsyncFilter => "async_filter",
1339            BuiltinId::RaceAll => "race_all",
1340            // Phase 27
1341            BuiltinId::IsError => "is_error",
1342            BuiltinId::ErrorType => "error_type",
1343            // Phase 32: GPU
1344            BuiltinId::GpuAvailable => "gpu_available",
1345            BuiltinId::ToGpu => "to_gpu",
1346            BuiltinId::ToCpu => "to_cpu",
1347            BuiltinId::GpuMatmul => "gpu_matmul",
1348            BuiltinId::GpuBatchPredict => "gpu_batch_predict",
1349            // Phase 33: SQLite
1350            BuiltinId::ReadSqlite => "read_sqlite",
1351            BuiltinId::WriteSqlite => "write_sqlite",
1352            // Phase 34: AI Agent Framework
1353            BuiltinId::Embed => "embed",
1354            BuiltinId::HttpRequest => "http_request",
1355            BuiltinId::RunAgent => "run_agent",
1356            // Phase E5/E6
1357            BuiltinId::Random => "random",
1358            BuiltinId::RandomInt => "random_int",
1359            BuiltinId::Sample => "sample",
1360            BuiltinId::Exp => "exp",
1361            BuiltinId::IsNan => "is_nan",
1362            BuiltinId::IsInfinite => "is_infinite",
1363            BuiltinId::Sign => "sign",
1364            BuiltinId::AssertTableEq => "assert_table_eq",
1365            BuiltinId::Today => "today",
1366            BuiltinId::DateAdd => "date_add",
1367            BuiltinId::DateDiff => "date_diff",
1368            BuiltinId::DateTrunc => "date_trunc",
1369            BuiltinId::DateExtract => "date_extract",
1370            BuiltinId::StreamAgent => "stream_agent",
1371            BuiltinId::PostgresQuery => "postgres_query",
1372            BuiltinId::Fold => "fold",
1373            BuiltinId::TlConfigResolve => "tl_config_resolve",
1374            BuiltinId::ReadDuckDb => "duckdb",
1375            BuiltinId::WriteDuckDb => "write_duckdb",
1376            BuiltinId::ReadRedshift => "redshift",
1377            BuiltinId::ReadMssql => "mssql",
1378            BuiltinId::ReadSnowflake => "snowflake",
1379            BuiltinId::ReadBigQuery => "bigquery",
1380            BuiltinId::ReadDatabricks => "databricks",
1381            BuiltinId::ReadClickHouse => "clickhouse",
1382            BuiltinId::ReadMongo => "mongo",
1383            BuiltinId::SftpDownload => "sftp_download",
1384            BuiltinId::SftpUpload => "sftp_upload",
1385            BuiltinId::SftpList => "sftp_list",
1386            BuiltinId::SftpReadCsv => "sftp_read_csv",
1387            BuiltinId::SftpReadParquet => "sftp_read_parquet",
1388            BuiltinId::McpConnect => "mcp_connect",
1389            BuiltinId::McpListTools => "mcp_list_tools",
1390            BuiltinId::McpCallTool => "mcp_call_tool",
1391            BuiltinId::McpDisconnect => "mcp_disconnect",
1392            BuiltinId::McpServe => "mcp_serve",
1393            BuiltinId::McpServerInfo => "mcp_server_info",
1394            BuiltinId::McpPing => "mcp_ping",
1395            BuiltinId::McpListResources => "mcp_list_resources",
1396            BuiltinId::McpReadResource => "mcp_read_resource",
1397            BuiltinId::McpListPrompts => "mcp_list_prompts",
1398            BuiltinId::McpGetPrompt => "mcp_get_prompt",
1399        }
1400    }
1401}
1402
1403/// Table pipe operation descriptor, stored as a constant.
1404#[derive(Debug, Clone)]
1405pub struct TableOpDescriptor {
1406    pub op_name: String,
1407    pub args: Vec<AstExpr>,
1408}
1409
1410#[cfg(test)]
1411mod tests {
1412    use super::*;
1413    use crate::compiler::compile_with_source;
1414    use tl_parser::parse;
1415
1416    #[test]
1417    fn test_disassemble_simple() {
1418        let source = "let x = 42";
1419        let program = parse(source).unwrap();
1420        let proto = compile_with_source(&program, source).unwrap();
1421        let output = proto.disassemble();
1422        assert!(
1423            output.contains("LoadConst"),
1424            "expected LoadConst in:\n{output}"
1425        );
1426        assert!(output.contains("42"), "expected 42 in:\n{output}");
1427    }
1428
1429    #[test]
1430    fn test_disassemble_line_numbers() {
1431        let source = "let x = 1\nlet y = 2\nlet z = x";
1432        let program = parse(source).unwrap();
1433        let proto = compile_with_source(&program, source).unwrap();
1434        let output = proto.disassemble();
1435        // Should have different line numbers for different statements
1436        assert!(output.contains("0001"), "expected line 0001 in:\n{output}");
1437        assert!(output.contains("0002"), "expected line 0002 in:\n{output}");
1438    }
1439
1440    #[test]
1441    fn test_disassemble_function() {
1442        let source = "fn add(a, b) { a + b }";
1443        let program = parse(source).unwrap();
1444        let proto = compile_with_source(&program, source).unwrap();
1445        let output = proto.disassemble();
1446        assert!(output.contains("Closure"), "expected Closure in:\n{output}");
1447    }
1448
1449    #[test]
1450    fn test_disassemble_constants_inline() {
1451        let source = "let s = \"hello world\"";
1452        let program = parse(source).unwrap();
1453        let proto = compile_with_source(&program, source).unwrap();
1454        let output = proto.disassemble();
1455        assert!(
1456            output.contains("hello world"),
1457            "expected 'hello world' in:\n{output}"
1458        );
1459    }
1460
1461    #[test]
1462    fn test_builtin_id_try_from_valid() {
1463        for v in 0..=215u16 {
1464            assert!(
1465                BuiltinId::try_from(v).is_ok(),
1466                "BuiltinId::try_from({v}) should succeed"
1467            );
1468        }
1469        assert_eq!(BuiltinId::try_from(0u16).unwrap(), BuiltinId::Print);
1470        assert_eq!(BuiltinId::try_from(198u16).unwrap(), BuiltinId::StreamAgent);
1471        assert_eq!(
1472            BuiltinId::try_from(201u16).unwrap(),
1473            BuiltinId::TlConfigResolve
1474        );
1475        assert_eq!(BuiltinId::try_from(203u16).unwrap(), BuiltinId::WriteDuckDb);
1476        assert_eq!(BuiltinId::try_from(205u16).unwrap(), BuiltinId::ReadMssql);
1477        assert_eq!(BuiltinId::try_from(210u16).unwrap(), BuiltinId::ReadMongo);
1478    }
1479
1480    #[test]
1481    fn test_builtin_id_try_from_invalid() {
1482        assert_eq!(BuiltinId::try_from(227u16), Err(227u16));
1483        assert_eq!(BuiltinId::try_from(65535u16), Err(65535u16));
1484    }
1485}