commit 8663eea2b2bc76a6c09345192f96f286281e08d0
parent dc25e4200eeff678683392c400adeef6f13cc0e8
Author: Brian Swetland <swetland@frotz.net>
Date: Wed, 4 Mar 2020 15:44:34 -0800
tlc: rearrange around new Object/Type model
similar to the oberon compiler
Diffstat:
M | src/tlc.c | | | 344 | +++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------- |
1 file changed, 222 insertions(+), 122 deletions(-)
diff --git a/src/tlc.c b/src/tlc.c
@@ -5,6 +5,7 @@
#include <stdlib.h>
#include <stdarg.h>
#include <stdint.h>
+#include <stdbool.h>
#include <strings.h>
#include <string.h>
@@ -14,6 +15,8 @@
#define FNMAXARGS 8
+#define nil 0
+
typedef uint32_t u32;
typedef int32_t i32;
@@ -44,17 +47,15 @@ char *tnames[] = {
typedef struct StringRec* String;
-typedef struct SymbolRec* Symbol;
-typedef struct ScopeRec* Scope;
+typedef struct ObjectRec* Object;
typedef struct TypeRec* Type;
-typedef struct FuncRec* Func;
+typedef struct ItemRec* Item;
typedef struct CtxRec* Ctx;
typedef struct StringRec StringRec;
-typedef struct SymbolRec SymbolRec;
-typedef struct ScopeRec ScopeRec;
+typedef struct ObjectRec ObjectRec;
typedef struct TypeRec TypeRec;
-typedef struct FuncRec FuncRec;
+typedef struct ItemRec ItemRec;
typedef struct CtxRec CtxRec;
struct StringRec {
@@ -63,17 +64,83 @@ struct StringRec {
char text[0];
};
-#define TF_INTEGER 0x01
-#define TF_SIGNED 0x02
-#define TF_VOID 0x04
+// ------------------------------------------------------------------
-struct TypeRec {
- Type next;
+struct ObjectRec {
+ u32 kind;
+ u32 flags;
+ u32 value;
+ Object next; // link in list
+ Object first; // list of...
+ Type type;
String name;
+};
+
+// Object Kind IDs
+enum {
+ oConst,
+ oVar,
+ oParam,
+ oField,
+ oType,
+};
+
+// Object Flags
+#define ofReadOnly 1
+#define ofPublic 2
+#define ofDefined 4
+
+// ------------------------------------------------------------------
+
+struct TypeRec {
+ u32 kind;
+ Object obj; // if we're non-anonymous
+ Object first; // list of Params or Fields
+ Type base; // Pointer-to, Func-return, or Array-elem
+ u32 len; // of Array
+ u32 size; // of Type in Memory
+};
+
+// Type Kind IDs
+enum {
+ tVoid,
+ tByte,
+ tBool,
+ tInt32,
+ tNil,
+ tString,
+ tPointer,
+ tArray,
+ rRecord,
+ tFunc,
+};
+
+// ------------------------------------------------------------------
+
+struct ItemRec {
+ u32 kind;
u32 flags;
- u32 width;
+ Type type;
+ u32 r;
+ u32 a;
+ u32 b;
+};
+
+// Item Kind IDs
+enum { // r a b
+ iConst, // - value -
+ iVar, // base offset
+ iParam, // - offset0 offset1
+ iReg, // regno
+ iRegInd, // regno offset
+ iCond, // ccode f-chain t-chain
};
+// Item Flags
+#define ifReadOnly 1
+
+// ------------------------------------------------------------------
+
struct CtxRec {
const char* source; // entire source file
const char* sptr; // tokenizer source pointer
@@ -86,42 +153,18 @@ struct CtxRec {
char tmp[256]; // used for tNAME, tTYPE, tNUMBER, tSTRING;
String strtab; // TODO: hashtable
- Type typetab; // TODO: hashtable
- Symbol symtab; // TODO: hashtable, globals
- Scope scope;
+ Object typetab; // TODO: hashtable
+ Object symtab; // TODO: hashtable, globals
+ Object scope;
Type type_void;
- Type type_i32;
- Type type_u32;
-};
-
-struct ScopeRec {
- Scope next;
- Symbol first;
+ Type type_byte;
+ Type type_bool;
+ Type type_int32;
+ Type type_nil;
+ Type type_string;
};
-#define SF_REGISTER 0x01
-#define SF_FRAMEREL 0x02
-#define SF_GLOBAL 0x04 // global variable
-#define SF_FUNC 0x08 // function
-#define SF_DEFINED 0x10 // defined, not just declared (function)
-
-struct SymbolRec {
- Symbol next;
- String name;
- Type type;
- u32 flags;
- i32 posn;
- i32 regno;
- Func func;
-};
-
-struct FuncRec {
- ScopeRec scope;
- u32 pcount;
- Type type; // return type
- SymbolRec param[0];
-};
String mkstring(Ctx ctx, const char* text, unsigned len) {
String str;
@@ -142,23 +185,67 @@ String mkstring(Ctx ctx, const char* text, unsigned len) {
return str;
}
-Type mktype(Ctx ctx, const char* text, unsigned len, unsigned flags, unsigned width) {
+Type mktype(Ctx ctx, const char* text, u32 len, u32 kind, u32 size) {
String str = mkstring(ctx, text, len);
Type type = malloc(sizeof(TypeRec));
- type->name = str;
- type->width = width;
- type->next = ctx->typetab;
- ctx->typetab = type;
+ Object obj = malloc(sizeof(ObjectRec));
+
+ type->kind = kind;
+ type->obj = obj;
+ type->first = nil;
+ type->base = nil;
+ type->len = 0;
+ type->size = size;
+
+ obj->kind = oType;
+ obj->flags = 0;
+ obj->value = 0;
+ obj->next = nil;
+ obj->first = nil;
+ obj->type = type;
+ obj->name = str;
+
+ obj->next = ctx->typetab;
+ ctx->typetab = obj;
+
return type;
}
void init_ctx(Ctx ctx) {
memset(ctx, 0, sizeof(CtxRec));
- // install built-in plain types
- ctx->type_void = mktype(ctx, "void", 4, TF_VOID, 0);
- ctx->type_i32 = mktype(ctx, "i32", 3, TF_INTEGER | TF_SIGNED, 4);
- ctx->type_u32 = mktype(ctx, "u32", 3, TF_SIGNED, 4);
+ // install built-in basic types
+ ctx->type_void = mktype(ctx, "void", 4, tVoid, 0);
+ ctx->type_byte = mktype(ctx, "byte", 4, tByte, 1);
+ ctx->type_bool = mktype(ctx, "bool", 4, tBool, 1);
+ ctx->type_int32 = mktype(ctx, "i32", 3, tInt32, 4);
+ ctx->type_nil = mktype(ctx, "nil", 3, tNil, 4);
+ ctx->type_string = mktype(ctx, "str", 3, tString, 8);
+}
+
+bool sametype(Type a, Type b) {
+ if (a->kind != b->kind) {
+ return false;
+ }
+ if (a->base != b->base) {
+ return false;
+ }
+ if (a->len != b->len) {
+ return false;
+ }
+ Object a1 = a->first;
+ Object b1 = b->first;
+ while ((a1 != nil) && (b1 != nil)) {
+ // check that parameters and fields match
+ if (!sametype(a1->type, b1->type)) {
+ return false;
+ }
+ }
+ if ((a1 != nil) || (b1 != nil)) {
+ // mismatched number of parameters or fields
+ return false;
+ }
+ return true;
}
void error(Ctx ctx, const char *fmt, ...) {
@@ -462,22 +549,50 @@ String parse_name(Ctx ctx, const char* what) {
Type parse_type(Ctx ctx) {
String tname = parse_name(ctx, "type name");
- for (Type type = ctx->typetab; type != NULL; type = type->next) {
- if (type->name == tname) {
- return type;
+ for (Object obj = ctx->typetab; obj != nil; obj = obj->next) {
+ if (obj->name == tname) {
+ return obj->type;
}
}
error(ctx, "unknown type name '%s'", tname->text);
- return NULL;
+ return nil;
}
void parse_function_body(Ctx ctx) {
error(ctx, "unsupported");
}
+Object parse_param(Ctx ctx, String fname, u32 n, Object first, Object last) {
+ if (n == FNMAXARGS) {
+ error(ctx, "too many parameters (%d) for '%s'", FNMAXARGS, fname->text);
+ }
+ Object param = malloc(sizeof(ObjectRec));
+ param->kind = oParam;
+ param->flags = 0;
+ param->value = n;
+ param->next = nil;
+ param->first = nil;
+ param->name = parse_name(ctx, "parameter name");
+ param->type = parse_type(ctx);
+
+ Object obj = first;
+ while (obj != nil) {
+ if (obj->name == param->name) {
+ error(ctx, "duplicate parameter name '%s'", fname->text);
+ }
+ obj = obj->next;
+ }
+
+ if (last != nil) {
+ last->next = param;
+ }
+ return param;
+}
+
void parse_function(Ctx ctx) {
- SymbolRec param[FNMAXARGS];
- unsigned n = 0;
+ Object first = nil;
+ Object last = nil;
+ u32 n = 0;
String fname = parse_name(ctx, "funcion name");
Type ftype = ctx->type_void;
@@ -485,32 +600,13 @@ void parse_function(Ctx ctx) {
// process parameters
if (ctx->tok != tCPAREN) {
- for (;;) {
- if (n == FNMAXARGS) {
- error(ctx, "too many parameters (%d)", FNMAXARGS);
- }
-
- String name = parse_name(ctx, "parameter name");
- Type type = parse_type(ctx);
-
- for (unsigned i = 0; i < n; i++) {
- if (param[i].name == name) {
- error(ctx, "duplicate parameter name '%s'", name->text);
- }
- }
-
- param[n].name = name;
- param[n].type = type;
- param[n].flags = SF_FRAMEREL;
- param[n].posn = -4 * (n + 1);
- param[n].regno = 0;
- param[n].next = NULL;
- n++;
-
- if (ctx->tok != tCOMMA) {
- break;
- }
+ first = parse_param(ctx, fname, n, nil, nil);
+ last = first;
+ n++;
+ while (ctx->tok == tCOMMA) {
next(ctx, 0);
+ last = parse_param(ctx, fname, n, first, last);
+ n++;
}
}
@@ -534,62 +630,66 @@ void parse_function(Ctx ctx) {
// Look for an existing declaration or definintion of this function
// and if it exists, ensure that we are in argeement with it
- Symbol sym;
- for (sym = ctx->symtab; sym != NULL; sym = sym->next) {
- if (sym->name == fname) {
- if (!(sym->flags & SF_FUNC)) {
- error(ctx, "redefining variable as function '%s'", fname->text);
+ Object obj = ctx->symtab;
+ while (obj != nil) {
+ if (obj->name == fname) {
+ if (obj->type->kind != tFunc) {
+ error(ctx, "redefining '%s' as function", fname->text);
}
if (!isdef) {
error(ctx, "redeclared function '%s'", fname->text);
}
- if (sym->flags & SF_DEFINED) {
+ if (obj->flags & ofDefined) {
error(ctx, "redefined function '%s'", fname->text);
}
- int bad = 0;
- if (n != sym->func->pcount) {
- bad = 1;
- } else if (ftype != sym->func->type) {
- bad = 1;
- } else {
- for (unsigned i = 0; i < n; i++) {
- if (sym->func->param[i].type != param[i].type) {
- bad = 1;
- break;
- }
+ if (ftype != obj->type->base) {
+ error(ctx, "function definition mismatch for '%s' (return type)", fname->text);
+ }
+ Object pa = first;
+ Object pb = obj->type->first;
+ u32 i = 1;
+ while ((pa != nil) && (pb != nil)) {
+ if (!sametype(pa->type, pb->type)) {
+ error(ctx, "function definition mismatch for '%s' (parameter #%u)", fname->text, i);
}
+ pa = pa->next;
+ pb = pb->next;
}
- if (bad) {
- error(ctx, "function declaration/definition mismatch for '%s'", fname->text);
+ if ((pa != nil) || (pb != nil)) {
+ error(ctx, "function definition mismatch for '%s' (parameter count mismatch)", fname->text);
}
break;
}
+ obj = obj->next;
}
// if there was no existing record of this function, create one now
- if (sym == NULL) {
- Func func = malloc(sizeof(FuncRec) + sizeof(SymbolRec) * n);
- func->scope.next = NULL;
- func->scope.first = NULL;
- func->type = ftype;
- func->pcount = n;
- memcpy(func->param, param, sizeof(SymbolRec) * n);
-
- sym = malloc(sizeof(SymbolRec));
- sym->name = fname;
- sym->type = NULL;
- sym->flags = SF_FUNC;
- sym->posn = 0;
- sym->regno = 0;
- sym->func = func;
-
- sym->next = ctx->symtab;
- ctx->symtab = sym;
+ if (obj == nil) {
+ Type type = malloc(sizeof(TypeRec));
+ obj = malloc(sizeof(ObjectRec));
+
+ type->kind = tFunc;
+ type->obj = obj;
+ type->first = first;
+ type->base = ftype;
+ type->len = 0;
+ type->size = 0;
+
+ obj->kind = oType; //??
+ obj->flags = 0;
+ obj->value = 0;
+ obj->next = nil;
+ obj->first = first;
+ obj->type = type;
+ obj->name = fname;
+
+ obj->next = ctx->symtab;
+ ctx->symtab = obj;
}
// handle definition if it is one
if (isdef) {
- sym->flags |= SF_DEFINED;
+ obj->flags |= ofDefined;
parse_function_body(ctx);
}
}