data: T;
}
-List :: struct (T: type_expr) {
+List :: struct (Elem_Type: type_expr) {
allocator: Allocator;
- first: ^ListElem(T) = null;
- last: ^ListElem(T) = null;
+ first: ^ListElem(Elem_Type) = null;
+ last: ^ListElem(Elem_Type) = null;
// "Method" like things
free :: free
return .{ allocator = allocator };
}
-free :: (list: ^List($T)) {
+free :: (list: ^List) {
elem := list.first;
while elem != null {
to_delete := elem;
}
}
-push_end :: (list: ^List($T), x: T) {
+push_end :: (list: ^List, x: list.Elem_Type) {
new_elem := allocate_elem(list);
new_elem.data = x;
if list.first == null do list.first = new_elem;
}
-push_begin :: (list: ^List($T), x: T) {
+push_begin :: (list: ^List, x: list.Elem_Type) {
new_elem := allocate_elem(list);
new_elem.data = x;
return begin.data;
}
-count :: (list: ^List($T)) -> i32 {
+count :: (list: ^List) -> i32 {
c := 0;
elem := list.first;
while elem != null {
return c;
}
-at :: (list: ^List($T), index: i32) -> ^T {
+at :: (list: ^List, index: i32) -> ^T {
elem := list.first;
while elem != null {
if index == 0 do return ^elem.data;
return null;
}
-contains :: (list: ^List($T), x: T) -> bool {
+contains :: (list: ^List, x: list.Elem_Type) -> bool {
elem := list.first;
while elem != null {
if elem.data == x do return true;
while (!consume_token_if_next(parser, end_token)) {
if (parser->hit_unexpected_token) return;
- if (next_tokens_are(parser, 2, Token_Type_Symbol, '=')) {
+ //
+ // This has a weird condition to avoid the problem of using a quick function as an argument:
+ // f(x => x + 1)
+ // This shouldn't be a named argument, but this should:
+ // f(g = x => x + 1)
+ //
+ if (next_tokens_are(parser, 2, Token_Type_Symbol, '=') && peek_token(2)->type != '>') {
OnyxToken* name = expect_token(parser, Token_Type_Symbol);
expect_token(parser, '=');
}
case Token_Type_Symbol: {
+ if (parse_possible_quick_function_definition(parser, &retval)) {
+ ENTITY_SUBMIT(retval);
+ break;
+ }
+
OnyxToken* sym_token = expect_token(parser, Token_Type_Symbol);
AstTyped* sym_node = make_node(AstTyped, Ast_Kind_Symbol);
sym_node->token = sym_token;
} QuickParam;
static b32 parse_possible_quick_function_definition_no_consume(OnyxParser* parser) {
+ //
+ // x => x + 1 case.
+ if (next_tokens_are(parser, 3, Token_Type_Symbol, '=', '>')) {
+ return 1;
+ }
+
if (parser->curr->type != '(') return 0;
OnyxToken* matching_paren = find_matching_paren(parser->curr);
static b32 parse_possible_quick_function_definition(OnyxParser* parser, AstTyped** ret) {
if (!parse_possible_quick_function_definition_no_consume(parser)) return 0;
- OnyxToken* proc_token = expect_token(parser, '(');
-
bh_arr(QuickParam) params=NULL;
bh_arr_new(global_heap_allocator, params, 4);
+ OnyxToken* proc_token;
- while (parser->curr->type != ')') {
- if (parser->hit_unexpected_token) return 0;
-
+ if (parser->curr->type == Token_Type_Symbol) {
QuickParam param = { 0 };
- if (consume_token_if_next(parser, '$')) param.is_baked = 1;
param.token = expect_token(parser, Token_Type_Symbol);
-
+ proc_token = param.token;
bh_arr_push(params, param);
- if (parser->curr->type != ')') {
- expect_token(parser, ',');
+ } else {
+ proc_token = expect_token(parser, '(');
+ while (parser->curr->type != ')') {
+ if (parser->hit_unexpected_token) return 0;
+
+ QuickParam param = { 0 };
+ if (consume_token_if_next(parser, '$')) param.is_baked = 1;
+ param.token = expect_token(parser, Token_Type_Symbol);
+
+ bh_arr_push(params, param);
+
+ if (parser->curr->type != ')') {
+ expect_token(parser, ',');
+ }
}
+
+ expect_token(parser, ')');
}
- expect_token(parser, ')');
expect_token(parser, '=');
expect_token(parser, '>');
case Ast_Kind_Array_Type: to_replace = &((AstArrayType *) *to_replace)->elem; param_type = ((AstArrayType *) param_type)->elem; break;
case Ast_Kind_Slice_Type: to_replace = &((AstSliceType *) *to_replace)->elem; param_type = ((AstSliceType *) param_type)->elem; break;
case Ast_Kind_DynArr_Type: to_replace = &((AstDynArrType *) *to_replace)->elem; param_type = ((AstDynArrType *) param_type)->elem; break;
- case Ast_Kind_Alias: param_type = ((AstAlias *) param_type)->alias; break;
+ case Ast_Kind_Alias: param_type = (AstType *) ((AstAlias *) param_type)->alias; break;
case Ast_Kind_Type_Alias: param_type = ((AstTypeAlias *) param_type)->to; break;
case Ast_Kind_Poly_Struct_Type: {
AutoPolymorphVariable apv;
#include "astnodes.h"
#include "errors.h"
+// :EliminatingSymres - notes the places where too much work is being done in symbol resolution
+
// Variables used during the symbol resolution phase.
static Scope* curr_scope = NULL;
static b32 report_unresolved_symbols = 1;
case Ast_Kind_Alias: {
AstAlias* alias = (AstAlias *) *type;
- SYMRES_INVISIBLE(type, alias, &alias->alias);
+ SYMRES_INVISIBLE(type, alias, (AstType **) &alias->alias);
break;
}
if ((*pipe)->left == NULL) return Symres_Error;
+ // :EliminatingSymres
bh_arr_insertn(call_node->args.values, 0, 1);
call_node->args.values[0] = (AstTyped *) make_argument(context.ast_alloc, (*pipe)->left);
call_node->next = (*pipe)->next;
SYMRES(expression, &(*mcall)->left);
if ((*mcall)->left == NULL) return Symres_Error;
+ // :EliminatingSymres
if (((*mcall)->flags & Ast_Flag_Has_Been_Symres) == 0) {
AstFieldAccess* implicit_field_access = make_field_access(context.ast_alloc, (*mcall)->left, NULL);
implicit_field_access->token = call_node->callee->token;
call_node->callee = (AstTyped *) implicit_field_access;
+ (*mcall)->flags |= Ast_Flag_Has_Been_Symres;
}
SYMRES(expression, (AstTyped **) &call_node);
- (*mcall)->flags |= Ast_Flag_Has_Been_Symres;
return Symres_Success;
}
static SymresStatus symres_struct_literal(AstStructLiteral* sl) {
if (sl->stnode != NULL) SYMRES(expression, &sl->stnode);
+ // :EliminatingSymres
sl->type_node = (AstType *) sl->stnode;
while (sl->type_node && sl->type_node->kind == Ast_Kind_Type_Alias)
sl->type_node = ((AstTypeAlias *) sl->type_node)->to;
static SymresStatus symres_array_literal(AstArrayLiteral* al) {
if (al->atnode != NULL) SYMRES(expression, &al->atnode);
+ // :EliminatingSymres
al->type_node = (AstType *) al->atnode;
while (al->type_node && al->type_node->kind == Ast_Kind_Type_Alias)
al->type_node = ((AstTypeAlias *) al->type_node)->to;
SYMRES(expression, &((AstRangeLiteral *)(*expr))->low);
SYMRES(expression, &((AstRangeLiteral *)(*expr))->high);
+ // :EliminatingSymres
SYMRES(type, &builtin_range_type);
(*expr)->type_node = builtin_range_type;
case Ast_Kind_Param:
if ((*expr)->flags & Ast_Flag_Param_Symbol_Dirty) {
assert((*expr)->token->type == Token_Type_Symbol);
- *expr = make_symbol(context.ast_alloc, (*expr)->token);
+ *expr = (AstTyped *) make_symbol(context.ast_alloc, (*expr)->token);
SYMRES(expression, expr);
}
break;
static SymresStatus symres_use(AstUse* use) {
SYMRES(expression, &use->expr);
+ // :EliminatingSymres
if (use->expr->kind == Ast_Kind_Package) {
AstPackage* package = (AstPackage *) use->expr;
SYMRES(package, package);
if (use->expr->type_node == NULL && use->expr->type == NULL) goto cannot_use;
+ // :EliminatingSymres
AstType* effective_type = use->expr->type_node;
if (effective_type->kind == Ast_Kind_Pointer_Type)
effective_type = ((AstPointerType *) effective_type)->elem;
scope_enter(func->scope);
if ((func->flags & Ast_Flag_Has_Been_Symres) == 0) {
+ // :EliminatingSymres
bh_arr_each(AstParam, param, func->params) {
// CLEANUP: Currently, in order to 'use' parameters, the type must be completely
// resolved and built. This is excessive because all that should need to be known
scope_enter(enum_node->scope);
+ // :EliminatingSymres
u64 next_assign_value = enum_node->is_flags ? 1 : 0;
bh_arr_each(AstEnumValue *, value, enum_node->values) {
if ((*value)->flags & Ast_Flag_Has_Been_Checked) continue;
}
static SymresStatus symres_process_directive(AstNode* directive) {
+ // :EliminatingSymres
switch (directive->kind) {
case Ast_Kind_Directive_Add_Overload: {
AstDirectiveAddOverload *add_overload = (AstDirectiveAddOverload *) directive;
}
static SymresStatus symres_polyquery(AstPolyQuery *query) {
+ // :EliminatingSymres
query->successful_symres = 0;
if (query->function_header->scope == NULL)
quick_iterator :=
count_iterator(1.0f, 20.0f)
- |> iter.map((x) => x * 2)
+ |> iter.map(x => x * 2)
|> iter.filter(lower_bound, (x, l) => x > ~~l)
|> iter.map(addition, (x, addition) => x + ~~addition)
|> iter.take(5);
println("\nStarting the zipped iteration...");
zipped_iterator := count_iterator(1, 10)
- |> iter.map((x) => x * 2)
- |> iter.filter((x) => x > 10)
- |> iter.map((x) => x + 42)
+ |> iter.map(x => x * 2)
+ |> iter.filter(x => x > 10)
+ |> iter.map(x => x + 42)
|> iter.zip(iter.const(42.0f));
for value: zipped_iterator {