Commits

KS Sreeram  committed a037beb

test/lua: add test program which creates a custom type with both properties and methods.

  • Participants
  • Parent commits f058513

Comments (0)

Files changed (3)

File test/lua/highlevel/customtype5/buildflags.txt

+-L/opt/local/lib -llua

File test/lua/highlevel/customtype5/main.clay

+import lua;
+
+record Point (
+    x:Double,
+    y:Double,
+);
+
+pointFieldRef(p:Point, i) {
+    if (i == 0) {
+        return ref p.x;
+    }
+    else if (i == 1) {
+        return ref p.y;
+    }
+    else {
+        assert(false, "invalid field index", i);
+        return ref null(Double)^;
+    }
+}
+
+Point_new(s:lua.State) {
+    var x = lua.checkNumber(s, 1);
+    var y = lua.checkNumber(s, 2);
+    var data = lua.newUserData(s, TypeSize(Point));
+    Pointer[Point](data)^ = Point(x, y);
+    lua.lookupMetaTable(s, "Point");
+    lua.setMetaTable(s, -2);
+    return 1;
+}
+
+checkPoint(s:lua.State, index:Int) {
+    var data = lua.checkUserData(s, index, "Point");
+    return ref Pointer[Point](data)^;
+}
+
+Point_index(s:lua.State) {
+    lua.lookupMetaTable(s, "PointFields");
+    lua.pushValue(s, 2);
+    lua.rawGet(s, -2);
+    if (lua.number?(s, -1)) {
+        var fieldIndex = lua.toInteger(s, -1);
+        ref p = checkPoint(s, 1);
+        var result = pointFieldRef(p, fieldIndex);
+        lua.pushNumber(s, result);
+        return 1;
+    }
+    else if (lua.function?(s, -1)) {
+        return 1;
+    }
+    else {
+        throw lua.Error("Point: invalid field: ", lua.toString(s, 2));
+    }
+}
+
+Point_newIndex(s:lua.State) {
+    lua.lookupMetaTable(s, "PointFields");
+    lua.pushValue(s, 2);
+    lua.rawGet(s, -2);
+    if (not lua.number?(s, -1))
+        throw lua.Error("Point: can't assign to field: ", lua.toString(s, 2));
+    var fieldIndex = lua.toInteger(s, -1);
+    var newValue = lua.toNumber(s, 3);
+    ref p = checkPoint(s, 1);
+    pointFieldRef(p, fieldIndex) = newValue;
+    return 0;
+}
+
+Point_xyValues(s:lua.State) {
+    ref p = checkPoint(s, 1);
+    lua.pushNumber(s, p.x);
+    lua.pushNumber(s, p.y);
+    return 2;
+}
+
+Point_xyArray(s:lua.State) {
+    ref p = checkPoint(s, 1);
+    lua.newTable(s);
+    lua.pushNumber(s, p.x);
+    lua.rawSetI(s, -2, 1);
+    lua.pushNumber(s, p.y);
+    lua.rawSetI(s, -2, 2);
+    return 1;
+}
+
+registerPoint(s:lua.State) {
+    lua.newMetaTable(s, "PointFields");
+    static for (i in ...staticIntegers(static RecordFieldCount(Point))) {
+        lua.pushNumber(s, unwrapStatic(i));
+        lua.setField(s, -2, StaticName(RecordFieldName(Point, i)));
+    }
+    lua.registerTable(s,
+        ("xyValues", Point_xyValues),
+        ("xyArray", Point_xyArray),
+    );
+    lua.pop(s, 1);
+    lua.newMetaTable(s, "Point");
+    lua.registerTable(s,
+        ("__index", Point_index),
+        ("__newindex", Point_newIndex),
+    );
+    lua.pop(s, 1);
+    lua.registerModule(s, "Module",
+        ("newPoint", Point_new),
+    );
+    lua.pop(s, 1);
+}
+
+main() {
+    var s = lua.State();
+    lua.openLibs(s);
+    registerPoint(s);
+    try {
+        lua.doString(s, "
+            a = Module.newPoint(-2, 50)
+            b = Module.newPoint(10, 15)
+            print(a.x .. ', ' .. a.y)
+            print(b.x .. ', ' .. b.y)
+            a.x = a.x + 1
+            b.y = b.y + 1
+            local first, second = a:xyValues()
+            print(first .. ', ' .. second)
+            local both = b:xyArray()
+            print(both[1] .. ', ' .. both[2])
+        ");
+    }
+    catch (e:lua.Error) {
+        println("error: ", e.msg);
+    }
+}

File test/lua/highlevel/customtype5/out.txt

+-2, 50
+10, 15
+-1, 50
+10, 16