@tishlang/tish 1.9.1 → 1.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/bin/tish +0 -0
  2. package/crates/js_to_tish/src/transform/expr.rs +8 -6
  3. package/crates/js_to_tish/src/transform/stmt.rs +12 -13
  4. package/crates/tish/Cargo.toml +1 -1
  5. package/crates/tish/src/cargo_native_registry.rs +4 -1
  6. package/crates/tish/src/main.rs +11 -8
  7. package/crates/tish/tests/integration_test.rs +145 -7
  8. package/crates/tish_ast/src/ast.rs +3 -9
  9. package/crates/tish_build_utils/src/lib.rs +43 -15
  10. package/crates/tish_builtins/src/array.rs +2 -3
  11. package/crates/tish_builtins/src/construct.rs +15 -28
  12. package/crates/tish_builtins/src/globals.rs +18 -16
  13. package/crates/tish_builtins/src/helpers.rs +1 -4
  14. package/crates/tish_builtins/src/lib.rs +1 -0
  15. package/crates/tish_builtins/src/object.rs +10 -10
  16. package/crates/tish_builtins/src/string.rs +1 -3
  17. package/crates/tish_builtins/src/symbol.rs +83 -0
  18. package/crates/tish_compile/src/codegen.rs +123 -138
  19. package/crates/tish_compile/src/lib.rs +25 -3
  20. package/crates/tish_compile/src/resolve.rs +6 -3
  21. package/crates/tish_compile/src/types.rs +6 -6
  22. package/crates/tish_compile_js/src/codegen.rs +50 -29
  23. package/crates/tish_compile_js/src/tests_jsx.rs +44 -0
  24. package/crates/tish_core/src/console_style.rs +9 -0
  25. package/crates/tish_core/src/json.rs +17 -7
  26. package/crates/tish_core/src/macros.rs +2 -2
  27. package/crates/tish_core/src/value.rs +192 -4
  28. package/crates/tish_cranelift_runtime/Cargo.toml +4 -0
  29. package/crates/tish_eval/src/eval.rs +135 -73
  30. package/crates/tish_eval/src/http.rs +18 -12
  31. package/crates/tish_eval/src/lib.rs +29 -0
  32. package/crates/tish_eval/src/regex.rs +1 -1
  33. package/crates/tish_eval/src/value.rs +89 -4
  34. package/crates/tish_eval/src/value_convert.rs +30 -8
  35. package/crates/tish_fmt/src/lib.rs +4 -1
  36. package/crates/tish_lexer/src/lib.rs +7 -2
  37. package/crates/tish_llvm/src/lib.rs +2 -2
  38. package/crates/tish_lsp/src/builtin_goto.rs +111 -10
  39. package/crates/tish_lsp/src/import_goto.rs +35 -22
  40. package/crates/tish_lsp/src/main.rs +118 -85
  41. package/crates/tish_native/src/build.rs +187 -10
  42. package/crates/tish_native/src/lib.rs +92 -8
  43. package/crates/tish_parser/src/lib.rs +77 -0
  44. package/crates/tish_parser/src/parser.rs +71 -74
  45. package/crates/tish_pg/src/error.rs +1 -1
  46. package/crates/tish_pg/src/lib.rs +61 -73
  47. package/crates/tish_resolve/src/lib.rs +283 -158
  48. package/crates/tish_resolve/src/pos.rs +10 -2
  49. package/crates/tish_runtime/Cargo.toml +3 -0
  50. package/crates/tish_runtime/src/http.rs +39 -39
  51. package/crates/tish_runtime/src/http_fetch.rs +12 -12
  52. package/crates/tish_runtime/src/lib.rs +26 -43
  53. package/crates/tish_runtime/src/native_promise.rs +0 -11
  54. package/crates/tish_runtime/src/promise.rs +14 -1
  55. package/crates/tish_runtime/src/promise_io.rs +1 -4
  56. package/crates/tish_runtime/src/ws.rs +40 -27
  57. package/crates/tish_runtime/tests/fetch_readable_stream.rs +10 -8
  58. package/crates/tish_ui/src/jsx.rs +6 -4
  59. package/crates/tish_ui/src/lib.rs +2 -2
  60. package/crates/tish_ui/src/runtime/hooks.rs +5 -15
  61. package/crates/tish_ui/src/runtime/mod.rs +16 -17
  62. package/crates/tish_vm/Cargo.toml +2 -0
  63. package/crates/tish_vm/src/vm.rs +218 -153
  64. package/crates/tish_wasm/src/lib.rs +33 -7
  65. package/crates/tish_wasm_runtime/Cargo.toml +4 -1
  66. package/crates/tish_wasm_runtime/src/lib.rs +2 -1
  67. package/crates/tishlang_cargo_bindgen/src/classify.rs +1 -3
  68. package/crates/tishlang_cargo_bindgen/src/discover.rs +10 -5
  69. package/crates/tishlang_cargo_bindgen/src/infer.rs +18 -8
  70. package/crates/tishlang_cargo_bindgen/src/lib.rs +25 -26
  71. package/crates/tishlang_cargo_bindgen/src/main.rs +41 -38
  72. package/crates/tishlang_cargo_bindgen/src/metadata.rs +4 -1
  73. package/justfile +3 -3
  74. package/package.json +1 -1
  75. package/platform/darwin-arm64/tish +0 -0
  76. package/platform/darwin-x64/tish +0 -0
  77. package/platform/linux-arm64/tish +0 -0
  78. package/platform/linux-x64/tish +0 -0
  79. package/platform/win32-x64/tish.exe +0 -0
@@ -90,15 +90,9 @@ fn params_to_sql(values: &[JsonValue]) -> Result<Vec<Box<dyn ToSql + Sync + Send
90
90
  } else if let Some(u) = n.as_u64() {
91
91
  Box::new(u as i64)
92
92
  } else if let Some(f) = n.as_f64() {
93
- if f.fract() == 0.0
94
- && f >= i32::MIN as f64
95
- && f <= i32::MAX as f64
96
- {
93
+ if f.fract() == 0.0 && f >= i32::MIN as f64 && f <= i32::MAX as f64 {
97
94
  Box::new(f as i32)
98
- } else if f.fract() == 0.0
99
- && f >= i64::MIN as f64
100
- && f <= i64::MAX as f64
101
- {
95
+ } else if f.fract() == 0.0 && f >= i64::MIN as f64 && f <= i64::MAX as f64 {
102
96
  Box::new(f as i64)
103
97
  } else {
104
98
  Box::new(f)
@@ -110,7 +104,9 @@ fn params_to_sql(values: &[JsonValue]) -> Result<Vec<Box<dyn ToSql + Sync + Send
110
104
  }
111
105
  }
112
106
  JsonValue::String(s) => Box::new(s.clone()),
113
- JsonValue::Array(_) | JsonValue::Object(_) => Box::new(tokio_postgres::types::Json(v.clone())),
107
+ JsonValue::Array(_) | JsonValue::Object(_) => {
108
+ Box::new(tokio_postgres::types::Json(v.clone()))
109
+ }
114
110
  };
115
111
  out.push(b);
116
112
  }
@@ -222,7 +218,7 @@ fn row_to_value_direct(row: &Row) -> tishlang_runtime::Value {
222
218
  };
223
219
  om.insert(key, v);
224
220
  }
225
- RtValue::Object(VmRef::new(om))
221
+ RtValue::object(om)
226
222
  }
227
223
 
228
224
  fn row_to_object(row: &Row) -> Result<JsonValue> {
@@ -378,8 +374,8 @@ pub struct PerWorkerClient {
378
374
  impl PerWorkerClient {
379
375
  /// Open a single direct connection (no pool).
380
376
  pub async fn connect(connection_string: &str) -> Result<Self> {
381
- let cfg = parse_connection_string(connection_string)
382
- .map_err(TishPgError::BadConnectionString)?;
377
+ let cfg =
378
+ parse_connection_string(connection_string).map_err(TishPgError::BadConnectionString)?;
383
379
  let (client, connection) = cfg.connect(NoTls).await?;
384
380
  let driver = tokio::spawn(async move {
385
381
  if let Err(e) = connection.await {
@@ -530,13 +526,11 @@ mod tish_sync {
530
526
  use super::*;
531
527
  use once_cell::sync::Lazy;
532
528
  use slab::Slab;
533
- use std::sync::Mutex;
534
529
  use tishlang_runtime::Value as TishValue;
535
530
  use tokio::runtime::Runtime as TokioRuntime;
536
531
 
537
- static RT: Lazy<TokioRuntime> = Lazy::new(|| {
538
- TokioRuntime::new().expect("tish_pg: failed to build tokio runtime")
539
- });
532
+ static RT: Lazy<TokioRuntime> =
533
+ Lazy::new(|| TokioRuntime::new().expect("tish_pg: failed to build tokio runtime"));
540
534
  // `RwLock` (not `Mutex`) on the registries: hot path is read-only —
541
535
  // every query does `get_client(id)` + `get_statement(id)`. Inserts
542
536
  // happen once per `connect`/`prepare` at startup. With multiple HTTP
@@ -544,8 +538,7 @@ mod tish_sync {
544
538
  // serialised every query through one global lock; `RwLock` lets all
545
539
  // concurrent reads run lock-free against each other.
546
540
  use std::sync::RwLock;
547
- static CLIENTS: Lazy<RwLock<Slab<PerWorkerClient>>> =
548
- Lazy::new(|| RwLock::new(Slab::new()));
541
+ static CLIENTS: Lazy<RwLock<Slab<PerWorkerClient>>> = Lazy::new(|| RwLock::new(Slab::new()));
549
542
  static STATEMENTS: Lazy<RwLock<Slab<(usize, Statement)>>> =
550
543
  Lazy::new(|| RwLock::new(Slab::new()));
551
544
 
@@ -609,12 +602,10 @@ mod tish_sync {
609
602
  .map(JsonValue::Number)
610
603
  .unwrap_or(JsonValue::Null),
611
604
  TishValue::String(s) => JsonValue::String(s.to_string()),
612
- TishValue::Array(a) => {
613
- JsonValue::Array(a.borrow().iter().map(tish_to_json).collect())
614
- }
605
+ TishValue::Array(a) => JsonValue::Array(a.borrow().iter().map(tish_to_json).collect()),
615
606
  TishValue::Object(o) => {
616
607
  let mut m = serde_json::Map::new();
617
- for (k, v) in o.borrow().iter() {
608
+ for (k, v) in o.borrow().strings.iter() {
618
609
  m.insert(k.to_string(), tish_to_json(v));
619
610
  }
620
611
  JsonValue::Object(m)
@@ -623,35 +614,35 @@ mod tish_sync {
623
614
  }
624
615
  }
625
616
 
626
- fn json_to_tish(v: JsonValue) -> TishValue {
627
- use std::cell::RefCell;
628
- use std::rc::Rc;
629
- use std::sync::Arc;
630
- use tishlang_runtime::ObjectMap;
631
- match v {
632
- JsonValue::Null => TishValue::Null,
633
- JsonValue::Bool(b) => TishValue::Bool(b),
634
- JsonValue::Number(n) => TishValue::Number(n.as_f64().unwrap_or(0.0)),
635
- JsonValue::String(s) => TishValue::String(s.into()),
636
- JsonValue::Array(a) => {
637
- let mut out = Vec::with_capacity(a.len());
638
- for item in a {
639
- out.push(json_to_tish(item));
640
- }
641
- TishValue::Array(VmRef::new(out))
642
- }
643
- JsonValue::Object(m) => {
644
- // Pre-allocate ObjectMap capacity so HashMap doesn't rehash
645
- // on every insert. Common TFB rows are 2 columns (id,
646
- // randomnumber or id, message).
647
- let mut om = ObjectMap::with_capacity(m.len());
648
- for (k, v) in m {
649
- om.insert(Arc::from(k), json_to_tish(v));
650
- }
651
- TishValue::Object(VmRef::new(om))
652
- }
653
- }
654
- }
617
+ // fn json_to_tish(v: JsonValue) -> TishValue {
618
+ // use std::cell::RefCell;
619
+ // use std::rc::Rc;
620
+ // use std::sync::Arc;
621
+ // use tishlang_runtime::ObjectMap;
622
+ // match v {
623
+ // JsonValue::Null => TishValue::Null,
624
+ // JsonValue::Bool(b) => TishValue::Bool(b),
625
+ // JsonValue::Number(n) => TishValue::Number(n.as_f64().unwrap_or(0.0)),
626
+ // JsonValue::String(s) => TishValue::String(s.into()),
627
+ // JsonValue::Array(a) => {
628
+ // let mut out = Vec::with_capacity(a.len());
629
+ // for item in a {
630
+ // out.push(json_to_tish(item));
631
+ // }
632
+ // TishValue::Array(VmRef::new(out))
633
+ // }
634
+ // JsonValue::Object(m) => {
635
+ // // Pre-allocate ObjectMap capacity so HashMap doesn't rehash
636
+ // // on every insert. Common TFB rows are 2 columns (id,
637
+ // // randomnumber or id, message).
638
+ // let mut om = ObjectMap::with_capacity(m.len());
639
+ // for (k, v) in m {
640
+ // om.insert(Arc::from(k), json_to_tish(v));
641
+ // }
642
+ // TishValue::object(om)
643
+ // }
644
+ // }
645
+ // }
655
646
 
656
647
  fn tish_err(msg: impl Into<String>) -> TishValue {
657
648
  use std::sync::Arc;
@@ -659,16 +650,14 @@ mod tish_sync {
659
650
  let mut om = ObjectMap::with_capacity(2);
660
651
  om.insert(Arc::from("error"), TishValue::String(msg.into().into()));
661
652
  om.insert(Arc::from("ok"), TishValue::Bool(false));
662
- TishValue::Object(VmRef::new(om))
653
+ TishValue::object(om)
663
654
  }
664
655
 
665
- fn rows_to_value(res: QueryResult) -> TishValue {
666
- use std::cell::RefCell;
667
- use std::rc::Rc;
668
- TishValue::Array(VmRef::new(
669
- res.rows.into_iter().map(json_to_tish).collect(),
670
- ))
671
- }
656
+ // fn rows_to_value(res: QueryResult) -> TishValue {
657
+ // use std::cell::RefCell;
658
+ // use std::rc::Rc;
659
+ // TishValue::Array(VmRef::new(res.rows.into_iter().map(json_to_tish).collect()))
660
+ // }
672
661
 
673
662
  /// `perWorkerClient(connection_string) -> client_handle` (blocking).
674
663
  pub fn per_worker_client(args: &[TishValue]) -> TishValue {
@@ -682,7 +671,10 @@ mod tish_sync {
682
671
  let id = g.insert(c);
683
672
  TishValue::Number(id as f64)
684
673
  }
685
- Err(e) => tish_err(format!("perWorkerClient: {}", crate::format_tish_pg_error(&e))),
674
+ Err(e) => tish_err(format!(
675
+ "perWorkerClient: {}",
676
+ crate::format_tish_pg_error(&e)
677
+ )),
686
678
  }
687
679
  }
688
680
 
@@ -694,9 +686,8 @@ mod tish_sync {
694
686
  let cs = match args.first() {
695
687
  Some(TishValue::String(s)) => s.to_string(),
696
688
  Some(TishValue::Object(obj)) => {
697
- use std::sync::Arc;
698
689
  let b = obj.borrow();
699
- match b.get(&Arc::from("connectionString")) {
690
+ match b.strings.get("connectionString") {
700
691
  Some(TishValue::String(s)) => s.to_string(),
701
692
  _ => return tish_err("connect: options.connectionString missing"),
702
693
  }
@@ -754,11 +745,7 @@ mod tish_sync {
754
745
  return tish_err("queryPrepared: expected (client, stmt, params)");
755
746
  };
756
747
  let params = match args.get(2) {
757
- Some(TishValue::Array(a)) => a
758
- .borrow()
759
- .iter()
760
- .map(tish_to_json)
761
- .collect::<Vec<_>>(),
748
+ Some(TishValue::Array(a)) => a.borrow().iter().map(tish_to_json).collect::<Vec<_>>(),
762
749
  Some(TishValue::Null) | None => Vec::new(),
763
750
  Some(v) => vec![tish_to_json(v)],
764
751
  };
@@ -773,7 +760,10 @@ mod tish_sync {
773
760
  // produces. Fewer allocations + interned column-name `Arc`s.
774
761
  match block_on(client.query_prepared_to_values(&stmt, &params)) {
775
762
  Ok(rows) => TishValue::Array(VmRef::new(rows)),
776
- Err(e) => tish_err(format!("queryPrepared: {}", crate::format_tish_pg_error(&e))),
763
+ Err(e) => tish_err(format!(
764
+ "queryPrepared: {}",
765
+ crate::format_tish_pg_error(&e)
766
+ )),
777
767
  }
778
768
  }
779
769
 
@@ -895,10 +885,8 @@ mod tish_sync {
895
885
  let rows = raw_client
896
886
  .query("SELECT name FROM _tish_pg_migrations", &[])
897
887
  .await?;
898
- let already: std::collections::HashSet<String> = rows
899
- .iter()
900
- .map(|r| r.get::<_, String>(0))
901
- .collect();
888
+ let already: std::collections::HashSet<String> =
889
+ rows.iter().map(|r| r.get::<_, String>(0)).collect();
902
890
 
903
891
  let mut applied_now: Vec<String> = Vec::new();
904
892
  for (name, path) in &files {
@@ -942,7 +930,7 @@ mod tish_sync {
942
930
  let mut om = ObjectMap::with_capacity(2);
943
931
  om.insert(Arc::from("ok"), TishValue::Bool(true));
944
932
  om.insert(Arc::from("applied"), TishValue::Array(VmRef::new(applied)));
945
- TishValue::Object(VmRef::new(om))
933
+ TishValue::object(om)
946
934
  }
947
935
  }
948
936