aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/parser.c12
-rw-r--r--src/tokens.h1
-rw-r--r--src/types.c10
-rw-r--r--src/types.h2
-rw-r--r--std/common.cup8
5 files changed, 24 insertions, 9 deletions
diff --git a/src/parser.c b/src/parser.c
index 267947c..49c9689 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -227,6 +227,9 @@ Type *parse_type(Lexer *lexer)
} else if (token.type == TOKEN_CHAR) {
Lexer_next(lexer);
type = type_new(TYPE_CHAR);
+ } else if (token.type == TOKEN_VOID) {
+ Lexer_next(lexer);
+ type = type_new(TYPE_VOID);
} else {
assert_token(token, TOKEN_IDENTIFIER);
// TODO: Don't allow a type to contain itself.
@@ -590,7 +593,6 @@ Node *parse_factor(Lexer *lexer)
} else if (token.type == TOKEN_MINUSMINUS) {
die_location(token.loc, "Post-decrementing is not supported\n");
} else if (token.type == TOKEN_DOT) {
- // TODO: Pointer to struct
if (!is_struct_or_struct_ptr(expr->expr_type))
die_location(token.loc, "Cannot access member of non-struct type");
@@ -607,8 +609,8 @@ Node *parse_factor(Lexer *lexer)
member->member.expr = expr;
member->member.offset = struct_type->fields.offset[index];
member->member.is_ptr = (expr->expr_type->type == TYPE_PTR);
- expr = member;
+ expr = decay_array_to_pointer(member, &token);
} else {
break;
}
@@ -685,8 +687,8 @@ Node *parse_expression(Lexer *lexer)
Lexer_next(lexer);
Node *assign = Node_new(OP_ASSIGN);
assign->assign.var = node;
- assign->assign.value = parse_expression(lexer);
-
+ Node *expr = parse_expression(lexer);
+ assign->assign.value = expr;
if (!is_convertible(node->expr_type, assign->assign.value->expr_type)) {
fprintf(stderr, "- Variable type: %s\n", type_to_str(assign->assign.var->expr_type));
@@ -901,7 +903,7 @@ Node *parse_func(Lexer *lexer)
func->func.return_type = parse_type(lexer);
} else {
// No return type, void fn.
- func->func.return_type = type_new(TYPE_NONE);
+ func->func.return_type = type_new(TYPE_VOID);
}
// Make sure there's no funny business with the stack offset
diff --git a/src/tokens.h b/src/tokens.h
index 7045a5c..d0f216a 100644
--- a/src/tokens.h
+++ b/src/tokens.h
@@ -60,6 +60,7 @@
F(TOKEN_RETURN, "return") \
F(TOKEN_STRUCT, "struct") \
F(TOKEN_UNION, "union") \
+ F(TOKEN_VOID, "void") \
F(TOKEN_WHILE, "while") \
F(TOKEN_IMPORT, "import") \
diff --git a/src/types.c b/src/types.c
index 8ac4c77..c44f88d 100644
--- a/src/types.c
+++ b/src/types.c
@@ -21,6 +21,12 @@ bool is_convertible(Type *from, Type *to)
{
if (from->type == TYPE_ANY || to->type == TYPE_ANY)
return true;
+
+ // Allow converstions to and from void* to any other pointer type
+ if (from->type == TYPE_PTR && to->type == TYPE_PTR)
+ if (from->ptr->type == TYPE_VOID || to->ptr->type == TYPE_VOID)
+ return true;
+
// TODO: Should we rause a warning if the target type is narrower
// than the source type?
if (is_int_type(from) && is_int_type(to))
@@ -52,9 +58,11 @@ Type *type_new(DataType type)
static Type type_int = {.type = TYPE_INT, .ptr = NULL};
static Type type_char = {.type = TYPE_CHAR, .ptr = NULL};
static Type type_any = {.type = TYPE_ANY, .ptr = NULL};
+ static Type type_void = {.type = TYPE_VOID, .ptr = NULL};
if (type == TYPE_INT) return &type_int;
if (type == TYPE_CHAR) return &type_char;
if (type == TYPE_ANY) return &type_any;
+ if (type == TYPE_VOID) return &type_void;
Type *self = calloc(sizeof(Type), 1);
self->type = type;
@@ -102,7 +110,7 @@ static char *data_type_to_str(Type *type)
{
switch (type->type)
{
- case TYPE_NONE: return "void";
+ case TYPE_VOID: return "void";
case TYPE_INT: return "int";
case TYPE_PTR: return "*";
case TYPE_ARRAY: return "array";
diff --git a/src/types.h b/src/types.h
index 22c0d5f..2b9353d 100644
--- a/src/types.h
+++ b/src/types.h
@@ -4,7 +4,7 @@
#include <stdio.h>
typedef enum {
- TYPE_NONE,
+ TYPE_VOID,
TYPE_ANY, // This is a hack for builtins till we can cast types
TYPE_INT,
TYPE_CHAR,
diff --git a/std/common.cup b/std/common.cup
index 24e24b7..68cf3a6 100644
--- a/std/common.cup
+++ b/std/common.cup
@@ -1,10 +1,14 @@
+
const true = 1;
const false = 0;
+// This should really be a constant, but we only allow integers...
+let null: void*; // Zero initialized by default.
+
///////////////////////////////////////////////////////////////////////////////
// Syscalls
-fn write(fd: int, s: char*, n: int): int {
+fn write(fd: int, s: void*, n: int): int {
return syscall3(SYS_write, fd, s, n);
}
@@ -12,7 +16,7 @@ fn exit(status: int): int {
return syscall1(SYS_exit, status);
}
-fn read(fd: int, s: char*, n: int): int {
+fn read(fd: int, s: void*, n: int): int {
return syscall3(SYS_read, fd, s, n);
}