fix(lua/sexpr): make sexpr bindings robust
Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
parent
055cc7f957
commit
0cc475e581
2 changed files with 78 additions and 12 deletions
|
@ -48,7 +48,7 @@ static sexpr to_sexpr_elem(lua_State * L, int idx) {
|
|||
if (lua_isnil(L, idx)) {
|
||||
return sexpr();
|
||||
} else if (lua_isboolean(L, idx)) {
|
||||
return sexpr(lua_toboolean(L, idx));
|
||||
return sexpr(static_cast<bool>(lua_toboolean(L, idx)));
|
||||
} else if (lua_isnumber(L, idx)) {
|
||||
// Remark: we convert to integer by default
|
||||
return sexpr(static_cast<int>(lua_tointeger(L, idx)));
|
||||
|
@ -95,7 +95,7 @@ static int sexpr_is_name(lua_State * L) { lua_pushboolean(L, is_name(to_sexpr(
|
|||
static int sexpr_is_mpz(lua_State * L) { lua_pushboolean(L, is_mpz(to_sexpr(L, 1))); return 1; }
|
||||
static int sexpr_is_mpq(lua_State * L) { lua_pushboolean(L, is_mpq(to_sexpr(L, 1))); return 1; }
|
||||
|
||||
static int sexpr_length(lua_State * L) {
|
||||
static int sexpr_length(lua_State * L) {
|
||||
sexpr const & e = to_sexpr(L, 1);
|
||||
if (!is_list(e))
|
||||
return luaL_error(L, "s-expression is not a list");
|
||||
|
@ -103,27 +103,72 @@ static int sexpr_length(lua_State * L) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int sexpr_head(lua_State * L) {
|
||||
static int sexpr_head(lua_State * L) {
|
||||
sexpr const & e = to_sexpr(L, 1);
|
||||
if (!is_cons(e))
|
||||
return luaL_error(L, "s-expression is not a cons cell");
|
||||
return push_sexpr(L, head(e));
|
||||
}
|
||||
|
||||
static int sexpr_tail(lua_State * L) {
|
||||
static int sexpr_tail(lua_State * L) {
|
||||
sexpr const & e = to_sexpr(L, 1);
|
||||
if (!is_cons(e))
|
||||
return luaL_error(L, "s-expression is not a cons cell");
|
||||
return push_sexpr(L, tail(e));
|
||||
}
|
||||
|
||||
static int sexpr_to_bool(lua_State * L) { lua_pushboolean(L, to_bool(to_sexpr(L, 1))); return 1; }
|
||||
static int sexpr_to_string(lua_State * L) { lua_pushfstring(L, to_string(to_sexpr(L, 1)).c_str()); return 1; }
|
||||
static int sexpr_to_int(lua_State * L) { lua_pushinteger(L, to_int(to_sexpr(L, 1))); return 1; }
|
||||
static int sexpr_to_double(lua_State * L) { lua_pushnumber(L, to_double(to_sexpr(L, 1))); return 1; }
|
||||
static int sexpr_to_name(lua_State * L) { return push_name(L, to_name(to_sexpr(L, 1))); }
|
||||
static int sexpr_to_mpz(lua_State * L) { return push_mpz(L, to_mpz(to_sexpr(L, 1))); }
|
||||
static int sexpr_to_mpq(lua_State * L) { return push_mpq(L, to_mpq(to_sexpr(L, 1))); }
|
||||
static int sexpr_to_bool(lua_State * L) {
|
||||
sexpr const & e = to_sexpr(L, 1);
|
||||
if (!is_bool(e))
|
||||
return luaL_error(L, "s-expression is not a Boolean");
|
||||
lua_pushboolean(L, to_bool(e));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int sexpr_to_string(lua_State * L) {
|
||||
sexpr const & e = to_sexpr(L, 1);
|
||||
if (!is_string(e))
|
||||
return luaL_error(L, "s-expression is not a string");
|
||||
lua_pushfstring(L, to_string(e).c_str());
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int sexpr_to_int(lua_State * L) {
|
||||
sexpr const & e = to_sexpr(L, 1);
|
||||
if (!is_int(e))
|
||||
return luaL_error(L, "s-expression is not an integer");
|
||||
lua_pushinteger(L, to_int(e));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int sexpr_to_double(lua_State * L) {
|
||||
sexpr const & e = to_sexpr(L, 1);
|
||||
if (!is_double(e))
|
||||
return luaL_error(L, "s-expression is not a double");
|
||||
lua_pushnumber(L, to_double(e));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int sexpr_to_name(lua_State * L) {
|
||||
sexpr const & e = to_sexpr(L, 1);
|
||||
if (!is_name(e))
|
||||
return luaL_error(L, "s-expression is not a name");
|
||||
return push_name(L, to_name(e));
|
||||
}
|
||||
|
||||
static int sexpr_to_mpz(lua_State * L) {
|
||||
sexpr const & e = to_sexpr(L, 1);
|
||||
if (!is_mpz(e))
|
||||
return luaL_error(L, "s-expression is not a multi-precision integer");
|
||||
return push_mpz(L, to_mpz(e));
|
||||
}
|
||||
|
||||
static int sexpr_to_mpq(lua_State * L) {
|
||||
sexpr const & e = to_sexpr(L, 1);
|
||||
if (!is_mpq(e))
|
||||
return luaL_error(L, "s-expression is not a multi-precision rational");
|
||||
return push_mpq(L, to_mpq(e));
|
||||
}
|
||||
|
||||
static const struct luaL_Reg sexpr_m[] = {
|
||||
{"__gc", sexpr_gc}, // never throws
|
||||
|
|
|
@ -1,3 +1,14 @@
|
|||
function check_error(f)
|
||||
ok, msg = pcall(function ()
|
||||
f()
|
||||
end)
|
||||
if ok then
|
||||
error("unexpected success...")
|
||||
else
|
||||
print("caught expected error: ", msg)
|
||||
end
|
||||
end
|
||||
|
||||
s = sexpr(1, 2, 3)
|
||||
print(s)
|
||||
s = sexpr(1, 2, 3, nil)
|
||||
|
@ -11,8 +22,9 @@ print(sexpr(1):is_nil())
|
|||
print(sexpr(true):is_bool())
|
||||
print(sexpr(true):to_bool())
|
||||
print(sexpr(false):to_bool())
|
||||
check_error(function() sexpr(10):to_bool() end)
|
||||
print(sexpr(name("foo",1)):to_name())
|
||||
print(sexpr(10):to_name())
|
||||
check_error(function () print(sexpr(10):to_name()) end)
|
||||
print(sexpr(mpq(10)/3):to_mpq())
|
||||
print(sexpr(mpz("10000000000000000000000000000000000")):to_mpz())
|
||||
print(sexpr(10, 20, 30, 40, nil):length())
|
||||
|
@ -20,3 +32,12 @@ print(sexpr(10, 20, nil):head())
|
|||
print(sexpr(10, 20, nil):tail())
|
||||
print(sexpr(10, 20):head())
|
||||
print(sexpr(10, 20):tail())
|
||||
check_error(function () sexpr(10):head() end)
|
||||
check_error(function () sexpr(10):tail() end)
|
||||
check_error(function () sexpr(10):to_mpz() end)
|
||||
check_error(function () sexpr(10):to_mpq() end)
|
||||
check_error(function () sexpr(10):to_string() end)
|
||||
check_error(function () sexpr(10):to_bool() end)
|
||||
check_error(function () sexpr(10):to_double() end)
|
||||
print(sexpr("hello"):to_string())
|
||||
|
||||
|
|
Loading…
Reference in a new issue