Squashed: platform support, bugfixes, GH workflows, read more

I've expanded support to three major platforms:

- linux
- windows
- macos

The CI now runs the test suites for all of these, both under normal
conditions and under GDB (except for macos, which lacks GDB support).

TOY_BITNESS specifies the bit-width of the current platform, either 32
or 64. A value of -1 means the bit-width could not be determined. Some
tests will be disabled if the appropriate bit-width can't be determined,
and a warning is printed to stderr.

TOY_API has been tweaked, and is now dependant on different
preprocessor flags. It is defined as 'extern' on all supported
platforms except windows, which instead specifies DLL support. It
defaults to 'extern' if the platform can't be determined.

commit d0350998ecc80b8925a1962ceb2ab400da50be9d
Author: Kayne Ruse <kayneruse@gmail.com>
Date:   Sun Sep 22 09:55:42 2024 +1000

    Expanded GDB tests using matrix strategy

commit dc2addacc52830227ddcd0f35997c0e1668b579c
Author: Kayne Ruse <kayneruse@gmail.com>
Date:   Sun Sep 22 09:05:42 2024 +1000

    Reserved the yield keyword

commit f485c380f74a49092e0c5a41e599fbb06dbce235
Author: Kayne Ruse <kayneruse@gmail.com>
Date:   Sat Sep 21 15:17:11 2024 +1000

    Potential segfault fix

commit d8b19d21c92133feb071e631009a3cf99df0f068
Author: Kayne Ruse <kayneruse@gmail.com>
Date:   Sat Sep 21 14:25:47 2024 +1000

    Added testing on windows under GDB, read more

    I'm hunting a segfault that only appears on windows, but I lack a
    windows machine, so github's runners are all I have right now.

commit 8606db541fb5cbe91b16a39e9815fe4a27ba0c8a
Author: Kayne Ruse <kayneruse@gmail.com>
Date:   Sat Sep 21 13:12:02 2024 +1000

    DLL import/export macros tweaked for windows

    TOY_EXPORT for making a DLL
    TOY_IMPORT for using a DLL

    Defaults to 'extern' if neither option is present

commit a6929666401953a5b3a93dfe83c9398e012beefc
Author: Kayne Ruse <kayneruse@gmail.com>
Date:   Sat Sep 21 12:52:06 2024 +1000

    Investigating bitness issue on windows

commit 8f615f735868a316e8d5a6a77ed899e72fd537f8
Author: Kayne Ruse <kayneruse@gmail.com>
Date:   Sat Sep 21 12:32:55 2024 +1000

    Adjusting bitness tests in test_ast.c

commit 61694f2183ac84ee7c53c855f2f6aa29f360f16c
Author: Kayne Ruse <kayneruse@gmail.com>
Date:   Sat Sep 21 11:46:59 2024 +1000

    Added experimental macOS CI job
This commit is contained in:
2024-09-22 11:27:08 +10:00
parent ac89f80b5b
commit 4567484038
11 changed files with 129 additions and 46 deletions

View File

@@ -14,21 +14,24 @@ on:
- dev - dev
workflow_dispatch: workflow_dispatch:
#testing the CI workflows while nothing is functional yet #CI workflows using a matrix
jobs: jobs:
test-ubuntu-latest: run-test-suites:
runs-on: ubuntu-latest strategy:
matrix:
steps: platforms:
- uses: actions/checkout@v4 - { os: ubuntu-latest, preinstall: sudo apt-get install gdb, gdb_skip: false }
- name: make tests (ubuntu) - { os: windows-latest, preinstall: , gdb_skip: false }
run: make tests - { os: macos-latest, preinstall: , gdb_skip: true }
commands:
test-windows-latest: - make tests
runs-on: windows-latest - make tests-gdb
runs-on: ${{ matrix.platforms.os }}
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: make tests (windows) - name: Preinstall dependencies
run: make tests run: ${{ matrix.platforms.preinstall }}
- name: run the test suites
if: matrix.platforms.gdb_skip != true
run: ${{ matrix.commands }}

View File

@@ -19,6 +19,10 @@ all: clean tests
tests: tests:
$(MAKE) -C tests -k $(MAKE) -C tests -k
.PHONY: tests-gdb
tests-gdb:
$(MAKE) -C tests all-gdb -k
#util targets #util targets
$(TOY_OUTDIR): $(TOY_OUTDIR):
mkdir $(TOY_OUTDIR) mkdir $(TOY_OUTDIR)

View File

@@ -110,14 +110,14 @@ typedef struct Toy_AstEnd {
Toy_AstType type; Toy_AstType type;
} Toy_AstEnd; } Toy_AstEnd;
union Toy_Ast { union Toy_Ast { //32 | 64 BITNESS
Toy_AstType type; //4 Toy_AstType type; //4 | 4
Toy_AstBlock block; //12 Toy_AstBlock block; //16 | 32
Toy_AstValue value; //12 Toy_AstValue value; //12 | 12
Toy_AstUnary unary; //12 Toy_AstUnary unary; //12 | 16
Toy_AstBinary binary; //16 Toy_AstBinary binary; //16 | 24
Toy_AstGroup group; //8 Toy_AstGroup group; //8 | 16
Toy_AstPass pass; //4 Toy_AstPass pass; //4 | 4
Toy_AstError error; //4 Toy_AstError error; //4 | 4
Toy_AstEnd end; //4 Toy_AstEnd end; //4 | 4
}; //16 }; //16 | 32

View File

@@ -6,29 +6,38 @@
#include <stddef.h> #include <stddef.h>
//TOY_API is platform-dependant, and marks publicly usable API functions //TOY_API is platform-dependant, and marks publicly usable API functions
#if defined(__GNUC__) #if defined(__linux__)
#define TOY_API extern #define TOY_API extern
#elif defined(_MSC_VER) #elif defined(_WIN32) || defined(_WIN64)
#ifndef TOY_EXPORT #if defined(TOY_EXPORT)
#define TOY_API __declspec(dllexport)
#elif defined(TOY_IMPORT)
#define TOY_API __declspec(dllimport) #define TOY_API __declspec(dllimport)
#else #else
#define TOY_API __declspec(dllexport) #define TOY_API extern
#endif #endif
#elif defined(__APPLE__)
#define TOY_API extern
#else #else
//generic solution //generic solution
#define TOY_API extern #define TOY_API extern
#endif #endif
//TOY_BITNESS is used to encourage memory-cache friendliness //TOY_BITNESS is used to encourage memory-cache friendliness
//source: https://www.linuxquestions.org/questions/programming-9/c-preprocessor-define-for-32-vs-64-bit-long-int-4175658579/ #if defined(__linux__)
#if defined(__GNUC__) #if defined(__LP64__)
#if defined(__x86_64)
#define TOY_BITNESS 64 #define TOY_BITNESS 64
#else #else
#define TOY_BITNESS 32 #define TOY_BITNESS 32
#endif #endif
#elif defined(_MSC_VER) #elif defined(_WIN32) || defined(_WIN64)
#if defined(_M_X64) #if defined(_WIN64)
#define TOY_BITNESS 64
#else
#define TOY_BITNESS 32
#endif
#elif defined(__APPLE__)
#if defined(__LP64__)
#define TOY_BITNESS 64 #define TOY_BITNESS 64
#else #else
#define TOY_BITNESS 32 #define TOY_BITNESS 32

View File

@@ -41,6 +41,7 @@ const Toy_KeywordTypeTuple Toy_private_keywords[] = {
{TOY_TOKEN_KEYWORD_TYPEOF, "typeof"}, {TOY_TOKEN_KEYWORD_TYPEOF, "typeof"},
{TOY_TOKEN_KEYWORD_VAR, "var"}, {TOY_TOKEN_KEYWORD_VAR, "var"},
{TOY_TOKEN_KEYWORD_WHILE, "while"}, {TOY_TOKEN_KEYWORD_WHILE, "while"},
{TOY_TOKEN_KEYWORD_YIELD, "yield"},
//literal values //literal values
{TOY_TOKEN_LITERAL_TRUE, "true"}, {TOY_TOKEN_LITERAL_TRUE, "true"},

View File

@@ -36,5 +36,5 @@ typedef enum Toy_OpcodeType {
//meta instructions //meta instructions
TOY_OPCODE_PASS, TOY_OPCODE_PASS,
TOY_OPCODE_ERROR, TOY_OPCODE_ERROR,
TOY_OPCODE_EOF, TOY_OPCODE_EOF = 255,
} Toy_OpcodeType; } Toy_OpcodeType;

View File

@@ -154,6 +154,7 @@ static ParsingTuple parsingRulesetTable[] = {
{PREC_NONE,NULL,NULL},// TOY_TOKEN_KEYWORD_TYPEOF, {PREC_NONE,NULL,NULL},// TOY_TOKEN_KEYWORD_TYPEOF,
{PREC_NONE,NULL,NULL},// TOY_TOKEN_KEYWORD_VAR, {PREC_NONE,NULL,NULL},// TOY_TOKEN_KEYWORD_VAR,
{PREC_NONE,NULL,NULL},// TOY_TOKEN_KEYWORD_WHILE, {PREC_NONE,NULL,NULL},// TOY_TOKEN_KEYWORD_WHILE,
{PREC_NONE,NULL,NULL},// TOY_TOKEN_KEYWORD_YIELD,
//literal values //literal values
{PREC_PRIMARY,atomic,NULL},// TOY_TOKEN_LITERAL_TRUE, {PREC_PRIMARY,atomic,NULL},// TOY_TOKEN_LITERAL_TRUE,

View File

@@ -281,12 +281,12 @@ static void* writeRoutine(Toy_Routine* rt, Toy_Ast* ast) {
expand(&buffer, &capacity, &count, rt->codeCount); expand(&buffer, &capacity, &count, rt->codeCount);
memcpy((buffer + count), rt->code, rt->codeCount); memcpy((buffer + count), rt->code, rt->codeCount);
((int*)buffer)[codeAddr] = count; *((int*)(buffer + codeAddr)) = count;
count += rt->codeCount; count += rt->codeCount;
} }
//finally, record the total size, and return the result //finally, record the total size, and return the result
((int*)buffer)[0] = count; *((int*)buffer) = count;
return buffer; return buffer;
} }

View File

@@ -43,6 +43,7 @@ typedef enum Toy_TokenType {
TOY_TOKEN_KEYWORD_TYPEOF, TOY_TOKEN_KEYWORD_TYPEOF,
TOY_TOKEN_KEYWORD_VAR, TOY_TOKEN_KEYWORD_VAR,
TOY_TOKEN_KEYWORD_WHILE, TOY_TOKEN_KEYWORD_WHILE,
TOY_TOKEN_KEYWORD_YIELD,
//literal values //literal values
TOY_TOKEN_LITERAL_TRUE, TOY_TOKEN_LITERAL_TRUE,

View File

@@ -3,6 +3,33 @@
#include <stdio.h> #include <stdio.h>
int test_sizeof_ast_64bit() {
#define TEST_SIZEOF(type, size) \
if (sizeof(type) != size) { \
fprintf(stderr, TOY_CC_ERROR "ERROR: sizeof(" #type ") is %d, expected %d\n" TOY_CC_RESET, (int)sizeof(type), size); \
++err; \
}
//count errors
int err = 0;
//run for each type
TEST_SIZEOF(Toy_AstType, 4);
TEST_SIZEOF(Toy_AstBlock, 32);
TEST_SIZEOF(Toy_AstValue, 12);
TEST_SIZEOF(Toy_AstUnary, 16);
TEST_SIZEOF(Toy_AstBinary, 24);
TEST_SIZEOF(Toy_AstGroup, 16);
TEST_SIZEOF(Toy_AstPass, 4);
TEST_SIZEOF(Toy_AstError, 4);
TEST_SIZEOF(Toy_AstEnd, 4);
TEST_SIZEOF(Toy_Ast, 32);
#undef TEST_SIZEOF
return -err;
}
int test_sizeof_ast_32bit() { int test_sizeof_ast_32bit() {
#define TEST_SIZEOF(type, size) \ #define TEST_SIZEOF(type, size) \
if (sizeof(type) != size) { \ if (sizeof(type) != size) { \
@@ -22,6 +49,7 @@ int test_sizeof_ast_32bit() {
TEST_SIZEOF(Toy_AstGroup, 8); TEST_SIZEOF(Toy_AstGroup, 8);
TEST_SIZEOF(Toy_AstPass, 4); TEST_SIZEOF(Toy_AstPass, 4);
TEST_SIZEOF(Toy_AstError, 4); TEST_SIZEOF(Toy_AstError, 4);
TEST_SIZEOF(Toy_AstEnd, 4);
TEST_SIZEOF(Toy_Ast, 16); TEST_SIZEOF(Toy_Ast, 16);
#undef TEST_SIZEOF #undef TEST_SIZEOF
@@ -168,7 +196,15 @@ int main() {
//run each test set, returning the total errors given //run each test set, returning the total errors given
int total = 0, res = 0; int total = 0, res = 0;
#if TOY_BITNESS == 32
#if TOY_BITNESS == 64
res = test_sizeof_ast_64bit();
total += res;
if (res == 0) {
printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET);
}
#elif TOY_BITNESS == 32
res = test_sizeof_ast_32bit(); res = test_sizeof_ast_32bit();
total += res; total += res;
@@ -176,7 +212,7 @@ int main() {
printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET); printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET);
} }
#else #else
fprintf(stderr, TOY_CC_WARN "WARNING: Skipping test_sizeof_ast_32bit(); Can't determine the 'bitness' of this platform\n" TOY_CC_RESET); fprintf(stderr, TOY_CC_WARN "WARNING: Skipping test_sizeof_ast_*bit(); Can't determine the 'bitness' of this platform (seems to be %d)\n" TOY_CC_RESET, TOY_BITNESS);
#endif #endif
{ {

View File

@@ -3,6 +3,16 @@ CC=gcc
CFLAGS=-g -Wall -Werror -Wno-unused-parameter -Wno-unused-function -Wno-unused-variable CFLAGS=-g -Wall -Werror -Wno-unused-parameter -Wno-unused-function -Wno-unused-variable
LIBS=-lm LIBS=-lm
ifeq ($(shell uname),Linux)
LDFLAG=-Wl,--gc-sections
else ifeq ($(OS),Windows_NT)
LDFLAG=-Wl,--gc-sections
else ifeq ($(shell uname),Darwin)
LDFLAG=-Wl,-dead_strip
else
@echo "LDFLAG set failed - what platform is this?"
endif
#directories #directories
TEST_ROOTDIR=.. TEST_ROOTDIR=..
TEST_SOURCEDIR=$(TEST_ROOTDIR)/$(TOY_SOURCEDIR) TEST_SOURCEDIR=$(TEST_ROOTDIR)/$(TOY_SOURCEDIR)
@@ -16,14 +26,20 @@ TEST_SOURCEFILES=$(addprefix $(TOY_ROOTDIR)/,$(TOY_SOURCEFILES))
TEST_CASESFILES=$(wildcard $(TEST_CASESDIR)/*.c) TEST_CASESFILES=$(wildcard $(TEST_CASESDIR)/*.c)
#build the object files, compile the test cases, and run #build the object files, compile the test cases, and run
all: clean build-source build-cases $(addprefix $(TEST_OUTDIR)/,$(notdir $(TEST_CASESFILES:%.c=%.exe))) all: clean build-source build-cases build-link build-run
#targets for each set of source files #targets for each step
.PHONY: build-source .PHONY: build-source
build-source: $(TEST_OUTDIR) $(TEST_OBJDIR) $(addprefix $(TEST_OBJDIR)/,$(notdir $(TEST_SOURCEFILES:.c=.o))) build-source: $(TEST_OUTDIR) $(TEST_OBJDIR) $(addprefix $(TEST_OBJDIR)/,$(notdir $(TEST_SOURCEFILES:.c=.o)))
.PHONY: build-cases .PHONY: build-cases
build-cases: $(TEST_OUTDIR) $(TEST_OBJDIR) $(addprefix $(TEST_OBJDIR)/,$(notdir $(TEST_CASESFILES:.c=.o))) build-cases: $(TEST_OUTDIR) $(TEST_OBJDIR) $(addprefix $(TEST_OBJDIR)/,$(notdir $(TEST_CASESFILES:.c=.o)))
.PHONY: build-link
build-link: $(TEST_OUTDIR) $(TEST_OBJDIR) $(addprefix $(TEST_OUTDIR)/,$(notdir $(TEST_CASESFILES:%.c=%.exe)))
.PHONY: build-run
build-run: $(addprefix $(TEST_OUTDIR)/,$(notdir $(TEST_CASESFILES:%.c=%.exe))) $(addprefix $(TEST_OUTDIR)/,$(notdir $(TEST_CASESFILES:%.c=%.run)))
#util targets #util targets
$(TEST_OUTDIR): $(TEST_OUTDIR):
@@ -32,17 +48,29 @@ $(TEST_OUTDIR):
$(TEST_OBJDIR): $(TEST_OBJDIR):
mkdir $(TEST_OBJDIR) mkdir $(TEST_OBJDIR)
#compilation step #compilation steps
$(TEST_OBJDIR)/%.o: $(TEST_SOURCEDIR)/%.c $(TEST_OBJDIR)/%.o: $(TEST_SOURCEDIR)/%.c
$(CC) -c -o $@ $< $(addprefix -I,$(TEST_SOURCEDIR)) $(CFLAGS) -fdata-sections -ffunction-sections $(CC) -c -o $@ $< $(addprefix -I,$(TEST_SOURCEDIR)) $(CFLAGS) -fdata-sections -ffunction-sections
$(TEST_OBJDIR)/%.o: $(TEST_CASESDIR)/%.c $(TEST_OBJDIR)/%.o: $(TEST_CASESDIR)/%.c
$(CC) -c -o $@ $< $(addprefix -I,$(TEST_SOURCEDIR) $(TEST_CASESDIR)) $(CFLAGS) -fdata-sections -ffunction-sections $(CC) -c -o $@ $< $(addprefix -I,$(TEST_SOURCEDIR) $(TEST_CASESDIR)) $(CFLAGS) -fdata-sections -ffunction-sections
#final linking step (with extra flags to strip dead code)
$(TEST_OUTDIR)/%.exe: $(TEST_OBJDIR)/%.o $(TEST_OUTDIR)/%.exe: $(TEST_OBJDIR)/%.o
@$(CC) -o $@ $< $(addprefix $(TEST_OBJDIR)/,$(notdir $(TEST_SOURCEFILES:.c=.o))) $(CFLAGS) $(LIBS) -Wl,--gc-sections @$(CC) -o $@ $< $(addprefix $(TEST_OBJDIR)/,$(notdir $(TEST_SOURCEFILES:.c=.o))) $(CFLAGS) $(LIBS) $(LDFLAGS)
$@
.PRECIOUS: $(TEST_OUTDIR)/%.run
$(TEST_OUTDIR)/%.run: $(TEST_OUTDIR)/%.exe
$<
#debugging targets
all-gdb: clean build-source build-cases build-link build-run-gdb
.PHONY: build-run-gdb
build-run-gdb: $(addprefix $(TEST_OUTDIR)/,$(notdir $(TEST_CASESFILES:%.c=%.exe))) $(addprefix $(TEST_OUTDIR)/,$(notdir $(TEST_CASESFILES:%.c=%.run-gdb)))
.PRECIOUS: $(TEST_OUTDIR)/%.run-gdb
$(TEST_OUTDIR)/%.run-gdb: $(TEST_OUTDIR)/%.exe
gdb $< -ex "run" --batch
#util commands #util commands
.PHONY: clean .PHONY: clean