Files
lambda/lc.c
2026-04-09 23:27:34 -07:00

145 lines
3.6 KiB
C

#include "lc.h"
#include "util.h"
#include <stdarg.h>
#include <stdbool.h>
static LambdaTerm *make_variable(char *name, size_t name_len) {
LambdaTerm *term = malloc_safe(sizeof(LambdaTerm));
term->type = TYPE_VARIABLE;
term->v.name = name;
term->v.name_len = name_len;
return term;
}
static LambdaTerm *make_lambda(char *arg, size_t arg_len, LambdaTerm *body) {
LambdaTerm *term = malloc_safe(sizeof(LambdaTerm));
term->type = TYPE_LAMBDA;
term->l.arg = arg;
term->l.arg_len = arg_len;
term->l.body = body;
return term;
}
static LambdaTerm *make_apply(LambdaTerm *func, LambdaTerm *arg) {
LambdaTerm *term = malloc_safe(sizeof(LambdaTerm));
term->type = TYPE_APPLY;
term->a.func = func;
term->a.arg = arg;
return term;
}
static bool is_lambda_term_token(const Token *tok) {
switch (tok->type) {
case TOKEN_BACKSLASH:
case TOKEN_OPEN_PAREN:
case TOKEN_CLOSE_PAREN:
case TOKEN_IDENT:
return true;
case TOKEN_LET:
case TOKEN_EVAL:
case TOKEN_CONF:
case TOKEN_EQUALS:
case TOKEN_COLON:
case TOKEN_DEFINE:
case TOKEN_REDUCE:
case TOKEN_EOF:
return false;
default:
abort();
}
}
enum OperatorType {
OPER_APPLY,
OPER_DEFINE,
};
struct OperatorStack {
struct OperatorStack *next;
Token src;
enum OperatorType type;
};
static struct OperatorStack *push_oper(struct OperatorStack *restrict stack,
const Token *restrict src,
enum OperatorType type) {
struct OperatorStack *new = malloc_safe(sizeof(struct OperatorStack));
new->next = stack;
new->src = *src;
new->type = type;
return new;
}
enum OperandType {
OPAND_TERM,
OPAND_OPEN_PAREN,
OPAND_DEF_BEGIN,
};
struct OperandStack {
struct OperandStack *next;
Token src;
enum OperandType type;
LambdaTerm *term;
};
static struct OperandStack *push_opand(struct OperandStack *restrict stack,
const Token *restrict src,
enum OperandType type, ...) {
struct OperandStack *new = malloc_safe(sizeof(struct OperandStack));
new->next = stack;
new->src = *src;
new->type = type;
if (type == OPAND_TERM) {
va_list args;
va_start(args, type);
new->term = va_arg(args, LambdaTerm *);
va_end(args);
}
return new;
}
static void apply_one(struct OperatorStack **oper_stack,
struct OperandStack **opand_stack,
ParseError *restrict err_out) {
if (!*oper_stack) {
abort();
} else if () {
}
}
LambdaTerm *read_lambda_term(TokenStream *restrict stream,
ParseError *restrict err_out) {
ParseError backup_err;
if (!err_out) {
err_out = &backup_err;
}
struct OperatorStack *oper_stack = NULL;
struct OperandStack *opand_stack = NULL;
Token tok;
while (true) {
if (!token_stream_peek(stream, &tok, err_out)) {
return false;
} else if (!is_lambda_term_token(&tok)) {
break;
}
token_stream_discard(stream, NULL);
switch (tok.type) {
case TOKEN_OPEN_PAREN:
opand_stack = push_opand(opand_stack, OPAND_OPEN_PAREN);
break;
case TOKEN_BACKSLASH:
opand_stack = push_opand(opand_stack, OPAND_DEF_BEGIN);
break;
case TOKEN_CLOSE_PAREN:
case TOKEN_IDENT:
case TOKEN_DEFINE:
break;
default:
abort();
}
}
}