return ~~(str1[i] - str2[i]);
}
-equal :: (str1: str, str2: str) -> bool #operator== {
+#operator == equal
+equal :: (str1: str, str2: str) -> bool {
if str1.count != str2.count do return false;
while i := 0; i < str1.count {
if str1[i] != str2[i] do return false;
#include "onyxlex.h"
#include "onyxtypes.h"
-#define AST_NODES \
- NODE(Node) \
- NODE(Typed) \
- \
- NODE(NamedValue) \
- NODE(BinaryOp) \
- NODE(UnaryOp) \
- NODE(NumLit) \
- NODE(StrLit) \
- NODE(Local) \
- NODE(Call) \
- NODE(Argument) \
- NODE(AddressOf) \
- NODE(Dereference) \
- NODE(ArrayAccess) \
- NODE(FieldAccess) \
- NODE(SizeOf) \
- NODE(AlignOf) \
- NODE(FileContents) \
- NODE(StructLiteral) \
- NODE(ArrayLiteral) \
- NODE(RangeLiteral) \
- NODE(Compound) \
- \
- NODE(DirectiveSolidify) \
- NODE(StaticIf) \
- NODE(DirectiveError) \
- \
- NODE(Return) \
- NODE(Jump) \
- NODE(Use) \
- \
- NODE(Block) \
- NODE(IfWhile) \
- NODE(For) \
- NODE(Defer) \
- NODE(SwitchCase) \
- NODE(Switch) \
- \
- NODE(Type) \
- NODE(BasicType) \
- NODE(PointerType) \
- NODE(FunctionType) \
- NODE(ArrayType) \
- NODE(SliceType) \
- NODE(DynArrType) \
- NODE(VarArgType) \
- NODE(StructType) \
- NODE(StructMember) \
- NODE(PolyStructType) \
- NODE(PolyStructParam) \
- NODE(PolyCallType) \
- NODE(EnumType) \
- NODE(EnumValue) \
- NODE(TypeAlias) \
- NODE(TypeRawAlias) \
- NODE(CompoundType) \
- \
- NODE(Binding) \
- NODE(MemRes) \
- NODE(Include) \
- NODE(UsePackage) \
- NODE(Alias) \
- NODE(Global) \
- NODE(Param) \
- NODE(Function) \
- NODE(OverloadedFunction) \
- \
- NODE(PolyParam) \
- NODE(PolySolution) \
- NODE(SolidifiedFunction) \
- NODE(PolyProc) \
- \
+#define AST_NODES \
+ NODE(Node) \
+ NODE(Typed) \
+ \
+ NODE(NamedValue) \
+ NODE(BinaryOp) \
+ NODE(UnaryOp) \
+ NODE(NumLit) \
+ NODE(StrLit) \
+ NODE(Local) \
+ NODE(Call) \
+ NODE(Argument) \
+ NODE(AddressOf) \
+ NODE(Dereference) \
+ NODE(ArrayAccess) \
+ NODE(FieldAccess) \
+ NODE(SizeOf) \
+ NODE(AlignOf) \
+ NODE(FileContents) \
+ NODE(StructLiteral) \
+ NODE(ArrayLiteral) \
+ NODE(RangeLiteral) \
+ NODE(Compound) \
+ \
+ NODE(DirectiveSolidify) \
+ NODE(StaticIf) \
+ NODE(DirectiveError) \
+ NODE(DirectiveAddOverload) \
+ NODE(DirectiveOperator) \
+ \
+ NODE(Return) \
+ NODE(Jump) \
+ NODE(Use) \
+ \
+ NODE(Block) \
+ NODE(IfWhile) \
+ NODE(For) \
+ NODE(Defer) \
+ NODE(SwitchCase) \
+ NODE(Switch) \
+ \
+ NODE(Type) \
+ NODE(BasicType) \
+ NODE(PointerType) \
+ NODE(FunctionType) \
+ NODE(ArrayType) \
+ NODE(SliceType) \
+ NODE(DynArrType) \
+ NODE(VarArgType) \
+ NODE(StructType) \
+ NODE(StructMember) \
+ NODE(PolyStructType) \
+ NODE(PolyStructParam) \
+ NODE(PolyCallType) \
+ NODE(EnumType) \
+ NODE(EnumValue) \
+ NODE(TypeAlias) \
+ NODE(TypeRawAlias) \
+ NODE(CompoundType) \
+ \
+ NODE(Binding) \
+ NODE(MemRes) \
+ NODE(Include) \
+ NODE(UsePackage) \
+ NODE(Alias) \
+ NODE(Global) \
+ NODE(Param) \
+ NODE(Function) \
+ NODE(OverloadedFunction) \
+ \
+ NODE(PolyParam) \
+ NODE(PolySolution) \
+ NODE(SolidifiedFunction) \
+ NODE(PolyProc) \
+ \
NODE(Package)
#define NODE(name) typedef struct Ast ## name Ast ## name;
Ast_Kind_Directive_Solidify,
Ast_Kind_Static_If,
Ast_Kind_Directive_Error,
+ Ast_Kind_Directive_Add_Overload,
+ Ast_Kind_Directive_Operator,
Ast_Kind_Count
} AstKind;
AstBlock *body;
bh_arr(AstTyped *) allocate_exprs;
- // NOTE: used by the #add_overload directive. Initially set to a symbol,
- // then resolved to an overloaded function.
- AstNode *overloaded_function;
-
- // NOTE: set to -1 if the function is not an operator overload;
- // set to a BinaryOp value if it is.
- BinaryOp operator_overload;
-
OnyxToken* name;
OnyxToken* error_msg;
};
+struct AstDirectiveAddOverload {
+ AstNode_base;
+
+ // NOTE: used by the #add_overload directive. Initially set to a symbol,
+ // then resolved to an overloaded function.
+ AstNode *overloaded_function;
+
+ AstTyped *overload;
+};
+
+struct AstDirectiveOperator {
+ AstNode_base;
+
+ BinaryOp operator;
+ AstTyped *overload;
+};
+
extern AstNode empty_node;
Entity_Type_Foreign_Global_Header,
Entity_Type_Function_Header,
Entity_Type_Global_Header,
+ Entity_Type_Process_Directive,
Entity_Type_Struct_Member_Default,
Entity_Type_Memory_Reservation,
Entity_Type_Expression,
return Param_Pass_By_Value;
}
+static inline AstFunction* get_function_from_node(AstNode* node) {
+ if (node->kind == Ast_Kind_Function) return (AstFunction *) node;
+ if (node->kind == Ast_Kind_Polymorphic_Proc) return ((AstPolyProc *) node)->base_func;
+ return NULL;
+}
+
#endif // #ifndef ONYXASTNODES_H
for (i32 j = 0; j < Entity_State_Count; j++) {
if (eh->all_count[j][i] == 0) continue;
- printf(state_colors[j]);
+ printf("%s", state_colors[j]);
i32 count = (eh->all_count[j][i] >> 5) + 1;
for (i32 c = 0; c < count * 2; c++) printf("\xe2\x96\x88");
"SOLIDIFY",
"STATIC IF",
"STATIC ERROR",
+ "ADD OVERLOAD",
+ "OPERATOR OVERLOAD",
"AST_NODE_KIND_COUNT",
};
"Foreign_Global Header",
"Function Header",
"Global Header",
+ "Process Directive",
"Struct Member Default",
"Memory Reservation",
"Expression",
if (!type_is_structlike_strict(sl->type)) {
onyx_report_error(sl->token->pos,
- "'%s' is not a constructable using a struct literal.",
+ "'%s' is not constructable using a struct literal.",
type_get_name(sl->type));
return Check_Error;
}
ENTITY_INSERT(ent);
break;
}
+
+ case Ast_Kind_Directive_Add_Overload:
+ case Ast_Kind_Directive_Operator: {
+ ent.type = Entity_Type_Process_Directive;
+ ent.expr = (AstTyped *) node;
+ ENTITY_INSERT(ent);
+ break;
+ }
default: {
ent.type = Entity_Type_Expression;
AstFunction* func_def = make_node(AstFunction, Ast_Kind_Function);
func_def->token = token;
- func_def->operator_overload = -1;
bh_arr_new(global_heap_allocator, func_def->allocate_exprs, 4);
bh_arr_new(global_heap_allocator, func_def->params, 4);
func_def->return_type = parse_type(parser);
while (parser->curr->type == '#') {
- if (parse_possible_directive(parser, "add_overload")) {
- if (func_def->overloaded_function != NULL) {
- onyx_report_error(parser->curr->pos, "cannot have multiple #add_overload directives on a single procedure.");
- expect_token(parser, Token_Type_Symbol);
-
- } else {
- func_def->overloaded_function = (AstNode *) parse_expression(parser, 0);
- }
- }
-
- else if (parse_possible_directive(parser, "operator")) {
- BinaryOp op = binary_op_from_token_type(parser->curr->type);
- consume_token(parser);
-
- if (op == Binary_Op_Count) {
- onyx_report_error(parser->curr->pos, "Invalid binary operator.");
- } else {
- func_def->operator_overload = op;
- }
- }
-
- else if (parse_possible_directive(parser, "intrinsic")) {
+ if (parse_possible_directive(parser, "intrinsic")) {
func_def->flags |= Ast_Flag_Intrinsic;
if (parser->curr->type == Token_Type_Literal_String) {
ENTITY_SUBMIT(error);
return;
}
+ else if (parse_possible_directive(parser, "operator")) {
+ AstDirectiveOperator *operator = make_node(AstDirectiveOperator, Ast_Kind_Directive_Operator);
+ operator->token = dir_token;
+
+ BinaryOp op = binary_op_from_token_type(parser->curr->type);
+ consume_token(parser);
+
+ if (op == Binary_Op_Count) {
+ onyx_report_error(parser->curr->pos, "Invalid binary operator.");
+ } else {
+ operator->operator = op;
+ }
+
+ operator->overload = parse_expression(parser, 0);
+
+ ENTITY_SUBMIT(operator);
+ return;
+ }
+ else if (parse_possible_directive(parser, "add_overload")) {
+ AstDirectiveAddOverload *add_overload = make_node(AstDirectiveAddOverload, Ast_Kind_Directive_Add_Overload);
+ add_overload->token = dir_token;
+ add_overload->overloaded_function = (AstNode *) parse_expression(parser, 0);
+
+ expect_token(parser, ',');
+ add_overload->overload = parse_expression(parser, 0);
+
+ ENTITY_SUBMIT(add_overload);
+ return;
+ }
else {
OnyxToken* directive_token = expect_token(parser, '#');
OnyxToken* symbol_token = expect_token(parser, Token_Type_Symbol);
if (onyx_has_errors()) return Symres_Error;
}
}
-
- if ((func->flags & Ast_Flag_From_Polymorphism) == 0) {
- if (func->overloaded_function != NULL) {
- SYMRES(expression, (AstTyped **) &func->overloaded_function);
- if (func->overloaded_function == NULL) return Symres_Error; // NOTE: Error message will already be generated
-
- if (func->overloaded_function->kind != Ast_Kind_Overloaded_Function) {
- onyx_report_error(func->token->pos, "#add_overload directive did not resolve to an overloaded function.");
-
- } else {
- AstOverloadedFunction* ofunc = (AstOverloadedFunction *) func->overloaded_function;
- bh_arr_push(ofunc->overloads, (AstTyped *) func);
- }
- }
-
- if (func->operator_overload != (BinaryOp) -1) {
- if (bh_arr_length(func->params) != 2) {
- onyx_report_error(func->token->pos, "Expected 2 exactly arguments for binary operator overload.");
- }
-
- if (binop_is_assignment(func->operator_overload)) {
- onyx_report_error(func->token->pos, "'%s' is not currently overloadable.", binaryop_string[func->operator_overload]);
- }
-
- bh_arr_push(operator_overloads[func->operator_overload], (AstTyped *) func);
- }
- }
SYMRES(type, &func->return_type);
if (!node_is_type((AstNode *) func->return_type)) {
SYMRES(type, ¶m->type_expr);
}
- // CLEANUP: This was copied from symres_function_header.
- if (pp->base_func->operator_overload != (BinaryOp) -1) {
- if (bh_arr_length(pp->base_func->params) != 2) {
- onyx_report_error(pp->base_func->token->pos, "Expected 2 exactly arguments for binary operator overload.");
- }
-
- if (binop_is_assignment(pp->base_func->operator_overload)) {
- onyx_report_error(pp->base_func->token->pos, "'%s' is not currently overloadable.", binaryop_string[pp->base_func->operator_overload]);
- }
-
- bh_arr_push(operator_overloads[pp->base_func->operator_overload], (AstTyped *) pp);
- }
return Symres_Success;
}
return Symres_Success;
}
+static SymresStatus symres_process_directive(AstNode* directive) {
+ switch (directive->kind) {
+ case Ast_Kind_Directive_Add_Overload: {
+ AstDirectiveAddOverload *add_overload = (AstDirectiveAddOverload *) directive;
+
+ SYMRES(expression, (AstTyped **) &add_overload->overloaded_function);
+ if (add_overload->overloaded_function == NULL) return Symres_Error; // NOTE: Error message will already be generated
+
+ if (add_overload->overloaded_function->kind != Ast_Kind_Overloaded_Function) {
+ onyx_report_error(add_overload->token->pos, "#add_overload directive did not resolve to an overloaded function.");
+
+ } else {
+ AstOverloadedFunction* ofunc = (AstOverloadedFunction *) add_overload->overloaded_function;
+ bh_arr_push(ofunc->overloads, (AstTyped *) add_overload->overload);
+ }
+
+ break;
+ }
+
+ case Ast_Kind_Directive_Operator: {
+ AstDirectiveOperator *operator = (AstDirectiveOperator *) directive;
+ SYMRES(expression, &operator->overload);
+ if (!operator->overload) return Symres_Error;
+
+ AstFunction* overload = get_function_from_node((AstNode *) operator->overload);
+ if (overload == NULL) {
+ onyx_report_error(operator->token->pos, "This cannot be used as an operator overload.");
+ return Symres_Error;
+ }
+
+ if (bh_arr_length(overload->params) != 2) {
+ onyx_report_error(operator->token->pos, "Expected 2 exactly arguments for binary operator overload.");
+ return Symres_Error;
+ }
+
+ if (binop_is_assignment(operator->operator)) {
+ onyx_report_error(overload->token->pos, "'%s' is not currently overloadable.", binaryop_string[operator->operator]);
+ return Symres_Error;
+ }
+
+ bh_arr_push(operator_overloads[operator->operator], operator->overload);
+ break;
+ }
+ }
+
+ return Symres_Success;
+}
+
void symres_entity(Entity* ent) {
if (block_stack == NULL) bh_arr_new(global_heap_allocator, block_stack, 16);
case Entity_Type_Polymorphic_Proc: ss = symres_polyproc(ent->poly_proc); break;
case Entity_Type_String_Literal: ss = symres_expression(&ent->expr); break;
case Entity_Type_Struct_Member_Default: ss = symres_struct_defaults((AstType *) ent->type_alias); break;
+ case Entity_Type_Process_Directive: ss = symres_process_directive((AstNode *) ent->expr);
+ next_state = Entity_State_Finalized;
+ break;
default: break;
}
next := false;
}
-proc (c: CubePos) -> u32 #add_overload map.hash_function {
+#add_overload map.hash_function, (c: CubePos) -> u32 {
return 17 * c.x + 13 * c.y + 11 * c.z + 19 * c.w;
}
-proc (a: CubePos, b: CubePos) -> bool #add_overload map.cmp_function {
+#add_overload map.cmp_function, (a: CubePos, b: CubePos) -> bool {
return (a.x == b.x)
&& (a.y == b.y)
&& (a.z == b.z)
y: i32 = 0;
}
-proc (v: Vec2) -> u32 #add_overload map.hash_function {
+#add_overload map.hash_function, (v: Vec2) -> u32 {
return v.x * 11 + v.y * 17;
}
-proc (v1: Vec2, v2: Vec2) -> bool #add_overload map.cmp_function {
- return v1.x == v2.x
- && v1.y == v2.y;
+#add_overload map.cmp_function, (v1: Vec2, v2: Vec2) -> bool {
+ return v1.x == v2.x && v1.y == v2.y;
}
Hex_Directions := Vec2.[
Vec2 :: struct { x: i32; y: i32; }
// Overload print() to print Vec2's.
-proc (use writer: ^io.Writer, use v: Vec2) #add_overload io.write {
+#add_overload io.write, (use writer: ^io.Writer, use v: Vec2) {
io.write_format(writer, "Vec2(%i, %i)", x, y);
}
im : f32 = 0;
}
-proc (a: Complex, b: Complex) -> Complex #operator+ {
+#operator+ (a: Complex, b: Complex) -> Complex {
return Complex.{ a.re + b.re, a.im + b.im };
}
-proc (a: Complex, b: Complex) -> Complex #operator- {
+#operator- (a: Complex, b: Complex) -> Complex {
return Complex.{ a.re - b.re, a.im - b.im };
}
-proc (a: Complex, b: Complex) -> Complex #operator* {
+#operator* (a: Complex, b: Complex) -> Complex {
return Complex.{ a.re * b.re - a.im * b.im, a.re * b.im + a.im * b.re };
}
-
Vec :: struct (T: type_expr, N: i32) {
data: [N] T;
}
-proc (a: Vec($T, $N), b: Vec(T, N)) -> Vec(T, N) #operator+ {
+#operator+ (a: Vec($T, $N), b: Vec(T, N)) -> Vec(T, N) {
out : Vec(T, N);
for i: 0 .. N do out.data[i] = a.data[i] + b.data[i];
return out;
}
-proc (a: Vec($T, $N), b: Vec(T, N)) -> Vec(T, N) #operator- {
+#operator- (a: Vec($T, $N), b: Vec(T, N)) -> Vec(T, N) {
out : Vec(T, N);
for i: 0 .. N do out.data[i] = a.data[i] - b.data[i];
return out;
}
-proc (a: Vec($T, $N), s: T) -> Vec(T, N) #operator* {
+#operator* (a: Vec($T, $N), s: T) -> Vec(T, N) {
out : Vec(T, N);
for i: 0 .. N do out.data[i] = a.data[i] * s;
return out;
}
-proc (a: Vec($T, $N), b: Vec(T, N)) -> T #operator* {
+#operator* (a: Vec($T, $N), b: Vec(T, N)) -> T {
res := T.{};
for i: 0 .. N do res += a.data[i] * b.data[i];
return res;