clean up some stuff
This commit is contained in:
parent
1b14ecf5ff
commit
5e02ecd80d
10 changed files with 231 additions and 66 deletions
BIN
a.out
Executable file
BIN
a.out
Executable file
Binary file not shown.
104
src/codegen.c
104
src/codegen.c
|
@ -2,86 +2,114 @@
|
|||
#include "helpers.h"
|
||||
#include <stdio.h>
|
||||
|
||||
void codegen(Node node) {
|
||||
void codegen(Node node, bool emit_type) {
|
||||
switch(node.type) {
|
||||
case NODE_FUNCTION_CALL:
|
||||
codegen_function_call(node);
|
||||
codegen_function_call(node.function_call);
|
||||
break;
|
||||
case NODE_FUNCTION_DECL:
|
||||
codegen_function_decl(node);
|
||||
codegen_function_decl(node.function_decl);
|
||||
break;
|
||||
case NODE_FUNCTION_IMPL:
|
||||
codegen_function_impl(node);
|
||||
codegen_function_impl(node.function_impl);
|
||||
break;
|
||||
case NODE_ARG_DECL:
|
||||
codegen_arg_decl(node);
|
||||
codegen_arg_decl(node.arg_decl, emit_type);
|
||||
break;
|
||||
case NODE_REFERENCE:
|
||||
codegen_reference(node.reference, emit_type);
|
||||
break;
|
||||
case NODE_NUMBER:
|
||||
codegen_number(node);
|
||||
codegen_number(node.number, emit_type);
|
||||
break;
|
||||
case NODE_RETURN:
|
||||
codegen_return(node.ret);
|
||||
break;
|
||||
default:
|
||||
syntax_error("unexpected node %c", node.type);
|
||||
}
|
||||
}
|
||||
|
||||
void codegen_function_call(Node node) {
|
||||
printf("FunctionCall(%s", node.function_call.name);
|
||||
if(Nodes_size(&node.function_call.args) > 0)
|
||||
printf(", ");
|
||||
for(size_t i = 0; i < Nodes_size(&node.function_call.args); i++) {
|
||||
const Node* arg = Nodes_at(&node.function_call.args, i);
|
||||
codegen(*arg);
|
||||
void codegen_function_call(FunctionCall node) {
|
||||
printf("call $%s(", node.name);
|
||||
// printf("FunctionCall(%s", node.function_call.name);
|
||||
/*if(Nodes_size(&node.function_call.args) > 0)
|
||||
printf(", ");*/
|
||||
for(size_t i = 0; i < Nodes_size(&node.args); i++) {
|
||||
const Node* arg = Nodes_at(&node.args, i);
|
||||
codegen(*arg, true);
|
||||
|
||||
if(arg != Nodes_back(&node.function_call.args)) {
|
||||
if(arg != Nodes_back(&node.args)) {
|
||||
printf(", ");
|
||||
}
|
||||
}
|
||||
printf(")\n");
|
||||
}
|
||||
|
||||
void codegen_function_decl(Node node) {
|
||||
printf("FunctionDecl(%s, %s, ", node.function_decl.type, node.function_decl.name);
|
||||
for(size_t i = 0; i < Nodes_size(&node.function_decl.args); i++) {
|
||||
const Node* arg = Nodes_at(&node.function_decl.args, i);
|
||||
codegen(*arg);
|
||||
void codegen_function_decl(FunctionDecl node) {
|
||||
printf("FunctionDecl(%s, %s, ", node.type, node.name);
|
||||
for(size_t i = 0; i < Nodes_size(&node.args); i++) {
|
||||
const Node* arg = Nodes_at(&node.args, i);
|
||||
codegen(*arg, true);
|
||||
|
||||
if(arg != Nodes_back(&node.function_decl.args)) {
|
||||
if(arg != Nodes_back(&node.args)) {
|
||||
printf(", ");
|
||||
}
|
||||
}
|
||||
printf(")\n");
|
||||
}
|
||||
|
||||
void codegen_function_impl(Node node) {
|
||||
printf("FunctionImpl(%s, %s", node.function_impl.type, node.function_impl.name);
|
||||
if(Nodes_size(&node.function_impl.args) > 0)
|
||||
printf(", ");
|
||||
for(size_t i = 0; i < Nodes_size(&node.function_impl.args); i++) {
|
||||
const Node* arg = Nodes_at(&node.function_impl.args, i);
|
||||
codegen(*arg);
|
||||
void codegen_function_impl(FunctionImpl node) {
|
||||
printf("export function %s $%s(", node.type, node.name);
|
||||
for(size_t i = 0; i < Nodes_size(&node.args); i++) {
|
||||
const Node* arg = Nodes_at(&node.args, i);
|
||||
codegen(*arg, true);
|
||||
|
||||
if(arg != Nodes_back(&node.function_impl.args)) {
|
||||
if(arg != Nodes_back(&node.args)) {
|
||||
printf(", ");
|
||||
}
|
||||
}
|
||||
printf(") {\n\t");
|
||||
printf(") {\n@start\n\t");
|
||||
|
||||
for(size_t i = 0; i < Nodes_size(&node.function_impl.body); i++) {
|
||||
const Node* n = Nodes_at(&node.function_impl.body, i);
|
||||
codegen(*n);
|
||||
for(size_t i = 0; i < Nodes_size(&node.body); i++) {
|
||||
const Node* n = Nodes_at(&node.body, i);
|
||||
codegen(*n, true);
|
||||
|
||||
if(n != Nodes_back(&node.function_impl.body)) {
|
||||
if(n != Nodes_back(&node.body)) {
|
||||
printf("\t");
|
||||
}
|
||||
}
|
||||
|
||||
printf("}\n");
|
||||
printf("\t\n}\n");
|
||||
}
|
||||
|
||||
void codegen_arg_decl(Node node) {
|
||||
printf("ArgDecl(%s, %s)", node.arg_decl.type, node.arg_decl.name);
|
||||
void codegen_arg_decl(ArgDecl node, bool emit_type) {
|
||||
// printf("ArgDecl(%s, %s)", node.arg_decl.type, node.arg_decl.name);
|
||||
if(emit_type) {
|
||||
printf("%s ", node.type);
|
||||
}
|
||||
printf("%%%s", node.name);
|
||||
}
|
||||
|
||||
void codegen_number(Node node) {
|
||||
printf("Number(%llu)", node.number.value);
|
||||
void codegen_reference(Reference node, bool emit_type) {
|
||||
// printf("Reference(%s)", node.reference.name);
|
||||
if(emit_type) {
|
||||
printf("%s ", node.type);
|
||||
}
|
||||
printf("%%%s", node.name);
|
||||
}
|
||||
|
||||
void codegen_number(Number node, bool emit_type) {
|
||||
// printf("Number(%llu)", node.number.value);
|
||||
if(emit_type) {
|
||||
printf("w ");
|
||||
}
|
||||
printf("%d", node.value);
|
||||
}
|
||||
|
||||
void codegen_return(Return node) {
|
||||
printf("ret ");
|
||||
if(node.value != NULL) {
|
||||
codegen(*node.value, false);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,11 +3,13 @@
|
|||
|
||||
#include "node.h"
|
||||
|
||||
void codegen(Node node);
|
||||
void codegen_function_call(Node node);
|
||||
void codegen_function_decl(Node node);
|
||||
void codegen_arg_decl(Node node);
|
||||
void codegen_function_impl(Node node);
|
||||
void codegen_number(Node node);
|
||||
void codegen(Node node, bool emit_type);
|
||||
void codegen_function_call(FunctionCall node);
|
||||
void codegen_function_decl(FunctionDecl node);
|
||||
void codegen_arg_decl(ArgDecl node, bool emit_type);
|
||||
void codegen_function_impl(FunctionImpl node);
|
||||
void codegen_reference(Reference node, bool emit_type);
|
||||
void codegen_number(Number node, bool emit_type);
|
||||
void codegen_return(Return node);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#define COMPILER_H
|
||||
|
||||
#include "lexer.h"
|
||||
#include "node.h"
|
||||
|
||||
typedef enum {
|
||||
TOKEN_IDENTIFIER = 'I',
|
||||
|
@ -32,6 +33,7 @@ typedef enum {
|
|||
typedef struct {
|
||||
Lexer* lexer;
|
||||
cmap_str types;
|
||||
NodeMap symbols;
|
||||
} Compiler;
|
||||
|
||||
bool next(Compiler* compiler, Token* token);
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
#include "token.h"
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
assert(argc > 1);
|
||||
|
@ -38,13 +37,14 @@ int main(int argc, char** argv) {
|
|||
{ "i64", "l" },
|
||||
{ "void", "" },
|
||||
}),
|
||||
.symbols = { 0 },
|
||||
};
|
||||
|
||||
Token token;
|
||||
while(next(&compiler, &token)) {
|
||||
// printf("%c: %s\n", token.type, token.value);
|
||||
Node node = parse_token(&compiler, token);
|
||||
codegen(node);
|
||||
codegen(node, true);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
24
src/node.h
24
src/node.h
|
@ -1,17 +1,22 @@
|
|||
#ifndef NODE_H
|
||||
#define NODE_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include <stc/cstr.h>
|
||||
#include <stc/forward.h>
|
||||
typedef struct Node Node;
|
||||
forward_cvec(Nodes, struct Node);
|
||||
forward_cmap(NodeMap, cstr, struct Node);
|
||||
|
||||
typedef enum {
|
||||
NODE_FUNCTION_CALL = 'C',
|
||||
NODE_FUNCTION_DECL = 'D',
|
||||
NODE_FUNCTION_IMPL = 'I',
|
||||
NODE_ARG_DECL = 'A',
|
||||
NODE_RETURN = 'R',
|
||||
NODE_REFERENCE = 'r',
|
||||
NODE_NUMBER = 'N',
|
||||
} NodeType;
|
||||
|
||||
|
@ -39,9 +44,18 @@ typedef struct {
|
|||
} ArgDecl;
|
||||
|
||||
typedef struct {
|
||||
long long int value;
|
||||
const char* type;
|
||||
const char* name;
|
||||
} Reference;
|
||||
|
||||
typedef struct {
|
||||
int value;
|
||||
} Number;
|
||||
|
||||
typedef struct {
|
||||
Node* value;
|
||||
} Return;
|
||||
|
||||
struct Nodes;
|
||||
typedef struct Node {
|
||||
NodeType type;
|
||||
|
@ -50,7 +64,9 @@ typedef struct Node {
|
|||
FunctionDecl function_decl;
|
||||
FunctionImpl function_impl;
|
||||
ArgDecl arg_decl;
|
||||
Reference reference;
|
||||
Number number;
|
||||
Return ret;
|
||||
};
|
||||
} Node;
|
||||
|
||||
|
@ -60,4 +76,10 @@ typedef struct Node {
|
|||
#define i_opt c_no_cmp
|
||||
#include <stc/cvec.h>
|
||||
|
||||
#define i_type NodeMap
|
||||
#define i_is_forward
|
||||
#define i_key_str
|
||||
#define i_val Node
|
||||
#include <stc/cmap.h>
|
||||
|
||||
#endif
|
||||
|
|
85
src/parser.c
85
src/parser.c
|
@ -43,23 +43,53 @@ Node parse_type(Compiler* self, const char* type) {
|
|||
}
|
||||
}
|
||||
|
||||
Node parse_identifier(Compiler* self, const char* name) {
|
||||
Token token;
|
||||
next(self, &token);
|
||||
|
||||
switch(token.type) {
|
||||
case TOKEN_OPAREN:
|
||||
return parse_function_call(self, name);
|
||||
break;
|
||||
const char* resolve_type(Compiler* self, Node node) {
|
||||
switch(node.type) {
|
||||
case NODE_ARG_DECL:
|
||||
return node.arg_decl.type;
|
||||
default:
|
||||
syntax_error("unexpected token \"%s\" after identifier \"%s\"", token.value, name);
|
||||
syntax_error("unexpected node fed to resolve_type");
|
||||
}
|
||||
}
|
||||
|
||||
Node parse_identifier(Compiler* self, const char* name) {
|
||||
if(strcmp(name, "return") == 0) {
|
||||
Token token;
|
||||
next(self, &token);
|
||||
Node* node = NULL;
|
||||
|
||||
if(token.type != TOKEN_SEMICOLON) {
|
||||
node = malloc(sizeof(Node));
|
||||
Node parsed = parse_token(self, token);
|
||||
memcpy(node, &parsed, sizeof(Node));
|
||||
parse_semicolon(self);
|
||||
}
|
||||
return (Node){ .type = NODE_RETURN, .ret = { .value = node } };
|
||||
}
|
||||
|
||||
const NodeMap_value* symbol = NodeMap_get(&self->symbols, name);
|
||||
if(symbol == NULL) {
|
||||
syntax_error("undefined symbol \"%s\"", name);
|
||||
}
|
||||
|
||||
switch(symbol->second.type) {
|
||||
case NODE_FUNCTION_DECL:
|
||||
case NODE_FUNCTION_IMPL:
|
||||
return parse_function_call(self, name);
|
||||
case NODE_ARG_DECL:
|
||||
return (Node){
|
||||
.type = NODE_REFERENCE,
|
||||
.reference = { .type = resolve_type(self, symbol->second), .name = name },
|
||||
};
|
||||
default:
|
||||
syntax_error("unexpected symbol type");
|
||||
}
|
||||
}
|
||||
|
||||
Node parse_number(Compiler* self, const char* value) {
|
||||
return (Node){
|
||||
.type = NODE_NUMBER,
|
||||
.number = atoll(value),
|
||||
.number = atoi(value),
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -85,15 +115,17 @@ Node parse_function(Compiler* self, const char* type, const char* name) {
|
|||
if(arg_type.type == TOKEN_CPAREN) {
|
||||
break;
|
||||
}
|
||||
const cmap_str_value* type = cmap_str_get(&self->types, arg_type.value);
|
||||
|
||||
Token arg_name;
|
||||
next(self, &arg_name);
|
||||
|
||||
Nodes_push(&args,
|
||||
(Node){
|
||||
.type = NODE_ARG_DECL,
|
||||
.arg_decl = { .type = arg_type.value, .name = arg_name.value },
|
||||
});
|
||||
Node arg_decl = (Node){
|
||||
.type = NODE_ARG_DECL,
|
||||
.arg_decl = { .type = cstr_str(&type->second), .name = arg_name.value },
|
||||
};
|
||||
Nodes_push(&args, arg_decl);
|
||||
NodeMap_insert(&self->symbols, cstr_from(arg_name.value), arg_decl);
|
||||
|
||||
Token token;
|
||||
next(self, &token);
|
||||
|
@ -109,19 +141,29 @@ Node parse_function(Compiler* self, const char* type, const char* name) {
|
|||
break; // only reached if didnt continue or error
|
||||
}
|
||||
|
||||
const cmap_str_value* real_type = cmap_str_get(&self->types, type);
|
||||
const char* real_type_cstr = cstr_str(&real_type->second);
|
||||
|
||||
Token token;
|
||||
Node function_node;
|
||||
if(next(self, &token)) {
|
||||
switch(token.type) {
|
||||
case TOKEN_SEMICOLON:
|
||||
return parse_function_decl(self, type, name, args);
|
||||
function_node = parse_function_decl(self, real_type_cstr, name, args);
|
||||
break;
|
||||
case TOKEN_OBRACE:
|
||||
return parse_function_impl(self, type, name, args);
|
||||
function_node = parse_function_impl(self, real_type_cstr, name, args);
|
||||
break;
|
||||
default:
|
||||
syntax_error("expected semicolon or opening brace found, %s", token.value);
|
||||
}
|
||||
} else {
|
||||
syntax_error("expected token, found eof");
|
||||
}
|
||||
|
||||
printf("inserting %s into symbols\n", name);
|
||||
NodeMap_insert(&self->symbols, cstr_from(name), function_node);
|
||||
return function_node;
|
||||
}
|
||||
|
||||
Node parse_function_decl(Compiler* self, const char* type, const char* name, Nodes args) {
|
||||
|
@ -142,6 +184,15 @@ Node parse_function_impl(Compiler* self, const char* type, const char* name, Nod
|
|||
|
||||
Node parse_function_call(Compiler* self, const char* name) {
|
||||
printf("parse function call %s\n", name);
|
||||
Token token;
|
||||
next(self, &token);
|
||||
switch(token.type) {
|
||||
case TOKEN_OPAREN:
|
||||
break;
|
||||
default:
|
||||
syntax_error("unexpected token \"%s\" after function name", token.value);
|
||||
}
|
||||
|
||||
Nodes args = parse_until(self, TOKEN_CPAREN);
|
||||
|
||||
parse_semicolon(self);
|
||||
|
|
41
test.s
Normal file
41
test.s
Normal file
|
@ -0,0 +1,41 @@
|
|||
.text
|
||||
.balign 16
|
||||
.globl sayhi
|
||||
sayhi:
|
||||
hint #34
|
||||
stp x29, x30, [sp, -32]!
|
||||
mov x29, sp
|
||||
str x19, [x29, 24]
|
||||
mov w19, w0
|
||||
mov w0, #72
|
||||
bl putchar
|
||||
mov w0, w19
|
||||
mov w19, w0
|
||||
mov w0, #105
|
||||
bl putchar
|
||||
mov w0, w19
|
||||
bl putchar
|
||||
mov w0, #5
|
||||
ldr x19, [x29, 24]
|
||||
ldp x29, x30, [sp], 32
|
||||
ret
|
||||
.type sayhi, @function
|
||||
.size sayhi, .-sayhi
|
||||
/* end function sayhi */
|
||||
|
||||
.text
|
||||
.balign 16
|
||||
.globl main
|
||||
main:
|
||||
hint #34
|
||||
stp x29, x30, [sp, -16]!
|
||||
mov x29, sp
|
||||
mov w0, #74
|
||||
bl sayhi
|
||||
ldp x29, x30, [sp], 16
|
||||
ret
|
||||
.type main, @function
|
||||
.size main, .-main
|
||||
/* end function main */
|
||||
|
||||
.section .note.GNU-stack,"",@progbits
|
14
test.ssa
Normal file
14
test.ssa
Normal file
|
@ -0,0 +1,14 @@
|
|||
export function w $sayhi(w %char) {
|
||||
@start
|
||||
call $putchar(w 72)
|
||||
call $putchar(w 105)
|
||||
call $putchar(w %char)
|
||||
ret 5
|
||||
}
|
||||
|
||||
export function $main() {
|
||||
@start
|
||||
call $sayhi(w 74)
|
||||
ret
|
||||
}
|
||||
|
9
test.txt
9
test.txt
|
@ -1,8 +1,13 @@
|
|||
i32 putchar(i32 char);
|
||||
|
||||
void sayhi() {
|
||||
i32 sayhi(i32 char) {
|
||||
putchar(72);
|
||||
putchar(105);
|
||||
putchar(char);
|
||||
return 5;
|
||||
}
|
||||
|
||||
sayhi();
|
||||
void main() {
|
||||
sayhi(74);
|
||||
return;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue