step: playing around with more tweaks
This commit is contained in:
parent
59c51e0027
commit
ce12b90eb5
4
makefile
4
makefile
|
@ -6,8 +6,8 @@
|
||||||
# make uninstall
|
# make uninstall
|
||||||
|
|
||||||
## C compiler
|
## C compiler
|
||||||
CC=tcc # much faster compilation than gcc
|
CC=gcc # much faster compilation than gcc
|
||||||
COMPILER_FLAGS=#-g3 -Wall -Wextra -Wconversion -Wdouble-promotion -Wno-unused-parameter -Wno-unused-function -Wno-sign-conversion -fsanitize=undefined
|
COMPILER_FLAGS=-g3 -Wall -Wextra -Wconversion -Wdouble-promotion -Wno-unused-parameter -Wno-unused-function -Wno-sign-conversion -fsanitize=undefined
|
||||||
# exclude: -fsanitize-trap, because I'm using an old version of gcc and couldn't bother getting a new one.
|
# exclude: -fsanitize-trap, because I'm using an old version of gcc and couldn't bother getting a new one.
|
||||||
## ^ from <https://nullprogram.com/blog/2023/04/29/>
|
## ^ from <https://nullprogram.com/blog/2023/04/29/>
|
||||||
## <https://news.ycombinator.com/item?id=35758898>
|
## <https://news.ycombinator.com/item?id=35758898>
|
||||||
|
|
113
src/mumble.c
113
src/mumble.c
|
@ -5,12 +5,15 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "mpc/mpc.h"
|
#include "mpc/mpc.h"
|
||||||
#define VERBOSE 0
|
#define VERBOSE 1
|
||||||
#define LISPVAL_ASSERT(cond, err) \
|
#define LISPVAL_ASSERT(cond, err) \
|
||||||
if (!(cond)) { \
|
if (!(cond)) { \
|
||||||
return lispval_err(err); \
|
return lispval_err(err); \
|
||||||
}
|
}
|
||||||
|
#define printfln(...) do { \
|
||||||
|
printf ("\n@ %s (%d): ", __FILE__, __LINE__); \
|
||||||
|
printf (__VA_ARGS__); \
|
||||||
|
} while (0)
|
||||||
// Types
|
// Types
|
||||||
|
|
||||||
// Types: Forward declarations
|
// Types: Forward declarations
|
||||||
|
@ -60,7 +63,7 @@ enum {
|
||||||
// Constructors
|
// Constructors
|
||||||
lispval* lispval_num(double x)
|
lispval* lispval_num(double x)
|
||||||
{
|
{
|
||||||
if(VERBOSE) printf("\nAllocated num");
|
if(VERBOSE) printfln("Allocated num");
|
||||||
lispval* v = malloc(sizeof(lispval));
|
lispval* v = malloc(sizeof(lispval));
|
||||||
v->type = LISPVAL_NUM;
|
v->type = LISPVAL_NUM;
|
||||||
v->count = 0;
|
v->count = 0;
|
||||||
|
@ -70,7 +73,7 @@ lispval* lispval_num(double x)
|
||||||
|
|
||||||
lispval* lispval_err(char* message)
|
lispval* lispval_err(char* message)
|
||||||
{
|
{
|
||||||
if(VERBOSE) printf("\nAllocated err");
|
if(VERBOSE) printfln("Allocated err");
|
||||||
lispval* v = malloc(sizeof(lispval));
|
lispval* v = malloc(sizeof(lispval));
|
||||||
v->type = LISPVAL_ERR;
|
v->type = LISPVAL_ERR;
|
||||||
v->count = 0;
|
v->count = 0;
|
||||||
|
@ -81,7 +84,7 @@ lispval* lispval_err(char* message)
|
||||||
|
|
||||||
lispval* lispval_sym(char* symbol)
|
lispval* lispval_sym(char* symbol)
|
||||||
{
|
{
|
||||||
if(VERBOSE) printf("\nAllocated sym");
|
if(VERBOSE) printfln("Allocated sym");
|
||||||
lispval* v = malloc(sizeof(lispval));
|
lispval* v = malloc(sizeof(lispval));
|
||||||
v->type = LISPVAL_SYM;
|
v->type = LISPVAL_SYM;
|
||||||
v->count = 0;
|
v->count = 0;
|
||||||
|
@ -91,7 +94,7 @@ lispval* lispval_sym(char* symbol)
|
||||||
}
|
}
|
||||||
|
|
||||||
lispval* lispval_func(lispbuiltin func, char* funcname){
|
lispval* lispval_func(lispbuiltin func, char* funcname){
|
||||||
if(VERBOSE) printf("\nAllocated sym");
|
if(VERBOSE) printfln("Allocated sym");
|
||||||
lispval* v = malloc(sizeof(lispval));
|
lispval* v = malloc(sizeof(lispval));
|
||||||
v->type = LISPVAL_FUNC;
|
v->type = LISPVAL_FUNC;
|
||||||
v->count = 0;
|
v->count = 0;
|
||||||
|
@ -103,7 +106,7 @@ lispval* lispval_func(lispbuiltin func, char* funcname){
|
||||||
|
|
||||||
lispval* lispval_sexpr(void)
|
lispval* lispval_sexpr(void)
|
||||||
{
|
{
|
||||||
if(VERBOSE) printf("\nAllocated sexpr");
|
if(VERBOSE) printfln("Allocated sexpr");
|
||||||
lispval* v = malloc(sizeof(lispval));
|
lispval* v = malloc(sizeof(lispval));
|
||||||
v->type = LISPVAL_SEXPR;
|
v->type = LISPVAL_SEXPR;
|
||||||
v->count = 0;
|
v->count = 0;
|
||||||
|
@ -113,7 +116,7 @@ lispval* lispval_sexpr(void)
|
||||||
|
|
||||||
lispval* lispval_qexpr(void)
|
lispval* lispval_qexpr(void)
|
||||||
{
|
{
|
||||||
if(VERBOSE) printf("\nAllocated qexpr");
|
if(VERBOSE) printfln("Allocated qexpr");
|
||||||
lispval* v = malloc(sizeof(lispval));
|
lispval* v = malloc(sizeof(lispval));
|
||||||
v->type = LISPVAL_QEXPR;
|
v->type = LISPVAL_QEXPR;
|
||||||
v->count = 0;
|
v->count = 0;
|
||||||
|
@ -122,37 +125,42 @@ lispval* lispval_qexpr(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Destructor
|
// Destructor
|
||||||
|
void print_lispval_tree(lispval* v, int indent_level);
|
||||||
void delete_lispval(lispval* v)
|
void delete_lispval(lispval* v)
|
||||||
{
|
{
|
||||||
if(v == NULL) return;
|
if(v == NULL) return;
|
||||||
|
// print_lispval_tree(v, 0);
|
||||||
switch (v->type) {
|
switch (v->type) {
|
||||||
case LISPVAL_NUM:
|
case LISPVAL_NUM:
|
||||||
if(VERBOSE) printf("\nFreed num");
|
if(VERBOSE) printfln("Freeing num");
|
||||||
break;
|
break;
|
||||||
case LISPVAL_ERR:
|
case LISPVAL_ERR:
|
||||||
if(VERBOSE) printf("\nFreed err");
|
if(VERBOSE) printfln("Freeing err");
|
||||||
if (v->err != NULL)
|
if (v->err != NULL)
|
||||||
free(v->err);
|
free(v->err);
|
||||||
v->err = NULL;
|
v->err = NULL;
|
||||||
|
if(VERBOSE) printfln("Freed err");
|
||||||
break;
|
break;
|
||||||
case LISPVAL_SYM:
|
case LISPVAL_SYM:
|
||||||
if(VERBOSE) printf("\nFreed sym");
|
if(VERBOSE) printfln("Freeing sym");
|
||||||
if (v->sym != NULL)
|
if (v->sym != NULL)
|
||||||
free(v->sym);
|
free(v->sym);
|
||||||
v->sym = NULL;
|
v->sym = NULL;
|
||||||
|
if(VERBOSE) printfln("Freed sym");
|
||||||
break;
|
break;
|
||||||
case LISPVAL_FUNC:
|
case LISPVAL_FUNC:
|
||||||
if(VERBOSE) printf("\nFreed func");
|
if(VERBOSE) printfln("Freeing func");
|
||||||
if (v->funcname != NULL)
|
if (v->funcname != NULL)
|
||||||
free(v->funcname);
|
free(v->funcname);
|
||||||
v->funcname = NULL;
|
v->funcname = NULL;
|
||||||
|
if(VERBOSE) printfln("Freed func");
|
||||||
// Don't do anything with v->func for now
|
// Don't do anything with v->func for now
|
||||||
// Though we could delete the pointer to the function later
|
// Though we could delete the pointer to the function later
|
||||||
// free(v->func);
|
// free(v->func);
|
||||||
break;
|
break;
|
||||||
case LISPVAL_SEXPR:
|
case LISPVAL_SEXPR:
|
||||||
case LISPVAL_QEXPR:
|
case LISPVAL_QEXPR:
|
||||||
if(VERBOSE) printf("\nFreed s/qexpr");
|
if(VERBOSE) printfln("Freeing sexpr|qexpr");
|
||||||
for (int i = 0; i < v->count; i++) {
|
for (int i = 0; i < v->count; i++) {
|
||||||
if (v->cell[i] != NULL)
|
if (v->cell[i] != NULL)
|
||||||
delete_lispval(v->cell[i]);
|
delete_lispval(v->cell[i]);
|
||||||
|
@ -161,7 +169,10 @@ void delete_lispval(lispval* v)
|
||||||
if (v->cell != NULL)
|
if (v->cell != NULL)
|
||||||
free(v->cell);
|
free(v->cell);
|
||||||
v->cell = NULL;
|
v->cell = NULL;
|
||||||
|
if(VERBOSE) printfln("Freed sexpr|qexpr");
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
if(VERBOSE) printfln("Error: Unknown expression type.");
|
||||||
}
|
}
|
||||||
if (v != NULL)
|
if (v != NULL)
|
||||||
free(v);
|
free(v);
|
||||||
|
@ -262,7 +273,7 @@ lispval* read_lispval(mpc_ast_t* t)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (VERBOSE)
|
if (VERBOSE)
|
||||||
printf("\nNon ignorable children: %i", c);
|
printfln("Non ignorable children: %i", c);
|
||||||
|
|
||||||
if (strstr(t->tag, "number")) {
|
if (strstr(t->tag, "number")) {
|
||||||
return read_lispval_num(t);
|
return read_lispval_num(t);
|
||||||
|
@ -305,74 +316,79 @@ lispval* read_lispval(mpc_ast_t* t)
|
||||||
// Print
|
// Print
|
||||||
void print_lispval_tree(lispval* v, int indent_level)
|
void print_lispval_tree(lispval* v, int indent_level)
|
||||||
{
|
{
|
||||||
char* indent = malloc(sizeof(char) * (indent_level + 1));
|
char* indent = " ";/*malloc(sizeof(char) * (indent_level + 1));
|
||||||
for (int i = 0; i < indent_level; i++) {
|
for (int i = 0; i < indent_level; i++) {
|
||||||
indent[i] = ' ';
|
indent[i] = ' ';
|
||||||
}
|
}
|
||||||
indent[indent_level] = '\0';
|
indent[indent_level] = '\0';*/
|
||||||
|
|
||||||
switch (v->type) {
|
switch (v->type) {
|
||||||
case LISPVAL_NUM:
|
case LISPVAL_NUM:
|
||||||
printf("\n%sNumber: %f", indent, v->num);
|
printfln("%sNumber: %f", indent, v->num);
|
||||||
break;
|
break;
|
||||||
case LISPVAL_ERR:
|
case LISPVAL_ERR:
|
||||||
printf("\n%sError: %s", indent, v->err);
|
printfln("%sError: %s", indent, v->err);
|
||||||
break;
|
break;
|
||||||
case LISPVAL_SYM:
|
case LISPVAL_SYM:
|
||||||
printf("\n%sSymbol: %s", indent, v->sym);
|
printfln("%sSymbol: %s", indent, v->sym);
|
||||||
|
break;
|
||||||
|
case LISPVAL_FUNC:
|
||||||
|
printfln("%sFunction, name: %s, pointer: %p", indent, v->funcname, v->func);
|
||||||
break;
|
break;
|
||||||
case LISPVAL_SEXPR:
|
case LISPVAL_SEXPR:
|
||||||
printf("\n%sSExpr, with %d children:", indent, v->count);
|
printfln("%sSExpr, with %d children:", indent, v->count);
|
||||||
for (int i = 0; i < v->count; i++) {
|
for (int i = 0; i < v->count; i++) {
|
||||||
print_lispval_tree(v->cell[i], indent_level + 2);
|
print_lispval_tree(v->cell[i], indent_level + 2);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case LISPVAL_QEXPR:
|
case LISPVAL_QEXPR:
|
||||||
printf("\n%sQExpr, with %d children:", indent, v->count);
|
printfln("%sQExpr, with %d children:", indent, v->count);
|
||||||
for (int i = 0; i < v->count; i++) {
|
for (int i = 0; i < v->count; i++) {
|
||||||
print_lispval_tree(v->cell[i], indent_level + 2);
|
print_lispval_tree(v->cell[i], indent_level + 2);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printf("Error: unknown lispval type\n");
|
printfln("Error: unknown lispval type\n");
|
||||||
printf("%s", v->sym);
|
// printfln("%s", v->sym);
|
||||||
}
|
}
|
||||||
free(indent);
|
// printfln("Freeing indent");
|
||||||
indent = NULL;
|
// if (indent!=NULL) free(indent);
|
||||||
|
printfln("Freed indent");
|
||||||
|
// indent = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_lispval_parenthesis(lispval* v)
|
void print_lispval_parenthesis(lispval* v)
|
||||||
{
|
{
|
||||||
switch (v->type) {
|
switch (v->type) {
|
||||||
case LISPVAL_NUM:
|
case LISPVAL_NUM:
|
||||||
printf("%f ", v->num);
|
printfln("%f ", v->num);
|
||||||
break;
|
break;
|
||||||
case LISPVAL_ERR:
|
case LISPVAL_ERR:
|
||||||
printf("%s ", v->err);
|
printfln("%s ", v->err);
|
||||||
break;
|
break;
|
||||||
case LISPVAL_SYM:
|
case LISPVAL_SYM:
|
||||||
printf("%s ", v->sym);
|
printfln("%s ", v->sym);
|
||||||
break;
|
break;
|
||||||
case LISPVAL_FUNC:
|
case LISPVAL_FUNC:
|
||||||
printf("<function name: %s pointer: %p>", v->funcname, v->func);
|
printfln("<function name: %s pointer: %p>", v->funcname, v->func);
|
||||||
break;
|
break;
|
||||||
case LISPVAL_SEXPR:
|
case LISPVAL_SEXPR:
|
||||||
printf("( ");
|
printfln("( ");
|
||||||
for (int i = 0; i < v->count; i++) {
|
for (int i = 0; i < v->count; i++) {
|
||||||
print_lispval_parenthesis(v->cell[i]);
|
print_lispval_parenthesis(v->cell[i]);
|
||||||
}
|
}
|
||||||
printf(") ");
|
printfln(") ");
|
||||||
break;
|
break;
|
||||||
case LISPVAL_QEXPR:
|
case LISPVAL_QEXPR:
|
||||||
printf("{ ");
|
printfln("{ ");
|
||||||
for (int i = 0; i < v->count; i++) {
|
for (int i = 0; i < v->count; i++) {
|
||||||
print_lispval_parenthesis(v->cell[i]);
|
print_lispval_parenthesis(v->cell[i]);
|
||||||
}
|
}
|
||||||
printf("} ");
|
printfln("} ");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printf("Error: unknown lispval type\n");
|
printfln("Error: unknown lispval type\n");
|
||||||
printf("%s", v->sym);
|
// printfln("%s", v->sym);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -383,14 +399,14 @@ void print_ast(mpc_ast_t* ast, int indent_level)
|
||||||
indent[i] = ' ';
|
indent[i] = ' ';
|
||||||
}
|
}
|
||||||
indent[indent_level] = '\0';
|
indent[indent_level] = '\0';
|
||||||
printf("\n%sTag: %s", indent, ast->tag);
|
printfln("%sTag: %s", indent, ast->tag);
|
||||||
printf("\n%sContents: %s", indent,
|
printfln("%sContents: %s", indent,
|
||||||
strcmp(ast->contents, "") ? ast->contents : "None");
|
strcmp(ast->contents, "") ? ast->contents : "None");
|
||||||
printf("\n%sNumber of children: %i", indent, ast->children_num);
|
printfln("%sNumber of children: %i", indent, ast->children_num);
|
||||||
/* Print the children */
|
/* Print the children */
|
||||||
for (int i = 0; i < ast->children_num; i++) {
|
for (int i = 0; i < ast->children_num; i++) {
|
||||||
mpc_ast_t* child_i = ast->children[i];
|
mpc_ast_t* child_i = ast->children[i];
|
||||||
printf("\n%sChild #%d", indent, i);
|
printfln("%sChild #%d", indent, i);
|
||||||
print_ast(child_i, indent_level + 2);
|
print_ast(child_i, indent_level + 2);
|
||||||
}
|
}
|
||||||
free(indent);
|
free(indent);
|
||||||
|
@ -462,7 +478,7 @@ lispval* take_lispval(lispval* v, int i)
|
||||||
// Ops for q-expressions
|
// Ops for q-expressions
|
||||||
lispval* builtin_head(lispval* v)
|
lispval* builtin_head(lispval* v)
|
||||||
{
|
{
|
||||||
// printf("Entering builtin_head with v->count = %d and v->cell[0]->type = %d\n", v->count, v->cell[0]->type);
|
// printfln("Entering builtin_head with v->count = %d and v->cell[0]->type = %d\n", v->count, v->cell[0]->type);
|
||||||
// head { 1 2 3 }
|
// head { 1 2 3 }
|
||||||
// But actually, that gets processd into head ({ 1 2 3 }), hence the v->cell[0]->cell[0];
|
// But actually, that gets processd into head ({ 1 2 3 }), hence the v->cell[0]->cell[0];
|
||||||
LISPVAL_ASSERT(v->count == 1, "Error: function head passed too many arguments");
|
LISPVAL_ASSERT(v->count == 1, "Error: function head passed too many arguments");
|
||||||
|
@ -745,18 +761,18 @@ int main(int argc, char** argv)
|
||||||
|
|
||||||
// Print AST if VERBOSE
|
// Print AST if VERBOSE
|
||||||
if (VERBOSE) {
|
if (VERBOSE) {
|
||||||
printf("\nPrinting AST");
|
printfln("Printing AST");
|
||||||
print_ast(ast, 0);
|
print_ast(ast, 0);
|
||||||
}
|
}
|
||||||
// Evaluate the AST
|
// Evaluate the AST
|
||||||
if(VERBOSE) printf("\n\nEvaluating the AST");
|
if(VERBOSE) printfln("\nEvaluating the AST");
|
||||||
// lispval result = evaluate_ast(ast);
|
// lispval result = evaluate_ast(ast);
|
||||||
lispval* l = read_lispval(ast);
|
lispval* l = read_lispval(ast);
|
||||||
if (VERBOSE) {
|
if (VERBOSE) {
|
||||||
printf("\n\nPrinting initially parsed lispvalue");
|
printfln("\nPrinting initially parsed lispvalue");
|
||||||
printf("\nTree printing: ");
|
printfln("Tree printing: ");
|
||||||
print_lispval_tree(l, 2);
|
print_lispval_tree(l, 2);
|
||||||
printf("\nParenthesis printing: ");
|
printfln("Parenthesis printing: ");
|
||||||
print_lispval_parenthesis(l);
|
print_lispval_parenthesis(l);
|
||||||
}
|
}
|
||||||
// Create an environment
|
// Create an environment
|
||||||
|
@ -765,12 +781,13 @@ int main(int argc, char** argv)
|
||||||
// Eval the lispval in that environment.
|
// Eval the lispval in that environment.
|
||||||
lispval* answer = evaluate_lispval(l, env);
|
lispval* answer = evaluate_lispval(l, env);
|
||||||
{
|
{
|
||||||
printf("\n\nResult: ");
|
printfln("Result: ");
|
||||||
print_lispval_parenthesis(answer);
|
print_lispval_parenthesis(answer);
|
||||||
|
print_lispval_tree(answer, 0);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
delete_lispval(l);
|
// delete_lispval(l);
|
||||||
delete_lispval(answer);
|
// delete_lispval(answer);
|
||||||
|
|
||||||
// Clean up environment
|
// Clean up environment
|
||||||
destroy_lispenv(env);
|
destroy_lispenv(env);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user