summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2020-01-18 00:34:02 -0500
committerLeo Tenenbaum <pommicket@gmail.com>2020-01-18 00:34:02 -0500
commita66d9199eb6169265a103361b624fc1f8cb21364 (patch)
treeb7cbcf5fabef57a87564aa4c2d57e7a8be46ec0b
parent09a23bab279ac54b365e50e84962fdc2125114b9 (diff)
started #foreign
-rw-r--r--main.c2
-rw-r--r--parse.c19
-rw-r--r--test.toc4
-rw-r--r--tokenizer.c2
-rw-r--r--types.h7
5 files changed, 24 insertions, 10 deletions
diff --git a/main.c b/main.c
index a98fbb2..c3a5bb9 100644
--- a/main.c
+++ b/main.c
@@ -19,8 +19,8 @@
/*
TODO:
C functions (#foreign)
-#include
variadic fns
+#include
---
X ::= newtype(int); or something
don't allow while {3; 5} (once break is added)
diff --git a/parse.c b/parse.c
index 921a3b0..dd868a6 100644
--- a/parse.c
+++ b/parse.c
@@ -314,8 +314,8 @@ static Token *expr_find_end(Parser *p, ExprEndFlags flags) {
Token *token = t->token;
bool could_be_vbs = false; /* could this be a void block statement (whose semicolons can be omitted)? e.g. {x := 5;} */
while (1) {
+ bool all_levels_0 = paren_level == 0 && brace_level == 0 && square_level == 0;
if (token->kind == TOKEN_KW) {
- bool all_levels_0 = paren_level == 0 && brace_level == 0 && square_level == 0;
switch (token->kw) {
case KW_COMMA:
if ((flags & EXPR_CAN_END_WITH_COMMA) && all_levels_0)
@@ -853,8 +853,6 @@ static bool parse_fn_expr(Parser *p, FnExpr *f) {
} else {
if (!parse_decl_list(p, &f->params, DECL_END_RPAREN_COMMA))
return false;
- arr_foreach(f->params, Declaration, param)
- param->flags |= DECL_IS_PARAM;
}
if (t->token->kind == TOKEN_EOF) {
@@ -1681,6 +1679,7 @@ static bool parse_expr(Parser *p, Expression *e, Token *end) {
e->unary.op = UNARY_DALIGNOF;
single_arg = e->unary.of = parser_new_expr(p);
break;
+ case DIRECT_FOREIGN:
case DIRECT_EXPORT:
tokr_err(t, "Unrecognized expression.");
return false;
@@ -1831,7 +1830,17 @@ static bool parse_decl(Parser *p, Declaration *d, DeclEndKind ends_with, U16 fla
if (token_is_kw(t->token, KW_EQ)) {
++t->token;
- if ((flags & PARSE_DECL_ALLOW_INFER) && ends_decl(t->token, ends_with)) {
+ if (token_is_direct(t->token, DIRECT_FOREIGN)) {
+ d->flags |= DECL_FOREIGN;
+ ++t->token;
+ /* TODO: foreign name */
+ if (!ends_decl(t->token, ends_with)) {
+ tokr_err(t, "Expected declaration to stop after #foreign, but it continues.");
+ goto ret_false;
+ }
+ ++t->token;
+
+ } else if ((flags & PARSE_DECL_ALLOW_INFER) && ends_decl(t->token, ends_with)) {
/* inferred expression */
d->flags |= DECL_INFER;
if (arr_len(d->idents) > 1) {
@@ -1875,7 +1884,7 @@ static bool parse_decl(Parser *p, Declaration *d, DeclEndKind ends_with, U16 fla
}
}
- if ((d->flags & DECL_IS_CONST) && !(d->flags & DECL_HAS_EXPR) && !(flags & PARSE_DECL_ALLOW_CONST_WITH_NO_EXPR)) {
+ if ((d->flags & DECL_IS_CONST) && !(d->flags & (DECL_HAS_EXPR | DECL_FOREIGN)) && !(flags & PARSE_DECL_ALLOW_CONST_WITH_NO_EXPR)) {
--t->token;
/* disallowed constant without an expression, e.g. x :: int; */
tokr_err(t, "You must have an expression at the end of this constant declaration.");
diff --git a/test.toc b/test.toc
index d7654e3..aa12b62 100644
--- a/test.toc
+++ b/test.toc
@@ -5,6 +5,10 @@ import ::= fn(x :: []char) &Package {
p_ptr
};
+// n should be size_t
+memcpy :: fn (&u8, &u8, u64) = #foreign;
+
+
main ::= fn() {
io ::= import("std/io");
io.puts("Hello, world!");
diff --git a/tokenizer.c b/tokenizer.c
index 8aece94..1ca3b3b 100644
--- a/tokenizer.c
+++ b/tokenizer.c
@@ -20,7 +20,7 @@ static const char *const keywords[KW_COUNT] =
static inline const char *kw_to_str(Keyword k) { return keywords[k]; }
static const char *directives[DIRECT_COUNT] =
- {"C", "sizeof", "alignof", "export"};
+ {"C", "sizeof", "alignof", "export", "foreign"};
/* Returns KW_COUNT if it's not a keyword */
/* OPTIM: don't use strncmp so much */
diff --git a/types.h b/types.h
index 6fb68c2..f3adcee 100644
--- a/types.h
+++ b/types.h
@@ -205,6 +205,7 @@ typedef enum {
DIRECT_SIZEOF,
DIRECT_ALIGNOF,
DIRECT_EXPORT,
+ DIRECT_FOREIGN,
DIRECT_COUNT
} Directive;
@@ -696,9 +697,9 @@ enum {
DECL_FOUND_TYPE = 0x0010,
DECL_ERRORED_ABOUT_SELF_REFERENCE = 0x0020, /* has there been an error about this decl referencing itself? */
DECL_FOUND_VAL = 0x0040,
- DECL_IS_PARAM = 0x0080,
- DECL_INFER = 0x0100, /* infer the value (e.g. fn(t::Type=, x:t)) */
- DECL_EXPORT = 0x0200
+ DECL_INFER = 0x0080, /* infer the value (e.g. fn(t::Type=, x:t)) */
+ DECL_EXPORT = 0x0100,
+ DECL_FOREIGN = 0x0200
};
typedef U16 DeclFlags;