Demaybe operator ?

This commit is contained in:
Ginger Bill
2016-10-07 09:41:38 +01:00
parent f40482aa29
commit c5d20d2eef
7 changed files with 107 additions and 70 deletions

View File

@@ -129,6 +129,7 @@ AST_NODE_KIND(_ExprBegin, "", struct{}) \
AST_NODE_KIND(SelectorExpr, "selector expression", struct { Token token; AstNode *expr, *selector; }) \
AST_NODE_KIND(IndexExpr, "index expression", struct { AstNode *expr, *index; Token open, close; }) \
AST_NODE_KIND(DerefExpr, "dereference expression", struct { Token op; AstNode *expr; }) \
AST_NODE_KIND(DemaybeExpr, "demaybe expression", struct { Token op; AstNode *expr; }) \
AST_NODE_KIND(CallExpr, "call expression", struct { \
AstNode *proc; \
AstNodeArray args; \
@@ -398,6 +399,8 @@ Token ast_node_token(AstNode *node) {
return node->FieldValue.eq;
case AstNode_DerefExpr:
return node->DerefExpr.op;
case AstNode_DemaybeExpr:
return node->DemaybeExpr.op;
case AstNode_BadStmt:
return node->BadStmt.begin;
case AstNode_EmptyStmt:
@@ -597,6 +600,13 @@ AstNode *make_deref_expr(AstFile *f, AstNode *expr, Token op) {
return result;
}
AstNode *make_demaybe_expr(AstFile *f, AstNode *expr, Token op) {
AstNode *result = make_node(f, AstNode_DemaybeExpr);
result->DemaybeExpr.expr = expr;
result->DemaybeExpr.op = op;
return result;
}
AstNode *make_basic_lit(AstFile *f, Token basic_lit) {
AstNode *result = make_node(f, AstNode_BasicLit);
@@ -1453,7 +1463,8 @@ AstNode *parse_call_expr(AstFile *f, AstNode *operand) {
next_token(f);
}
gb_array_append(args, parse_expr(f, false));
AstNode *arg = parse_expr(f, false);
gb_array_append(args, arg);
if (f->curr_token.kind != Token_Comma) {
if (f->curr_token.kind == Token_CloseParen)
@@ -1564,6 +1575,10 @@ AstNode *parse_atom_expr(AstFile *f, b32 lhs) {
operand = make_deref_expr(f, operand, expect_token(f, Token_Pointer));
break;
case Token_Maybe: // Demaybe
operand = make_demaybe_expr(f, operand, expect_token(f, Token_Maybe));
break;
case Token_OpenBrace: {
if (!lhs && is_literal_type(operand) && f->expr_level >= 0) {
if (f->curr_token.pos.line == f->prev_token.pos.line) {
@@ -2715,12 +2730,12 @@ AstNode *parse_stmt(AstFile *f) {
f->is_global_scope = true;
return make_empty_stmt(f, f->curr_token);
}
syntax_error(token, "You cannot use #shared_global_scope within a procedure. This must be done at the file scope.");
syntax_error(token, "You cannot use #shared_global_scope within a procedure. This must be done at the file scope");
return make_bad_decl(f, token, f->curr_token);
} else if (tag == "import") {
// TODO(bill): better error messages
Token import_name = {};
Token file_path = expect_token(f, Token_String);
Token file_path = expect_token_after(f, Token_String, "#import");
if (allow_token(f, Token_as)) {
// NOTE(bill): Custom import name
if (f->curr_token.kind == Token_Period) {
@@ -2728,14 +2743,19 @@ AstNode *parse_stmt(AstFile *f) {
import_name.kind = Token_Identifier;
next_token(f);
} else {
import_name = expect_token(f, Token_Identifier);
import_name = expect_token_after(f, Token_Identifier, "`as` for import declaration");
}
if (import_name.string == "_") {
syntax_error(token, "Illegal import name: `_`");
return make_bad_decl(f, token, f->curr_token);
}
}
if (f->curr_proc == NULL) {
return make_import_decl(f, s->TagStmt.token, file_path, import_name, false);
}
syntax_error(token, "You cannot use #import within a procedure. This must be done at the file scope.");
syntax_error(token, "You cannot use #import within a procedure. This must be done at the file scope");
return make_bad_decl(f, token, file_path);
} else if (tag == "load") {
// TODO(bill): better error messages
@@ -2746,14 +2766,14 @@ AstNode *parse_stmt(AstFile *f) {
if (f->curr_proc == NULL) {
return make_import_decl(f, s->TagStmt.token, file_path, import_name, true);
}
syntax_error(token, "You cannot use #load within a procedure. This must be done at the file scope.");
syntax_error(token, "You cannot use #load within a procedure. This must be done at the file scope");
return make_bad_decl(f, token, file_path);
} else if (tag == "foreign_system_library") {
Token file_path = expect_token(f, Token_String);
if (f->curr_proc == NULL) {
return make_foreign_system_library(f, s->TagStmt.token, file_path);
}
syntax_error(token, "You cannot use #foreign_system_library within a procedure. This must be done at the file scope.");
syntax_error(token, "You cannot use #foreign_system_library within a procedure. This must be done at the file scope");
return make_bad_decl(f, token, file_path);
} else if (tag == "thread_local") {
AstNode *var_decl = parse_simple_stmt(f);
@@ -2762,7 +2782,7 @@ AstNode *parse_stmt(AstFile *f) {
return make_bad_decl(f, token, ast_node_token(var_decl));
}
if (f->curr_proc != NULL) {
syntax_error(token, "#thread_local is only allowed at the file scope.");
syntax_error(token, "#thread_local is only allowed at the file scope");
return make_bad_decl(f, token, ast_node_token(var_decl));
}
var_decl->VarDecl.tags |= VarDeclTag_thread_local;
@@ -2783,12 +2803,12 @@ AstNode *parse_stmt(AstFile *f) {
return s;
}
s->TagStmt.stmt = parse_stmt(f); // TODO(bill): Find out why this doesn't work as an argument
return s;
} break;
case Token_OpenBrace: return parse_block_stmt(f);
case Token_OpenBrace:
return parse_block_stmt(f);
case Token_Semicolon:
s = make_empty_stmt(f, token);