From 5f2220d6243a020bb1c0665b820f35f0970d8503 Mon Sep 17 00:00:00 2001
From: Robert Konrad <git2016@robdangero.us>
Date: Sat, 24 Aug 2024 22:31:30 +0200
Subject: [PATCH] Support const floats

---
 Sources/backends/hlsl.c     | 13 +++++-
 Sources/compiler.c          |  2 +-
 Sources/functions.c         | 55 +++++++++++++++++++++++++
 Sources/globals.c           | 82 +++++++++++++++++++++++++------------
 Sources/globals.h           | 24 ++++++++++-
 Sources/integrations/kinc.c | 14 +++----
 Sources/kong.c              |  6 +++
 Sources/parser.c            | 76 +++++++++++++++++++++++++++++++++-
 Sources/parser.h            |  2 +-
 9 files changed, 234 insertions(+), 40 deletions(-)

diff --git a/Sources/backends/hlsl.c b/Sources/backends/hlsl.c
index 2665891..668517b 100644
--- a/Sources/backends/hlsl.c
+++ b/Sources/backends/hlsl.c
@@ -259,6 +259,18 @@ static void write_globals(char *hlsl, size_t *offset, function *main, function *
 			*offset += sprintf(&hlsl[*offset], "TextureCube<float4> _%" PRIu64 " : register(t%i);\n\n", g.var_index, register_index);
 		}
 		else if (g.type == float_id) {
+			*offset += sprintf(&hlsl[*offset], "static const float _%" PRIu64 " = %f;\n\n", g.var_index, g.value.value.floats[0]);
+		}
+		else if (g.type == float2_id) {
+			*offset += sprintf(&hlsl[*offset], "static const float2 _%" PRIu64 " = float2(%f, %f);\n\n", g.var_index, g.value.value.floats[0], g.value.value.floats[1]);
+		}
+		else if (g.type == float3_id) {
+			*offset += sprintf(&hlsl[*offset], "static const float3 _%" PRIu64 " = float3(%f, %f, %f);\n\n", g.var_index, g.value.value.floats[0],
+			                   g.value.value.floats[1], g.value.value.floats[2]);
+		}
+		else if (g.type == float4_id) {
+			*offset += sprintf(&hlsl[*offset], "static const float4 _%" PRIu64 " = float4(%f, %f, %f, %f);\n\n", g.var_index, g.value.value.floats[0],
+			                   g.value.value.floats[1], g.value.value.floats[2], g.value.value.floats[3]);
 		}
 		else {
 			*offset += sprintf(&hlsl[*offset], "cbuffer _%" PRIu64 " : register(b%i) {\n", g.var_index, register_index);
@@ -468,7 +480,6 @@ static void write_functions(char *hlsl, size_t *offset, shader_stage stage, func
 				}
 				else if (parameter_index == 1) {
 					*offset += sprintf(&hlsl[*offset], ", BuiltInTriangleIntersectionAttributes _kong_triangle_intersection_attributes"); 
-					//type_string(f->parameter_types[parameter_index].type), parameter_ids[parameter_index]);
 				}
 				else {
 					*offset += sprintf(&hlsl[*offset], ", %s _%" PRIu64, type_string(f->parameter_types[parameter_index].type), parameter_ids[parameter_index]);
diff --git a/Sources/compiler.c b/Sources/compiler.c
index 58292cb..8ac4817 100644
--- a/Sources/compiler.c
+++ b/Sources/compiler.c
@@ -429,7 +429,7 @@ variable emit_expression(opcodes *code, block *parent, expression *e) {
 	case EXPRESSION_CALL: {
 		type_ref t;
 		init_type_ref(&t, NO_NAME);
-		t.type = float4_id;
+		t.type = e->type.type;
 		variable v = allocate_variable(t, VARIABLE_LOCAL);
 
 		opcode o;
diff --git a/Sources/functions.c b/Sources/functions.c
index baf1294..3a98209 100644
--- a/Sources/functions.c
+++ b/Sources/functions.c
@@ -15,6 +15,52 @@ function_id float2_constructor_id;
 function_id float3_constructor_id;
 function_id float4_constructor_id;
 
+static void add_func_int(char *name) {
+	function_id func = add_function(add_name(name));
+	function *f = get_function(func);
+	init_type_ref(&f->return_type, add_name("int"));
+	f->return_type.type = find_type_by_ref(&f->return_type);
+	f->parameters_size = 0;
+	f->block = NULL;
+}
+
+static void add_func_float3_float_float_float(char *name) {
+	function_id func = add_function(add_name(name));
+	function *f = get_function(func);
+	init_type_ref(&f->return_type, add_name("float3"));
+	f->return_type.type = find_type_by_ref(&f->return_type);
+	f->parameter_names[0] = add_name("a");
+	f->parameter_names[1] = add_name("b");
+	f->parameter_names[2] = add_name("c");
+	for (int i = 0; i < 3; ++i) {
+		init_type_ref(&f->parameter_types[0], add_name("float"));
+		f->parameter_types[0].type = find_type_by_ref(&f->parameter_types[0]);
+	}
+	f->parameters_size = 3;
+	f->block = NULL;
+}
+
+static void add_func_float3(char *name) {
+	function_id func = add_function(add_name(name));
+	function *f = get_function(func);
+	init_type_ref(&f->return_type, add_name("float3"));
+	f->return_type.type = find_type_by_ref(&f->return_type);
+	f->parameters_size = 0;
+	f->block = NULL;
+}
+
+static void add_func_float3_float3(char *name) {
+	function_id func = add_function(add_name(name));
+	function *f = get_function(func);
+	init_type_ref(&f->return_type, add_name("float3"));
+	f->return_type.type = find_type_by_ref(&f->return_type);
+	f->parameter_names[0] = add_name("a");
+	init_type_ref(&f->parameter_types[0], add_name("float3"));
+	f->parameter_types[0].type = find_type_by_ref(&f->parameter_types[0]);
+	f->parameters_size = 1;
+	f->block = NULL;
+}
+
 void functions_init(void) {
 	function *new_functions = realloc(functions, functions_size * sizeof(function));
 	debug_context context = {0};
@@ -81,6 +127,15 @@ void functions_init(void) {
 		f->parameters_size = 1;
 		f->block = NULL;
 	}
+
+	add_func_int("group_id");
+	add_func_int("group_thread_id");
+	add_func_int("dispatch_thread_id");
+	add_func_int("group_index");
+
+	add_func_float3_float_float_float("lerp");
+	add_func_float3("world_ray_direction");
+	add_func_float3_float3("normalize");
 }
 
 static void grow_if_needed(uint64_t size) {
diff --git a/Sources/globals.c b/Sources/globals.c
index 1da30db..dc53c2a 100644
--- a/Sources/globals.c
+++ b/Sources/globals.c
@@ -8,33 +8,61 @@ static global globals[1024];
 static global_id globals_size = 0;
 
 void globals_init(void) {
-	add_global_with_value(float_id, add_name("COMPARE_ALWAYS"), 0);
-	add_global_with_value(float_id, add_name("COMPARE_NEVER"), 1);
-	add_global_with_value(float_id, add_name("COMPARE_EQUAL"), 2);
-	add_global_with_value(float_id, add_name("COMPARE_NOT_EQUAL"), 3);
-	add_global_with_value(float_id, add_name("COMPARE_LESS"), 4);
-	add_global_with_value(float_id, add_name("COMPARE_LESS_EQUAL"), 5);
-	add_global_with_value(float_id, add_name("COMPARE_GREATER"), 6);
-	add_global_with_value(float_id, add_name("COMPARE_GREATER_EQUAL"), 7);
+	global_value int_value;
+	int_value.kind = GLOBAL_VALUE_INT;
+	
+	int_value.value.ints[0] = 0;
+	add_global_with_value(float_id, add_name("COMPARE_ALWAYS"), int_value);
+	int_value.value.ints[0] = 1;
+	add_global_with_value(float_id, add_name("COMPARE_NEVER"), int_value);
+	int_value.value.ints[0] = 2;
+	add_global_with_value(float_id, add_name("COMPARE_EQUAL"), int_value);
+	int_value.value.ints[0] = 3;
+	add_global_with_value(float_id, add_name("COMPARE_NOT_EQUAL"), int_value);
+	int_value.value.ints[0] = 4;
+	add_global_with_value(float_id, add_name("COMPARE_LESS"), int_value);
+	int_value.value.ints[0] = 5;
+	add_global_with_value(float_id, add_name("COMPARE_LESS_EQUAL"), int_value);
+	int_value.value.ints[0] = 6;
+	add_global_with_value(float_id, add_name("COMPARE_GREATER"), int_value);
+	int_value.value.ints[0] = 7;
+	add_global_with_value(float_id, add_name("COMPARE_GREATER_EQUAL"), int_value);
 
-	add_global_with_value(float_id, add_name("BLEND_ONE"), 0);
-	add_global_with_value(float_id, add_name("BLEND_ZERO"), 1);
-	add_global_with_value(float_id, add_name("BLEND_SOURCE_ALPHA"), 2);
-	add_global_with_value(float_id, add_name("BLEND_DEST_ALPHA"), 3);
-	add_global_with_value(float_id, add_name("BLEND_INV_SOURCE_ALPHA"), 4);
-	add_global_with_value(float_id, add_name("BLEND_INV_DEST_ALPHA"), 5);
-	add_global_with_value(float_id, add_name("BLEND_SOURCE_COLOR"), 6);
-	add_global_with_value(float_id, add_name("BLEND_DEST_COLOR"), 7);
-	add_global_with_value(float_id, add_name("BLEND_INV_SOURCE_COLOR"), 8);
-	add_global_with_value(float_id, add_name("BLEND_INV_DEST_COLOR"), 9);
-	add_global_with_value(float_id, add_name("BLEND_CONSTANT"), 10);
-	add_global_with_value(float_id, add_name("BLEND_INV_CONSTANT"), 11);
+	int_value.value.ints[0] = 0;
+	add_global_with_value(float_id, add_name("BLEND_ONE"), int_value);
+	int_value.value.ints[0] = 1;
+	add_global_with_value(float_id, add_name("BLEND_ZERO"), int_value);
+	int_value.value.ints[0] = 2;
+	add_global_with_value(float_id, add_name("BLEND_SOURCE_ALPHA"), int_value);
+	int_value.value.ints[0] = 3;
+	add_global_with_value(float_id, add_name("BLEND_DEST_ALPHA"), int_value);
+	int_value.value.ints[0] = 4;
+	add_global_with_value(float_id, add_name("BLEND_INV_SOURCE_ALPHA"), int_value);
+	int_value.value.ints[0] = 5;
+	add_global_with_value(float_id, add_name("BLEND_INV_DEST_ALPHA"), int_value);
+	int_value.value.ints[0] = 6;
+	add_global_with_value(float_id, add_name("BLEND_SOURCE_COLOR"), int_value);
+	int_value.value.ints[0] = 7;
+	add_global_with_value(float_id, add_name("BLEND_DEST_COLOR"), int_value);
+	int_value.value.ints[0] = 8;
+	add_global_with_value(float_id, add_name("BLEND_INV_SOURCE_COLOR"), int_value);
+	int_value.value.ints[0] = 9;
+	add_global_with_value(float_id, add_name("BLEND_INV_DEST_COLOR"), int_value);
+	int_value.value.ints[0] = 10;
+	add_global_with_value(float_id, add_name("BLEND_CONSTANT"), int_value);
+	int_value.value.ints[0] = 11;
+	add_global_with_value(float_id, add_name("BLEND_INV_CONSTANT"), int_value);
 
-	add_global_with_value(float_id, add_name("BLENDOP_ADD"), 0);
-	add_global_with_value(float_id, add_name("BLENDOP_SUBTRACT"), 1);
-	add_global_with_value(float_id, add_name("BLENDOP_REVERSE_SUBTRACT"), 2);
-	add_global_with_value(float_id, add_name("BLENDOP_MIN"), 3);
-	add_global_with_value(float_id, add_name("BLENDOP_MAX"), 4);
+	int_value.value.ints[0] = 0;
+	add_global_with_value(float_id, add_name("BLENDOP_ADD"), int_value);
+	int_value.value.ints[0] = 1;
+	add_global_with_value(float_id, add_name("BLENDOP_SUBTRACT"), int_value);
+	int_value.value.ints[0] = 2;
+	add_global_with_value(float_id, add_name("BLENDOP_REVERSE_SUBTRACT"), int_value);
+	int_value.value.ints[0] = 3;
+	add_global_with_value(float_id, add_name("BLENDOP_MIN"), int_value);
+	int_value.value.ints[0] = 4;
+	add_global_with_value(float_id, add_name("BLENDOP_MAX"), int_value);
 }
 
 global_id add_global(type_id type, name_id name) {
@@ -42,12 +70,12 @@ global_id add_global(type_id type, name_id name) {
 	globals[index].name = name;
 	globals[index].type = type;
 	globals[index].var_index = 0;
-	globals[index].value = 0;
+	globals[index].value.kind = GLOBAL_VALUE_NONE;
 	globals_size += 1;
 	return index;
 }
 
-global_id add_global_with_value(type_id type, name_id name, float value) {
+global_id add_global_with_value(type_id type, name_id name, global_value value) {
 	uint32_t index = globals_size;
 	globals[index].name = name;
 	globals[index].type = type;
diff --git a/Sources/globals.h b/Sources/globals.h
index 3a3b093..9bf654a 100644
--- a/Sources/globals.h
+++ b/Sources/globals.h
@@ -5,17 +5,37 @@
 
 typedef uint32_t global_id;
 
+typedef struct global_value {
+	enum {
+		GLOBAL_VALUE_FLOAT,
+		GLOBAL_VALUE_FLOAT2,
+		GLOBAL_VALUE_FLOAT3,
+		GLOBAL_VALUE_FLOAT4,
+		GLOBAL_VALUE_INT,
+		GLOBAL_VALUE_INT2,
+		GLOBAL_VALUE_INT3,
+		GLOBAL_VALUE_INT4,
+		GLOBAL_VALUE_BOOL,
+		GLOBAL_VALUE_NONE
+	} kind;
+	union {
+		float floats[4];
+		int ints[4];
+		bool b;
+	} value;
+} global_value;
+
 typedef struct global {
 	name_id name;
 	type_id type;
 	uint64_t var_index;
-	float value;
+	global_value value;
 } global;
 
 void globals_init(void);
 
 global_id add_global(type_id type, name_id name);
-global_id add_global_with_value(type_id type, name_id name, float value);
+global_id add_global_with_value(type_id type, name_id name, global_value value);
 
 global find_global(name_id name);
 
diff --git a/Sources/integrations/kinc.c b/Sources/integrations/kinc.c
index 574ae75..ac1009b 100644
--- a/Sources/integrations/kinc.c
+++ b/Sources/integrations/kinc.c
@@ -610,43 +610,43 @@ void kinc_export(char *directory, api_kind api) {
 						debug_context context = {0};
 						check(t->members.m[j].value.kind == TOKEN_IDENTIFIER, context, "depth_mode expects an identifier");
 						global g = find_global(t->members.m[j].value.identifier);
-						fprintf(output, "\t%s.depth_mode = %s;\n\n", get_name(t->name), convert_compare_mode((int)g.value));
+						fprintf(output, "\t%s.depth_mode = %s;\n\n", get_name(t->name), convert_compare_mode(g.value.value.ints[0]));
 					}
 					else if (t->members.m[j].name == add_name("blend_source")) {
 						debug_context context = {0};
 						check(t->members.m[j].value.kind == TOKEN_IDENTIFIER, context, "blend_source expects an identifier");
 						global g = find_global(t->members.m[j].value.identifier);
-						fprintf(output, "\t%s.blend_source = %s;\n\n", get_name(t->name), convert_blend_mode((int)g.value));
+						fprintf(output, "\t%s.blend_source = %s;\n\n", get_name(t->name), convert_blend_mode(g.value.value.ints[0]));
 					}
 					else if (t->members.m[j].name == add_name("blend_destination")) {
 						debug_context context = {0};
 						check(t->members.m[j].value.kind == TOKEN_IDENTIFIER, context, "blend_destination expects an identifier");
 						global g = find_global(t->members.m[j].value.identifier);
-						fprintf(output, "\t%s.blend_destination = %s;\n\n", get_name(t->name), convert_blend_mode((int)g.value));
+						fprintf(output, "\t%s.blend_destination = %s;\n\n", get_name(t->name), convert_blend_mode(g.value.value.ints[0]));
 					}
 					else if (t->members.m[j].name == add_name("blend_operation")) {
 						debug_context context = {0};
 						check(t->members.m[j].value.kind == TOKEN_IDENTIFIER, context, "blend_operation expects an identifier");
 						global g = find_global(t->members.m[j].value.identifier);
-						fprintf(output, "\t%s.blend_operation = %s;\n\n", get_name(t->name), convert_blend_op((int)g.value));
+						fprintf(output, "\t%s.blend_operation = %s;\n\n", get_name(t->name), convert_blend_op(g.value.value.ints[0]));
 					}
 					else if (t->members.m[j].name == add_name("alpha_blend_source")) {
 						debug_context context = {0};
 						check(t->members.m[j].value.kind == TOKEN_IDENTIFIER, context, "alpha_blend_source expects an identifier");
 						global g = find_global(t->members.m[j].value.identifier);
-						fprintf(output, "\t%s.alpha_blend_source = %s;\n\n", get_name(t->name), convert_blend_mode((int)g.value));
+						fprintf(output, "\t%s.alpha_blend_source = %s;\n\n", get_name(t->name), convert_blend_mode(g.value.value.ints[0]));
 					}
 					else if (t->members.m[j].name == add_name("alpha_blend_destination")) {
 						debug_context context = {0};
 						check(t->members.m[j].value.kind == TOKEN_IDENTIFIER, context, "alpha_blend_destination expects an identifier");
 						global g = find_global(t->members.m[j].value.identifier);
-						fprintf(output, "\t%s.alpha_blend_destination = %s;\n\n", get_name(t->name), convert_blend_mode((int)g.value));
+						fprintf(output, "\t%s.alpha_blend_destination = %s;\n\n", get_name(t->name), convert_blend_mode(g.value.value.ints[0]));
 					}
 					else if (t->members.m[j].name == add_name("alpha_blend_operation")) {
 						debug_context context = {0};
 						check(t->members.m[j].value.kind == TOKEN_IDENTIFIER, context, "alpha_blend_operation expects an identifier");
 						global g = find_global(t->members.m[j].value.identifier);
-						fprintf(output, "\t%s.alpha_blend_operation = %s;\n\n", get_name(t->name), convert_blend_op((int)g.value));
+						fprintf(output, "\t%s.alpha_blend_operation = %s;\n\n", get_name(t->name), convert_blend_op(g.value.value.ints[0]));
 					}
 					else {
 						debug_context context = {0};
diff --git a/Sources/kong.c b/Sources/kong.c
index 5ee896d..142f14a 100644
--- a/Sources/kong.c
+++ b/Sources/kong.c
@@ -69,6 +69,12 @@ type_ref resolve_member_var_type(statement *parent_block, type_ref parent_type,
 			return left->type;
 		}
 	}
+	else if (left->kind == EXPRESSION_CALL) {
+		if (parent_block != NULL) {
+			resolve_types_in_expression(parent_block, left);
+			return left->type;
+		}
+	}
 	else if (left->kind == EXPRESSION_INDEX) {
 		if (parent_type.type != NO_TYPE) {
 			init_type_ref(&left->type, NO_NAME);
diff --git a/Sources/parser.c b/Sources/parser.c
index 1317947..2924c48 100644
--- a/Sources/parser.c
+++ b/Sources/parser.c
@@ -811,6 +811,7 @@ static expressions parse_parameters(state_t *state) {
 	e.size = 0;
 
 	if (current(state).kind == TOKEN_RIGHT_PAREN) {
+		advance_state(state);
 		return e;
 	}
 
@@ -1042,6 +1043,12 @@ static definition parse_const(state_t *state) {
 		advance_state(state);
 	}
 
+	expression *value = NULL;
+	if (current(state).kind == TOKEN_OPERATOR && current(state).op == OPERATOR_ASSIGN) {
+		advance_state(state);
+		value = parse_expression(state);
+	}
+
 	match_token(state, TOKEN_SEMICOLON, "Expected a semicolon");
 	advance_state(state);
 
@@ -1049,7 +1056,7 @@ static definition parse_const(state_t *state) {
 
 	if (type_name == NO_NAME) {
 		debug_context context = {0};
-		check(type != NO_TYPE, context, "Const has not type");
+		check(type != NO_TYPE, context, "Const has no type");
 		d.kind = DEFINITION_CONST_CUSTOM;
 		d.global = add_global(type, name.identifier);
 	}
@@ -1065,6 +1072,73 @@ static definition parse_const(state_t *state) {
 		d.kind = DEFINITION_SAMPLER;
 		d.global = add_global(sampler_type_id, name.identifier);
 	}
+	else if (type_name == add_name("float")) {
+		debug_context context = {0};
+		check(value != NULL, context, "const float requires an initialization value");
+		check(value->kind == EXPRESSION_NUMBER, context, "const float3 requires a number");
+
+		global_value float_value;
+		float_value.kind = GLOBAL_VALUE_FLOAT;
+
+		float_value.value.floats[0] = (float)value->number;
+
+		d.kind = DEFINITION_CONST_BASIC;
+		d.global = add_global_with_value(float_id, name.identifier, float_value);
+	}
+	else if (type_name == add_name("float2")) {
+		debug_context context = {0};
+		check(value != NULL, context, "const float2 requires an initialization value");
+		check(value->kind == EXPRESSION_CALL, context, "const float2 requires a constructor call");
+		check(value->call.func_name == add_name("float2"), context, "const float2 requires a float2 call");
+		check(value->call.parameters.size == 3, context, "const float2 construtor call requires two parameters");
+
+		global_value float2_value;
+		float2_value.kind = GLOBAL_VALUE_FLOAT2;
+
+		for (int i = 0; i < 2; ++i) {
+			check(value->call.parameters.e[i]->kind == EXPRESSION_NUMBER, context, "const float2 construtor parameters have to be numbers");
+			float2_value.value.floats[i] = (float)value->call.parameters.e[i]->number;
+		}
+
+		d.kind = DEFINITION_CONST_BASIC;
+		d.global = add_global_with_value(float2_id, name.identifier, float2_value);
+	}
+	else if (type_name == add_name("float3")) {
+		debug_context context = {0};
+		check(value != NULL, context, "const float3 requires an initialization value");
+		check(value->kind == EXPRESSION_CALL, context, "const float3 requires a constructor call");
+		check(value->call.func_name == add_name("float3"), context, "const float3 requires a float3 call");
+		check(value->call.parameters.size == 3, context, "const float3 construtor call requires three parameters");
+
+		global_value float3_value;
+		float3_value.kind = GLOBAL_VALUE_FLOAT3;
+
+		for (int i = 0; i < 3; ++i) {
+			check(value->call.parameters.e[i]->kind == EXPRESSION_NUMBER, context, "const float3 construtor parameters have to be numbers");
+			float3_value.value.floats[i] = (float)value->call.parameters.e[i]->number;
+		}
+
+		d.kind = DEFINITION_CONST_BASIC;
+		d.global = add_global_with_value(float3_id, name.identifier, float3_value);
+	}
+	else if (type_name == add_name("float4")) {
+		debug_context context = {0};
+		check(value != NULL, context, "const float4 requires an initialization value");
+		check(value->kind == EXPRESSION_CALL, context, "const float4 requires a constructor call");
+		check(value->call.func_name == add_name("float4"), context, "const float4 requires a float4 call");
+		check(value->call.parameters.size == 4, context, "const float4 construtor call requires four parameters");
+
+		global_value float4_value;
+		float4_value.kind = GLOBAL_VALUE_FLOAT4;
+
+		for (int i = 0; i < 4; ++i) {
+			check(value->call.parameters.e[i]->kind == EXPRESSION_NUMBER, context, "const float4 construtor parameters have to be numbers");
+			float4_value.value.floats[i] = (float)value->call.parameters.e[i]->number;
+		}
+
+		d.kind = DEFINITION_CONST_BASIC;
+		d.global = add_global_with_value(float4_id, name.identifier, float4_value);
+	}
 	else {
 		debug_context context = {0};
 		error(context, "Unsupported global");
diff --git a/Sources/parser.h b/Sources/parser.h
index 0147ceb..5c4ebe5 100644
--- a/Sources/parser.h
+++ b/Sources/parser.h
@@ -120,7 +120,7 @@ typedef struct statement {
 } statement;
 
 typedef struct definition {
-	enum { DEFINITION_FUNCTION, DEFINITION_STRUCT, DEFINITION_TEX2D, DEFINITION_TEXCUBE, DEFINITION_SAMPLER, DEFINITION_CONST_CUSTOM } kind;
+	enum { DEFINITION_FUNCTION, DEFINITION_STRUCT, DEFINITION_TEX2D, DEFINITION_TEXCUBE, DEFINITION_SAMPLER, DEFINITION_CONST_CUSTOM, DEFINITION_CONST_BASIC } kind;
 
 	union {
 		function_id function;