devicetree-compiler.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: David Gibson <david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org>
To: devicetree-compiler-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Cc: jdl-CYoMK+44s/E@public.gmane.org,
	3fa55604225d40864c30a8b17d0dac60b2384cbe-mnsaURCQ41sdnm+yROfE0A@public.gmane.org,
	David Gibson
	<david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org>
Subject: [PATCH 03/10] Add type information to expression trees
Date: Mon, 17 Feb 2014 00:19:34 +1100	[thread overview]
Message-ID: <1392556781-7743-4-git-send-email-david@gibson.dropbear.id.au> (raw)
In-Reply-To: <1392556781-7743-1-git-send-email-david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org>

This implements a rudimentary dynamic typing system for dtc expressions,
laying the groundwork for expressions of multiple types (e.g. string,
bytestring).  For now, we don't actually implement any types beyond
integer, though.

Signed-off-by: David Gibson <david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org>
---
 dtc-parser.y |  19 ++++++-----
 dtc.h        |  20 +++++++++--
 expression.c | 109 +++++++++++++++++++++++++++++++++++++++++++++++++++--------
 3 files changed, 123 insertions(+), 25 deletions(-)

diff --git a/dtc-parser.y b/dtc-parser.y
index c5522e3..fbf5f3c 100644
--- a/dtc-parser.y
+++ b/dtc-parser.y
@@ -128,8 +128,7 @@ memreserves:
 memreserve:
 	  DT_MEMRESERVE expr_prim expr_prim ';'
 		{
-			$$ = build_reserve_entry(expr_int($2),
-						 expr_int($3));
+			$$ = build_reserve_entry(expr_int($2), expr_int($3));
 		}
 	| DT_LABEL memreserve
 		{
@@ -338,8 +337,8 @@ arrayprefix:
 	;
 
 expr_prim:
-	  DT_LITERAL 		{ $$ = expression_constant(&yylloc, $1); }
-	| DT_CHAR_LITERAL	{ $$ = expression_constant(&yylloc, $1); }
+	  DT_LITERAL 		{ $$ = expression_integer_constant(&yylloc, $1); }
+	| DT_CHAR_LITERAL	{ $$ = expression_integer_constant(&yylloc, $1); }
 	| '(' expr ')'
 		{
 			$$ = $2;
@@ -479,8 +478,12 @@ void yyerror(char const *s)
 
 static uint64_t expr_int(struct expression *expr)
 {
-	uint64_t val;
-	val = expression_evaluate(expr);
-	expression_free(expr);
-	return val;
+	struct expression_value v = expression_evaluate(expr, EXPR_INTEGER);
+
+	if (v.type == EXPR_VOID) {
+		treesource_error = true;
+		return -1;
+	}
+	assert(v.type == EXPR_INTEGER);
+	return v.value.integer;
 }
diff --git a/dtc.h b/dtc.h
index fed9d2d..95ed75e 100644
--- a/dtc.h
+++ b/dtc.h
@@ -223,20 +223,34 @@ uint32_t guess_boot_cpuid(struct node *tree);
 struct operator;
 struct srcpos;
 
+enum expr_type {
+	EXPR_VOID = 0, /* Missing or unspecified type */
+	EXPR_INTEGER,
+};
+
+struct expression_value {
+	enum expr_type type;
+	union {
+		uint64_t integer;
+	} value;
+};
+
 struct expression {
 	struct srcpos *loc;
 	struct operator *op;
 	int nargs;
 	union {
-		uint64_t constant;
+		struct expression_value constant;
 	} u;
 	struct expression *arg[0];
 };
 
 void expression_free(struct expression *expr);
-uint64_t expression_evaluate(struct expression *expr);
+struct expression_value expression_evaluate(struct expression *expr,
+					    enum expr_type context);
 
-struct expression *expression_constant(struct srcpos *pos, uint64_t val);
+struct expression *expression_integer_constant(struct srcpos *pos,
+					       uint64_t val);
 
 #define DEF_UNARY_OP(nm) \
 	struct expression *expression_##nm(struct srcpos *, \
diff --git a/expression.c b/expression.c
index 05d0df5..a89eea3 100644
--- a/expression.c
+++ b/expression.c
@@ -20,10 +20,25 @@
 #include "srcpos.h"
 #include "dtc.h"
 
+static const char *expression_typename(enum expr_type t)
+{
+	switch (t) {
+	case EXPR_VOID:
+		return "void";
+
+	case EXPR_INTEGER:
+		return "integer";
+
+	default:
+		assert(0);
+	}
+}
+
 struct operator {
 	const char *name;
 	unsigned nargs;
-	uint64_t (*evaluate)(struct expression *);
+	struct expression_value (*evaluate)(struct expression *,
+					    enum expr_type context);
 	void (*free)(struct expression *);
 };
 
@@ -70,12 +85,51 @@ void expression_free(struct expression *expr)
 	free(expr);
 }
 
-uint64_t expression_evaluate(struct expression *expr)
+static struct expression_value type_error(struct expression *expr,
+					  const char *fmt, ...)
+{
+	static const struct expression_value v = {
+		.type = EXPR_VOID,
+	};
+
+	va_list(ap);
+
+	va_start(ap, fmt);
+	srcpos_verror(expr->loc, "Type error", fmt, ap);
+	va_end(ap);
+
+	return v;
+}
+
+struct expression_value expression_evaluate(struct expression *expr,
+					    enum expr_type context)
 {
-	return expr->op->evaluate(expr);
+	struct expression_value v = expr->op->evaluate(expr, context);
+
+	if ((context != EXPR_VOID) && (context != v.type))
+		return type_error(expr, "Expected %s expression (found %s)",
+				  expression_typename(context),
+				  expression_typename(v.type));
+
+	return v;
 }
 
-static uint64_t op_eval_constant(struct expression *expr)
+#define EVALUATE(_v, _ex, _ctx) \
+	do { \
+		(_v) = expression_evaluate((_ex), (_ctx)); \
+		if ((_v).type == EXPR_VOID) \
+			return (_v); \
+	} while (0)
+
+#define EVALUATE_INT(_vi, _ex) \
+	do { \
+		struct expression_value _v; \
+		EVALUATE(_v, (_ex), EXPR_INTEGER); \
+		(_vi) = (_v).value.integer; \
+	} while (0)
+
+static struct expression_value op_eval_constant(struct expression *expr,
+						enum expr_type context)
 {
 	assert(expr->nargs == 0);
 	return expr->u.constant;
@@ -84,7 +138,9 @@ static struct operator op_constant = {
 	.name = "constant",
 	.evaluate = op_eval_constant,
 };
-struct expression *expression_constant(struct srcpos *loc, uint64_t val)
+
+static struct expression *__expression_constant(struct srcpos *loc,
+						struct expression_value val)
 {
 	struct expression *expr = expression_build(loc, &op_constant);
 
@@ -92,11 +148,27 @@ struct expression *expression_constant(struct srcpos *loc, uint64_t val)
 	return expr;
 }
 
+struct expression *expression_integer_constant(struct srcpos *pos,
+					       uint64_t val)
+{
+	struct expression_value v = {
+		.type = EXPR_INTEGER,
+		.value.integer = val,
+	};
+
+	return __expression_constant(pos, v);
+}
+
 #define INT_UNARY_OP(nm, cop) \
-	static uint64_t op_eval_##nm(struct expression *expr) \
+	static struct expression_value op_eval_##nm(struct expression *expr, \
+						    enum expr_type context) \
 	{ \
+		struct expression_value v = { .type = EXPR_INTEGER, }; \
+		uint64_t arg; \
 		assert(expr->nargs == 1); \
-		return cop expression_evaluate(expr->arg[0]);	\
+		EVALUATE_INT(arg, expr->arg[0]); \
+		v.value.integer = cop arg; \
+		return v; \
 	} \
 	static struct operator op_##nm = { \
 		.name = #cop, \
@@ -113,11 +185,16 @@ INT_UNARY_OP(bit_not, ~)
 INT_UNARY_OP(logic_not, !)
 
 #define INT_BINARY_OP(nm, cop) \
-	static uint64_t op_eval_##nm(struct expression *expr) \
+	static struct expression_value op_eval_##nm(struct expression *expr, \
+						    enum expr_type context) \
 	{ \
+		struct expression_value v = { .type = EXPR_INTEGER, }; \
+		uint64_t arg0, arg1; \
 		assert(expr->nargs == 2); \
-		return expression_evaluate(expr->arg[0]) \
-			cop expression_evaluate(expr->arg[1]);	\
+		EVALUATE_INT(arg0, expr->arg[0]); \
+		EVALUATE_INT(arg1, expr->arg[1]); \
+		v.value.integer = arg0 cop arg1; \
+		return v; \
 	} \
 	static struct operator op_##nm = { \
 		.name = #cop, \
@@ -155,12 +232,16 @@ INT_BINARY_OP(bit_or, |)
 INT_BINARY_OP(logic_and, &&)
 INT_BINARY_OP(logic_or, ||)
 
-static uint64_t op_eval_conditional(struct expression *expr)
+static struct expression_value op_eval_conditional(struct expression *expr,
+						   enum expr_type context)
 {
+	uint64_t cond;
+
 	assert(expr->nargs == 3);
-	return expression_evaluate(expr->arg[0])
-		? expression_evaluate(expr->arg[1])
-		: expression_evaluate(expr->arg[2]);
+	EVALUATE_INT(cond, expr->arg[0]);
+
+	return cond ? expression_evaluate(expr->arg[1], context)
+		: expression_evaluate(expr->arg[2], context);
 }
 static struct operator op_conditional = {
 	.name = "?:",
-- 
1.8.5.3

--
To unsubscribe from this list: send the line "unsubscribe devicetree-compiler" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

  parent reply	other threads:[~2014-02-16 13:19 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-02-16 13:19 [0/10] RFC: A new start on richer dtc expression support David Gibson
     [not found] ` <1392556781-7743-1-git-send-email-david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org>
2014-02-16 13:19   ` [PATCH 01/10] First cut at expression trees David Gibson
2014-02-16 13:19   ` [PATCH 02/10] Add srcpos information to expressions David Gibson
2014-02-16 13:19   ` David Gibson [this message]
2014-02-16 13:19   ` [PATCH 04/10] Add string and bytestring expression types David Gibson
2014-02-16 13:19   ` [PATCH 05/10] Integrate /incbin/ with expanded expressions David Gibson
2014-02-16 13:19   ` [PATCH 06/10] Implement arrays as expressions David Gibson
2014-02-16 13:19   ` [PATCH 07/10] Implement labels within property values as bytestring expressions David Gibson
2014-02-16 13:19   ` [PATCH 08/10] Implement path references in terms of " David Gibson
2014-02-16 13:19   ` [PATCH 09/10] Re-implement "," in property definitions as a bytestring operator David Gibson
2014-02-16 13:19   ` [PATCH 10/10] Implement string concatenate and repeat operators David Gibson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1392556781-7743-4-git-send-email-david@gibson.dropbear.id.au \
    --to=david-xt8fgy+axnrb3ne2bgzf6laj5h9x9tb+@public.gmane.org \
    --cc=3fa55604225d40864c30a8b17d0dac60b2384cbe-mnsaURCQ41sdnm+yROfE0A@public.gmane.org \
    --cc=devicetree-compiler-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    --cc=jdl-CYoMK+44s/E@public.gmane.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).