New calling conventions, start on print.cpp

This commit is contained in:
2021-09-07 17:37:23 -04:00
parent 924a5ec987
commit 6b2ebba84d
16 changed files with 216 additions and 104 deletions

View File

@@ -8,6 +8,7 @@ CPP_FILES=\
cpp/luastack.cpp\
cpp/traceback.cpp\
cpp/planemap.cpp\
cpp/print.cpp\
cpp/luaconsole.cpp\
cpp/idalloc.cpp\
cpp/globaldb.cpp\

View File

@@ -191,7 +191,7 @@ private:
IdGlobalPool *global_;
int fifo_capacity_;
std::deque<int64_t> ranges_;
friend int unittests_idalloc(lua_State *L);
friend int lfn_unittests_idalloc(lua_State *L);
};
#endif // IDALLOC_HPP

View File

@@ -323,13 +323,6 @@ int LuaStack::rawlen(LuaSlot obj) const {
return lua_rawlen(L_, obj.index());
}
void LuaStack::check_nret(int xnret, int otop, int nret) const {
int ntop = lua_gettop(L_);
if ((nret != xnret)||(ntop != otop + xnret)) {
luaL_error(L_, "expected %d return values", xnret);
}
}
int LuaStack::gettabletype(LuaSlot tab) const {
uint16_t bits = lua_getflagbits(L_, tab.index());
return LUA_TT_GENERAL + (bits & 0x000F);

View File

@@ -319,38 +319,6 @@ private:
void push_any_values() {
}
// Call the CFunction, pushing and popping arguments appropriately.
template<int NRET, typename... T>
void call_cfunction(int otop, LuaSlot s, T... args) {
call_cfunction<NRET+1>(otop, args...);
pop_any_value(s);
}
template<int NRET, typename... T>
void call_cfunction(int otop, lua_Integer &s, T... args) {
call_cfunction<NRET+1>(otop, args...);
pop_any_value(s);
}
template<int NRET, typename... T>
void call_cfunction(int otop, lua_Number &s, T... args) {
call_cfunction<NRET+1>(otop, args...);
pop_any_value(s);
}
template<int NRET, typename... T>
void call_cfunction(int otop, std::string &s, T... args) {
call_cfunction<NRET+1>(otop, args...);
pop_any_value(s);
}
template<int NRET, typename... T>
void call_cfunction(int otop, lua_CFunction fn, T... args) {
push_any_values(args...);
int nret = fn(L_);
check_nret(NRET, otop, nret);
}
// Check number of return values: xpected number of return values,
// original stack top, and number of declared return values.
void check_nret(int xnret, int otop, int nret) const;
template<typename T>
static void delete_pointer(void *p) { delete (T*)p; }
static void do_not_delete(void *p) { }
@@ -477,14 +445,6 @@ public:
lua_rawseti(L_, tab, key);
}
// Call invokes any C function. It pushes the arguments on the stack,
// calls the cfunction, verifies that the number of return values is as
// expected, and pops the return values into LuaVars.
template<typename... T>
void call(T&... args) {
call_cfunction<0>(lua_gettop(L_), args...);
}
// Lua flagbits manipulation: Table types.
int gettabletype(LuaSlot tab) const;
void settabletype(LuaSlot tab, int t) const;
@@ -521,9 +481,9 @@ public:
#define LuaDefine(name, mode) \
int name(lua_State *L); \
LuaFunctionReg reg_##name(mode, #name, name); \
int name(lua_State *L)
int lfn_##name(lua_State *L); \
LuaFunctionReg reg_##name(mode, #name, lfn_##name); \
int lfn_##name(lua_State *L)
#define LuaStringify(x) #x

View File

@@ -128,7 +128,7 @@ public:
private:
// unit testing stuff.
friend int unittests_planemap(lua_State *L);
friend int lfn_unittests_planemap(lua_State *L);
EltVec get_cell(const std::string &plane, int64_t cell) const;
int total_cells() const;
void clear() { planes_.clear(); }

32
luprex/core/cpp/print.cpp Normal file
View File

@@ -0,0 +1,32 @@
#include "print.hpp"
#include "util.hpp"
#include <ostream>
#include <iostream>
void luai_writestring(const char *s, size_t len) {
std::cout.write(s, len);
}
void luai_writeline() {
std::cout << std::endl;
std::cout.flush();
}
LuaDefine(string_isidentifier, "c") {
LuaArg str;
LuaRet result;
LuaStack LS(L, str, result);
if (LS.isstring(str)) {
std::string s = LS.ckstring(str);
LS.set(result, util::is_identifier(s));
} else {
LS.set(result, false);
}
return LS.result();
}
void pprint(LuaStack &LS0, LuaSlot val, int indent, int maxlen, std::ostream *os) {
}

46
luprex/core/cpp/print.hpp Normal file
View File

@@ -0,0 +1,46 @@
/////////////////////////////////////////////////////////
//
// Pretty-print routine.
//
// The pretty-printer can be called from C++ or Lua.
//
/////////////////////////////////////////////////////////
#ifndef PRINT_HPP
#define PRINT_HPP
#include "luastack.hpp"
// This file provides these functions for lua.
//
// They direct all output to std::cout
//
extern "C" {
void luai_writestring(const char *s, size_t len);
void luai_writeline();
}
// Pretty print to a stream.
//
// If indent is >=0, the output is indented. If indent<0, then
// the output is emitted without newlines or indentation.
//
// Maxlen specifies the maximum number of characters output. If
// this is exceeded, then the printout is truncated.
//
void pprint(LuaStack &LS, LuaSlot val, int indent, int maxlen, std::ostream *os);
// The following lua interfaces to this code are included:
//
// pprint(expr)
//
// - pretty print the specified expression to stdout.
//
// string.pprint(expr, indent, maxlen)
//
// - pretty print the specified expression, return the result as a string.
//
void pprint_pprint(lua_State *L);
void string_pprint(lua_State *L);
#endif // PRINT_HPP

View File

@@ -115,11 +115,10 @@ static void source_install_builtins(lua_State *L) {
LS.setmetatable(nullstring, stringclass);
}
static int source_updatefile(lua_State *L) {
LuaArg source, fn;
LuaRet info;
static void source_updatefile(LuaStack &LS0, LuaSlot source, LuaSlot fn, LuaSlot info) {
lua_State *L = LS0.state();
LuaVar fingerprint, null, loadresult;
LuaStack LS(L, source, fn, info, fingerprint, null, loadresult);
LuaStack LS(L, fingerprint, null, loadresult);
// Get the existing info table from the source DB.
if (LS.istable(source)) {
@@ -158,7 +157,7 @@ static int source_updatefile(lua_State *L) {
LS.rawset(info, "loadresult", loadresult);
}
}
return LS.result();
LS.result();
}
void SourceDB::update() {
@@ -184,7 +183,7 @@ void SourceDB::update() {
LS.set(fn, filenames[i]);
// Call source_updatefile to get the updated info for one file.
LS.call(info, source_updatefile, sourcedb, fn);
source_updatefile(LS, sourcedb, fn, info);
// Insert the sequence number and put finalized info into the new database.
LS.set(seq, i + 1);
@@ -209,7 +208,7 @@ static void source_clear_globals(lua_State *L) {
LS.set(classname, LuaNil);
while (LS.next(globtab, classname, classtab) != 0) {
if (LS.istable(classtab)) {
LS.call(table_clear, classtab);
table_clear(LS, classtab);
} else {
LS.rawset(globtab, classname, LuaNil);
}
@@ -238,7 +237,7 @@ static void source_load_cfunctions(lua_State *L) {
std::string mode = r->get_mode();
if (mode.find('c') != std::string::npos) { // Insert into class
lua_pushlstring(L, classname.c_str(), classname.size());
source_makeclass(L);
lfn_source_makeclass(L);
lua_pushcfunction(L, func);
lua_setfield(L, -2, funcname.c_str());
}

View File

@@ -163,11 +163,11 @@ public:
// If there's already a table with this name in the global environment,
// leaves it there, and repairs the __class and __index fields.
//
int source_makeclass(lua_State *L);
int lfn_source_makeclass(lua_State *L);
// Return true if the specified table is a class created by 'makeclass'
//
int source_isclass(lua_State *L);
int lfn_source_isclass(lua_State *L);
#endif // SOURCE_HPP

View File

@@ -416,7 +416,7 @@ private:
// This is for unit testing.
bool layout_is(int64_t a, int64_t b, int64_t c);
friend int unittests_streambuffer(lua_State *L);
friend int lfn_unittests_streambuffer(lua_State *L);
};

View File

@@ -1,6 +1,50 @@
#include "table.hpp"
#include "source.hpp"
void table_findtables_i(LuaStack &LS0, LuaSlot root, LuaSlot tabcount) {
lua_State *L = LS0.state();
LuaVar key, val, tab, count;
LuaStack LS(L, key, val, tab, count);
LS.newtable(tabcount);
int top = lua_gettop(L);
if (LS.istable(root)) {
lua_pushvalue(L, root.index());
}
while (lua_gettop(L) > top) {
lua_checkstack(L, 10);
lua_replace(L, tab.index());
LS.rawget(count, tabcount, tab);
if (LS.isnil(count)) {
LS.rawset(tabcount, tab, 1);
LS.set(key, LuaNil);
while (LS.next(tab, key, val)) {
if (LS.istable(key)) {
lua_pushvalue(L, key.index());
}
if (LS.istable(val)) {
lua_pushvalue(L, val.index());
}
}
LS.getmetatable(val, tab);
if (LS.istable(val)) {
lua_pushvalue(L, val.index());
}
} else {
LS.rawset(tabcount, tab, LS.ckint(count) + 1);
}
}
LS.result();
}
LuaDefine(table_findtables, "c") {
LuaArg root;
LuaRet tabcount;
LuaStack LS(L, root, tabcount);
table_findtables_i(LS, root, tabcount);
return LS.result();
}
LuaDefine(table_getregistry, "f") {
LuaArg key;
LuaRet result;
@@ -9,10 +53,8 @@ LuaDefine(table_getregistry, "f") {
return LS.result();
}
LuaDefine(table_equal, "c") {
LuaArg t1, t2;
LuaRet eql;
LuaStack LS(L, t1, t2, eql);
bool table_equal(LuaStack &LS, LuaSlot t1, LuaSlot t2) {
lua_State *L = LS.state();
LS.checktable(t1);
LS.checktable(t2);
lua_pushnil(L);
@@ -21,8 +63,7 @@ LuaDefine(table_equal, "c") {
lua_pushvalue(L, -2); // k v1 k
lua_rawget(L, t2.index()); // k v1 v2
if (!lua_rawequal(L, -1, -2)) {
LS.set(eql, false);
return LS.result();
return false;
}
lua_pop(L, 2);
total1 += 1;
@@ -33,7 +74,14 @@ LuaDefine(table_equal, "c") {
lua_pop(L, 1);
total2 += 1;
}
LS.set(eql, total1 == total2);
return total1 == total2;
}
LuaDefine(table_equal, "c") {
LuaArg t1, t2;
LuaRet eql;
LuaStack LS(L, t1, t2, eql);
LS.set(eql, table_equal(LS, t1, t2));
return LS.result();
}
@@ -124,10 +172,14 @@ LuaDefine(table_count, "c") {
return 1;
}
void table_clear(LuaStack &LS0, LuaSlot table) {
LS0.cleartable(table);
}
LuaDefine(table_clear, "c") {
LuaArg tab;
LuaStack LS(L, tab);
LS.cleartable(tab);
table_clear(LS, tab);
return LS.result();
}
@@ -607,7 +659,7 @@ LuaDefine(table_sortedpairs, "c") {
luaL_error(L, "Cannot iterate over a table with unsortable keys");
}
lua_replace(L, rtab.index());
LS.set(closure, table_nextsortedpair);
LS.set(closure, lfn_table_nextsortedpair);
LS.set(key, LuaNil);
return LS.result();
}

View File

@@ -12,83 +12,91 @@
#include "luastack.hpp"
// Starting at the specified root, find tables recursively.
//
// Returns a table containing every table found, in tabcount.
// The value associated with the table is the number of times the
// table was found.
//
void table_findtables(LuaStack &LS0, LuaSlot root, LuaSlot tabcount);
// table_clear
//
// Remove all key/value pairs from the table. Does not remove
// the metatable.
//
void table_clear(LuaStack &LS0, LuaSlot tab);
// table_equal
//
// True if two tables contain the same key/value pairs.
//
int table_equal(lua_State *L);
bool table_equal(LuaStack &LS0, LuaSlot tab1, LuaSlot tab2);
// table_findremove
//
// Given a vector and a value, remove the specified value from
// the vector, and shift elements downward to fill the gaps.
//
int table_findremove(lua_State *L);
int lfn_table_findremove(lua_State *L);
// table_push
//
// Given a vector and a value, push the value onto the end.
//
int table_push(lua_State *L);
int lfn_table_push(lua_State *L);
// table_find
//
// Given a vector and a value, search for the first occurrence
// of that value. Return the index.
//
int table_find(lua_State *L);
int lfn_table_find(lua_State *L);
// table_empty
//
// Return true if the table has no key/value pairs.
//
int table_empty(lua_State *L);
int lfn_table_empty(lua_State *L);
// table_count
//
// Return the number of key/value pairs in the table.
//
int table_count(lua_State *L);
// table_clear
//
// Remove all key/value pairs from the table. Does not
// remove the metatable.
//
int table_clear(lua_State *L);
int lfn_table_count(lua_State *L);
//
// Create and return an empty deque. Queues are implemented
// as tables which are used as dynamically-expandable circular
// buffers.
//
int deque_create(lua_State *L);
int lfn_deque_create(lua_State *L);
//
// Given a deque and a value, pushes the value onto the
// left or right end.
//
int deque_pushl(lua_State *L);
int deque_pushr(lua_State *L);
int lfn_deque_pushl(lua_State *L);
int lfn_deque_pushr(lua_State *L);
//
// Given a deque, pop from the left or right end. Returns the
// value and removes it from the deque. If the deque is
// empty, returns nil.
//
int deque_popl(lua_State *L);
int deque_popr(lua_State *L);
int lfn_deque_popl(lua_State *L);
int lfn_deque_popr(lua_State *L);
//
// Return the nth element from the left or right end of a deque.
//
int deque_nthl(lua_State *L);
int deque_nthr(lua_State *L);
int lfn_deque_nthl(lua_State *L);
int lfn_deque_nthr(lua_State *L);
// Set (overwrite) the nth element in a deque.
//
int deque_setl(lua_State *L);
int deque_setr(lua_State *L);
int lfn_deque_setl(lua_State *L);
int lfn_deque_setr(lua_State *L);
//
// Search a deque for a value.
@@ -96,13 +104,12 @@ int deque_setr(lua_State *L);
// Search starts on the specified end and indices are relative
// to specified end.
//
int deque_findl(lua_State *L);
int deque_findr(lua_State *L);
int lfn_deque_findl(lua_State *L);
int lfn_deque_findr(lua_State *L);
//
// Return the number of values in the deque.
//
int deque_size(lua_State *L);
int lfn_deque_size(lua_State *L);
#endif // TABLE_HPP

View File

@@ -16,6 +16,25 @@
namespace util {
static bool ascii_isalpha(char c) {
return ((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z'));
}
static bool ascii_isdigit(char c) {
return ((c >= '0') && (c <= '9'));
}
bool is_identifier(const std::string &str) {
if (str.size() == 0) return false;
char c=str[0];
if ((!ascii_isalpha(c)) && (c!='_')) return false;
for (int i = 1; i < int(str.size()); i++) {
char c = str[i];
if ((!ascii_isalpha(c)) && (!ascii_isdigit(c)) && (c!='_')) return false;
}
return true;
}
IdVector id_vector_create(int64_t id1, int64_t id2, int64_t id3, int64_t id4) {
IdVector result;
if (id1 >= 0) result.push_back(id1);

View File

@@ -24,6 +24,9 @@ using StringVec = std::vector<std::string>;
using HashValue = std::pair<uint64_t, uint64_t>;
using IdVector = std::vector<int64_t>;
// Return true if the string is a valid lua identifier.
bool is_identifier(const std::string &str);
// ID vector quick create.
IdVector id_vector_create(int64_t id1=-1, int64_t id2=-1, int64_t id3=-1, int64_t id4=-1);

View File

@@ -477,9 +477,9 @@ LuaDefine(table_diffapply, "c") {
patch_table(MLS, tangibles, mntmap, mstab, &sb);
MLS.call(eql, table_equal, mstab, mtab);
bool e = MLS.ckboolean(eql);
if (e) {
bool eq = table_equal(MLS, mstab, mtab);
MLS.set(eql, eq);
if (eq) {
MLS.set(eqlstr, "tables equal");
} else {
MLS.set(eqlstr, "tables were supposed to be equal");

View File

@@ -396,9 +396,9 @@ private:
Redirects redirects_;
friend class Tangible;
friend int tangible_animate(lua_State *L);
friend int tangible_build(lua_State *L);
friend int tangible_redirect(lua_State *L);
friend int lfn_tangible_animate(lua_State *L);
friend int lfn_tangible_build(lua_State *L);
friend int lfn_tangible_redirect(lua_State *L);
};
#endif // WORLD_HPP