aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/ek/ast.h12
-rw-r--r--src/ast.c1
-rw-r--r--src/parser.y62
-rw-r--r--tests/parse/struct_cont.ek3
4 files changed, 65 insertions, 13 deletions
diff --git a/include/ek/ast.h b/include/ek/ast.h
index 62a0901..59101ba 100644
--- a/include/ek/ast.h
+++ b/include/ek/ast.h
@@ -79,6 +79,8 @@ enum ast_kind {
AST_TRAIT_DEF,
/** Structure definition. */
AST_STRUCT_DEF,
+ /** Structure continuation, kind of like impl in Rust. */
+ AST_STRUCT_CONT_DEF,
/** If. */
AST_IF,
/** Block. E.g. \c {} */
@@ -372,7 +374,8 @@ static inline bool is_primitive(struct type *t)
#define gen_type(k, a, type, loc) gen_ast(k, a, NULL, NULL, NULL, type, NULL, \
-1, \
loc)
-#define gen_str2(k, s, a, b, loc) gen_ast(k, a, b, NULL, NULL, NULL, s, -1, loc)
+#define gen_str3(k, s, a, b, c, loc) gen_ast(k, a, b, c, NULL, NULL, s, -1, loc)
+#define gen_str2(k, s, a, b, loc) gen_str3(k, s, a, b, NULL, loc)
#define gen_str1(k, s, a, loc) gen_str2(k, s, a, NULL, loc)
#define gen_str(k, s, loc) gen_ast(k, NULL, NULL, NULL, NULL, NULL, s, -1, loc)
@@ -568,6 +571,13 @@ static inline bool is_primitive(struct type *t)
#define gen_struct(id, params, body, loc) \
gen_str2(AST_STRUCT_DEF, id, params, body, loc)
+#define struct_cont_id(x) return_s(x, AST_STRUCT_CONT_DEF)
+#define struct_cont_params(x) return_a0(x, AST_STRUCT_CONT_DEF)
+#define struct_cont_behav(x) return_t1(x, AST_STRUCT_CONT_DEF)
+#define struct_cont_body(x) return_a2(x, AST_STRUCT_CONT_DEF)
+#define gen_struct_cont(id, params, behav, body, loc) \
+ gen_ast(AST_STRUCT_CONT_DEF, params, body, NULL, NULL, behav, id, 0, loc)
+
#define val_id(x) return_s(x, AST_VAL)
#define val_val(x) return_a0(x, AST_VAL)
#define gen_val(id, val, loc) \
diff --git a/src/ast.c b/src/ast.c
index 6b3b28d..d734252 100644
--- a/src/ast.c
+++ b/src/ast.c
@@ -244,6 +244,7 @@ void ast_dump(int depth, struct ast *n)
DUMP(AST_ALIAS_DEF);
DUMP(AST_TRAIT_DEF);
DUMP(AST_STRUCT_DEF);
+ DUMP(AST_STRUCT_CONT_DEF);
DUMP(AST_IF);
DUMP(AST_BLOCK);
DUMP(AST_IMPORT);
diff --git a/src/parser.y b/src/parser.y
index 6c567a9..06599f2 100644
--- a/src/parser.y
+++ b/src/parser.y
@@ -140,7 +140,7 @@
%nterm <type> types type opt_type
-%nterm <node> tagged_struct expr_if
+%nterm <node> struct struct_cont expr_if
/* constant operations */
%nterm <node> const_expr const_unop const_binop
@@ -155,6 +155,7 @@
/* optional stuff */
%nterm <node> opt_exprs proc_decl member opt_members
%nterm <type> opt_types opt_sign_decls sign_decls sign_decl sign_var_decl
+%nterm <node> opt_behaviours behaviours behaviour
/* reverse lists */
%nterm <type> rev_sign_decls;
@@ -250,8 +251,7 @@ id
: ID {$$ = gen_id($1, src_loc(@$));}
var
- : var_decl
- | var_init
+ : var_init
embed
: "embed" "(" STRING ")" { $$ = gen_embed(strip($3), src_loc(@$)); }
@@ -476,7 +476,8 @@ statement
| while
| do_while
| body
- | tagged_struct
+ | struct
+ | struct_cont
| for
| defer
| if
@@ -731,11 +732,14 @@ proc
ast_set_flags($$, AST_FLAG_EXTERN | AST_FLAG_NOMANGLE);
}
-member
- : var_decl ";"
- | type_expand ";"
+behaviour
+ : type_expand ";"
| proc_decl ";"
| proc
+
+member
+ : var_decl ";"
+ | behaviour
;
members
@@ -746,12 +750,23 @@ opt_members
: members
| {$$ = NULL;}
+behaviours
+ : behaviours behaviour {
+ $$ = $1; $1->n = $2;
+ ast_set_flags($$, AST_FLAG_MEMBER);
+ }
+ | behaviour { $$ = $1; ast_set_flags($$, AST_FLAG_MEMBER); }
+
+opt_behaviours
+ : behaviours
+ | {$$ = NULL;}
+
macro_expand
: APPLY "(" opt_exprs ")" {
$$ = gen_macro_expand($1, $3, src_loc(@$));
}
-tagged_struct
+struct
: "typedef" ID "[" opt_type_params "]" "{" opt_members "}" {
$$ = gen_struct($2, $4, $7, src_loc(@$));
}
@@ -759,6 +774,25 @@ tagged_struct
$$ = gen_struct($2, NULL, $4, src_loc(@$));
}
+struct_cont
+ : "continue" "[" opt_type_params "]"
+ APPLY "[" opt_types "]" "{" opt_behaviours "}" {
+ /* full form */
+ $$ = gen_struct_cont($5, $3, $7, $10, src_loc(@$));
+ }
+ | "continue" "[" opt_type_params "]" ID "{" opt_behaviours "}" {
+ /* abbrev 1 */
+ $$ = gen_struct_cont($5, $3, NULL, $7, src_loc(@$));
+ }
+ | "continue" APPLY "[" opt_types "]" "{" opt_behaviours "}" {
+ /* abbrev 2 */
+ $$ = gen_struct_cont($2, NULL, $4, $7, src_loc(@$));
+ }
+ | "continue" ID "{" opt_behaviours "}" {
+ /* abbrev 3 */
+ $$ = gen_struct_cont($2, NULL, NULL, $4, src_loc(@$));
+ }
+
alias
: "typedef" ID type {
$$ = gen_alias($2, $3, src_loc(@$));
@@ -771,7 +805,9 @@ type_param
}
type_params
- : type_param "," type_params { $$ = $1; $1->n = $3; }
+ : type_param "," type_params {
+ $$ = $1; $1->n = $3; /** @todo this could be left recursive */
+ }
| type_param
opt_type_params
@@ -779,7 +815,7 @@ opt_type_params
| { $$ = NULL; }
trait
- : "define" ID "[" opt_type_params "]" "{" opt_members "}" {
+ : "define" ID "[" opt_type_params "]" "{" opt_behaviours "}" {
$$ = gen_trait($2, $4, $7, src_loc(@$));
}
@@ -824,14 +860,16 @@ top_if
top
: enum
| proc
- | tagged_struct
+ | struct
+ | struct_cont { $$ = $1; }
| macro { $$ = $1; }
| top_if { $$ = $1; ast_set_flags($$, AST_FLAG_CONST); }
| import { $$ = $1; }
| alias { $$ = $1; }
| trait { $$ = $1; }
| "pub" enum { $$ = $2; ast_set_flags($2, AST_FLAG_PUBLIC); }
- | "pub" tagged_struct { $$ = $2; ast_set_flags($2, AST_FLAG_PUBLIC); }
+ | "pub" struct { $$ = $2; ast_set_flags($2, AST_FLAG_PUBLIC); }
+ | "pub" struct_cont { $$ = $2; ast_set_flags($2, AST_FLAG_PUBLIC); }
| "pub" proc { $$ = $2; ast_set_flags($2, AST_FLAG_PUBLIC); }
| "pub" macro { $$ = $2; ast_set_flags($2, AST_FLAG_PUBLIC); }
| "pub" import { $$ = $2; ast_set_flags($2, AST_FLAG_PUBLIC); }
diff --git a/tests/parse/struct_cont.ek b/tests/parse/struct_cont.ek
new file mode 100644
index 0000000..f4799aa
--- /dev/null
+++ b/tests/parse/struct_cont.ek
@@ -0,0 +1,3 @@
+typedef i27 {}
+continue i27 {
+}