start working on text representation and constants

This commit is contained in:
2026-08-03 21:01:34 +10:00
parent b4cb3aa56e
commit 15709b65a6
19 changed files with 457 additions and 18 deletions

View File

@@ -2,7 +2,7 @@ SRC=src
OBJ=obj
CC=gcc
CFLAGS=-Wall -Wextra -O3
CFLAGS=-Wall -Wextra -fPIC -O3
TARGET=libgravity.so
TEST_TARGET=testapp
@@ -17,7 +17,7 @@ $(OBJ)/%.o: $(SRC)/%.c
$(CC) $(CFLAGS) -c $< -o $@
$(TEST_TARGET): test.c $(TARGET)
$(CC) $(CFLAGS) test.c -lgravity -L. -o $(TEST_TARGET)
$(CC) $(CFLAGS) test.c -lgravity -L. -o $(TEST_TARGET)
test: $(TEST_TARGET)
@@ -25,9 +25,9 @@ setup:
mkdir -p $(OBJ)
clean:
rm -r $(OBJ)/*.o
rm $(TARGET)
rm $(TEST_TARGET)
rm -r $(OBJ)/*.o
install: $(TARGET)
sudo cp $(TARGET) /usr/local/lib/

View File

@@ -6,12 +6,10 @@
// === TYPE DEFINITIONS === //
typedef struct GravityOpaqueModule* GravityModule;
typedef struct GravityOpaqueValue* GravityValue;
typedef struct GravityOpaqueBuilder* GravityBuilder;
typedef struct GravityOpaqueFunction* GravityFunction;
typedef struct GravityOpaqueBlock* GravityBlock;
typedef struct GravityOpaqueType* GravityType;
typedef enum {
@@ -27,9 +25,20 @@ GravityModule gravityCreateModule(void);
GravityBuilder gravityCreateBuilder(void);
GravityFunction gravityNewFunction(GravityModule module, const char* name, GravityType functionType);
GravityBlock gravityStartBlock(const char* name, GravityFunction function, uint16_t numBlockParams, ...);
GravityValue newIntConstant(GravityType intType, int64_t value);
GravityType gravityCreateFunctionType(int numArgs, GravityType* argTypes, GravityType returnType);
GravityType gravityCreateIntegerType(uint8_t width, bool isSigned);
char* gravityModuleToCStr(GravityModule module);
char* gravityTypeToCStr(GravityType type);
char* gravityFunctionToCStr(GravityFunction function);
char* gravityValueToCStr(GravityValue value);
void gravityPositionBuilderAtEnd(GravityBuilder builder, GravityBlock block);
GravityValue gravityBuildAlloc(GravityBuilder builder, GravityType type, const char* name);
// ============================ //
#endif

24
src/block.c Normal file
View File

@@ -0,0 +1,24 @@
#include "block.h"
char* gravityBlockToCStr(GravityBlock block) {
StringBuffer buff;
initStringBuff(&buff);
// print block header
sbAppend(&buff, "%s (", block->name);
for (unsigned int i = 0; i < block->numParams; i++) {
if (i < block->numParams - 1) {
sbAppend(&buff, "%s, ", gravityTypeToCStr(block->paramTypes[i]));
} else {
sbAppend(&buff, "%s", gravityTypeToCStr(block->paramTypes[i]));
}
}
sbAppend(&buff, "):\n");
for (unsigned int i = 0; i < block->instructions.count; i++) {
GravityInstruction inst = *get(block->instructions, i);
sbAppend(&buff, " %s\n", gravityInstructionToCStr(inst));
}
return buff.data;
}

View File

@@ -3,11 +3,20 @@
#include "list.h"
#include "instruction.h"
#include "type.h"
typedef struct GravityOpaqueBlock* GravityBlock;
UseList(GravityInstruction);
typedef struct {
struct GravityOpaqueBlock {
const char* name;
GravityType* paramTypes;
uint16_t numParams;
List(GravityInstruction) instructions;
} GravityBlock;
};
char* gravityBlockToCStr(GravityBlock block);
#endif

View File

@@ -1,8 +1,44 @@
#include "builder.h"
GravityBuilder* gravityCreateBuilder(void) {
GravityBuilder* newBuilder = malloc(sizeof(GravityBuilder));
void gravityBuildInstruction(GravityBuilder builder, GravityOpcode opcode, GravityValue* operands, size_t numOperands, GravityValue result) {
assert(builder->currentBlock != NULL);
// copy operands list to avoid stack lifetime
GravityValue* operandsCopy = calloc(numOperands, sizeof(GravityValue));
if (!operandsCopy)
return;
memcpy(operandsCopy, operands, sizeof(GravityValue) * numOperands);
GravityInstruction newInst = {
.opcode = opcode,
.operands = operandsCopy,
.numOperands = numOperands,
.result = result
};
append(builder->currentBlock->instructions, newInst);
}
GravityBuilder gravityCreateBuilder(void) {
GravityBuilder newBuilder = malloc(sizeof(struct GravityOpaqueBuilder));
if (newBuilder == NULL) return newBuilder;
return newBuilder;
}
void gravityPositionBuilderAtEnd(GravityBuilder builder, GravityBlock block) {
builder->currentBlock = block;
}
GravityValue gravityBuildAlloc(GravityBuilder builder, GravityType type, const char* name) {
GravityValue result = gravityNewValue(name, gravityCreatePointerType());
GravityType wrapperType = gravityCreateType();
wrapperType->typeKind = GravityTypeTypeKind;
wrapperType->typeData = type;\
GravityValue constant = gravityNewConstant(wrapperType);
gravityBuildInstruction(builder, GravityOpcodeAlloc, (GravityValue[]){constant}, 1, result);
return result;
}

View File

@@ -3,13 +3,18 @@
#include "block.h"
#include <stdlib.h>
#include <assert.h>
typedef struct GravityOpaqueBuilder* GravityBuilder;
struct {
struct GravityOpaqueBuilder {
GravityBlock currentBlock;
} GravityOpaqueBuilder;
};
GravityBuilder gravityCreateBuilder(void);
void gravityPositionBuilderAtEnd(GravityBuilder builder, GravityBlock block);
GravityValue gravityBuildAlloc(GravityBuilder builder, GravityType type, const char* name);
#endif

57
src/function.c Normal file
View File

@@ -0,0 +1,57 @@
#include "function.h"
GravityBlock gravityStartBlock(const char* name, GravityFunction function, uint16_t numBlockParams, ...) {
GravityBlock newBlock = malloc(sizeof(struct GravityOpaqueBlock));
if (newBlock == NULL) return newBlock;
newBlock->name = strdup(name);
GravityType* paramTypes = calloc(numBlockParams, sizeof(GravityType));
if (paramTypes == NULL) {
free(newBlock);
return NULL;
}
va_list vargs;
va_start(vargs, numBlockParams);
for (unsigned int i = 0; i < numBlockParams; i++) {
paramTypes[i] = va_arg(vargs, GravityType);
}
newBlock->numParams = numBlockParams;
newBlock->paramTypes = paramTypes;
newBlock->instructions = newList(GravityInstruction);
append(function->blocks, newBlock);
return newBlock;
}
char* gravityFunctionToCStr(GravityFunction function) {
StringBuffer buff;
initStringBuff(&buff);
// print func header
sbAppend(&buff, "fn %s (", function->name);
for (unsigned int i = 0; i < function->functionType.numArgs; i++) {
if (i < function->functionType.numArgs) {
sbAppend(&buff, "%s, ", gravityTypeToCStr(function->functionType.argTypes[i]));
} else {
sbAppend(&buff, "%s", gravityTypeToCStr(function->functionType.argTypes[i]));
}
break;
}
// print function blocks
sbAppend(&buff, ") %s {\n", gravityTypeToCStr(function->functionType.returnType));
for (unsigned int i = 0; i < function->blocks.count; i++) {
GravityBlock block = *get(function->blocks, i);
sbAppend(&buff, "%s\n", gravityBlockToCStr(block));
}
sbAppend(&buff, "}");
return buff.data;
}

View File

@@ -4,7 +4,10 @@
#include "type.h"
#include "block.h"
#include "list.h"
#include <assert.h>
#include "strb.h"
#include <stdint.h>
#include <stdarg.h>
#include <string.h>
UseList(GravityBlock);
@@ -13,6 +16,10 @@ typedef struct GravityOpaqueFunction* GravityFunction;
struct GravityOpaqueFunction {
GravityFunctionType functionType;
List(GravityBlock) blocks;
const char* name;
};
GravityBlock gravityStartBlock(const char* name, GravityFunction function, uint16_t numBlockParams, ...);
char* gravityFunctionToCStr(GravityFunction function);
#endif

30
src/instruction.c Normal file
View File

@@ -0,0 +1,30 @@
#include "instruction.h"
char* gravityOpcodeToCStr(GravityOpcode opcode) {
switch (opcode) {
case GravityOpcodeAlloc: return "alloc";
case GravityOpcodeStore: return "store";
case GravityOpcodeLoad: return "load";
default: return "fixme";
}
}
char* gravityInstructionToCStr(GravityInstruction inst) {
StringBuffer buff;
initStringBuff(&buff);
if (inst.result != NULL) {
sbAppend(&buff, "%s = ", gravityValueToCStr(inst.result));
}
sbAppend(&buff, "%s ", gravityOpcodeToCStr(inst.opcode));
for (unsigned int i = 0; i < inst.numOperands; i++) {
if (i < inst.numOperands - 1) {
sbAppend(&buff, "%s, ", gravityValueToCStr(inst.operands[i]));
} else {
sbAppend(&buff, "%s", gravityValueToCStr(inst.operands[i]));
}
}
return buff.data;
}

View File

@@ -5,13 +5,19 @@
#include <stddef.h>
typedef enum {
GravityOpcodeAdd = 0
GravityOpcodeAlloc = 0,
GravityOpcodeStore,
GravityOpcodeLoad
} GravityOpcode;
typedef struct {
GravityOpcode opcode;
GravityValue* operands;
size_t numOperands;
GravityValue result;
} GravityInstruction;
char* gravityInstructionToCStr(GravityInstruction inst);
char* gravityOpcodeToCStr(GravityOpcode opcode);
#endif

View File

@@ -15,10 +15,23 @@ GravityFunction gravityNewFunction(GravityModule module, const char* name, Gravi
GravityFunction newFunc = malloc(sizeof(struct GravityOpaqueFunction));
if (newFunc == NULL) return newFunc;
newFunc->name = strdup(name);
newFunc->blocks = newList(GravityBlock);
newFunc->functionType = functionType->function;
append(module->functions, newFunc);
return newFunc;
}
char* gravityModuleToCStr(GravityModule module) {
StringBuffer buff;
initStringBuff(&buff);
for (unsigned int i = 0; i < module->functions.count; i++) {
GravityFunction func = *get(module->functions, i);
sbAppend(&buff, "%s\n\n", gravityFunctionToCStr(func));
}
return buff.data;
}

View File

@@ -3,7 +3,9 @@
#include "function.h"
#include "list.h"
#include "strb.h"
#include <stdlib.h>
#include <assert.h>
typedef struct GravityOpaqueModule* GravityModule;
@@ -17,4 +19,6 @@ GravityModule gravityCreateModule(void);
GravityFunction gravityNewFunction(GravityModule module, const char* name, GravityType functionType);
char* gravityModuleToCStr(GravityModule module);
#endif

37
src/strb.c Normal file
View File

@@ -0,0 +1,37 @@
#include "strb.h"
void initStringBuff(StringBuffer* sb) {
sb->capacity = 128;
sb->length = 0;
sb->data = (char*)malloc(sb->capacity);
sb->data[0] = '\0';
}
void sbAppend(StringBuffer* sb, const char* fmt, ...) {
va_list args;
va_start(args, fmt);
// Check how much space we need
va_list args_copy;
va_copy(args_copy, args);
int needed = vsnprintf(NULL, 0, fmt, args_copy);
va_end(args_copy);
if (needed < 0) {
va_end(args);
return;
}
// Grow buffer if needed
if (sb->length + needed >= sb->capacity) {
while (sb->length + needed >= sb->capacity) {
sb->capacity *= 2;
}
sb->data = (char*)realloc(sb->data, sb->capacity);
}
// Append the string safely
vsnprintf(sb->data + sb->length, needed + 1, fmt, args);
sb->length += needed;
va_end(args);
}

18
src/strb.h Normal file
View File

@@ -0,0 +1,18 @@
#ifndef __GRAVITY__STRB_H
#define __GRAVITY__STRB_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
typedef struct {
char* data;
size_t length;
size_t capacity;
} StringBuffer;
void initStringBuff(StringBuffer* sb);
void sbAppend(StringBuffer* sb, const char* fmt, ...);
#endif

View File

@@ -2,6 +2,7 @@
GravityType gravityCreateType(void) {
GravityType type = malloc(sizeof(struct GravityOpaqueType));
type->typeKind = GravityIntTypeKind;
return type;
}
@@ -24,4 +25,47 @@ GravityType gravityCreateIntegerType(uint8_t width, bool isSigned) {
type->integer.isSigned = isSigned;
return type;
}
GravityType gravityCreatePointerType(void) {
GravityType type = gravityCreateType();
if (type == NULL) return type;
type->typeKind = GravityPointerTypeKind;
return type;
}
char* gravityTypeToCStr(GravityType type) {
StringBuffer buff;
initStringBuff(&buff);
switch (type->typeKind) {
case GravityIntTypeKind: {
if (type->integer.isSigned) {
sbAppend(&buff, "i%d", type->integer.width);
} else {
sbAppend(&buff, "u%d", type->integer.width);
}
break;
}
case GravityPointerTypeKind: {
sbAppend(&buff, "pointer");
break;
}
case GravityTypeTypeKind: {
sbAppend(&buff, "%s", gravityTypeToCStr(type->typeData));
break;
}
default: {
sbAppend(&buff, "type_fixme");
break;
}
}
return buff.data;
}

View File

@@ -2,9 +2,11 @@
#define __GRAVITY__TYPE_H
#include "list.h"
#include "strb.h"
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include <assert.h>
typedef struct GravityOpaqueType* GravityType;
@@ -13,6 +15,7 @@ typedef enum {
GravityFloatTypeKind,
GravityPointerTypeKind,
GravityFunctionTypeKind,
GravityTypeTypeKind, // type name
} GravityTypeKind;
typedef struct {
@@ -31,11 +34,17 @@ struct GravityOpaqueType {
union {
GravityFunctionType function;
GravityIntType integer;
GravityType typeData;
};
};
UseList(GravityType);
GravityType gravityCreateFunctionType(int numArgs, GravityType* argTypes, GravityType returnType);
GravityType gravityCreateIntegerType(uint8_t width, bool isSigned);
GravityType gravityCreateType(void);
GravityType gravityCreatePointerType(void);
char* gravityTypeToCStr(GravityType type);
#endif

96
src/value.c Normal file
View File

@@ -0,0 +1,96 @@
#include "value.h"
uint32_t globalValueIncrementer = 0;
char* getIncrementedName(void) {
char* buffer = malloc(32);
if (buffer == NULL) return buffer;
snprintf(buffer, 32, "%%%d", globalValueIncrementer);
globalValueIncrementer++;
return buffer;
}
GravityValue gravityNewValue(const char* name, GravityType type) {
GravityValue newValue = malloc(sizeof(struct GravityOpaqueValue));
if (newValue == NULL) return newValue;
newValue->kind = GravityLocalValueKind;
newValue->type = type;
if (name == NULL) {
name = getIncrementedName();
} else {
name = strdup(name);
}
newValue->name = name;
return newValue;
}
GravityValue gravityTypeToTypeValue(GravityType type) {
GravityType valueType = gravityCreateType();
valueType->typeKind = GravityTypeTypeKind;
valueType->typeData = type;
GravityValue newValue = gravityNewValue(NULL, valueType);
if (newValue == NULL) return newValue;
return newValue;
}
char* gravityValueToCStr(GravityValue value) {
switch (value->kind) {
case GravityLocalValueKind:
return strdup(value->name);
case GravityConstantValueKind: {
StringBuffer buff;
initStringBuff(&buff);
switch (value->type->typeKind) {
case GravityIntTypeKind: {
sbAppend(&buff, "%ld", value->constant.intValue);
break;
}
case GravityTypeTypeKind: {
sbAppend(&buff, "%s", gravityTypeToCStr(value->type->typeData));
break;
}
default: assert(false);
}
return buff.data;
}
default: assert(false);
}
}
GravityValue gravityNewConstant(GravityType type) {
GravityValue newValue = malloc(sizeof(struct GravityOpaqueValue));
if (newValue == NULL) return newValue;
newValue->kind = GravityConstantValueKind;
newValue->type = type;
newValue->name = NULL;
return newValue;
}
GravityValue newIntConstant(GravityType intType, int64_t value) {
assert(intType->typeKind == GravityIntTypeKind);
GravityValue newValue = gravityNewConstant(intType);
if (newValue == NULL) return newValue;
newValue->constant.intValue = value;
return newValue;
}

View File

@@ -3,9 +3,38 @@
#include "type.h"
typedef struct {
extern uint32_t globalValueIncrementer;
typedef struct GravityOpaqueValue* GravityValue;
typedef struct GravityOpaqueConstant* GravityConstant;
typedef enum {
GravityLocalValueKind,
GravityConstantValueKind
} GravityValueKind;
struct GravityOpaqueValue {
GravityValueKind kind;
GravityType type;
const char* name;
} GravityValue;
const char* name; // local name
union {
int64_t intValue;
} constant;
};
struct GravityOpaqueConstant {
GravityType type;
union {
int64_t intValue;
};
};
GravityValue gravityNewValue(const char* name, GravityType type);
GravityValue gravityTypeToTypeValue(GravityType type);
char* gravityValueToCStr(GravityValue value);
GravityValue gravityNewConstant(GravityType type);
GravityValue newIntConstant(GravityType intType, int64_t value);
#endif

8
test.c
View File

@@ -5,10 +5,16 @@ int main(void) {
GravityModule module = gravityCreateModule();
GravityBuilder builder = gravityCreateBuilder();
GravityType charType = gravityCreateIntegerType(1, false);
GravityType charType = gravityCreateIntegerType(8, false);
GravityType mainFuncType = gravityCreateFunctionType(0, NULL, charType);
GravityFunction mainFunc = gravityNewFunction(module, "main", mainFuncType);
GravityBlock entryBlock = gravityStartBlock("entry", mainFunc, 0);
gravityPositionBuilderAtEnd(builder, entryBlock);
GravityValue something = gravityBuildAlloc(builder, charType, NULL);
printf("%s\n", gravityFunctionToCStr(mainFunc));
return 0;
}