feat: lifetime elision, tooling CI, registry, and LSP locals
Ship the QUALITY_PLAN stretch from ownership through ecosystem: C.1 lifetime elision (bootstrap + selfhost), bux fmt/test/doc CI hooks, stdlib goldens, package registry (bux search/add), and LSP 0.4 position-sensitive locals with inferred let types. Full-tree format pass plus Map/Set remove double-free fix.
This commit is contained in:
@@ -10,20 +10,20 @@ enum Result {
|
||||
func Main() -> int {
|
||||
let r1: Result = Result { tag: Result_Ok };
|
||||
r1.data.Ok_0 = 42;
|
||||
|
||||
|
||||
let r2: Result = Result { tag: Result_Err };
|
||||
r2.data.Err_0 = "error message";
|
||||
|
||||
|
||||
if r1.tag == Result_Ok {
|
||||
PrintLine("r1 is Ok:");
|
||||
PrintInt(r1.data.Ok_0);
|
||||
PrintLine("");
|
||||
}
|
||||
|
||||
|
||||
if r2.tag == Result_Err {
|
||||
PrintLine("r2 is Err:");
|
||||
PrintLine(r2.data.Err_0);
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
// borrow.bux — Test explicit borrow expressions
|
||||
|
||||
struct Point {
|
||||
x: int;
|
||||
y: int;
|
||||
x: int;
|
||||
y: int;
|
||||
}
|
||||
|
||||
// NOT @[Checked] — borrow keyword available everywhere
|
||||
|
||||
+2
-2
@@ -23,12 +23,12 @@ func ColorName(c: Color) -> String {
|
||||
|
||||
func Main() -> int {
|
||||
let myColor: Color = Color::Green;
|
||||
|
||||
|
||||
PrintLine("My color is:");
|
||||
PrintLine(ColorName(myColor));
|
||||
PrintLine("Color value:");
|
||||
PrintInt(myColor as int);
|
||||
PrintLine("");
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -27,4 +27,4 @@ func Main() -> int {
|
||||
PrintLine("");
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,13 +11,13 @@ func Factorial(n: int) -> int {
|
||||
|
||||
func Main() -> int {
|
||||
PrintLine("Factorials:");
|
||||
|
||||
|
||||
var i: int = 1;
|
||||
while i <= 10 {
|
||||
let fact: int = Factorial(i);
|
||||
PrintLine(Fmt_Fmt2("{0}! = {1}", String_FromInt(i), String_FromInt(fact)));
|
||||
i = i + 1;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -11,13 +11,13 @@ func Fibonacci(n: int) -> int {
|
||||
|
||||
func Main() -> int {
|
||||
PrintLine("Fibonacci sequence:");
|
||||
|
||||
|
||||
var i: int = 0;
|
||||
while i < 10 {
|
||||
let fib: int = Fibonacci(i);
|
||||
PrintLine(Fmt_Fmt1("{0}", String_FromInt(fib)));
|
||||
i = i + 1;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -13,14 +13,14 @@ func Main() -> int {
|
||||
// Inferred: T = int
|
||||
let m1: int = Max(10, 20);
|
||||
let m2: int = Max(5, 3);
|
||||
|
||||
|
||||
PrintLine("Max(10, 20) = ");
|
||||
PrintInt(m1);
|
||||
PrintLine("");
|
||||
|
||||
|
||||
PrintLine("Max(5, 3) = ");
|
||||
PrintInt(m2);
|
||||
PrintLine("");
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,4 +20,4 @@ func Main() -> int {
|
||||
PrintInt(p.GetFirst());
|
||||
PrintLine("");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,14 +13,14 @@ func Max<T>(a: T, b: T) -> T {
|
||||
func Main() -> int {
|
||||
let m1: int = Max<int>(10, 20);
|
||||
let m2: int = Max<int>(5, 3);
|
||||
|
||||
|
||||
PrintLine("Max(10, 20) = ");
|
||||
PrintInt(m1);
|
||||
PrintLine("");
|
||||
|
||||
|
||||
PrintLine("Max(5, 3) = ");
|
||||
PrintInt(m2);
|
||||
PrintLine("");
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -31,21 +31,21 @@ func Main() -> int {
|
||||
PrintLine("Box value:");
|
||||
PrintInt(b.Get());
|
||||
PrintLine("");
|
||||
|
||||
|
||||
b.Set(100);
|
||||
PrintLine("Box after Set(100):");
|
||||
PrintInt(b.Get());
|
||||
PrintLine("");
|
||||
|
||||
|
||||
let p: Pair<int, String> = Pair<int, String> { first: 10, second: "hello" };
|
||||
PrintLine("Pair first:");
|
||||
PrintInt(p.GetFirst());
|
||||
PrintLine("");
|
||||
|
||||
|
||||
let bp: *Box<int> = &b;
|
||||
PrintLine("Box via pointer:");
|
||||
PrintInt(bp.Get());
|
||||
PrintLine("");
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
+5
-5
@@ -5,20 +5,20 @@ import Std::Fmt::{Fmt_Fmt1, Fmt_FmtInt};
|
||||
|
||||
func Main() -> int {
|
||||
PrintLine("=== Json Demo ===");
|
||||
|
||||
|
||||
let s: String = "{\"name\":\"Bux\",\"count\":42,\"items\":[\"a\",\"b\",\"c\"]}";
|
||||
let j: JsonValue = Json_Parse(s);
|
||||
PrintLine("Parsed and stringified:");
|
||||
PrintLine(Json_Stringify(j));
|
||||
|
||||
|
||||
PrintLine("\nAccess fields:");
|
||||
PrintLine(Fmt_Fmt1("name = {0}", Json_AsString(Json_ObjectGet(j, "name"))));
|
||||
PrintLine(Fmt_FmtInt("count = {0}", Json_AsNumber(Json_ObjectGet(j, "count")) as int64));
|
||||
|
||||
|
||||
let items: JsonValue = Json_ObjectGet(j, "items");
|
||||
PrintLine(Fmt_Fmt1("items[0] = {0}", Json_AsString(Json_ArrayGet(items, 0))));
|
||||
PrintLine(Fmt_Fmt1("items[1] = {0}", Json_AsString(Json_ArrayGet(items, 1))));
|
||||
|
||||
|
||||
PrintLine("\nBuild JSON programmatically:");
|
||||
var obj: JsonValue = Json_Object();
|
||||
Json_ObjectSet(&obj, "lang", Json_String("Bux"));
|
||||
@@ -28,6 +28,6 @@ func Main() -> int {
|
||||
Json_ArrayPush(&arr, Json_String("safe"));
|
||||
Json_ObjectSet(&obj, "tags", arr);
|
||||
PrintLine(Json_Stringify(obj));
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
+7
-7
@@ -29,30 +29,30 @@ func Jwt_Create(payload: JsonValue, secret: String) -> String {
|
||||
let header: JsonValue = Json_Object();
|
||||
Json_ObjectSet(&header, "alg", Json_String("HS256"));
|
||||
Json_ObjectSet(&header, "typ", Json_String("JWT"));
|
||||
|
||||
|
||||
let headerB64: String = Base64UrlEncode(Json_Stringify(header));
|
||||
let payloadB64: String = Base64UrlEncode(Json_Stringify(payload));
|
||||
|
||||
|
||||
let signingInput: String = String_Concat(headerB64, ".");
|
||||
signingInput = String_Concat(signingInput, payloadB64);
|
||||
|
||||
|
||||
let sigRaw: String = Crypto_HmacSha256Raw(secret, signingInput);
|
||||
let sigB64: String = Base64UrlEncodeSig(sigRaw);
|
||||
|
||||
|
||||
return String_Concat(String_Concat(signingInput, "."), sigB64);
|
||||
}
|
||||
|
||||
func Main() -> int {
|
||||
PrintLine("=== JWT Demo ===");
|
||||
|
||||
|
||||
let payload: JsonValue = Json_Object();
|
||||
Json_ObjectSet(&payload, "sub", Json_String("user123"));
|
||||
Json_ObjectSet(&payload, "name", Json_String("Bux Developer"));
|
||||
Json_ObjectSet(&payload, "admin", Json_Bool(true));
|
||||
|
||||
|
||||
let token: String = Jwt_Create(payload, "my-secret-key");
|
||||
PrintLine("Token:");
|
||||
PrintLine(token);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
// lifetime_elision.bux — C.1: elided lifetimes for common &[Checked] APIs
|
||||
// No 'a annotations needed when there is a single input reference.
|
||||
import Std::Io::{PrintLine, PrintInt};
|
||||
import Std::Test::{Test_AssertEqInt, Test_Pass};
|
||||
|
||||
// Elided: param and return share one lifetime automatically
|
||||
@[Checked]
|
||||
func Identity(p: &int) -> &int {
|
||||
return p;
|
||||
}
|
||||
|
||||
// Explicit lifetime for documentation / multi-ref (same lifetime both sides)
|
||||
@[Checked]
|
||||
func IdentityNamed<'a>(p: &'a int) -> &'a int {
|
||||
return p;
|
||||
}
|
||||
|
||||
// Via intermediate let binding — lifetime is propagated
|
||||
@[Checked]
|
||||
func ViaLet(p: &int) -> &int {
|
||||
let r: &int = p;
|
||||
return r;
|
||||
}
|
||||
|
||||
// self-style first param: elision prefers the first input for the return
|
||||
@[Checked]
|
||||
func FirstOf(self: &int, _other: int) -> &int {
|
||||
return self;
|
||||
}
|
||||
|
||||
@[Checked]
|
||||
func Main() -> int {
|
||||
var x: int = 10;
|
||||
var y: int = 20;
|
||||
|
||||
let a: &int = Identity(&x);
|
||||
Test_AssertEqInt(*a, 10);
|
||||
|
||||
let b: &int = IdentityNamed(&y);
|
||||
Test_AssertEqInt(*b, 20);
|
||||
|
||||
let c: &int = ViaLet(&x);
|
||||
Test_AssertEqInt(*c, 10);
|
||||
|
||||
let d: &int = FirstOf(&y, 0);
|
||||
Test_AssertEqInt(*d, 20);
|
||||
|
||||
Test_Pass("lifetime_elision");
|
||||
PrintLine("lifetime_elision: ok");
|
||||
return 0;
|
||||
}
|
||||
+7
-7
@@ -5,26 +5,26 @@ import Std::Map::{Map, Map_New, Map_Set, Map_Get, Map_Has, Map_Free};
|
||||
func Main() -> int {
|
||||
PrintLine("=== Map<int, String> ===");
|
||||
let m: Map<int, String> = Map_New<int, String>(16);
|
||||
|
||||
|
||||
Map_Set<int, String>(&m, 1, "one");
|
||||
Map_Set<int, String>(&m, 2, "two");
|
||||
Map_Set<int, String>(&m, 3, "three");
|
||||
|
||||
|
||||
PrintLine("Get 1:");
|
||||
PrintLine(Map_Get<int, String>(&m, 1));
|
||||
|
||||
|
||||
PrintLine("Get 2:");
|
||||
PrintLine(Map_Get<int, String>(&m, 2));
|
||||
|
||||
|
||||
if Map_Has<int, String>(&m, 1) {
|
||||
PrintLine("Has 1: yes");
|
||||
}
|
||||
|
||||
|
||||
// Test update
|
||||
Map_Set<int, String>(&m, 2, "updated");
|
||||
PrintLine("Updated 2:");
|
||||
PrintLine(Map_Get<int, String>(&m, 2));
|
||||
|
||||
|
||||
Map_Free<int, String>(&m);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ extend Rectangle {
|
||||
func Area(self: Rectangle) -> int {
|
||||
return self.width * self.height;
|
||||
}
|
||||
|
||||
|
||||
func Perimeter(self: Rectangle) -> int {
|
||||
return 2 * (self.width + self.height);
|
||||
}
|
||||
@@ -19,7 +19,7 @@ extend Rectangle {
|
||||
|
||||
func Main() -> int {
|
||||
let rect: Rectangle = Rectangle { width: 10, height: 5 };
|
||||
|
||||
|
||||
PrintLine("Rectangle:");
|
||||
PrintLine("Width = ");
|
||||
PrintInt(rect.width);
|
||||
@@ -33,6 +33,6 @@ func Main() -> int {
|
||||
PrintLine("Perimeter = ");
|
||||
PrintInt(rect.Perimeter());
|
||||
PrintLine("");
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -9,16 +9,16 @@ func Main() -> int {
|
||||
PrintLine(Fmt_Fmt1("Current directory: {0}", Os_GetCwd()));
|
||||
PrintLine(Fmt_FmtInt("Command-line args: {0}", Os_ArgsCount() as int64));
|
||||
PrintLine(Fmt_Fmt1("HOME env: {0}", Os_GetEnv("HOME")));
|
||||
|
||||
|
||||
PrintLine("\n=== Time Demo ===");
|
||||
let start: int64 = Time_NowMs();
|
||||
PrintLine(Fmt_FmtInt("Start: {0} ms", start));
|
||||
PrintLine("Sleeping 150ms...");
|
||||
Time_SleepMs(150);
|
||||
|
||||
|
||||
let end: int64 = Time_NowMs();
|
||||
PrintLine(Fmt_FmtInt("End: {0} ms", end));
|
||||
PrintLine(Fmt_FmtInt("Elapsed: {0} ms", end - start));
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -23,17 +23,17 @@ func UncheckedSwap(a: *int, b: *int) {
|
||||
|
||||
func Main() -> int {
|
||||
var x: int = 10;
|
||||
|
||||
|
||||
// &mut allows mutation
|
||||
ScaleInPlace(&x, 3);
|
||||
PrintInt(x); // 30
|
||||
PrintLine("");
|
||||
|
||||
|
||||
// & allows reading
|
||||
let y: int = GetValue(&x);
|
||||
PrintInt(y); // 30
|
||||
PrintLine("");
|
||||
|
||||
|
||||
// Unchecked: raw pointers work like C
|
||||
var a: int = 5;
|
||||
var b: int = 7;
|
||||
@@ -42,6 +42,6 @@ func Main() -> int {
|
||||
PrintLine("");
|
||||
PrintInt(b); // 5
|
||||
PrintLine("");
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -5,12 +5,12 @@ import Std::Fmt::{Fmt_Fmt1, Fmt_FmtInt};
|
||||
|
||||
func Main() -> int {
|
||||
PrintLine("Process demo:");
|
||||
|
||||
|
||||
let output: String = Process_Output("echo Hello from subprocess");
|
||||
PrintLine(Fmt_Fmt1("Captured: {0}", output));
|
||||
|
||||
|
||||
let rc: int = Process_Run("true");
|
||||
PrintLine(Fmt_FmtInt("Exit code: {0}", rc));
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -82,14 +82,14 @@ func SafeDivide(a: int, b: int) -> Option {
|
||||
|
||||
func Main() -> int {
|
||||
PrintLine("Result demo:");
|
||||
|
||||
|
||||
let r1: Result = Divide(10, 2);
|
||||
if Result_IsOk(r1) {
|
||||
PrintLine("10 / 2 = ");
|
||||
PrintInt(Result_Unwrap(r1));
|
||||
PrintLine("");
|
||||
}
|
||||
|
||||
|
||||
let r2: Result = Divide(10, 0);
|
||||
if Result_IsErr(r2) {
|
||||
PrintLine("10 / 0 failed");
|
||||
@@ -97,20 +97,20 @@ func Main() -> int {
|
||||
PrintLine("unwrap_or = ");
|
||||
PrintInt(Result_UnwrapOr(r2, -1));
|
||||
PrintLine("");
|
||||
|
||||
|
||||
PrintLine("Option demo:");
|
||||
|
||||
|
||||
let o1: Option = SafeDivide(20, 4);
|
||||
if Option_IsSome(o1) {
|
||||
PrintLine("20 / 4 = ");
|
||||
PrintInt(Option_UnwrapOr(o1, 0));
|
||||
PrintLine("");
|
||||
}
|
||||
|
||||
|
||||
let o2: Option = SafeDivide(20, 0);
|
||||
PrintLine("20 / 0 fallback = ");
|
||||
PrintInt(Option_UnwrapOr(o2, -1));
|
||||
PrintLine("");
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -5,30 +5,30 @@ import Std::String::{String_Len, String_Eq, String_Concat};
|
||||
func Main() -> int {
|
||||
let hello: String = "Hello";
|
||||
let world: String = "World";
|
||||
|
||||
|
||||
PrintLine("String operations:");
|
||||
|
||||
|
||||
// Length
|
||||
PrintLine("Length of 'Hello':");
|
||||
PrintInt(String_Len(hello));
|
||||
PrintLine("");
|
||||
|
||||
|
||||
// Concatenation
|
||||
let greeting: String = String_Concat(hello, ", ");
|
||||
let greeting2: String = String_Concat(greeting, world);
|
||||
let full: String = String_Concat(greeting2, "!");
|
||||
|
||||
|
||||
PrintLine("Concatenated:");
|
||||
PrintLine(full);
|
||||
|
||||
|
||||
// Equality
|
||||
if String_Eq(hello, "Hello") {
|
||||
PrintLine("'Hello' equals 'Hello'");
|
||||
}
|
||||
|
||||
|
||||
if !String_Eq(hello, world) {
|
||||
PrintLine("'Hello' does not equal 'World'");
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -65,10 +65,10 @@ func Main() -> int {
|
||||
StringBuilder_Append(&sb, "World");
|
||||
StringBuilder_Append(&sb, "! #");
|
||||
StringBuilder_AppendInt(&sb, 42);
|
||||
|
||||
|
||||
Print("StringBuilder: ");
|
||||
PrintLine(StringBuilder_Build(&sb));
|
||||
StringBuilder_Free(&sb);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ func Main() -> int {
|
||||
let p1: Point = Point { x: 10, y: 20 };
|
||||
let p2: Point = Point { x: 5, y: 15 };
|
||||
let sum: Point = AddPoints(p1, p2);
|
||||
|
||||
|
||||
PrintLine("Point sum:");
|
||||
PrintLine("x = ");
|
||||
PrintInt(sum.x);
|
||||
@@ -24,6 +24,6 @@ func Main() -> int {
|
||||
PrintLine("y = ");
|
||||
PrintInt(sum.y);
|
||||
PrintLine("");
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ func ComputeWithError() -> Result {
|
||||
|
||||
func Main() -> int {
|
||||
PrintLine("Try operator demo:");
|
||||
|
||||
|
||||
let r1: Result = Compute();
|
||||
if r1.tag == Result_Ok {
|
||||
PrintLine("Compute() = ");
|
||||
@@ -48,11 +48,11 @@ func Main() -> int {
|
||||
} else {
|
||||
PrintLine("Compute() failed");
|
||||
}
|
||||
|
||||
|
||||
let r2: Result = ComputeWithError();
|
||||
if r2.tag == Result_Err {
|
||||
PrintLine("ComputeWithError() failed as expected");
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user