Compare commits

...

5 Commits

8 changed files with 152 additions and 55 deletions

View File

@ -1,7 +1,7 @@
0. Create file to describe properties of terminology used; param, arg, var, &c.
1. Differenciate parameters and arguments -- params for function definitions,
1. Differentiate parameters and arguments -- params for function definitions,
arguments for function calls
2. Add scope field to all ASTs, and new scope layer for those that need it.
Change editor to GNU Readline.
Make variables persist through lines in the editor.
Return syntax errors as exceptions.

View File

@ -17,7 +17,9 @@ static char* asttype_names[] = {
[AST_TYPE_BLOCK] = "BLOCK",
[AST_TYPE_EXC] = "EXCEPTION",
[AST_TYPE_FDEF] = "FUNCTION DEFINITION",
[AST_TYPE_ARG] = "DEFINITION ARGUMENT"
[AST_TYPE_ARG] = "DEFINITION ARGUMENT",
[AST_TYPE_LAMBDA] = "LAMBDA EXPRESSION"
};
AST* ast_init(ASTType type, void* data) {
@ -51,13 +53,14 @@ void ast_destroy(AST* ast) {
if (!ast) return;
switch (ast->type) {
case AST_TYPE_NUM: ast_num_data_destroy(ast->data); break;
case AST_TYPE_CALL: ast_call_data_destroy(ast->data); break;
case AST_TYPE_VREF: ast_vref_data_destroy(ast->data); break;
case AST_TYPE_VDEF: ast_vdef_data_destroy(ast->data); break;
case AST_TYPE_BLOCK: ast_block_data_destroy(ast->data); break;
case AST_TYPE_FDEF: ast_fdef_data_destroy(ast->data); break;
case AST_TYPE_ARG: ast_arg_data_destroy(ast->data); break;
case AST_TYPE_NUM: ast_num_data_destroy(ast->data); break;
case AST_TYPE_CALL: ast_call_data_destroy(ast->data); break;
case AST_TYPE_VREF: ast_vref_data_destroy(ast->data); break;
case AST_TYPE_VDEF: ast_vdef_data_destroy(ast->data); break;
case AST_TYPE_BLOCK: ast_block_data_destroy(ast->data); break;
case AST_TYPE_FDEF: ast_fdef_data_destroy(ast->data); break;
case AST_TYPE_ARG: ast_arg_data_destroy(ast->data); break;
case AST_TYPE_LAMBDA: ast_lambda_data_destroy(ast->data); break;
default:
log_dbgf("Unknown ast type %d (max: %d)", ast->type, AST_TYPE_MAX);
}
@ -72,15 +75,16 @@ void ast_destroy_psv(AST* ast) {
if (!ast) return;
switch (ast->type) {
case AST_TYPE_NUM: ast_num_data_destroy(ast->data); break;
case AST_TYPE_CALL: ast_call_data_destroy_psv(ast->data); break;
case AST_TYPE_VREF: ast_vref_data_destroy(ast->data); break;
case AST_TYPE_VDEF: ast_vdef_data_destroy_psv(ast->data); break;
case AST_TYPE_BLOCK: ast_block_data_destroy_psv(ast->data); break;
case AST_TYPE_FDEF: ast_fdef_data_destroy_psv(ast->data); break;
case AST_TYPE_ARG: ast_arg_data_destroy(ast->data); break;
case AST_TYPE_BIF: ast_bif_data_destroy(ast->data); break;
case AST_TYPE_EXC: ast_exc_data_destroy(ast->data); break;
case AST_TYPE_NUM: ast_num_data_destroy(ast->data); break;
case AST_TYPE_CALL: ast_call_data_destroy_psv(ast->data); break;
case AST_TYPE_VREF: ast_vref_data_destroy(ast->data); break;
case AST_TYPE_VDEF: ast_vdef_data_destroy_psv(ast->data); break;
case AST_TYPE_BLOCK: ast_block_data_destroy_psv(ast->data); break;
case AST_TYPE_FDEF: ast_fdef_data_destroy_psv(ast->data); break;
case AST_TYPE_ARG: ast_arg_data_destroy(ast->data); break;
case AST_TYPE_BIF: ast_bif_data_destroy(ast->data); break;
case AST_TYPE_EXC: ast_exc_data_destroy(ast->data); break;
case AST_TYPE_LAMBDA: ast_lambda_data_destroy(ast->data); break;
default:
log_dbgf("Unknown ast type %d (max: %d)", ast->type, AST_TYPE_MAX);
}
@ -104,14 +108,15 @@ void ast_print_i(AST* ast, int i) {
case AST_TYPE_NUM:
printf("%s %lf\n", INDENT_spacing->buf, *(ASTNumData*)ast->data);
break;
case AST_TYPE_CALL: ast_call_print(ast->data, i + 2); break;
case AST_TYPE_EXC: ast_exc_print(ast->data, i + 2); break;
case AST_TYPE_VREF: ast_vref_print(ast->data, i + 2); break;
case AST_TYPE_VDEF: ast_vdef_print(ast->data, i + 2); break;
case AST_TYPE_BLOCK: ast_block_print(ast->data, i + 2); break;
case AST_TYPE_FDEF: ast_fdef_print(ast->data, i + 2); break;
case AST_TYPE_ARG: ast_arg_print(ast->data, i + 2); break;
default: exit(1);
case AST_TYPE_CALL: ast_call_print(ast->data, i + 2); break;
case AST_TYPE_EXC: ast_exc_print(ast->data, i + 2); break;
case AST_TYPE_VREF: ast_vref_print(ast->data, i + 2); break;
case AST_TYPE_VDEF: ast_vdef_print(ast->data, i + 2); break;
case AST_TYPE_BLOCK: ast_block_print(ast->data, i + 2); break;
case AST_TYPE_FDEF: ast_fdef_print(ast->data, i + 2); break;
case AST_TYPE_ARG: ast_arg_print(ast->data, i + 2); break;
case AST_TYPE_LAMBDA: ast_lambda_print(ast->data, i + 2); break;
default: exit(1);
}
INDENT_FIELD_NONL_END;
INDENT_END;
@ -344,6 +349,32 @@ void ast_arg_print(ASTArgData* arg, int i) {
INDENT_END;
}
ASTLambdaData* ast_lambda_data_init(size_t argc, AST** argv, AST* body) {
talloc(ASTLambdaData, lambda);
lambda->argc = argc;
lambda->argv = argv;
lambda->body = body;
return lambda;
}
void ast_lambda_data_destroy(ASTLambdaData* lambda) {
free(lambda->argv);
free(lambda);
}
void ast_lambda_print(ASTLambdaData* lambda, int i) {
INDENT_BEGIN(i)
INDENT_TITLE("ASTLambdaData", lambda);
INDENT_FIELD("argc", "%ld", lambda->argc);
INDENT_FIELD_LIST("argv", lambda->argv, lambda->argc, ast_print_i);
INDENT_FIELD_EXT_NONL_START("body");
ast_print_i(lambda->body, i + 2);
INDENT_FIELD_NONL_END;
INDENT_END;
}
AST* ast_find(Scope* scope, char* name) {
while (scope) {
AST* gotten = htab_get(scope->here, name);

View File

@ -39,10 +39,11 @@ AST* exec_exp(AST* ast, Scope* parent) {
return ast_init(
AST_TYPE_NUM, ast_num_data_init(*(ASTNumData*)ast->data)
);
case AST_TYPE_VREF: return exec_vref(ast, parent);
case AST_TYPE_VDEF: return exec_vdef(ast, parent);
case AST_TYPE_FDEF: return exec_fdef(ast, parent);
default: printf("what\n"); exit(1);
case AST_TYPE_VREF: return exec_vref(ast, parent);
case AST_TYPE_VDEF: return exec_vdef(ast, parent);
case AST_TYPE_FDEF: return exec_fdef(ast, parent);
case AST_TYPE_LAMBDA: return exec_lambda(ast, parent);
default: printf("what\n"); exit(1);
}
}
@ -79,7 +80,8 @@ AST* exec_call(AST* ast, Scope* parent) {
case AST_TYPE_BIF:
ASTBIFData bifdata = fdef->data;
return bifdata(argc, argv, parent);
case AST_TYPE_FDEF: return exec_cf(fdef, argc, argv);
case AST_TYPE_FDEF: return exec_cf(fdef, argc, argv);
case AST_TYPE_LAMBDA: return exec_lambda_call(fdef, argc, argv);
default:
return ast_init(AST_TYPE_EXC, ast_exc_data_init("Good job!", NULL));
}
@ -132,14 +134,29 @@ AST* exec_vref(AST* ast, Scope* parent) {
AST* exec_fdef(AST* ast, Scope* parent) {
ast->scope = scope_init(parent);
ASTFDefData* fdef = (ASTFDefData*)ast->data;
log_dbgf("IS THIS SUSPICIOUS??? %i", fdef->body->type);
AST* val = ast;
char* key = fdef->name;
scope_add(parent, key, val);
// TODO: Create lambda functions.
return fdef->body; // Function definitions return function body.
}
AST* exec_lambda(AST* ast, Scope* parent) {
// Executing a lambda on its own with no arguments returns itself.
return ast;
}
AST* exec_lambda_call(AST* ast, size_t argc, AST** argv) {
Scope* callscope = scope_init(ast->scope);
ASTFDefData* lambda = (ASTFDefData*)ast->data;
for (int i = 0; i < argc; i++) {
char* key = ((ASTArgData*)lambda->argv[i]->data)->name;
AST* val = argv[i];
scope_add(callscope, key, val);
}
return exec_exp(lambda->body, callscope);
}
void exec_print(double n) { printf("= %lf\n", n); }
inline void exec_new_scope(AST* ast, Scope* inherit) {

View File

@ -47,6 +47,8 @@
%token NL // Newline.
%token BACKSLASH
%left ADD SUB
%left MUL DIV
%precedence NEG
@ -125,13 +127,31 @@ exp:
NUM { $$ = ast_init(AST_TYPE_NUM, ast_num_data_init($1)); }
// Function definitions.
| WORD GROUPS arg GROUPE EQ exp {
| WORD GROUPS arg GROUPE exp {
size_t argc = $3->ln;
AST** argv = $3->buf;
argarr_destroypsv($3);
$$ = ast_init(AST_TYPE_FDEF, ast_fdef_data_init($1, argc, argv, $6));
$$ = ast_init(AST_TYPE_FDEF, ast_fdef_data_init($1, argc, argv, $5));
}
// Lambda definitions.
| BACKSLASH GROUPS arg GROUPE exp {
size_t argc = $3->ln;
AST** argv = $3->buf;
argarr_destroypsv($3);
$$ = ast_init(AST_TYPE_LAMBDA, ast_lambda_data_init(argc, argv, $5));
}
/*
// Inline call.
| exp GROUPS arg GROUPE {
size_t argc = $3->ln;
AST** argv = $3->buf;
argarr_destroypsv($3);
$$ = ast_init(AST_TYPE_CALL, ($1, argc, argv));
}
*/
| BLOCKS block BLOCKE {
$$ = ast_init(AST_TYPE_BLOCK, ast_block_data_init((AST**) $2->buf, $2->ln));
}

View File

@ -18,13 +18,14 @@ typedef enum {
AST_TYPE_LIST, // A list (variable size, variable type).
// Misc. types.
AST_TYPE_BIF, // Built-in function.
AST_TYPE_CALL, // A function call.
AST_TYPE_VDEF, // A variable definition.
AST_TYPE_VREF, // A variable reference.
AST_TYPE_BLOCK, // A block of code (scope).
AST_TYPE_FDEF, // A function definition.
AST_TYPE_ARG, // A definition argument.
AST_TYPE_BIF, // Built-in function.
AST_TYPE_CALL, // A function call.
AST_TYPE_VDEF, // A variable definition.
AST_TYPE_VREF, // A variable reference.
AST_TYPE_BLOCK, // A block of code (scope).
AST_TYPE_FDEF, // A function definition.
AST_TYPE_LAMBDA, // An anonymous function definition.
AST_TYPE_ARG, // A definition argument.
AST_TYPE_MAX = AST_TYPE_ARG,
} ASTType;
@ -60,8 +61,8 @@ void ast_num_print(ASTNumData*, int i);
// An exception.
typedef struct ASTEXCDATA {
const char* msg; // The exception message.
AST* trace; // The previous exception.
const char* msg; // The exception message.
AST* trace; // The previous exception.
} ASTExcData;
// Create a new `ASTExecData. `msg` should be static.
ASTExcData* ast_exc_data_init(const char* msg, AST* trace);
@ -70,6 +71,13 @@ void ast_exc_data_destroy(ASTExcData* exc);
// Print an `ASTExecData`.
void ast_exc_print(ASTExcData*, int i);
// arguments list as anonymous struct
#define ARGS \
struct { \
size_t argc; \
AST** argv; \
}
// A built-in function.
typedef AST* (*ASTBIFData)(size_t argc, AST** argv, Scope* scope);
@ -80,9 +88,8 @@ void ast_bif_data_destroy(ASTBIFData* bif);
// A call (to a function).
typedef struct {
char* to; // What the call's to.
size_t argc; // Argument count.
AST** argv; // Argument vector.
char* to; // What the call's to.
ARGS; // argument list
} ASTCallData;
// Create a new `ASTCallData`.
@ -90,7 +97,7 @@ ASTCallData* ast_call_data_init(char* to, size_t argc, AST** argv);
// Destroy an `ASTCallData` recursively.
void ast_call_data_destroy(ASTCallData* call);
// Destroy an `ASTCallData`.
void ast_call_data_destroy_psv(ASTCallData *call);
void ast_call_data_destroy_psv(ASTCallData* call);
// Print an `ASTCallData`.
void ast_call_print(ASTCallData*, int i);
@ -132,15 +139,14 @@ ASTBlockData* ast_block_data_init(AST** inside, size_t ln);
// Destroy an `ASTBlockData`, recursively.
void ast_block_data_destroy(ASTBlockData* block);
// Destroy an `ASTBlockData`.
void ast_block_data_destroy_psv(ASTBlockData *block);
void ast_block_data_destroy_psv(ASTBlockData* block);
// Print an `ASTBlockData`.
void ast_block_print(ASTBlockData*, int i);
typedef struct {
char* name; // Function name.
size_t argc; // Argument count.
AST** argv; // Argument vector.
AST* body; // Function body.
char* name; // Function name.
ARGS; // Function args.
AST* body; // Function body.
} ASTFDefData;
// Create a new `ASTFDefData`.
@ -163,6 +169,19 @@ void ast_arg_data_destroy(ASTArgData* arg);
// Print an `ASTArgData`.
void ast_arg_print(ASTArgData* arg, int i);
// Represents a function as data.
typedef struct {
ARGS;
AST* body;
} ASTLambdaData;
// Creates a new `ASTLambdaData`.
ASTLambdaData* ast_lambda_data_init(size_t argc, AST** argv, AST* body);
// Destroy an `ASTLambdaData`.
void ast_lambda_data_destroy(ASTLambdaData*);
// Print an `ASTLambdaData`.
void ast_lambda_print(ASTLambdaData* arg, int i);
// Find a name in the scope.
AST* ast_find(Scope* scope, char* name);

View File

@ -20,6 +20,10 @@ AST* exec_vdef(AST* ast, Scope* parent);
AST* exec_vref(AST* ast, Scope* parent);
// Execute a function definition.
AST* exec_fdef(AST* ast, Scope* parent);
// Execute a lambda expression.
AST* exec_lambda(AST* ast, Scope* parent);
// Execute a lambda call.
AST* exec_lambda_call(AST* ast, size_t argc, AST** argv);
// Print the result of an execution.
void exec_print(double n);

View File

@ -1,6 +1,8 @@
#ifndef UTIL_H
#define UTIL_H
#include <signal.h>
// Most of this file is cursed printing macros for `ast_print()`. Do not attempt
// to comprehend.
@ -10,6 +12,9 @@
// Get the length of an array.
#define arrln(A) (sizeof(A)/sizeof(*A))
// Trap GDB &c.
#define TRAP() RAISE(SIGTRAP)
#ifdef DBG // Debug macros
// Log a message.

View File

@ -116,6 +116,7 @@ int yylex() {
case '{': return BLOCKS;
case '}': return BLOCKE;
case '=': return EQ;
case '\\': return BACKSLASH;
default: fprintf(stderr, "Unexpected character: %c\n", c);
}