New generic syntax and ad hoc invocation.

This commit is contained in:
Christoffer Lerno
2023-07-06 01:27:15 +02:00
committed by Christoffer Lerno
parent 276281c3f9
commit 4f7b42cdc4
61 changed files with 405 additions and 228 deletions

View File

@@ -79,13 +79,13 @@ import stack;
// Define our new types, the first will implicitly create
// a complete copy of the entire Stack module with "Type" set to "int"
def IntStack = Stack<int>;
def IntStack = Stack(<int>);
// The second creates another copy with "Type" set to "double"
def DoubleStack = Stack<double>;
def DoubleStack = Stack(<double>);
// If we had added "define IntStack2 = Stack<int>"
// If we had added "define IntStack2 = Stack(<int>)"
// no additional copy would have been made (since we already
// have an parameterization of Stack<int>) so it would
// have an parameterization of Stack(<int>)) so it would
// be same as declaring IntStack2 an alias of IntStack
// Importing an external C function is straightforward

View File

@@ -1,4 +1,4 @@
module std::collections::enummap<Enum, ValueType>;
module std::collections::enummap(<Enum, ValueType>);
struct EnumMap
{

View File

@@ -5,7 +5,7 @@
/**
* @require Enum.kindof == TypeKind.ENUM : "Only enums maybe be used with an enumset"
**/
module std::collections::enumset<Enum>;
module std::collections::enumset(<Enum>);
def EnumSetType = $typefrom(private::type_for_enum_elements(Enum.elements)) @private ;

View File

@@ -1,7 +1,7 @@
// Copyright (c) 2021 Christoffer Lerno. All rights reserved.
// Use of self source code is governed by the MIT license
// a copy of which can be found in the LICENSE_STDLIB file.
module std::collections::linkedlist<Type>;
module std::collections::linkedlist(<Type>);
struct Node @private
{

View File

@@ -1,7 +1,7 @@
// Copyright (c) 2021 Christoffer Lerno. All rights reserved.
// Use of self source code is governed by the MIT license
// a copy of which can be found in the LICENSE_STDLIB file.
module std::collections::list<Type>;
module std::collections::list(<Type>);
import std::math;
def ElementPredicate = fn bool(Type *type);

View File

@@ -1,7 +1,7 @@
// Copyright (c) 2023 Christoffer Lerno. All rights reserved.
// Use of this source code is governed by the MIT license
// a copy of which can be found in the LICENSE_STDLIB file.
module std::collections::map<Key, Value>;
module std::collections::map(<Key, Value>);
import std::math;
const uint DEFAULT_INITIAL_CAPACITY = 16;

View File

@@ -465,7 +465,7 @@ fn Object* Object.get_or_create_obj(&self, String key)
return container;
}
def ObjectInternalMap = HashMap<String, Object*> @private;
def ObjectInternalList = List<Object*> @private;
def ObjectInternalMapEntry = Entry<String, Object*> @private;
def ObjectInternalMap = HashMap(<String, Object*>) @private;
def ObjectInternalList = List(<Object*>) @private;
def ObjectInternalMapEntry = Entry(<String, Object*>) @private;

View File

@@ -20,10 +20,10 @@
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
module std::collections::priorityqueue<Type>;
module std::collections::priorityqueue(<Type>);
import std::collections::list;
def Heap = List<Type>;
def Heap = List(<Type>);
struct PriorityQueue
{

View File

@@ -2,7 +2,7 @@
* @checked Type{} < Type{} : "The type must be comparable"
* @checked Type{} + (Type)1 : "The type must be possible to add to"
**/
module std::collections::range<Type>;
module std::collections::range(<Type>);
struct Range
{

View File

@@ -5,7 +5,7 @@
module std::core::mem::allocator;
import std::collections::map;
def PtrMap = HashMap<uptr, usz>;
def PtrMap = HashMap(<uptr, usz>);
// A simple tracking allocator.
// It tracks allocations using a hash map but

View File

@@ -6,7 +6,7 @@ const char PREFERRED_SEPARATOR_WIN32 = '\\';
const char PREFERRED_SEPARATOR_POSIX = '/';
const char PREFERRED_SEPARATOR = env::WIN32 ? PREFERRED_SEPARATOR_WIN32 : PREFERRED_SEPARATOR_POSIX;
def PathList = List<Path>;
def PathList = List(<Path>);
fault PathResult
{

View File

@@ -85,33 +85,33 @@ fault MatrixError
MATRIX_INVERSE_DOESNT_EXIST,
}
def Complexf = Complex<float>;
def Complex = Complex<double>;
def complexf_identity = complex::identity<float>;
def complex_identity = complex::identity<double>;
def Complexf = Complex(<float>);
def Complex = Complex(<double>);
def complexf_identity = complex::identity(<float>);
def complex_identity = complex::identity(<double>);
def Quaternionf = Quaternion<float>;
def Quaternion = Quaternion<double>;
def quaternionf_identity = quaternion::identity<float>;
def quaternion_identity = quaternion::identity<double>;
def Quaternionf = Quaternion(<float>);
def Quaternion = Quaternion(<double>);
def quaternionf_identity = quaternion::identity(<float>);
def quaternion_identity = quaternion::identity(<double>);
def Matrix2f = Matrix2x2<float>;
def Matrix2 = Matrix2x2<double>;
def Matrix3f = Matrix3x3<float>;
def Matrix3 = Matrix3x3<double>;
def Matrix4f = Matrix4x4<float>;
def Matrix4 = Matrix4x4<double>;
def matrix4_ortho = matrix::ortho<double>;
def matrix4_perspective = matrix::perspective<double>;
def matrix4f_ortho = matrix::ortho<float>;
def matrix4f_perspective = matrix::perspective<float>;
def Matrix2f = Matrix2x2(<float>);
def Matrix2 = Matrix2x2(<double>);
def Matrix3f = Matrix3x3(<float>);
def Matrix3 = Matrix3x3(<double>);
def Matrix4f = Matrix4x4(<float>);
def Matrix4 = Matrix4x4(<double>);
def matrix4_ortho = matrix::ortho(<double>);
def matrix4_perspective = matrix::perspective(<double>);
def matrix4f_ortho = matrix::ortho(<float>);
def matrix4f_perspective = matrix::perspective(<float>);
def MATRIX2_IDENTITY = matrix::IDENTITY2<double>;
def MATRIX2F_IDENTITY = matrix::IDENTITY2<float>;
def MATRIX3_IDENTITY = matrix::IDENTITY3<double>;
def MATRIX3F_IDENTITY = matrix::IDENTITY3<float>;
def MATRIX4_IDENTITY = matrix::IDENTITY4<double>;
def MATRIX4F_IDENTITY = matrix::IDENTITY4<float>;
def MATRIX2_IDENTITY = matrix::IDENTITY2(<double>);
def MATRIX2F_IDENTITY = matrix::IDENTITY2(<float>);
def MATRIX3_IDENTITY = matrix::IDENTITY3(<double>);
def MATRIX3F_IDENTITY = matrix::IDENTITY3(<float>);
def MATRIX4_IDENTITY = matrix::IDENTITY4(<double>);
def MATRIX4F_IDENTITY = matrix::IDENTITY4(<float>);
/**
* @require types::is_numerical($typeof(x)) `The input must be a numerical value or numerical vector`

View File

@@ -1,4 +1,4 @@
module std::math::complex<Real>;
module std::math::complex(<Real>);
union Complex
{

View File

@@ -1,4 +1,4 @@
module std::math::matrix<Real>;
module std::math::matrix(<Real>);
struct Matrix2x2
{

View File

@@ -1,4 +1,4 @@
module std::math::quaternion<Real>;
module std::math::quaternion(<Real>);
import std::math::vector;
union Quaternion
{

View File

@@ -1,4 +1,4 @@
module std::sort::quicksort<Type>;
module std::sort::quicksort(<Type>);
import std::sort;
def ElementType = $typeof(Type{}[0]);

View File

@@ -3,6 +3,8 @@
## 0.5.0 Change List
### Changes / improvements
- New generic syntax.
- Ad hoc generics are now allowed.
- Allow inferred type on method first argument.
- Fix to void expression blocks
- Temporary objects may now invoke methods using ref parameters.

View File

@@ -1,4 +1,4 @@
module std::container::map <Key, Type>;
module std::container::map(<Key, Type>);
import std::core::builtin;
import std::io;
fault MapResult

View File

@@ -751,7 +751,7 @@ fn u32 addKind(u32 value, NodeKind k) @(inline) {
}
fn NodeKind getKind(u32 value) @(inline) {
return cast<NodeKind>(value >> NodeKindOffset);
return cast(<NodeKind>)(value >> NodeKindOffset);
}
fn u32 getValue(u32 value) @(inline) {

View File

@@ -216,6 +216,8 @@ b64\`{B64}+\` { count(); return(BYTES); }
"=>" { count(); return(IMPLIES); }
"[<" { count(); return(LVEC); }
">]" { count(); return(RVEC); }
"(<" { count(); return(LGENPAR); }
">)" { count(); return(RGENPAR); }
"$$" { count(); return(BUILTIN); }
";" { count(); return(';'); }
("{") { count(); return('{'); }

View File

@@ -15,6 +15,7 @@ void yyerror(char *s);
%token STRING_LITERAL INTEGER
%token INC_OP DEC_OP SHL_OP SHR_OP LE_OP GE_OP EQ_OP NE_OP
%token AND_OP OR_OP MUL_ASSIGN DIV_ASSIGN MOD_ASSIGN ADD_ASSIGN
%token LGENPAR RGENPAR
%token SUB_ASSIGN SHL_ASSIGN SHR_ASSIGN AND_ASSIGN
%token XOR_ASSIGN OR_ASSIGN VAR NUL ELVIS NEXTCASE ANYFAULT
%token MODULE IMPORT DEF EXTERN
@@ -187,6 +188,7 @@ call_trailing
| call_invocation
| call_invocation compound_statement
| '.' access_ident
| generic_expr
| INC_OP
| DEC_OP
| '!'
@@ -1104,9 +1106,9 @@ opt_distinct_inline
;
generic_parameters
: additive_expr
: expr
| type
| generic_parameters ',' bit_expr
| generic_parameters ',' expr
| generic_parameters ',' type
;
@@ -1154,8 +1156,12 @@ define_attribute
| AT_TYPE_IDENT opt_attributes '=' '{' opt_attributes '}'
;
generic_expr
: LGENPAR generic_parameters RGENPAR
;
opt_generic_parameters
: '<' generic_parameters '>'
: generic_expr
| empty
;
@@ -1194,7 +1200,7 @@ module_params
module
: MODULE path_ident opt_attributes ';'
| MODULE path_ident '<' module_params '>' opt_attributes ';'
| MODULE path_ident LGENPAR module_params RGENPAR opt_attributes ';'
;
import_paths

View File

@@ -377,6 +377,11 @@ struct TypeInfo_
Expr *len;
} array;
TypeInfo *pointer;
struct
{
TypeInfo *base;
Expr **params;
} generic;
};
};
@@ -840,6 +845,13 @@ typedef struct
BuiltinAccessKind kind : 8;
ExprId inner;
} ExprBuiltinAccess;
typedef struct
{
ExprId parent;
Expr **parmeters;
} ExprGenericIdent;
typedef struct
{
Expr *parent;
@@ -1135,6 +1147,7 @@ struct Expr_
ExprCall call_expr; // 32
Expr *inner_expr; // 8
ExprBuiltinAccess builtin_access_expr;
ExprGenericIdent generic_ident_expr;
ExprCatchUnwrap catch_unwrap_expr; // 24
ExprSubscript subscript_expr; // 12
ExprSubscriptAssign subscript_assign_expr;
@@ -1482,6 +1495,7 @@ typedef struct Module_
Module **sub_modules;
Decl **tests;
Decl **lambdas_to_evaluate;
const char *generic_suffix;
} Module;
@@ -2548,6 +2562,11 @@ INLINE bool type_is_integer_unsigned(Type *type)
INLINE bool type_info_poison(TypeInfo *type)
{
if (global_context.suppress_errors)
{
type->resolve_status = RESOLVE_NOT_DONE;
return false;
}
type->type = poisoned_type;
type->resolve_status = RESOLVE_DONE;
return false;

View File

@@ -296,6 +296,10 @@ Expr *copy_expr(CopyStruct *c, Expr *source_expr)
{
case EXPR_ANYSWITCH:
UNREACHABLE
case EXPR_GENERIC_IDENT:
MACRO_COPY_EXPRID(expr->generic_ident_expr.parent);
MACRO_COPY_EXPR_LIST(expr->generic_ident_expr.parmeters);
return expr;
case EXPR_MACRO_BODY_EXPANSION:
MACRO_COPY_EXPR_LIST(expr->body_expansion_expr.values);
MACRO_COPY_DECL_LIST(expr->body_expansion_expr.declarations);
@@ -797,6 +801,10 @@ TypeInfo *copy_type_info(CopyStruct *c, TypeInfo *source)
case TYPE_INFO_CT_IDENTIFIER:
case TYPE_INFO_IDENTIFIER:
return copy;
case TYPE_INFO_GENERIC:
copy->generic.base = copy_type_info(c, copy->generic.base);
copy->generic.params = copy_expr_list(c, copy->generic.params);
return copy;
case TYPE_INFO_TYPEFROM:
case TYPE_INFO_EVALTYPE:
case TYPE_INFO_TYPEOF:

View File

@@ -228,6 +228,7 @@ typedef enum
EXPR_EXPR_BLOCK,
EXPR_OPTIONAL,
EXPR_FORCE_UNWRAP,
EXPR_GENERIC_IDENT,
EXPR_GROUP,
EXPR_HASH_IDENT,
EXPR_IDENTIFIER,
@@ -375,6 +376,7 @@ typedef enum
TYPE_INFO_INFERRED_VECTOR,
TYPE_INFO_SUBARRAY,
TYPE_INFO_POINTER,
TYPE_INFO_GENERIC,
} TypeInfoKind;
typedef enum
@@ -427,6 +429,7 @@ typedef enum
TOKEN_IMPLIES, // =>
TOKEN_LESS_EQ, // <=
TOKEN_LBRAPIPE, // {|
TOKEN_LGENPAR, // (<
TOKEN_LVEC, // [<
TOKEN_MINUS_ASSIGN, // -=
TOKEN_MINUSMINUS, // --
@@ -437,6 +440,7 @@ typedef enum
TOKEN_PLUS_ASSIGN, // +=
TOKEN_PLUSPLUS, // ++
TOKEN_RBRAPIPE, // |}
TOKEN_RGENPAR, // >)
TOKEN_RVEC, // >]
TOKEN_QUESTQUEST, // ??
TOKEN_SCOPE, // ::
@@ -812,7 +816,8 @@ typedef enum
ANALYSIS_CT_ECHO,
ANALYSIS_CT_ASSERT,
ANALYSIS_FUNCTIONS,
ANALYSIS_LAST = ANALYSIS_FUNCTIONS
ANALYSIS_FINALIZE,
ANALYSIS_LAST = ANALYSIS_FINALIZE
} AnalysisStage;
typedef enum

View File

@@ -133,6 +133,7 @@ bool expr_may_addr(Expr *expr)
case EXPR_VASPLAT:
case EXPR_SWIZZLE:
case EXPR_LAMBDA:
case EXPR_GENERIC_IDENT:
return false;
}
UNREACHABLE
@@ -325,6 +326,7 @@ bool expr_is_constant_eval(Expr *expr, ConstantEvalKind eval_kind)
case EXPR_CT_ARG:
case EXPR_ASM:
case EXPR_SUBSCRIPT_ASSIGN:
case EXPR_GENERIC_IDENT:
UNREACHABLE
case EXPR_NOP:
return true;
@@ -689,6 +691,8 @@ bool expr_is_pure(Expr *expr)
return expr_is_pure(expr->unary_expr.expr);
}
UNREACHABLE
case EXPR_GENERIC_IDENT:
return exprid_is_pure(expr->generic_ident_expr.parent);
case EXPR_BITACCESS:
case EXPR_ACCESS:
// All access is pure if the parent is pure.

View File

@@ -1312,7 +1312,7 @@ static bool lexer_scan_token_inner(Lexer *lexer)
case '}':
return return_token(lexer, TOKEN_RBRACE, "}");
case '(':
return return_token(lexer, TOKEN_LPAREN, "(");
return match(lexer, '<') ? return_token(lexer, TOKEN_LGENPAR, "(<") : return_token(lexer, TOKEN_LPAREN, "(");
case ')':
return return_token(lexer, TOKEN_RPAREN, ")");
case '[':
@@ -1368,6 +1368,7 @@ static bool lexer_scan_token_inner(Lexer *lexer)
if (match(lexer, '=')) return return_token(lexer, TOKEN_SHR_ASSIGN, ">>=");
return return_token(lexer, TOKEN_SHR, ">>");
}
if (match(lexer, ')')) return return_token(lexer, TOKEN_RGENPAR, ">)");
if (match(lexer, ']')) return return_token(lexer, TOKEN_RVEC, ">]");
return match(lexer, '=') ? return_token(lexer, TOKEN_GREATER_EQ, ">=") : return_token(lexer,
TOKEN_GREATER,

View File

@@ -6543,6 +6543,7 @@ void llvm_emit_expr(GenContext *c, BEValue *value, Expr *expr)
case EXPR_COND:
case EXPR_ASM:
case EXPR_VASPLAT:
case EXPR_GENERIC_IDENT:
UNREACHABLE
case EXPR_LAMBDA:
llvm_emit_lambda(c, value, expr);

View File

@@ -525,7 +525,7 @@ Expr *parse_expression_list(ParseContext *c, bool allow_decl)
while (1)
{
Decl *decl;
ASSIGN_EXPR_OR_RET(Expr * expr, parse_decl_or_expr(c, &decl), poisoned_expr);
ASSIGN_EXPR_OR_RET(Expr *expr, parse_decl_or_expr(c, &decl), poisoned_expr);
if (!expr)
{
if (!allow_decl)
@@ -969,6 +969,28 @@ static Expr *parse_subscript_expr(ParseContext *c, Expr *left)
return subs_expr;
}
/**
* generic_expr ::= '(<' generic_parameters '>)'
*/
static Expr *parse_generic_expr(ParseContext *c, Expr *left)
{
assert(left && expr_ok(left));
advance_and_verify(c, TOKEN_LGENPAR);
Expr *subs_expr = expr_new_expr(EXPR_GENERIC_IDENT, left);
subs_expr->generic_ident_expr.parent = exprid(left);
Expr **exprs = NULL;
do
{
ASSIGN_EXPR_OR_RET(Expr *param, parse_expr(c), poisoned_expr);
vec_add(exprs, param);
} while (try_consume(c, TOKEN_COMMA));
CONSUME_OR_RET(TOKEN_RGENPAR, poisoned_expr);
subs_expr->generic_ident_expr.parmeters = exprs;
RANGE_EXTEND_PREV(subs_expr);
return subs_expr;
}
/**
* access_expr ::= '.' primary_expr
*/
@@ -1809,6 +1831,7 @@ ParseRule rules[TOKEN_EOF + 1] = {
[TOKEN_LBRAPIPE] = { parse_expr_block, NULL, PREC_NONE },
[TOKEN_BANGBANG] = { NULL, parse_force_unwrap_expr, PREC_CALL },
[TOKEN_LBRACKET] = { NULL, parse_subscript_expr, PREC_CALL },
[TOKEN_LGENPAR] = { NULL, parse_generic_expr, PREC_CALL },
[TOKEN_MINUS] = { parse_unary_expr, parse_binary, PREC_ADDITIVE },
[TOKEN_PLUS] = { parse_unary_expr, parse_binary, PREC_ADDITIVE },
[TOKEN_DIV] = { NULL, parse_binary, PREC_MULTIPLICATIVE },

View File

@@ -144,9 +144,13 @@ static inline bool parse_optional_module_params(ParseContext *c, const char ***t
*tokens_ref = NULL;
if (!try_consume(c, TOKEN_LESS)) return true;
SourceSpan span = c->span;
bool is_old_style = try_consume(c, TOKEN_LESS);
if (!is_old_style && !try_consume(c, TOKEN_LGENPAR)) return true;
if (try_consume(c, TOKEN_GREATER)) RETURN_SEMA_ERROR_HERE("Generic parameter list cannot be empty.");
// TODO remove after deprecation time
TokenType end_token = is_old_style ? TOKEN_GREATER : TOKEN_RGENPAR;
if (try_consume(c, end_token)) RETURN_SEMA_ERROR_HERE("Generic parameter list cannot be empty.");
// No params
while (1)
@@ -170,13 +174,18 @@ static inline bool parse_optional_module_params(ParseContext *c, const char ***t
advance(c);
if (!try_consume(c, TOKEN_COMMA))
{
return consume(c, TOKEN_GREATER, "Expected '>'.");
if (!consume(c, end_token, "Expected '>)'.")) return false;
if (is_old_style)
{
span = extend_span_with_token(span, c->prev_span);
sema_warning_at(span, "Generics with <...> syntax is deprecated, use (<...>) instead.");
}
return true;
}
}
}
/**
* module ::= MODULE module_path ('<' module_params '>')? (@public|@private|@local|@test|@export|@extern) EOS
* module ::= MODULE module_path ('(<' module_params '>)')? (@public|@private|@local|@test|@export|@extern) EOS
*/
bool parse_module(ParseContext *c, AstId contracts)
{
@@ -487,6 +496,24 @@ static inline TypeInfo *parse_base_type(ParseContext *c)
return type_info;
}
static inline TypeInfo *parse_generic_type(ParseContext *c, TypeInfo *type)
{
assert(type_info_ok(type));
advance_and_verify(c, TOKEN_LGENPAR);
Expr **exprs = NULL;
do
{
ASSIGN_EXPR_OR_RET(Expr *param, parse_expr(c), poisoned_type_info);
vec_add(exprs, param);
} while (try_consume(c, TOKEN_COMMA));
CONSUME_OR_RET(TOKEN_RGENPAR, poisoned_type_info);
TypeInfo *generic_type = type_info_new(TYPE_INFO_GENERIC, type->span);
generic_type->generic.params = exprs;
generic_type->generic.base = type;
return generic_type;
}
/**
* array_type_index
* : '[' constant_expression ']'
@@ -597,6 +624,9 @@ TypeInfo *parse_type_with_base(ParseContext *c, TypeInfo *type_info)
case TOKEN_LBRACKET:
type_info = parse_array_type_index(c, type_info);
break;
case TOKEN_LGENPAR:
type_info = parse_generic_type(c, type_info);
break;
case TOKEN_STAR:
advance(c);
{
@@ -1629,21 +1659,23 @@ static bool parse_macro_params(ParseContext *c, Decl *macro)
}
/**
* define_parameters ::= expr (',' expr)* '>'
* define_parameters ::= expr (<',' expr)* '>)'
*
* @return NULL if parsing failed, otherwise a list of Type*
*/
static inline Expr **parse_generic_parameters(ParseContext *c)
static inline Expr **parse_generic_parameters(ParseContext *c, bool old_style)
{
Expr **params = NULL;
while (!try_consume(c, TOKEN_GREATER))
// TODO remove deprecation
TokenType end_token = old_style ? TOKEN_GREATER : TOKEN_RGENPAR;
while (!try_consume(c, end_token))
{
ASSIGN_EXPR_OR_RET(Expr *arg, parse_generic_parameter(c), NULL);
ASSIGN_EXPR_OR_RET(Expr *arg, old_style ? parse_generic_parameter(c) : parse_expr(c), NULL);
vec_add(params, arg);
TokenType tok = c->tok;
if (tok != TOKEN_RPAREN && tok != TOKEN_GREATER)
if (tok != end_token)
{
TRY_CONSUME_OR_RET(TOKEN_COMMA, "Expected ',' after argument.", NULL);
TRY_CONSUME_OR_RET(TOKEN_COMMA, "Expected ',' after the argument.", NULL);
}
}
return params;
@@ -1723,10 +1755,12 @@ static inline Decl *parse_def_type(ParseContext *c)
// 2. Now parse the type which we know is here.
ASSIGN_TYPE_OR_RET(TypeInfo *type_info, parse_type(c), poisoned_decl);
// 3. Do we have '<' if so it's a parameterized type e.g. foo::bar::Type<int, double>.
if (try_consume(c, TOKEN_LESS))
bool old_style_encountered = try_consume(c, TOKEN_LESS);
// 3. Do we have '(<' if so it's a parameterized type e.g. foo::bar::Type(<int, double>).
if (old_style_encountered || try_consume(c, TOKEN_LGENPAR))
{
Expr **params = parse_generic_parameters(c);
Expr **params = parse_generic_parameters(c, old_style_encountered);
if (!params) return poisoned_decl;
decl->decl_kind = DECL_DEFINE;
decl_add_type(decl, TYPE_TYPEDEF);
@@ -1736,6 +1770,10 @@ static inline Decl *parse_def_type(ParseContext *c)
if (!parse_attributes_for_global(c, decl)) return poisoned_decl;
RANGE_EXTEND_PREV(decl);
if (old_style_encountered)
{
sema_warning_at(decl->span, "Use of <...> for generics is deprecated, please use (<...>) instead.");
}
CONSUME_EOS_OR_RET(poisoned_decl);
return decl;
}
@@ -1849,16 +1887,22 @@ static inline Decl *parse_def_ident(ParseContext *c)
decl->define_decl.span = c->span;
advance(c);
if (try_consume(c, TOKEN_LESS))
bool old_style_encountered = try_consume(c, TOKEN_LESS);
if (old_style_encountered || try_consume(c, TOKEN_LGENPAR) )
{
decl->define_decl.define_kind = DEFINE_IDENT_GENERIC;
Expr **params = parse_generic_parameters(c);
Expr **params = parse_generic_parameters(c, old_style_encountered);
if (!params) return poisoned_decl;
decl->define_decl.generic_params = params;
}
if (!parse_attributes_for_global(c, decl)) return poisoned_decl;
RANGE_EXTEND_PREV(decl);
if (old_style_encountered)
{
sema_warning_at(decl->span, "Use of <...> for generics is deprecated, please use (<...>) instead.");
}
CONSUME_EOS_OR_RET(poisoned_decl);
return decl;
}

View File

@@ -1316,6 +1316,7 @@ Ast *parse_stmt(ParseContext *c)
case TOKEN_INLINE:
case TOKEN_DISTINCT:
case TOKEN_CT_INCLUDE:
case TOKEN_LGENPAR:
SEMA_ERROR_HERE("Unexpected '%s' found when expecting a statement.",
token_type_to_string(c->tok));
advance(c);
@@ -1323,6 +1324,7 @@ Ast *parse_stmt(ParseContext *c)
case TOKEN_RPAREN:
case TOKEN_RBRACE:
case TOKEN_RBRACKET:
case TOKEN_RGENPAR:
SEMA_ERROR_HERE("Mismatched '%s' found.", token_type_to_string(c->tok));
advance(c);
return poisoned_ast;

View File

@@ -79,11 +79,12 @@ INLINE void add_decl_to_list(Decl ***list, Decl *decl)
}
bool parse_module(ParseContext *c, AstId contracts);
Expr *parse_generic_parameter(ParseContext *c);
bool try_consume(ParseContext *c, TokenType type);
bool consume(ParseContext *c, TokenType type, const char *message, ...);
bool consume_const_name(ParseContext *c, const char* type);
Expr *parse_precedence_with_left_side(ParseContext *c, Expr *left_side, Precedence precedence);
Expr *parse_generic_parameter(ParseContext *c);
INLINE const char *symstr(ParseContext *c)
{

View File

@@ -139,7 +139,7 @@ static inline bool sema_analyse_struct_member(SemaContext *context, Decl *parent
{
RETURN_SEMA_ERROR(decl, "Circular dependency resolving member.");
}
assert(!decl->unit || decl->unit->module->is_generic);
assert(!decl->unit || decl->unit->module->is_generic || decl->unit == parent->unit);
decl->unit = parent->unit;
AttributeDomain domain = ATTR_MEMBER;
@@ -319,6 +319,7 @@ static bool sema_analyse_struct_members(SemaContext *context, Decl *decl, Decl *
bool is_packed = decl->is_packed;
unsigned member_count = vec_size(members);
Decl **struct_members = decl->strukt.members;
for (unsigned i = 0; i < member_count; i++)
{
AGAIN:;
@@ -331,12 +332,8 @@ static bool sema_analyse_struct_members(SemaContext *context, Decl *decl, Decl *
bool erase_decl = false;
if (!sema_analyse_struct_member(context, decl, member, &erase_decl))
{
if (decl_ok(decl))
{
decl_poison(decl);
continue;
}
continue;
decl_poison(member);
return decl_poison(decl);
}
if (erase_decl)
{
@@ -2988,20 +2985,8 @@ static CompilationUnit *unit_copy(Module *module, CompilationUnit *unit)
static Module *module_instantiate_generic(SemaContext *context, Module *module, Path *path, Expr **params,
SourceSpan from)
{
Module *new_module = compiler_find_or_create_module(path, NULL);
new_module->is_generic = false;
CompilationUnit **units = module->units;
VECEACH(units, i)
{
vec_add(new_module->units, unit_copy(new_module, units[i]));
}
CompilationUnit *first_context = new_module->units[0];
if (module->contracts)
{
copy_begin();
new_module->contracts = astid(copy_ast_macro(astptr(module->contracts)));
copy_end();
}
unsigned decls = 0;
Decl* params_decls[MAX_PARAMS];
VECEACH(module->parameters, i)
{
const char *param_name = module->parameters[i];
@@ -3018,7 +3003,7 @@ static Module *module_instantiate_generic(SemaContext *context, Module *module,
decl->var.init_expr = param;
decl->type = param->type;
decl->resolve_status = RESOLVE_NOT_DONE;
vec_add(first_context->global_decls, decl);
params_decls[decls++] = decl;
continue;
}
if (is_value)
@@ -3033,12 +3018,34 @@ static Module *module_instantiate_generic(SemaContext *context, Module *module,
decl->typedef_decl.type_info = type_info;
decl->type->name = decl->name;
decl->type->canonical = type_info->type->canonical;
vec_add(first_context->global_decls, decl);
params_decls[decls++] = decl;
}
Module *new_module = compiler_find_or_create_module(path, NULL);
new_module->is_generic = false;
CompilationUnit **units = module->units;
VECEACH(units, i)
{
vec_add(new_module->units, unit_copy(new_module, units[i]));
}
CompilationUnit *first_context = new_module->units[0];
for (unsigned i = 0; i < decls; i++)
{
vec_add(first_context->global_decls, params_decls[i]);
}
if (module->contracts)
{
copy_begin();
new_module->contracts = astid(copy_ast_macro(astptr(module->contracts)));
copy_end();
}
return new_module;
}
static bool sema_append_generate_parameterized_name(SemaContext *c, Module *module, Decl *decl, bool mangled)
static bool sema_append_generate_parameterized_name(SemaContext *c, Module *module, Expr **params, bool mangled)
{
if (mangled)
{
@@ -3047,9 +3054,9 @@ static bool sema_append_generate_parameterized_name(SemaContext *c, Module *modu
}
else
{
scratch_buffer_append_char('<');
scratch_buffer_append("(<");
}
FOREACH_BEGIN_IDX(i, Expr *param, decl->define_decl.generic_params)
FOREACH_BEGIN_IDX(i, Expr *param, params)
if (i != 0)
{
scratch_buffer_append(mangled ? "$" : ", ");
@@ -3057,23 +3064,11 @@ static bool sema_append_generate_parameterized_name(SemaContext *c, Module *modu
if (param->expr_kind == EXPR_TYPEINFO)
{
TypeInfo *type_info = param->type_expr;
if (!sema_resolve_type_info(c, type_info)) return decl_poison(decl);
if (!sema_resolve_type_info(c, type_info)) return false;
Type *type = type_info->type->canonical;
if (type->type_kind == TYPE_OPTIONAL)
{
SEMA_ERROR(type_info, "Expected a non-optional type.");
return poisoned_decl;
}
if (type == type_void)
{
SEMA_ERROR(type_info, "A 'void' type cannot be used as a parameter type.");
return poisoned_decl;
}
if (type_is_invalid_storage_type(type))
{
SEMA_ERROR(type_info, "Expected a runtime type.");
return poisoned_decl;
}
if (type->type_kind == TYPE_OPTIONAL) RETURN_SEMA_ERROR(type_info, "Expected a non-optional type.");
if (type == type_void) RETURN_SEMA_ERROR(type_info, "A 'void' type cannot be used as a parameter type.");
if (type_is_invalid_storage_type(type)) RETURN_SEMA_ERROR(type_info, "Expected a runtime type.");
if (mangled)
{
type_mangle_introspect_name_to_buffer(type);
@@ -3085,7 +3080,7 @@ static bool sema_append_generate_parameterized_name(SemaContext *c, Module *modu
}
else
{
if (!sema_analyse_ct_expr(c, param)) return decl_poison(decl);
if (!sema_analyse_ct_expr(c, param)) return false;
Type *type = param->type->canonical;
if (!type_is_integer_or_bool_kind(type))
{
@@ -3110,7 +3105,6 @@ static bool sema_append_generate_parameterized_name(SemaContext *c, Module *modu
if (type->type_kind == TYPE_I128 || type->type_kind == TYPE_U128)
{
char *str = int_to_str(param->const_expr.ixx, 10);
scratch_buffer_append(str);
}
else
@@ -3121,7 +3115,7 @@ static bool sema_append_generate_parameterized_name(SemaContext *c, Module *modu
}
else
{
scratch_buffer_append_unsigned_int(param->const_expr.ixx.i.high);
scratch_buffer_append_unsigned_int(param->const_expr.ixx.i.low);
}
}
if (mangled)
@@ -3132,7 +3126,7 @@ static bool sema_append_generate_parameterized_name(SemaContext *c, Module *modu
}
}
FOREACH_END();
scratch_buffer_append_char(mangled ? '$' : '>');
scratch_buffer_append(mangled ? "$" : ">)");
return true;
}
@@ -3176,6 +3170,8 @@ static bool sema_analyse_generic_module_contracts(SemaContext *c, Module *module
}
return true;
}
static bool sema_analyse_parameterized_define(SemaContext *c, Decl *decl)
{
Path *decl_path;
@@ -3204,19 +3200,40 @@ static bool sema_analyse_parameterized_define(SemaContext *c, Decl *decl)
default:
UNREACHABLE
}
Expr **params = decl->define_decl.generic_params;
Decl *symbol = sema_analyse_parameterized_identifier(c, decl_path, name, span, params);
if (!decl_ok(symbol)) return decl_poison(decl);
switch (decl->define_decl.define_kind)
{
case DEFINE_IDENT_GENERIC:
decl->define_decl.alias = symbol;
decl->type = symbol->type;
return true;
case DEFINE_TYPE_GENERIC:
{
Type *type = type_new(TYPE_TYPEDEF, decl->name);
decl->type = type;
type->decl = symbol;
decl->decl_kind = DECL_TYPEDEF;
type->canonical = symbol->type->canonical;
return true;
}
default:
UNREACHABLE
}
}
Decl *sema_analyse_parameterized_identifier(SemaContext *c, Path *decl_path, const char *name, SourceSpan span, Expr **params)
{
NameResolve name_resolve = {
.path = decl_path,
.span = span,
.symbol = name
};
Decl *alias = unit_resolve_parameterized_symbol(c->unit, &name_resolve);
if (!decl_ok(alias))
{
return decl_poison(decl);
}
if (!decl_ok(alias)) return poisoned_decl;
Module *module = alias->unit->module;
Expr **params = decl->define_decl.generic_params;
unsigned parameter_count = vec_size(module->parameters);
assert(parameter_count > 0);
if (parameter_count != vec_size(params))
@@ -3225,11 +3242,11 @@ static bool sema_analyse_parameterized_define(SemaContext *c, Decl *decl)
sema_error_at(extend_span_with_token(params[0]->span, vectail(params)->span),
"The generic module expected %d arguments, but you supplied %d, did you make a mistake?",
parameter_count,
vec_size(decl->define_decl.generic_params));
return decl_poison(decl);
vec_size(params));
return poisoned_decl;
}
scratch_buffer_clear();
if (!sema_append_generate_parameterized_name(c, module, decl, true)) return decl_poison(decl);
if (!sema_append_generate_parameterized_name(c, module, params, true)) return poisoned_decl;
TokenType ident_type = TOKEN_IDENT;
const char *path_string = scratch_buffer_interned();
Module *instantiated_module = global_context_find_module(path_string);
@@ -3242,50 +3259,31 @@ static bool sema_analyse_parameterized_define(SemaContext *c, Decl *decl)
path->module = path_string;
path->span = module->name->span;
path->len = scratch_buffer.len;
instantiated_module = module_instantiate_generic(c, module, path,
decl->define_decl.generic_params, decl->span);
if (!instantiated_module) return decl_poison(decl);
instantiated_module = module_instantiate_generic(c, module, path, params, span);
scratch_buffer_clear();
if (!sema_append_generate_parameterized_name(c, module, params, false)) return poisoned_decl;
if (!instantiated_module) return poisoned_decl;
instantiated_module->generic_suffix = scratch_buffer_copy();
sema_analyze_stage(instantiated_module, c->unit->module->stage - 1);
}
if (global_context.errors_found) return decl_poison(decl);
if (global_context.errors_found) return poisoned_decl;
Decl *symbol = module_find_symbol(instantiated_module, name);
if (!symbol)
{
SEMA_ERROR(decl, "The generic module '%s' does not have '%s' for this parameterization.", module->name->module, name);
return decl_poison(decl);
sema_error_at(span, "The generic module '%s' does not have '%s' for this parameterization.", module->name->module, name);
return poisoned_decl;
}
if (was_initiated && instantiated_module->contracts)
{
SourceSpan error_span = extend_span_with_token(params[0]->span, params[parameter_count - 1]->span);
if (!sema_analyse_generic_module_contracts(c, instantiated_module, error_span))
{
return decl_poison(decl);
return poisoned_decl;
}
}
if (!sema_analyse_decl(c, symbol)) return false;
if (!sema_analyse_decl(c, symbol)) return poisoned_decl;
unit_register_external_symbol(c->compilation_unit, symbol);
switch (decl->define_decl.define_kind)
{
case DEFINE_IDENT_GENERIC:
decl->define_decl.alias = symbol;
decl->type = symbol->type;
return true;
case DEFINE_TYPE_GENERIC:
{
scratch_buffer_clear();
scratch_buffer_append(symbol->name);
sema_append_generate_parameterized_name(c, module, decl, false);
symbol->type->name = scratch_buffer_interned();
Type *type = type_new(TYPE_TYPEDEF, decl->name);
decl->type = type;
type->decl = symbol;
decl->decl_kind = DECL_TYPEDEF;
type->canonical = symbol->type->canonical;
return true;
}
default:
UNREACHABLE
}
return symbol;
}
static inline bool sema_analyse_attribute_decl(SemaContext *c, Decl *decl)

View File

@@ -507,6 +507,7 @@ static bool sema_binary_is_expr_lvalue(Expr *top_expr, Expr *expr)
case EXPR_ANYSWITCH:
case EXPR_VASPLAT:
case EXPR_TEST_HOOK:
case EXPR_GENERIC_IDENT:
goto ERR;
}
UNREACHABLE
@@ -616,6 +617,7 @@ static bool expr_may_ref(Expr *expr)
case EXPR_ANYSWITCH:
case EXPR_VASPLAT:
case EXPR_TEST_HOOK:
case EXPR_GENERIC_IDENT:
return false;
}
UNREACHABLE
@@ -6764,6 +6766,8 @@ RETRY:
{
case TYPE_INFO_POISON:
return poisoned_type;
case TYPE_INFO_GENERIC:
TODO
case TYPE_INFO_VECTOR:
{
ArraySize size;
@@ -6968,6 +6972,23 @@ static inline Decl *sema_find_cached_lambda(SemaContext *context, Type *func_typ
return NULL;
}
static inline bool sema_expr_analyse_generic_ident(SemaContext *context, Expr *expr)
{
Expr *parent = exprptr(expr->generic_ident_expr.parent);
if (parent->expr_kind != EXPR_IDENTIFIER)
{
SEMA_ERROR(parent, "Expected an identifier to parameterize.");
return false;
}
Decl *symbol = sema_analyse_parameterized_identifier(context, parent->identifier_expr.path, parent->identifier_expr.ident, parent->span, expr->generic_ident_expr.parmeters);
if (!decl_ok(symbol)) return false;
expr->expr_kind = EXPR_IDENTIFIER;
expr->identifier_expr.decl = symbol;
expr->resolve_status = RESOLVE_DONE;
expr->type = symbol->type;
return true;
}
static inline bool sema_expr_analyse_lambda(SemaContext *context, Type *func_type, Expr *expr)
{
Decl *decl = expr->lambda_expr;
@@ -7447,6 +7468,8 @@ static inline bool sema_analyse_expr_dispatch(SemaContext *context, Expr *expr)
case EXPR_VASPLAT:
SEMA_ERROR(expr, "'$vasplat' can only be used inside of macros.");
return false;
case EXPR_GENERIC_IDENT:
return sema_expr_analyse_generic_ident(context, expr);
case EXPR_LAMBDA:
return sema_expr_analyse_lambda(context, NULL, expr);
case EXPR_CT_CHECKS:

View File

@@ -87,6 +87,7 @@ Type *cast_numeric_arithmetic_promotion(Type *type);
void cast_to_int_to_max_bit_size(SemaContext *context, Expr *lhs, Expr *rhs, Type *left_type, Type *right_type);
bool sema_decl_if_cond(SemaContext *context, Decl *decl);
bool sema_flattened_expr_is_const(SemaContext *context, Expr *expr);
Decl *sema_analyse_parameterized_identifier(SemaContext *c, Path *decl_path, const char *name, SourceSpan span, Expr **params);
bool sema_analyse_checked(SemaContext *context, Ast *directive, SourceSpan span);

View File

@@ -249,6 +249,7 @@ RETRY:
case EXPR_CT_EVAL:
case EXPR_CT_IDENT:
case EXPR_ANYSWITCH:
case EXPR_GENERIC_IDENT:
UNREACHABLE
case EXPR_DESIGNATOR:
sema_trace_expr_liveness(expr->designator_expr.value);

View File

@@ -311,6 +311,23 @@ INLINE bool sema_resolve_vatype(SemaContext *context, TypeInfo *type_info)
return true;
}
// Foo(<...>)
INLINE bool sema_resolve_generic_type(SemaContext *context, TypeInfo *type_info)
{
TypeInfo *inner = type_info->generic.base;
if (inner->kind != TYPE_INFO_IDENTIFIER && inner->subtype != TYPE_COMPRESSED_NONE && !inner->optional)
{
SEMA_ERROR(inner, "Parameterization required a concrete type name here.");
return false;
}
assert(inner->resolve_status == RESOLVE_NOT_DONE);
Decl *type = sema_analyse_parameterized_identifier(context, inner->unresolved.path, inner->unresolved.name, inner->span, type_info->generic.params);
if (!decl_ok(type)) return false;
type_info->type = type->type;
return true;
}
static inline bool sema_resolve_type(SemaContext *context, TypeInfo *type_info, bool allow_inferred_type, bool is_pointee)
{
// Ok, already resolved.
@@ -338,6 +355,9 @@ static inline bool sema_resolve_type(SemaContext *context, TypeInfo *type_info,
{
case TYPE_INFO_POISON:
UNREACHABLE
case TYPE_INFO_GENERIC:
if (!sema_resolve_generic_type(context, type_info)) return type_info_poison(type_info);
goto APPEND_QUALIFIERS;
case TYPE_INFO_VATYPE:
if (!sema_resolve_vatype(context, type_info)) return type_info_poison(type_info);
goto APPEND_QUALIFIERS;

View File

@@ -159,6 +159,8 @@ void sema_analyze_stage(Module *module, AnalysisStage stage)
case ANALYSIS_FUNCTIONS:
sema_analysis_pass_functions(module);
break;
case ANALYSIS_FINALIZE:
break;
}
if (global_context.errors_found) return;
}

View File

@@ -98,6 +98,8 @@ const char *token_type_to_string(TokenType type)
return "<=";
case TOKEN_LBRAPIPE:
return "{|";
case TOKEN_LGENPAR:
return "(<";
case TOKEN_LVEC:
return "[<";
case TOKEN_MINUS_ASSIGN:
@@ -120,6 +122,8 @@ const char *token_type_to_string(TokenType type)
return "??";
case TOKEN_RBRAPIPE:
return "|}";
case TOKEN_RGENPAR:
return ">)";
case TOKEN_RVEC:
return ">]";
case TOKEN_SCOPE:

View File

@@ -201,27 +201,36 @@ const char *type_to_error_string(Type *type)
{
case TYPE_POISONED:
return "poisoned";
case TYPE_ENUM:
case TYPE_FAULTTYPE:
case TYPE_TYPEDEF:
case TYPE_STRUCT:
case TYPE_VOID:
case TYPE_BOOL:
case ALL_INTS:
case ALL_FLOATS:
case TYPE_UNION:
case TYPE_DISTINCT:
case TYPE_BITSTRUCT:
case TYPE_ANYFAULT:
case TYPE_UNTYPED_LIST:
case TYPE_ANY:
case TYPE_MEMBER:
case TYPE_WILDCARD:
return type->name;
case TYPE_ENUM:
case TYPE_FAULTTYPE:
case TYPE_TYPEDEF:
case TYPE_STRUCT:
case TYPE_UNION:
case TYPE_DISTINCT:
case TYPE_BITSTRUCT:
{
Decl *decl = type->decl;
if (!decl || !decl->unit || !decl->unit->module->generic_suffix) return type->name;
scratch_buffer_clear();
scratch_buffer_append(decl->name);
scratch_buffer_append(decl->unit->module->generic_suffix);
return scratch_buffer_copy();
}
case TYPE_FUNC:
scratch_buffer_clear();
scratch_buffer_append("fn ");
type_append_func_to_scratch(type->function.prototype);
return str_printf("fn %s", scratch_buffer_to_string());
return scratch_buffer_copy();
case TYPE_INFERRED_VECTOR:
return str_printf("%s[<*>]", type_to_error_string(type->array.base));
case TYPE_VECTOR:

View File

@@ -1 +1 @@
#define COMPILER_VERSION "0.4.554"
#define COMPILER_VERSION "0.4.555"

View File

@@ -2,11 +2,11 @@ module foo;
// def <name> = <name>
def standard_foo = __stdin;
def someFunctionIntBool = someFunction<int, bool>;
def FooInt = Foo<int>;
def A_CONST_INT = A_CONST<int>;
def someFunctionIntBool = someFunction(<int, bool>);
def FooInt = Foo(<int>);
def A_CONST_INT = A_CONST(<int>);
def standard_foo<int> = ofke; // #error: Expected '='
def standard_foo(<int>) = ofke; // #error: Expected '='
def fn foo = fef; // #error: A type, variable, constant or attribute name was expected here
def feokfe = fn void(int); // #error: Expected a function or variable name here
def AOFKE = ofek; // #error: Expected a constant name here

View File

@@ -1,4 +1,4 @@
module foo<Type>;
module foo(<Type>);
import std::io;
macro @hello(Type thing) {
@@ -9,8 +9,8 @@ module bar;
import foo @public;
def intHello = foo::@hello<int>; // #error: cannot be aliased
def @intHello = foo::hello<int>; // #error: cannot use
def intHello = foo::@hello(<int>); // #error: cannot be aliased
def @intHello = foo::hello(<int>); // #error: cannot use
fn void main(String[] args) {
@intHello(42);

View File

@@ -1,4 +1,4 @@
module foo<Type>;
module foo(<Type>);
import std::io;
macro @hello(Type thing) {
@@ -9,7 +9,7 @@ module bar;
import foo @public;
def @intHello = foo::@hello<int>;
def @intHello = foo::@hello(<int>);
fn void main(String[] args) {
@intHello(42);

View File

@@ -65,8 +65,8 @@ fn int Foo2.mutate(Foo2 *foo)
return ++foo.x;
}
def oopsInt = test2::argh<int>;
def oopsDouble = test2::argh<int>;
def oopsInt = test2::argh(<int>);
def oopsDouble = test2::argh(<int>);
def Argh = fn int(double, Bobo);
def Argh2 = fn int(double, Bobo);
@@ -95,15 +95,15 @@ struct Foo
int b;
}
def getValueInt = test2::getValue<int>;
def getValueDouble = test2::getValue<double>;
def IntBlob = test2::Blob<int>;
def DoubleBlob = Blob<double>;
def getMultInt = test2::getMult<int>;
def getMultDouble = test2::getMult<double>;
def getValueInt = test2::getValue(<int>);
def getValueDouble = test2::getValue(<double>);
def IntBlob = test2::Blob(<int>);
def DoubleBlob = Blob(<double>);
def getMultInt = test2::getMult(<int>);
def getMultDouble = test2::getMult(<double>);
def IntArray = List<int>;
def IntList = LinkedList<int>;
def IntArray = List(<int>);
def IntList = LinkedList(<int>);
enum MyEnum : int
{
@@ -173,7 +173,7 @@ module hello_world;
import foo;
extern fn int printf(char *, ...);
def doubleMult = foo::check<double>;
def doubleMult = foo::check(<double>);
fn void hello()
{
@@ -181,14 +181,14 @@ fn void hello()
printf("Mult %f\n", doubleMult(11.1));
}
module foo <Type>;
module foo(<Type>);
fn Type check(Type i)
{
return i * i;
}
module test2 <Type>;
module test2(<Type>);
struct Blob
{

View File

@@ -67,8 +67,8 @@ fn int Foo2.mutate(Foo2 *foo)
def oopsInt = test2::argh<int>;
def oopsDouble = test2::argh<int>;
def oopsInt = test2::argh(<int>);
def oopsDouble = test2::argh(<int>);
def Argh = fn int(double, Bobo);
def Argh2 = fn int(double, Bobo);
@@ -97,15 +97,15 @@ struct Foo
int b;
}
def getValueInt = test2::getValue<int>;
def getValueDouble = test2::getValue<double>;
def IntBlob = test2::Blob<int>;
def DoubleBlob = Blob<double>;
def getMultInt = test2::getMult<int>;
def getMultDouble = test2::getMult<double>;
def getValueInt = test2::getValue(<int>);
def getValueDouble = test2::getValue(<double>);
def IntBlob = test2::Blob(<int>);
def DoubleBlob = Blob(<double>);
def getMultInt = test2::getMult(<int>);
def getMultDouble = test2::getMult(<double>);
def IntArray = List<int>;
def IntList = LinkedList<int>;
def IntArray = List(<int>);
def IntList = LinkedList(<int>);
enum MyEnum : int
{
@@ -175,7 +175,7 @@ module hello_world;
import foo;
extern fn int printf(char *, ...);
def doubleMult = foo::check<double>;
def doubleMult = foo::check(<double>);
fn void hello()
{
@@ -183,14 +183,14 @@ fn void hello()
printf("Mult %f\n", doubleMult(11.1));
}
module foo <Type>;
module foo(<Type>);
fn Type check(Type i)
{
return i * i;
}
module test2 <Type>;
module test2(<Type>);
struct Blob
{

View File

@@ -3,7 +3,7 @@ module test;
import std::io;
import std::collections::enumset;
def AbcEnumSet = EnumSet<Abc>;
def AbcEnumSet = EnumSet(<Abc>);
enum Abc
{

View File

@@ -1,4 +1,4 @@
module foo<Type>;
module foo(<Type>);
fn void abc()
{
@@ -9,4 +9,4 @@ fn void abc()
module tester;
import foo;
def abc_my = foo::abc<int>;
def abc_my = foo::abc(<int>);

View File

@@ -2,14 +2,14 @@
module test;
import bar;
def BazTest = Baz<Test>;
def BazTest = Baz(<Test>); // #error: Recursive definition of 'BazTest'
struct Test // #error: Recursive definition of 'Test'
struct Test
{
BazTest t;
}
module bar<Test>;
module bar(<Test>);
struct Baz
{

View File

@@ -1,4 +1,4 @@
module gen <Type>;
module gen(<Type>);
fn Type mult(Type x)
{
@@ -13,8 +13,8 @@ fn Type addMult(Type x, Type a, Type b)
module test;
import gen;
def intMult = gen::mult<int>;
def doubleAddMult = gen::addMult<double>;
def intMult = gen::mult(<int>);
def doubleAddMult = gen::addMult(<double>);
fn int getIt(int i)
{

View File

@@ -1,5 +1,5 @@
// #target: macos-x64
module hello<Type, FOO>;
module hello(<Type, FOO>);
fn Type x(Type t)
{
@@ -8,7 +8,7 @@ fn Type x(Type t)
module test;
import hello;
def xint = hello::x<int, -123>;
def xint = hello::x(<int, -123>);
import std::io;

View File

@@ -3,7 +3,7 @@ module test;
import std::io;
import std::collections::list;
def TreeNodeList = List<TreeNode>;
def TreeNodeList = List(<TreeNode>);
struct TreeNode
{

View File

@@ -1,4 +1,4 @@
module foo<Type, SIZE>;
module foo(<Type, SIZE>);
struct Foo
{
@@ -7,5 +7,5 @@ struct Foo
module bar;
import foo;
def Bar = Foo<int, int>; // #error: Expected a value, not a type
def Baz = Foo<5, 4>; // #error: Expected a type, not a value
def Bar = Foo(<int, int>); // #error: Expected a value, not a type
def Baz = Foo(<5, 4>); // #error: Expected a type, not a value

View File

@@ -1,7 +1,7 @@
module compiler_c3;
import std::collections::list;
def IntArray = List<int>;
def IntArray = List(<int>);
extern fn void printf(char*, ...);

View File

@@ -3,7 +3,7 @@
module test;
import std::collections::map;
def IntMap = HashMap<char[], int>;
def IntMap = HashMap(<char[], int>);
fn void main()
{

View File

@@ -6,8 +6,8 @@ import std::collections::map;
struct Foo { int x; void* bar; }
def IntFooMap = HashMap<int, Foo>;
def IntDoubleMap = HashMap<int, double>;
def IntFooMap = HashMap(<int, Foo>);
def IntDoubleMap = HashMap(<int, double>);
fn String Foo.to_string(Foo* foo, Allocator* allocator = mem::heap()) @dynamic
{

View File

@@ -4,7 +4,7 @@ import std::io;
import std::math;
import std::collections::priorityqueue;
def FooPriorityQueue = PriorityQueue<Foo>;
def FooPriorityQueue = PriorityQueue(<Foo>);
fn void main()
{

View File

@@ -8,7 +8,7 @@ enum FooEnum
THREE,
}
def FooEnumMap = EnumMap<FooEnum, uint>;
def FooEnumMap = EnumMap(<FooEnum, uint>);
fn void! enums()
{

View File

@@ -1,7 +1,7 @@
module linkedlist_test @test;
import std::collections::linkedlist;
def IntList = LinkedList<int>;
def IntList = LinkedList(<int>);
fn void! test_push()
{

View File

@@ -1,8 +1,8 @@
module listtests @test;
import std::collections::list;
def IntList = List<int>;
def PtrList = List<void*>;
def IntList = List(<int>);
def PtrList = List(<void*>);
fn void! test_delete_contains_index()
{

View File

@@ -1,8 +1,8 @@
module range_test @test;
import std::collections::range;
def IntRange = Range<int>;
def IntExRange = ExclusiveRange<int>;
def IntRange = Range(<int>);
def IntExRange = ExclusiveRange(<int>);
fn void! test_exrange()
{

View File

@@ -2,7 +2,7 @@ module sort_test @test;
import std::sort;
import std::sort::quicksort;
def qs_int = quicksort::sort<int[]>;
def qs_int = quicksort::sort(<int[]>);
fn void quicksort()
{
@@ -22,7 +22,8 @@ fn void quicksort()
}
def Cmp = fn int(int*, int*);
def qs_int_ref = quicksort::sort_ref_fn<int[]>;
def qs_int_ref = quicksort::sort_ref_fn(<int[]>);
fn void quicksort_with()
{
@@ -41,7 +42,7 @@ fn void quicksort_with()
}
}
def qs_int_fn = quicksort::sort_fn<int[]>;
def qs_int_fn = quicksort::sort_fn(<int[]>);
fn void quicksort_with2()
{