Some work

This commit is contained in:
2026-04-09 23:27:34 -07:00
parent 0671e17e8e
commit 52e421d0c9
7 changed files with 218 additions and 7 deletions

View File

@@ -5,7 +5,7 @@ CFLAGS=-std=c11 -D_FILE_OFFSET_BITS=64 -D_POSIX_C_SOURCE=200112L -Wall -Wextra $
LD=gcc LD=gcc
LDFLAGS=$(DEBUG_FLAGS) LDFLAGS=$(DEBUG_FLAGS)
lambda: main.o token.o lc.o lambda: main.o token.o lc.o util.o
$(LD) $(LDFLAGS) -o $@ $^ $(LD) $(LDFLAGS) -o $@ $^
%.o: %.c %.o: %.c
@@ -19,4 +19,5 @@ clean:
# Dependencies # Dependencies
main.o: token.h lc.h main.o: token.h lc.h
token.o: token.h util.h token.o: token.h util.h
lc.o: lc.h token.h lc.o: lc.h token.h util.h
util.o: util.h

143
lc.c
View File

@@ -1 +1,144 @@
#include "lc.h" #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();
}
}
}

17
lc.h
View File

@@ -1,6 +1,8 @@
#ifndef INCLUDED_TERM_H #ifndef INCLUDED_TERM_H
#define INCLUDED_TERM_H #define INCLUDED_TERM_H
#include "token.h"
#include <stddef.h> #include <stddef.h>
typedef enum { typedef enum {
@@ -14,17 +16,22 @@ struct _LambdaTerm {
LambdaTermType type; LambdaTermType type;
union { union {
struct { struct {
char name; char *name;
size_t name_len;
} v; } v;
struct { struct {
char argument; char *arg;
size_t arg_len;
LambdaTerm *body; LambdaTerm *body;
} l; } l;
struct { struct {
char function; LambdaTerm *func;
LambdaTerm *argument; LambdaTerm *arg;
}; } a;
}; };
}; };
LambdaTerm *read_lambda_term(TokenStream *restrict stream,
ParseError *restrict err_out);
#endif #endif

34
token.c
View File

@@ -136,11 +136,32 @@ static bool read_next_ident(TokenStream *restrict stream, Token *restrict out);
static bool read_next_reduce(TokenStream *restrict stream, Token *restrict out, static bool read_next_reduce(TokenStream *restrict stream, Token *restrict out,
ParseError *restrict error); ParseError *restrict error);
bool token_stream_peek(TokenStream *restrict stream, Token *restrict out,
ParseError *restrict error) {
if (error) {
error->set = false;
}
if (!stream->has_buffer) {
bool res = token_stream_next(stream, &stream->buffer, error);
if (!res) {
return false;
}
stream->has_buffer = true;
}
*out = stream->buffer;
return true;
}
bool token_stream_next(TokenStream *restrict stream, Token *restrict out, bool token_stream_next(TokenStream *restrict stream, Token *restrict out,
ParseError *restrict error) { ParseError *restrict error) {
if (error) { if (error) {
error->set = false; error->set = false;
} }
if (stream->has_buffer) {
stream->has_buffer = false;
*out = stream->buffer;
return true;
}
restart: restart:
skip_whitespace(stream); skip_whitespace(stream);
int c = peekc(stream); int c = peekc(stream);
@@ -232,3 +253,16 @@ static bool read_next_reduce(TokenStream *restrict stream, Token *restrict out,
return false; return false;
} }
} }
bool token_stream_discard(TokenStream *restrict stream,
ParseError *restrict error) {
if (stream->has_buffer) {
stream->has_buffer = false;
if (error) {
error->set = false;
}
return true;
}
Token tok;
return token_stream_next(stream, &tok, error);
}

View File

@@ -50,6 +50,9 @@ typedef struct {
SrcPos pos; SrcPos pos;
const char *src; const char *src;
size_t src_len; size_t src_len;
bool has_buffer;
Token buffer;
} TokenStream; } TokenStream;
typedef struct { typedef struct {
@@ -66,6 +69,7 @@ inline static void token_stream_init(TokenStream *stream, const char *src,
stream->pos.line_offset = 0; stream->pos.line_offset = 0;
stream->src = src; stream->src = src;
stream->src_len = src_len; stream->src_len = src_len;
stream->has_buffer = false;
} }
inline static bool token_stream_is_eof(TokenStream *stream) { inline static bool token_stream_is_eof(TokenStream *stream) {
@@ -73,8 +77,13 @@ inline static bool token_stream_is_eof(TokenStream *stream) {
} }
// return true on success, false on error // return true on success, false on error
bool token_stream_peek(TokenStream *restrict stream, Token *restrict out,
ParseError *restrict error);
bool token_stream_next(TokenStream *restrict stream, Token *restrict out, bool token_stream_next(TokenStream *restrict stream, Token *restrict out,
ParseError *restrict error); ParseError *restrict error);
bool token_stream_discard(TokenStream *restrict stream,
ParseError *restrict error);
static inline void parse_error_clear(ParseError *error) { static inline void parse_error_clear(ParseError *error) {
error->set = false; error->set = false;
} }

13
util.c Normal file
View File

@@ -0,0 +1,13 @@
#include "util.h"
#include <stdio.h>
void *malloc_safe(size_t size) {
void *ptr = malloc(size);
if (!ptr && size) {
static char message[] = "out of memory!\n";
fwrite(message, 1, sizeof(message) - 1, stdout);
abort();
}
return ptr;
}

4
util.h
View File

@@ -11,4 +11,8 @@
# define ATTR_FORMAT(...) # define ATTR_FORMAT(...)
#endif #endif
#include <stdlib.h>
void *malloc_safe(size_t size);
#endif #endif