Compare commits

...

12 Commits

Author SHA1 Message Date
Aryadev Chavali
10d6876de4 reader: implement read_err_to_cstr 2026-02-05 04:07:59 +00:00
Aryadev Chavali
75daad53ea reader: add a few more read errors and read_err_to_cstr 2026-02-05 04:06:27 +00:00
Aryadev Chavali
1e451c57e8 stream: stream_line_col: get the line/column of stream currently
Best part is that this should only use cached data, so no chunking
required.
2026-02-05 04:04:54 +00:00
Aryadev Chavali
d14f015c38 stream: use the nonexistent errors in stream_init_* 2026-02-05 04:04:54 +00:00
Aryadev Chavali
26e545a732 stream: Rearranged STREAM_ERR to be nonzero positive
I don't know why I was thinking about having valid positive values for
STREAM_ERR.  Doesn't make sense.
2026-02-05 04:04:54 +00:00
Aryadev Chavali
169a165cfc stream: added stream_err_to_cstr
Simple routine, not really much to explain here.
2026-02-05 04:04:54 +00:00
Aryadev Chavali
438a494ac7 lisp: sys_cleanup -> sys_free 2026-02-05 04:04:54 +00:00
Aryadev Chavali
068e4aa9f0 Makefile: added -Werror to general flags
May as well remove all warnings if possible, though in most cases this
is just to ensure I catch everything and deal with it.
2026-02-05 04:04:54 +00:00
Aryadev Chavali
271e0bff9b Makefile: added examples recipe to run examples 2026-02-05 04:04:54 +00:00
Aryadev Chavali
010895331d examples: Added an example for hello world 2026-02-05 04:04:54 +00:00
Aryadev Chavali
6a75c1d9d4 Makefile: added VERBOSE_LOGS=1 declaration to DFLAGS for debug build 2026-02-05 04:04:54 +00:00
Aryadev Chavali
01b695eb6a base: implement LOG macro which only prints if VERBOSE_LOGS = 1
This allows us to make builds that don't have verbose logging, whether
they're debug or not.

We could have release builds that have verbose logging.
2026-02-05 04:04:54 +00:00
11 changed files with 166 additions and 16 deletions

View File

@@ -5,8 +5,8 @@ OUT=$(DIST)/alisp.out
TEST=$(DIST)/test.out TEST=$(DIST)/test.out
LDFLAGS= LDFLAGS=
GFLAGS=-Wall -Wextra -Wpedantic -std=c23 -I./include/ GFLAGS=-Wall -Wextra -Wpedantic -Werror -std=c23 -I./include/
DFLAGS=-ggdb -fsanitize=address -fsanitize=undefined DFLAGS=-ggdb -fsanitize=address -fsanitize=undefined -DVERBOSE_LOGS=1
RFLAGS=-O3 RFLAGS=-O3
MODE=release MODE=release
@@ -61,6 +61,9 @@ run: $(OUT)
test: $(TEST) test: $(TEST)
./$^ ./$^
examples: $(OUT)
./$^ ./examples/hello-world.lisp
clean: clean:
rm -rf $(DIST) rm -rf $(DIST)

14
examples/hello-world.lisp Normal file
View File

@@ -0,0 +1,14 @@
;;; hello-world.lisp - 2026-02-04
;; Copyright (C) 2026 Aryadev Chavali
;; This program is distributed in the hope that it will be useful, but WITHOUT
;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
;; FOR A PARTICULAR PURPOSE. See the GNU General Public License Version 2 for
;; details.
;; You may distribute and modify this code under the terms of the GNU General
;; Public License Version 2, which you should have received a copy of along with
;; this program. If not, please go to <https://www.gnu.org/licenses/>.
(display "Hello, world!")

View File

@@ -19,6 +19,20 @@
#define FAIL(MSG) assert(false && "FAIL: " #MSG) #define FAIL(MSG) assert(false && "FAIL: " #MSG)
#define TODO(MSG) assert(false && "TODO: " #MSG) #define TODO(MSG) assert(false && "TODO: " #MSG)
#ifndef VERBOSE_LOGS
#define VERBOSE_LOGS 0
#endif
#if VERBOSE_LOGS
#define LOG(...) \
do \
{ \
printf(__VA_ARGS__); \
} while (0)
#else
#define LOG(...)
#endif
/// Numeric aliases /// Numeric aliases
typedef uint8_t u8; typedef uint8_t u8;
typedef uint16_t u16; typedef uint16_t u16;

View File

@@ -30,7 +30,7 @@ typedef struct
void sys_init(sys_t *); void sys_init(sys_t *);
void sys_register(sys_t *, lisp_t *); void sys_register(sys_t *, lisp_t *);
void sys_cleanup(sys_t *); void sys_free(sys_t *);
/// Constructors and destructors /// Constructors and destructors
lisp_t *make_int(i64); lisp_t *make_int(i64);

View File

@@ -8,13 +8,18 @@
#ifndef READER_H #ifndef READER_H
#define READER_H #define READER_H
#include <alisp/lisp.h>
#include <alisp/stream.h> #include <alisp/stream.h>
typedef enum typedef enum
{ {
READ_OK = 0, READ_ERR_OK = 0,
READ_ERR_EOF,
READ_ERR_UNKNOWN_CHAR,
} read_err_t; } read_err_t;
const char *read_err_to_cstr(read_err_t);
// Attempt to read an expression from the stream, storing it in a pointer, // Attempt to read an expression from the stream, storing it in a pointer,
// returning any errors if failed. // returning any errors if failed.
read_err_t read(sys_t *, stream_t *, lisp_t **); read_err_t read(sys_t *, stream_t *, lisp_t **);

View File

@@ -22,13 +22,15 @@ typedef enum
typedef enum typedef enum
{ {
STREAM_ERR_INVALID_PTR = -4,
STREAM_ERR_FILE_NONEXISTENT = -3,
STREAM_ERR_FILE_READ = -2,
STREAM_ERR_PIPE_NONEXISTENT = -1,
STREAM_ERR_OK = 0, STREAM_ERR_OK = 0,
STREAM_ERR_INVALID_PTR,
STREAM_ERR_FILE_NONEXISTENT,
STREAM_ERR_FILE_READ,
STREAM_ERR_PIPE_NONEXISTENT,
} stream_err_t; } stream_err_t;
const char *stream_err_to_cstr(stream_err_t);
typedef struct typedef struct
{ {
vec_t cache; vec_t cache;
@@ -80,6 +82,9 @@ sv_t stream_till(stream_t *, const char *);
// present. // present.
sv_t stream_while(stream_t *, const char *); sv_t stream_while(stream_t *, const char *);
// Get the line and column of the stream at its current position.
void stream_line_col(stream_t *, u64 *line, u64 *col);
#endif #endif
/* Copyright (C) 2026 Aryadev Chavali /* Copyright (C) 2026 Aryadev Chavali

View File

@@ -22,7 +22,7 @@ void sys_register(sys_t *sys, lisp_t *ptr)
vec_append(&sys->memory, &ptr, sizeof(&ptr)); vec_append(&sys->memory, &ptr, sizeof(&ptr));
} }
void sys_cleanup(sys_t *sys) void sys_free(sys_t *sys)
{ {
static_assert(NUM_TAGS == 5); static_assert(NUM_TAGS == 5);

43
src/reader.c Normal file
View File

@@ -0,0 +1,43 @@
/* reader.c: Stream reader implementation
* Created: 2026-02-04
* Author: Aryadev Chavali
* License: See end of file
* Commentary:
*/
#include <ctype.h>
#include <string.h>
#include <alisp/base.h>
#include <alisp/reader.h>
const char *read_err_to_cstr(read_err_t err)
{
switch (err)
{
case READ_ERR_OK:
return "OK";
break;
case READ_ERR_EOF:
return "EOF";
break;
case READ_ERR_UNKNOWN_CHAR:
return "UNKNOWN_CHAR";
break;
default:
FAIL("Unreachable");
}
}
/* Copyright (C) 2026 Aryadev Chavali
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License Version 2 for
* details.
* You may distribute and modify this code under the terms of the GNU General
* Public License Version 2, which you should have received a copy of along with
* this program. If not, please go to <https://www.gnu.org/licenses/>.
*/

View File

@@ -8,8 +8,33 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <alisp/base.h>
#include <alisp/stream.h> #include <alisp/stream.h>
const char *stream_err_to_cstr(stream_err_t err)
{
switch (err)
{
case STREAM_ERR_INVALID_PTR:
return "INVALID PTR";
break;
case STREAM_ERR_FILE_NONEXISTENT:
return "FILE NONEXISTENT";
break;
case STREAM_ERR_FILE_READ:
return "FILE READ";
break;
case STREAM_ERR_PIPE_NONEXISTENT:
return "PIPE NONEXISTENT";
break;
case STREAM_ERR_OK:
return "OK";
break;
default:
FAIL("Unreachable");
}
}
stream_err_t stream_init_string(stream_t *stream, char *name, sv_t contents) stream_err_t stream_init_string(stream_t *stream, char *name, sv_t contents)
{ {
if (!stream) if (!stream)
@@ -26,8 +51,11 @@ stream_err_t stream_init_string(stream_t *stream, char *name, sv_t contents)
stream_err_t stream_init_pipe(stream_t *stream, char *name, FILE *pipe) stream_err_t stream_init_pipe(stream_t *stream, char *name, FILE *pipe)
{ {
if (!stream || !pipe) if (!stream)
return STREAM_ERR_INVALID_PTR; return STREAM_ERR_INVALID_PTR;
else if (!pipe)
return STREAM_ERR_PIPE_NONEXISTENT;
name = name ? name : "<stream>"; name = name ? name : "<stream>";
memset(stream, 0, sizeof(*stream)); memset(stream, 0, sizeof(*stream));
@@ -42,8 +70,11 @@ stream_err_t stream_init_pipe(stream_t *stream, char *name, FILE *pipe)
stream_err_t stream_init_file(stream_t *stream, char *name, FILE *pipe) stream_err_t stream_init_file(stream_t *stream, char *name, FILE *pipe)
{ {
if (!stream || !pipe) if (!stream)
return STREAM_ERR_INVALID_PTR; return STREAM_ERR_INVALID_PTR;
else if (!pipe)
return STREAM_ERR_FILE_NONEXISTENT;
name = name ? name : "<stream>"; name = name ? name : "<stream>";
memset(stream, 0, sizeof(*stream)); memset(stream, 0, sizeof(*stream));
@@ -361,6 +392,41 @@ sv_t stream_while(stream_t *stream, const char *str)
return stream_substr_abs(stream, current_position, size - 1); return stream_substr_abs(stream, current_position, size - 1);
} }
void stream_line_col(stream_t *stream, u64 *line, u64 *col)
{
if (!stream || !line || !col)
return;
// Go through the cache, byte by byte.
char *cache = NULL;
u64 size = 0;
if (stream->type == STREAM_TYPE_STRING)
{
cache = stream->string.data;
size = stream->string.size;
}
else
{
cache = (char *)vec_data(&stream->pipe.cache);
size = stream->pipe.cache.size;
}
*line = 1;
*col = 0;
for (u64 i = 0; i < size; ++i)
{
char c = cache[i];
if (c == '\n')
{
*line += 1;
*col = 0;
}
else
{
*col += 1;
}
}
}
/* Copyright (C) 2025, 2026 Aryadev Chavali /* Copyright (C) 2025, 2026 Aryadev Chavali
* This program is distributed in the hope that it will be useful, but WITHOUT * This program is distributed in the hope that it will be useful, but WITHOUT

View File

@@ -60,7 +60,7 @@ void sym_test(void)
TEST(strncmp(in, out, strlen(in)) == 0, "%d", strncmp(in, out, strlen(in))); TEST(strncmp(in, out, strlen(in)) == 0, "%d", strncmp(in, out, strlen(in)));
} }
TEST_PASSED(); TEST_PASSED();
sys_cleanup(&system); sys_free(&system);
} }
void cons_test(void) void cons_test(void)
@@ -91,7 +91,7 @@ void cons_test(void)
TEST_PASSED(); TEST_PASSED();
sys_cleanup(&system); sys_free(&system);
} }
const test_fn TESTS_LISP_API[] = { const test_fn TESTS_LISP_API[] = {

View File

@@ -32,7 +32,7 @@ void vec_test1(void)
strncmp((char *)vec_data(vec), words_text, vec->size)); strncmp((char *)vec_data(vec), words_text, vec->size));
TEST_PASSED(); TEST_PASSED();
sys_cleanup(&system); sys_free(&system);
} }
void vec_test2(void) void vec_test2(void)
@@ -65,7 +65,7 @@ void vec_test2(void)
} }
TEST_PASSED(); TEST_PASSED();
sys_cleanup(&system); sys_free(&system);
} }
const test_fn TESTS_VEC[] = { const test_fn TESTS_VEC[] = {