Skip to content

Commit

Permalink
Merge branch 'reorganization'
Browse files Browse the repository at this point in the history
The lone repository is now properly organized.

 - Organized lone into numerous source and header files
   - Modular design
   - High level structure evident
   - Easier to change and develop
   - Discoverability of concepts, structures, functions
 - Refactored code, improving quality
 - Revamped GNU Make build system
   - Supports arbitrary source code file system tree structure
   - Automatically discovers, builds and links all the source files
   - Organized build tree that matches the source tree structure
   - Automatic prerequisite file generation and inclusion
   - Generated file support
 - Updated README
   - Supported architectures
   - Project structure
 - Ensured entire test suite still green

This merge finally pays off a truly massive amount of technical debt
by converting lone from a single C source file into a proper project
with a proper build system that works and is maintainable.
  • Loading branch information
matheusmoreira committed Nov 11, 2023
2 parents 45795c6 + 4130e72 commit 127367a
Show file tree
Hide file tree
Showing 106 changed files with 5,738 additions and 4,280 deletions.
8 changes: 2 additions & 6 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,2 @@
# lone binary
./lone

# generated files and code
NR.list
NR.c
# build tree
build/
83 changes: 64 additions & 19 deletions GNUmakefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# SPDX-License-Identifier: AGPL-3.0-or-later

MAKEFLAGS += --no-builtin-variables --no-builtin-rules

CC := cc
CFLAGS := -Wall -Wextra -Wpedantic -Os

ifdef TARGET
ifndef UAPI
$(error UAPI must be defined when cross compiling)
Expand All @@ -11,30 +16,70 @@ else
TARGET := $(shell uname -m)
endif

override ARCH := $(TARGET)
override ARCH.c := arch/$(ARCH).c
source_to_object = $(patsubst $(directories.source)/%.c,$(directories.build.objects)/%.o,$(1))
source_to_prerequisite = $(patsubst $(directories.source)/%.c,$(directories.build.prerequisites)/%.d,$(1))

CFLAGS := -Wall -Wextra -Wpedantic -Os
override directories := $(if $(UAPI),-isystem $(UAPI))
override definitions := -D LONE_ARCH=$(ARCH) -D LONE_ARCH_SOURCE='"$(ARCH.c)"' -D LONE_NR_SOURCE='"NR.c"'
override essential_flags := $(definitions) -ffreestanding -nostdlib -Wl,-elone_start -static -fno-omit-frame-pointer -fshort-enums
override CC := $(strip $(CC) $(directories))
ARCH := $(TARGET)

lone : lone.c NR.c $(ARCH.c)
$(CC) $(essential_flags) $(CFLAGS) -o $@ $<
directories.build := build/$(ARCH)
directories.build.objects := $(directories.build)/objects
directories.build.prerequisites := $(directories.build)/prerequisites
directories.build.include := $(directories.build)/include
directories.create :=

phony += clean
clean:
rm -f lone NR.list NR.c
directories.include := include architecture/$(ARCH)/include $(directories.build.include)
directories.source := source

phony += test
test: lone
scripts/test.bash
files.sources := $(shell find $(directories.source) -type f)

NR.list: scripts/NR.filter
$(CC) -E -dM -include linux/unistd.h - < /dev/null | scripts/NR.filter > $@
targets.phony :=
targets.NR.list := $(directories.build)/NR.list
targets.NR.c := $(directories.build.include)/lone/NR.c
targets.NR := $(targets.NR.list) $(targets.NR.c)
targets.objects := $(call source_to_object,$(files.sources))
targets.lone := $(directories.build)/lone
targets.prerequisites := $(call source_to_prerequisite,$(files.sources))

directories.create += $(dir $(targets.lone) $(targets.objects) $(targets.prerequisites) $(targets.NR))

flags.definitions := -D LONE_ARCH=$(ARCH)
flags.include_directories := $(foreach directory,$(directories.include),-I $(directory))
flags.system_include_directories := $(if $(UAPI),-isystem $(UAPI))
flags.prerequisites_generation = -MMD -MF $(call source_to_prerequisite,$(<))
flags.common := -static -ffreestanding -nostdlib -fno-omit-frame-pointer -fshort-enums -flto
flags.object = $(flags.system_include_directories) $(flags.include_directories) $(flags.prerequisites_generation) $(flags.definitions) $(flags.common)
flags.lone = $(flags.common) -Wl,-elone_start

$(directories.build.objects)/%.o: $(directories.source)/%.c | directories
$(strip $(CC) $(flags.object) $(CFLAGS) -o $@ -c $<)

$(targets.lone): $(targets.objects) | directories
$(strip $(CC) $(flags.lone) $(CFLAGS) -o $@ $^)

NR.c: NR.list scripts/NR.generate
$(call source_to_object,source/lone/modules/linux.c): $(targets.NR.c)

$(targets.NR.c): $(targets.NR.list) scripts/NR.generate
scripts/NR.generate < $< > $@

.PHONY: $(phony)
$(targets.NR.list): scripts/NR.filter
$(CC) -E -dM -include linux/unistd.h - < /dev/null | scripts/NR.filter > $@

targets.phony += lone
lone: $(targets.lone)

targets.phony += clean
clean:
rm -rf $(directories.build)

targets.phony += test
test: $(targets.lone)
scripts/test.bash $<

targets.phony += directories
directories:
mkdir -p $(sort $(directories.create))

.PHONY: $(targets.phony)
.DEFAULT_GOAL := lone

sinclude $(targets.prerequisites)
149 changes: 121 additions & 28 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,19 @@ Any of the following commands can be used:
make clean lone UAPI=/alternative/linux/uapi/headers
make clean lone TARGET=x86_64 UAPI=/linux/uapi/headers/x86_64

Currently supported targets:

- `x86_64`
- `aarch64`

## Testing

Lone has an automated test suite that exercises language features.
Any of the following commands can be used to run it:

make test
make clean test
scripts/test.bash
scripts/test.bash [lone-executable [test-suite-directory]]

New tests are added by creating directories inside `test/`,
forming an arbitrary directory tree which determines the test name.
Expand Down Expand Up @@ -61,30 +66,118 @@ the successful status code `0` is expected.

## Project structure

lone/ # The lone repository
├── arch/ # Architecture-specific code, one file each
│ ├── aarch64.c # System calls and process start for aarch64
│ └── x86_64.c # System calls and process start for x86_64
├── scripts/ # Small support programs for development
│ ├── NR.filter # Extracts system call definitions from compiler output
│ ├── NR.generate # Generates C structure initializers for system call names and numbers
│ ├── test.bash # The automated testing script
│ └── test.new # The new test case creation script
├── test/ # The lone test suite
│ └── arbitrary/tree/ # Arbitrary tree, determines test name, leaves contain test files
│ ├── arguments # Arguments passed, one per line
│ ├── environment # Environment variables set, one per line
│ ├── input # Standard input
│ ├── output # Expected standard output
│ ├── error # Expected standard error
│ └── status # Expected exit status
├── GNUmakefile # The GNU Make file
├── LICENSE.AGPLv3 # GNU Affero General Public License version 3, full license text
├── lone # The lone executable produced by make
├── lone.c # The lone C source code
├── README.md # This README file
├── .gdbinit # GDB visualization functions for lone's data structures
└── .github/ # GitHub-specific data
└── workflows/ # GitHub Actions workflows
├── codeql.yml # Automated code quality checker
└── lone.yml # Automated building and testing
lone/ # The lone repository
├── build/ # The build tree
├── include/ # Header files
├── source/ # Source files
├── architecture/ # Architecture-specific tree
├── scripts/ # Development tools and test suite
├── test/ # The lone test suite
├── GNUmakefile # The build system
├── LICENSE.AGPLv3 # Full license text of the GNU AGPLv3
├── README.md # This README file
├── .gdbinit # GDB visualization functions for lone's data structures
└── .github/ # GitHub-specific data

lone/include/ # Added to compiler include directories
└── lone/ # Lone namespace
├── hash/ # Hash function implementations
│ └── fnv_1a.h # Fowler–Noll–Vo hash function
├── lisp/ # Lone lisp language features
│ ├── constants.h # Constants like nil and true
│ ├── evaluator.h # Evaluates lone values
│ ├── printer.h # Writes lone values into text
│ └── reader.h # Reads text into lone values
├── memory/ # Lone's memory subsystem
│ ├── allocator.h # General memory block allocator
│ ├── functions.h # Memory moving and filling functions
│ ├── garbage_collector.h # The lone garbage collector
│ └── heap.h # The lone value heap
├── modules/ # Intrinsic lone modules
│ ├── intrinsic.h # Bulk initializer for all built-in modules
│ ├── linux.h # Linux system calls and process parameters
│ ├── list.h # List functions
│ ├── lone.h # Lone language primitives
│ ├── math.h # Mathematical functions
│ └── text.h # Text manipulation functions
├── struct/ # Lone structure definitions
│ ├── auxiliary.h # Auxiliary vector elements
│ ├── bytes.h # Memory segments of known size
│ ├── function.h # Reusable code blocks
│ ├── heap.h # Heap from where values are allocated
│ ├── lisp.h # Lone lisp interpreter
│ ├── list.h # Linked list of lone values
│ ├── memory.h # Memory blocks managed by lone
│ ├── module.h # Modules
│ ├── pointer.h # Typed pointers
│ ├── primitive.h # Functions implemented in C
│ ├── reader.h # Reader state and buffer
│ ├── table.h # Hash table with prototypal inheritance
│ ├── value.h # Tagged and flagged union of all value types
│ └── vector.h # Contiguous arrays of lone values
├── value/ # Functions for each type of value
│ ├── bytes.h # Creation and transfer functions
│ ├── function.h # Function and closure instantiation
│ ├── integer.h # Integer value creation and parsing
│ ├── list.h # List construction and processing
│ ├── module.h # Module value creation
│ ├── pointer.h # Typed pointer value creation
│ ├── primitive.h # Primitive C function binding creation
│ ├── symbol.h # Symbol creation and interning
│ ├── table.h # Hash table creation and operations
│ ├── text.h # Text value creation and C string transfers
│ └── vector.h # Vector creation and operations
├── definitions.h # Defined constants and macros
├── hash.h # General hashing functions
├── linux.h # Linux system calls used by lone
├── lisp.h # Lone lisp interpreter initialization
├── memory.h # Lone memory subsystem initialization
├── modules.h # Module loading, search, path management
├── structures.h # Includes all lone structure definitions
├── types.h # Basic type definitions and forward declarations
├── utilities.h # Useful functions
└── value.h # Blank slate lone value creation

lone/source/ # Lone lisp implementation source code
├── lone/ # Matches the structure or the include/ directory
└── lone.c # The main lone function

lone/architecture/
└── $ARCH/
└── include/ # Added to compiler include directories
└── lone/architecture/
├── linux/
│ ├── entry_point.c # Process start code
│ └── system_calls.c # Linux system call stubs
└── garbage_collector.c # Register spilling code

lone/build/
└── $ARCH/ # The targeted architecture
├── include/ # Added to compiler include directories
│ └── lone/
│ └── NR.c # Generated Linux system call table initializers
├── objects/ # Compiled object files; mirrors source tree structure
├── prerequisites/ # Prerequisite files; mirrors source tree structure
├── NR.list # List of system calls found on the targeted Linux UAPI
└── lone # The built lone lisp freestanding executable

lone/scripts/
├── NR.filter # Extracts system call definitions from compiler output
├── NR.generate # Generates C structure initializers for system call names and numbers
├── test.bash # The automated test suite script
└── test.new # The new test case creation script

lone/test/
└── arbitrary/tree/ # Arbitrary tree, determines test name, leaves contain test files
├── arguments # Arguments passed, one per line
├── environment # Environment variables set, one per line
├── input # Standard input
├── output # Expected standard output
├── error # Expected standard error
└── status # Expected exit status

lone/.github/
├── workflows/ # GitHub Actions workflows
│ ├── codeql.yml # Automated code quality checker
│ └── lone.yml # Automated building and testing
└── FUNDING.yml # Funding information
Loading

0 comments on commit 127367a

Please sign in to comment.