@xnoxs/flux-lang 3.4.0 → 3.4.1

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.
package/src/self/cli.flux CHANGED
@@ -588,54 +588,153 @@ fn cmdInit(name, opts):
588
588
  Fs.mkdirSync(Path.join(dir, "src"), { recursive: true })
589
589
  Fs.mkdirSync(Path.join(dir, "tests"), { recursive: true })
590
590
 
591
- val mainFlux = `// {projectName} — written in Flux Lang v{VERSION}
591
+ val mainFlux = `// {projectName} — built with Flux Lang v{VERSION}
592
+ // Run: flux run src/main.flux
592
593
 
593
- type Shape =
594
- | Circle(radius: Float)
595
- | Rect(width: Float, height: Float)
596
- | Triangle(base: Float, height: Float)
594
+ // ── Algebraic Data Types + Pattern Matching ───────────────────
595
+ type Shape = Circle(radius) | Rect(width, height) | Triangle(base, height)
597
596
 
598
- fn area(shape: Shape) -> Float:
597
+ fn area(shape):
599
598
  match shape:
600
- when Circle(r): return Math.PI * r * r
601
- when Rect(w, h): return w * h
602
- when Triangle(b, h): return 0.5 * b * h
599
+ when Circle(r): return Math.PI * r * r
600
+ when Rect(w, h): return w * h
601
+ when Triangle(b, h): return 0.5 * b * h
603
602
 
604
- fn greet(name: String) -> String:
605
- return "Hello from Flux, {name}!"
603
+ fn describe(shape):
604
+ match shape:
605
+ when Circle(r): return "Circle(r={r:.2f})"
606
+ when Rect(w, h): return "Rect({w:.1f}x{h:.1f})"
607
+ when Triangle(b, h): return "Triangle(b={b:.1f}, h={h:.1f})"
608
+
609
+ // ── Result type ───────────────────────────────────────────────
610
+ type Result = Ok(value) | Err(message)
611
+
612
+ fn safeDivide(a, b):
613
+ if b == 0: return Err("division by zero")
614
+ return Ok(a / b)
615
+
616
+ // ── Utility functions ─────────────────────────────────────────
617
+ fn greet(name): return "Hello from Flux, {name}!"
618
+
619
+ fn formatList(items):
620
+ if items.length == 0: return "(empty)"
621
+ return "[" + items.join(", ") + "]"
606
622
 
607
- val shapes = [
608
- Circle(5.0),
609
- Rect(10.0, 4.0),
610
- Triangle(6.0, 8.0),
611
- ]
623
+ fn clamp(value, lo, hi):
624
+ if value < lo: return lo
625
+ if value > hi: return hi
626
+ return value
612
627
 
628
+ // ── Pipe operator + stdlib ────────────────────────────────────
629
+ val numbers = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5]
630
+ val processed = numbers
631
+ |> filter(n -> n > 3)
632
+ |> map(n -> n * n)
633
+ |> sort
634
+
635
+ // ── Main ──────────────────────────────────────────────────────
636
+ print(greet("{projectName}"))
637
+ print("Squares > 3: {formatList(processed)}")
638
+ print("clamp(12, 0, 10) = {clamp(12, 0, 10)}")
639
+
640
+ val shapes = [Circle(5.0), Rect(8.0, 3.0), Triangle(6.0, 4.0)]
613
641
  for shape in shapes:
614
642
  val a = area(shape)
615
- print("Area: {a:.2f}")
643
+ print("{describe(shape)} area={a:.2f}")
616
644
 
617
- print(greet("{projectName}"))
645
+ match safeDivide(10.0, 3.0):
646
+ when Ok(v): print("10 / 3 = {v:.4f}")
647
+ when Err(e): print("Error: {e}")
618
648
  `
619
649
 
620
- val testFlux = `// {projectName} tests
650
+ val utilsFlux = `// Utility functions for {projectName}
651
+ // Use with: flux bundle src/main.flux (bundles imports automatically)
652
+
653
+ export fn greet(name):
654
+ return "Hello from Flux, {name}!"
621
655
 
622
- fn add(a: Int, b: Int) -> Int: return a + b
623
- fn mul(a: Int, b: Int) -> Int: return a * b
656
+ export fn formatList(items):
657
+ if items.length == 0: return "(empty)"
658
+ return "[" + items.join(", ") + "]"
624
659
 
625
- test "add works":
626
- assert add(1, 2) == 3
627
- assert add(0, 0) == 0
628
- assert add(-1, 1) == 0
660
+ export fn clamp(value, lo, hi):
661
+ if value < lo: return lo
662
+ if value > hi: return hi
663
+ return value
629
664
 
630
- test "mul works":
631
- assert mul(3, 4) == 12
632
- assert mul(0, 5) == 0
665
+ export fn sum(nums):
666
+ return nums.reduce((acc, x) -> acc + x, 0)
667
+
668
+ export fn average(nums):
669
+ if nums.length == 0: return 0
670
+ return sum(nums) / nums.length
671
+ `
672
+
673
+ val testFlux = `// Tests for {projectName}
674
+ // Run: flux test tests/
675
+
676
+ // ── Functions under test ──────────────────────────────────────
677
+ fn add(a, b):
678
+ return a + b
679
+
680
+ fn mul(a, b):
681
+ return a * b
682
+
683
+ fn clamp(value, lo, hi):
684
+ if value < lo: return lo
685
+ if value > hi: return hi
686
+ return value
687
+
688
+ fn average(nums):
689
+ if nums.length == 0: return 0
690
+ return nums.reduce((s, x) -> s + x, 0) / nums.length
691
+
692
+ type Result = Ok(value) | Err(message)
693
+
694
+ fn safeDivide(a, b):
695
+ if b == 0: return Err("div by zero")
696
+ return Ok(a / b)
697
+
698
+ // ── Test functions ────────────────────────────────────────────
699
+ fn test_add():
700
+ assert(add(1, 2) == 3, "1+2=3")
701
+ assert(add(0, 0) == 0, "0+0=0")
702
+ assert(add(-1, 1) == 0, "-1+1=0")
703
+
704
+ fn test_mul():
705
+ assert(mul(3, 4) == 12, "3*4=12")
706
+ assert(mul(0, 5) == 0, "0*5=0")
707
+
708
+ fn test_clamp():
709
+ assert(clamp(5, 0, 10) == 5, "within range")
710
+ assert(clamp(-1, 0, 10) == 0, "below min")
711
+ assert(clamp(15, 0, 10) == 10, "above max")
712
+
713
+ fn test_average():
714
+ assert(average([2, 4, 6]) == 4, "average of 2,4,6")
715
+ assert(average([]) == 0, "empty list")
716
+
717
+ fn test_safe_divide():
718
+ val ok = safeDivide(10, 2)
719
+ match ok:
720
+ when Ok(v): assert(v == 5, "10/2=5")
721
+ when Err(e): assert(false, "unexpected error")
722
+ val err = safeDivide(10, 0)
723
+ match err:
724
+ when Ok(v): assert(false, "expected error")
725
+ when Err(e): assert(e == "div by zero", "error message")
726
+
727
+ fn test_pipe_operator():
728
+ val result = [1, 2, 3, 4, 5] |> filter(n -> n > 2) |> map(n -> n * 2)
729
+ assert(result.length == 3, "filter length")
730
+ assert(result[0] == 6, "first element")
731
+ assert(result[2] == 10, "last element")
633
732
  `
634
733
 
635
734
  val fluxJson = {
636
735
  name: projectName,
637
736
  version: "1.0.0",
638
- description: "A Flux Lang project",
737
+ description: "A Flux Lang v" + VERSION + " project",
639
738
  author: "",
640
739
  license: "MIT",
641
740
  entry: "src/main.flux",
@@ -652,40 +751,60 @@ test "mul works":
652
751
  lint: "flux lint src/",
653
752
  },
654
753
  dependencies: {},
655
- devDependencies: {},
754
+ devDependencies: { "@xnoxs/flux-lang": "^" + VERSION },
656
755
  }
657
756
 
658
- val gitignore = `node_modules/
659
- dist/
660
- flux_modules/
661
- *.js.map
662
- .DS_Store
663
- `
757
+ val gitignore = "node_modules/\ndist/\nflux_modules/\n*.js.map\n.DS_Store\n"
664
758
 
665
759
  val readme = `# {projectName}
666
760
 
667
- A project built with [Flux Lang](https://flux-lang.dev) v{VERSION}.
761
+ A project built with [Flux Lang](https://flux-lang.dev) v{VERSION} — the self-hosted compiler.
668
762
 
669
- ## Getting Started
763
+ ## Quick Start
670
764
 
671
765
  \`\`\`bash
672
766
  flux run src/main.flux
673
767
  \`\`\`
674
768
 
769
+ ## Project Structure
770
+
771
+ \`\`\`
772
+ {projectName}/
773
+ ├── src/
774
+ │ ├── main.flux # Entry point
775
+ │ └── utils.flux # Utility functions
776
+ ├── tests/
777
+ │ └── main.test.flux # Test suite
778
+ ├── flux.json # Project config
779
+ └── README.md
780
+ \`\`\`
781
+
675
782
  ## Commands
676
783
 
677
784
  | Command | Description |
678
785
  |---|---|
679
- | \`flux run src/main.flux\` | Run main file |
680
- | \`flux build\` | Bundle to dist/ |
786
+ | \`flux run src/main.flux\` | Run the project |
787
+ | \`flux bundle src/main.flux -o dist/bundle.js\` | Bundle to single file |
681
788
  | \`flux watch src/main.flux\` | Watch mode |
682
- | \`flux check src/main.flux\` | Type check |
683
- | \`flux test tests/\` | Run tests |
684
- | \`flux fmt src/\` | Format code |
789
+ | \`flux check src/main.flux\` | Type check + static analysis |
790
+ | \`flux test tests/\` | Run all tests |
791
+ | \`flux fmt src/\` | Format source code |
792
+ | \`flux lint src/\` | Lint for issues |
793
+ | \`flux add <package>\` | Add a dependency |
685
794
  `
686
795
 
687
- Fs.writeFileSync(Path.join(dir, "src", "main.flux"), mainFlux, "utf8")
688
- Fs.writeFileSync(Path.join(dir, "tests", "main.test.flux"), testFlux, "utf8")
796
+ val allFiles = [
797
+ projectName + "/src/main.flux",
798
+ projectName + "/src/utils.flux",
799
+ projectName + "/tests/main.test.flux",
800
+ projectName + "/flux.json",
801
+ projectName + "/.gitignore",
802
+ projectName + "/README.md",
803
+ ]
804
+
805
+ Fs.writeFileSync(Path.join(dir, "src", "main.flux"), mainFlux, "utf8")
806
+ Fs.writeFileSync(Path.join(dir, "src", "utils.flux"), utilsFlux, "utf8")
807
+ Fs.writeFileSync(Path.join(dir, "tests", "main.test.flux"), testFlux, "utf8")
689
808
  Fs.writeFileSync(Path.join(dir, "flux.json"), JSON.stringify(fluxJson, null, 2) + "\n", "utf8")
690
809
  Fs.writeFileSync(Path.join(dir, ".gitignore"), gitignore, "utf8")
691
810
  Fs.writeFileSync(Path.join(dir, "README.md"), readme, "utf8")
@@ -694,16 +813,16 @@ flux run src/main.flux
694
813
  console.log(green("✓ Created: ") + bold(projectName + "/"))
695
814
  console.log()
696
815
  console.log(gray(" Files:"))
697
- console.log(" " + cyan(projectName + "/src/main.flux"))
698
- console.log(" " + cyan(projectName + "/tests/main.test.flux"))
699
- console.log(" " + cyan(projectName + "/flux.json"))
700
- console.log(" " + cyan(projectName + "/.gitignore"))
701
- console.log(" " + cyan(projectName + "/README.md"))
816
+ for f in allFiles:
817
+ console.log(" " + cyan(f))
702
818
  console.log()
703
819
  console.log(bold(" Next steps:"))
704
820
  console.log(" " + yellow("cd " + projectName))
705
821
  console.log(" " + yellow("flux run src/main.flux"))
706
822
  console.log()
823
+ console.log(gray(" Or run the test suite:"))
824
+ console.log(" " + yellow("flux test tests/"))
825
+ console.log()
707
826
 
708
827
  // ── flux self-hosted ──────────────────────────────────────────
709
828
  fn cmdSelfHosted(sub, opts):