source/lexer.o \
source/ast.o \
source/types.o \
- source/syms.o
+ source/syms.o \
+ source/codegen.o
.PHONY: all tests specs
all: sclpl tests specs
--- /dev/null
+#include <sclpl.h>
+
+void codegen_init(Parser* p) {
+ sym_add(&(p->syms), SF_TYPEDEF, "void", VoidType());
+ sym_add(&(p->syms), SF_TYPEDEF, "bool", UIntType(1u));
+ sym_add(&(p->syms), SF_TYPEDEF, "byte", UIntType(8u));
+ sym_add(&(p->syms), SF_TYPEDEF, "uint", UIntType(64u));
+ sym_add(&(p->syms), SF_TYPEDEF, "u8", UIntType(8u));
+ sym_add(&(p->syms), SF_TYPEDEF, "u16", UIntType(16u));
+ sym_add(&(p->syms), SF_TYPEDEF, "u32", UIntType(32u));
+ sym_add(&(p->syms), SF_TYPEDEF, "u64", UIntType(64u));
+ sym_add(&(p->syms), SF_TYPEDEF, "int", IntType(64u));
+ sym_add(&(p->syms), SF_TYPEDEF, "i8", IntType(8u));
+ sym_add(&(p->syms), SF_TYPEDEF, "i16", IntType(16u));
+ sym_add(&(p->syms), SF_TYPEDEF, "i32", IntType(32u));
+ sym_add(&(p->syms), SF_TYPEDEF, "i64", IntType(64u));
+ sym_add(&(p->syms), SF_TYPEDEF, "string",
+ ArrayOf(sym_get(&(p->syms), "byte")->type, -1));
+}
char* ARGV0;
char* Artifact = "ast";
-/* Builtin Types
- *****************************************************************************/
-static void builtins(Parser* p) {
- sym_addtype(&(p->syms), "void", VoidType());
- sym_addtype(&(p->syms), "bool", UIntType(1u));
- sym_addtype(&(p->syms), "byte", UIntType(8u));
- sym_addtype(&(p->syms), "uint", UIntType(64u));
- sym_addtype(&(p->syms), "u8", UIntType(8u));
- sym_addtype(&(p->syms), "u16", UIntType(16u));
- sym_addtype(&(p->syms), "u32", UIntType(32u));
- sym_addtype(&(p->syms), "u64", UIntType(64u));
- sym_addtype(&(p->syms), "int", IntType(64u));
- sym_addtype(&(p->syms), "i8", IntType(8u));
- sym_addtype(&(p->syms), "i16", IntType(16u));
- sym_addtype(&(p->syms), "i32", IntType(32u));
- sym_addtype(&(p->syms), "i64", IntType(64u));
- sym_addtype(&(p->syms), "string",
- ArrayOf(sym_get(&(p->syms), "byte")->type, -1));
-}
-
/* Driver Modes
*****************************************************************************/
static int emit_tokens(void) {
static int emit_ast(void) {
AST* tree = NULL;
Parser ctx = { .input = stdin };
- builtins(&ctx);
+ codegen_init(&ctx);
while(NULL != (tree = toplevel(&ctx)))
pprint_tree(stdout, tree, 0);
return 0;
} else if (0 == strcmp("bin", Artifact)) {
return emit_binary();
} else {
- fprintf(stderr, "Unknonwn artifact type: '%s'\n\n", Artifact);
+ fprintf(stderr, "Unknown artifact type: '%s'\n\n", Artifact);
usage();
}
return 1;
#include <sclpl.h>
+#include <stdarg.h>
static AST* const_definition(Parser* p, bool constant);
static AST* const_expression(Parser* p);
return &(p->tok);
}
-static void error(Parser* parser, const char* text) {
+static void error(Parser* parser, const char* fmt, ...) {
Tok* tok = peek(parser);
- fprintf(stderr, "<file>:%zu:%zu:Error: %s\n", tok->line, tok->col, text);
+ va_list args;
+ va_start(args, fmt);
+ fprintf(stderr, "<file>:%zu:%zu: error: ", tok->line, tok->col);
+ vfprintf(stderr, fmt, args);
+ fprintf(stderr, "\n");
+ va_end(args);
exit(1);
}
}
static AST* const_definition(Parser* p, bool constant) {
- AST* expr;
Tok* id = expect_val(p, T_ID);
- type_annotation(p);
+ Type* type = type_annotation(p);
expect(p, T_ASSIGN);
- expr = const_expression(p);
+ AST* expr = const_expression(p);
+ sym_add(&(p->syms), (constant ? SF_CONSTANT : 0), id->value.text, type);
return Var(id, expr, constant);
}
}
static Type* type_annotation(Parser* p) {
- expect(p, T_ID);
- return NULL;
+ Tok* id = expect_val(p, T_ID);
+ Sym* sym = sym_get(&(p->syms), id->value.text);
+ if (!sym) error(p, "unknown type '%s'", id->value.text);
+ return sym->type;
}
static AST* literal(Parser* p) {
/* Symbol Table
*****************************************************************************/
+typedef enum {
+ SF_TYPEDEF = (1 << 0),
+ SF_CONSTANT = (1 << 1),
+} SymFlags;
+
typedef struct Sym {
struct Sym* next;
bool is_typedef;
+ int flags;
char* name;
Type* type;
} Sym;
Sym* syms;
} SymTable;
-void sym_adddef(SymTable* syms, char* name, Type* type);
-void sym_addtype(SymTable* syms, char* name, Type* type);
+void sym_add(SymTable* syms, int flags, char* name, Type* type);
Sym* sym_get(SymTable* syms, char* name);
/* AST Types
void gettoken(Parser* ctx, Tok* tok);
AST* toplevel(Parser* p);
+void codegen_init(Parser* p);
/* Option Parsing
*****************************************************************************/
#include <sclpl.h>
-Sym* mksym(char* name, Type* type, bool is_typedef, Sym* next) {
+static Sym* mksym(int flags, char* name, Type* type, Sym* next) {
Sym* sym = emalloc(sizeof(Sym));
+ sym->flags = flags;
sym->name = name;
sym->type = type;
- sym->is_typedef = is_typedef;
sym->next = next;
return sym;
}
-void sym_adddef(SymTable* syms, char* name, Type* type) {
- syms->syms = mksym(name, type, false, syms->syms);
-}
-
-void sym_addtype(SymTable* syms, char* name, Type* type) {
- syms->syms = mksym(name, type, true, syms->syms);
+void sym_add(SymTable* syms, int flags, char* name, Type* type) {
+ syms->syms = mksym(flags, name, type, syms->syms);
}
Sym* sym_get(SymTable* syms, char* name) {