mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Foreach overload is now done using attributes (@operator(elementat), @operator(elementref) and @operator(len)) rather than reserved functions.
This commit is contained in:
@@ -99,7 +99,7 @@ fn bool List.isEmpty(List *list)
|
||||
return list.size;
|
||||
}
|
||||
|
||||
fn usize List.len(List *list)
|
||||
fn usize List.len(List *list) @operator(len)
|
||||
{
|
||||
return list.size;
|
||||
}
|
||||
@@ -116,12 +116,13 @@ fn void List.free(List *list)
|
||||
list.size = 0;
|
||||
}
|
||||
|
||||
macro usize List.operator_len(List &list)
|
||||
{
|
||||
return list.len();
|
||||
}
|
||||
|
||||
macro Type List.operator_element_at(List &list, usize index)
|
||||
macro Type List.item_at(List &list, usize index) @operator(elementat)
|
||||
{
|
||||
return list.entries[index];
|
||||
}
|
||||
|
||||
macro Type* List.item_ref(List &list, usize index) @operator(elementref)
|
||||
{
|
||||
return &list.entries[index];
|
||||
}
|
||||
|
||||
@@ -313,6 +313,7 @@ typedef struct
|
||||
{
|
||||
Expr *expr;
|
||||
uint32_t alignment;
|
||||
OperatorOverload operator;
|
||||
};
|
||||
} Attr;
|
||||
|
||||
@@ -588,6 +589,7 @@ typedef struct Decl_
|
||||
bool escaping : 1;
|
||||
bool is_value : 1;
|
||||
bool is_autoimport : 1;
|
||||
OperatorOverload operator : 3;
|
||||
union
|
||||
{
|
||||
void *backend_ref;
|
||||
@@ -1607,10 +1609,9 @@ extern const char *kw_distinct;
|
||||
extern const char *kw_ensure;
|
||||
extern const char *kw_inline;
|
||||
extern const char *kw_inf;
|
||||
extern const char *kw_iterator;
|
||||
extern const char *kw_operator_element_at;
|
||||
extern const char *kw_operator_element_at_ref;
|
||||
extern const char *kw_operator_len;
|
||||
extern const char *kw_elementat;
|
||||
extern const char *kw_elementref;
|
||||
extern const char *kw_elementset;
|
||||
extern const char *kw_len;
|
||||
extern const char *kw_next;
|
||||
extern const char *kw_nan;
|
||||
|
||||
@@ -123,6 +123,7 @@ bool context_set_module(ParseContext *context, Path *path, TokenId *generic_para
|
||||
|
||||
void unit_register_external_symbol(CompilationUnit *unit, Decl *decl)
|
||||
{
|
||||
if (decl->decl_kind == DECL_MACRO) return;
|
||||
assert(decl->external_name && "Missing external name");
|
||||
Decl *prev = stable_get(&unit->external_symbols, decl->external_name);
|
||||
if (prev) return;
|
||||
|
||||
@@ -637,6 +637,14 @@ typedef enum
|
||||
ATTR_MACRO = 1 << 13,
|
||||
} AttributeDomain;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
OVERLOAD_ELEMENT_AT = 1,
|
||||
OVERLOAD_ELEMENT_REF,
|
||||
OVERLOAT_ELEMENT_SET,
|
||||
OVERLOAD_LEN
|
||||
} OperatorOverload;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ATTRIBUTE_INLINE,
|
||||
@@ -661,6 +669,7 @@ typedef enum
|
||||
ATTRIBUTE_FASTCALL,
|
||||
ATTRIBUTE_OVERLAP,
|
||||
ATTRIBUTE_AUTOIMPORT,
|
||||
ATTRIBUTE_OPERATOR,
|
||||
ATTRIBUTE_NONE,
|
||||
NUMBER_OF_ATTRIBUTES = ATTRIBUTE_NONE,
|
||||
} AttributeType;
|
||||
|
||||
@@ -942,34 +942,47 @@ static bool sema_analyse_operator_common(Decl *method, TypeInfo **rtype_ptr, Dec
|
||||
return true;
|
||||
}
|
||||
|
||||
Decl *sema_find_operator(SemaContext *context, Expr *expr, const char *kw)
|
||||
|
||||
Decl *sema_find_operator(SemaContext *context, Expr *expr, OperatorOverload operator_overload)
|
||||
{
|
||||
Decl *ambiguous = NULL;
|
||||
Decl *private = NULL;
|
||||
Type *type = expr->type->canonical;
|
||||
Decl *method = type_may_have_sub_elements(type) ? sema_resolve_method(context->unit, type->decl, kw, &ambiguous, &private) : NULL;
|
||||
if (!decl_ok(method)) return NULL;
|
||||
if (!method)
|
||||
if (!type_may_have_sub_elements(type)) return NULL;
|
||||
Decl *def = type->decl;
|
||||
Decl **funcs = def->methods;
|
||||
VECEACH(funcs, i)
|
||||
{
|
||||
if (ambiguous)
|
||||
Decl *func = funcs[i];
|
||||
if (func->operator == operator_overload)
|
||||
{
|
||||
SEMA_ERROR(expr,
|
||||
"It's not possible to find a definition for '%s' on %s that is not ambiguous.",
|
||||
kw, type_quoted_error_string(expr->type));
|
||||
return NULL;
|
||||
unit_register_external_symbol(context->compilation_unit, func);
|
||||
return func;
|
||||
}
|
||||
if (private)
|
||||
{
|
||||
SEMA_ERROR(expr,
|
||||
"It's not possible to find a public definition for '%s' with '%s'.",
|
||||
kw, type_quoted_error_string(expr->type));
|
||||
return NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
return method;
|
||||
Decl **imports = context->unit->imports;
|
||||
VECEACH(imports, i)
|
||||
{
|
||||
Decl *import = imports[i];
|
||||
Module *module = import->module;
|
||||
|
||||
if (module->is_generic) continue;
|
||||
|
||||
Decl **extensions = module->method_extensions;
|
||||
VECEACH(extensions, j)
|
||||
{
|
||||
Decl *extension = extensions[j];
|
||||
if (extension->operator == operator_overload)
|
||||
{
|
||||
unit_register_external_symbol(context->compilation_unit, extension);
|
||||
return extension;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static inline bool sema_analyse_operator_element_at(Decl *method)
|
||||
{
|
||||
TypeInfo *rtype;
|
||||
@@ -983,6 +996,19 @@ static inline bool sema_analyse_operator_element_at(Decl *method)
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool sema_analyse_operator_element_set(Decl *method)
|
||||
{
|
||||
TypeInfo *rtype;
|
||||
Decl **params;
|
||||
if (!sema_analyse_operator_common(method, &rtype, ¶ms, 3)) return false;
|
||||
if (rtype->type->canonical != type_void)
|
||||
{
|
||||
SEMA_ERROR(rtype, "The return type should be 'void'.");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool sema_analyse_operator_len(Decl *method)
|
||||
{
|
||||
TypeInfo *rtype;
|
||||
@@ -998,15 +1024,18 @@ static inline bool sema_analyse_operator_len(Decl *method)
|
||||
|
||||
static bool sema_check_operator_method_validity(Decl *method)
|
||||
{
|
||||
if (method->name == kw_operator_element_at || method->name == kw_operator_element_at_ref)
|
||||
switch (method->operator)
|
||||
{
|
||||
return sema_analyse_operator_element_at(method);
|
||||
case OVERLOAT_ELEMENT_SET:
|
||||
return sema_analyse_operator_element_set(method);
|
||||
case OVERLOAD_ELEMENT_AT:
|
||||
case OVERLOAD_ELEMENT_REF:
|
||||
return sema_analyse_operator_element_at(method);
|
||||
case OVERLOAD_LEN:
|
||||
return sema_analyse_operator_len(method);
|
||||
default:
|
||||
UNREACHABLE
|
||||
}
|
||||
if (method->name == kw_operator_len)
|
||||
{
|
||||
return sema_analyse_operator_len(method);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool unit_add_method_like(CompilationUnit *unit, Type *parent_type, Decl *method_like)
|
||||
@@ -1030,7 +1059,8 @@ static inline bool unit_add_method_like(CompilationUnit *unit, Type *parent_type
|
||||
SEMA_TOKID_PREV(method->name_token, "The previous definition was here.");
|
||||
return false;
|
||||
}
|
||||
if (!sema_check_operator_method_validity(method_like)) return false;
|
||||
if (method_like->operator && !sema_check_operator_method_validity(method_like)) return false;
|
||||
REMINDER("Check multiple operator");
|
||||
scratch_buffer_clear();
|
||||
if (method_like->visibility <= VISIBLE_MODULE)
|
||||
{
|
||||
@@ -1150,6 +1180,7 @@ AttributeType sema_analyse_attribute(SemaContext *context, Attr *attr, Attribute
|
||||
[ATTRIBUTE_NOSCOPE] = ATTR_MACRO,
|
||||
[ATTRIBUTE_ESCAPING] = ATTR_MACRO,
|
||||
[ATTRIBUTE_AUTOIMPORT] = ATTR_MACRO | ATTR_FUNC,
|
||||
[ATTRIBUTE_OPERATOR] = ATTR_MACRO | ATTR_FUNC,
|
||||
};
|
||||
|
||||
if ((attribute_domain[type] & domain) != domain)
|
||||
@@ -1165,6 +1196,38 @@ AttributeType sema_analyse_attribute(SemaContext *context, Attr *attr, Attribute
|
||||
case ATTRIBUTE_VECCALL:
|
||||
case ATTRIBUTE_REGCALL:
|
||||
return type;
|
||||
case ATTRIBUTE_OPERATOR:
|
||||
{
|
||||
Expr *expr = attr->expr;
|
||||
if (!expr || expr->expr_kind != EXPR_IDENTIFIER) goto FAILED_OP_TYPE;
|
||||
if (expr->identifier_expr.path) goto FAILED_OP_TYPE;
|
||||
TokenId tok = expr->identifier_expr.identifier;
|
||||
const char *kw = TOKSTR(tok);
|
||||
if (kw == kw_elementat)
|
||||
{
|
||||
attr->operator = OVERLOAD_ELEMENT_AT;
|
||||
}
|
||||
else if (kw == kw_elementref)
|
||||
{
|
||||
attr->operator = OVERLOAD_ELEMENT_REF;
|
||||
}
|
||||
else if (kw == kw_elementset)
|
||||
{
|
||||
attr->operator = OVERLOAT_ELEMENT_SET;
|
||||
}
|
||||
else if (kw == kw_len)
|
||||
{
|
||||
attr->operator = OVERLOAD_LEN;
|
||||
}
|
||||
else
|
||||
{
|
||||
goto FAILED_OP_TYPE;
|
||||
}
|
||||
return ATTRIBUTE_OPERATOR;
|
||||
FAILED_OP_TYPE:
|
||||
SEMA_ERROR(expr, "'operator' requires an operator type argument: '%s', '%s' or '%s'.", kw_elementat, kw_elementref, kw_len);
|
||||
return ATTRIBUTE_NONE;
|
||||
}
|
||||
case ATTRIBUTE_ALIGN:
|
||||
if (!attr->expr)
|
||||
{
|
||||
@@ -1389,6 +1452,7 @@ static inline bool sema_analyse_main_function(SemaContext *context, Decl *decl)
|
||||
context->unit->main_function = function;
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool sema_analyse_func(SemaContext *context, Decl *decl)
|
||||
{
|
||||
DEBUG_LOG("----Analysing function %s", decl->name);
|
||||
@@ -1406,6 +1470,10 @@ static inline bool sema_analyse_func(SemaContext *context, Decl *decl)
|
||||
|
||||
switch (attribute)
|
||||
{
|
||||
case ATTRIBUTE_OPERATOR:
|
||||
had = decl->operator > 0;
|
||||
decl->operator = attr->operator;
|
||||
break;
|
||||
case ATTRIBUTE_EXTNAME:
|
||||
had = decl->extname != NULL;
|
||||
decl->extname = attr->expr->const_expr.string.chars;
|
||||
@@ -1559,6 +1627,10 @@ static inline bool sema_analyse_macro(SemaContext *context, Decl *decl)
|
||||
bool had = false;
|
||||
switch (attribute)
|
||||
{
|
||||
case ATTRIBUTE_OPERATOR:
|
||||
had = decl->operator > 0;
|
||||
decl->operator = attr->operator;
|
||||
break;
|
||||
case ATTRIBUTE_NOSCOPE:
|
||||
had = decl->no_scope;
|
||||
decl->no_scope = true;
|
||||
|
||||
@@ -2572,14 +2572,14 @@ static inline bool sema_expr_analyse_subscript(SemaContext *context, Expr *expr,
|
||||
if (!inner_type)
|
||||
{
|
||||
Decl *decl = NULL;
|
||||
if (is_addr) decl = sema_find_operator(context, current_expr, kw_operator_element_at_ref);
|
||||
if (is_addr) decl = sema_find_operator(context, current_expr, OVERLOAD_ELEMENT_REF);
|
||||
if (!decl)
|
||||
{
|
||||
decl = sema_find_operator(context, current_expr, kw_operator_element_at);
|
||||
decl = sema_find_operator(context, current_expr, OVERLOAD_ELEMENT_AT);
|
||||
if (decl && is_addr)
|
||||
{
|
||||
SEMA_ERROR(expr, "'%s' is not defined for %s, so you need && to take the address of the temporary.",
|
||||
kw_operator_element_at_ref, type_quoted_error_string(current_expr->type));
|
||||
SEMA_ERROR(expr, "A function or macro with '@operator(%s)' is not defined for %s, so you need && to take the address of the temporary.",
|
||||
kw_elementref, type_quoted_error_string(current_expr->type));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ void sema_analysis_pass_decls(Module *module);
|
||||
void sema_analysis_pass_ct_assert(Module *module);
|
||||
void sema_analysis_pass_functions(Module *module);
|
||||
void sema_analyze_stage(Module *module, AnalysisStage stage);
|
||||
Decl *sema_find_operator(SemaContext *context, Expr *expr, const char *kw);
|
||||
Decl *sema_find_operator(SemaContext *context, Expr *expr, OperatorOverload operator_overload);
|
||||
bool sema_analyse_expr_lvalue(SemaContext *context, Expr *expr);
|
||||
bool sema_analyse_ct_expr(SemaContext *context, Expr *expr);
|
||||
bool sema_expr_analyse_macro_call(SemaContext *context, Expr *call_expr, Expr *struct_var, Decl *decl, bool failable);
|
||||
|
||||
@@ -890,158 +890,22 @@ static inline bool sema_analyse_for_stmt(SemaContext *context, Ast *statement)
|
||||
}
|
||||
|
||||
|
||||
static inline bool sema_inline_default_iterator(SemaContext *context, Expr *expr, Decl *decl)
|
||||
{
|
||||
Expr *inner = expr_copy(expr);
|
||||
expr_insert_addr(inner);
|
||||
expr->expr_kind = EXPR_CALL;
|
||||
expr->call_expr = (ExprCall) {
|
||||
.is_type_method = true,
|
||||
};
|
||||
REMINDER("Failability");
|
||||
return sema_expr_analyse_general_call(context, expr, decl, inner, decl->decl_kind == DECL_MACRO, false);
|
||||
}
|
||||
|
||||
static Decl *find_iterator(SemaContext *context, Expr *enumerator)
|
||||
{
|
||||
if (!type_may_have_sub_elements(enumerator->type))
|
||||
{
|
||||
SEMA_ERROR(enumerator, "It's not possible to enumerate an expression of type %s.", type_quoted_error_string(enumerator->type));
|
||||
return NULL;
|
||||
}
|
||||
Decl *ambiguous = NULL;
|
||||
Decl *private = NULL;
|
||||
Decl *method = sema_resolve_method(context->unit, enumerator->type->decl, kw_iterator, &ambiguous, &private);
|
||||
if (!decl_ok(method)) return NULL;
|
||||
if (!method)
|
||||
{
|
||||
if (ambiguous)
|
||||
{
|
||||
SEMA_ERROR(enumerator,
|
||||
"It's not possible to find a definition for 'iterator' on %s that is not ambiguous.",
|
||||
type_quoted_error_string(enumerator->type));
|
||||
return NULL;
|
||||
}
|
||||
if (private)
|
||||
{
|
||||
SEMA_ERROR(enumerator,
|
||||
"It's not possible to find a public definition for 'iterator' with '%s'.",
|
||||
type_quoted_error_string(enumerator->type));
|
||||
return NULL;
|
||||
}
|
||||
SEMA_ERROR(enumerator,
|
||||
"This type cannot be iterated over, implement a method or method macro called 'iterator'.",
|
||||
type_to_error_string(enumerator->type));
|
||||
return NULL;
|
||||
}
|
||||
Decl **parameters;
|
||||
TypeInfo *iterator_type;
|
||||
switch (method->decl_kind)
|
||||
{
|
||||
case DECL_GENERIC:
|
||||
parameters = method->generic_decl.parameters;
|
||||
iterator_type = method->generic_decl.rtype;
|
||||
break;
|
||||
case DECL_MACRO:
|
||||
parameters = method->macro_decl.parameters;
|
||||
iterator_type = method->macro_decl.rtype;
|
||||
break;
|
||||
case DECL_FUNC:
|
||||
parameters = method->func_decl.function_signature.params;
|
||||
iterator_type = method->func_decl.function_signature.returntype;
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE
|
||||
}
|
||||
if (vec_size(parameters) > 1)
|
||||
{
|
||||
SEMA_ERROR(enumerator, "'iterator()' takes parameters and can't be used for 'foreach'.");
|
||||
return NULL;
|
||||
}
|
||||
if (!iterator_type)
|
||||
{
|
||||
SEMA_ERROR(enumerator, "This type has an iterator without a declared result type, this can't be used with 'foreach'.");
|
||||
return NULL;
|
||||
}
|
||||
assert(iterator_type->resolve_status == RESOLVE_DONE);
|
||||
Type *it_type = iterator_type->type->canonical;
|
||||
if (it_type->type_kind != TYPE_STRUCT)
|
||||
{
|
||||
SEMA_ERROR(enumerator, "This type has an implementation of 'iterator()' that doesn't return a struct, so it can't be used with 'foreach'.");
|
||||
return NULL;
|
||||
}
|
||||
return method;
|
||||
}
|
||||
|
||||
static Decl *find_iterator_next(SemaContext *context, Expr *enumerator)
|
||||
{
|
||||
Type *type = enumerator->type->canonical;
|
||||
assert(type->type_kind == TYPE_STRUCT);
|
||||
Decl *ambiguous = NULL;
|
||||
Decl *private = NULL;
|
||||
Decl *method = sema_resolve_method(context->unit, type->decl, kw_next, &ambiguous, &private);
|
||||
if (!decl_ok(method)) return NULL;
|
||||
if (!method)
|
||||
{
|
||||
if (ambiguous)
|
||||
{
|
||||
SEMA_ERROR(enumerator, "The iterator %s has ambiguous 'next' definitions.", type_quoted_error_string(type));
|
||||
return NULL;
|
||||
}
|
||||
if (private)
|
||||
{
|
||||
SEMA_ERROR(enumerator,
|
||||
"The iterator %s has a private 'next' definition.",
|
||||
type_quoted_error_string(type));
|
||||
return NULL;
|
||||
}
|
||||
SEMA_ERROR(enumerator,
|
||||
"The iterator %s is missing a definition for 'next()'.",
|
||||
type_quoted_error_string(type));
|
||||
return NULL;
|
||||
}
|
||||
Decl **parameters;
|
||||
TypeInfo *rtype;
|
||||
switch (method->decl_kind)
|
||||
{
|
||||
case DECL_GENERIC:
|
||||
parameters = method->generic_decl.parameters;
|
||||
rtype = method->generic_decl.rtype;
|
||||
break;
|
||||
case DECL_MACRO:
|
||||
parameters = method->macro_decl.parameters;
|
||||
rtype = method->macro_decl.rtype;
|
||||
break;
|
||||
case DECL_FUNC:
|
||||
parameters = method->func_decl.function_signature.params;
|
||||
rtype = method->func_decl.function_signature.returntype;
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE
|
||||
}
|
||||
if (vec_size(parameters) != 2)
|
||||
{
|
||||
SEMA_ERROR(enumerator, "An iterator with a 'next()' that take takes %d parameters can't be used for 'foreach', it should have 1.", vec_size(parameters) - 1);
|
||||
return NULL;
|
||||
}
|
||||
if (!rtype)
|
||||
{
|
||||
SEMA_ERROR(enumerator, "This type has an iterator without a declared return type, this can't be used with 'foreach'.");
|
||||
return NULL;
|
||||
}
|
||||
return method;
|
||||
}
|
||||
|
||||
static Expr *sema_insert_method_macro_call(SemaContext *context, SourceSpan span, Decl *macro_decl, Expr *parent, Expr **arguments)
|
||||
static Expr *sema_insert_method_macro_call(SemaContext *context, SourceSpan span, Decl *method_decl, Expr *parent, Expr **arguments)
|
||||
{
|
||||
Expr *len_call = expr_new(EXPR_CALL, span);
|
||||
len_call->resolve_status = RESOLVE_RUNNING;
|
||||
len_call->call_expr.func_ref = macro_decl;
|
||||
len_call->call_expr.func_ref = method_decl;
|
||||
len_call->call_expr.arguments = arguments;
|
||||
len_call->call_expr.body = NULL;
|
||||
len_call->call_expr.unsplat_last = false;
|
||||
len_call->call_expr.is_type_method = true;
|
||||
if (!sema_expr_analyse_macro_call(context, len_call, parent, macro_decl, false)) return poisoned_expr;
|
||||
bool is_macro = method_decl->decl_kind == DECL_MACRO;
|
||||
if (!is_macro)
|
||||
{
|
||||
if (parent->type->type_kind != TYPE_POINTER) expr_insert_addr(parent);
|
||||
}
|
||||
if (!sema_expr_analyse_general_call(context, len_call, method_decl, parent, is_macro, false)) return poisoned_expr;
|
||||
len_call->resolve_status = RESOLVE_DONE;
|
||||
return len_call;
|
||||
}
|
||||
@@ -1160,9 +1024,9 @@ static inline bool sema_analyse_foreach_stmt(SemaContext *context, Ast *statemen
|
||||
|
||||
if (!value_type)
|
||||
{
|
||||
len = sema_find_operator(context, enumerator, kw_operator_len);
|
||||
Decl *by_val = sema_find_operator(context, enumerator, kw_operator_element_at);
|
||||
Decl *by_ref = sema_find_operator(context, enumerator, kw_operator_element_at_ref);
|
||||
len = sema_find_operator(context, enumerator, OVERLOAD_LEN);
|
||||
Decl *by_val = sema_find_operator(context, enumerator, OVERLOAD_ELEMENT_AT);
|
||||
Decl *by_ref = sema_find_operator(context, enumerator, OVERLOAD_ELEMENT_REF);
|
||||
if (!len || (!by_val && !by_ref))
|
||||
{
|
||||
SEMA_ERROR(enumerator, "It's not possible to enumerate an expression of type %s.", type_quoted_error_string(enumerator->type));
|
||||
|
||||
@@ -45,10 +45,9 @@ const char *kw_elements;
|
||||
const char *kw_errors;
|
||||
const char *kw_inf;
|
||||
const char *kw_inline;
|
||||
const char *kw_iterator;
|
||||
const char *kw_operator_element_at;
|
||||
const char *kw_operator_element_at_ref;
|
||||
const char *kw_operator_len;
|
||||
const char *kw_elementat;
|
||||
const char *kw_elementref;
|
||||
const char *kw_elementset;
|
||||
const char *kw_len;
|
||||
const char *kw_main;
|
||||
const char *kw_max;
|
||||
@@ -138,10 +137,9 @@ void symtab_init(uint32_t capacity)
|
||||
kw_errors = KW_DEF("errors");
|
||||
kw_inf = KW_DEF("inf");
|
||||
kw_inline = KW_DEF("inline");
|
||||
kw_iterator = KW_DEF("iterator");
|
||||
kw_operator_element_at = KW_DEF("operator_element_at");
|
||||
kw_operator_element_at_ref = KW_DEF("operator_element_at_ref");
|
||||
kw_operator_len = KW_DEF("operator_len");
|
||||
kw_elementat = KW_DEF("elementat");
|
||||
kw_elementref = KW_DEF("elementref");
|
||||
kw_elementset = KW_DEF("elementset");
|
||||
kw_len = KW_DEF("len");
|
||||
kw_main = KW_DEF("main");
|
||||
kw_max = KW_DEF("max");
|
||||
@@ -213,6 +211,7 @@ void symtab_init(uint32_t capacity)
|
||||
attribute_list[ATTRIBUTE_REGCALL] = KW_DEF("regcall");
|
||||
attribute_list[ATTRIBUTE_FASTCALL] = KW_DEF("fastcall");
|
||||
attribute_list[ATTRIBUTE_OVERLAP] = KW_DEF("overlap");
|
||||
attribute_list[ATTRIBUTE_OPERATOR] = KW_DEF("operator");
|
||||
attribute_list[ATTRIBUTE_AUTOIMPORT] = KW_DEF("autoimport");
|
||||
|
||||
for (unsigned i = 0; i < NUMBER_OF_ATTRIBUTES; i++)
|
||||
|
||||
@@ -1 +1 @@
|
||||
#define COMPILER_VERSION "PRE.20"
|
||||
#define COMPILER_VERSION "PRE.21"
|
||||
@@ -8,17 +8,17 @@ struct Foo
|
||||
|
||||
extern fn void printf(char*, ...);
|
||||
|
||||
macro int* Foo.operator_element_at_ref(Foo &f, int a)
|
||||
macro int* Foo.operator_element_at_ref(Foo &f, int a) @operator(elementref)
|
||||
{
|
||||
return &f.a[a];
|
||||
}
|
||||
|
||||
macro int Foo.operator_len(Foo &f)
|
||||
macro int Foo.operator_len(Foo &f) @operator(len)
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
|
||||
macro int Foo.operator_element_at(Foo &f, int a)
|
||||
macro int Foo.operator_element_at(Foo &f, int a) @operator(elementat)
|
||||
{
|
||||
return f.a[a];
|
||||
}
|
||||
|
||||
@@ -6,12 +6,12 @@ struct Foo
|
||||
int[] x;
|
||||
}
|
||||
|
||||
macro int Foo.operator_element_at(Foo &foo, usize index)
|
||||
macro int Foo.operator_element_at(Foo &foo, usize index) @operator(elementat)
|
||||
{
|
||||
return foo.x[index];
|
||||
}
|
||||
|
||||
macro usize Foo.operator_len(Foo &foo)
|
||||
macro usize Foo.operator_len(Foo &foo) @operator(len)
|
||||
{
|
||||
return foo.x.len;
|
||||
}
|
||||
|
||||
@@ -5,12 +5,12 @@ struct Foo
|
||||
int[] x;
|
||||
}
|
||||
|
||||
macro int Foo.operator_element_at(Foo &foo, usize index)
|
||||
macro int Foo.operator_element_at(Foo &foo, usize index) @operator(elementat)
|
||||
{
|
||||
return foo.x[index];
|
||||
}
|
||||
|
||||
macro usize Foo.operator_len(Foo &foo)
|
||||
macro usize Foo.operator_len(Foo &foo) @operator(len)
|
||||
{
|
||||
return foo.x.len;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user