mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 03:51:18 +00:00
Remove operator(@construct). Fix sample.
This commit is contained in:
committed by
Christoffer Lerno
parent
2a895ec7be
commit
fb6b048bd0
@@ -14,6 +14,7 @@
|
|||||||
- Removed `@adhoc` attribute.
|
- Removed `@adhoc` attribute.
|
||||||
- Disallow inline use of nested generics (e.g. `List{List{int}}`.
|
- Disallow inline use of nested generics (e.g. `List{List{int}}`.
|
||||||
- Remove `.allocator = allocator` syntax for functions.
|
- Remove `.allocator = allocator` syntax for functions.
|
||||||
|
- Remove `@operator(construct)`.
|
||||||
|
|
||||||
## 0.6.8 Change list
|
## 0.6.8 Change list
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,9 @@
|
|||||||
|
|
||||||
module test;
|
module test;
|
||||||
import libc;
|
import libc;
|
||||||
import std::io;
|
import std::io;
|
||||||
import std::collections::maybe;
|
import std::collections::maybe;
|
||||||
|
|
||||||
def MaybeString = Maybe{String};
|
|
||||||
def MaybeHead = Maybe{Head};
|
|
||||||
def new_head_val = maybe::value{Head};
|
|
||||||
def new_string_val = maybe::value{String};
|
|
||||||
|
|
||||||
fault TitleResult
|
fault TitleResult
|
||||||
{
|
{
|
||||||
TITLE_MISSING
|
TITLE_MISSING
|
||||||
@@ -18,16 +14,23 @@ fault ReadError
|
|||||||
BAD_READ,
|
BAD_READ,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Doc { MaybeHead head; }
|
struct Doc
|
||||||
struct Head { MaybeString title; }
|
{
|
||||||
|
Maybe { Head } head;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Head
|
||||||
|
{
|
||||||
|
Maybe { String } title;
|
||||||
|
}
|
||||||
|
|
||||||
struct Summary
|
struct Summary
|
||||||
{
|
{
|
||||||
MaybeString title;
|
Maybe { String } title;
|
||||||
bool ok;
|
bool ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn void! Summary.print(Summary *s, OutStream out)
|
fn void! Summary.print(Summary* s, OutStream out)
|
||||||
{
|
{
|
||||||
io::fprintf(out, "Summary({ .title = %s, .ok = %s})", s.title.get() ?? "missing", s.ok)!;
|
io::fprintf(out, "Summary({ .title = %s, .ok = %s})", s.title.get() ?? "missing", s.ok)!;
|
||||||
}
|
}
|
||||||
@@ -36,22 +39,22 @@ fn Doc! read_doc(String url)
|
|||||||
{
|
{
|
||||||
if (url.contains("fail")) return ReadError.BAD_READ?;
|
if (url.contains("fail")) return ReadError.BAD_READ?;
|
||||||
if (url.contains("head-missing")) return { };
|
if (url.contains("head-missing")) return { };
|
||||||
if (url.contains("title-missing")) return { .head = new_head_val({}) };
|
if (url.contains("title-missing")) return { .head = maybe::value{Head}({}) };
|
||||||
if (url.contains("title-empty")) return { .head = new_head_val({ .title = new_string_val("")}) };
|
if (url.contains("title-empty")) return { .head = maybe::value{Head}({ .title = maybe::value{String}("")}) };
|
||||||
return { .head = new_head_val({ .title = new_string_val(string::new_format("Title of %s", url)) }) };
|
return { .head = maybe::value{Head}({ .title = maybe::value{String}(string::format(mem, "Title of %s", url)) }) };
|
||||||
}
|
}
|
||||||
|
|
||||||
fn Summary build_summary(Doc doc)
|
fn Summary build_summary(Doc doc)
|
||||||
{
|
{
|
||||||
return Summary {
|
return {
|
||||||
.title = new_string_val(doc.head.get().title.get()) ?? MaybeString {},
|
.title = maybe::value{String}(doc.head.get().title.get()) ?? {},
|
||||||
.ok = true,
|
.ok = true,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn Summary read_and_build_summary(String url)
|
fn Summary read_and_build_summary(String url)
|
||||||
{
|
{
|
||||||
return build_summary(read_doc(url)) ?? Summary {};
|
return build_summary(read_doc(url)) ?? {};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bool! is_title_non_empty(Doc doc)
|
fn bool! is_title_non_empty(Doc doc)
|
||||||
|
|||||||
@@ -1,101 +0,0 @@
|
|||||||
|
|
||||||
module test;
|
|
||||||
import libc;
|
|
||||||
import std::io;
|
|
||||||
import std::collections::maybe;
|
|
||||||
|
|
||||||
fault TitleResult
|
|
||||||
{
|
|
||||||
TITLE_MISSING
|
|
||||||
}
|
|
||||||
|
|
||||||
fault ReadError
|
|
||||||
{
|
|
||||||
BAD_READ,
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Doc
|
|
||||||
{
|
|
||||||
Maybe { Head } head;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Head
|
|
||||||
{
|
|
||||||
Maybe { String } title;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Summary
|
|
||||||
{
|
|
||||||
Maybe { String } title;
|
|
||||||
bool ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn void! Summary.print(Summary* s, OutStream out)
|
|
||||||
{
|
|
||||||
io::fprintf(out, "Summary({ .title = %s, .ok = %s})", s.title.get() ?? "missing", s.ok)!;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn Doc! read_doc(String url)
|
|
||||||
{
|
|
||||||
if (url.contains("fail")) return ReadError.BAD_READ?;
|
|
||||||
if (url.contains("head-missing")) return { };
|
|
||||||
if (url.contains("title-missing")) return { .head = maybe::value{Head}({}) };
|
|
||||||
if (url.contains("title-empty")) return { .head = maybe::value{Head}({ .title = maybe::value{String}("")}) };
|
|
||||||
return { .head = maybe::value{Head}({ .title = maybe::value{String}(string::format(mem, "Title of %s", url)) }) };
|
|
||||||
}
|
|
||||||
|
|
||||||
fn Summary build_summary(Doc doc)
|
|
||||||
{
|
|
||||||
return {
|
|
||||||
.title = maybe::value{String}(doc.head.get().title.get()) ?? {},
|
|
||||||
.ok = true,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
fn Summary read_and_build_summary(String url)
|
|
||||||
{
|
|
||||||
return build_summary(read_doc(url)) ?? {};
|
|
||||||
}
|
|
||||||
|
|
||||||
fn bool! is_title_non_empty(Doc doc)
|
|
||||||
{
|
|
||||||
String! title = doc.head.get().title.get();
|
|
||||||
if (catch title) return TitleResult.TITLE_MISSING?;
|
|
||||||
return title.len > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn bool! read_whether_title_non_empty(String url)
|
|
||||||
{
|
|
||||||
return is_title_non_empty(read_doc(url));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn String bool_to_string(bool b)
|
|
||||||
{
|
|
||||||
return b ? "true" : "false";
|
|
||||||
}
|
|
||||||
|
|
||||||
fn void main()
|
|
||||||
{
|
|
||||||
const String[] URLS = { "good", "title-empty", "title-missing", "head-missing", "fail" };
|
|
||||||
DynamicArenaAllocator dynamic_arena;
|
|
||||||
dynamic_arena.init(1024, allocator::heap());
|
|
||||||
OutStream out = io::stdout();
|
|
||||||
foreach (String url : URLS)
|
|
||||||
{
|
|
||||||
mem::@scoped(&dynamic_arena)
|
|
||||||
{
|
|
||||||
io::printf(`Checking "https://%s/":` "\n", url);
|
|
||||||
Summary summary = read_and_build_summary(url);
|
|
||||||
io::fprintf(out, " Summary: ")!!;
|
|
||||||
summary.print(out)!!;
|
|
||||||
io::fprintn(out, "")!!;
|
|
||||||
io::fprintf(out, " Title: %s\n", summary.title.get() ?? "")!!;
|
|
||||||
bool! has_title = read_whether_title_non_empty(url);
|
|
||||||
// This looks a bit less than elegant, but as you see it's mostly due to having to
|
|
||||||
// use printf here.
|
|
||||||
io::fprintf(out, " Has title: %s vs %s\n", bool_to_string(has_title) ?? (@catch(has_title)).nameof, has_title ?? false)!!;
|
|
||||||
};
|
|
||||||
dynamic_arena.reset();
|
|
||||||
}
|
|
||||||
dynamic_arena.free();
|
|
||||||
}
|
|
||||||
@@ -1916,7 +1916,6 @@ extern const char *kw_at_pure;
|
|||||||
extern const char *kw_at_require;
|
extern const char *kw_at_require;
|
||||||
extern const char *kw_at_return;
|
extern const char *kw_at_return;
|
||||||
extern const char *kw_at_jump;
|
extern const char *kw_at_jump;
|
||||||
extern const char *kw_construct;
|
|
||||||
extern const char *kw_in;
|
extern const char *kw_in;
|
||||||
extern const char *kw_inout;
|
extern const char *kw_inout;
|
||||||
extern const char *kw_len;
|
extern const char *kw_len;
|
||||||
|
|||||||
@@ -902,7 +902,6 @@ typedef enum
|
|||||||
OVERLOAD_ELEMENT_REF,
|
OVERLOAD_ELEMENT_REF,
|
||||||
OVERLOAD_ELEMENT_SET,
|
OVERLOAD_ELEMENT_SET,
|
||||||
OVERLOAD_LEN,
|
OVERLOAD_LEN,
|
||||||
OVERLOAD_CONSTRUCT,
|
|
||||||
} OperatorOverload;
|
} OperatorOverload;
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
|
|||||||
@@ -1180,7 +1180,7 @@ static inline bool sema_analyse_signature(SemaContext *context, Signature *sig,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Ensure it has at least one parameter if method.
|
// Ensure it has at least one parameter if method.
|
||||||
if (method_parent && !vec_size(params) && decl->operator != OVERLOAD_CONSTRUCT)
|
if (method_parent && !vec_size(params))
|
||||||
{
|
{
|
||||||
RETURN_SEMA_ERROR(decl, "A method must start with an argument of the type "
|
RETURN_SEMA_ERROR(decl, "A method must start with an argument of the type "
|
||||||
"it is a method of, e.g. 'fn void %s.%s(%s* self)', "
|
"it is a method of, e.g. 'fn void %s.%s(%s* self)', "
|
||||||
@@ -1702,33 +1702,6 @@ Decl *sema_find_operator(SemaContext *context, Type *type, OperatorOverload oper
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool sema_analyse_operator_construct(SemaContext *context, Decl *method)
|
|
||||||
{
|
|
||||||
Signature *signature = &method->func_decl.signature;
|
|
||||||
Decl **params = signature->params;
|
|
||||||
uint32_t param_count = vec_size(params);
|
|
||||||
if (param_count && params[0] && params[0]->var.is_self)
|
|
||||||
{
|
|
||||||
RETURN_SEMA_ERROR(method, "'construct' methods cannot have 'self' parameters.");
|
|
||||||
}
|
|
||||||
if (!signature->rtype)
|
|
||||||
{
|
|
||||||
RETURN_SEMA_ERROR(method, "A 'construct' macro method should always have an explicitly typed return value.");
|
|
||||||
}
|
|
||||||
Type *rtype = typeget(signature->rtype)->canonical;
|
|
||||||
Type *parent = typeget(method->func_decl.type_parent);
|
|
||||||
if (parent->canonical != rtype && type_get_ptr(parent->canonical) != rtype)
|
|
||||||
{
|
|
||||||
RETURN_SEMA_ERROR(type_infoptr(signature->rtype),
|
|
||||||
"The return type of a 'construct' method must be the method type, or a pointer to it."
|
|
||||||
" In this case %s or %s was expected.",
|
|
||||||
type_quoted_error_string(parent), type_quoted_error_string(type_get_ptr(parent)));
|
|
||||||
}
|
|
||||||
SEMA_DEPRECATED(method, "'operator(@construct)' is deprecated and will be removed in the next version, prefer using init methods and functions instead.");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static inline bool sema_analyse_operator_element_at(SemaContext *context, Decl *method)
|
static inline bool sema_analyse_operator_element_at(SemaContext *context, Decl *method)
|
||||||
{
|
{
|
||||||
TypeInfo *rtype;
|
TypeInfo *rtype;
|
||||||
@@ -1781,8 +1754,6 @@ static bool sema_check_operator_method_validity(SemaContext *context, Decl *meth
|
|||||||
{
|
{
|
||||||
switch (method->operator)
|
switch (method->operator)
|
||||||
{
|
{
|
||||||
case OVERLOAD_CONSTRUCT:
|
|
||||||
return sema_analyse_operator_construct(context, method);
|
|
||||||
case OVERLOAD_ELEMENT_SET:
|
case OVERLOAD_ELEMENT_SET:
|
||||||
return sema_analyse_operator_element_set(context, method);
|
return sema_analyse_operator_element_set(context, method);
|
||||||
case OVERLOAD_ELEMENT_AT:
|
case OVERLOAD_ELEMENT_AT:
|
||||||
@@ -1889,7 +1860,6 @@ INLINE bool sema_analyse_operator_method(SemaContext *context, Type *parent_type
|
|||||||
|
|
||||||
// See if the operator has already been defined.
|
// See if the operator has already been defined.
|
||||||
OperatorOverload operator = method->operator;
|
OperatorOverload operator = method->operator;
|
||||||
if (operator == OVERLOAD_CONSTRUCT) return true;
|
|
||||||
|
|
||||||
Decl *other = sema_find_operator(context, parent_type, operator);
|
Decl *other = sema_find_operator(context, parent_type, operator);
|
||||||
if (other != method)
|
if (other != method)
|
||||||
@@ -1956,7 +1926,6 @@ INLINE bool sema_analyse_operator_method(SemaContext *context, Type *parent_type
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
case OVERLOAD_CONSTRUCT:
|
|
||||||
default:
|
default:
|
||||||
UNREACHABLE
|
UNREACHABLE
|
||||||
}
|
}
|
||||||
@@ -2355,10 +2324,8 @@ static inline bool sema_analyse_method(SemaContext *context, Decl *decl)
|
|||||||
Decl **params = decl->func_decl.signature.params;
|
Decl **params = decl->func_decl.signature.params;
|
||||||
bool is_dynamic = decl->func_decl.attr_dynamic;
|
bool is_dynamic = decl->func_decl.attr_dynamic;
|
||||||
|
|
||||||
bool is_constructor = decl->operator == OVERLOAD_CONSTRUCT;
|
|
||||||
|
|
||||||
// Ensure that the first parameter is valid.
|
// Ensure that the first parameter is valid.
|
||||||
if (!is_constructor && !sema_is_valid_method_param(context, params[0], par_type, is_dynamic)) return false;
|
if (!sema_is_valid_method_param(context, params[0], par_type, is_dynamic)) return false;
|
||||||
|
|
||||||
// Make dynamic checks.
|
// Make dynamic checks.
|
||||||
if (is_dynamic)
|
if (is_dynamic)
|
||||||
@@ -2371,10 +2338,6 @@ static inline bool sema_analyse_method(SemaContext *context, Decl *decl)
|
|||||||
{
|
{
|
||||||
RETURN_SEMA_ERROR(decl, "'any' may not implement '@dynamic' methods, only regular methods.");
|
RETURN_SEMA_ERROR(decl, "'any' may not implement '@dynamic' methods, only regular methods.");
|
||||||
}
|
}
|
||||||
if (is_constructor)
|
|
||||||
{
|
|
||||||
RETURN_SEMA_ERROR(decl, "A 'construct' method may not be '@dynamic'.");
|
|
||||||
}
|
|
||||||
// Retrieve the implemented method.
|
// Retrieve the implemented method.
|
||||||
Decl *implemented_method = sema_find_interface_for_method(context, par_type, decl);
|
Decl *implemented_method = sema_find_interface_for_method(context, par_type, decl);
|
||||||
if (!decl_ok(implemented_method)) return false;
|
if (!decl_ok(implemented_method)) return false;
|
||||||
@@ -2671,11 +2634,6 @@ static bool sema_analyse_attribute(SemaContext *context, ResolvedAttrData *attr_
|
|||||||
{
|
{
|
||||||
case EXPR_UNRESOLVED_IDENTIFIER:
|
case EXPR_UNRESOLVED_IDENTIFIER:
|
||||||
if (expr->unresolved_ident_expr.path) goto FAILED_OP_TYPE;
|
if (expr->unresolved_ident_expr.path) goto FAILED_OP_TYPE;
|
||||||
if (expr->unresolved_ident_expr.ident == kw_construct)
|
|
||||||
{
|
|
||||||
decl->operator = OVERLOAD_CONSTRUCT;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (expr->unresolved_ident_expr.ident != kw_len) goto FAILED_OP_TYPE;
|
if (expr->unresolved_ident_expr.ident != kw_len) goto FAILED_OP_TYPE;
|
||||||
decl->operator = OVERLOAD_LEN;
|
decl->operator = OVERLOAD_LEN;
|
||||||
break;
|
break;
|
||||||
@@ -3688,19 +3646,17 @@ static bool sema_analyse_macro_method(SemaContext *context, Decl *decl)
|
|||||||
ASSERT(parent_type_info->resolve_status == RESOLVE_DONE);
|
ASSERT(parent_type_info->resolve_status == RESOLVE_DONE);
|
||||||
Type *parent_type = parent_type_info->type->canonical;
|
Type *parent_type = parent_type_info->type->canonical;
|
||||||
|
|
||||||
bool is_constructor = decl->operator == OVERLOAD_CONSTRUCT;
|
|
||||||
|
|
||||||
// Check the first argument.
|
// Check the first argument.
|
||||||
Decl *first_param = is_constructor ? NULL : decl->func_decl.signature.params[0];
|
Decl *first_param = decl->func_decl.signature.params[0];
|
||||||
if (!is_constructor && !first_param)
|
if (!first_param)
|
||||||
{
|
{
|
||||||
RETURN_SEMA_ERROR(decl, "The first parameter to this method must be of type %s or %s.", type_quoted_error_string(parent_type),
|
RETURN_SEMA_ERROR(decl, "The first parameter to this method must be of type %s or %s.", type_quoted_error_string(parent_type),
|
||||||
type_quoted_error_string(type_get_ptr(parent_type)));
|
type_quoted_error_string(type_get_ptr(parent_type)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!is_constructor && !sema_is_valid_method_param(context, first_param, parent_type, false)) return false;
|
if (!sema_is_valid_method_param(context, first_param, parent_type, false)) return false;
|
||||||
|
|
||||||
if (!is_constructor && first_param->var.kind != VARDECL_PARAM_EXPR && first_param->var.kind != VARDECL_PARAM_CT && first_param->var.kind != VARDECL_PARAM)
|
if (first_param->var.kind != VARDECL_PARAM_EXPR && first_param->var.kind != VARDECL_PARAM_CT && first_param->var.kind != VARDECL_PARAM)
|
||||||
{
|
{
|
||||||
RETURN_SEMA_ERROR(first_param, "The first parameter must be a compile time, regular or ref (&) type.");
|
RETURN_SEMA_ERROR(first_param, "The first parameter must be a compile time, regular or ref (&) type.");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,7 +47,6 @@ const char *kw_at_pure;
|
|||||||
const char *kw_at_require;
|
const char *kw_at_require;
|
||||||
const char *kw_at_return;
|
const char *kw_at_return;
|
||||||
const char *kw_at_jump;
|
const char *kw_at_jump;
|
||||||
const char *kw_construct;
|
|
||||||
const char *kw_in;
|
const char *kw_in;
|
||||||
const char *kw_inout;
|
const char *kw_inout;
|
||||||
const char *kw_len;
|
const char *kw_len;
|
||||||
@@ -134,7 +133,6 @@ void symtab_init(uint32_t capacity)
|
|||||||
kw_IoError = KW_DEF("IoError");
|
kw_IoError = KW_DEF("IoError");
|
||||||
|
|
||||||
type = TOKEN_IDENT;
|
type = TOKEN_IDENT;
|
||||||
kw_construct = KW_DEF("construct");
|
|
||||||
kw_in = KW_DEF("in");
|
kw_in = KW_DEF("in");
|
||||||
kw_inout = KW_DEF("inout");
|
kw_inout = KW_DEF("inout");
|
||||||
kw_libc = KW_DEF("libc");
|
kw_libc = KW_DEF("libc");
|
||||||
|
|||||||
Reference in New Issue
Block a user