From 643d255a21a671e517ee210c2a941fa7eb8ca0f8 Mon Sep 17 00:00:00 2001 From: Simon Brooke Date: Mon, 6 Apr 2026 12:47:41 +0100 Subject: [PATCH] Added all the error codes from the manual. Some will be irrelevant to this project, but they're all here. --- README.md | 13 +++++++++++ src/c/error.c | 5 ++--- src/c/error.h | 60 ++++++++++++++++++++++++++++++++++++++++++--------- 3 files changed, 65 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 62d34b6..4974b07 100644 --- a/README.md +++ b/README.md @@ -60,3 +60,16 @@ Tags will be allocated as follows: | 7 | 119 | | unassigned | | 7 | 127 | 0x7f | a free cell | +## Problems with building a Ghuloum-style compiler in Lisp 1.5 + +Ghuloum's compiler emits strings in the form of assembly language statements into a file which is then run through a separate assembler to produce a binary which is finally integrated with a launcher stub written in C using a linker. This makes it possible to write a Lisp largely in that Lisp itself (provided you have an existing Lisp fostermother image to run the initial compilation); but it does not dirctly enable you to compile a single function into the existing image at runtime, and then immediately use the newly compiled function; and as far as I'm concerned, until you have that you don't have a working Lisp compiler. + +Furthermore, Lisp 1.5 does not have a concept of a string, and cannot manipulate strings. I *could* add strings as an extension, but that feels somewhat outwith the scope of this project. + +I don't feel that any of this is insuperable. Lisp 1.5 supports the functions `PRINT`, `PRIN1`, and `TERPRI` which respectively make it possible to print complete S-expressions, individual atoms, and linefeeds. It would be possible to create a symbol whose print name was a single blank space. It would be perverse, and annoying, and `READ` would not recognise such a symbol so if it were included in a sysout file that sysout could not be read back in; but it would be possible. + +Or else, we could assemble the assembly language statements as a list of individual S-expressions, print that, run it through an external preprocessor and the assembler, and then link the resulting binary. It does not seem to me that using an external pre-processor is any more 'cheating' than using an external assembler. + +But finally, and this will be my preferred outcome, one could create that list of assembly language statements in memory; one could estimate from it the size of the compiled function; one could malloc a block of memory of that size on the heap; and one could then assemble the function by writing bytes into that block of memory as specified in the assembly language statements. + +If I'm going to use this side-project as an exercise to learn how to write the Post Scarcity compiler, the Post Scarcity compiler has got to be able to do that; so I should try. \ No newline at end of file diff --git a/src/c/error.c b/src/c/error.c index 3c60319..9515e8c 100644 --- a/src/c/error.c +++ b/src/c/error.c @@ -13,17 +13,16 @@ * Licensed under GPL version 2.0, or, at your option, any later version. */ -#include #include #include #include "error.h" -#include "memory.h" uint32_t make_error( char* code) { uint32_t error = 0; + char* dest = (char *)&error; - strncpy( (char *)((&error) &1), code, 3); + strncpy( (char *)(dest + 1), code, 3); return error; } diff --git a/src/c/error.h b/src/c/error.h index 0c09a42..f603941 100644 --- a/src/c/error.h +++ b/src/c/error.h @@ -25,21 +25,61 @@ uint32_t make_error( char* code); * * Error codes are detailed in section 6.3, page 32, of the * Lisp 1.5 Programmer's Manual. I shall in so far as possible follow - * those codes. + * reproduce those codes. * * Error codes comprise a one or two alphabetic character category, followed * by a single digit number. A space is shown in the manual between the * category and the number, but I have not followed that here for reasons. */ -#define APPLIED_FUNCTION_CALLED_ERROR (make_error( "A1")) -#define UNDEFINED_FUNCTION_APPLY_ERROR (make_error( "A2")) -#define COND_UNSATISFIED_ERROR (make_error( "A3")) -#define SETQ_ON_NONEXISTANT_VAR_ERROR (make_error( "A4")) -#define SET_ON_NONEXISTANT_VAR_ERROR (make_error( "A5")) -#define NO_TARGET_FOR_GO_ERROR (make_error( "A6")) -#define TOO_MANY_ARGUMENTS_ERROR (make_error( "A7")) -#define UNBOUND_VARIABLE_ERROR (make_error( "A8")) -#define UNDEFINED_FUNCTION_EVAL_ERROR (make_error( "A9")) +#define ERROR_APPLIED_FUNCTION_CALLED (make_error( "A1")) +#define ERROR_UNDEFINED_FUNCTION_APPLY (make_error( "A2")) +#define ERROR_COND_UNSATISFIED (make_error( "A3")) +#define ERROR_SETQ_ON_NONEXISTANT_VAR (make_error( "A4")) +#define ERROR_SET_ON_NONEXISTANT_VAR (make_error( "A5")) +#define ERROR_NO_TARGET_FOR_GO (make_error( "A6")) +#define ERROR_TOO_MANY_ARGUMENTS (make_error( "A7")) +#define ERROR_UNBOUND_VARIABLE (make_error( "A8")) +#define ERROR_UNDEFINED_FUNCTION_EVAL (make_error( "A9")) + +#define ERROR_TOO_MANY_CHARS_IN_NAME (make_error( "CH1")) +#define ERROR_FLOAT_NUMBER_OUT_OF_RANGE (make_error( "CH2")) +#define ERROR_TAPE_READING (make_error( "CH3")) + +#define ERROR_CONS_COUNTER_TRAP (make_error( "F1")) +#define ERROR_FIRST_ARG_LIST_TOO_SHORT (make_error( "F2")) +#define ERROR_SECOND_ARG_LIST_TOO_SHORT (make_error( "F3")) +// I wonder what happened to F4? +#define ERROR_STR_TRAP (make_error( "F5")) + +#define ERROR_FLOAT_TRAP (make_error( "G1")) +#define ERROR_OUT_OF_PUSHDOWN_LIST (make_error( "G2")) + +#define ERROR_FATAL_RECLAIMER (make_error( "GC1")) +#define ERROR_NOT_ENOUGH_RECLAIMED (make_error( "GC2")) + +#define ERROR_NOT_ENOUGH_ROOM_ARRAY (make_error( "I1")) +#define ERROR_FIRST_ARG_NEGATIVE (make_error( "I2")) + +#define ERROR_UNABLE_TO_DETERMINE_ORIGIN (make_error( "L1")) +#define ERROR_OUT_OF_BINARY_SPACE (make_error( "L2")) +#define ERROR_UNDEFINED_SYMBOL (make_error( "L3")) +#define ERROR_FIELD_CONTAINED_SUB_SUBS (make_error( "L4")) + +#define ERROR_ERROR_IN_SIZE_CARD (make_error( "O1")) +#define ERROR_INVALID_TAPE_DESIGNATION (make_error( "O2")) +#define ERROR_NO_SIZECARD (make_error( "O3")) +#define ERROR_BAD_DUMP_ARGUMENTS (make_error( "O4")) +#define ERROR_BAD_INPUT_BUT_GOING_ON (make_error( "O5")) +#define ERROR_OVERLAPPING_PARAMETERS (make_error( "O7")) + +#define ERROR_PRIN1_NON_OBJECT (make_error( "P1")) + +#define ERROR_FIRST_OBJECT_ILLEGAL (make_error( "R1")) +#define ERROR_CONTEXT_WITH_DOT_NOTATION (make_error( "R2")) +#define ERROR_ILLEGAL_CHARACTER (make_error( "R3")) +#define ERROR_END_OF_FILE_ON_READ_IN (make_error( "R4")) +#define ERROR_PRINT_NAME_TOO_LONG (make_error( "R5")) +#define ERROR_NUMBER_TOO_LARGE (make_error( "R6")) #endif