callstack added

This commit is contained in:
VaclavT 2021-04-09 00:07:20 +02:00
parent 5afa7dd69f
commit 9ab0a2c98d
5 changed files with 72 additions and 27 deletions

View File

@ -7,19 +7,28 @@
### TODO
- replace to_string macro in ml.cpp
- add debug support, at least call stack
- documentation
- add url of source/inspiration to clib/*.cpp
- add stdtest - to test every functionality
- add instrumentation (time, nr of evals, num of atoms, debug info, debug environment etc)
- add parenthesis coloring into linenoise
- multiline editing (kilo editor)
- execute system command should capture stderr
- add some mem stats to benchmark
- create pastebin like web using ml
#### Code
- documentation
- rename constants in ml_profiler.h
- replace to_string macro in ml.cpp
- add url of source/inspiration to clib/*.cpp
- add instrumentation (time, nr of evals, num of atoms, debug info, debug environment etc)
#### Language
- support for (), nil, t, in lsp code replace 0 by nil in logicals
- file functions
- name it here
- open file
- read line
- write line
- close file
- string functions
- itok - integer to char, chartoint (better names) - mini printf can be useed for it (%d)
- compare - needed for sorting, cmp ignore case
- regexp functions
- date support
@ -31,7 +40,6 @@
- mapcar (funcall, apply)
- syntax highlighting do VS Code
- add hash datatype
- create pastebin like web using ml
#### Performance
- define is one of most frequent callee, when in scope with very few vars, lookup sequentially
@ -40,24 +48,25 @@
- mini_sprintf - unnecesary copying between vector and list
- (do, scope ..) repeatedly assign to acc
#### Compile
```
mkdir -p build
gcc -std=c99 -c -O2 -o linenoise.o clib/linenoise.c
c++ -c -O2 -I/usr/local/opt/openssl/include -Iclib --std=c++17 ml.cpp ml_io.cpp ml_date.cpp ml_string.cpp ml_util.cpp ml_profiler.cpp clib/json11.cpp clib/csvparser.cpp clib/sslclient.cpp clib/printf.cpp
// on linux c++ -o build/ml -O2 -L/usr/local/lib -L/usr/local/opt/openssl/lib -lm -lstdc++ -lcrypto -lssl *.o
c++ -o build/ml -O2 -L/usr/local/lib -L/usr/local/opt/openssl/lib -lm -lstdc++ -lcrypto -lssl -Wl,-stack_size -Wl,0x1000000 *.o
```
// or cmake
#### Install
```
cp build/ml /usr/local/bin/ml
cp stdlib/*.lsp /usr/local/var/mlisp/
```
#### Compile
```
gcc -std=c99 -c -O2 -o linenoise.o clib/linenoise.c
c++ -c -O2 -I/usr/local/opt/openssl/include -Iclib --std=c++17 ml.cpp ml_io.cpp ml_date.cpp ml_string.cpp ml_util.cpp ml_profiler.cpp clib/json11.cpp clib/csvparser.cpp clib/sslclient.cpp clib/printf.cpp
c++ -o ml -O2 -L/usr/local/lib -L/usr/local/opt/openssl/lib -lm -lstdc++ -lcrypto -lssl -Wl,-stack_size -Wl,0x1000000 *.o
```
or
cmake
### Example of use
```
time ./build/ml -c '(include "../example.lisp") (print (fact 1000))'
./build/ml -f debug.lisp
```

View File

@ -46,4 +46,12 @@
(print (and (print "xx") (= 1 0) (print "yy")))
(defun aa () (do
(print "prvni")
(+ 1 xx)
(print "druhy")
))
(aa)
; (sleep 1.5)

23
ml.cpp
View File

@ -51,10 +51,10 @@
// Convert an object to a string using a string stream conveniently
#if __APPLE_
#define to_string(x) static_cast<std::ostringstream>((std::ostringstream() << std::dec << x )).str()
#elif __linux
#if __linux
#define to_string(x) static_cast<std::ostringstream&>((std::ostringstream() << std::dec << x )).str()
#else
#define to_string(x) static_cast<std::ostringstream>((std::ostringstream() << std::dec << x )).str()
#endif
// Is this character a valid lisp symbol character
@ -624,7 +624,8 @@ MlError::~MlError() {
std::string MlError::description() {
// return "error: the expression `" + cause->debug() + "` failed in scope " + to_string(env) + " with message \"" + msg + "\"";
return "error: the expression `" + cause->debug() + "` with message \"" + msg + "\"";
return MlPerfMon::instance().callstack() +
"error: the expression `" + cause->debug() + "` with message \"" + msg + "\"";
}
void MlEnvironment::combine(MlEnvironment const &other) {
@ -693,6 +694,7 @@ MlValue MlValue::apply(std::vector<MlValue> args, MlEnvironment &env) {
MlValue MlValue::eval(MlEnvironment &env) {
std::vector<MlValue> args;
MlValue function;
MlValue res;
MlEnvironment e;
switch (type) {
case QUOTE:
@ -715,11 +717,10 @@ MlValue MlValue::eval(MlEnvironment &env) {
args[i] = args[i].eval(env);
MlPerfMon::instance().add_method_call(function.type == LAMBDA ? "lambda" : function.str);
res = function.apply( args, env );
MlPerfMon::instance().end_method_call();
return function.apply(
args,
env
);
return res;
default:
return *this;
@ -1015,7 +1016,7 @@ namespace builtin {
eval_args(args, env);
std::exit(args.size() < 1 ? 0 : args[0].cast_to_int().as_int());
return MlValue();
return MlValue(); // will not be called :-)
}
// Print several values and return the last one
@ -1557,7 +1558,7 @@ namespace builtin {
if (args.size() != 2)
throw MlError(MlValue("string-split", string_split), env, args.size() > 2 ? TOO_MANY_ARGS : TOO_FEW_ARGS);
// TODO more efficient
// TODO do it more efficient
std::vector<std::string> elements = regexp_strsplit(args[0].as_string(), args[1].as_string());
std::vector<MlValue> result{};
@ -1970,7 +1971,7 @@ int main(int argc, char *argv[]) {
} catch (MlError &e) {
std::cerr << e.description() << std::endl;
} catch (std::runtime_error &e) {
std::cerr << e.what() << std::endl;
std::cerr << MlPerfMon::instance().callstack() << e.what() << std::endl;
}
return 1;

View File

@ -2,9 +2,10 @@
#include "ml_profiler.h"
#include <iostream>
#include <algorithm>
// for linux gcc
#include <iomanip>
#include <numeric>
#include <algorithm>
using namespace std::chrono;
@ -15,6 +16,8 @@ void MlPerfMon::turnOn() {
}
void MlPerfMon::add_method_call(const std::string &method) {
call_stack.push_back(method);
if (perfOn) {
auto search = calls_counter.find(method);
if (search != calls_counter.end()) {
@ -25,6 +28,25 @@ void MlPerfMon::add_method_call(const std::string &method) {
}
}
void MlPerfMon::end_method_call() {
if (!call_stack.empty()){
call_stack.pop_back();
}
}
std::string MlPerfMon::callstack() const {
std::string cs {"call stack:\n"};
int cnt = 0;
for (auto it = call_stack.rbegin(); it != call_stack.rend() && cnt < call_stack_max_methods; ++it, ++cnt)
cs.append( std::string(*it) + "\n"); // << std::endl;
if (call_stack.size() > call_stack_max_methods)
cs.append("next " + std::to_string(call_stack.size() - call_stack_max_methods) + " entries skipped..\n");
return cs.append("\n");
}
void MlPerfMon::print_results() {
if (perfOn) {
std::chrono::time_point<std::chrono::high_resolution_clock> end_time = std::chrono::high_resolution_clock::now();

View File

@ -3,10 +3,12 @@
#include "ml.h"
#include <unordered_map>
#include <deque>
#include <chrono>
static const int method_name_print_len = 15;
static const int print_top_methods = 15;
static const int call_stack_max_methods = 10;
class MlPerfMon {
@ -24,10 +26,13 @@ public:
void turnOn();
void add_method_call(const std::string &method);
void end_method_call();
std::string callstack() const;
void print_results();
private:
bool perfOn;
std::unordered_map<std::string, long> calls_counter;
std::chrono::time_point<std::chrono::high_resolution_clock> start_time;
std::deque<std::string> call_stack;
};