commit a4321b7134e3144f4ebf9169c3c0eaec27058f36
parent 2ff3f3a3928f52bc20b2f851975b40c43b78ec7b
Author: Drew DeVault <sir@cmpwn.com>
Date: Fri, 25 Dec 2020 14:03:12 -0500
Implement true, false, null constants
Diffstat:
7 files changed, 67 insertions(+), 8 deletions(-)
diff --git a/include/ast.h b/include/ast.h
@@ -125,6 +125,7 @@ struct ast_expression_constant {
intmax_t ival;
uintmax_t uval;
uint32_t rune;
+ bool bval;
struct {
size_t len;
char *value;
diff --git a/include/expr.h b/include/expr.h
@@ -94,11 +94,11 @@ struct expression_call {
};
union expression_constant {
- bool bval;
struct {
char *sval;
size_t ssz;
};
+ bool bval;
double fval;
intmax_t ival;
uintmax_t uval;
diff --git a/include/qbe.h b/include/qbe.h
@@ -217,5 +217,6 @@ void constw(struct qbe_value *val, uint32_t l);
void constl(struct qbe_value *val, uint64_t l);
void consts(struct qbe_value *val, float l);
void constd(struct qbe_value *val, double l);
+void const_void(struct qbe_value *val);
#endif
diff --git a/src/check.c b/src/check.c
@@ -264,11 +264,15 @@ check_expr_constant(struct context *ctx,
expr->constant.rune = aexpr->constant.rune;
break;
case TYPE_STORAGE_BOOL:
+ expr->constant.bval = aexpr->constant.bval;
+ break;
+ case TYPE_STORAGE_NULL:
+ case TYPE_STORAGE_VOID:
+ // No storage
+ break;
case TYPE_STORAGE_F32:
case TYPE_STORAGE_F64:
case TYPE_STORAGE_STRING:
- case TYPE_STORAGE_NULL:
- case TYPE_STORAGE_VOID:
assert(0); // TODO
case TYPE_STORAGE_CHAR:
case TYPE_STORAGE_ENUM:
diff --git a/src/gen.c b/src/gen.c
@@ -328,8 +328,28 @@ gen_constant(struct gen_context *ctx,
return;
}
- const struct qbe_type *qtype = qtype_for_type(ctx, expr->result, false);
struct qbe_value val = {0};
+
+ // Special cases
+ switch (expr->result->storage) {
+ case TYPE_STORAGE_BOOL:
+ constw(&val, expr->constant.bval ? 1 : 0);
+ gen_store(ctx, out, &val);
+ return;
+ case TYPE_STORAGE_VOID:
+ const_void(&val);
+ gen_store(ctx, out, &val);
+ return;
+ case TYPE_STORAGE_NULL:
+ constl(&val, 0);
+ gen_store(ctx, out, &val);
+ return;
+ default:
+ // Moving right along
+ break;
+ }
+
+ const struct qbe_type *qtype = qtype_for_type(ctx, expr->result, false);
switch (qtype->stype) {
case Q_BYTE:
case Q_HALF:
diff --git a/src/parse.c b/src/parse.c
@@ -429,12 +429,33 @@ parse_constant(struct parser *par)
{
trenter(TR_PARSE, "constant");
- struct token tok = {0};
- want(par, T_LITERAL, &tok);
-
struct ast_expression *exp = xcalloc(1, sizeof(struct ast_expression));
exp->type = EXPR_CONSTANT;
- exp->constant.storage = tok.storage;
+
+ struct token tok = {0};
+ switch (lex(par->lex, &tok)) {
+ case T_TRUE:
+ exp->constant.storage = TYPE_STORAGE_BOOL;
+ exp->constant.bval = true;
+ return exp;
+ case T_FALSE:
+ exp->constant.storage = TYPE_STORAGE_BOOL;
+ exp->constant.bval = false;
+ return exp;
+ case T_NULL:
+ exp->constant.storage = TYPE_STORAGE_NULL;
+ return exp;
+ case T_VOID:
+ exp->constant.storage = TYPE_STORAGE_VOID;
+ return exp;
+ case T_LITERAL:
+ exp->constant.storage = tok.storage;
+ break;
+ default:
+ synassert(false, &tok, T_LITERAL, T_TRUE,
+ T_FALSE, T_NULL, T_VOID, T_EOF);
+ break;
+ }
switch (tok.storage) {
case TYPE_STORAGE_CHAR:
@@ -464,6 +485,7 @@ parse_constant(struct parser *par)
default:
assert(0); // TODO
}
+
trleave(TR_PARSE, "%s", token_str(&tok));
return exp;
}
@@ -476,6 +498,10 @@ parse_plain_expression(struct parser *par)
struct token tok;
switch (lex(par->lex, &tok)) {
case T_LITERAL:
+ case T_TRUE:
+ case T_FALSE:
+ case T_NULL:
+ case T_VOID:
unlex(par->lex, &tok);
return parse_constant(par);
case T_NAME:
diff --git a/src/qbe.c b/src/qbe.c
@@ -294,3 +294,10 @@ constd(struct qbe_value *val, double d)
val->type = &qbe_double;
val->dval = d;
}
+
+void
+const_void(struct qbe_value *val)
+{
+ val->kind = QV_CONST;
+ val->type = &qbe_void;
+}