Add simple sigint handler for repl.
inline evalLambdaArgs() and evalBuiltIns()
This commit is contained in:
parent
abaf3a1ddc
commit
4d215b1b79
34
src/main.c
34
src/main.c
|
@ -2,25 +2,31 @@
|
||||||
|
|
||||||
#include "pebblisp.h"
|
#include "pebblisp.h"
|
||||||
|
|
||||||
|
#include <signal.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <readline/readline.h>
|
#include <readline/readline.h>
|
||||||
#include <readline/history.h>
|
#include <readline/history.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
char* getPrompt(struct Environment* env)
|
Object getPrompt(struct Environment* env)
|
||||||
{
|
{
|
||||||
Object prompt = fetchFromEnvironment("prompt", env);
|
Object prompt = fetchFromEnvironment("prompt", env);
|
||||||
prompt = cloneObject(prompt);
|
prompt = cloneObject(prompt);
|
||||||
if (prompt.type == TYPE_STRING) {
|
if (prompt.type == TYPE_STRING) {
|
||||||
char* ret = readline(prompt.string);
|
return prompt;
|
||||||
cleanObject(&prompt);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
Object param = stringFromSlice("", 1);
|
Object param = stringFromSlice("", 1);
|
||||||
Object e = listEvalLambda(&prompt, ¶m, 2, env);
|
Object e = listEvalLambda(&prompt, ¶m, 2, env);
|
||||||
cleanObject(&prompt);
|
cleanObject(&prompt);
|
||||||
cleanObject(¶m);
|
cleanObject(¶m);
|
||||||
char* ret = readline(e.string);
|
return e;
|
||||||
cleanObject(&e);
|
}
|
||||||
|
|
||||||
|
char* prompt(struct Environment* env)
|
||||||
|
{
|
||||||
|
Object p = getPrompt(env);
|
||||||
|
char* ret = readline(p.string);
|
||||||
|
cleanObject(&p);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,12 +39,21 @@ char* preprocess(char* buf, struct Environment* env)
|
||||||
return stringObj(&s, &length);
|
return stringObj(&s, &length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void sigintHandler(unused int signalNumber)
|
||||||
|
{
|
||||||
|
Object p = getPrompt(global());
|
||||||
|
write(1, "\n", 1);
|
||||||
|
write(1, p.string, strlen(p.string));
|
||||||
|
cleanObject(&p);
|
||||||
|
}
|
||||||
|
|
||||||
void repl(struct Environment* env)
|
void repl(struct Environment* env)
|
||||||
{
|
{
|
||||||
|
signal(SIGINT, sigintHandler);
|
||||||
char* buf;
|
char* buf;
|
||||||
using_history();
|
using_history();
|
||||||
|
|
||||||
while ((buf = getPrompt(env)) != NULL) {
|
while ((buf = prompt(env)) != NULL) {
|
||||||
if (strcmp("q", buf) == 0) {
|
if (strcmp("q", buf) == 0) {
|
||||||
free(buf);
|
free(buf);
|
||||||
break;
|
break;
|
||||||
|
@ -90,12 +105,11 @@ void loadArgsIntoEnv(int argc, const char* argv[], struct Environment* env)
|
||||||
|
|
||||||
#ifdef __x86_64__
|
#ifdef __x86_64__
|
||||||
|
|
||||||
#include <signal.h>
|
|
||||||
#include <ucontext.h>
|
#include <ucontext.h>
|
||||||
|
|
||||||
int nestedSegfault = 0;
|
int nestedSegfault = 0;
|
||||||
|
|
||||||
void handler(int nSignum, siginfo_t* si, void* vcontext)
|
void handler(unused int nSignum, unused siginfo_t* si, void* vcontext)
|
||||||
{
|
{
|
||||||
if (nestedSegfault) {
|
if (nestedSegfault) {
|
||||||
printf("Nested segfault!!!\n");
|
printf("Nested segfault!!!\n");
|
||||||
|
@ -122,7 +136,6 @@ void setupSegfaultHandler()
|
||||||
action.sa_flags = SA_SIGINFO;
|
action.sa_flags = SA_SIGINFO;
|
||||||
action.sa_sigaction = handler;
|
action.sa_sigaction = handler;
|
||||||
sigaction(SIGSEGV, &action, NULL);
|
sigaction(SIGSEGV, &action, NULL);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
@ -176,6 +189,7 @@ void getSettings(int argc, const char* argv[])
|
||||||
int main(int argc, const char* argv[])
|
int main(int argc, const char* argv[])
|
||||||
{
|
{
|
||||||
setupSegfaultHandler();
|
setupSegfaultHandler();
|
||||||
|
|
||||||
getSettings(argc, argv);
|
getSettings(argc, argv);
|
||||||
|
|
||||||
struct Environment env = defaultEnv();
|
struct Environment env = defaultEnv();
|
||||||
|
|
|
@ -79,14 +79,6 @@ Object evalIfArgs(const Object* argForms, struct Environment* env)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Not a typical pl function because it relies almost exclusively on symbols
|
|
||||||
*/
|
|
||||||
Object evalLambdaArgs(const Object* argForms, struct Environment* env)
|
|
||||||
{
|
|
||||||
return constructLambda(argForms, argForms ? argForms->forward : NULL, env);
|
|
||||||
}
|
|
||||||
|
|
||||||
Object mapO(Object* params, int length, struct Environment* env)
|
Object mapO(Object* params, int length, struct Environment* env)
|
||||||
{
|
{
|
||||||
if (length < 2) {
|
if (length < 2) {
|
||||||
|
@ -101,7 +93,6 @@ Object mapO(Object* params, int length, struct Environment* env)
|
||||||
}
|
}
|
||||||
|
|
||||||
Object outputList = listObject();
|
Object outputList = listObject();
|
||||||
if (inputList) {
|
|
||||||
FOR_POINTER_IN_LIST(inputList) {
|
FOR_POINTER_IN_LIST(inputList) {
|
||||||
// Create a new list for each element,
|
// Create a new list for each element,
|
||||||
// since lambda evaluation looks for a list
|
// since lambda evaluation looks for a list
|
||||||
|
@ -116,28 +107,11 @@ Object mapO(Object* params, int length, struct Environment* env)
|
||||||
deleteEnv(&newEnv);
|
deleteEnv(&newEnv);
|
||||||
cleanObject(&tempInput);
|
cleanObject(&tempInput);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
cleanObject(&lambda);
|
cleanObject(&lambda);
|
||||||
|
|
||||||
return outputList;
|
return outputList;
|
||||||
}
|
}
|
||||||
|
|
||||||
Object evalBuiltIns(const Object* first, const Object* rest,
|
|
||||||
struct Environment* env, int* found)
|
|
||||||
{
|
|
||||||
*found = 1;
|
|
||||||
if (strcmp(first->string, "if") == 0) {
|
|
||||||
return evalIfArgs(rest, env);
|
|
||||||
} else if (strcmp(first->string, "fn") == 0) {
|
|
||||||
return evalLambdaArgs(rest, env);
|
|
||||||
} else if (strcmp(first->string, "struct") == 0) {
|
|
||||||
return evalStructArgs(rest, rest->forward, env);
|
|
||||||
}
|
|
||||||
|
|
||||||
*found = 0;
|
|
||||||
return *first;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Evaluates a paramList whose first element is a function, applying that function
|
* Evaluates a paramList whose first element is a function, applying that function
|
||||||
*
|
*
|
||||||
|
@ -229,10 +203,14 @@ Object evalList(const Object* obj, struct Environment* env)
|
||||||
|
|
||||||
Object* first_form = obj->list;
|
Object* first_form = obj->list;
|
||||||
if (first_form->type == TYPE_SYMBOL) {
|
if (first_form->type == TYPE_SYMBOL) {
|
||||||
int found;
|
if (strcmp(first_form->string, "if") == 0) {
|
||||||
Object builtIn = evalBuiltIns(first_form, first_form->forward, env, &found);
|
return evalIfArgs(first_form->forward, env);
|
||||||
if (found) {
|
} else if (strcmp(first_form->string, "fn") == 0) {
|
||||||
return builtIn;
|
Object* params = first_form->forward;
|
||||||
|
Object* body = params ? params->forward : NULL;
|
||||||
|
return constructLambda(params, body, env);
|
||||||
|
} else if (strcmp(first_form->string, "struct") == 0) {
|
||||||
|
return evalStructArgs(first_form->forward, first_form->forward->forward, env);
|
||||||
}
|
}
|
||||||
|
|
||||||
int i = getStructIndex(first_form->string);
|
int i = getStructIndex(first_form->string);
|
||||||
|
@ -275,6 +253,19 @@ Object evalList(const Object* obj, struct Environment* env)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
Object funcyWithArgs(Object funcy, int count, ...)
|
||||||
|
{
|
||||||
|
va_list ptr;
|
||||||
|
va_start(ptr, count);
|
||||||
|
Object args[count];
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
args[i] = va_arg(ptr, Object);
|
||||||
|
}
|
||||||
|
va_end(ptr);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
Object eval(const Object* obj, struct Environment* env)
|
Object eval(const Object* obj, struct Environment* env)
|
||||||
{
|
{
|
||||||
switch (obj->type) {
|
switch (obj->type) {
|
||||||
|
@ -342,10 +333,10 @@ Result parse(struct Slice* slices)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SUGAR
|
#ifndef NO_SUGAR
|
||||||
#define sugar(_desc, _code) ;
|
|
||||||
#else
|
|
||||||
#define sugar(_desc, _code) _code
|
#define sugar(_desc, _code) _code
|
||||||
|
#else
|
||||||
|
#define sugar(_desc, _code) ;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Result readSeq(struct Slice* tokens)
|
Result readSeq(struct Slice* tokens)
|
||||||
|
|
|
@ -77,8 +77,6 @@ Object parseEval(const char* input, struct Environment* env);
|
||||||
|
|
||||||
Object evalList(const Object* obj, struct Environment* env);
|
Object evalList(const Object* obj, struct Environment* env);
|
||||||
|
|
||||||
Object evalLambdaArgs(const Object* arg_forms, struct Environment* env);
|
|
||||||
|
|
||||||
Object listEvalLambda(Object* lambda, const Object* remaining, int evalLength,
|
Object listEvalLambda(Object* lambda, const Object* remaining, int evalLength,
|
||||||
struct Environment* env);
|
struct Environment* env);
|
||||||
|
|
||||||
|
@ -110,7 +108,8 @@ struct Slice* getLastOpen();
|
||||||
|
|
||||||
#endif /* STANDALONE */
|
#endif /* STANDALONE */
|
||||||
|
|
||||||
fn(mapO, "map",
|
tfn(mapO, "map",
|
||||||
|
({ expect(isFuncy), expect(isListy), returns(isListy) }),
|
||||||
"Map over a list with a function.",
|
"Map over a list with a function.",
|
||||||
"(map (fn (a) (* a a)) (1 2 3))", "( 1 4 9 )",
|
"(map (fn (a) (* a a)) (1 2 3))", "( 1 4 9 )",
|
||||||
);
|
);
|
||||||
|
@ -124,8 +123,8 @@ tfn(structAccess, "poss",
|
||||||
({ expect(isStruct), expect(isStringy), anyType }),
|
({ expect(isStruct), expect(isStringy), anyType }),
|
||||||
"Get the value of a struct's field",
|
"Get the value of a struct's field",
|
||||||
"(struct Post (title body))\n "
|
"(struct Post (title body))\n "
|
||||||
"(def p (Post \"TI\" \"BO\"))\n "
|
"(def p (Post \"This is a title\" \"This is the body\"))\n "
|
||||||
"p.title", "TI"
|
"p.title", "This is a title"
|
||||||
);
|
);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue