@tishlang/tish 1.6.0 → 1.7.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/Cargo.toml +1 -0
  2. package/bin/tish +0 -0
  3. package/crates/js_to_tish/src/error.rs +2 -8
  4. package/crates/js_to_tish/src/transform/expr.rs +101 -130
  5. package/crates/js_to_tish/src/transform/stmt.rs +25 -22
  6. package/crates/tish/Cargo.toml +1 -1
  7. package/crates/tish/src/cli_help.rs +76 -29
  8. package/crates/tish/src/main.rs +85 -54
  9. package/crates/tish/tests/cargo_example_compile.rs +3 -1
  10. package/crates/tish/tests/integration_test.rs +197 -47
  11. package/crates/tish/tests/run_optimize_stdout_parity.rs +3 -7
  12. package/crates/tish/tests/shortcircuit.rs +19 -4
  13. package/crates/tish_ast/src/ast.rs +12 -14
  14. package/crates/tish_build_utils/src/lib.rs +31 -6
  15. package/crates/tish_builtins/src/array.rs +52 -21
  16. package/crates/tish_builtins/src/construct.rs +2 -8
  17. package/crates/tish_builtins/src/globals.rs +30 -15
  18. package/crates/tish_builtins/src/lib.rs +5 -5
  19. package/crates/tish_builtins/src/math.rs +5 -3
  20. package/crates/tish_builtins/src/string.rs +71 -19
  21. package/crates/tish_bytecode/src/chunk.rs +0 -1
  22. package/crates/tish_bytecode/src/compiler.rs +164 -60
  23. package/crates/tish_bytecode/src/opcode.rs +13 -4
  24. package/crates/tish_bytecode/src/peephole.rs +2 -2
  25. package/crates/tish_compile/src/codegen.rs +921 -299
  26. package/crates/tish_compile/src/infer.rs +69 -19
  27. package/crates/tish_compile/src/lib.rs +15 -5
  28. package/crates/tish_compile/src/resolve.rs +112 -69
  29. package/crates/tish_compile/src/types.rs +10 -14
  30. package/crates/tish_compile_js/src/codegen.rs +34 -13
  31. package/crates/tish_compile_js/src/tests_jsx.rs +30 -6
  32. package/crates/tish_compiler_wasm/src/lib.rs +16 -13
  33. package/crates/tish_compiler_wasm/src/resolve_virtual.rs +39 -48
  34. package/crates/tish_core/src/json.rs +5 -3
  35. package/crates/tish_core/src/lib.rs +1 -1
  36. package/crates/tish_core/src/uri.rs +9 -6
  37. package/crates/tish_core/src/value.rs +92 -28
  38. package/crates/tish_cranelift/src/link.rs +6 -9
  39. package/crates/tish_cranelift/src/lower.rs +14 -8
  40. package/crates/tish_eval/src/eval.rs +389 -142
  41. package/crates/tish_eval/src/lib.rs +10 -6
  42. package/crates/tish_eval/src/natives.rs +95 -38
  43. package/crates/tish_eval/src/promise.rs +14 -8
  44. package/crates/tish_eval/src/timers.rs +28 -19
  45. package/crates/tish_eval/src/value.rs +10 -3
  46. package/crates/tish_fmt/src/lib.rs +29 -13
  47. package/crates/tish_lexer/src/lib.rs +217 -63
  48. package/crates/tish_lexer/src/token.rs +6 -6
  49. package/crates/tish_llvm/src/lib.rs +15 -8
  50. package/crates/tish_lsp/src/main.rs +41 -43
  51. package/crates/tish_native/src/build.rs +1 -6
  52. package/crates/tish_native/src/lib.rs +48 -19
  53. package/crates/tish_opt/src/lib.rs +67 -50
  54. package/crates/tish_parser/src/lib.rs +36 -11
  55. package/crates/tish_parser/src/parser.rs +172 -87
  56. package/crates/tish_runtime/src/http.rs +15 -6
  57. package/crates/tish_runtime/src/http_fetch.rs +24 -14
  58. package/crates/tish_runtime/src/lib.rs +224 -168
  59. package/crates/tish_runtime/src/promise.rs +1 -5
  60. package/crates/tish_runtime/src/ws.rs +45 -20
  61. package/crates/tish_runtime/tests/fetch_readable_stream.rs +5 -4
  62. package/crates/tish_ui/src/jsx.rs +41 -22
  63. package/crates/tish_ui/src/lib.rs +2 -2
  64. package/crates/tish_vm/src/vm.rs +309 -112
  65. package/crates/tish_vm/tests/peephole_jump_chain_logical_or.rs +8 -3
  66. package/crates/tish_wasm/src/lib.rs +38 -28
  67. package/crates/tishlang_cargo_bindgen/Cargo.toml +25 -0
  68. package/crates/tishlang_cargo_bindgen/src/classify.rs +265 -0
  69. package/crates/tishlang_cargo_bindgen/src/discover.rs +52 -0
  70. package/crates/tishlang_cargo_bindgen/src/infer.rs +372 -0
  71. package/crates/tishlang_cargo_bindgen/src/lib.rs +349 -0
  72. package/crates/tishlang_cargo_bindgen/src/main.rs +164 -0
  73. package/crates/tishlang_cargo_bindgen/src/metadata.rs +114 -0
  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
@@ -5,7 +5,7 @@
5
5
 
6
6
  mod token;
7
7
 
8
- pub use token::{Token, TokenKind, Span};
8
+ pub use token::{Span, Token, TokenKind};
9
9
 
10
10
  use std::collections::VecDeque;
11
11
  use std::iter::Peekable;
@@ -74,14 +74,21 @@ impl<'a> Lexer<'a> {
74
74
  loop {
75
75
  match self.peek() {
76
76
  None | Some('{') | Some('<') => break,
77
- Some(c) => { self.advance(); s.push(c); }
77
+ Some(c) => {
78
+ self.advance();
79
+ s.push(c);
80
+ }
78
81
  }
79
82
  }
80
83
  if s.is_empty() {
81
84
  Ok(None)
82
85
  } else {
83
86
  let end = self.span_start();
84
- Ok(Some(Token { kind: TokenKind::JsxText, span: Span { start, end }, literal: Some(s.into()) }))
87
+ Ok(Some(Token {
88
+ kind: TokenKind::JsxText,
89
+ span: Span { start, end },
90
+ literal: Some(s.into()),
91
+ }))
85
92
  }
86
93
  }
87
94
 
@@ -139,7 +146,9 @@ impl<'a> Lexer<'a> {
139
146
 
140
147
  fn skip_line_comment(&mut self) {
141
148
  while let Some(c) = self.advance() {
142
- if c == '\n' { break; }
149
+ if c == '\n' {
150
+ break;
151
+ }
143
152
  }
144
153
  }
145
154
 
@@ -147,8 +156,14 @@ impl<'a> Lexer<'a> {
147
156
  let mut depth = 1;
148
157
  while depth > 0 {
149
158
  match self.advance() {
150
- Some('*') if self.peek() == Some('/') => { self.advance(); depth -= 1; }
151
- Some('/') if self.peek() == Some('*') => { self.advance(); depth += 1; }
159
+ Some('*') if self.peek() == Some('/') => {
160
+ self.advance();
161
+ depth -= 1;
162
+ }
163
+ Some('/') if self.peek() == Some('*') => {
164
+ self.advance();
165
+ depth += 1;
166
+ }
152
167
  None => return Err("Unterminated block comment".to_string()),
153
168
  _ => {}
154
169
  }
@@ -186,7 +201,11 @@ impl<'a> Lexer<'a> {
186
201
 
187
202
  fn read_string(&mut self, quote: char) -> Result<String, String> {
188
203
  let mut s = String::with_capacity(32);
189
- let extra = if quote == '"' { &['"', '\''][..] } else { &['\'', '"'][..] };
204
+ let extra = if quote == '"' {
205
+ &['"', '\''][..]
206
+ } else {
207
+ &['\'', '"'][..]
208
+ };
190
209
  loop {
191
210
  match self.advance() {
192
211
  None => return Err("Unterminated string".to_string()),
@@ -213,24 +232,44 @@ impl<'a> Lexer<'a> {
213
232
  }
214
233
 
215
234
  /// Read a template literal. If `is_continuation` is true, we're continuing after a `}`.
216
- fn read_template(&mut self, start: (usize, usize), is_continuation: bool) -> Result<Option<Token>, String> {
235
+ fn read_template(
236
+ &mut self,
237
+ start: (usize, usize),
238
+ is_continuation: bool,
239
+ ) -> Result<Option<Token>, String> {
217
240
  let mut s = String::with_capacity(if is_continuation { 32 } else { 64 });
218
241
  let extra = &['`', '$', '{'][..];
219
-
242
+
220
243
  loop {
221
244
  match self.advance() {
222
245
  None => return Err("Unterminated template literal".to_string()),
223
246
  Some('`') => {
224
247
  let end = self.span_start();
225
- let kind = if is_continuation { TokenKind::TemplateTail } else { TokenKind::TemplateNoSub };
226
- return Ok(Some(Token { kind, span: Span { start, end }, literal: Some(s.into()) }));
248
+ let kind = if is_continuation {
249
+ TokenKind::TemplateTail
250
+ } else {
251
+ TokenKind::TemplateNoSub
252
+ };
253
+ return Ok(Some(Token {
254
+ kind,
255
+ span: Span { start, end },
256
+ literal: Some(s.into()),
257
+ }));
227
258
  }
228
259
  Some('$') if self.peek() == Some('{') => {
229
260
  self.advance();
230
261
  self.template_brace_stack.push(1);
231
262
  let end = self.span_start();
232
- let kind = if is_continuation { TokenKind::TemplateMiddle } else { TokenKind::TemplateHead };
233
- return Ok(Some(Token { kind, span: Span { start, end }, literal: Some(s.into()) }));
263
+ let kind = if is_continuation {
264
+ TokenKind::TemplateMiddle
265
+ } else {
266
+ TokenKind::TemplateHead
267
+ };
268
+ return Ok(Some(Token {
269
+ kind,
270
+ span: Span { start, end },
271
+ literal: Some(s.into()),
272
+ }));
234
273
  }
235
274
  Some('\\') => s.push(self.handle_escape(extra)?),
236
275
  Some(c) => s.push(c),
@@ -308,7 +347,10 @@ impl<'a> Lexer<'a> {
308
347
  self.indent_stack.pop();
309
348
  return Ok(Some(Token {
310
349
  kind: TokenKind::Dedent,
311
- span: Span { start: (self.line, self.col), end: (self.line, self.col) },
350
+ span: Span {
351
+ start: (self.line, self.col),
352
+ end: (self.line, self.col),
353
+ },
312
354
  literal: None,
313
355
  }));
314
356
  }
@@ -362,31 +404,66 @@ impl<'a> Lexer<'a> {
362
404
  ';' => TokenKind::Semicolon,
363
405
  ',' => TokenKind::Comma,
364
406
  '.' => {
365
- if self.peek() == Some('?') { self.advance(); TokenKind::OptionalChain }
366
- else if self.peek() == Some('.') {
407
+ if self.peek() == Some('?') {
367
408
  self.advance();
368
- if self.peek() == Some('.') { self.advance(); TokenKind::Spread }
369
- else { return Err("Unexpected .. (use ... for rest params)".to_string()); }
370
- } else { TokenKind::Dot }
409
+ TokenKind::OptionalChain
410
+ } else if self.peek() == Some('.') {
411
+ self.advance();
412
+ if self.peek() == Some('.') {
413
+ self.advance();
414
+ TokenKind::Spread
415
+ } else {
416
+ return Err("Unexpected .. (use ... for rest params)".to_string());
417
+ }
418
+ } else {
419
+ TokenKind::Dot
420
+ }
371
421
  }
372
422
  '=' => {
373
423
  if self.peek() == Some('=') {
374
424
  self.advance();
375
- if self.peek() == Some('=') { self.advance(); TokenKind::StrictEq } else { TokenKind::Eq }
376
- } else if self.peek() == Some('>') { self.advance(); TokenKind::Arrow }
377
- else { TokenKind::Assign }
425
+ if self.peek() == Some('=') {
426
+ self.advance();
427
+ TokenKind::StrictEq
428
+ } else {
429
+ TokenKind::Eq
430
+ }
431
+ } else if self.peek() == Some('>') {
432
+ self.advance();
433
+ TokenKind::Arrow
434
+ } else {
435
+ TokenKind::Assign
436
+ }
378
437
  }
379
438
  '!' => {
380
439
  if self.peek() == Some('=') {
381
440
  self.advance();
382
- if self.peek() == Some('=') { self.advance(); TokenKind::StrictNe } else { TokenKind::Ne }
383
- } else { TokenKind::Not }
441
+ if self.peek() == Some('=') {
442
+ self.advance();
443
+ TokenKind::StrictNe
444
+ } else {
445
+ TokenKind::Ne
446
+ }
447
+ } else {
448
+ TokenKind::Not
449
+ }
384
450
  }
385
451
  '<' => {
386
- if self.peek() == Some('=') { self.advance(); TokenKind::Le }
387
- else if self.peek() == Some('<') { self.advance(); TokenKind::Shl }
388
- else if self.peek() == Some('/') { self.jsx_in_closing_tag = true; TokenKind::Lt }
389
- else if self.peek() == Some('>') || self.peek().map(|c| c.is_ascii_alphabetic() || c == '_').unwrap_or(false) {
452
+ if self.peek() == Some('=') {
453
+ self.advance();
454
+ TokenKind::Le
455
+ } else if self.peek() == Some('<') {
456
+ self.advance();
457
+ TokenKind::Shl
458
+ } else if self.peek() == Some('/') {
459
+ self.jsx_in_closing_tag = true;
460
+ TokenKind::Lt
461
+ } else if self.peek() == Some('>')
462
+ || self
463
+ .peek()
464
+ .map(|c| c.is_ascii_alphabetic() || c == '_')
465
+ .unwrap_or(false)
466
+ {
390
467
  self.jsx_depth += 1;
391
468
  self.jsx_stack.push(JsxEl {
392
469
  in_opener: true,
@@ -394,12 +471,18 @@ impl<'a> Lexer<'a> {
394
471
  });
395
472
  self.jsx_in_opening_tag = true;
396
473
  TokenKind::Lt
397
- } else { TokenKind::Lt }
474
+ } else {
475
+ TokenKind::Lt
476
+ }
398
477
  }
399
478
  '>' => {
400
- if self.peek() == Some('=') { self.advance(); TokenKind::Ge }
401
- else if self.peek() == Some('>') { self.advance(); TokenKind::Shr }
402
- else {
479
+ if self.peek() == Some('=') {
480
+ self.advance();
481
+ TokenKind::Ge
482
+ } else if self.peek() == Some('>') {
483
+ self.advance();
484
+ TokenKind::Shr
485
+ } else {
403
486
  if self.jsx_in_closing_tag {
404
487
  self.jsx_depth = (self.jsx_depth - 1).max(0);
405
488
  self.jsx_stack.pop();
@@ -425,66 +508,126 @@ impl<'a> Lexer<'a> {
425
508
  '^' => TokenKind::BitXor,
426
509
  '~' => TokenKind::BitNot,
427
510
  '+' => {
428
- if self.peek() == Some('+') { self.advance(); TokenKind::PlusPlus }
429
- else if self.peek() == Some('=') { self.advance(); TokenKind::PlusAssign }
430
- else { TokenKind::Plus }
511
+ if self.peek() == Some('+') {
512
+ self.advance();
513
+ TokenKind::PlusPlus
514
+ } else if self.peek() == Some('=') {
515
+ self.advance();
516
+ TokenKind::PlusAssign
517
+ } else {
518
+ TokenKind::Plus
519
+ }
431
520
  }
432
521
  '-' => {
433
- if self.peek() == Some('-') { self.advance(); TokenKind::MinusMinus }
434
- else if self.peek() == Some('=') { self.advance(); TokenKind::MinusAssign }
435
- else { TokenKind::Minus }
522
+ if self.peek() == Some('-') {
523
+ self.advance();
524
+ TokenKind::MinusMinus
525
+ } else if self.peek() == Some('=') {
526
+ self.advance();
527
+ TokenKind::MinusAssign
528
+ } else {
529
+ TokenKind::Minus
530
+ }
436
531
  }
437
532
  '*' => {
438
- if self.peek() == Some('*') { self.advance(); TokenKind::StarStar }
439
- else if self.peek() == Some('=') { self.advance(); TokenKind::StarAssign }
440
- else { TokenKind::Star }
533
+ if self.peek() == Some('*') {
534
+ self.advance();
535
+ TokenKind::StarStar
536
+ } else if self.peek() == Some('=') {
537
+ self.advance();
538
+ TokenKind::StarAssign
539
+ } else {
540
+ TokenKind::Star
541
+ }
441
542
  }
442
543
  '/' => {
443
- if self.peek() == Some('/') { self.advance(); self.skip_line_comment(); return self.next_token(); }
444
- else if self.peek() == Some('*') { self.advance(); self.skip_block_comment()?; return self.next_token(); }
445
- else if self.peek() == Some('=') { self.advance(); TokenKind::SlashAssign }
446
- else {
447
- if self.jsx_in_opening_tag { self.jsx_saw_slash_before_gt = true; }
544
+ if self.peek() == Some('/') {
545
+ self.advance();
546
+ self.skip_line_comment();
547
+ return self.next_token();
548
+ } else if self.peek() == Some('*') {
549
+ self.advance();
550
+ self.skip_block_comment()?;
551
+ return self.next_token();
552
+ } else if self.peek() == Some('=') {
553
+ self.advance();
554
+ TokenKind::SlashAssign
555
+ } else {
556
+ if self.jsx_in_opening_tag {
557
+ self.jsx_saw_slash_before_gt = true;
558
+ }
448
559
  TokenKind::Slash
449
560
  }
450
561
  }
451
562
  '%' => {
452
- if self.peek() == Some('=') { self.advance(); TokenKind::PercentAssign }
453
- else { TokenKind::Percent }
563
+ if self.peek() == Some('=') {
564
+ self.advance();
565
+ TokenKind::PercentAssign
566
+ } else {
567
+ TokenKind::Percent
568
+ }
454
569
  }
455
570
  '&' => {
456
571
  if self.peek() == Some('&') {
457
572
  self.advance();
458
- if self.peek() == Some('=') { self.advance(); TokenKind::AndAndAssign }
459
- else { TokenKind::And }
460
- } else { TokenKind::BitAnd }
573
+ if self.peek() == Some('=') {
574
+ self.advance();
575
+ TokenKind::AndAndAssign
576
+ } else {
577
+ TokenKind::And
578
+ }
579
+ } else {
580
+ TokenKind::BitAnd
581
+ }
461
582
  }
462
583
  '|' => {
463
584
  if self.peek() == Some('|') {
464
585
  self.advance();
465
- if self.peek() == Some('=') { self.advance(); TokenKind::OrOrAssign }
466
- else { TokenKind::Or }
467
- } else { TokenKind::BitOr }
586
+ if self.peek() == Some('=') {
587
+ self.advance();
588
+ TokenKind::OrOrAssign
589
+ } else {
590
+ TokenKind::Or
591
+ }
592
+ } else {
593
+ TokenKind::BitOr
594
+ }
468
595
  }
469
596
  '?' => {
470
597
  if self.peek() == Some('?') {
471
598
  self.advance();
472
- if self.peek() == Some('=') { self.advance(); TokenKind::NullishAssign }
473
- else { TokenKind::NullishCoalesce }
474
- } else if self.peek() == Some('.') { self.advance(); TokenKind::OptionalChain }
475
- else { TokenKind::Question }
599
+ if self.peek() == Some('=') {
600
+ self.advance();
601
+ TokenKind::NullishAssign
602
+ } else {
603
+ TokenKind::NullishCoalesce
604
+ }
605
+ } else if self.peek() == Some('.') {
606
+ self.advance();
607
+ TokenKind::OptionalChain
608
+ } else {
609
+ TokenKind::Question
610
+ }
476
611
  }
477
612
  ':' => TokenKind::Colon,
478
613
  '"' | '\'' => {
479
614
  let s = self.read_string(c)?;
480
615
  let end = self.span_start();
481
- return Ok(Some(Token { kind: TokenKind::String, span: Span { start, end }, literal: Some(s.into()) }));
616
+ return Ok(Some(Token {
617
+ kind: TokenKind::String,
618
+ span: Span { start, end },
619
+ literal: Some(s.into()),
620
+ }));
482
621
  }
483
622
  '`' => return self.read_template(start, false),
484
623
  '0'..='9' => {
485
624
  let num = self.read_number(c);
486
625
  let end = self.span_start();
487
- return Ok(Some(Token { kind: TokenKind::Number, span: Span { start, end }, literal: Some(num.into()) }));
626
+ return Ok(Some(Token {
627
+ kind: TokenKind::Number,
628
+ span: Span { start, end },
629
+ literal: Some(num.into()),
630
+ }));
488
631
  }
489
632
  'a'..='z' | 'A'..='Z' | '_' => {
490
633
  let ident = self.read_ident_or_keyword(c);
@@ -493,15 +636,26 @@ impl<'a> Lexer<'a> {
493
636
  return Ok(Some(Token {
494
637
  kind,
495
638
  span: Span { start, end },
496
- literal: if matches!(kind, TokenKind::Ident) { Some(ident.into()) } else { None },
639
+ literal: if matches!(kind, TokenKind::Ident) {
640
+ Some(ident.into())
641
+ } else {
642
+ None
643
+ },
497
644
  }));
498
645
  }
499
- '\n' => { self.at_line_start = true; return self.next_token(); }
646
+ '\n' => {
647
+ self.at_line_start = true;
648
+ return self.next_token();
649
+ }
500
650
  _ => return Err(format!("Unexpected character: {:?}", c)),
501
651
  };
502
652
 
503
653
  let end = self.span_start();
504
- Ok(Some(Token { kind, span: Span { start, end }, literal: None }))
654
+ Ok(Some(Token {
655
+ kind,
656
+ span: Span { start, end },
657
+ literal: None,
658
+ }))
505
659
  }
506
660
  }
507
661
 
@@ -110,14 +110,14 @@ pub enum TokenKind {
110
110
  NullishCoalesce,
111
111
  Question,
112
112
  Arrow,
113
-
113
+
114
114
  // Template literal tokens
115
- TemplateNoSub, // `text` (no interpolation)
116
- TemplateHead, // `text${ (start with interpolation)
117
- TemplateMiddle, // }text${ (middle part)
118
- TemplateTail, // }text` (end part)
115
+ TemplateNoSub, // `text` (no interpolation)
116
+ TemplateHead, // `text${ (start with interpolation)
117
+ TemplateMiddle, // }text${ (middle part)
118
+ TemplateTail, // }text` (end part)
119
119
 
120
- JsxText, // Raw text in JSX children (emojis, etc.); only {}<> are special
120
+ JsxText, // Raw text in JSX children (emojis, etc.); only {}<> are special
121
121
  }
122
122
 
123
123
  impl TokenKind {
@@ -17,10 +17,15 @@ pub fn compile_to_native(
17
17
  project_root: Option<&Path>,
18
18
  output_path: &Path,
19
19
  ) -> Result<(), LlvmError> {
20
- let modules = resolve_project(entry_path, project_root)
21
- .map_err(|e| LlvmError { message: e.to_string() })?;
22
- detect_cycles(&modules).map_err(|e| LlvmError { message: e.to_string() })?;
23
- let program = merge_modules(modules).map_err(|e| LlvmError { message: e.to_string() })?;
20
+ let modules = resolve_project(entry_path, project_root).map_err(|e| LlvmError {
21
+ message: e.to_string(),
22
+ })?;
23
+ detect_cycles(&modules).map_err(|e| LlvmError {
24
+ message: e.to_string(),
25
+ })?;
26
+ let program = merge_modules(modules).map_err(|e| LlvmError {
27
+ message: e.to_string(),
28
+ })?;
24
29
  let chunk = tishlang_bytecode::compile(&program).map_err(|e| LlvmError {
25
30
  message: e.to_string(),
26
31
  })?;
@@ -71,7 +76,10 @@ const uint64_t tish_chunk_len = sizeof(tish_chunk_data);
71
76
  .arg(&chunk_c_path)
72
77
  .status()
73
78
  .map_err(|e| LlvmError {
74
- message: format!("Failed to run clang: {}. Install clang (LLVM) or set CLANG env var.", e),
79
+ message: format!(
80
+ "Failed to run clang: {}. Install clang (LLVM) or set CLANG env var.",
81
+ e
82
+ ),
75
83
  })?;
76
84
 
77
85
  if !status.success() {
@@ -84,9 +92,8 @@ const uint64_t tish_chunk_len = sizeof(tish_chunk_data);
84
92
  let object_path_canonical = object_path.canonicalize().map_err(|e| LlvmError {
85
93
  message: format!("Cannot canonicalize object path: {}", e),
86
94
  })?;
87
- tishlang_cranelift::link_to_binary(&object_path_canonical, output_path, features).map_err(|e| LlvmError {
88
- message: e.message,
89
- })?;
95
+ tishlang_cranelift::link_to_binary(&object_path_canonical, output_path, features)
96
+ .map_err(|e| LlvmError { message: e.message })?;
90
97
 
91
98
  Ok(())
92
99
  }
@@ -7,12 +7,12 @@ use std::sync::{Arc, RwLock};
7
7
  use regex::Regex;
8
8
  use tower_lsp::jsonrpc::Result;
9
9
  use tower_lsp::lsp_types::{
10
- CompletionItem, CompletionItemKind, NumberOrString,
11
- CompletionParams, CompletionResponse, CompletionTriggerKind, Diagnostic, DiagnosticSeverity,
12
- DidChangeTextDocumentParams, DidCloseTextDocumentParams, DidOpenTextDocumentParams,
13
- DocumentFormattingParams, DocumentSymbolParams, DocumentSymbolResponse, GotoDefinitionParams,
14
- GotoDefinitionResponse, InitializeParams, InitializeResult, Location, MessageType, OneOf,
15
- Position, Range, ServerCapabilities, ServerInfo, SymbolInformation, SymbolKind,
10
+ CompletionItem, CompletionItemKind, CompletionParams, CompletionResponse,
11
+ CompletionTriggerKind, Diagnostic, DiagnosticSeverity, DidChangeTextDocumentParams,
12
+ DidCloseTextDocumentParams, DidOpenTextDocumentParams, DocumentFormattingParams,
13
+ DocumentSymbolParams, DocumentSymbolResponse, GotoDefinitionParams, GotoDefinitionResponse,
14
+ InitializeParams, InitializeResult, Location, MessageType, NumberOrString, OneOf, Position,
15
+ Range, ServerCapabilities, ServerInfo, SymbolInformation, SymbolKind,
16
16
  TextDocumentPositionParams, TextDocumentSyncCapability, TextDocumentSyncKind, Url,
17
17
  WorkspaceSymbolParams,
18
18
  };
@@ -171,11 +171,7 @@ impl LanguageServer for Backend {
171
171
  }
172
172
 
173
173
  async fn completion(&self, params: CompletionParams) -> Result<Option<CompletionResponse>> {
174
- let uri = params
175
- .text_document_position
176
- .text_document
177
- .uri
178
- .clone();
174
+ let uri = params.text_document_position.text_document.uri.clone();
179
175
  let _pos = params.text_document_position.position;
180
176
  let text = {
181
177
  let g = self.docs.read().unwrap();
@@ -223,10 +219,8 @@ impl LanguageServer for Backend {
223
219
  }
224
220
 
225
221
  if let Some(ctx) = params.context {
226
- if matches!(
227
- ctx.trigger_kind,
228
- CompletionTriggerKind::TRIGGER_CHARACTER
229
- ) && ctx.trigger_character.as_deref() == Some(".")
222
+ if matches!(ctx.trigger_kind, CompletionTriggerKind::TRIGGER_CHARACTER)
223
+ && ctx.trigger_character.as_deref() == Some(".")
230
224
  {
231
225
  // After dot: could add member completion later
232
226
  }
@@ -294,16 +288,15 @@ impl LanguageServer for Backend {
294
288
  if let Some(ref base) = path {
295
289
  for s in &program.statements {
296
290
  if let tishlang_ast::Statement::Import {
297
- specifiers,
298
- from,
299
- ..
291
+ specifiers, from, ..
300
292
  } = s
301
293
  {
302
294
  for sp in specifiers {
303
295
  let (imported, local) = match sp {
304
- tishlang_ast::ImportSpecifier::Named { name, alias } => {
305
- (name.as_ref(), alias.as_ref().map(|a| a.as_ref()).unwrap_or(name.as_ref()))
306
- }
296
+ tishlang_ast::ImportSpecifier::Named { name, alias } => (
297
+ name.as_ref(),
298
+ alias.as_ref().map(|a| a.as_ref()).unwrap_or(name.as_ref()),
299
+ ),
307
300
  tishlang_ast::ImportSpecifier::Default(n) => (n.as_ref(), n.as_ref()),
308
301
  _ => continue,
309
302
  };
@@ -325,9 +318,7 @@ impl LanguageServer for Backend {
325
318
  if let Ok(u) = Url::from_file_path(&can) {
326
319
  if let Ok(src) = std::fs::read_to_string(&can) {
327
320
  if let Ok(prog) = tishlang_parser::parse(&src) {
328
- if let Some(loc) =
329
- find_export(&prog, imported, &u, &src)
330
- {
321
+ if let Some(loc) = find_export(&prog, imported, &u, &src) {
331
322
  return Ok(Some(GotoDefinitionResponse::Scalar(loc)));
332
323
  }
333
324
  }
@@ -342,7 +333,10 @@ impl LanguageServer for Backend {
342
333
  Ok(None)
343
334
  }
344
335
 
345
- async fn formatting(&self, params: DocumentFormattingParams) -> Result<Option<Vec<tower_lsp::lsp_types::TextEdit>>> {
336
+ async fn formatting(
337
+ &self,
338
+ params: DocumentFormattingParams,
339
+ ) -> Result<Option<Vec<tower_lsp::lsp_types::TextEdit>>> {
346
340
  let uri = params.text_document.uri;
347
341
  let text = {
348
342
  let g = self.docs.read().unwrap();
@@ -365,10 +359,7 @@ impl LanguageServer for Backend {
365
359
  }
366
360
  Err(e) => {
367
361
  self.client
368
- .show_message(
369
- MessageType::ERROR,
370
- format!("tish-fmt (formatter): {}", e),
371
- )
362
+ .show_message(MessageType::ERROR, format!("tish-fmt (formatter): {}", e))
372
363
  .await;
373
364
  Ok(None)
374
365
  }
@@ -499,14 +490,18 @@ fn find_decl_in_stmt(
499
490
  text: &str,
500
491
  ) -> Option<Location> {
501
492
  match s {
502
- tishlang_ast::Statement::FunDecl { name, span, .. } if name.as_ref() == word => Some(Location {
503
- uri: uri.clone(),
504
- range: span_to_range(span, text),
505
- }),
506
- tishlang_ast::Statement::VarDecl { name, span, .. } if name.as_ref() == word => Some(Location {
507
- uri: uri.clone(),
508
- range: span_to_range(span, text),
509
- }),
493
+ tishlang_ast::Statement::FunDecl { name, span, .. } if name.as_ref() == word => {
494
+ Some(Location {
495
+ uri: uri.clone(),
496
+ range: span_to_range(span, text),
497
+ })
498
+ }
499
+ tishlang_ast::Statement::VarDecl { name, span, .. } if name.as_ref() == word => {
500
+ Some(Location {
501
+ uri: uri.clone(),
502
+ range: span_to_range(span, text),
503
+ })
504
+ }
510
505
  tishlang_ast::Statement::Block { statements, .. } => {
511
506
  for x in statements {
512
507
  if let Some(l) = find_decl_in_stmt(x, word, uri, text) {
@@ -521,8 +516,14 @@ fn find_decl_in_stmt(
521
516
 
522
517
  fn span_to_range(span: &tishlang_ast::Span, _text: &str) -> Range {
523
518
  Range {
524
- start: pos(span.start.0.saturating_sub(1) as u32, span.start.1.saturating_sub(1) as u32),
525
- end: pos(span.end.0.saturating_sub(1) as u32, span.end.1.saturating_sub(1) as u32),
519
+ start: pos(
520
+ span.start.0.saturating_sub(1) as u32,
521
+ span.start.1.saturating_sub(1) as u32,
522
+ ),
523
+ end: pos(
524
+ span.end.0.saturating_sub(1) as u32,
525
+ span.end.1.saturating_sub(1) as u32,
526
+ ),
526
527
  }
527
528
  }
528
529
 
@@ -556,10 +557,7 @@ fn doc_symbol_stmt(
556
557
  ) {
557
558
  match s {
558
559
  tishlang_ast::Statement::FunDecl {
559
- name,
560
- span,
561
- body,
562
- ..
560
+ name, span, body, ..
563
561
  } => {
564
562
  let mut children = Vec::new();
565
563
  collect_child_syms(body, text, &mut children);
@@ -127,11 +127,7 @@ lto = "thin"
127
127
  [dependencies]
128
128
  tishlang_runtime = {{ path = {:?}{} }}
129
129
  {}{}"#,
130
- out_name,
131
- runtime_path,
132
- features_str,
133
- more_deps,
134
- ui_dep
130
+ out_name, runtime_path, features_str, more_deps, ui_dep
135
131
  );
136
132
 
137
133
  fs::write(build_dir.join("Cargo.toml"), cargo_toml)
@@ -182,4 +178,3 @@ mod tests {
182
178
  assert_eq!(f.len(), 5);
183
179
  }
184
180
  }
185
-