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

View File

@@ -6,12 +6,10 @@
// === TYPE DEFINITIONS === // // === TYPE DEFINITIONS === //
typedef struct GravityOpaqueModule* GravityModule; typedef struct GravityOpaqueModule* GravityModule;
typedef struct GravityOpaqueValue* GravityValue; typedef struct GravityOpaqueValue* GravityValue;
typedef struct GravityOpaqueBuilder* GravityBuilder; typedef struct GravityOpaqueBuilder* GravityBuilder;
typedef struct GravityOpaqueFunction* GravityFunction; typedef struct GravityOpaqueFunction* GravityFunction;
typedef struct GravityOpaqueBlock* GravityBlock;
typedef struct GravityOpaqueType* GravityType; typedef struct GravityOpaqueType* GravityType;
typedef enum { typedef enum {
@@ -27,9 +25,20 @@ GravityModule gravityCreateModule(void);
GravityBuilder gravityCreateBuilder(void); GravityBuilder gravityCreateBuilder(void);
GravityFunction gravityNewFunction(GravityModule module, const char* name, GravityType functionType); 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 gravityCreateFunctionType(int numArgs, GravityType* argTypes, GravityType returnType);
GravityType gravityCreateIntegerType(uint8_t width, bool isSigned); 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 #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 "list.h"
#include "instruction.h" #include "instruction.h"
#include "type.h"
typedef struct GravityOpaqueBlock* GravityBlock;
UseList(GravityInstruction); UseList(GravityInstruction);
typedef struct { struct GravityOpaqueBlock {
const char* name;
GravityType* paramTypes;
uint16_t numParams;
List(GravityInstruction) instructions; List(GravityInstruction) instructions;
} GravityBlock; };
char* gravityBlockToCStr(GravityBlock block);
#endif #endif

View File

@@ -1,8 +1,44 @@
#include "builder.h" #include "builder.h"
GravityBuilder* gravityCreateBuilder(void) { void gravityBuildInstruction(GravityBuilder builder, GravityOpcode opcode, GravityValue* operands, size_t numOperands, GravityValue result) {
GravityBuilder* newBuilder = malloc(sizeof(GravityBuilder)); 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; if (newBuilder == NULL) return newBuilder;
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 "block.h"
#include <stdlib.h> #include <stdlib.h>
#include <assert.h>
typedef struct GravityOpaqueBuilder* GravityBuilder; typedef struct GravityOpaqueBuilder* GravityBuilder;
struct { struct GravityOpaqueBuilder {
GravityBlock currentBlock; GravityBlock currentBlock;
} GravityOpaqueBuilder; };
GravityBuilder gravityCreateBuilder(void); GravityBuilder gravityCreateBuilder(void);
void gravityPositionBuilderAtEnd(GravityBuilder builder, GravityBlock block);
GravityValue gravityBuildAlloc(GravityBuilder builder, GravityType type, const char* name);
#endif #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 "type.h"
#include "block.h" #include "block.h"
#include "list.h" #include "list.h"
#include <assert.h> #include "strb.h"
#include <stdint.h>
#include <stdarg.h>
#include <string.h>
UseList(GravityBlock); UseList(GravityBlock);
@@ -13,6 +16,10 @@ typedef struct GravityOpaqueFunction* GravityFunction;
struct GravityOpaqueFunction { struct GravityOpaqueFunction {
GravityFunctionType functionType; GravityFunctionType functionType;
List(GravityBlock) blocks; List(GravityBlock) blocks;
const char* name;
}; };
GravityBlock gravityStartBlock(const char* name, GravityFunction function, uint16_t numBlockParams, ...);
char* gravityFunctionToCStr(GravityFunction function);
#endif #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> #include <stddef.h>
typedef enum { typedef enum {
GravityOpcodeAdd = 0 GravityOpcodeAlloc = 0,
GravityOpcodeStore,
GravityOpcodeLoad
} GravityOpcode; } GravityOpcode;
typedef struct { typedef struct {
GravityOpcode opcode; GravityOpcode opcode;
GravityValue* operands; GravityValue* operands;
size_t numOperands; size_t numOperands;
GravityValue result;
} GravityInstruction; } GravityInstruction;
char* gravityInstructionToCStr(GravityInstruction inst);
char* gravityOpcodeToCStr(GravityOpcode opcode);
#endif #endif

View File

@@ -15,10 +15,23 @@ GravityFunction gravityNewFunction(GravityModule module, const char* name, Gravi
GravityFunction newFunc = malloc(sizeof(struct GravityOpaqueFunction)); GravityFunction newFunc = malloc(sizeof(struct GravityOpaqueFunction));
if (newFunc == NULL) return newFunc; if (newFunc == NULL) return newFunc;
newFunc->name = strdup(name);
newFunc->blocks = newList(GravityBlock); newFunc->blocks = newList(GravityBlock);
newFunc->functionType = functionType->function; newFunc->functionType = functionType->function;
append(module->functions, newFunc); append(module->functions, newFunc);
return 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 "function.h"
#include "list.h" #include "list.h"
#include "strb.h"
#include <stdlib.h> #include <stdlib.h>
#include <assert.h>
typedef struct GravityOpaqueModule* GravityModule; typedef struct GravityOpaqueModule* GravityModule;
@@ -17,4 +19,6 @@ GravityModule gravityCreateModule(void);
GravityFunction gravityNewFunction(GravityModule module, const char* name, GravityType functionType); GravityFunction gravityNewFunction(GravityModule module, const char* name, GravityType functionType);
char* gravityModuleToCStr(GravityModule module);
#endif #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 gravityCreateType(void) {
GravityType type = malloc(sizeof(struct GravityOpaqueType)); GravityType type = malloc(sizeof(struct GravityOpaqueType));
type->typeKind = GravityIntTypeKind;
return type; return type;
} }
@@ -24,4 +25,47 @@ GravityType gravityCreateIntegerType(uint8_t width, bool isSigned) {
type->integer.isSigned = isSigned; type->integer.isSigned = isSigned;
return type; 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 #define __GRAVITY__TYPE_H
#include "list.h" #include "list.h"
#include "strb.h"
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#include <assert.h>
typedef struct GravityOpaqueType* GravityType; typedef struct GravityOpaqueType* GravityType;
@@ -13,6 +15,7 @@ typedef enum {
GravityFloatTypeKind, GravityFloatTypeKind,
GravityPointerTypeKind, GravityPointerTypeKind,
GravityFunctionTypeKind, GravityFunctionTypeKind,
GravityTypeTypeKind, // type name
} GravityTypeKind; } GravityTypeKind;
typedef struct { typedef struct {
@@ -31,11 +34,17 @@ struct GravityOpaqueType {
union { union {
GravityFunctionType function; GravityFunctionType function;
GravityIntType integer; GravityIntType integer;
GravityType typeData;
}; };
}; };
UseList(GravityType);
GravityType gravityCreateFunctionType(int numArgs, GravityType* argTypes, GravityType returnType); GravityType gravityCreateFunctionType(int numArgs, GravityType* argTypes, GravityType returnType);
GravityType gravityCreateIntegerType(uint8_t width, bool isSigned); GravityType gravityCreateIntegerType(uint8_t width, bool isSigned);
GravityType gravityCreateType(void); GravityType gravityCreateType(void);
GravityType gravityCreatePointerType(void);
char* gravityTypeToCStr(GravityType type);
#endif #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" #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; GravityType type;
const char* name; const char* name; // local name
} GravityValue;
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 #endif

8
test.c
View File

@@ -5,10 +5,16 @@ int main(void) {
GravityModule module = gravityCreateModule(); GravityModule module = gravityCreateModule();
GravityBuilder builder = gravityCreateBuilder(); GravityBuilder builder = gravityCreateBuilder();
GravityType charType = gravityCreateIntegerType(1, false); GravityType charType = gravityCreateIntegerType(8, false);
GravityType mainFuncType = gravityCreateFunctionType(0, NULL, charType); GravityType mainFuncType = gravityCreateFunctionType(0, NULL, charType);
GravityFunction mainFunc = gravityNewFunction(module, "main", mainFuncType); 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; return 0;
} }