diff options
author | Leo Tenenbaum <pommicket@gmail.com> | 2020-03-15 14:59:17 -0400 |
---|---|---|
committer | Leo Tenenbaum <pommicket@gmail.com> | 2020-03-15 14:59:17 -0400 |
commit | e093297dd5846e963868b62afe55f589d72384c0 (patch) | |
tree | 986dfcf4cf6ea5c0f3c94bcaa6da090339abe9ea | |
parent | 6bedd04d011eaadf9ec0dc865bb8f84127db7e75 (diff) |
#error, realized this can replace where
-rw-r--r-- | cgen.c | 4 | ||||
-rw-r--r-- | copy.c | 3 | ||||
-rw-r--r-- | decls_cgen.c | 2 | ||||
-rw-r--r-- | eval.c | 2 | ||||
-rw-r--r-- | main.c | 9 | ||||
-rw-r--r-- | parse.c | 43 | ||||
-rw-r--r-- | sdecls_cgen.c | 2 | ||||
-rw-r--r-- | test.toc | 34 | ||||
-rw-r--r-- | types.c | 17 | ||||
-rw-r--r-- | types.h | 23 |
10 files changed, 128 insertions, 11 deletions
@@ -1997,6 +1997,8 @@ static void cgen_stmt(CGenerator *g, Statement *s) { cgen_stmt(g, sub); } break; + case STMT_MESSAGE: + break; } } @@ -2051,6 +2053,8 @@ static void cgen_defs_stmt(CGenerator *g, Statement *s) { cgen_defs_stmt(g, sub); } break; + case STMT_MESSAGE: + break; } } @@ -441,6 +441,9 @@ static void copy_stmt(Copier *c, Statement *out, Statement *in) { case STMT_DECL: copy_decl(c, out->decl = allocr_malloc(c->allocr, sizeof *out->decl), in->decl); break; + case STMT_MESSAGE: + copy_expr(c, &out->message.text, &in->message.text); + break; } } diff --git a/decls_cgen.c b/decls_cgen.c index 844db46..b9f7a04 100644 --- a/decls_cgen.c +++ b/decls_cgen.c @@ -268,6 +268,8 @@ static void cgen_decls_stmt(CGenerator *g, Statement *s) { cgen_decls_stmt(g, sub); } break; + case STMT_MESSAGE: + break; } } @@ -1687,6 +1687,8 @@ static Status eval_stmt(Evaluator *ev, Statement *stmt) { } eval_exit_stmts(stmt->inc.stmts, last_reached); } break; + case STMT_MESSAGE: + break; } return true; } @@ -8,10 +8,8 @@ /* TODO: -fix foreign varargs -user-generated errors -#returns_code (struct body is a block, to be evaluated at compile time, which returns the actual statements) - - struct varargs +allow omission of trailing ; in foo ::= fn() {...} or foo ::= nms {...} or foo ::= struct { ... } +- just end expressions when you get to a closing brace unless there's an elif, etc. break continue switch @@ -24,11 +22,12 @@ switch to / add as an alternative: libffi X ::= newtype(int); or something don't allow while {3; 5} or for 0..10 { 3; 5 } (once break is added) any odd number of "s for a string -allow omission of trailing ; in foo ::= fn() {...} or foo ::= nms {...} or foo ::= struct { ... } consider- should #sizeof always take a Type? it would be more verbose, but we might not actually need #sizeof that much, given that we have new. it probably should, because #sizeof(x[0]) can't be evaluated at compile time if x is not a constant --- +#returns_code (struct body is a block, to be evaluated at compile time, which returns the actual statements) + - struct varargs macros */ @@ -2011,6 +2011,9 @@ static Status parse_expr(Parser *p, Expression *e, Token *end) { fn->where.end = t->token; return true; } + case DIRECT_ERROR: + case DIRECT_WARN: + case DIRECT_INFO: case DIRECT_EXPORT: case DIRECT_INCLUDE: case DIRECT_FORCE: @@ -2531,6 +2534,32 @@ static Status parse_stmt(Parser *p, Statement *s, bool *was_a_statement) { ++t->token; goto success; } break; + case DIRECT_ERROR: + case DIRECT_WARN: + case DIRECT_INFO: { + MessageKind kind; + if (t->token->direct == DIRECT_ERROR) { + kind = MESSAGE_ERROR; + } else if (t->token->direct == DIRECT_WARN) { + kind = MESSAGE_WARN; + } else { + kind = MESSAGE_INFO; + } + ++t->token; + s->kind = STMT_MESSAGE; + Message *m = &s->message; + m->kind = kind; + if (!parse_expr(p, &m->text, expr_find_end(p, 0))) { + tokr_skip_semicolon(t); + return false; + } + if (!token_is_kw(t->token, KW_SEMICOLON)) { + tokr_err(t, "Expected ; at end of statement."); + tokr_skip_semicolon(t); + return false; + } + goto success; + } default: break; } @@ -2909,6 +2938,20 @@ static void fprint_stmt(FILE *out, Statement *s) { fprintf(out, ";\n"); } break; + case STMT_MESSAGE: { + Message *m = &s->message; + switch (m->kind) { + case MESSAGE_ERROR: + fprintf(out, "#error "); + break; + case MESSAGE_WARN: + fprintf(out, "#warn "); + break; + case MESSAGE_INFO: + fprintf(out, "#info "); + break; + } + } break; } } diff --git a/sdecls_cgen.c b/sdecls_cgen.c index f186792..0445851 100644 --- a/sdecls_cgen.c +++ b/sdecls_cgen.c @@ -146,6 +146,8 @@ static void cgen_sdecls_stmt(CGenerator *g, Statement *s) { cgen_sdecls_stmt(g, sub); } break; + case STMT_MESSAGE: + break; } } @@ -1,9 +1,35 @@ printf ::= #foreign("printf","libc.so.6") fn(#C &"const char", #C ..) #C int; -main ::= fn() { - x := "hey %ld %ld %ld %ld %ld\n\0"; - printf(&x[0], 5, 3, 8, 9, 4); +// NOTE: this doesn't work (e.g. "%%%") +tprintf_valid ::= fn(fmt :: []char, nargs: int) bool { + if fmt[fmt.len-1] != '\0' { + return false; + } + count := 0; + for x, i := fmt { + if x == '%' { + if i == fmt.len-1 { + count += 1; + } elif fmt[i+1] != '%' { + count += 1; + } else { + count -= 1; + } + } + } + count == nargs +}; + + +tprintf ::= fn(fmt :: []char, args: ..) { + #if !tprintf_valid(fmt, args.len) { + #error "Invalid printf format"; + } + f := fmt; + printf(&f[0], args); }; -main();
\ No newline at end of file +main ::= fn() { + tprintf("%d %d%%\n", 3, 4); +}; @@ -3385,6 +3385,23 @@ static Status types_stmt(Typer *tr, Statement *s) { } } break; + case STMT_MESSAGE: { + Message *m = &s->message; + char *text = eval_expr_as_cstr(tr, &m->text, "message"); + if (!text) + return false; + switch (m->kind) { + case MESSAGE_INFO: + info_print(s->where, "%s", text); + break; + case MESSAGE_WARN: + warn_print(s->where, "%s", text); + break; + case MESSAGE_ERROR: + err_print(s->where, "%s", text); + return false; + } + } break; } s->flags |= STMT_TYPED; return true; @@ -248,11 +248,15 @@ typedef enum { DIRECT_INCLUDE, DIRECT_FORCE, DIRECT_IF, + DIRECT_ERROR, + DIRECT_WARN, + DIRECT_INFO, DIRECT_COUNT } Directive; static const char *directives[DIRECT_COUNT] = - {"C", "sizeof", "alignof", "export", "foreign", "builtin", "include", "force", "if"}; + {"C", "sizeof", "alignof", "export", "foreign", "builtin", "include", "force", "if", "error", "warn", + "info"}; typedef enum { KW_SEMICOLON, @@ -786,10 +790,12 @@ typedef struct Namespace { } c; } Namespace; + enum { EXPR_FOUND_TYPE = 0x01 }; + typedef U8 ExprFlags; typedef struct Expression { @@ -900,7 +906,8 @@ typedef enum { STMT_DECL, STMT_EXPR, STMT_RET, - STMT_INCLUDE + STMT_INCLUDE, + STMT_MESSAGE } StatementKind; enum { @@ -937,6 +944,17 @@ typedef union { IncludedFile *inc_file; } Include; +typedef enum { + MESSAGE_ERROR, + MESSAGE_WARN, + MESSAGE_INFO +} MessageKind; + +typedef struct { + MessageKind kind; + Expression text; +} Message; + enum { STMT_EXPR_NO_SEMICOLON = 0x01, STMT_INC_TO_NMS = 0x01, @@ -951,6 +969,7 @@ typedef struct Statement { Expression expr; Return ret; Include inc; + Message message; /* #error, #warn, #info */ }; } Statement; |