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    ToRows = 227,
677}
678
679impl TryFrom<u16> for BuiltinId {
680    type Error = u16;
681
682    fn try_from(value: u16) -> Result<Self, Self::Error> {
683        match value {
684            0 => Ok(BuiltinId::Print),
685            1 => Ok(BuiltinId::Println),
686            2 => Ok(BuiltinId::Len),
687            3 => Ok(BuiltinId::Str),
688            4 => Ok(BuiltinId::Int),
689            5 => Ok(BuiltinId::Float),
690            6 => Ok(BuiltinId::Abs),
691            7 => Ok(BuiltinId::Min),
692            8 => Ok(BuiltinId::Max),
693            9 => Ok(BuiltinId::Range),
694            10 => Ok(BuiltinId::Push),
695            11 => Ok(BuiltinId::TypeOf),
696            12 => Ok(BuiltinId::Map),
697            13 => Ok(BuiltinId::Filter),
698            14 => Ok(BuiltinId::Reduce),
699            15 => Ok(BuiltinId::Sum),
700            16 => Ok(BuiltinId::Any),
701            17 => Ok(BuiltinId::All),
702            18 => Ok(BuiltinId::ReadCsv),
703            19 => Ok(BuiltinId::ReadParquet),
704            20 => Ok(BuiltinId::WriteCsv),
705            21 => Ok(BuiltinId::WriteParquet),
706            22 => Ok(BuiltinId::Collect),
707            23 => Ok(BuiltinId::Show),
708            24 => Ok(BuiltinId::Describe),
709            25 => Ok(BuiltinId::Head),
710            26 => Ok(BuiltinId::Postgres),
711            27 => Ok(BuiltinId::Tensor),
712            28 => Ok(BuiltinId::TensorZeros),
713            29 => Ok(BuiltinId::TensorOnes),
714            30 => Ok(BuiltinId::TensorShape),
715            31 => Ok(BuiltinId::TensorReshape),
716            32 => Ok(BuiltinId::TensorTranspose),
717            33 => Ok(BuiltinId::TensorSum),
718            34 => Ok(BuiltinId::TensorMean),
719            35 => Ok(BuiltinId::TensorDot),
720            36 => Ok(BuiltinId::Predict),
721            37 => Ok(BuiltinId::Similarity),
722            38 => Ok(BuiltinId::AiComplete),
723            39 => Ok(BuiltinId::AiChat),
724            40 => Ok(BuiltinId::ModelSave),
725            41 => Ok(BuiltinId::ModelLoad),
726            42 => Ok(BuiltinId::ModelRegister),
727            43 => Ok(BuiltinId::ModelList),
728            44 => Ok(BuiltinId::ModelGet),
729            45 => Ok(BuiltinId::AlertSlack),
730            46 => Ok(BuiltinId::AlertWebhook),
731            47 => Ok(BuiltinId::Emit),
732            48 => Ok(BuiltinId::Lineage),
733            49 => Ok(BuiltinId::RunPipeline),
734            50 => Ok(BuiltinId::Sqrt),
735            51 => Ok(BuiltinId::Pow),
736            52 => Ok(BuiltinId::Floor),
737            53 => Ok(BuiltinId::Ceil),
738            54 => Ok(BuiltinId::Round),
739            55 => Ok(BuiltinId::Sin),
740            56 => Ok(BuiltinId::Cos),
741            57 => Ok(BuiltinId::Tan),
742            58 => Ok(BuiltinId::Log),
743            59 => Ok(BuiltinId::Log2),
744            60 => Ok(BuiltinId::Log10),
745            61 => Ok(BuiltinId::Join),
746            62 => Ok(BuiltinId::HttpGet),
747            63 => Ok(BuiltinId::HttpPost),
748            64 => Ok(BuiltinId::Assert),
749            65 => Ok(BuiltinId::AssertEq),
750            66 => Ok(BuiltinId::JsonParse),
751            67 => Ok(BuiltinId::JsonStringify),
752            68 => Ok(BuiltinId::MapFrom),
753            69 => Ok(BuiltinId::ReadFile),
754            70 => Ok(BuiltinId::WriteFile),
755            71 => Ok(BuiltinId::AppendFile),
756            72 => Ok(BuiltinId::FileExists),
757            73 => Ok(BuiltinId::ListDir),
758            74 => Ok(BuiltinId::EnvGet),
759            75 => Ok(BuiltinId::EnvSet),
760            76 => Ok(BuiltinId::RegexMatch),
761            77 => Ok(BuiltinId::RegexFind),
762            78 => Ok(BuiltinId::RegexReplace),
763            79 => Ok(BuiltinId::Now),
764            80 => Ok(BuiltinId::DateFormat),
765            81 => Ok(BuiltinId::DateParse),
766            82 => Ok(BuiltinId::Zip),
767            83 => Ok(BuiltinId::Enumerate),
768            84 => Ok(BuiltinId::Bool),
769            85 => Ok(BuiltinId::Spawn),
770            86 => Ok(BuiltinId::Sleep),
771            87 => Ok(BuiltinId::Channel),
772            88 => Ok(BuiltinId::Send),
773            89 => Ok(BuiltinId::Recv),
774            90 => Ok(BuiltinId::TryRecv),
775            91 => Ok(BuiltinId::AwaitAll),
776            92 => Ok(BuiltinId::Pmap),
777            93 => Ok(BuiltinId::Timeout),
778            94 => Ok(BuiltinId::Next),
779            95 => Ok(BuiltinId::IsGenerator),
780            96 => Ok(BuiltinId::Iter),
781            97 => Ok(BuiltinId::Take),
782            98 => Ok(BuiltinId::Skip_),
783            99 => Ok(BuiltinId::GenCollect),
784            100 => Ok(BuiltinId::GenMap),
785            101 => Ok(BuiltinId::GenFilter),
786            102 => Ok(BuiltinId::Chain),
787            103 => Ok(BuiltinId::GenZip),
788            104 => Ok(BuiltinId::GenEnumerate),
789            105 => Ok(BuiltinId::Ok),
790            106 => Ok(BuiltinId::Err_),
791            107 => Ok(BuiltinId::IsOk),
792            108 => Ok(BuiltinId::IsErr),
793            109 => Ok(BuiltinId::Unwrap),
794            110 => Ok(BuiltinId::SetFrom),
795            111 => Ok(BuiltinId::SetAdd),
796            112 => Ok(BuiltinId::SetRemove),
797            113 => Ok(BuiltinId::SetContains),
798            114 => Ok(BuiltinId::SetUnion),
799            115 => Ok(BuiltinId::SetIntersection),
800            116 => Ok(BuiltinId::SetDifference),
801            117 => Ok(BuiltinId::FillNull),
802            118 => Ok(BuiltinId::DropNull),
803            119 => Ok(BuiltinId::Dedup),
804            120 => Ok(BuiltinId::Clamp),
805            121 => Ok(BuiltinId::DataProfile),
806            122 => Ok(BuiltinId::RowCount),
807            123 => Ok(BuiltinId::NullRate),
808            124 => Ok(BuiltinId::IsUnique),
809            125 => Ok(BuiltinId::IsEmail),
810            126 => Ok(BuiltinId::IsUrl),
811            127 => Ok(BuiltinId::IsPhone),
812            128 => Ok(BuiltinId::IsBetween),
813            129 => Ok(BuiltinId::Levenshtein),
814            130 => Ok(BuiltinId::Soundex),
815            131 => Ok(BuiltinId::ReadMysql),
816            132 => Ok(BuiltinId::RedisConnect),
817            133 => Ok(BuiltinId::RedisGet),
818            134 => Ok(BuiltinId::RedisSet),
819            135 => Ok(BuiltinId::RedisDel),
820            136 => Ok(BuiltinId::GraphqlQuery),
821            137 => Ok(BuiltinId::RegisterS3),
822            138 => Ok(BuiltinId::PyImport),
823            139 => Ok(BuiltinId::PyCall),
824            140 => Ok(BuiltinId::PyEval),
825            141 => Ok(BuiltinId::PyGetAttr),
826            142 => Ok(BuiltinId::PySetAttr),
827            143 => Ok(BuiltinId::PyToTl),
828            144 => Ok(BuiltinId::SchemaRegister),
829            145 => Ok(BuiltinId::SchemaGet),
830            146 => Ok(BuiltinId::SchemaLatest),
831            147 => Ok(BuiltinId::SchemaHistory),
832            148 => Ok(BuiltinId::SchemaCheck),
833            149 => Ok(BuiltinId::SchemaDiff),
834            150 => Ok(BuiltinId::SchemaApplyMigration),
835            151 => Ok(BuiltinId::SchemaVersions),
836            152 => Ok(BuiltinId::SchemaFields),
837            153 => Ok(BuiltinId::Decimal),
838            154 => Ok(BuiltinId::SecretGet),
839            155 => Ok(BuiltinId::SecretSet),
840            156 => Ok(BuiltinId::SecretDelete),
841            157 => Ok(BuiltinId::SecretList),
842            158 => Ok(BuiltinId::CheckPermission),
843            159 => Ok(BuiltinId::MaskEmail),
844            160 => Ok(BuiltinId::MaskPhone),
845            161 => Ok(BuiltinId::MaskCreditCard),
846            162 => Ok(BuiltinId::Redact),
847            163 => Ok(BuiltinId::Hash),
848            164 => Ok(BuiltinId::AsyncReadFile),
849            165 => Ok(BuiltinId::AsyncWriteFile),
850            166 => Ok(BuiltinId::AsyncHttpGet),
851            167 => Ok(BuiltinId::AsyncHttpPost),
852            168 => Ok(BuiltinId::AsyncSleep),
853            169 => Ok(BuiltinId::Select),
854            170 => Ok(BuiltinId::AsyncMap),
855            171 => Ok(BuiltinId::AsyncFilter),
856            172 => Ok(BuiltinId::RaceAll),
857            173 => Ok(BuiltinId::IsError),
858            174 => Ok(BuiltinId::ErrorType),
859            175 => Ok(BuiltinId::GpuAvailable),
860            176 => Ok(BuiltinId::ToGpu),
861            177 => Ok(BuiltinId::ToCpu),
862            178 => Ok(BuiltinId::GpuMatmul),
863            179 => Ok(BuiltinId::GpuBatchPredict),
864            180 => Ok(BuiltinId::ReadSqlite),
865            181 => Ok(BuiltinId::WriteSqlite),
866            182 => Ok(BuiltinId::Embed),
867            183 => Ok(BuiltinId::HttpRequest),
868            184 => Ok(BuiltinId::RunAgent),
869            185 => Ok(BuiltinId::Random),
870            186 => Ok(BuiltinId::RandomInt),
871            187 => Ok(BuiltinId::Sample),
872            188 => Ok(BuiltinId::Exp),
873            189 => Ok(BuiltinId::IsNan),
874            190 => Ok(BuiltinId::IsInfinite),
875            191 => Ok(BuiltinId::Sign),
876            192 => Ok(BuiltinId::AssertTableEq),
877            193 => Ok(BuiltinId::Today),
878            194 => Ok(BuiltinId::DateAdd),
879            195 => Ok(BuiltinId::DateDiff),
880            196 => Ok(BuiltinId::DateTrunc),
881            197 => Ok(BuiltinId::DateExtract),
882            198 => Ok(BuiltinId::StreamAgent),
883            199 => Ok(BuiltinId::PostgresQuery),
884            200 => Ok(BuiltinId::Fold),
885            201 => Ok(BuiltinId::TlConfigResolve),
886            202 => Ok(BuiltinId::ReadDuckDb),
887            203 => Ok(BuiltinId::WriteDuckDb),
888            204 => Ok(BuiltinId::ReadRedshift),
889            205 => Ok(BuiltinId::ReadMssql),
890            206 => Ok(BuiltinId::ReadSnowflake),
891            207 => Ok(BuiltinId::ReadBigQuery),
892            208 => Ok(BuiltinId::ReadDatabricks),
893            209 => Ok(BuiltinId::ReadClickHouse),
894            210 => Ok(BuiltinId::ReadMongo),
895            211 => Ok(BuiltinId::SftpDownload),
896            212 => Ok(BuiltinId::SftpUpload),
897            213 => Ok(BuiltinId::SftpList),
898            214 => Ok(BuiltinId::SftpReadCsv),
899            215 => Ok(BuiltinId::SftpReadParquet),
900            216 => Ok(BuiltinId::McpConnect),
901            217 => Ok(BuiltinId::McpListTools),
902            218 => Ok(BuiltinId::McpCallTool),
903            219 => Ok(BuiltinId::McpDisconnect),
904            220 => Ok(BuiltinId::McpServe),
905            221 => Ok(BuiltinId::McpServerInfo),
906            222 => Ok(BuiltinId::McpPing),
907            223 => Ok(BuiltinId::McpListResources),
908            224 => Ok(BuiltinId::McpReadResource),
909            225 => Ok(BuiltinId::McpListPrompts),
910            226 => Ok(BuiltinId::McpGetPrompt),
911            227 => Ok(BuiltinId::ToRows),
912            _ => Err(value),
913        }
914    }
915}
916
917impl BuiltinId {
918    pub fn from_name(name: &str) -> Option<BuiltinId> {
919        match name {
920            "print" => Some(BuiltinId::Print),
921            "println" => Some(BuiltinId::Println),
922            "len" => Some(BuiltinId::Len),
923            "str" => Some(BuiltinId::Str),
924            "int" => Some(BuiltinId::Int),
925            "float" => Some(BuiltinId::Float),
926            "abs" => Some(BuiltinId::Abs),
927            "min" => Some(BuiltinId::Min),
928            "max" => Some(BuiltinId::Max),
929            "range" => Some(BuiltinId::Range),
930            "push" => Some(BuiltinId::Push),
931            "type_of" => Some(BuiltinId::TypeOf),
932            "map" => Some(BuiltinId::Map),
933            "filter" => Some(BuiltinId::Filter),
934            "reduce" => Some(BuiltinId::Reduce),
935            "sum" => Some(BuiltinId::Sum),
936            "any" => Some(BuiltinId::Any),
937            "all" => Some(BuiltinId::All),
938            "read_csv" => Some(BuiltinId::ReadCsv),
939            "read_parquet" => Some(BuiltinId::ReadParquet),
940            "write_csv" => Some(BuiltinId::WriteCsv),
941            "write_parquet" => Some(BuiltinId::WriteParquet),
942            "collect" => Some(BuiltinId::Collect),
943            "show" => Some(BuiltinId::Show),
944            "describe" => Some(BuiltinId::Describe),
945            "head" => Some(BuiltinId::Head),
946            "postgres" | "read_postgres" => Some(BuiltinId::Postgres),
947            "tensor" => Some(BuiltinId::Tensor),
948            "tensor_zeros" => Some(BuiltinId::TensorZeros),
949            "tensor_ones" => Some(BuiltinId::TensorOnes),
950            "tensor_shape" | "shape" => Some(BuiltinId::TensorShape),
951            "tensor_reshape" => Some(BuiltinId::TensorReshape),
952            "tensor_transpose" => Some(BuiltinId::TensorTranspose),
953            "tensor_sum" => Some(BuiltinId::TensorSum),
954            "tensor_mean" => Some(BuiltinId::TensorMean),
955            "tensor_dot" => Some(BuiltinId::TensorDot),
956            "predict" => Some(BuiltinId::Predict),
957            "similarity" => Some(BuiltinId::Similarity),
958            "ai_complete" => Some(BuiltinId::AiComplete),
959            "ai_chat" => Some(BuiltinId::AiChat),
960            "model_save" => Some(BuiltinId::ModelSave),
961            "model_load" => Some(BuiltinId::ModelLoad),
962            "model_register" => Some(BuiltinId::ModelRegister),
963            "model_list" => Some(BuiltinId::ModelList),
964            "model_get" => Some(BuiltinId::ModelGet),
965            "alert_slack" => Some(BuiltinId::AlertSlack),
966            "alert_webhook" => Some(BuiltinId::AlertWebhook),
967            "emit" => Some(BuiltinId::Emit),
968            "lineage" => Some(BuiltinId::Lineage),
969            "run_pipeline" => Some(BuiltinId::RunPipeline),
970            "sqrt" => Some(BuiltinId::Sqrt),
971            "pow" => Some(BuiltinId::Pow),
972            "floor" => Some(BuiltinId::Floor),
973            "ceil" => Some(BuiltinId::Ceil),
974            "round" => Some(BuiltinId::Round),
975            "sin" => Some(BuiltinId::Sin),
976            "cos" => Some(BuiltinId::Cos),
977            "tan" => Some(BuiltinId::Tan),
978            "log" => Some(BuiltinId::Log),
979            "log2" => Some(BuiltinId::Log2),
980            "log10" => Some(BuiltinId::Log10),
981            "join" => Some(BuiltinId::Join),
982            "http_get" => Some(BuiltinId::HttpGet),
983            "http_post" => Some(BuiltinId::HttpPost),
984            "assert" => Some(BuiltinId::Assert),
985            "assert_eq" => Some(BuiltinId::AssertEq),
986            "json_parse" => Some(BuiltinId::JsonParse),
987            "json_stringify" => Some(BuiltinId::JsonStringify),
988            "map_from" => Some(BuiltinId::MapFrom),
989            "read_file" => Some(BuiltinId::ReadFile),
990            "write_file" => Some(BuiltinId::WriteFile),
991            "append_file" => Some(BuiltinId::AppendFile),
992            "file_exists" => Some(BuiltinId::FileExists),
993            "list_dir" => Some(BuiltinId::ListDir),
994            "env_get" => Some(BuiltinId::EnvGet),
995            "env_set" => Some(BuiltinId::EnvSet),
996            "regex_match" => Some(BuiltinId::RegexMatch),
997            "regex_find" => Some(BuiltinId::RegexFind),
998            "regex_replace" => Some(BuiltinId::RegexReplace),
999            "now" => Some(BuiltinId::Now),
1000            "date_format" => Some(BuiltinId::DateFormat),
1001            "date_parse" => Some(BuiltinId::DateParse),
1002            "zip" => Some(BuiltinId::Zip),
1003            "enumerate" => Some(BuiltinId::Enumerate),
1004            "bool" => Some(BuiltinId::Bool),
1005            "spawn" => Some(BuiltinId::Spawn),
1006            "sleep" => Some(BuiltinId::Sleep),
1007            "channel" => Some(BuiltinId::Channel),
1008            "send" => Some(BuiltinId::Send),
1009            "recv" => Some(BuiltinId::Recv),
1010            "try_recv" => Some(BuiltinId::TryRecv),
1011            "await_all" => Some(BuiltinId::AwaitAll),
1012            "pmap" => Some(BuiltinId::Pmap),
1013            "timeout" => Some(BuiltinId::Timeout),
1014            "next" => Some(BuiltinId::Next),
1015            "is_generator" => Some(BuiltinId::IsGenerator),
1016            "iter" => Some(BuiltinId::Iter),
1017            "take" => Some(BuiltinId::Take),
1018            "skip" => Some(BuiltinId::Skip_),
1019            "gen_collect" => Some(BuiltinId::GenCollect),
1020            "gen_map" => Some(BuiltinId::GenMap),
1021            "gen_filter" => Some(BuiltinId::GenFilter),
1022            "chain" => Some(BuiltinId::Chain),
1023            "gen_zip" => Some(BuiltinId::GenZip),
1024            "gen_enumerate" => Some(BuiltinId::GenEnumerate),
1025            "Ok" => Some(BuiltinId::Ok),
1026            "Err" => Some(BuiltinId::Err_),
1027            "is_ok" => Some(BuiltinId::IsOk),
1028            "is_err" => Some(BuiltinId::IsErr),
1029            "unwrap" => Some(BuiltinId::Unwrap),
1030            "set_from" => Some(BuiltinId::SetFrom),
1031            "set_add" => Some(BuiltinId::SetAdd),
1032            "set_remove" => Some(BuiltinId::SetRemove),
1033            "set_contains" => Some(BuiltinId::SetContains),
1034            "set_union" => Some(BuiltinId::SetUnion),
1035            "set_intersection" => Some(BuiltinId::SetIntersection),
1036            "set_difference" => Some(BuiltinId::SetDifference),
1037            // Phase 15: Data Quality & Connectors
1038            "fill_null" => Some(BuiltinId::FillNull),
1039            "drop_null" => Some(BuiltinId::DropNull),
1040            "dedup" => Some(BuiltinId::Dedup),
1041            "clamp" => Some(BuiltinId::Clamp),
1042            "data_profile" => Some(BuiltinId::DataProfile),
1043            "row_count" => Some(BuiltinId::RowCount),
1044            "null_rate" => Some(BuiltinId::NullRate),
1045            "is_unique" => Some(BuiltinId::IsUnique),
1046            "is_email" => Some(BuiltinId::IsEmail),
1047            "is_url" => Some(BuiltinId::IsUrl),
1048            "is_phone" => Some(BuiltinId::IsPhone),
1049            "is_between" => Some(BuiltinId::IsBetween),
1050            "levenshtein" => Some(BuiltinId::Levenshtein),
1051            "soundex" => Some(BuiltinId::Soundex),
1052            "read_mysql" => Some(BuiltinId::ReadMysql),
1053            "redis_connect" => Some(BuiltinId::RedisConnect),
1054            "redis_get" => Some(BuiltinId::RedisGet),
1055            "redis_set" => Some(BuiltinId::RedisSet),
1056            "redis_del" => Some(BuiltinId::RedisDel),
1057            "graphql_query" => Some(BuiltinId::GraphqlQuery),
1058            "register_s3" => Some(BuiltinId::RegisterS3),
1059            // Phase 20: Python FFI
1060            "py_import" => Some(BuiltinId::PyImport),
1061            "py_call" => Some(BuiltinId::PyCall),
1062            "py_eval" => Some(BuiltinId::PyEval),
1063            "py_getattr" => Some(BuiltinId::PyGetAttr),
1064            "py_setattr" => Some(BuiltinId::PySetAttr),
1065            "py_to_tl" => Some(BuiltinId::PyToTl),
1066            // Phase 21: Schema Evolution
1067            "schema_register" => Some(BuiltinId::SchemaRegister),
1068            "schema_get" => Some(BuiltinId::SchemaGet),
1069            "schema_latest" => Some(BuiltinId::SchemaLatest),
1070            "schema_history" => Some(BuiltinId::SchemaHistory),
1071            "schema_check" => Some(BuiltinId::SchemaCheck),
1072            "schema_diff" => Some(BuiltinId::SchemaDiff),
1073            "schema_apply_migration" => Some(BuiltinId::SchemaApplyMigration),
1074            "schema_versions" => Some(BuiltinId::SchemaVersions),
1075            "schema_fields" => Some(BuiltinId::SchemaFields),
1076            // Phase 22: Advanced Types
1077            "decimal" => Some(BuiltinId::Decimal),
1078            // Phase 23: Security
1079            "secret_get" => Some(BuiltinId::SecretGet),
1080            "secret_set" => Some(BuiltinId::SecretSet),
1081            "secret_delete" => Some(BuiltinId::SecretDelete),
1082            "secret_list" => Some(BuiltinId::SecretList),
1083            "check_permission" => Some(BuiltinId::CheckPermission),
1084            "mask_email" => Some(BuiltinId::MaskEmail),
1085            "mask_phone" => Some(BuiltinId::MaskPhone),
1086            "mask_cc" => Some(BuiltinId::MaskCreditCard),
1087            "redact" => Some(BuiltinId::Redact),
1088            "hash" => Some(BuiltinId::Hash),
1089            // Phase 24: Async
1090            "async_read_file" => Some(BuiltinId::AsyncReadFile),
1091            "async_write_file" => Some(BuiltinId::AsyncWriteFile),
1092            "async_http_get" => Some(BuiltinId::AsyncHttpGet),
1093            "async_http_post" => Some(BuiltinId::AsyncHttpPost),
1094            "async_sleep" => Some(BuiltinId::AsyncSleep),
1095            "select" => Some(BuiltinId::Select),
1096            "async_map" => Some(BuiltinId::AsyncMap),
1097            "async_filter" => Some(BuiltinId::AsyncFilter),
1098            "race_all" => Some(BuiltinId::RaceAll),
1099            // Phase 27: Data Error Hierarchy
1100            "is_error" => Some(BuiltinId::IsError),
1101            "error_type" => Some(BuiltinId::ErrorType),
1102            // Phase 32: GPU Tensor Support
1103            "gpu_available" => Some(BuiltinId::GpuAvailable),
1104            "to_gpu" => Some(BuiltinId::ToGpu),
1105            "to_cpu" => Some(BuiltinId::ToCpu),
1106            "gpu_matmul" => Some(BuiltinId::GpuMatmul),
1107            "gpu_batch_predict" => Some(BuiltinId::GpuBatchPredict),
1108            // Phase 33: SQLite
1109            "read_sqlite" => Some(BuiltinId::ReadSqlite),
1110            "write_sqlite" => Some(BuiltinId::WriteSqlite),
1111            // Phase 34: AI Agent Framework
1112            "embed" => Some(BuiltinId::Embed),
1113            "http_request" => Some(BuiltinId::HttpRequest),
1114            "run_agent" => Some(BuiltinId::RunAgent),
1115            "random" => Some(BuiltinId::Random),
1116            "random_int" => Some(BuiltinId::RandomInt),
1117            "sample" => Some(BuiltinId::Sample),
1118            "exp" => Some(BuiltinId::Exp),
1119            "is_nan" => Some(BuiltinId::IsNan),
1120            "is_infinite" => Some(BuiltinId::IsInfinite),
1121            "sign" => Some(BuiltinId::Sign),
1122            "assert_table_eq" => Some(BuiltinId::AssertTableEq),
1123            "today" => Some(BuiltinId::Today),
1124            "date_add" => Some(BuiltinId::DateAdd),
1125            "date_diff" => Some(BuiltinId::DateDiff),
1126            "date_trunc" => Some(BuiltinId::DateTrunc),
1127            "date_extract" | "extract" => Some(BuiltinId::DateExtract),
1128            "stream_agent" => Some(BuiltinId::StreamAgent),
1129            "postgres_query" => Some(BuiltinId::PostgresQuery),
1130            "fold" => Some(BuiltinId::Fold),
1131            "tl_config_resolve" => Some(BuiltinId::TlConfigResolve),
1132            "duckdb" | "read_duckdb" => Some(BuiltinId::ReadDuckDb),
1133            "write_duckdb" => Some(BuiltinId::WriteDuckDb),
1134            "redshift" | "read_redshift" => Some(BuiltinId::ReadRedshift),
1135            "mssql" | "read_mssql" => Some(BuiltinId::ReadMssql),
1136            "snowflake" | "read_snowflake" => Some(BuiltinId::ReadSnowflake),
1137            "bigquery" | "read_bigquery" => Some(BuiltinId::ReadBigQuery),
1138            "databricks" | "read_databricks" => Some(BuiltinId::ReadDatabricks),
1139            "clickhouse" | "read_clickhouse" => Some(BuiltinId::ReadClickHouse),
1140            "mongo" | "read_mongo" | "read_mongodb" => Some(BuiltinId::ReadMongo),
1141            "sftp_download" => Some(BuiltinId::SftpDownload),
1142            "sftp_upload" => Some(BuiltinId::SftpUpload),
1143            "sftp_list" | "sftp_ls" => Some(BuiltinId::SftpList),
1144            "sftp_read_csv" => Some(BuiltinId::SftpReadCsv),
1145            "sftp_read_parquet" => Some(BuiltinId::SftpReadParquet),
1146            "mcp_connect" => Some(BuiltinId::McpConnect),
1147            "mcp_list_tools" => Some(BuiltinId::McpListTools),
1148            "mcp_call_tool" => Some(BuiltinId::McpCallTool),
1149            "mcp_disconnect" => Some(BuiltinId::McpDisconnect),
1150            "mcp_serve" => Some(BuiltinId::McpServe),
1151            "mcp_server_info" => Some(BuiltinId::McpServerInfo),
1152            "mcp_ping" => Some(BuiltinId::McpPing),
1153            "mcp_list_resources" => Some(BuiltinId::McpListResources),
1154            "mcp_read_resource" => Some(BuiltinId::McpReadResource),
1155            "mcp_list_prompts" => Some(BuiltinId::McpListPrompts),
1156            "mcp_get_prompt" => Some(BuiltinId::McpGetPrompt),
1157            "to_rows" => Some(BuiltinId::ToRows),
1158            _ => None,
1159        }
1160    }
1161
1162    pub fn name(&self) -> &'static str {
1163        match self {
1164            BuiltinId::Print => "print",
1165            BuiltinId::Println => "println",
1166            BuiltinId::Len => "len",
1167            BuiltinId::Str => "str",
1168            BuiltinId::Int => "int",
1169            BuiltinId::Float => "float",
1170            BuiltinId::Abs => "abs",
1171            BuiltinId::Min => "min",
1172            BuiltinId::Max => "max",
1173            BuiltinId::Range => "range",
1174            BuiltinId::Push => "push",
1175            BuiltinId::TypeOf => "type_of",
1176            BuiltinId::Map => "map",
1177            BuiltinId::Filter => "filter",
1178            BuiltinId::Reduce => "reduce",
1179            BuiltinId::Sum => "sum",
1180            BuiltinId::Any => "any",
1181            BuiltinId::All => "all",
1182            BuiltinId::ReadCsv => "read_csv",
1183            BuiltinId::ReadParquet => "read_parquet",
1184            BuiltinId::WriteCsv => "write_csv",
1185            BuiltinId::WriteParquet => "write_parquet",
1186            BuiltinId::Collect => "collect",
1187            BuiltinId::Show => "show",
1188            BuiltinId::Describe => "describe",
1189            BuiltinId::Head => "head",
1190            BuiltinId::Postgres => "postgres",
1191            BuiltinId::Tensor => "tensor",
1192            BuiltinId::TensorZeros => "tensor_zeros",
1193            BuiltinId::TensorOnes => "tensor_ones",
1194            BuiltinId::TensorShape => "tensor_shape",
1195            BuiltinId::TensorReshape => "tensor_reshape",
1196            BuiltinId::TensorTranspose => "tensor_transpose",
1197            BuiltinId::TensorSum => "tensor_sum",
1198            BuiltinId::TensorMean => "tensor_mean",
1199            BuiltinId::TensorDot => "tensor_dot",
1200            BuiltinId::Predict => "predict",
1201            BuiltinId::Similarity => "similarity",
1202            BuiltinId::AiComplete => "ai_complete",
1203            BuiltinId::AiChat => "ai_chat",
1204            BuiltinId::ModelSave => "model_save",
1205            BuiltinId::ModelLoad => "model_load",
1206            BuiltinId::ModelRegister => "model_register",
1207            BuiltinId::ModelList => "model_list",
1208            BuiltinId::ModelGet => "model_get",
1209            BuiltinId::AlertSlack => "alert_slack",
1210            BuiltinId::AlertWebhook => "alert_webhook",
1211            BuiltinId::Emit => "emit",
1212            BuiltinId::Lineage => "lineage",
1213            BuiltinId::RunPipeline => "run_pipeline",
1214            BuiltinId::Sqrt => "sqrt",
1215            BuiltinId::Pow => "pow",
1216            BuiltinId::Floor => "floor",
1217            BuiltinId::Ceil => "ceil",
1218            BuiltinId::Round => "round",
1219            BuiltinId::Sin => "sin",
1220            BuiltinId::Cos => "cos",
1221            BuiltinId::Tan => "tan",
1222            BuiltinId::Log => "log",
1223            BuiltinId::Log2 => "log2",
1224            BuiltinId::Log10 => "log10",
1225            BuiltinId::Join => "join",
1226            BuiltinId::HttpGet => "http_get",
1227            BuiltinId::HttpPost => "http_post",
1228            BuiltinId::Assert => "assert",
1229            BuiltinId::AssertEq => "assert_eq",
1230            BuiltinId::JsonParse => "json_parse",
1231            BuiltinId::JsonStringify => "json_stringify",
1232            BuiltinId::MapFrom => "map_from",
1233            BuiltinId::ReadFile => "read_file",
1234            BuiltinId::WriteFile => "write_file",
1235            BuiltinId::AppendFile => "append_file",
1236            BuiltinId::FileExists => "file_exists",
1237            BuiltinId::ListDir => "list_dir",
1238            BuiltinId::EnvGet => "env_get",
1239            BuiltinId::EnvSet => "env_set",
1240            BuiltinId::RegexMatch => "regex_match",
1241            BuiltinId::RegexFind => "regex_find",
1242            BuiltinId::RegexReplace => "regex_replace",
1243            BuiltinId::Now => "now",
1244            BuiltinId::DateFormat => "date_format",
1245            BuiltinId::DateParse => "date_parse",
1246            BuiltinId::Zip => "zip",
1247            BuiltinId::Enumerate => "enumerate",
1248            BuiltinId::Bool => "bool",
1249            BuiltinId::Spawn => "spawn",
1250            BuiltinId::Sleep => "sleep",
1251            BuiltinId::Channel => "channel",
1252            BuiltinId::Send => "send",
1253            BuiltinId::Recv => "recv",
1254            BuiltinId::TryRecv => "try_recv",
1255            BuiltinId::AwaitAll => "await_all",
1256            BuiltinId::Pmap => "pmap",
1257            BuiltinId::Timeout => "timeout",
1258            BuiltinId::Next => "next",
1259            BuiltinId::IsGenerator => "is_generator",
1260            BuiltinId::Iter => "iter",
1261            BuiltinId::Take => "take",
1262            BuiltinId::Skip_ => "skip",
1263            BuiltinId::GenCollect => "gen_collect",
1264            BuiltinId::GenMap => "gen_map",
1265            BuiltinId::GenFilter => "gen_filter",
1266            BuiltinId::Chain => "chain",
1267            BuiltinId::GenZip => "gen_zip",
1268            BuiltinId::GenEnumerate => "gen_enumerate",
1269            BuiltinId::Ok => "Ok",
1270            BuiltinId::Err_ => "Err",
1271            BuiltinId::IsOk => "is_ok",
1272            BuiltinId::IsErr => "is_err",
1273            BuiltinId::Unwrap => "unwrap",
1274            BuiltinId::SetFrom => "set_from",
1275            BuiltinId::SetAdd => "set_add",
1276            BuiltinId::SetRemove => "set_remove",
1277            BuiltinId::SetContains => "set_contains",
1278            BuiltinId::SetUnion => "set_union",
1279            BuiltinId::SetIntersection => "set_intersection",
1280            BuiltinId::SetDifference => "set_difference",
1281            // Phase 15: Data Quality & Connectors
1282            BuiltinId::FillNull => "fill_null",
1283            BuiltinId::DropNull => "drop_null",
1284            BuiltinId::Dedup => "dedup",
1285            BuiltinId::Clamp => "clamp",
1286            BuiltinId::DataProfile => "data_profile",
1287            BuiltinId::RowCount => "row_count",
1288            BuiltinId::NullRate => "null_rate",
1289            BuiltinId::IsUnique => "is_unique",
1290            BuiltinId::IsEmail => "is_email",
1291            BuiltinId::IsUrl => "is_url",
1292            BuiltinId::IsPhone => "is_phone",
1293            BuiltinId::IsBetween => "is_between",
1294            BuiltinId::Levenshtein => "levenshtein",
1295            BuiltinId::Soundex => "soundex",
1296            BuiltinId::ReadMysql => "read_mysql",
1297            BuiltinId::RedisConnect => "redis_connect",
1298            BuiltinId::RedisGet => "redis_get",
1299            BuiltinId::RedisSet => "redis_set",
1300            BuiltinId::RedisDel => "redis_del",
1301            BuiltinId::GraphqlQuery => "graphql_query",
1302            BuiltinId::RegisterS3 => "register_s3",
1303            // Phase 20: Python FFI
1304            BuiltinId::PyImport => "py_import",
1305            BuiltinId::PyCall => "py_call",
1306            BuiltinId::PyEval => "py_eval",
1307            BuiltinId::PyGetAttr => "py_getattr",
1308            BuiltinId::PySetAttr => "py_setattr",
1309            BuiltinId::PyToTl => "py_to_tl",
1310            // Phase 21: Schema Evolution
1311            BuiltinId::SchemaRegister => "schema_register",
1312            BuiltinId::SchemaGet => "schema_get",
1313            BuiltinId::SchemaLatest => "schema_latest",
1314            BuiltinId::SchemaHistory => "schema_history",
1315            BuiltinId::SchemaCheck => "schema_check",
1316            BuiltinId::SchemaDiff => "schema_diff",
1317            BuiltinId::SchemaApplyMigration => "schema_apply_migration",
1318            BuiltinId::SchemaVersions => "schema_versions",
1319            BuiltinId::SchemaFields => "schema_fields",
1320            // Phase 22
1321            BuiltinId::Decimal => "decimal",
1322            // Phase 23
1323            BuiltinId::SecretGet => "secret_get",
1324            BuiltinId::SecretSet => "secret_set",
1325            BuiltinId::SecretDelete => "secret_delete",
1326            BuiltinId::SecretList => "secret_list",
1327            BuiltinId::CheckPermission => "check_permission",
1328            BuiltinId::MaskEmail => "mask_email",
1329            BuiltinId::MaskPhone => "mask_phone",
1330            BuiltinId::MaskCreditCard => "mask_cc",
1331            BuiltinId::Redact => "redact",
1332            BuiltinId::Hash => "hash",
1333            // Phase 24
1334            BuiltinId::AsyncReadFile => "async_read_file",
1335            BuiltinId::AsyncWriteFile => "async_write_file",
1336            BuiltinId::AsyncHttpGet => "async_http_get",
1337            BuiltinId::AsyncHttpPost => "async_http_post",
1338            BuiltinId::AsyncSleep => "async_sleep",
1339            BuiltinId::Select => "select",
1340            BuiltinId::AsyncMap => "async_map",
1341            BuiltinId::AsyncFilter => "async_filter",
1342            BuiltinId::RaceAll => "race_all",
1343            // Phase 27
1344            BuiltinId::IsError => "is_error",
1345            BuiltinId::ErrorType => "error_type",
1346            // Phase 32: GPU
1347            BuiltinId::GpuAvailable => "gpu_available",
1348            BuiltinId::ToGpu => "to_gpu",
1349            BuiltinId::ToCpu => "to_cpu",
1350            BuiltinId::GpuMatmul => "gpu_matmul",
1351            BuiltinId::GpuBatchPredict => "gpu_batch_predict",
1352            // Phase 33: SQLite
1353            BuiltinId::ReadSqlite => "read_sqlite",
1354            BuiltinId::WriteSqlite => "write_sqlite",
1355            // Phase 34: AI Agent Framework
1356            BuiltinId::Embed => "embed",
1357            BuiltinId::HttpRequest => "http_request",
1358            BuiltinId::RunAgent => "run_agent",
1359            // Phase E5/E6
1360            BuiltinId::Random => "random",
1361            BuiltinId::RandomInt => "random_int",
1362            BuiltinId::Sample => "sample",
1363            BuiltinId::Exp => "exp",
1364            BuiltinId::IsNan => "is_nan",
1365            BuiltinId::IsInfinite => "is_infinite",
1366            BuiltinId::Sign => "sign",
1367            BuiltinId::AssertTableEq => "assert_table_eq",
1368            BuiltinId::Today => "today",
1369            BuiltinId::DateAdd => "date_add",
1370            BuiltinId::DateDiff => "date_diff",
1371            BuiltinId::DateTrunc => "date_trunc",
1372            BuiltinId::DateExtract => "date_extract",
1373            BuiltinId::StreamAgent => "stream_agent",
1374            BuiltinId::PostgresQuery => "postgres_query",
1375            BuiltinId::Fold => "fold",
1376            BuiltinId::TlConfigResolve => "tl_config_resolve",
1377            BuiltinId::ReadDuckDb => "duckdb",
1378            BuiltinId::WriteDuckDb => "write_duckdb",
1379            BuiltinId::ReadRedshift => "redshift",
1380            BuiltinId::ReadMssql => "mssql",
1381            BuiltinId::ReadSnowflake => "snowflake",
1382            BuiltinId::ReadBigQuery => "bigquery",
1383            BuiltinId::ReadDatabricks => "databricks",
1384            BuiltinId::ReadClickHouse => "clickhouse",
1385            BuiltinId::ReadMongo => "mongo",
1386            BuiltinId::SftpDownload => "sftp_download",
1387            BuiltinId::SftpUpload => "sftp_upload",
1388            BuiltinId::SftpList => "sftp_list",
1389            BuiltinId::SftpReadCsv => "sftp_read_csv",
1390            BuiltinId::SftpReadParquet => "sftp_read_parquet",
1391            BuiltinId::McpConnect => "mcp_connect",
1392            BuiltinId::McpListTools => "mcp_list_tools",
1393            BuiltinId::McpCallTool => "mcp_call_tool",
1394            BuiltinId::McpDisconnect => "mcp_disconnect",
1395            BuiltinId::McpServe => "mcp_serve",
1396            BuiltinId::McpServerInfo => "mcp_server_info",
1397            BuiltinId::McpPing => "mcp_ping",
1398            BuiltinId::McpListResources => "mcp_list_resources",
1399            BuiltinId::McpReadResource => "mcp_read_resource",
1400            BuiltinId::McpListPrompts => "mcp_list_prompts",
1401            BuiltinId::McpGetPrompt => "mcp_get_prompt",
1402            BuiltinId::ToRows => "to_rows",
1403        }
1404    }
1405}
1406
1407/// Table pipe operation descriptor, stored as a constant.
1408#[derive(Debug, Clone)]
1409pub struct TableOpDescriptor {
1410    pub op_name: String,
1411    pub args: Vec<AstExpr>,
1412}
1413
1414#[cfg(test)]
1415mod tests {
1416    use super::*;
1417    use crate::compiler::compile_with_source;
1418    use tl_parser::parse;
1419
1420    #[test]
1421    fn test_disassemble_simple() {
1422        let source = "let x = 42";
1423        let program = parse(source).unwrap();
1424        let proto = compile_with_source(&program, source).unwrap();
1425        let output = proto.disassemble();
1426        assert!(
1427            output.contains("LoadConst"),
1428            "expected LoadConst in:\n{output}"
1429        );
1430        assert!(output.contains("42"), "expected 42 in:\n{output}");
1431    }
1432
1433    #[test]
1434    fn test_disassemble_line_numbers() {
1435        let source = "let x = 1\nlet y = 2\nlet z = x";
1436        let program = parse(source).unwrap();
1437        let proto = compile_with_source(&program, source).unwrap();
1438        let output = proto.disassemble();
1439        // Should have different line numbers for different statements
1440        assert!(output.contains("0001"), "expected line 0001 in:\n{output}");
1441        assert!(output.contains("0002"), "expected line 0002 in:\n{output}");
1442    }
1443
1444    #[test]
1445    fn test_disassemble_function() {
1446        let source = "fn add(a, b) { a + b }";
1447        let program = parse(source).unwrap();
1448        let proto = compile_with_source(&program, source).unwrap();
1449        let output = proto.disassemble();
1450        assert!(output.contains("Closure"), "expected Closure in:\n{output}");
1451    }
1452
1453    #[test]
1454    fn test_disassemble_constants_inline() {
1455        let source = "let s = \"hello world\"";
1456        let program = parse(source).unwrap();
1457        let proto = compile_with_source(&program, source).unwrap();
1458        let output = proto.disassemble();
1459        assert!(
1460            output.contains("hello world"),
1461            "expected 'hello world' in:\n{output}"
1462        );
1463    }
1464
1465    #[test]
1466    fn test_builtin_id_try_from_valid() {
1467        for v in 0..=215u16 {
1468            assert!(
1469                BuiltinId::try_from(v).is_ok(),
1470                "BuiltinId::try_from({v}) should succeed"
1471            );
1472        }
1473        assert_eq!(BuiltinId::try_from(0u16).unwrap(), BuiltinId::Print);
1474        assert_eq!(BuiltinId::try_from(198u16).unwrap(), BuiltinId::StreamAgent);
1475        assert_eq!(
1476            BuiltinId::try_from(201u16).unwrap(),
1477            BuiltinId::TlConfigResolve
1478        );
1479        assert_eq!(BuiltinId::try_from(203u16).unwrap(), BuiltinId::WriteDuckDb);
1480        assert_eq!(BuiltinId::try_from(205u16).unwrap(), BuiltinId::ReadMssql);
1481        assert_eq!(BuiltinId::try_from(210u16).unwrap(), BuiltinId::ReadMongo);
1482    }
1483
1484    #[test]
1485    fn test_builtin_id_try_from_invalid() {
1486        assert_eq!(BuiltinId::try_from(228u16), Err(228u16));
1487        assert_eq!(BuiltinId::try_from(65535u16), Err(65535u16));
1488    }
1489}