mirror of
https://github.com/Ed94/Odin.git
synced 2026-07-17 00:11:25 -07:00
Infix and Postfix procedure calls
This commit is contained in:
+17
-2
@@ -1386,7 +1386,6 @@ Entity *lookup_field(Type *type, AstNode *field_node, isize *index = NULL) {
|
||||
}
|
||||
}
|
||||
break;
|
||||
break;
|
||||
// TODO(bill): Other types and extra "hidden" fields (e.g. introspection stuff)
|
||||
// TODO(bill): Allow for access of field through index? e.g. `x.3` will get member of index 3
|
||||
// Or is this only suitable if tuples are first-class?
|
||||
@@ -1402,7 +1401,14 @@ void check_selector(Checker *c, Operand *operand, AstNode *node) {
|
||||
AstNode *op_expr = se->expr;
|
||||
AstNode *selector = se->selector;
|
||||
if (selector) {
|
||||
Entity *entity = lookup_field(operand->type, selector);
|
||||
Entity *entity = NULL;
|
||||
if (is_type_enum(operand->type)) {
|
||||
if (operand->mode == Addressing_Type) {
|
||||
entity = lookup_field(operand->type, selector);
|
||||
}
|
||||
} else {
|
||||
entity = lookup_field(operand->type, selector);
|
||||
}
|
||||
if (entity == NULL) {
|
||||
gbString op_str = expr_to_string(op_expr);
|
||||
gbString sel_str = expr_to_string(selector);
|
||||
@@ -2631,6 +2637,15 @@ gbString write_expr_to_string(gbString str, AstNode *node) {
|
||||
str = gb_string_appendc(str, "}");
|
||||
case_end;
|
||||
|
||||
case_ast_node(et, EnumType, node);
|
||||
str = gb_string_appendc(str, "enum ");
|
||||
if (et->base_type != NULL) {
|
||||
str = write_expr_to_string(str, et->base_type);
|
||||
str = gb_string_appendc(str, " ");
|
||||
}
|
||||
str = gb_string_appendc(str, "{");
|
||||
str = gb_string_appendc(str, "}");
|
||||
case_end;
|
||||
}
|
||||
|
||||
return str;
|
||||
|
||||
+26
-3
@@ -81,6 +81,12 @@ enum VarDeclTag {
|
||||
VarDeclTag_thread_local = GB_BIT(0),
|
||||
};
|
||||
|
||||
enum CallExprKind {
|
||||
CallExpr_Normal,
|
||||
CallExpr_UnaryOp,
|
||||
CallExpr_BinaryOp,
|
||||
};
|
||||
|
||||
#define AST_NODE_KINDS \
|
||||
AST_NODE_KIND(Invalid, struct{}) \
|
||||
AST_NODE_KIND(BasicLit, Token) \
|
||||
@@ -112,6 +118,7 @@ AST_NODE_KIND(_ExprBegin, struct{}) \
|
||||
AstNode *proc, *arg_list; \
|
||||
isize arg_list_count; \
|
||||
Token open, close; \
|
||||
CallExprKind kind; \
|
||||
}) \
|
||||
AST_NODE_KIND(SliceExpr, struct { \
|
||||
AstNode *expr; \
|
||||
@@ -1186,6 +1193,16 @@ AstNode *parse_atom_expr(AstFile *f, b32 lhs) {
|
||||
b32 loop = true;
|
||||
while (loop) {
|
||||
switch (f->cursor[0].kind) {
|
||||
|
||||
case Token_CustomUnaryOp: {
|
||||
Token op = expect_token(f, Token_CustomUnaryOp);
|
||||
if (lhs) {
|
||||
// TODO(bill): Handle this
|
||||
}
|
||||
AstNode *proc = make_ident(f, op);
|
||||
operand = make_call_expr(f, proc, operand, 1, ast_node_token(operand), op);
|
||||
} break;
|
||||
|
||||
case Token_OpenParen: {
|
||||
if (lhs) {
|
||||
// TODO(bill): Handle this shit! Is this even allowed in this language?!
|
||||
@@ -1354,8 +1371,14 @@ AstNode *parse_binary_expr(AstFile *f, b32 lhs, i32 prec_in) {
|
||||
ast_file_err(f, op, "Expected expression on the right hand side of the binary operator");
|
||||
}
|
||||
}
|
||||
expression = make_binary_expr(f, op, expression, right);
|
||||
|
||||
if (op.kind == Token_CustomBinaryOp) {
|
||||
AstNode *proc = make_ident(f, op);
|
||||
expression->next = right;
|
||||
expression = make_call_expr(f, proc, expression, 2, ast_node_token(expression), ast_node_token(right));
|
||||
} else {
|
||||
expression = make_binary_expr(f, op, expression, right);
|
||||
}
|
||||
}
|
||||
}
|
||||
return expression;
|
||||
@@ -1638,7 +1661,7 @@ AstNode *parse_identifier_or_type(AstFile *f) {
|
||||
Token token = expect_token(f, Token_enum);
|
||||
AstNode *base_type = NULL;
|
||||
Token open, close;
|
||||
|
||||
|
||||
if (f->cursor[0].kind != Token_OpenBrace) {
|
||||
base_type = parse_type(f);
|
||||
}
|
||||
@@ -1669,7 +1692,7 @@ AstNode *parse_identifier_or_type(AstFile *f) {
|
||||
close = expect_token(f, Token_CloseBrace);
|
||||
|
||||
return make_enum_type(f, token, base_type, root, field_count);
|
||||
}
|
||||
}
|
||||
|
||||
case Token_proc:
|
||||
return parse_proc_type(f, NULL);
|
||||
|
||||
+5
-5
@@ -82,7 +82,7 @@ b32 string_contains_char(String s, u8 c) {
|
||||
|
||||
b32 unquote_char(String s, u8 quote, Rune *rune, b32 *multiple_bytes, String *tail_string) {
|
||||
if (s.text[0] == quote &&
|
||||
(quote == '\'' || quote == '"')) {
|
||||
(quote == '$' || quote == '"')) {
|
||||
return false;
|
||||
} else if (s.text[0] >= 0x80) {
|
||||
Rune r = -1;
|
||||
@@ -116,7 +116,7 @@ b32 unquote_char(String s, u8 quote, Rune *rune, b32 *multiple_bytes, String *ta
|
||||
case '\\': *rune = '\\'; break;
|
||||
|
||||
|
||||
case '\'':
|
||||
case '$':
|
||||
case '"':
|
||||
if (c != quote) {
|
||||
return false;
|
||||
@@ -210,7 +210,7 @@ i32 unquote_string(gbAllocator a, String *s_) {
|
||||
*s_ = s;
|
||||
return 1;
|
||||
}
|
||||
if (quote != '"' && quote != '\'')
|
||||
if (quote != '"' && quote != '$')
|
||||
return 0;
|
||||
|
||||
if (string_contains_char(s, '\n'))
|
||||
@@ -220,7 +220,7 @@ i32 unquote_string(gbAllocator a, String *s_) {
|
||||
if (quote == '"') {
|
||||
*s_ = s;
|
||||
return 1;
|
||||
} else if (quote == '\'') {
|
||||
} else if (quote == '$') {
|
||||
Rune r = GB_RUNE_INVALID;
|
||||
isize size = gb_utf8_decode(s.text, s.len, &r);
|
||||
if ((size == s.len) && (r != -1 || size != 1)) {
|
||||
@@ -254,7 +254,7 @@ i32 unquote_string(gbAllocator a, String *s_) {
|
||||
offset += size;
|
||||
}
|
||||
|
||||
if (quote == '\'' && s.len != 0) {
|
||||
if (quote == '$' && s.len != 0) {
|
||||
gb_free(a, buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
+30
-4
@@ -30,6 +30,9 @@ TOKEN_KIND(Token__OperatorBegin, "_OperatorBegin"), \
|
||||
\
|
||||
TOKEN_KIND(Token_as, "as"), \
|
||||
TOKEN_KIND(Token_transmute, "transmute"), \
|
||||
\
|
||||
TOKEN_KIND(Token_CustomUnaryOp, "custom unary op"), \
|
||||
TOKEN_KIND(Token_CustomBinaryOp, "custom binary op"), \
|
||||
\
|
||||
TOKEN_KIND(Token__AssignOpBegin, "_AssignOpBegin"), \
|
||||
TOKEN_KIND(Token_AddEq, "+="), \
|
||||
@@ -199,9 +202,11 @@ i32 token_precedence(Token t) {
|
||||
case Token_Shl:
|
||||
case Token_Shr:
|
||||
return 5;
|
||||
case Token_CustomBinaryOp:
|
||||
return 6;
|
||||
case Token_as:
|
||||
case Token_transmute:
|
||||
return 6;
|
||||
return 7;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -642,6 +647,27 @@ Token tokenizer_get_token(Tokenizer *t) {
|
||||
token.kind = Token_EOF;
|
||||
break;
|
||||
|
||||
case '\'': {
|
||||
token.kind = Token_CustomUnaryOp;
|
||||
while (rune_is_whitespace(t->curr_rune))
|
||||
advance_to_next_rune(t);
|
||||
token.string.text = t->curr;
|
||||
while (rune_is_letter(t->curr_rune) || rune_is_digit(t->curr_rune)) {
|
||||
advance_to_next_rune(t);
|
||||
}
|
||||
token.string.len = t->curr - token.string.text;
|
||||
|
||||
while (rune_is_whitespace(t->curr_rune))
|
||||
advance_to_next_rune(t);
|
||||
|
||||
if (t->curr_rune == '\'') {
|
||||
advance_to_next_rune(t);
|
||||
token.kind = Token_CustomBinaryOp;
|
||||
}
|
||||
|
||||
return token;
|
||||
} break;
|
||||
|
||||
case '`': // Raw String Literal
|
||||
case '"': // String Literal
|
||||
{
|
||||
@@ -684,7 +710,7 @@ Token tokenizer_get_token(Tokenizer *t) {
|
||||
}
|
||||
} break;
|
||||
|
||||
case '\'': { // Rune Literal
|
||||
case '$': { // Rune Literal
|
||||
b32 valid = true;
|
||||
isize len = 0;
|
||||
token.kind = Token_Rune;
|
||||
@@ -696,11 +722,11 @@ Token tokenizer_get_token(Tokenizer *t) {
|
||||
break;
|
||||
}
|
||||
advance_to_next_rune(t);
|
||||
if (r == '\'')
|
||||
if (r == '$')
|
||||
break;
|
||||
len++;
|
||||
if (r == '\\') {
|
||||
if (!scan_escape(t, '\''))
|
||||
if (!scan_escape(t, '$'))
|
||||
valid = false;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user