Day 1. Assembly code is being generated, on a monkey see, monkey do basis;

but it doesn't link because of a missing library; and having moved source
files around the Makefile currently doesn't work.
This commit is contained in:
Simon Brooke 2026-04-06 09:48:44 +01:00
parent 8e9ad73229
commit 882f991db4
13 changed files with 206 additions and 36 deletions

3
.gitignore vendored
View file

@ -57,3 +57,6 @@ dkms.conf
.project
.settings/
build/
# Munit
src/munit.*

3
.gitmodules vendored Normal file
View file

@ -0,0 +1,3 @@
[submodule "munit"]
path = munit
url = https://github.com/nemequ/munit.git

View file

@ -15,7 +15,7 @@ else
$(error Build mode $(BUILD_MODE) not supported by this Makefile)
endif
SRC_DIR=$(PROJECT_ROOT)/src
SRC_DIR=$(PROJECT_ROOT)/src/c
all: grendel

View file

@ -36,11 +36,11 @@ Tags will be allocated as follows:
| 3-bit value | 7-bit value | (Hex) | Interpretation |
| ----------- | ----------- | ----- | ------------------------------------------------------------ |
| 0 | 0 | 0x0 | a pointer; an offset into the vector of words. |
| 1 | 1 | 0x1 | a signed 28 bit integer. |
| 2 | 2 | 0x2 | a character; possibly just a byte, or possibly a 16 bit wchar. |
| 3 | 3 | 0x3 | unassigned (possibly a floating point number, later.) |
| 4 | 4 | 0x4 | unassigned |
| 0 | 0 | 0x0 | an error object, whose payload is a 3 character error code. |
| 1 | 1 | 0x1 | a pointer; an offset into the vector of words. |
| 2 | 2 | 0x2 | a signed 28 bit integer. |
| 3 | 3 | 0x3 | a character; possibly just a byte, or possibly a 16 bit wchar. |
| 4 | 4 | 0x4 | unassigned (possibly a floating point number, later.) |
| 5 | 5 | 0x5 | unassigned |
| 6 | 6 | 0x6 | unassigned |
| 7 | 7 | 0x7 | a cons cell |

1
munit Submodule

@ -0,0 +1 @@
Subproject commit fbbdf1467eb0d04a6ee465def2e529e4c87f2118

26
src/c/day1.c Normal file
View file

@ -0,0 +1,26 @@
/**
* day1.c
*
* Grendel: a compiling Beowulf reimplementation.
*
* Day 1 of work towards a compiler... eventually..
*
* This is a straight copy of Noah Zentzis' work. There's no original work of
* mine here, yet
*
* (c) 2026 Simon Brooke <simon@journeyman.cc>
* Licensed under GPL version 2.0, or, at your option, any later version.
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
__attribute__((__cdecl__))
extern int lisp_entry();
int main(int argc, const char **argv) {
int val = lisp_entry();
printf("%d\n", val);
return 0;
}

29
src/c/error.c Normal file
View file

@ -0,0 +1,29 @@
/**
* error.c
*
* Grendel: a compiling Beowulf reimplementation.
*
* The error handling subsystem.
*
* 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.
*
* (c) 2026 Simon Brooke <simon@journeyman.cc>
* Licensed under GPL version 2.0, or, at your option, any later version.
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "error.h"
#include "memory.h"
uint32_t make_error( char* code) {
uint32_t error = 0;
strncpy( (char *)((&error) &1), code, 3);
return error;
}

45
src/c/error.h Normal file
View file

@ -0,0 +1,45 @@
/**
* error.h
*
* Grendel: a compiling Beowulf reimplementation.
*
* The error handling subsystem.
*
* 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.
*
* (c) 2026 Simon Brooke <simon@journeyman.cc>
* Licensed under GPL version 2.0, or, at your option, any later version.
*/
#ifndef __grendel_error_h
#define __grendel_error_h
#include <stdint.h>
uint32_t make_error( char* code);
/**
* @brief error codes
*
* 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.
*
* 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"))
#endif

View file

@ -15,6 +15,11 @@
#include <stdint.h>
#include "memory.h"
#include "version.h"
__attribute__((__cdecl__))
extern int lisp_entry();
void showbits( unsigned int x )
{
@ -28,18 +33,12 @@ void showbits( unsigned int x )
int main(int argc, char **argv) {
printf( "Grendel:\n");
int i;
for ( i = 0; i < 8; i++) {
printf( "\ti = %d (%b, 0x%x);\n", i, i, i);
}
for ( ; i < 128; i++) {
if ((i & TAG32MASK) == TAG32MASK) {
printf( "\ti = %d (%b, 0x%x);\n", i, i, i);
}
}
printf( "Grendel, a compiler for Beowulf: version %s\n", VERSION);
int val = lisp_entry();
printf("%d\n", val);
return 0;
}
return 0;
}

19
src/c/lisp.c Normal file
View file

@ -0,0 +1,19 @@
/**
* lisp.c
*
* Grendel: a compiling Beowulf reimplementation.
*
* The compiler... eventually..
*
* 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.
*
* (c) 2026 Simon Brooke <simon@journeyman.cc>
* Licensed under GPL version 2.0, or, at your option, any later version.
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>

View file

@ -16,64 +16,64 @@
/* Tags for 32 bit objects, with 3 bits of tag an one mark bit */
#define ERRORTV (0)
/**
* @brief This pointer object is an actual pointer -- an offset into consspace.
*/
#define OFFSETTV (0)
#define OFFSETTV (1)
/**
* @brief This pointer object is actually a 28 bit integer value.
*/
#define INTEGERTV (1)
#define INTEGERTV (2)
/**
* @brief A character; initially just a byte. but potentially a 16 bit wchar.
*/
#define CHARTV (2)
#define CHARTV (3)
/**
* @brief A 16 bit floating point number. (future expansion)
*
* Yes, it could be 28 bit, but I think that would hurt my brain.
*/
#define FLOATTV (3)
#define FLOATTV (4)
/*
* Values 4..6 inclusive reserved further data types, including maybe
* implementing reals later.
* Values 5 and 6 are available for further 32 bit data types.
*/
/**
* @bried This is not actually a pointer at all but the first word of a cell.
*/
#define CELLTV (7)
#define CELLTV (7)
/**
* @brief this cell is a symbol
*/
#define SYMBOLTV (0xf)
#define SYMBOLTV (0xf)
/**
* @brief this cell is a pointer to a compiled function
*/
#define FUNCTIONTV (0x17)
#define FUNCTIONTV (0x17)
/**
* @brief This cell is pointer to a compiled special form
*/
#define SPECIALTV (0x1f)
#define SPECIALTV (0x1f)
/**
* @brief this cell is a rational number (future expansion)
*/
#define RATIOTV (0x27)
#define RATIOTV (0x27)
/**
* @brief this cell is a digit of a big number (future expansion)
*/
#define BIGNUMTV (0x2f)
#define BIGNUMTV (0x2f)
/**
* @brief this cell is part of a string (future expansion)
*/
#define STRINGTV (0x37)
#define STRINGTV (0x37)
// The possible potential values remain unassigned:
// i = 63 (111111, 0x3f);
@ -85,14 +85,14 @@
// i = 111 (1101111, 0x6f);
// i = 119 (1110111, 0x77);
#define FREETV (0x7f)
#define FREETV (0x7f)
#define MARKMASK ((unsigned int)1)
#define TAG32MASK ((unsigned int)7)
#define TAG64MASK ((unsigned int)0xf)
#define MARKMASK ((uint64_t)1)
#define TAG32MASK ((uint64_t)7)
#define TAG64MASK ((uint64_t)0xf)
#define MASK64 (0xffffffffffffffff)
#define MASK32 (0xffffffff)
#define MASK64 ((uint64_t)0xffffffffffffffff)
#define MASK32 ((uint64_t)0xffffffff)
/**
* @brief Return the mark bit of this object.

15
src/c/version.h Normal file
View file

@ -0,0 +1,15 @@
/**
* version.h
*
* Grendel: a compiling Beowulf reimplementation.
*
* (c) 2026 Simon Brooke <simon@journeyman.cc>
* Licensed under GPL version 2.0, or, at your option, any later version.
*/
#ifndef __grendel_version_h
#define __grendel_version_h
#define VERSIOM "Aelfhere"
#ifndef

30
src/guile/day1.scm Normal file
View file

@ -0,0 +1,30 @@
(define emit (lambda args (apply simple-format #t args)
(newline)))
(define (compile-program program)
(emit ".text")
(emit ".p2align 4,,15")
(emit ".globl lisp_entry")
(emit "lisp_entry:")
; handle incoming call from C
(emit "push %esi")
(emit "push %edi")
(emit "push %edx")
; our code goes here
(emit "movl $42, %eax")
; restore state for return to C
(emit "pop %edx")
(emit "pop %edi")
(emit "pop %esi")
(emit "ret"))
(define (compile-to-binary program)
(begin
(with-output-to-file "/tmp/compiled.s"
(lambda () (compile-program program)))
(system "gcc -fomit-frame-pointer -m32 /tmp/compiled.s src/c/day1.c")))