Fixes #1253
More accurate type classification and eager evaluation of left "and" operand.pull/1258/head
parent
a268ea89f2
commit
105908204b
|
@ -154,6 +154,21 @@ export function evalExpression(
|
||||||
} else {
|
} else {
|
||||||
return evalExpression(e.right, env, sf);
|
return evalExpression(e.right, env, sf);
|
||||||
}
|
}
|
||||||
|
} else if (e.operator === "and") {
|
||||||
|
// Special case: eagerly evaluate left before even attempting right
|
||||||
|
const left = evalExpression(e.left, env, sf);
|
||||||
|
if (left instanceof Promise) {
|
||||||
|
return left.then((left) => {
|
||||||
|
if (!luaTruthy(left)) {
|
||||||
|
return left;
|
||||||
|
}
|
||||||
|
return evalExpression(e.right, env, sf);
|
||||||
|
});
|
||||||
|
} else if (!luaTruthy(left)) {
|
||||||
|
return left;
|
||||||
|
} else {
|
||||||
|
return evalExpression(e.right, env, sf);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
const values = evalPromiseValues([
|
const values = evalPromiseValues([
|
||||||
evalExpression(e.left, env, sf),
|
evalExpression(e.left, env, sf),
|
||||||
|
|
|
@ -433,3 +433,11 @@ end
|
||||||
|
|
||||||
assertEqual(sum(1, 2, 3), 6)
|
assertEqual(sum(1, 2, 3), 6)
|
||||||
assertEqual(sum(1, 2, 3, 4, 5), 15)
|
assertEqual(sum(1, 2, 3, 4, 5), 15)
|
||||||
|
|
||||||
|
local data = { { name = "John", favorite = { color = "blue" } }, { name = "Jane" } }
|
||||||
|
assertEqual(type(data[1].favorite), "table")
|
||||||
|
assertEqual(data[1].favorite.color, "blue")
|
||||||
|
|
||||||
|
local r = query [[from p = data where type(p.favorite) == "table" and p.favorite.color == "blue"]]
|
||||||
|
assertEqual(#r, 1)
|
||||||
|
assertEqual(r[1].name, "John")
|
||||||
|
|
|
@ -657,9 +657,12 @@ export function luaKeys(val: any): any[] {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function luaTypeOf(val: any): LuaType {
|
export function luaTypeOf(val: any): LuaType | Promise<LuaType> {
|
||||||
if (val === null || val === undefined) {
|
if (val === null || val === undefined) {
|
||||||
return "nil";
|
return "nil";
|
||||||
|
}
|
||||||
|
if (val instanceof Promise) {
|
||||||
|
return val.then((v) => luaTypeOf(v));
|
||||||
} else if (typeof val === "boolean") {
|
} else if (typeof val === "boolean") {
|
||||||
return "boolean";
|
return "boolean";
|
||||||
} else if (typeof val === "number") {
|
} else if (typeof val === "number") {
|
||||||
|
@ -672,6 +675,8 @@ export function luaTypeOf(val: any): LuaType {
|
||||||
return "table";
|
return "table";
|
||||||
} else if (typeof val === "function" || val.call) {
|
} else if (typeof val === "function" || val.call) {
|
||||||
return "function";
|
return "function";
|
||||||
|
} else if (typeof val === "object" && val.constructor === Object) {
|
||||||
|
return "table";
|
||||||
} else {
|
} else {
|
||||||
return "userdata";
|
return "userdata";
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,9 +80,11 @@ const unpackFunction = new LuaBuiltinFunction(async (sf, t: LuaTable) => {
|
||||||
return new LuaMultiRes(values);
|
return new LuaMultiRes(values);
|
||||||
});
|
});
|
||||||
|
|
||||||
const typeFunction = new LuaBuiltinFunction((_sf, value: LuaValue): string => {
|
const typeFunction = new LuaBuiltinFunction(
|
||||||
return luaTypeOf(value);
|
(_sf, value: LuaValue): string | Promise<string> => {
|
||||||
});
|
return luaTypeOf(value);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
const tostringFunction = new LuaBuiltinFunction((_sf, value: any) => {
|
const tostringFunction = new LuaBuiltinFunction((_sf, value: any) => {
|
||||||
return luaToString(value);
|
return luaToString(value);
|
||||||
|
|
Loading…
Reference in New Issue