aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/actualize.c205
-rw-r--r--src/ast.c135
-rw-r--r--src/debug.c2
-rw-r--r--src/gen_lexer.h497
-rw-r--r--src/lexer.l1
-rw-r--r--src/parser.y5
-rw-r--r--src/source.mk2
7 files changed, 269 insertions, 578 deletions
diff --git a/src/actualize.c b/src/actualize.c
index 8424c52..8aec279 100644
--- a/src/actualize.c
+++ b/src/actualize.c
@@ -84,6 +84,32 @@ static struct ast_node *void_type()
return void_type;
}
+static struct ast_node *i64_type()
+{
+ char *i64_str = strdup("i64");
+ if (!i64_str) {
+ internal_error("couldn't allocate i64 string");
+ return NULL;
+ }
+
+ struct ast_node *i64_id = gen_id(i64_str);
+ if (!i64_id) {
+ internal_error("couldn't allocate i64 id");
+ free(i64_str);
+ return NULL;
+ }
+
+ struct ast_node *i64_type = gen_type(AST_TYPE_ID, i64_id, NULL, NULL);
+ if (!i64_type) {
+ internal_error("couldn't allocate i64 type");
+ destroy_ast_node(i64_id);
+ return NULL;
+ }
+
+ i64_type->type = i64_type;
+ return i64_type;
+}
+
static int push_defer(struct act_state *state, struct ast_node *expr)
{
struct act_stack *new = calloc(1, sizeof(struct act_stack));
@@ -306,7 +332,6 @@ static int analyze_file_visibility(struct scope *scope, struct ast_node *node)
}
case AST_STRUCT: {
- /* TODO: should structs be their own 'thing'? */
ret |= scope_add_type(scope, node);
break;
}
@@ -570,18 +595,6 @@ struct ast_node *extract_template(struct ast_node *type)
return extract_template(type->_type.next);
}
-struct ast_node *extract_base(struct ast_node *type)
-{
- if (!type)
- return 0;
-
- assert(type->node_type == AST_TYPE);
- if (is_templateable(type))
- return type;
-
- return extract_base(type->_type.next);
-}
-
static void actualize_template_types(struct ast_node *params,
struct ast_node *args)
{
@@ -1146,24 +1159,23 @@ static int actualize_type(struct act_state *state,
assert(exists->node_type == AST_ALIAS
|| exists->node_type == AST_TEMPLATE
|| exists->node_type == AST_STRUCT
- || exists->node_type == AST_ENUM);
+ || exists->node_type == AST_ENUM
+ || exists->node_type == AST_UNION);
/* actualize whatever type we have on demand, either alias or
* template */
if (!ast_flags(exists, AST_FLAG_ACTUAL))
if (actualize(state, exists->scope, exists))
EXIT_ACT(-1);
+ assert(type->_type.next == NULL);
+ destroy_ast_node(type->_type.id);
if (exists->node_type == AST_ALIAS) {
/* TODO: check if this is good enough */
- destroy_ast_node(type->_type.id);
- assert(type->_type.next == NULL);
type->_type.kind = AST_TYPE_ALIAS;
type->_type.alias.alias = exists;
type->_type.alias.actual = exists->_alias.type;
}
else if (exists->node_type == AST_TEMPLATE) {
- destroy_ast_node(type->_type.id);
- assert(type->_type.next == NULL);
type->_type.kind = AST_TYPE_TEMPLATE;
type->_type.template.template = exists;
/* this should be populated later */
@@ -1171,16 +1183,23 @@ static int actualize_type(struct act_state *state,
}
else if (exists->node_type == AST_STRUCT) {
/* I think, will still have to TODO: check */
- destroy_ast_node(type->_type.id);
- assert(type->_type.next == NULL);
type->_type.kind = AST_TYPE_STRUCT;
- type->_type.struc.struc = clone_ast_node(
- exists->_struct.id);
+ type->_type.struc.id =
+ clone_ast_node(exists->_struct.id);
/* should be populated later */
type->_type.struc.impls = NULL;
}
+ else if (exists->node_type == AST_ENUM) {
+ type->_type.kind = AST_TYPE_ENUM;
+ type->_type.enu.id = clone_ast_node(exists->_enum.id);
+ type->_type.enu.type = exists->_enum.type;
+ }
+ else if (exists->node_type == AST_UNION) {
+ type->_type.kind = AST_TYPE_UNION;
+ type->_type.unio.id = clone_ast_node(exists->_union.id);
+ type->_type.unio.impls = NULL;
+ }
- /* TODO: what about enums? */
break;
}
@@ -1236,8 +1255,8 @@ static int actualize_type(struct act_state *state,
}
case AST_TYPE_STRUCT: {
- struct ast_node *struc = type->_type.struc.struc;
- struct ast_node *exists = file_scope_resolve_type(scope, struc);
+ struct ast_node *id = type->_type.struc.id;
+ struct ast_node *exists = file_scope_resolve_type(scope, id);
if (!exists || exists->node_type != AST_STRUCT) {
semantic_error(scope->fctx, type, "no such struct");
EXIT_ACT(-1);
@@ -1362,40 +1381,6 @@ static int pointer_conversion(struct ast_node *a, struct ast_node *b)
return 0;
}
-static int check_impls(struct scope *scope, struct ast_node *target,
- struct ast_node *exists)
-{
- struct ast_node *args = target->_type.struc.impls;
- struct ast_node *params = exists->_struct.generics;
- while (args && params) {
- assert(params->node_type == AST_ALIAS);
- assert(args->node_type == AST_TYPE);
-
- struct ast_node *alias_actual = params->_alias.type;
- if (!implements(scope, args, alias_actual)) {
- char *astr = type_str(args);
- char *pstr = type_str(params->type);
- semantic_error(scope->fctx, args,
- "%s does not implement %s",
- astr, pstr);
- free(astr);
- free(pstr);
- return -1;
- }
-
- params = params->next;
- args = args->next;
- }
-
- if (args || params) {
- semantic_error(scope->fctx, target,
- "wrong number of type arguments");
- return -1;
- }
-
- return 0;
-}
-
static size_t member_count(struct ast_node *exists)
{
assert(exists->node_type == AST_STRUCT);
@@ -1448,6 +1433,22 @@ static struct ast_node *lookup_struct_member(struct ast_node *struc,
return lookup_struct_member_idx(struc, find, idx);
}
+static struct ast_node *lookup_enum_member(struct ast_node *enu,
+ struct ast_node *find)
+{
+ size_t i = 0;
+ struct ast_node *m = enu->_enum.body;
+ while (m) {
+ assert(m->node_type == AST_VAL);
+ if (identical_ast_nodes(0, find, m->_val.id))
+ break;
+ m = m->next;
+ i++;
+ }
+
+ return m;
+}
+
static int init_struct(struct act_state *state, struct scope *scope,
struct ast_node *exists, struct ast_node *init)
{
@@ -1529,7 +1530,7 @@ static int actualize_struct_init(struct act_state *state,
return -1;
}
- struct ast_node *id = struct_type->_type.struc.struc;
+ struct ast_node *id = struct_type->_type.struc.id;
struct ast_node *exists = file_scope_resolve_type(scope, id);
assert(exists);
@@ -1909,7 +1910,7 @@ static int actualize_struct(struct act_state *state,
}
/* could maybe be renamed, but essentially dot in copper works as either
- * -> or . in C, so allow structures or templates and single lever pointers to
+ * -> or . in C, so allow structures or templates and single level pointers to
* structures or templates. */
static int has_members(struct ast_node *type)
{
@@ -2004,6 +2005,86 @@ static int actualize_assign(struct act_state *state, struct scope *scope,
return 0;
}
+static int actualize_fetch(struct act_state *state, struct scope *scope,
+ struct ast_node *fetch)
+{
+ assert(fetch->node_type == AST_FETCH);
+ struct ast_node *type = fetch->_fetch.type;
+ if (actualize(state, scope, type))
+ return -1;
+
+ if (type->_type.kind != AST_TYPE_ENUM) {
+ semantic_error(scope->fctx, type, "type is not an enum");
+ return -1;
+ }
+
+ struct ast_node *id = fetch->_fetch.id;
+ struct ast_node *enu = file_scope_resolve_type(scope, type->_type.id);
+ assert(enu);
+
+ struct ast_node *member = lookup_enum_member(enu, id);
+ if (!member) {
+ char *estr = type_str(type);
+ semantic_error(scope->fctx, id, "no such member in enum %s");
+ free(estr);
+ return -1;
+ }
+
+ fetch->type = enu->type;
+ return 0;
+}
+
+static int actualize_enum(struct act_state *state, struct scope *scope,
+ struct ast_node *node)
+{
+ assert(node->node_type == AST_ENUM);
+ struct ast_node *type = node->_enum.type;
+ struct scope *enum_scope = node->scope;
+
+ /* TODO: here we could save space by choosing the smallest type that
+ * fits */
+ if (!type) {
+ type = i64_type();
+ node->_enum.type = type;
+ } else if (actualize(state, enum_scope, type))
+ return -1;
+
+ long long counter = 0;
+ node->type = type;
+ struct ast_node *members = node->_enum.body;
+ while (members) {
+ members->type = type;
+ if (members->_val.val) {
+ struct ast_node *val = members->_val.val;
+ if (actualize(state, enum_scope, val))
+ return -1;
+
+ if (val->node_type != AST_CONST) {
+ semantic_error(scope->fctx, members,
+ "unable to process nonconstant expression");
+ return -1;
+ }
+
+ if (val->_const.kind != AST_CONST_INTEGER) {
+ semantic_error(scope->fctx, members,
+ "not expandable to an integer constant");
+ return -1;
+ }
+
+ counter = val->_const.integer;
+ }
+ else {
+ members->_val.val = gen_int(counter);
+ }
+
+ members = members->next;
+ counter++;
+ }
+
+ /* TODO: check that we don't go outside the limits of the type */
+ return 0;
+}
+
static int actualize(struct act_state *state, struct scope *scope,
struct ast_node *node)
{
@@ -2043,6 +2124,8 @@ static int actualize(struct act_state *state, struct scope *scope,
case AST_DOT: ret |= actualize_dot(state, scope, node); break;
case AST_INIT: ret |= actualize_init(state, scope, node); break;
case AST_ASSIGN: ret |= actualize_assign(state, scope, node); break;
+ case AST_FETCH: ret |= actualize_fetch(state, scope, node); break;
+ case AST_ENUM: ret |= actualize_enum(state, scope, node); break;
default:
/* more like internal_error, maybe? */
diff --git a/src/ast.c b/src/ast.c
index c80dd26..d258b91 100644
--- a/src/ast.c
+++ b/src/ast.c
@@ -310,6 +310,24 @@ void destroy_ctrl(struct ast_node *ctrl)
free(ctrl);
}
+struct ast_node *gen_fetch(struct ast_node *id, struct ast_node *type)
+{
+ ALLOC_NODE(n, "fetch");
+ n->node_type = AST_FETCH;
+ n->_fetch.id = id;
+ n->_fetch.type = type;
+ n->loc = id->loc;
+ return n;
+}
+
+static void destroy_fetch(struct ast_node *fetch)
+{
+ assert(fetch->node_type == AST_FETCH);
+ destroy_ast_node(fetch->_fetch.id);
+ destroy_ast_node(fetch->_fetch.type);
+ free(fetch);
+}
+
struct ast_node *gen_macro(struct ast_node *id, struct ast_node *params,
struct ast_node *body)
{
@@ -437,16 +455,19 @@ struct ast_node *gen_type(enum ast_type_kind kind, struct ast_node *id,
case AST_TYPE_UNION:
n->_type.unio.id = id;
- n->_type.unio.body = expr;
- if (id)
- n->loc = id->loc;
- else
- n->loc = expr->loc;
+ n->_type.unio.impls = expr;
+ n->loc = id->loc;
break;
case AST_TYPE_STRUCT:
- n->_type.struc.struc = id;
+ n->_type.struc.id = id;
+ n->_type.struc.impls = expr;
+ n->loc = id->loc;
+ break;
+
+ case AST_TYPE_ENUM:
+ n->_type.enu.id = id;
n->_type.struc.impls = expr;
n->loc = id->loc;
break;
@@ -503,13 +524,18 @@ void destroy_type(struct ast_node *type)
break;
case AST_TYPE_STRUCT:
- destroy_ast_node(type->_type.struc.struc);
+ destroy_ast_node(type->_type.struc.id);
DESTROY_LIST(type->_type.struc.impls);
break;
case AST_TYPE_UNION:
- DESTROY_LIST(type->_type.unio.body);
destroy_ast_node(type->_type.unio.id);
+ DESTROY_LIST(type->_type.unio.impls);
+ break;
+
+ case AST_TYPE_ENUM:
+ destroy_ast_node(type->_type.enu.id);
+ destroy_ast_node(type->_type.enu.type);
break;
case AST_TYPE_SIGN:
@@ -872,6 +898,7 @@ void destroy_ast_node(struct ast_node *node)
assert(node->node_type);
switch (node->node_type) {
+ case AST_FETCH: destroy_fetch(node); break;
case AST_UNION: destroy_union(node); break;
case AST_ASSIGN: destroy_assign(node); break;
case AST_INIT: destroy_init(node); break;
@@ -1028,6 +1055,17 @@ static void dump_flags(struct ast_node *node)
static void __dump_ast(int depth, struct ast_node *node)
{
switch (node->node_type) {
+ case AST_FETCH:
+ dump(depth, "{FETCH:");
+ dump_flags(node);
+ putchar('\n');
+
+ dump_ast(depth + 1, node->_fetch.id);
+ dump_ast(depth + 1, node->_fetch.type);
+
+ dump(depth, "}\n");
+ break;
+
case AST_UNION:
dump(depth, "{UNION:");
dump_flags(node);
@@ -1282,14 +1320,20 @@ static void __dump_ast(int depth, struct ast_node *node)
printf(" STRUCT\n");
/* oh yeah, struc is at least right now just an ID that
* we can use to fetch the actual struct with. */
- dump_ast(depth + 1, node->_type.struc.struc);
+ dump_ast(depth + 1, node->_type.struc.id);
dump_ast(depth + 1, node->_type.struc.impls);
break;
+ case AST_TYPE_ENUM:
+ printf(" ENUM\n");
+ dump_ast(depth + 1, node->_type.enu.id);
+ dump_ast(depth + 1, node->_type.enu.type);
+ break;
+
case AST_TYPE_UNION:
printf(" UNION\n");
dump_ast(depth + 1, node->_type.unio.id);
- dump_ast(depth + 1, node->_type.unio.body);
+ dump_ast(depth + 1, node->_type.unio.impls);
break;
case AST_TYPE_SIGN: printf(" SIGN\n");
@@ -1500,6 +1544,11 @@ struct ast_node *clone_ast_node(struct ast_node *node)
assert(node->node_type);
struct ast_node *new = NULL;
switch (node->node_type) {
+ case AST_FETCH:
+ new = gen_fetch(clone_ast_node(node->_fetch.id),
+ clone_ast_node(node->_fetch.type));
+ break;
+
case AST_UNION:
new = gen_union(clone_ast_node(node->_union.id),
clone_ast_node(node->_union.generics),
@@ -1632,15 +1681,22 @@ struct ast_node *clone_ast_node(struct ast_node *node)
case AST_TYPE_STRUCT:
new = gen_type(AST_TYPE_STRUCT,
- clone_ast_node(node->_type.struc.struc),
+ clone_ast_node(node->_type.struc.id),
clone_ast_node(node->_type.struc.impls),
NULL);
break;
+ case AST_TYPE_ENUM:
+ new = gen_type(AST_TYPE_ENUM,
+ clone_ast_node(node->_type.enu.id),
+ clone_ast_node(node->_type.enu.type),
+ NULL);
+ break;
+
case AST_TYPE_UNION:
new = gen_type(AST_TYPE_UNION,
clone_ast_node(node->_type.unio.id),
- clone_ast_node(node->_type.unio.body),
+ clone_ast_node(node->_type.unio.impls),
NULL);
break;
@@ -2083,8 +2139,7 @@ static int identical_type_sign(int exact, struct ast_node *a,
static int identical_type_struct(int exact, struct ast_node *a,
struct ast_node *b)
{
- if (!identical_ast_nodes(exact, a->_type.struc.struc,
- b->_type.struc.struc))
+ if (!identical_ast_nodes(exact, a->_type.struc.id, b->_type.struc.id))
return 0;
if (!identical_ast_nodes(exact, a->_type.struc.impls,
@@ -2100,7 +2155,20 @@ static int identical_type_union(int exact, struct ast_node *a,
if (!identical_ast_nodes(exact, a->_type.unio.id, b->_type.unio.id))
return 0;
- if (!identical_ast_nodes(exact, a->_type.unio.body, b->_type.unio.body))
+ if (!identical_ast_nodes(exact, a->_type.unio.impls,
+ b->_type.unio.impls))
+ return 0;
+
+ return 1;
+}
+
+static int identical_type_enum(int exact, struct ast_node *a,
+ struct ast_node *b)
+{
+ if (!identical_ast_nodes(exact, a->_type.enu.id, b->_type.enu.id))
+ return 0;
+
+ if (!identical_ast_nodes(exact, a->_type.enu.type, b->_type.enu.type))
return 0;
return 1;
@@ -2113,6 +2181,7 @@ static int identical_type(int exact, struct ast_node *a, struct ast_node *b)
int ret = 0;
switch (a->_type.kind) {
+ case AST_TYPE_ENUM: ret = identical_type_enum(exact, a, b); break;
case AST_TYPE_ALIAS: ret = identical_type_alias(exact, a, b); break;
case AST_TYPE_TEMPLATE: ret = identical_type_template(exact, a, b);
break;
@@ -2286,6 +2355,17 @@ static int identical_if(int exact, struct ast_node *a, struct ast_node *b)
return 1;
}
+static int identical_fetch(int exact, struct ast_node *a, struct ast_node *b)
+{
+ if (!identical_ast_nodes(exact, a->_fetch.id, b->_fetch.id))
+ return 0;
+
+ if (!identical_ast_nodes(exact, a->_fetch.type, b->_fetch.type))
+ return 0;
+
+ return 1;
+}
+
/* sort of unfortnate that we can't just do a direct memcmp... */
int identical_ast_nodes(int exact, struct ast_node *a, struct ast_node *b)
{
@@ -2318,6 +2398,7 @@ int identical_ast_nodes(int exact, struct ast_node *a, struct ast_node *b)
int ret = 0;
switch (a->node_type) {
+ case AST_FETCH: ret = identical_fetch(exact, a, b); break;
case AST_UNION: ret = identical_union(exact, a, b); break;
case AST_ASSIGN: ret = identical_assign(exact, a, b); break;
case AST_INIT: ret = identical_init(exact, a, b); break;
@@ -2598,7 +2679,7 @@ static int call_on_type_union(int (*call)(struct ast_node *,
{
int ret = 0;
ret |= call(node->_type.unio.id, data);
- ret |= call(node->_type.unio.body, data);
+ ret |= call(node->_type.unio.impls, data);
return ret;
}
@@ -2606,7 +2687,7 @@ static int call_on_type_struct(int (*call)(struct ast_node *,
void *), struct ast_node *node, void *data)
{
int ret = 0;
- ret |= call(node->_type.struc.struc, data);
+ ret |= call(node->_type.struc.id, data);
ret |= call(node->_type.struc.impls, data);
return ret;
}
@@ -2639,11 +2720,21 @@ static int call_on_type_sign(int (*call)(struct ast_node *,
return ret;
}
+static int call_on_type_enum(int (*call)(struct ast_node *,
+ void *), struct ast_node *node, void *data)
+{
+ int ret = 0;
+ ret |= call(node->_type.enu.id, data);
+ ret |= call(node->_type.enu.type, data);
+ return ret;
+}
+
static int call_on_type(int (*call)(struct ast_node *,
void *), struct ast_node *node, void *data)
{
int ret = 0;
switch (node->_type.kind) {
+ case AST_TYPE_ENUM: ret = call_on_type_enum(call, node, data); break;
case AST_TYPE_ALIAS: ret = call_on_type_alias(call, node, data); break;
case AST_TYPE_TEMPLATE: ret = call_on_type_template(call, node, data);
break;
@@ -2726,6 +2817,15 @@ static int call_on_block(int (*call)(struct ast_node *,
return call(node->_block.body, data);
}
+static int call_on_fetch(int (*call)(struct ast_node *,
+ void *), struct ast_node *node, void *data)
+{
+ int ret = 0;
+ ret |= call(node->_fetch.id, data);
+ ret |= call(node->_fetch.type, data);
+ return ret;
+}
+
/* I guess this works, but it's not exactly optimal as the caller sort of has to
* know when to continue to call on, and when it would cause an infinite loop.
* I.e. a call on an ID that is forwarded results in an infinite loop.
@@ -2741,6 +2841,7 @@ int ast_call_on(int (*call)(struct ast_node *,
return ret;
switch (node->node_type) {
+ case AST_FETCH: ret = call_on_fetch(call, node, data); break;
case AST_UNION: ret = call_on_union(call, node, data); break;
case AST_ASSIGN: ret = call_on_assign(call, node, data); break;
case AST_INIT: ret = call_on_init(call, node, data); break;
diff --git a/src/debug.c b/src/debug.c
index 566da42..e42aedc 100644
--- a/src/debug.c
+++ b/src/debug.c
@@ -193,7 +193,7 @@ static void _type_str(FILE *fp, struct ast_node *type)
}
case AST_TYPE_STRUCT: {
- struct ast_node *struc_id = type->_type.struc.struc;
+ struct ast_node *struc_id = type->_type.struc.id;
fprintf(fp, "%s", struc_id->_id.id);
struct ast_node *impls = type->_type.struc.impls;
diff --git a/src/gen_lexer.h b/src/gen_lexer.h
deleted file mode 100644
index 7fd7f5c..0000000
--- a/src/gen_lexer.h
+++ /dev/null
@@ -1,497 +0,0 @@
-/* SPDX-License-Identifier: GPL-3.0-or-later */
-
-#ifndef yyHEADER_H
-#define yyHEADER_H 1
-#define yyIN_HEADER 1
-
-#line 6 "src/gen_lexer.h"
-
-#line 8 "src/gen_lexer.h"
-
-#define YY_INT_ALIGNED short int
-
-/* A lexical scanner generated by flex */
-
-#define FLEX_SCANNER
-#define YY_FLEX_MAJOR_VERSION 2
-#define YY_FLEX_MINOR_VERSION 6
-#define YY_FLEX_SUBMINOR_VERSION 4
-#if YY_FLEX_SUBMINOR_VERSION > 0
-#define FLEX_BETA
-#endif
-
-/* First, we deal with platform-specific or compiler-specific issues. */
-
-/* begin standard C headers. */
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <stdlib.h>
-
-/* end standard C headers. */
-
-/* flex integer type definitions */
-
-#ifndef FLEXINT_H
-#define FLEXINT_H
-
-/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
-
-#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
-
-/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
- * if you want the limit (max/min) macros for int types.
- */
-#ifndef __STDC_LIMIT_MACROS
-#define __STDC_LIMIT_MACROS 1
-#endif
-
-#include <inttypes.h>
-typedef int8_t flex_int8_t;
-typedef uint8_t flex_uint8_t;
-typedef int16_t flex_int16_t;
-typedef uint16_t flex_uint16_t;
-typedef int32_t flex_int32_t;
-typedef uint32_t flex_uint32_t;
-#else
-typedef signed char flex_int8_t;
-typedef short int flex_int16_t;
-typedef int flex_int32_t;
-typedef unsigned char flex_uint8_t;
-typedef unsigned short int flex_uint16_t;
-typedef unsigned int flex_uint32_t;
-
-/* Limits of integral types. */
-#ifndef INT8_MIN
-#define INT8_MIN (-128)
-#endif
-#ifndef INT16_MIN
-#define INT16_MIN (-32767-1)
-#endif
-#ifndef INT32_MIN
-#define INT32_MIN (-2147483647-1)
-#endif
-#ifndef INT8_MAX
-#define INT8_MAX (127)
-#endif
-#ifndef INT16_MAX
-#define INT16_MAX (32767)
-#endif
-#ifndef INT32_MAX
-#define INT32_MAX (2147483647)
-#endif
-#ifndef UINT8_MAX
-#define UINT8_MAX (255U)
-#endif
-#ifndef UINT16_MAX
-#define UINT16_MAX (65535U)
-#endif
-#ifndef UINT32_MAX
-#define UINT32_MAX (4294967295U)
-#endif
-
-#ifndef SIZE_MAX
-#define SIZE_MAX (~(size_t)0)
-#endif
-
-#endif /* ! C99 */
-
-#endif /* ! FLEXINT_H */
-
-/* begin standard C++ headers. */
-
-/* TODO: this is always defined, so inline it */
-#define yyconst const
-
-#if defined(__GNUC__) && __GNUC__ >= 3
-#define yynoreturn __attribute__((__noreturn__))
-#else
-#define yynoreturn
-#endif
-
-/* An opaque pointer. */
-#ifndef YY_TYPEDEF_YY_SCANNER_T
-#define YY_TYPEDEF_YY_SCANNER_T
-typedef void* yyscan_t;
-#endif
-
-/* For convenience, these vars (plus the bison vars far below)
- are macros in the reentrant scanner. */
-#define yyin yyg->yyin_r
-#define yyout yyg->yyout_r
-#define yyextra yyg->yyextra_r
-#define yyleng yyg->yyleng_r
-#define yytext yyg->yytext_r
-#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno)
-#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column)
-#define yy_flex_debug yyg->yy_flex_debug_r
-
-/* Size of default input buffer. */
-#ifndef YY_BUF_SIZE
-#ifdef __ia64__
-/* On IA-64, the buffer size is 16k, not 8k.
- * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case.
- * Ditto for the __ia64__ case accordingly.
- */
-#define YY_BUF_SIZE 32768
-#else
-#define YY_BUF_SIZE 16384
-#endif /* __ia64__ */
-#endif
-
-#ifndef YY_TYPEDEF_YY_BUFFER_STATE
-#define YY_TYPEDEF_YY_BUFFER_STATE
-typedef struct yy_buffer_state *YY_BUFFER_STATE;
-#endif
-
-#ifndef YY_TYPEDEF_YY_SIZE_T
-#define YY_TYPEDEF_YY_SIZE_T
-typedef size_t yy_size_t;
-#endif
-
-#ifndef YY_STRUCT_YY_BUFFER_STATE
-#define YY_STRUCT_YY_BUFFER_STATE
-struct yy_buffer_state
-{
- FILE *yy_input_file;
-
- char *yy_ch_buf; /* input buffer */
- char *yy_buf_pos; /* current position in input buffer */
-
- /* Size of input buffer in bytes, not including room for EOB
- * characters.
- */
- int yy_buf_size;
-
- /* Number of characters read into yy_ch_buf, not including EOB
- * characters.
- */
- int yy_n_chars;
-
- /* Whether we "own" the buffer - i.e., we know we created it,
- * and can realloc() it to grow it, and should free() it to
- * delete it.
- */
- int yy_is_our_buffer;
-
- /* Whether this is an "interactive" input source; if so, and
- * if we're using stdio for input, then we want to use getc()
- * instead of fread(), to make sure we stop fetching input after
- * each newline.
- */
- int yy_is_interactive;
-
- /* Whether we're considered to be at the beginning of a line.
- * If so, '^' rules will be active on the next match, otherwise
- * not.
- */
- int yy_at_bol;
-
- int yy_bs_lineno; /**< The line count. */
- int yy_bs_column; /**< The column count. */
-
- /* Whether to try to fill the input buffer when we reach the
- * end of it.
- */
- int yy_fill_buffer;
-
- int yy_buffer_status;
-
-};
-#endif /* !YY_STRUCT_YY_BUFFER_STATE */
-
-void yyrestart ( FILE *input_file, yyscan_t yyscanner );
-void yy_switch_to_buffer ( YY_BUFFER_STATE new_buffer, yyscan_t yyscanner );
-YY_BUFFER_STATE yy_create_buffer ( FILE *file, int size, yyscan_t yyscanner );
-void yy_delete_buffer ( YY_BUFFER_STATE b, yyscan_t yyscanner );
-void yy_flush_buffer ( YY_BUFFER_STATE b, yyscan_t yyscanner );
-void yypush_buffer_state ( YY_BUFFER_STATE new_buffer, yyscan_t yyscanner );
-void yypop_buffer_state ( yyscan_t yyscanner );
-
-YY_BUFFER_STATE yy_scan_buffer ( char *base, yy_size_t size,
- yyscan_t yyscanner );
-YY_BUFFER_STATE yy_scan_string ( const char *yy_str, yyscan_t yyscanner );
-YY_BUFFER_STATE yy_scan_bytes ( const char *bytes, int len,
- yyscan_t yyscanner );
-
-void *yyalloc ( yy_size_t, yyscan_t yyscanner );
-void *yyrealloc ( void *, yy_size_t, yyscan_t yyscanner );
-void yyfree ( void *, yyscan_t yyscanner );
-
-/* Begin user sect3 */
-
-#define yywrap(yyscanner) (/*CONSTCOND*/ 1)
-#define YY_SKIP_YYWRAP
-
-#define yytext_ptr yytext_r
-
-#ifdef YY_HEADER_EXPORT_START_CONDITIONS
-#define INITIAL 0
-#define SC_COMMENT 1
-
-#endif
-
-#ifndef YY_NO_UNISTD_H
-/* Special case for "unistd.h", since it is non-ANSI. We include it way
- * down here because we want the user's section 1 to have been scanned first.
- * The user has a chance to override it with an option.
- */
-#include <unistd.h>
-#endif
-
-#ifndef YY_EXTRA_TYPE
-#define YY_EXTRA_TYPE void *
-#endif
-
-int yylex_init (yyscan_t* scanner);
-
-int yylex_init_extra ( YY_EXTRA_TYPE user_defined, yyscan_t* scanner);
-
-/* Accessor methods to globals.
- These are made visible to non-reentrant scanners for convenience. */
-
-int yylex_destroy ( yyscan_t yyscanner );
-
-int yyget_debug ( yyscan_t yyscanner );
-
-void yyset_debug ( int debug_flag, yyscan_t yyscanner );
-
-YY_EXTRA_TYPE yyget_extra ( yyscan_t yyscanner );
-
-void yyset_extra ( YY_EXTRA_TYPE user_defined, yyscan_t yyscanner );
-
-FILE *yyget_in ( yyscan_t yyscanner );
-
-void yyset_in ( FILE * _in_str, yyscan_t yyscanner );
-
-FILE *yyget_out ( yyscan_t yyscanner );
-
-void yyset_out ( FILE * _out_str, yyscan_t yyscanner );
-
-int yyget_leng ( yyscan_t yyscanner );
-
-char *yyget_text ( yyscan_t yyscanner );
-
-int yyget_lineno ( yyscan_t yyscanner );
-
-void yyset_lineno ( int _line_number, yyscan_t yyscanner );
-
-int yyget_column ( yyscan_t yyscanner );
-
-void yyset_column ( int _column_no, yyscan_t yyscanner );
-
-/* Macros after this point can all be overridden by user definitions in
- * section 1.
- */
-
-#ifndef YY_SKIP_YYWRAP
-#ifdef __cplusplus
-extern "C" int yywrap ( yyscan_t yyscanner );
-#else
-extern int yywrap ( yyscan_t yyscanner );
-#endif
-#endif
-
-#ifndef yytext_ptr
-static void yy_flex_strncpy ( char *, const char *, int, yyscan_t yyscanner);
-#endif
-
-#ifdef YY_NEED_STRLEN
-static int yy_flex_strlen ( const char *, yyscan_t yyscanner);
-#endif
-
-#ifndef YY_NO_INPUT
-
-#endif
-
-/* Amount of stuff to slurp up with each read. */
-#ifndef YY_READ_BUF_SIZE
-#ifdef __ia64__
-/* On IA-64, the buffer size is 16k, not 8k */
-#define YY_READ_BUF_SIZE 16384
-#else
-#define YY_READ_BUF_SIZE 8192
-#endif /* __ia64__ */
-#endif
-
-/* Number of entries by which start-condition stack grows. */
-#ifndef YY_START_STACK_INCR
-#define YY_START_STACK_INCR 25
-#endif
-
-/* Default declaration of generated scanner - a define so the user can
- * easily add parameters.
- */
-#ifndef YY_DECL
-#define YY_DECL_IS_OURS 1
-
-extern int yylex (yyscan_t yyscanner);
-
-#define YY_DECL int yylex (yyscan_t yyscanner)
-#endif /* !YY_DECL */
-
-/* yy_get_previous_state - get the state just before the EOB char was reached */
-
-#undef YY_NEW_FILE
-#undef YY_FLUSH_BUFFER
-#undef yy_set_bol
-#undef yy_new_buffer
-#undef yy_set_interactive
-#undef YY_DO_BEFORE_ACTION
-
-#ifdef YY_DECL_IS_OURS
-#undef YY_DECL_IS_OURS
-#undef YY_DECL
-#endif
-
-#ifndef yy_create_buffer_ALREADY_DEFINED
-#undef yy_create_buffer
-#endif
-#ifndef yy_delete_buffer_ALREADY_DEFINED
-#undef yy_delete_buffer
-#endif
-#ifndef yy_scan_buffer_ALREADY_DEFINED
-#undef yy_scan_buffer
-#endif
-#ifndef yy_scan_string_ALREADY_DEFINED
-#undef yy_scan_string
-#endif
-#ifndef yy_scan_bytes_ALREADY_DEFINED
-#undef yy_scan_bytes
-#endif
-#ifndef yy_init_buffer_ALREADY_DEFINED
-#undef yy_init_buffer
-#endif
-#ifndef yy_flush_buffer_ALREADY_DEFINED
-#undef yy_flush_buffer
-#endif
-#ifndef yy_load_buffer_state_ALREADY_DEFINED
-#undef yy_load_buffer_state
-#endif
-#ifndef yy_switch_to_buffer_ALREADY_DEFINED
-#undef yy_switch_to_buffer
-#endif
-#ifndef yypush_buffer_state_ALREADY_DEFINED
-#undef yypush_buffer_state
-#endif
-#ifndef yypop_buffer_state_ALREADY_DEFINED
-#undef yypop_buffer_state
-#endif
-#ifndef yyensure_buffer_stack_ALREADY_DEFINED
-#undef yyensure_buffer_stack
-#endif
-#ifndef yylex_ALREADY_DEFINED
-#undef yylex
-#endif
-#ifndef yyrestart_ALREADY_DEFINED
-#undef yyrestart
-#endif
-#ifndef yylex_init_ALREADY_DEFINED
-#undef yylex_init
-#endif
-#ifndef yylex_init_extra_ALREADY_DEFINED
-#undef yylex_init_extra
-#endif
-#ifndef yylex_destroy_ALREADY_DEFINED
-#undef yylex_destroy
-#endif
-#ifndef yyget_debug_ALREADY_DEFINED
-#undef yyget_debug
-#endif
-#ifndef yyset_debug_ALREADY_DEFINED
-#undef yyset_debug
-#endif
-#ifndef yyget_extra_ALREADY_DEFINED
-#undef yyget_extra
-#endif
-#ifndef yyset_extra_ALREADY_DEFINED
-#undef yyset_extra
-#endif
-#ifndef yyget_in_ALREADY_DEFINED
-#undef yyget_in
-#endif
-#ifndef yyset_in_ALREADY_DEFINED
-#undef yyset_in
-#endif
-#ifndef yyget_out_ALREADY_DEFINED
-#undef yyget_out
-#endif
-#ifndef yyset_out_ALREADY_DEFINED
-#undef yyset_out
-#endif
-#ifndef yyget_leng_ALREADY_DEFINED
-#undef yyget_leng
-#endif
-#ifndef yyget_text_ALREADY_DEFINED
-#undef yyget_text
-#endif
-#ifndef yyget_lineno_ALREADY_DEFINED
-#undef yyget_lineno
-#endif
-#ifndef yyset_lineno_ALREADY_DEFINED
-#undef yyset_lineno
-#endif
-#ifndef yyget_column_ALREADY_DEFINED
-#undef yyget_column
-#endif
-#ifndef yyset_column_ALREADY_DEFINED
-#undef yyset_column
-#endif
-#ifndef yywrap_ALREADY_DEFINED
-#undef yywrap
-#endif
-#ifndef yyget_lval_ALREADY_DEFINED
-#undef yyget_lval
-#endif
-#ifndef yyset_lval_ALREADY_DEFINED
-#undef yyset_lval
-#endif
-#ifndef yyget_lloc_ALREADY_DEFINED
-#undef yyget_lloc
-#endif
-#ifndef yyset_lloc_ALREADY_DEFINED
-#undef yyset_lloc
-#endif
-#ifndef yyalloc_ALREADY_DEFINED
-#undef yyalloc
-#endif
-#ifndef yyrealloc_ALREADY_DEFINED
-#undef yyrealloc
-#endif
-#ifndef yyfree_ALREADY_DEFINED
-#undef yyfree
-#endif
-#ifndef yytext_ALREADY_DEFINED
-#undef yytext
-#endif
-#ifndef yyleng_ALREADY_DEFINED
-#undef yyleng
-#endif
-#ifndef yyin_ALREADY_DEFINED
-#undef yyin
-#endif
-#ifndef yyout_ALREADY_DEFINED
-#undef yyout
-#endif
-#ifndef yy_flex_debug_ALREADY_DEFINED
-#undef yy_flex_debug
-#endif
-#ifndef yylineno_ALREADY_DEFINED
-#undef yylineno
-#endif
-#ifndef yytables_fload_ALREADY_DEFINED
-#undef yytables_fload
-#endif
-#ifndef yytables_destroy_ALREADY_DEFINED
-#undef yytables_destroy
-#endif
-#ifndef yyTABLES_NAME_ALREADY_DEFINED
-#undef yyTABLES_NAME
-#endif
-
-#line 212 "src/lexer.l"
-
-
-#line 492 "src/gen_lexer.h"
-#undef yyIN_HEADER
-#endif /* yyHEADER_H */
diff --git a/src/lexer.l b/src/lexer.l
index e7dad6a..ce0b269 100644
--- a/src/lexer.l
+++ b/src/lexer.l
@@ -60,6 +60,7 @@ STRING \"(\\.|[^"\\])*\"
\n {}
}
+"::" {return SCOPE;}
"(" {return LPAREN;}
")" {return RPAREN;}
"{" {return LBRACE;}
diff --git a/src/parser.y b/src/parser.y
index 665a6a0..4ad4d8b 100644
--- a/src/parser.y
+++ b/src/parser.y
@@ -108,6 +108,7 @@
%token RBRACKET "]"
%token AS "as"
%token DOT "."
+%token SCOPE "::"
%token FATARROW "=>"
/* precedence */
@@ -127,6 +128,7 @@
%left "as" "sizeof" "typeof"
%right "'" "!" "~"
%left "." "=>" "(" ")"
+%left "::"
/* why doesn't bison allow <*> for %nterm? would be so much easier */
%nterm <node> import binary_op unary_op arg arg_list decl_list call expr
@@ -252,6 +254,7 @@ expr: id { $$ = $1; }
| "(" var_init ")" { $$ = $2; }
| "sizeof" expr { $$ = gen_sizeof($2); }
| expr "as" type { $$ = gen_cast($1, $3); }
+ | id "::" type { $$ = gen_fetch($1, $3); }
| "as" type { $$ = gen_as($2); }
| embed { $$ = $1; }
| lambda { $$ = $1; }
@@ -553,7 +556,7 @@ type_template: "type" id "{" template_list "}" {
}
;
-enum_val: id { $$ = gen_val($1, gen_int(0)); }
+enum_val: id { $$ = gen_val($1, NULL); }
| id "=" expr { $$ = gen_val($1, $3); }
;
diff --git a/src/source.mk b/src/source.mk
index 5b3d2ae..4f707de 100644
--- a/src/source.mk
+++ b/src/source.mk
@@ -5,6 +5,6 @@ gen/gen_parser.c: src/parser.y
bison -Wcounterexamples -H -o $@ $<
gen/gen_lexer.c: src/lexer.l
- flex --header-file=src/gen_lexer.h -o $@ $<
+ flex --header-file=gen/gen_lexer.h -o $@ $<
include/cu/parser.h: gen/gen_lexer.c gen/gen_parser.c