From 82b7e24b857d5fbb83321c1f73cb7575fd5155db Mon Sep 17 00:00:00 2001
From: "benjamin.franksen" <benjamin.franksen@helmholtz-berlin.de>
Date: Wed, 2 Oct 2013 18:05:21 +0000
Subject: [PATCH] snc: completed implementation of indirect calls

---
 src/snc/analysis.c    | 13 +++++++-
 src/snc/gen_ss_code.c | 78 ++++++++++++++++++++++---------------------
 src/snc/types.h       |  6 ++++
 3 files changed, 58 insertions(+), 39 deletions(-)

diff --git a/src/snc/analysis.c b/src/snc/analysis.c
index c0f27645..62220498 100644
--- a/src/snc/analysis.c
+++ b/src/snc/analysis.c
@@ -1101,10 +1101,21 @@ static int connect_variable(Expr *ep, Expr *scope, void *parg)
 	if (!vp)
 	{
 		VarList *var_list = var_list_from_scope(scope);
-		struct const_symbol *csym = lookup_builtin_const(st, ep->value);
+		struct const_symbol *csym;
+		struct func_symbol *fsym;
+
+		csym = lookup_builtin_const(st, ep->value);
 		if (csym)
 		{
 			ep->type = E_CONST;
+			ep->extra.e_const = csym;
+			return FALSE;
+		}
+		fsym = lookup_builtin_func(st, ep->value);
+		if (fsym)
+		{
+			ep->type = E_BUILTIN;
+			ep->extra.e_builtin = fsym;
 			return FALSE;
 		}
 
diff --git a/src/snc/gen_ss_code.c b/src/snc/gen_ss_code.c
index fd54cd25..1392f93d 100644
--- a/src/snc/gen_ss_code.c
+++ b/src/snc/gen_ss_code.c
@@ -45,8 +45,7 @@ static void gen_pv_func(int context, Expr *ep,
 	const char *func_name, uint add_length,
 	uint num_params, uint ef_args,
 	const char *default_values[]);
-static int gen_builtin_func(int context, Expr *ep);
-static int gen_builtin_const(Expr *ep);
+static void gen_builtin_func(int context, Expr *ep);
 
 static void gen_prog_func(
 	Expr *prog,
@@ -437,17 +436,33 @@ static void gen_expr(
 		gen_code("]");
 		break;
 	case E_CONST:
-		if (gen_builtin_const(ep))
-			break;
-		gen_code("%s", ep->value);
+		if (ep->extra.e_const)
+			gen_code("%s", ep->extra.e_const->name);
+		else
+			gen_code("%s", ep->value);
 		break;
 	case E_STRING:
 		gen_code("\"%s\"", ep->value);
 		break;
 	case E_FUNC:
-		if (ep->func_expr->type == E_VAR && gen_builtin_func(context, ep))
+		if (ep->func_expr->type == E_BUILTIN)
+		{
+			gen_builtin_func(context, ep);
 			break;
-		gen_expr(context, ep->func_expr, 0);
+		}
+		if (ep->func_expr->type == E_VAR &&
+				ep->func_expr->extra.e_var->type->tag != T_NONE)
+		{
+			/* we don't yet support variables of function type */
+			error_at_expr(ep->func_expr,
+				"variable '%s' is not a function\n",
+				ep->func_expr->extra.e_var->name);
+			report_at_expr(ep->func_expr->extra.e_var->decl,
+				"variable '%s' is declared here\n",
+				ep->func_expr->extra.e_var->name);
+		}
+		else
+			gen_expr(context, ep->func_expr, 0);
 		gen_code("(");
 		foreach (cep, ep->func_args)
 		{
@@ -520,54 +535,39 @@ static void gen_expr(
 	}
 }
 
-static int gen_builtin_const(Expr *ep)
-{
-	char	*const_name = ep->value;
-	struct const_symbol *sym = lookup_builtin_const(global_sym_table, const_name);
-
-	if (!sym)
-		return CT_NONE;
-	gen_code("%s", const_name);
-	return sym->type;
-}
-
 /* Generate builtin function call */
-static int gen_builtin_func(int context, Expr *ep)
+static void gen_builtin_func(int context, Expr *ep)
 {
-	char	*func_name = ep->func_expr->value;
-	Expr	*ap;			/* argument expr */
-	struct func_symbol *sym;
+	Expr *ap;	/* argument expr */
+	struct func_symbol *sym = ep->func_expr->extra.e_builtin;
 
-	if (ep->func_expr->type != E_VAR)
-		return FALSE;
-	sym = lookup_builtin_func(global_sym_table, func_name);
-	if (!sym)
-		return FALSE;	/* not a special function */
+	assert(ep->func_expr->type == E_BUILTIN);
+	assert(sym);
 
 #ifdef	DEBUG
 	report("gen_builtin_func: name=%s, type=%u, add_length=%u, "
 		"default_args=%u, ef_action_only=%u, ef_args=%u\n",
-		func_name, sym->type, sym->add_length, sym->default_args,
+		sym->name, sym->type, sym->add_length, sym->default_args,
 		sym->ef_action_only, sym->ef_args);
 #endif
 	/* All builtin functions require ssId as 1st parameter */
 	assert_at_expr(context != C_GLOBAL, ep,
-		"calling built-in function %s not allowed here\n", func_name);
-	gen_code("seq_%s("NM_SS, func_name);
+		"calling built-in function %s not allowed here\n", sym->name);
+	gen_code("seq_%s("NM_SS, sym->name);
 	if (context != C_COND && sym->cond_only)
 	{
 		error_at_expr(ep,
-		  "calling built-in function %s not allowed here\n", func_name);
-		return TRUE;
+		  "calling built-in function %s not allowed here\n", sym->name);
+		return;
 	}
 	switch (sym->type)
 	{
 	case FT_EVENT:
 		/* Event flag functions */
-		gen_ef_func(context, ep, func_name, sym->ef_action_only);
+		gen_ef_func(context, ep, sym->name, sym->ef_action_only);
 		break;
 	case FT_PV:
-		gen_pv_func(context, ep, func_name, sym->add_length,
+		gen_pv_func(context, ep, sym->name, sym->add_length,
 			sym->default_args, sym->ef_args, sym->default_values);
 		break;
 	case FT_OTHER:
@@ -582,7 +582,6 @@ static int gen_builtin_func(int context, Expr *ep)
 	default:
 		assert(impossible);
 	}
-	return TRUE;
 }
 
 /* Check an event flag argument */
@@ -665,7 +664,7 @@ static void gen_pv_func(
 	if (ap == 0)
 	{
 		error_at_expr(ep,
-			"function '%s' requires a parameter\n", func_name);
+			"function '%s' requires an argument\n", func_name);
 		return;
 	}
 
@@ -746,9 +745,12 @@ static void gen_pv_func(
 			/* special case: constant NOEVFLAG */
 			if (ap->type == E_CONST)
 			{
-				if (gen_builtin_const(ap)!=CT_EVFLAG)
+				if (ap->extra.e_const && ap->extra.e_const->type == CT_EVFLAG)
+					gen_expr(context, ap, 0);
+				else
 					error_at_expr(ap,
-					  "argument %d to built-in function %s must be an event flag\n",
+					  "argument %d to built-in function %s must "
+					  "be an event flag\n",
 					  num_extra_parms+1, func_name);
 			}
 			else
diff --git a/src/snc/types.h b/src/snc/types.h
index 2ee9027a..ed86ddbe 100644
--- a/src/snc/types.h
+++ b/src/snc/types.h
@@ -41,6 +41,8 @@ typedef struct chan_list	ChanList;
 typedef struct sync_queue_list	SyncQList;
 typedef struct var_list		VarList;
 typedef struct expr_pair	ExprPair;
+typedef struct func_symbol	FuncSym;
+typedef struct const_symbol	ConstSym;
 
 typedef unsigned long long	TypeMask;
 typedef unsigned int		uint;
@@ -129,6 +131,8 @@ struct expression			/* generic syntax node */
 		Expr	*e_change;	/* declaration of target state */
 		VarList	*e_entex;	/* local declarations */
 		VarList	*e_cmpnd;	/* block local definitions */
+		FuncSym	*e_builtin;	/* builtin function */
+		ConstSym *e_const;	/* builtin constant */
 	}	extra;
 };
 
@@ -284,6 +288,7 @@ enum expr_type			/* description [child expressions...] */
 	D_WHEN,			/* when statement [cond,defns,stmts] */
 
 	E_BINOP,		/* binary operator [left,right] */
+	E_BUILTIN,		/* builtin function [] */
 	E_CAST,			/* type cast [operand] */
 	E_CONST,		/* numeric (inkl. character) constant [] */
 	E_FUNC,			/* function call [expr,args] */
@@ -404,6 +409,7 @@ expr_type_info[]
 	{ "D_SYNCQ",	3 },
 	{ "D_WHEN",	3 },
 	{ "E_BINOP",	2 },
+	{ "E_BUILTIN",	0 },
 	{ "E_CAST",	2 },
 	{ "E_CONST",	0 },
 	{ "E_FUNC",	2 },
-- 
GitLab