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