From cc5e08b53e724b425c9db31b3ee9ec445a394ae6 Mon Sep 17 00:00:00 2001
From: Leo Tenenbaum <pommicket@gmail.com>
Date: Fri, 8 Nov 2019 17:50:13 -0500
Subject: added value exprs in preparation for compile time arguments

---
 cgen.c          |  17 +++++++++
 decls_cgen.c    |   1 +
 eval.c          | 106 +++++++++++++++++++++++++++++---------------------------
 main.c          |   1 +
 parse.c         |   8 +++--
 typedefs_cgen.c |   1 +
 types.c         |  13 ++++---
 types.h         |   7 +++-
 8 files changed, 96 insertions(+), 58 deletions(-)

diff --git a/cgen.c b/cgen.c
index 0e0a3ce..78b706e 100644
--- a/cgen.c
+++ b/cgen.c
@@ -453,6 +453,9 @@ static bool cgen_set(CGenerator *g, Expression *set_expr, const char *set_str, E
 static bool cgen_set_tuple(CGenerator *g, Expression *exprs, Identifier *idents, const char *prefix, Expression *to) {
 	IdentID prefix_id; /* ID of prefix for block */
 	switch (to->kind) {
+	case EXPR_VAL:
+		assert(0); /* never needed at the moment */
+		break;
 	case EXPR_TUPLE:
 		/* e.g. a, b = 3, 5; */
 		for (size_t i = 0; i < arr_len(to->tuple); i++) {
@@ -957,6 +960,17 @@ static bool cgen_expr_pre(CGenerator *g, Expression *e) {
 		if (e->new.n && !cgen_expr_pre(g, e->new.n))
 			return false;
 		break;
+	case EXPR_VAL:
+		if (!cgen_type_pre(g, &e->type, e->where)) return false;
+		e->val_c_id = g->ident_counter++;
+		cgen_write(g, " ");
+		cgen_ident_id(g, e->val_c_id);
+		if (!cgen_type_post(g, &e->type, e->where)) return false;
+		cgen_write(g, " = ");
+		cgen_val(g, &e->val, &e->type, e->where);
+		cgen_write(g, ";");
+		cgen_nl(g);
+		break;
 	case EXPR_LITERAL_INT:
 	case EXPR_LITERAL_FLOAT:
 	case EXPR_LITERAL_BOOL:
@@ -1247,6 +1261,9 @@ static bool cgen_expr(CGenerator *g, Expression *e) {
 	case EXPR_SLICE:
 		cgen_ident_id(g, e->slice.c.id);
 		break;
+	case EXPR_VAL:
+		cgen_ident_id(g, e->val_c_id);
+		break;
 	}
 	return true;
 }
diff --git a/decls_cgen.c b/decls_cgen.c
index 86ca5f8..ad0c552 100644
--- a/decls_cgen.c
+++ b/decls_cgen.c
@@ -83,6 +83,7 @@ static bool cgen_decls_expr(CGenerator *g, Expression *e) {
 		fn_exit(&e->fn);
 		break;
 	case EXPR_TYPE:
+	case EXPR_VAL:
 	case EXPR_C:
 	case EXPR_DSIZEOF:
 	case EXPR_DALIGNOF:
diff --git a/eval.c b/eval.c
index a3c2c83..aa60c7b 100644
--- a/eval.c
+++ b/eval.c
@@ -313,21 +313,21 @@ static void fprint_val_ptr(FILE *f, void *p, Type *t) {
 	}
 }
 
-static void fprint_val(FILE *f, Value *v, Type *t) {
+static void fprint_val(FILE *f, Value v, Type *t) {
 	if (t->kind == TYPE_TUPLE) {
 		fprintf(f, "(");
 		for (size_t i = 0; i < arr_len(t->tuple); i++) {
-			fprint_val(f, &v->tuple[i], &t->tuple[i]);
+			fprint_val(f, v.tuple[i], &t->tuple[i]);
 		}
 		fprintf(f, ")");
 	} else {
-		fprint_val_ptr(f, v, t);
+		fprint_val_ptr(f, &v, t);
 	}
 }
 
 /* 
-IMPORTANT: Only pass an evaluator if you want it to use its allocator.
-Otherwise, pass NULL.
+   IMPORTANT: Only pass an evaluator if you want it to use its allocator.
+   Otherwise, pass NULL.
 */
 static void val_copy(Evaluator *ev, Value *dest, Value *src, Type *t) {
 	switch (t->kind) {
@@ -421,21 +421,21 @@ static void val_free(Value *v, Type *t) {
 	case BUILTIN_F64:							\
 	vout->f64 = (F64)vin->x; break
 
-#define builtin_int_casts(low, up)										\
-	case BUILTIN_##up:													\
-	switch (to) {														\
-		builtin_casts_to_num(low);										\
-	case BUILTIN_CHAR: vout->charv = (char)vin->low; break;				\
-	case BUILTIN_BOOL: vout->boolv = vin->low != 0; break;				\
+#define builtin_int_casts(low, up)							\
+	case BUILTIN_##up:										\
+	switch (to) {											\
+		builtin_casts_to_num(low);							\
+	case BUILTIN_CHAR: vout->charv = (char)vin->low; break;	\
+	case BUILTIN_BOOL: vout->boolv = vin->low != 0; break;	\
 	} break
 
-#define builtin_float_casts(low, up)									\
-	case BUILTIN_##up:													\
-	switch (to) {														\
-	builtin_casts_to_num(low);											\
-	case BUILTIN_BOOL: vout->boolv = vin->low != 0.0f; break;			\
-	case BUILTIN_CHAR:													\
-		assert(0); break;												\
+#define builtin_float_casts(low, up)							\
+	case BUILTIN_##up:											\
+	switch (to) {												\
+		builtin_casts_to_num(low);								\
+	case BUILTIN_BOOL: vout->boolv = vin->low != 0.0f; break;	\
+	case BUILTIN_CHAR:											\
+		assert(0); break;										\
 	} break
 	
 static void val_builtin_cast(Value *vin, BuiltinType from, Value *vout, BuiltinType to) {
@@ -895,7 +895,7 @@ static bool eval_set(Evaluator *ev, Expression *set, Value *to) {
 }
 
 static void eval_numerical_bin_op(Value lhs, Type *lhs_type, BinaryOp op, Value rhs, Type *rhs_type, Value *out, Type *out_type) {
-		/* WARNING: macros ahead */
+	/* WARNING: macros ahead */
 
 #define eval_unary_op_nums_only(op)				\
 	switch (builtin) {							\
@@ -903,8 +903,8 @@ static void eval_numerical_bin_op(Value lhs, Type *lhs_type, BinaryOp op, Value
 	default: assert(0); break;					\
 	}
 
-#define eval_binary_op_one(low, up, op)			\
-	case BUILTIN_##up:							\
+#define eval_binary_op_one(low, up, op)				\
+	case BUILTIN_##up:								\
 		out->low = (up)(lhs.low op rhs.low); break
 	
 #define eval_binary_op_nums(builtin, op)		\
@@ -920,44 +920,44 @@ static void eval_numerical_bin_op(Value lhs, Type *lhs_type, BinaryOp op, Value
 	eval_binary_op_one(f64, F64, op)
 
 	
-#define eval_binary_op_nums_only(op)						\
-	val_cast(&lhs, lhs_type, &lhs, out_type);				\
-	val_cast(&rhs, rhs_type, &rhs, out_type);				\
-	assert(out_type->kind == TYPE_BUILTIN);					\
-	switch (builtin) {										\
-		eval_binary_op_nums(builtin, op);					\
-	default: assert(0); break;								\
+#define eval_binary_op_nums_only(op)			\
+	val_cast(&lhs, lhs_type, &lhs, out_type);	\
+	val_cast(&rhs, rhs_type, &rhs, out_type);	\
+	assert(out_type->kind == TYPE_BUILTIN);		\
+	switch (builtin) {							\
+		eval_binary_op_nums(builtin, op);		\
+	default: assert(0); break;					\
 	}
 
 
 #define eval_binary_bool_op_one(low, up, op)	\
 	case BUILTIN_##up:							\
-	out->boolv = lhs.low op rhs.low; break
+		out->boolv = lhs.low op rhs.low; break
 
-#define eval_binary_bool_op_nums(builtin, op)			\
-	eval_binary_bool_op_one(i8, I8, op);				\
-	eval_binary_bool_op_one(i16, I16, op);				\
-	eval_binary_bool_op_one(i32, I32, op);				\
-	eval_binary_bool_op_one(i64, I64, op);				\
-	eval_binary_bool_op_one(u8, U8, op);				\
-	eval_binary_bool_op_one(u16, U16, op);				\
-	eval_binary_bool_op_one(u32, U32, op);				\
-	eval_binary_bool_op_one(u64, U64, op);				\
-	eval_binary_bool_op_one(f32, F32, op);				\
-	eval_binary_bool_op_one(f64, F64, op);				\
-	eval_binary_bool_op_one(boolv, BOOL, op);			\
+#define eval_binary_bool_op_nums(builtin, op)	\
+	eval_binary_bool_op_one(i8, I8, op);		\
+	eval_binary_bool_op_one(i16, I16, op);		\
+	eval_binary_bool_op_one(i32, I32, op);		\
+	eval_binary_bool_op_one(i64, I64, op);		\
+	eval_binary_bool_op_one(u8, U8, op);		\
+	eval_binary_bool_op_one(u16, U16, op);		\
+	eval_binary_bool_op_one(u32, U32, op);		\
+	eval_binary_bool_op_one(u64, U64, op);		\
+	eval_binary_bool_op_one(f32, F32, op);		\
+	eval_binary_bool_op_one(f64, F64, op);		\
+	eval_binary_bool_op_one(boolv, BOOL, op);	\
 	eval_binary_bool_op_one(charv, CHAR, op);
 
-#define eval_binary_bool_op_nums_only(op)								\
-	{Type *cast_to =	lhs_type->flags & TYPE_FLAG_FLEXIBLE ?			\
-			rhs_type : lhs_type;										\
-		val_cast(&lhs, lhs_type, &lhs, cast_to);						\
-		val_cast(&rhs, rhs_type, &rhs, cast_to);						\
-		assert(lhs_type->kind == TYPE_BUILTIN);							\
-		switch (builtin) {												\
-			eval_binary_bool_op_nums(builtin, op);						\
-		default:														\
-			assert(!("Invalid builtin to "#op)[0]); break;				\
+#define eval_binary_bool_op_nums_only(op)						\
+	{Type *cast_to =	lhs_type->flags & TYPE_FLAG_FLEXIBLE ?	\
+			rhs_type : lhs_type;								\
+		val_cast(&lhs, lhs_type, &lhs, cast_to);				\
+		val_cast(&rhs, rhs_type, &rhs, cast_to);				\
+		assert(lhs_type->kind == TYPE_BUILTIN);					\
+		switch (builtin) {										\
+			eval_binary_bool_op_nums(builtin, op);				\
+		default:												\
+			assert(!("Invalid builtin to "#op)[0]); break;		\
 		}}
 	
 #define eval_binary_bool_op(op)					\
@@ -1495,6 +1495,10 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) {
 	} break;
 	case EXPR_TYPE:
 		v->type = &e->typeval;
+		break;
+	case EXPR_VAL:
+		*v = e->val;
+		break;
 	}
 	return true;
 }
diff --git a/main.c b/main.c
index 88ac5f7..3c0c0b5 100644
--- a/main.c
+++ b/main.c
@@ -1,6 +1,7 @@
 /* 
 TODO:
 compile-time arguments
+don't allow pointers to functions with compile-time arguments
 don't allow while {3; 5} (once break is added)
 any odd number of "s for a string
 modifiable strings:
diff --git a/parse.c b/parse.c
index a7ac633..f14cc89 100644
--- a/parse.c
+++ b/parse.c
@@ -27,6 +27,7 @@ static const char *expr_kind_to_str(ExprKind k) {
 	case EXPR_IDENT: return "identifier";
 	case EXPR_SLICE: return "slice";
 	case EXPR_TYPE: return "type";
+	case EXPR_VAL: return "value";
 	}
 	assert(0);
 	return "";
@@ -1956,7 +1957,7 @@ static void fprint_arg_exprs(FILE *out, Expression *args) {
 	fprintf(out, ")");
 }
 
-static void fprint_val(FILE *f, Value *v, Type *t);
+static void fprint_val(FILE *f, Value v, Type *t);
 
 static void fprint_expr(FILE *out, Expression *e) {
 	PARSE_PRINT_LOCATION(e->where);
@@ -2048,7 +2049,7 @@ static void fprint_expr(FILE *out, Expression *e) {
 			if (parse_printing_after_types) {
 				if (ea->range.stepval) {
 					fprintf(out, ",");
-					fprint_val(out, ea->range.stepval, &ea->type);
+					fprint_val(out, *ea->range.stepval, &ea->type);
 				}
 			} else {
 				if (ea->range.step) {
@@ -2112,6 +2113,9 @@ static void fprint_expr(FILE *out, Expression *e) {
 	case EXPR_TYPE:
 		fprint_type(out, &e->typeval);
 		break;
+	case EXPR_VAL:
+		fprint_val(out, e->val, &e->type);
+		break;
 	}
 	if (parse_printing_after_types) {
 		fprintf(out, ":");
diff --git a/typedefs_cgen.c b/typedefs_cgen.c
index b193e9a..8756298 100644
--- a/typedefs_cgen.c
+++ b/typedefs_cgen.c
@@ -89,6 +89,7 @@ static bool typedefs_expr(CGenerator *g, Expression *e) {
 		if (e->new.n && !typedefs_expr(g, e->new.n))
 			return false;
 		break;
+	case EXPR_VAL:
 	case EXPR_TYPE:
 	case EXPR_C:
 	case EXPR_DSIZEOF:
diff --git a/types.c b/types.c
index 337b97e..a635956 100644
--- a/types.c
+++ b/types.c
@@ -95,8 +95,8 @@ static bool type_must_eq(Location where, Type *expected, Type *got) {
 
 
 /*
-this expression, which is an array (or slice), must be mutable (otherwise print an error,
-return false)!
+  this expression, which is an array (or slice), must be mutable (otherwise print an error,
+  return false)!
 */
 static bool expr_arr_must_mut(Expression *e) {
 	switch (e->kind) {
@@ -116,6 +116,7 @@ static bool expr_arr_must_mut(Expression *e) {
 	case EXPR_NEW:
 	case EXPR_UNARY_OP:
 	case EXPR_C:
+	case EXPR_VAL:
 		return true;
 	case EXPR_SLICE:
 		return expr_arr_must_mut(e->slice.of);
@@ -218,7 +219,8 @@ static bool expr_must_lval(Expression *e) {
 	case EXPR_DSIZEOF:
 	case EXPR_BLOCK:
 	case EXPR_SLICE:
-	case EXPR_TYPE: {
+	case EXPR_TYPE:
+	case EXPR_VAL: {
 		err_print(e->where, "Cannot use %s as l-value.", expr_kind_to_str(e->kind));
 		return false;
 	}
@@ -633,7 +635,7 @@ static bool types_expr(Typer *tr, Expression *e) {
 				if (last_stmt->kind == STMT_RET) {
 					/*
 					  last statement is a return, so it doesn't matter that the function has no return value
-					ideally this would handle if foo { return 5; } else { return 6; } */
+					  ideally this would handle if foo { return 5; } else { return 6; } */
 					success = true;
 					goto fn_ret;
 				}
@@ -1438,6 +1440,9 @@ static bool types_expr(Typer *tr, Expression *e) {
 	case EXPR_TYPE:
 		t->kind = TYPE_TYPE;
 		break;
+	case EXPR_VAL:
+		assert(0);
+		return false;
 	}
     e->type.flags |= TYPE_FLAG_RESOLVED;
 	return true;
diff --git a/types.h b/types.h
index d6143da..84ae982 100644
--- a/types.h
+++ b/types.h
@@ -367,7 +367,8 @@ typedef enum {
 			  EXPR_DSIZEOF,
 			  EXPR_DALIGNOF,
 			  EXPR_SLICE,
-			  EXPR_TYPE
+			  EXPR_TYPE,
+			  EXPR_VAL /* a value (it's useful to have this). for now, tuples are not supported. see cgen_set_tuple */
 } ExprKind;
 
 typedef enum {
@@ -535,6 +536,10 @@ typedef struct Expression {
 		};
 		struct Expression *tuple;
 		Type typeval;
+		struct {
+			Value val;
+			IdentID val_c_id;
+		};
 	};
 } Expression;
 
-- 
cgit v1.2.3